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. CLIsyncthing 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 APIlib/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.