How to use REST API to accept new folders

I’m new to using the REST API – heck I’m new to using the concept of a REST API but I’ve definitely heard this term a lot over the years. I’m wondering how to add a new folder on the remote side.

On the client side using the GUI I’ve added a new folder to sync

Querying through the REST API on the peer side - I get the following:

$ curl -k -X GET -H "X-API-Key: ZjpQ5U7gaXdjYttzikzvZvtwPHaUnqvj" https://localhost:8384/rest/cluster/pending/folders
{
  "kmmgl-nygfm": {
    "offeredBy": {
      "Z2M6GO2-455NXSO-CQLJVBB-IIG5MPA-ERT636W-LUK3GUC-MUSIBP6-6UIVQQF": {
        "time": "2021-10-20T16:47:37Z",
        "label": "syncthing-restAPI",
        "receiveEncrypted": false,
        "remoteEncrypted": false
      }
    }
  }
}

So I’m at a loss here how to add this folder using PUT/PATCH or any other method using the CLI.

With the PUT method I think I’m expected to push the entire config. With $ curl -k -X GET -H "X-API-Key: ZjpQ5U7gaXdjYttzikzvZvtwPHaUnqvj" https://localhost:8384/rest/config I’m able to get the entire config, however I’m not sure how I added the pending folder into the config or even push the config. I was looking for some guidance on this issue.

You can use the cli for adding removing devices. But adding it on one side is not enough, you have to do the same thing on the other side for things to work.

The prompt in the UI is just an intermediate step for that, so A has to add B, and B has to add A.

I understand the approval needs to be on both ends. However with my test situation I’ve added both devices on both ends using GUI.

I’m trying now how to add a folder on one end (using GUI) – which I’ve done – but accept the folder request on the other end using CLI via RestAPI. I might be asking indirectly how to specifically use the PUT command since I’m guessing that’s what needs to be used for this operation – but I don’t know how to pass the config on the CLI, nor exactly how to modify the config.xml to add the folder.

Syncthing comes with a cli built in

syncthing cli help

The rest commands are documented in the docs.

“Accepting” a device is the same as just adding it.

Maybe I’m not asking my question appropriately.

I wasn’t aware that the syncthing cli existed but I see it. In going through the syncthing cli – is there a way to show pending folder requests that is equivalent to:

curl -k -X GET -H "X-API-Key: ZjpQ5U7gaXdjYttzikzvZvtwPHaUnqvj" https://localhost:8384/rest/cluster/pending/folders

How do I accept the pending folder either through the use of the syncthing cli or rest-api?

I’ve read the rest documentation. I’ve never used PUSH via rest-API to invoke changes. How do I push the config or portion of the config to accept a pending folder?

You need to copy the respective values from the pending folder object to where they would live in the config basically. Only folder ID and the two booleans are required AFAIR and the label is just a suggestion from the other end.

Sorry can’t tell you much about the PATCH method, but I know there is something about it in the docs.

According to Config Endpoints — Syncthing v1 documentation, using the POST method would be appropriate to add or change a single folder config. Payload is JSON just as you would GET it for an existing folder.

Hmm, its clearly my lack of experience here.

Ok I learned how to put the entire config:

Get config: curl -k -X GET -H "X-API-Key: ZjpQ5U7gaXdjYttzikzvZvtwPHaUnqvj" https://localhost:8384/rest/config > config.json

PUT config: curl -k -X PUT -H "X-API-Key: ZjpQ5U7gaXdjYttzikzvZvtwPHaUnqvj" https://localhost:8384/rest/config -d @config.json

Get pending folders:

curl -k -X GET -H "X-API-Key: ZjpQ5U7gaXdjYttzikzvZvtwPHaUnqvj" https://localhost:8384/rest/cluster/pending/folders
{
  "kmmgl-nygfm": {
    "offeredBy": {
      "Z2M6GO2-455NXSO-CQLJVBB-IIG5MPA-ERT636W-LUK3GUC-MUSIBP6-6UIVQQF": {
        "time": "2021-10-20T18:18:40Z",
        "label": "syncthing-restAPI",
        "receiveEncrypted": false,
        "remoteEncrypted": false
      }
    }
  }
}

Doesnt seem to be a simple way to add this folder to the config – other than manually do it and then add a bunch of other parameters. In terms of other parameters, my folders have the following structure:

$ curl -k -X GET -H "X-API-Key: ZjpQ5U7gaXdjYttzikzvZvtwPHaUnqvj" https://localhost:8384/rest/config/folders
[
  {
    "id": "default",
    "label": "Default Folder",
    "filesystemType": "basic",
    "path": "/home/kevdog/Sync",
    "type": "sendreceive",
    "devices": [
      {
        "deviceID": "Z2M6GO2-455NXSO-CQLJVBB-IIG5MPA-ERT636W-LUK3GUC-MUSIBP6-6UIVQQF",
        "introducedBy": "",
        "encryptionPassword": ""
      },
      {
        "deviceID": "4UGYVUF-5Q52M6L-BAXWG3H-CBNO2TC-HOWE6ZM-NJAZDNT-OTP7FOR-VZUP6AS",
        "introducedBy": "",
        "encryptionPassword": ""
      }
    ],
    "rescanIntervalS": 3600,
    "fsWatcherEnabled": true,
    "fsWatcherDelayS": 10,
    "ignorePerms": false,
    "autoNormalize": true,
    "minDiskFree": {
      "value": 0,
      "unit": ""
    },
    "versioning": {
      "type": "",
      "params": {},
      "cleanupIntervalS": 3600,
      "fsPath": "",
      "fsType": "basic"
    },
    "copiers": 0,
    "pullerMaxPendingKiB": 0,
    "hashers": 0,
    "order": "random",
    "ignoreDelete": false,
    "scanProgressIntervalS": 0,
    "pullerPauseS": 0,
    "maxConflicts": -1,
    "disableSparseFiles": false,
    "disableTempIndexes": false,
    "paused": false,
    "weakHashThresholdPct": 25,
    "markerName": ".stfolder",
    "copyOwnershipFromParent": false,
    "modTimeWindowS": 0,
    "maxConcurrentWrites": 2,
    "disableFsync": false,
    "blockPullOrder": "standard",
    "copyRangeMethod": "standard",
    "caseSensitiveFS": false,
    "junctionsAsDirs": false
  },
  {
    "id": "uxdnc-gkngr",
    "label": "SyncthingTestFolder",
    "filesystemType": "basic",
    "path": "/home/kevdog/SyncthingTestFolder",
    "type": "sendreceive",
    "devices": [
      {
        "deviceID": "Z2M6GO2-455NXSO-CQLJVBB-IIG5MPA-ERT636W-LUK3GUC-MUSIBP6-6UIVQQF",
        "introducedBy": "",
        "encryptionPassword": ""
      },
      {
        "deviceID": "4UGYVUF-5Q52M6L-BAXWG3H-CBNO2TC-HOWE6ZM-NJAZDNT-OTP7FOR-VZUP6AS",
        "introducedBy": "",
        "encryptionPassword": ""
      }
    ],
    "rescanIntervalS": 3600,
    "fsWatcherEnabled": true,
    "fsWatcherDelayS": 10,
    "ignorePerms": false,
    "autoNormalize": true,
    "minDiskFree": {
      "value": 1,
      "unit": "%"
    },
    "versioning": {
      "type": "",
      "params": {},
      "cleanupIntervalS": 0,
      "fsPath": "",
      "fsType": "basic"
    },
    "copiers": 0,
    "pullerMaxPendingKiB": 0,
    "hashers": 0,
    "order": "random",
    "ignoreDelete": false,
    "scanProgressIntervalS": 0,
    "pullerPauseS": 0,
    "maxConflicts": 10,
    "disableSparseFiles": false,
    "disableTempIndexes": false,
    "paused": false,
    "weakHashThresholdPct": 25,
    "markerName": ".stfolder",
    "copyOwnershipFromParent": false,
    "modTimeWindowS": 0,
    "maxConcurrentWrites": 2,
    "disableFsync": false,
    "blockPullOrder": "standard",
    "copyRangeMethod": "standard",
    "caseSensitiveFS": false,
    "junctionsAsDirs": false
  }
]

Seems like there should be an easy route to add a folder but apparently there isn’t. Seems like my workflow here is going to be GET folders, query pending folders/endpoints, generate json manually to add folder modifying path and any other parameters, use POST method to add folder.

**Confirmed this method to work although its clunky. Get an existing folder object so I can use it as baseline for new folder:

curl -k -X GET -H "X-API-Key: ZjpQ5U7gaXdjYttzikzvZvtwPHaUnqvj" https://localhost:8384/rest/config/folders/uxdnc-gkngr > test2.json

Modify test2.json changing id, label and path (and optionally anything else if needed).

Post the Object back:

curl -k -X POST -H "X-API-Key: ZjpQ5U7gaXdjYttzikzvZvtwPHaUnqvj" https://localhost:8384/rest/config/folders -d @test2.json

Sync worked. Cool stuff I suppose.

There was some discussion about dedicated API endpoints to accept or ignore a pending folder, but that was before the /rest/config API was born. With that available, one doesn’t need to re-post the complete config anymore, but just a single folder entry. So having separate API endpoints became less important because they would have looked much the same, just a few less attributes in the JSON you’d need to send. So yes, copying the details to a new JSON object and posting that is the way it’s supposed to work.

Note that the folder defaults should probably get applied automatically though. So you only need to supply the fields which are unique to the new folder. Some from the pending folder info and others (like the filesystem path) you need to choose “manually” somehow. Everything else gets initialized to defaults, though I haven’t checked if it actually does use the configured folder defaults. So your constructed JSON object reduces to just a few lines and can be constructed with a simple jq command invocation for example.

If you’re looking to automate accepting folders, and don’t have a requirement to supply the filesystem path manually, there is also an “auto accept” feature which you can enable for a device. Just in case you haven’t noticed that.

Example:

{
    "id": "abcde-fghij",
    "label": "Test cand 2",
    "path": "/home/acolomb/Syncthing/devtest/Test cand 2",
    "devices": [
        {
            "deviceID": "3RNMLV5-76TKW3U-VZXZ2AQ-FWHWW5W-IIFN2MF-J7JOZ6Q-YWPJ5AB-OC4IDQH",
        }
    ],
}

After a bit of fiddling with the jq tool:

jq --arg l "My Label" --arg p /path/to/folder \
   '{ id: . | keys[], label: $l, path: $p, devices: .[].offeredBy | keys | map({ deviceID: . }) }'\
<<EOF
{
  "kmmgl-nygfm": {
    "offeredBy": {
      "Z2M6GO2-455NXSO-CQLJVBB-IIG5MPA-ERT636W-LUK3GUC-MUSIBP6-6UIVQQF": {
        "time": "2021-10-20T18:18:40Z",
        "label": "syncthing-restAPI",
        "receiveEncrypted": false,
        "remoteEncrypted": false
      }
    }
  }
}
EOF
{
  "id": "kmmgl-nygfm",
  "label": "My Label",
  "path": "/path/to/folder",
  "devices": [
    {
      "deviceID": "Z2M6GO2-455NXSO-CQLJVBB-IIG5MPA-ERT636W-LUK3GUC-MUSIBP6-6UIVQQF"
    }
  ]
}

(Note the <<EOF so-called heredoc syntax is just for this example usage. Redirect from a file or build a pipe as you see fit in your use case.)

Obviously doesn’t handle all the details, but it’s a start for most stuff that can be processed automatically. remoteEncrypted cries for a password to be supplied if true. The label can be different when offered from several devices, so it’s ambiguous which one to pick.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.