Syncthing — API Surface#
API types#
Syncthing exposes four distinct API surfaces:
- REST/HTTP API — the primary management and control plane, consumed by the web GUI and CLI tooling
- CLI —
syncthing clisubcommand that wraps the REST API for terminal use - BEP (Block Exchange Protocol) — peer-to-peer binary protocol over TLS/QUIC for file synchronization between devices (not gRPC, custom protobuf framing)
- Library API —
lib/syncthing.Appis 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/httprouterfor the REST mux;net/http.ServeMuxfor the outer routing layer - Route registration: All routes registered inline in
lib/api/api.go:250–380during theServe()call; config routes use a builder pattern inlib/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)#
| Layer | Middleware | Purpose |
|---|---|---|
| 1 | debugMiddleware | Request logging, request ID |
| 2 | localhostMiddleware | Rejects non-localhost Host headers when bound to loopback |
| 3 | corsMiddleware | CORS headers (Access-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETE, OPTIONS) |
| 4 | redirectToHTTPSMiddleware | Redirect HTTP→HTTPS when TLS configured |
| 5 | basicAuthAndSessionMiddleware | Username/password + session cookie; LDAP optional |
| 6 | csrfManager | CSRF token validation for non-API-key requests |
| 7 | withDetailsMiddleware | Adds X-Syncthing-Version / X-Syncthing-ID response headers |
| 8 | noCacheMiddleware | Cache-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
basicAuthAndSessionMiddlewarewhenconfig.LDAPConfigurationis set - Unauthenticated routes:
/rest/noauth/health(health check) and/rest/noauth/auth/*(login/logout)
Key endpoints#
Cluster / Device Management#
| Method | Path | Description |
|---|---|---|
| GET | /rest/cluster/pending/devices | Devices that have tried to connect but are not configured |
| GET | /rest/cluster/pending/folders | Folders that remote devices have offered but are not configured |
| DELETE | /rest/cluster/pending/devices | Dismiss a pending device |
| DELETE | /rest/cluster/pending/folders | Dismiss a pending folder |
Database / File Index (/rest/db/)#
| Method | Path | Description |
|---|---|---|
| GET | /rest/db/status | Folder sync status (global/local counts, need counts) |
| GET | /rest/db/completion | Sync completion percentage for device+folder |
| GET | /rest/db/file | Metadata for a specific file across all devices |
| GET | /rest/db/need | Files this device needs from remotes (paginated) |
| GET | /rest/db/remoteneed | Files a specific remote device needs |
| GET | /rest/db/localchanged | Files changed locally in a receive-only folder |
| GET | /rest/db/browse | Directory browser for a folder |
| GET | /rest/db/ignores | Ignore patterns for a folder |
| POST | /rest/db/ignores | Update ignore patterns |
| POST | /rest/db/scan | Trigger a folder scan (with optional sub-path) |
| POST | /rest/db/prio | Prioritize download of a specific file |
| POST | /rest/db/override | Override (send-only folder: push local to remotes) |
| POST | /rest/db/revert | Revert (receive-only folder: restore remote state) |
Folder Management (/rest/folder/)#
| Method | Path | Description |
|---|---|---|
| GET | /rest/folder/versions | List file version history for a folder |
| POST | /rest/folder/versions | Restore a specific file version |
| GET | /rest/folder/errors | Files with sync errors in a folder |
Events (/rest/events/)#
| Method | Path | Description |
|---|---|---|
| GET | /rest/events | Long-poll for all events (since, limit, timeout, events bitmask params) |
| GET | /rest/events/disk | Long-poll for disk-change events only (LocalChangeDetected, RemoteChangeDetected) |
System Operations (/rest/system/)#
| Method | Path | Description |
|---|---|---|
| GET | /rest/system/status | Instance status (RAM, CPU, uptime, device ID, etc.) |
| GET | /rest/system/version | Version, OS, arch, build info |
| GET | /rest/system/connections | Active connections and statistics per peer |
| GET | /rest/system/discovery | Cached discovered addresses per device |
| GET | /rest/system/ping | Liveness check (also POST) |
| GET | /rest/system/upgrade | Check for newer version |
| GET | /rest/system/log | Application log (filtered by since) |
| GET | /rest/system/paths | Filesystem paths used by this instance |
| GET | /rest/system/error | Recent GUI errors |
| POST | /rest/system/restart | Restart the syncthing process |
| POST | /rest/system/shutdown | Shutdown the syncthing process |
| POST | /rest/system/upgrade | Perform upgrade and restart |
| POST | /rest/system/reset | Reset folder index (force full resync) |
| POST | /rest/system/pause | Pause a device |
| POST | /rest/system/resume | Resume a paused device |
| POST | /rest/system/error | Submit a GUI error |
| POST | /rest/system/loglevels | Change per-package log levels at runtime |
Configuration (/rest/config/)#
All config endpoints support GET+PUT for full replacement and PATCH for partial update.
| Path | Description |
|---|---|
/rest/config | Full configuration document |
/rest/config/restart-required | Whether pending changes need a restart |
/rest/config/folders | List of all folders (GET/POST) |
/rest/config/folders/:id | Individual folder (GET/PUT/PATCH/DELETE) |
/rest/config/devices | List of all devices (GET/POST) |
/rest/config/devices/:id | Individual device (GET/PUT/PATCH/DELETE) |
/rest/config/defaults/folder | Default folder template |
/rest/config/defaults/device | Default device template |
/rest/config/defaults/ignores | Default ignore patterns |
/rest/config/options | Global options |
/rest/config/gui | GUI configuration |
/rest/config/ldap | LDAP configuration |
Statistics and Utilities#
| Method | Path | Description |
|---|---|---|
| GET | /rest/stats/device | Per-device statistics (last seen, etc.) |
| GET | /rest/stats/folder | Per-folder statistics (last scan, etc.) |
| GET | /rest/svc/deviceid | Validate/canonicalize a device ID |
| GET | /rest/svc/random/string | Generate a random string |
| GET | /rest/svc/lang | Accepted languages from Accept-Language |
| GET | /rest/svc/report | Current anonymous usage report payload |
Debug (not for general use)#
| Path | Description |
|---|---|
/rest/debug/cpuprof | CPU profile (duration query param) |
/rest/debug/heapprof | Heap profile snapshot |
/rest/debug/support | Support bundle (zipped logs + config) |
/rest/debug/file | Read an arbitrary file (development only) |
Other#
| Path | Description |
|---|---|
/metrics | Prometheus metrics (via promhttp.Handler()) |
/qr/ | QR code image for a device ID or address |
/ | Embedded AngularJS web UI (static assets from lib/assets) |
/meta.js | JavaScript 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/kongpletefor 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 subcommandsFlag 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-filesetc.- 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):
| Message | Direction | Purpose |
|---|---|---|
Hello | Both (pre-auth) | Protocol greeting, client name, version, connection count |
ClusterConfig | Both | Advertise shared folders and participating devices |
Index | Both | Full file index for a folder |
IndexUpdate | Both | Incremental index change |
Request | → source | Request a block by folder, name, offset, size, hash |
Response | ← source | Return block bytes |
DownloadProgress | Both | Progress on in-flight downloads |
Ping | Both | Keepalive |
Close | Both | Graceful 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 callsyncthing.New(cfg, options)/app.Start()/app.Stop()/app.Wait()/app.Error() - Key exported types:
App,Options,Internals - Remote control helper:
lib/rc(package rc) —Processstruct 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
Optionsstruct - 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 checkGET /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-srvaddress (default:22070) serves JSON status and optionally pprof
Notable API design observations#
Long-polling for events, not WebSockets. The
/rest/eventsendpoint uses blocking GET with atimeoutparameter. The web UI polls continuously. This avoids WebSocket complexity but means each event delivery requires a full HTTP round trip./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.Config as a REST resource with PATCH support. The
/rest/config/folders/:idand/rest/config/devices/:idendpoints support HTTP PATCH for partial updates — unusual in Go projects, which often require a full PUT. This is especially useful for automated management tools.Prometheus metrics co-located with the REST API.
/metricsis served by the samelib/apiservice, requiring the same authentication. This is a deliberate security trade-off; operators can configure a separate unauthenticated port for scraping if needed.CLI is a REST client, not a separate protocol.
syncthing cliandlib/rcboth 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.