SYNCTHING-EVENT-API(7)
hiii bestie ๐ welcome to SYNCTHING-EVENT-API(7) from the Syncthing manual โ yes the whole thing is literally called the Event API and we're gonna get through it together, no stress ๐ซถ
๐ NAME ๐
syncthing-event-api โ Event API โจ
๐ธ DESCRIPTION ๐ธ
okay so here's the vibe: Syncthing ships a simple long polling interface that exposes events from the core utility out to a GUI ๐ that's it, that's the whole job.
and like โ to actually receive these events? you go look at GET /rest/events. that's your entry point, bestie ๐ชโจ
๐ฆ EVENT STRUCTURE ๐ฆ
every event is an object, and it looks a little something like this ๐
{
"id": 2,
"globalID": 3,
"type": "DeviceConnected",
"time": "2014-07-13T21:04:33.687836696+02:00",
"data": {
"addr": "172.16.32.25:22000",
"id": "NFGKEKE-7Z6RTH7-I3PRZXS-DEJF3UJ-FRWJBFO-VBBTDND-4SGNGVZ-QUQHJAG"
}
}
the top level keys id, globalID, time, type and data are always present โ like, no cap, every single time ๐ โ though data may legitimately be null (it's giving "empty but valid", we respect it ๐).
idโ a unique ID for this event on the events API. it always increases by1: the first event generated has id1, the next has id2, etc. and important: if this increases by more than1, then one or more events have been skipped by the events API ๐ซฅ so yeah, watch for gaps.globalIDโ a global ID for this event, spanning across the events API, the audit log, and any other sources ๐ it may increase by more than1, but it will always be greater than or equal to theid(fr fr, that's guaranteed ๐).timeโ the time the event was generated ๐ฐ๏ธtypeโ indicates the type of (i.e. the reason for) the event, and it's one of the event types below ๐ท๏ธdataโ an object containing optional extra information; the exact structure is determined by the event type ๐
โจ EVENT TYPES โจ
๐ ClusterConfigReceived
Added in version 1.20.0. โญ
the ClusterConfigReceived event gets emitted after processing such a protocol message received from a remote device ๐ก it's mainly used for internal purposes (iykyk, not really your main character moment).
{
"id": 84,
"globalID": 84,
"type": "ClusterConfigReceived",
"time": "2022-04-27T14:14:27.043576583+09:00",
"data": {
"device": "I6KAH76-66SLLLB-5PFXSOA-UFJCDZC-YAOMLEK-CP2GB32-BV5RQST-3PSROAU"
}
}
๐ ConfigSaved
emitted after the config has been saved โ either by the user or by Syncthing itself ๐พโจ
{
"id": 50,
"globalID": 50,
"type": "ConfigSaved",
"time": "2014-12-13T00:09:13.5166486Z",
"data": {
"version": 7,
"folders": [{"..."}],
"devices": [{"..."}],
"gui": {"..."},
"ldap": {"..."},
"options": {"..."},
"remoteIgnoredDevices": [{"..."}],
"defaults": {"..."}
}
}
๐ DeviceConnected
generated each time a connection to a device has been established ๐คโจ
{
"id": 2,
"globalID": 2,
"type": "DeviceConnected",
"time": "2014-07-13T21:04:33.687836696+02:00",
"data": {
"addr": "172.16.32.25:22000",
"id": "NFGKEKE-7Z6RTH7-I3PRZXS-DEJF3UJ-FRWJBFO-VBBTDND-4SGNGVZ-QUQHJAG",
"deviceName": "Laptop",
"clientName": "syncthing",
"clientVersion": "v0.13.4",
"type": "TCP (Client)"
}
}
๐ DeviceDisconnected
generated each time a connection to a device has been terminated ๐ญ
{
"id": 48,
"globalID": 48,
"type": "DeviceDisconnected",
"time": "2014-07-13T21:18:52.859929215+02:00",
"data": {
"error": "unexpected EOF",
"id": "NFGKEKE-7Z6RTH7-I3PRZXS-DEJF3UJ-FRWJBFO-VBBTDND-4SGNGVZ-QUQHJAG"
}
}
NOTE: ๐จ the error key contains the cause for disconnection โ which might not necessarily be an error as such. specifically, โEOFโ and โunexpected EOFโ both signify TCP connection termination, either because the other device restarted or went offline, or because of a network change ๐ so like, don't panic-fix things that aren't broken bestie ๐
๐ฆ DeviceDiscovered
emitted when a new device is discovered using local discovery ๐โจ
{
"id": 13,
"globalID": 13,
"type": "DeviceDiscovered",
"time": "2014-07-17T13:28:05.043465207+02:00",
"data": {
"addrs": [
"172.16.32.25:22000"
],
"device": "NFGKEKE-7Z6RTH7-I3PRZXS-DEJF3UJ-FRWJBFO-VBBTDND-4SGNGVZ-QUQHJAG"
}
}
โธ๏ธ DevicePaused
emitted when a device was paused ๐
{
"id": 13,
"globalID": 13,
"type": "DevicePaused",
"time": "2014-07-17T13:28:05.043465207+02:00",
"data": {
"device": "NFGKEKE-7Z6RTH7-I3PRZXS-DEJF3UJ-FRWJBFO-VBBTDND-4SGNGVZ-QUQHJAG"
}
}
๐ DeviceRejected (DEPRECATED)
Deprecated since version v1.13.0: this event is still emitted for compatibility, but it's deprecated โ use the replacement PendingDevicesChanged event instead ๐
emitted when there's a connection from a device we are not configured to talk to ๐ (stranger danger, but make it networking)
{
"id": 24,
"globalID": 24,
"type": "DeviceRejected",
"time": "2014-08-19T10:43:00.562821045+02:00",
"data": {
"address": "127.0.0.1:51807",
"name": "My dusty computer",
"device": "EJHMPAQ-OGCVORE-ISB4IS3-SYYVJXF-TKJGLTU-66DIQPF-GJ5D2GX-GQ3OWQK"
}
}
โถ๏ธ DeviceResumed
generated each time a device was resumed ๐ฑโจ
{
"id": 2,
"globalID": 2,
"type": "DeviceResumed",
"time": "2014-07-13T21:04:33.687836696+02:00",
"data": {
"device": "NFGKEKE-7Z6RTH7-I3PRZXS-DEJF3UJ-FRWJBFO-VBBTDND-4SGNGVZ-QUQHJAG"
}
}
๐ DownloadProgress
emitted during file downloads, for each folder and for each file ๐ฅ by default only a single file in a folder is handled at the same time, but custom configuration can cause multiple files to be shown (so if you see a whole crowd in there, that's your config talking ๐).
{
"id": 221,
"globalID": 221,
"type": "DownloadProgress",
"time": "2014-12-13T00:26:12.9876937Z",
"data": {
"folder1": {
"file1": {
"total": 800,
"pulling": 2,
"copiedFromOrigin": 0,
"reused": 633,
"copiedFromElsewhere": 0,
"pulled": 38,
"bytesTotal": 104792064,
"bytesDone": 87883776
},
"dir\\file2": {
"total": 80,
"pulling": 2,
"copiedFromOrigin": 0,
"reused": 0,
"copiedFromElsewhere": 0,
"pulled": 32,
"bytesTotal": 10420224,
"bytesDone": 4128768
}
},
"folder2": {
"file3": {
"total": 800,
"pulling": 2,
"copiedFromOrigin": 0,
"reused": 633,
"copiedFromElsewhere": 0,
"pulled": 38,
"bytesTotal": 104792064,
"bytesDone": 87883776
},
"dir\\file4": {
"total": 80,
"pulling": 2,
"copiedFromOrigin": 0,
"reused": 0,
"copiedFromElsewhere": 0,
"pulled": 32,
"bytesTotal": 10420224,
"bytesDone": 4128768
}
}
}
}
okay so here's what all those numbers actually mean ๐
totalโ total number of blocks in the file ๐งฑpullingโ number of blocks currently being downloaded ๐ถcopiedFromOriginโ number of blocks copied from the file we are about to replace โป๏ธreusedโ number of blocks reused from a previous temporary file ๐copiedFromElsewhereโ number of blocks copied from other files or potentially other folders ๐๏ธpulledโ number of blocks actually downloaded so far โbytesTotalโ approximate total file size ๐bytesDoneโ approximate number of bytes already handled (already reused, copied or pulled) ๐ซ
where block size is 128KB ๐งฎ
files/folders appearing in the event data imply that the download has been started for that file/folder โ and them disappearing implies that the downloads have been finished or failed for that file/folder ๐ and there is always a last event emitted with no data, which implies all downloads have finished/failed ๐โจ
๐ฅ Failure
generated for specific errors that will also be sent to the usage reporting server, if enabled in the configuration ๐ฎ these are usually of special interest to the developers to troubleshoot complex errors ๐งโ๐ป the data field contains a textual error message โ๏ธ
{
"id": 93,
"globalID": 93,
"type": "Failure",
"time": "2021-06-07T21:22:03.414609034+02:00",
"data": "index handler got paused while already paused"
}
๐ธ FolderCompletion
the FolderCompletion event is emitted when the local or remote contents for a folder changes ๐ it contains the completion percentage for a given remote device, and it's emitted once per currently connected remote device ๐ป๐ป
Added in version 1.20.0: indication whether the remote device has accepted the folder (shares it with us) as well, and whether it is paused โธ๏ธ the remoteState field is unknown when the remote device is not connected ๐ซฅ otherwise it can be either paused, notSharing, or valid if the remote is sharing back ๐ซถ
{
"id": 84,
"globalID": 84,
"type": "FolderCompletion",
"time": "2022-04-27T14:14:27.043576583+09:00",
"data": {
"completion": 100,
"device": "I6KAH76-66SLLLB-5PFXSOA-UFJCDZC-YAOMLEK-CP2GB32-BV5RQST-3PSROAU",
"folder": "default",
"globalBytes": 17,
"globalItems": 4,
"needBytes": 0,
"needDeletes": 0,
"needItems": 0,
"remoteState": "valid",
"sequence": 12
}
}
๐ง FolderErrors
the FolderErrors event is emitted when a folder cannot be successfully synchronized ๐ญ the event contains the ID of the affected folder and a list of errors for files or directories therein ๐ this list of errors is obsolete once the folder changes state to syncing โ and if errors remain after the next synchronization attempt, a new FolderErrors event is emitted ๐โจ
๐ FolderErrors
okay so the FolderErrors payload, she's giving nested-errors realness โ here's what she looks like:
{
"id": 132,
"type": "FolderErrors",
"time": "2015-06-26T13:39:24.697401384+02:00",
"data": {
"errors": [
{
"error": "open /Users/jb/src/github.com/syncthing/syncthing/test/s2/h2j/.syncthing.aslkjd.tmp: permission denied",
"path": "h2j/aslkjd"
}
],
"folder": "default"
}
}
Added in version 0.11.12. โจ
SEE ALSO: the StateChanged event, bestie โ that's your girl for the bigger picture ๐
๐ FolderPaused
Fires when the config changes around the "paused" state of a folder. And like, it's sent repeatedly for each changed folder โ so don't be like "why is this firing so much", that's literally the point ๐
{
"id": 93,
"globalID": 93,
"type": "FolderPaused",
"time": "2021-06-07T23:45:03.414609034+02:00",
"data": {
"id": "abcde-fghij",
"label": "My folder"
}
}
๐ FolderRejected (DEPRECATED)
Deprecated since version v1.13.0 โ she's still emitted for compatibility, but she's deprecated, periodt. Use the replacement PendingFoldersChanged event instead, iykyk ๐
She's emitted when a device sends index info for a folder we don't have, or do have but don't share with the device in question. Awkward much ๐ญ
{
"id": 27,
"globalID": 27,
"type": "FolderRejected",
"time": "2014-08-19T10:41:06.761751399+02:00",
"data": {
"device": "EJHMPAQ-OGCVORE-ISB4IS3-SYYVJXF-TKJGLTU-66DIQPF-GJ5D2GX-GQ3OWQK",
"folder": "GXWxf-3zgnU",
"folderLabel": "My Pictures"
}
}
๐ฆ FolderResumed
Bestie this is the glow-up of FolderPaused โ generated when the config changes regarding the "paused" state of a folder, and yeah, sent repeatedly for each changed folder. Same energy, unpaused โจ
{
"id": 93,
"globalID": 93,
"type": "FolderResumed",
"time": "2021-06-07T23:45:03.414609034+02:00",
"data": {
"id": "abcde-fghij",
"label": "My folder"
}
}
๐ FolderScanProgress
Emitted in regular intervals (folder setting ProgressIntervalS, 2s by default โ yes bestie, two whole seconds) during scans. She gives you the amount of bytes already scanned and the bytes to be scanned in total, plus the current scanning rates in bytes per second. It's giving progress bar main character energy ๐
{
"data" : {
"total" : 1,
"rate" : 0,
"current" : 0,
"folder" : "bd7q3-zskm5"
},
"globalID" : 29,
"type" : "FolderScanProgress",
"time" : "2017-03-06T15:00:58.072004209+01:00",
"id" : 29
}
๐ FolderSummary
The FolderSummary event is emitted when folder contents have changed locally. Use it to calculate the current local completion state โ literally your "how done are we" vibe check ๐ฅ
{
"id": 16,
"type": "FolderSummary",
"time": "2024-01-31T08:27:30.777875+01:00",
"data": {
"folder": "default",
"summary": {
"error": "",
"errors": 0,
"globalBytes": 4,
"globalDeleted": 18664,
"globalDirectories": 0,
"globalFiles": 1,
"globalSymlinks": 0,
"globalTotalItems": 18665,
"ignorePatterns": false,
"inSyncBytes": 4,
"inSyncFiles": 1,
"invalid": "",
"localBytes": 4,
"localDeleted": 18664,
"localDirectories": 0,
"localFiles": 1,
"localSymlinks": 0,
"localTotalItems": 18665,
"needBytes": 0,
"needDeletes": 0,
"needDirectories": 0,
"needFiles": 0,
"needSymlinks": 0,
"needTotalItems": 0,
"pullErrors": 0,
"receiveOnlyChangedBytes": 0,
"receiveOnlyChangedDeletes": 0,
"receiveOnlyChangedDirectories": 0,
"receiveOnlyChangedFiles": 0,
"receiveOnlyChangedSymlinks": 0,
"receiveOnlyTotalItems": 0,
"remoteSequence": {
"MRIW7OK-NETT3M4-N6SBWME-N25O76W-YJKVXPH-FUMQJ3S-P57B74J-GBITBAC": 37329
},
"sequence": 37329,
"state": "idle",
"stateChanged": "2024-01-31T08:27:24+01:00",
"version": 37329,
"watchError": ""
}
}
}
๐ง FolderWatchStateChanged
The FolderWatchStateChanged event pops off when a folder's watcher routine encounters a new error, or when a previous error disappeared after retrying. She contains the ID of the affected folder plus textual error messages describing the previous (from) and the updated (to) error conditions. And if there was no error in either of these? The respective field is just omitted โ she's discreet like that ๐
{
"id": 123,
"type": "FolderWatchStateChanged",
"time": "2022-03-14T12:34:56.890000000+01:00",
"data": {
"folder": "default",
"from": "Something bad happened.",
"to": "Something worse happened."
}
}
๐ธ ItemFinished
Generated when Syncthing ends synchronizing a file to a newer version. Here's a successful operation, slay:
{
"id": 93,
"globalID": 93,
"type": "ItemFinished",
"time": "2014-07-13T21:22:03.414609034+02:00",
"data": {
"item": "test.txt",
"folder": "default",
"error": null,
"type": "file",
"action": "update"
}
}
And an unsuccessful one, we've all been there ๐ญ:
{
"id": 44,
"globalID": 44,
"type": "ItemFinished",
"time": "2015-05-27T11:21:05.711133004+02:00",
"data": {
"action": "update",
"error": "open /Users/jb/src/github.com/syncthing/syncthing/test/s2/foo/.syncthing.hej.tmp: permission denied",
"folder": "default",
"item": "foo/hej",
"type": "file"
}
}
The action field is either update (contents changed), metadata (file metadata changed but not contents), or delete. No cap ๐ซถ
Added in version 0.11.10: the metadata action.
๐ ItemStarted
Generated when Syncthing begins synchronizing a file to a newer version. The prequel โจ
{
"id": 93,
"globalID": 93,
"type": "ItemStarted",
"time": "2014-07-13T21:22:03.414609034+02:00",
"data": {
"item": "test.txt",
"folder": "default",
"type": "file",
"action": "update"
}
}
Same deal: the action field is either update (contents changed), metadata (file metadata changed but not contents), or delete.
Added in version 0.11.10: the metadata action.
๐ ListenAddressesChanged
This event is emitted when a listen address changes. She's got a whole URL-parsing situation going on, look:
{
"type" : "ListenAddressesChanged",
"id" : 70,
"time" : "2017-03-06T15:01:24.88340663+01:00",
"globalID" : 70,
"data" : {
"address" : {
"Fragment" : "",
"RawQuery" : "",
"Scheme" : "dynamic+https",
"Path" : "/endpoint",
"RawPath" : "",
"User" : null,
"ForceQuery" : false,
"Host" : "relays.syncthing.net",
"Opaque" : ""
},
"wan" : [
{
"ForceQuery" : false,
"User" : null,
"Host" : "31.15.66.212:443",
"Opaque" : "",
"Path" : "/",
"RawPath" : "",
"RawQuery" : "id=F4HSJVO-CP2C3IL-YLQYLSU-XTYODAG-PPU4LGV-PH3MU4N-G6K56DV-IPN47A&pingInterval=1m0s&networkTimeout=2m0s&sessionLimitBps=0&globalLimitBps=0&statusAddr=:22070&providedBy=",
"Scheme" : "relay",
"Fragment" : ""
}
],
"lan" : [
{
"RawQuery" : "id=F4HSJVO-CP2C3IL-YLQYLSU-XTYODAG-PPU4LGV-PH3MU4N-G6K56DV-IPN47A&pingInterval=1m0s&networkTimeout=2m0s&sessionLimitBps=0&globalLimitBps=0&statusAddr=:22070&providedBy=",
"Scheme" : "relay",
"Fragment" : "",
"RawPath" : "",
"Path" : "/",
"Host" : "31.15.66.212:443",
"Opaque" : "",
"ForceQuery" : false,
"User" : null
}
]
}
}
(yes the field order in the JSON is different in wan and lan, no she will not be fixing that, don't come for her ๐)
๐ LocalChangeDetected
Generated upon scan whenever the local disk has discovered an updated file from the previous scan. And listen โ this does not include events that are discovered and copied from other devices (RemoteChangeDetected). Only files that were changed on the local filesystem, okay? Local only, homegrown, main character ๐
NOTE: this event is not included in GET /rest/events endpoint without a mask specified โ you gotta select it explicitly, bestie. She doesn't just show up uninvited ๐
{
"id": 7,
"globalID": 59,
"time": "2016-09-26T22:07:10.7189141-04:00",
"type": "LocalChangeDetected",
"data": {
"action": "deleted",
"folder": "vitwy-zjxqt",
"folderID": "vitwy-zjxqt",
"label": "TestSync",
"path": "test file.rtf",
"type": "file"
}
}
Deprecated since version v1.1.2: the folderID field is a legacy name kept only for compatibility. Use the folder field with identical content instead, mkay? ๐ซถ
โญ LocalIndexUpdated
Generated when the local index information has changed โ due to synchronizing one or more items from the cluster, or discovering local changes during a scan. Busy girl behaviour ๐
{
"id": 59,
"globalID": 59,
"type": "LocalIndexUpdated",
"time": "2014-07-17T13:27:28.051369434+02:00",
"data": {
"folder": "default",
"items": 1000,
"filenames": [
"foo",
"bar",
"baz"
],
"sequence": 12345,
"version": 12345
}
}
Deprecated since version v1.10.0: the version field is a legacy name kept only for compatibility. Use the sequence field with identical content instead. Same content, different name, we love a rebrand โจ
๐ฅ LoginAttempt
When authentication is enabled for the GUI, this event is emitted on every login attempt. And if either the username or password are incorrect, success is false โ and in any case the given username is returned. So yeah, she's watching ๐๐
{
"id" : 187,
"time" : "2017-03-07T00:19:24.420386143+01:00",
"data" : {
"remoteAddress" : "127.0.0.1",
"username" : "somename",
"success" : false
},
"type" : "LoginAttempt",
"globalID" : 195
}
But wait, bestie, there's a plot twist ๐ซถ โ if the X-Forwared-For header is present and the connecting host is either on localhost or on the same LAN, then it gets treated as a reverse proxy. In that case the remoteAddress field gets filled with the leftmost IP address from the header, and the extra proxy field keeps the original IP of the connecting host. Two fields, two truths, no cap.
{
"id" : 187,
"time" : "2017-03-07T00:19:24.420386143+01:00",
"data" : {
"proxy" : "127.0.0.1",
"remoteAddress" : "192.168.178.10",
"username" : "somename",
"success" : false
},
"type" : "LoginAttempt",
"globalID" : 195
}
๐ PendingDevicesChanged ๐
Added in version 1.14.0.
This one drops when pending devices get added / updated (that's a connection from an unknown ID, bestie ๐) or removed (the device is ignored, dismissed or added). Literally the "who is this??" notification of the Syncthing world.
{
"id": 87,
"type": "PendingDevicesChanged",
"time": "2020-12-22T22:24:37.578586718+01:00",
"data": {
"added": [
{
"address": "127.0.0.1:51807",
"deviceID": "EJHMPAQ-OGCVORE-ISB4IS3-SYYVJXF-TKJGLTU-66DIQPF-GJ5D2GX-GQ3OWQK",
"name": "My dusty computer"
}
],
"removed": [
{
"deviceID": "P56IOI7-MZJNU2Y-IQGDREY-DM2MGTI-MGL3BXN-PQ6W5BM-TBBZ4TJ-XZWICQ2"
}
]
}
}
๐ธ PendingFoldersChanged ๐ธ
Added in version 1.14.0.
Emitted when pending folders were added / updated โ meaning some device offered them but they're not shared to them โ or removed (the folder got ignored, dismissed or added, or it's just no longer offered from the remote device). Big heads up ๐
: a removed entry without a deviceID attribute means the folder is no longer pending for any device. So no deviceID = nobody wants it, periodt.
{
"id": 101,
"type": "PendingFoldersChanged",
"time": "2020-12-22T22:36:55.66744317+01:00",
"data": {
"added": [
{
"deviceID": "EJHMPAQ-OGCVORE-ISB4IS3-SYYVJXF-TKJGLTU-66DIQPF-GJ5D2GX-GQ3OWQK",
"folderID": "GXWxf-3zgnU",
"folderLabel": "My Pictures"
"receiveEncrypted": "false"
"remoteEncrypted": "false"
}
],
"removed": [
{
"deviceID": "P56IOI7-MZJNU2Y-IQGDREY-DM2MGTI-MGL3BXN-PQ6W5BM-TBBZ4TJ-XZWICQ2",
"folderID": "neyfh-sa2nu"
},
{
"folderID": "abcde-fghij"
}
]
}
}
๐ฆ RemoteChangeDetected ๐ฆ
Generated upon scan whenever a file is locally updated because of a remote change. Files that get updated locally produce a LocalChangeDetected event instead โ so like, know the difference, iykyk.
NOTE: This event is not included in the GET /rest/events endpoint without a mask specified โ you have to select it explicitly, bestie. It's not gonna show up just because you want it to ๐ญ
{
"time" : "2017-03-06T23:58:21.844739891+01:00",
"globalID" : 123,
"data" : {
"type" : "file",
"action" : "deleted",
"folder": "Dokumente",
"folderID" : "Dokumente",
"path" : "testfile",
"label" : "Dokumente",
"modifiedBy" : "BPDFDTU"
},
"type" : "RemoteChangeDetected",
"id" : 2
}
Deprecated since versionv1.1.2: thefolderIDfield is a legacy name kept only for compatibility. Use thefolderfield instead โ identical content, so swap it and slay ๐ซถ
๐ RemoteDownloadProgress ๐
This event is emitted when a DownloadProgress message is received. It returns a data map of filenames with a count of downloaded blocks. The files in question are currently being downloaded on the remote device and belong to folder. It's giving "progress bar but make it JSON" โญ
{
"time" : "2017-03-07T00:11:37.65838955+01:00",
"globalID" : 170,
"data" : {
"state" : {
"tahr64-6.0.5.iso" : 1784
},
"device" : "F4HSJVO-CP2C3IL-YLQYLSU-XTYODAG-PPU4LGV-PH3MU4N-G6K56DV-IPN47A",
"folder" : "Dokumente"
},
"type" : "RemoteDownloadProgress",
"id" : 163
}
๐ RemoteIndexUpdated ๐
Generated each and every time new index information arrives from a device. Every time. No skipping ๐
{
"id": 44,
"globalID": 44,
"type": "RemoteIndexUpdated",
"time": "2014-07-13T21:04:35.394184435+02:00",
"data": {
"device": "NFGKEKE-7Z6RTH7-I3PRZXS-DEJF3UJ-FRWJBFO-VBBTDND-4SGNGVZ-QUQHJAG",
"folder": "lightroom",
"items": 1000
}
}
โจ Starting โจ
Emitted exactly once, when Syncthing starts โ and like, before parsing configuration etc. So it's the very first thing awake in the morning, before coffee โ
{
"id": 1,
"globalID": 1,
"type": "Starting",
"time": "2014-07-17T13:13:32.044470055+02:00",
"data": {
"home": "/home/jb/.config/syncthing"
}
}
๐ง StartupComplete ๐ง
Emitted exactly once too, when initialization is complete and Syncthing is ready to start exchanging data with other devices. That's the "okay I'm dressed, let's go" moment ๐
{
"id": 1,
"globalID": 1,
"type": "StartupComplete",
"time": "2014-07-13T21:03:18.383239179+02:00",
"data": null
}
๐ StateChanged ๐
Emitted when a folder changes state. The possible states are idle, scanning, syncing and error. The field duration is the number of seconds the folder spent in the state named by from. In the example down below, the folder default was in state scanning for 0.198 seconds and is now chilling in state idle. Character development, honestly ๐
{
"id": 8,
"globalID": 8,
"type": "StateChanged",
"time": "2014-07-17T13:14:28.697493016+02:00",
"data": {
"folder": "default",
"from": "scanning",
"duration": 0.19782869900000002,
"to": "idle"
}
}
๐ AUTHOR ๐
The Syncthing Authors โ yes, all of them, a whole squad ๐ซถ
๐ COPYRIGHT ๐
2014-2026, The Syncthing Authors
And that's the whole page, bestie, we ate and left absolutely no crumbs ๐ธ This was SYNCTHING-EVENT-API(7), version v2.1.0, dated Oct 07, 2026 โ go forth and stream those events responsibly ๐โจ
๐ฆ where this page comes from
- arch rolling: syncthing 2.1.7-1 ยท MPL-2.0
- nixos 26.05: syncthing 2.1.7
- nixpkgs unstable: syncthing 2.1.7
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms