Syncthing — API Surface#

API types#

Syncthing exposes four distinct API surfaces:

  1. REST/HTTP API — the primary management and control plane, consumed by the web GUI and CLI tooling
  2. CLI — syncthing cli subcommand that wraps the REST API for terminal use
  3. BEP (Block Exchange Protocol) — peer-to-peer binary protocol over TLS/QUIC for file synchronization between devices (not gRPC, custom protobuf framing)
  4. Library API — lib/syncthing.App is designed to be embedded by third-party programs (native GUI wrappers)

There is no gRPC service. The .proto files (proto/bep/, proto/dbproto/, proto/discoproto/) are used for internal message serialization only, not exposed as gRPC services.


REST/HTTP API#

  • Router: github.com/julienschmidt/httprouter for the REST mux; net/http.ServeMux for the outer routing layer
  • Route registration: All routes registered inline in lib/api/api.go:250–380 during the Serve() call; config routes use a builder pattern in lib/api/confighandler.go
  • Base URL: http://127.0.0.1:8384 (default; HTTPS optional)
  • All REST endpoints are prefixed /rest/

Middleware chain (outermost to innermost)#

LayerMiddlewarePurpose
1debugMiddlewareRequest logging, request ID
2localhostMiddlewareRejects non-localhost Host headers when bound to loopback
3corsMiddlewareCORS headers (Access-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETE, OPTIONS)
4redirectToHTTPSMiddlewareRedirect HTTP→HTTPS when TLS configured
5basicAuthAndSessionMiddlewareUsername/password + session cookie; LDAP optional
6csrfManagerCSRF token validation for non-API-key requests
7withDetailsMiddlewareAdds X-Syncthing-Version / X-Syncthing-ID response headers
8noCacheMiddlewareCache-Control: no-cache on all /rest/ responses

Authentication#

  • API key: Send X-API-Key: <key> header or ?apikey=<key> query parameter — bypasses session auth and CSRF
  • Session cookie: POST credentials to /rest/noauth/auth/password; receive a session token cookie
  • LDAP: Pluggable into the basicAuthAndSessionMiddleware when config.LDAPConfiguration is set
  • Unauthenticated routes: /rest/noauth/health (health check) and /rest/noauth/auth/* (login/logout)

Key endpoints#

Cluster / Device Management#

MethodPathDescription
GET/rest/cluster/pending/devicesDevices that have tried to connect but are not configured
GET/rest/cluster/pending/foldersFolders that remote devices have offered but are not configured
DELETE/rest/cluster/pending/devicesDismiss a pending device
DELETE/rest/cluster/pending/foldersDismiss a pending folder

Database / File Index (/rest/db/)#

MethodPathDescription
GET/rest/db/statusFolder sync status (global/local counts, need counts)
GET/rest/db/completionSync completion percentage for device+folder
GET/rest/db/fileMetadata for a specific file across all devices
GET/rest/db/needFiles this device needs from remotes (paginated)
GET/rest/db/remoteneedFiles a specific remote device needs
GET/rest/db/localchangedFiles changed locally in a receive-only folder
GET/rest/db/browseDirectory browser for a folder
GET/rest/db/ignoresIgnore patterns for a folder
POST/rest/db/ignoresUpdate ignore patterns
POST/rest/db/scanTrigger a folder scan (with optional sub-path)
POST/rest/db/prioPrioritize download of a specific file
POST/rest/db/overrideOverride (send-only folder: push local to remotes)
POST/rest/db/revertRevert (receive-only folder: restore remote state)

Folder Management (/rest/folder/)#

MethodPathDescription
GET/rest/folder/versionsList file version history for a folder
POST/rest/folder/versionsRestore a specific file version
GET/rest/folder/errorsFiles with sync errors in a folder

Events (/rest/events/)#

MethodPathDescription
GET/rest/eventsLong-poll for all events (since, limit, timeout, events bitmask params)
GET/rest/events/diskLong-poll for disk-change events only (LocalChangeDetected, RemoteChangeDetected)

System Operations (/rest/system/)#

MethodPathDescription
GET/rest/system/statusInstance status (RAM, CPU, uptime, device ID, etc.)
GET/rest/system/versionVersion, OS, arch, build info
GET/rest/system/connectionsActive connections and statistics per peer
GET/rest/system/discoveryCached discovered addresses per device
GET/rest/system/pingLiveness check (also POST)
GET/rest/system/upgradeCheck for newer version
GET/rest/system/logApplication log (filtered by since)
GET/rest/system/pathsFilesystem paths used by this instance
GET/rest/system/errorRecent GUI errors
POST/rest/system/restartRestart the syncthing process
POST/rest/system/shutdownShutdown the syncthing process
POST/rest/system/upgradePerform upgrade and restart
POST/rest/system/resetReset folder index (force full resync)
POST/rest/system/pausePause a device
POST/rest/system/resumeResume a paused device
POST/rest/system/errorSubmit a GUI error
POST/rest/system/loglevelsChange per-package log levels at runtime

Configuration (/rest/config/)#

All config endpoints support GET+PUT for full replacement and PATCH for partial update.

PathDescription
/rest/configFull configuration document
/rest/config/restart-requiredWhether pending changes need a restart
/rest/config/foldersList of all folders (GET/POST)
/rest/config/folders/:idIndividual folder (GET/PUT/PATCH/DELETE)
/rest/config/devicesList of all devices (GET/POST)
/rest/config/devices/:idIndividual device (GET/PUT/PATCH/DELETE)
/rest/config/defaults/folderDefault folder template
/rest/config/defaults/deviceDefault device template
/rest/config/defaults/ignoresDefault ignore patterns
/rest/config/optionsGlobal options
/rest/config/guiGUI configuration
/rest/config/ldapLDAP configuration

Statistics and Utilities#

MethodPathDescription
GET/rest/stats/devicePer-device statistics (last seen, etc.)
GET/rest/stats/folderPer-folder statistics (last scan, etc.)
GET/rest/svc/deviceidValidate/canonicalize a device ID
GET/rest/svc/random/stringGenerate a random string
GET/rest/svc/langAccepted languages from Accept-Language
GET/rest/svc/reportCurrent anonymous usage report payload

Debug (not for general use)#

PathDescription
/rest/debug/cpuprofCPU profile (duration query param)
/rest/debug/heapprofHeap profile snapshot
/rest/debug/supportSupport bundle (zipped logs + config)
/rest/debug/fileRead an arbitrary file (development only)

Other#

PathDescription
/metricsPrometheus metrics (via promhttp.Handler())
/qr/QR code image for a device ID or address
/Embedded AngularJS web UI (static assets from lib/assets)
/meta.jsJavaScript metadata (version, device ID, theme) for the web UI

CLI#

  • Framework: github.com/alecthomas/kong (struct-tag-driven; all options defined as typed struct fields)
  • Shell completion: github.com/willabides/kongplete for Bash/Zsh/Fish completions

Top-level command structure#

syncthing
├── serve          Run the daemon (default command)
├── cli            Control a running syncthing instance via REST API
│   ├── show
│   │   ├── version          GET /rest/system/version
│   │   ├── config-status    GET /rest/config/restart-required
│   │   ├── system           GET /rest/system/status
│   │   ├── connections      GET /rest/system/connections
│   │   ├── discovery        GET /rest/system/discovery
│   │   ├── usage            GET /rest/svc/report
│   │   └── pending          (devices/folders)
│   ├── operations
│   │   ├── restart          POST /rest/system/restart
│   │   ├── shutdown         POST /rest/system/shutdown
│   │   ├── upgrade          POST /rest/system/upgrade
│   │   ├── folder-override  POST /rest/db/override
│   │   └── default-ignores  PUT /rest/config/defaults/ignores
│   ├── errors
│   ├── debug
│   ├── config               (passthrough — full config CRUD via REST)
│   └── - (stdin)            Read commands line-by-line from stdin
├── browser        Open the GUI in the default browser and exit
├── decrypt        Decrypt or verify an encrypted receive-only folder
├── device-id      Show this node's device ID and exit
├── generate       Generate a key pair and initial config and exit
├── paths          Show all filesystem paths in use and exit
├── upgrade        Check for / perform an upgrade and exit
├── version        Show version string and exit
└── debug          Developer debugging subcommands

Flag patterns for syncthing serve#

Global flags (also apply to cli subcommand via env):

  • --config PATH / -C / STCONFDIR: Configuration directory
  • --data PATH / -D / STDATADIR: Data directory (database, logs)
  • --home PATH / -H / STHOMEDIR: Combined config+data directory

Key serve flags:

  • --gui-address URL / STGUIADDRESS
  • --gui-apikey KEY / STGUIAPIKEY
  • --no-browser / STNOBROWSER
  • --no-restart / STNORESTART
  • --no-upgrade / STNOUPGRADE
  • --paused / STPAUSED
  • --log-file, --log-level, --log-max-old-files etc.
  • Debug: --debug-gui-assets-dir, --debug-profiler-listen, --debug-profile-cpu, etc.

Environment variables are the canonical way to configure Syncthing in containerized or systemd deployments; every flag has a STXXX equivalent.


BEP — Block Exchange Protocol (peer-to-peer API)#

Not gRPC. A custom binary protocol over multiplexed TLS 1.3 streams (QUIC primary, TCP fallback). Protobuf-encoded messages (defined in proto/bep/bep.proto) with a length-prefixed framing layer.

Message types (from proto/bep/bep.proto):

MessageDirectionPurpose
HelloBoth (pre-auth)Protocol greeting, client name, version, connection count
ClusterConfigBothAdvertise shared folders and participating devices
IndexBothFull file index for a folder
IndexUpdateBothIncremental index change
Request→ sourceRequest a block by folder, name, offset, size, hash
Response← sourceReturn block bytes
DownloadProgressBothProgress on in-flight downloads
PingBothKeepalive
CloseBothGraceful shutdown with reason

Authentication: Mutual TLS certificate authentication. Device identity is derived from the SHA-256 fingerprint of the TLS certificate. No passwords or PKI — device IDs are self-certifying.

Encryption modes: Syncthing supports “untrusted device” (encrypted) folders where a receive-only device stores ciphertext without keys. The encrypting device wraps file contents; the untrusted device stores encrypted blocks without ever seeing plaintext.


Library API#

  • Embeddable package: lib/syncthing — third-party GUI wrappers (Syncthing-macOS, Syncthing-GTK, Syncthing-Android) import and call syncthing.New(cfg, options) / app.Start() / app.Stop() / app.Wait() / app.Error()
  • Key exported types: App, Options, Internals
  • Remote control helper: lib/rc (package rc) — Process struct for spawning and controlling a syncthing binary in tests or tooling, wrapping the REST API with typed methods (GetConfig, PostDBScan, WaitForCompletion, etc.)
  • API style: Constructor function returns an interface; no fluent builder; options via an Options struct
  • Backward compatibility: No explicit versioning strategy visible; the lib/ packages evolve with the main binary. Third-party embedders track Syncthing releases directly.

stdiscosrv (Discovery Server binary)#

cmd/stdiscosrv is a standalone binary (separate from the main daemon) that implements the global discovery HTTP service:

  • GET / — Look up addresses for a device ID (via client certificate authentication)
  • POST / — Announce addresses for a device (the device posts its own listen addresses)
  • GET /ping — Health check
  • GET /metrics — Prometheus metrics

Discovery uses HTTPS with certificate pinning — the querying device presents its own TLS certificate, and the server uses the certificate fingerprint as the device identity. No passwords or API keys.


strelaysrv (Relay Server binary)#

cmd/strelaysrv is a relay server for NAT-traversal. It uses a custom binary protocol (not HTTP) on port 22067, and exposes an HTTP status API on port 22070:

  • Configured entirely via stdlib flag (no kong, no cobra)
  • Key flags: --listen, --keys, --pools, --per-session-rate, --global-rate, --nat, --status-srv
  • Status endpoint at --status-srv address (default :22070) serves JSON status and optionally pprof

Notable API design observations#

  1. Long-polling for events, not WebSockets. The /rest/events endpoint uses blocking GET with a timeout parameter. The web UI polls continuously. This avoids WebSocket complexity but means each event delivery requires a full HTTP round trip.

  2. /rest/noauth/ prefix for unauthenticated routes. Rather than a separate port or path exclusion list, unauthenticated endpoints are co-located under /rest/noauth/, making the security boundary explicit and easily auditable.

  3. Config as a REST resource with PATCH support. The /rest/config/folders/:id and /rest/config/devices/:id endpoints support HTTP PATCH for partial updates — unusual in Go projects, which often require a full PUT. This is especially useful for automated management tools.

  4. Prometheus metrics co-located with the REST API. /metrics is served by the same lib/api service, requiring the same authentication. This is a deliberate security trade-off; operators can configure a separate unauthenticated port for scraping if needed.

  5. CLI is a REST client, not a separate protocol. syncthing cli and lib/rc both drive the REST API. There is no private administrative socket or gRPC admin channel. Every operation available in the web UI is available via REST, making the API complete.