API

Automation.

Hot folders and sync jobs are administrator calls and need the automation feature once you pass the free allowance. Event rules are for the rule's owner, and an administrator sees every rule. In Free mode one automation job runs.

See the API reference for the key and for errors. The guide to what a rule can do is Event rules.

Hot folders

GET /api/v1/hot-folders

Watched folders.

Who. An administrator, with a key that has the admin scope. An administrator's key that does not have that scope is refused. The key needs a license that includes the REST API.

Success. 200.

The body is an array.

FieldTypeMeaning
idstringrequiredThe id.
namestringrequiredThe name.
rootIdstringrequiredThe id.
rootNamestringrequiredThe storage location's name.
pathstringrequiredA path relative to the space or the storage location, with / between folders and no leading slash.
settleSecsintegerrequired
destinationstringrequired
destKindstringrequiredWhat the destination means. unset is a row from before kinds existed; the runner refuses those rather than guessing.
afterSendstringrequiredWhat happens to the original once it has gone: leave, move or delete.
enabledbooleanrequired
pausedReasonstringoptional, left out when empty
lastRunAtstringoptional, left out when emptyWhen the runner last looked at this folder. Absent until it has.
lastErrorstringoptional, left out when emptyWhy it is not working, in the runner's words. This is what turns "nothing is happening" into something an administrator can fix.
createdAtstringrequiredA time, as RFC 3339.
[
  {
    "id": "k7Qm2sLp9vX4aB1c",
    "name": "Rush delivery",
    "rootId": "k7Qm2sLp9vX4aB1c",
    "rootName": "example",
    "path": "projects/rush",
    "settleSecs": 1,
    "destination": "example",
    "destKind": "example",
    "afterSend": "example",
    "enabled": true,
    "createdAt": "2026-10-05T18:00:00Z"
  }
]

Errors. The body always has the shape in Errors. Match on code.

StatuscodeWhen
401unauthenticatedno key, or a key that is unknown, expired, revoked, or owned by a disabled account
403forbiddenthe key is valid but does not have the scope, or an administrator route was called by someone who is not an administrator
402licence_requiredthe license does not include the REST API
{
  "error": {
    "code": "unauthenticated",
    "message": "sign in to continue"
  }
}

POST /api/v1/hot-folders

Watch a folder.

Who. An administrator, with a key that has the admin scope. An administrator's key that does not have that scope is refused. The key needs a license that includes the REST API.

Request body. JSON.

A field the server does not know is refused with 400.

FieldTypeMeaning
namestringrequiredThe name.
rootIdstringoptionalThe location, for a caller that still names storage directly.
spaceIdstringoptionalThe space, when the folder was chosen from Home.
pathstringoptionalA path relative to the space or the storage location, with / between folders and no leading slash.
settleSecsintegeroptional
destinationstringrequired
destKindstringrequiredWhat the destination means. Required on a new folder: there is no sensible default, and guessing is the thing this field exists to stop.
afterSendstringoptional
{
  "name": "Rush delivery",
  "rootId": "k7Qm2sLp9vX4aB1c",
  "spaceId": "k7Qm2sLp9vX4aB1c",
  "path": "projects/rush",
  "settleSecs": 1,
  "destination": "example",
  "destKind": "example",
  "afterSend": "example"
}

Success. 200.

FieldTypeMeaning
idstringrequiredThe id.
namestringrequiredThe name.
rootIdstringrequiredThe id.
rootNamestringrequiredThe storage location's name.
pathstringrequiredA path relative to the space or the storage location, with / between folders and no leading slash.
settleSecsintegerrequired
destinationstringrequired
destKindstringrequiredWhat the destination means. unset is a row from before kinds existed; the runner refuses those rather than guessing.
afterSendstringrequiredWhat happens to the original once it has gone: leave, move or delete.
enabledbooleanrequired
pausedReasonstringoptional, left out when empty
lastRunAtstringoptional, left out when emptyWhen the runner last looked at this folder. Absent until it has.
lastErrorstringoptional, left out when emptyWhy it is not working, in the runner's words. This is what turns "nothing is happening" into something an administrator can fix.
createdAtstringrequiredA time, as RFC 3339.
{
  "id": "k7Qm2sLp9vX4aB1c",
  "name": "Rush delivery",
  "rootId": "k7Qm2sLp9vX4aB1c",
  "rootName": "example",
  "path": "projects/rush",
  "settleSecs": 1,
  "destination": "example",
  "destKind": "example",
  "afterSend": "example",
  "enabled": true,
  "createdAt": "2026-10-05T18:00:00Z"
}

Errors. The body always has the shape in Errors. Match on code.

StatuscodeWhen
401unauthenticatedno key, or a key that is unknown, expired, revoked, or owned by a disabled account
403forbiddenthe key is valid but does not have the scope, or an administrator route was called by someone who is not an administrator
402licence_requiredthe license does not include the REST API
{
  "error": {
    "code": "unauthenticated",
    "message": "sign in to continue"
  }
}

PATCH /api/v1/hot-folders/{id}

Change one.

Who. An administrator, with a key that has the admin scope. An administrator's key that does not have that scope is refused. The key needs a license that includes the REST API.

Parameters.

NameInTypeMeaning
idpathstringrequiredThe resource's id.

Request body. JSON.

A field the server does not know is refused with 400.

FieldTypeMeaning
namestringoptionalThe name.
pathstringoptionalA path relative to the space or the storage location, with / between folders and no leading slash.
settleSecsintegeroptional
destinationstringoptional
destKindstringoptional
afterSendstringoptional
enabledbooleanoptional
{
  "name": "Rush delivery",
  "path": "projects/rush",
  "settleSecs": 1,
  "destination": "example",
  "destKind": "example",
  "afterSend": "example",
  "enabled": true
}

Success. 200.

FieldTypeMeaning
idstringrequiredThe id.
namestringrequiredThe name.
rootIdstringrequiredThe id.
rootNamestringrequiredThe storage location's name.
pathstringrequiredA path relative to the space or the storage location, with / between folders and no leading slash.
settleSecsintegerrequired
destinationstringrequired
destKindstringrequiredWhat the destination means. unset is a row from before kinds existed; the runner refuses those rather than guessing.
afterSendstringrequiredWhat happens to the original once it has gone: leave, move or delete.
enabledbooleanrequired
pausedReasonstringoptional, left out when empty
lastRunAtstringoptional, left out when emptyWhen the runner last looked at this folder. Absent until it has.
lastErrorstringoptional, left out when emptyWhy it is not working, in the runner's words. This is what turns "nothing is happening" into something an administrator can fix.
createdAtstringrequiredA time, as RFC 3339.
{
  "id": "k7Qm2sLp9vX4aB1c",
  "name": "Rush delivery",
  "rootId": "k7Qm2sLp9vX4aB1c",
  "rootName": "example",
  "path": "projects/rush",
  "settleSecs": 1,
  "destination": "example",
  "destKind": "example",
  "afterSend": "example",
  "enabled": true,
  "createdAt": "2026-10-05T18:00:00Z"
}

Errors. The body always has the shape in Errors. Match on code.

StatuscodeWhen
404not_foundnot there, or not visible to this caller
401unauthenticatedno key, or a key that is unknown, expired, revoked, or owned by a disabled account
403forbiddenthe key is valid but does not have the scope, or an administrator route was called by someone who is not an administrator
402licence_requiredthe license does not include the REST API
{
  "error": {
    "code": "not_found",
    "message": "not found"
  }
}

DELETE /api/v1/hot-folders/{id}

Stop watching.

Who. An administrator, with a key that has the admin scope. An administrator's key that does not have that scope is refused. The key needs a license that includes the REST API.

Parameters.

NameInTypeMeaning
idpathstringrequiredThe resource's id.

Success. 200.

The reply has no body.

Errors. The body always has the shape in Errors. Match on code.

StatuscodeWhen
404not_foundnot there, or not visible to this caller
401unauthenticatedno key, or a key that is unknown, expired, revoked, or owned by a disabled account
403forbiddenthe key is valid but does not have the scope, or an administrator route was called by someone who is not an administrator
402licence_requiredthe license does not include the REST API
{
  "error": {
    "code": "not_found",
    "message": "not found"
  }
}

Sync jobs

GET /api/v1/sync-jobs

One-way sync jobs.

Who. An administrator, with a key that has the admin scope. An administrator's key that does not have that scope is refused. The key needs a license that includes the REST API.

Success. 200.

The body is an array.

FieldTypeMeaning
idstringrequiredThe id.
namestringrequiredThe name.
sourceRootstringrequired
sourceRootNamestringrequired
sourcePathstringrequired
destinationstringrequired
schedulestringrequired
enabledbooleanrequired
pausedReasonstringoptional, left out when empty
lastRunAtstringoptional, left out when emptyA time, as RFC 3339.
destKindstringrequiredWhat the destination means. unset is a row from before kinds existed; the runner refuses those rather than guessing.
nextRunAtstringoptional, left out when emptyWhen the schedule says it should next go. Absent for a job that is not on a timer.
lastErrorstringoptional, left out when emptyWhy it is not working, in the runner's words.
createdAtstringrequiredA time, as RFC 3339.
[
  {
    "id": "k7Qm2sLp9vX4aB1c",
    "name": "Rush delivery",
    "sourceRoot": "example",
    "sourceRootName": "example",
    "sourcePath": "projects/rush",
    "destination": "example",
    "schedule": "example",
    "enabled": true,
    "destKind": "example",
    "createdAt": "2026-10-05T18:00:00Z"
  }
]

Errors. The body always has the shape in Errors. Match on code.

StatuscodeWhen
401unauthenticatedno key, or a key that is unknown, expired, revoked, or owned by a disabled account
403forbiddenthe key is valid but does not have the scope, or an administrator route was called by someone who is not an administrator
402licence_requiredthe license does not include the REST API
{
  "error": {
    "code": "unauthenticated",
    "message": "sign in to continue"
  }
}

POST /api/v1/sync-jobs

Add one.

Who. An administrator, with a key that has the admin scope. An administrator's key that does not have that scope is refused. The key needs a license that includes the REST API.

Request body. JSON.

A field the server does not know is refused with 400.

FieldTypeMeaning
namestringrequiredThe name.
sourceRootstringoptionalThe location, for a caller that still names storage directly.
spaceIdstringoptionalThe space, when the folder was chosen from Home.
sourcePathstringoptional
destinationstringrequired
schedulestringoptional
destKindstringrequiredWhat the destination means. Required: there is no sensible default, and guessing is what this field exists to stop.
{
  "name": "Rush delivery",
  "sourceRoot": "example",
  "spaceId": "k7Qm2sLp9vX4aB1c",
  "sourcePath": "projects/rush",
  "destination": "example",
  "schedule": "example",
  "destKind": "example"
}

Success. 200.

FieldTypeMeaning
idstringrequiredThe id.
namestringrequiredThe name.
sourceRootstringrequired
sourceRootNamestringrequired
sourcePathstringrequired
destinationstringrequired
schedulestringrequired
enabledbooleanrequired
pausedReasonstringoptional, left out when empty
lastRunAtstringoptional, left out when emptyA time, as RFC 3339.
destKindstringrequiredWhat the destination means. unset is a row from before kinds existed; the runner refuses those rather than guessing.
nextRunAtstringoptional, left out when emptyWhen the schedule says it should next go. Absent for a job that is not on a timer.
lastErrorstringoptional, left out when emptyWhy it is not working, in the runner's words.
createdAtstringrequiredA time, as RFC 3339.
{
  "id": "k7Qm2sLp9vX4aB1c",
  "name": "Rush delivery",
  "sourceRoot": "example",
  "sourceRootName": "example",
  "sourcePath": "projects/rush",
  "destination": "example",
  "schedule": "example",
  "enabled": true,
  "destKind": "example",
  "createdAt": "2026-10-05T18:00:00Z"
}

Errors. The body always has the shape in Errors. Match on code.

StatuscodeWhen
401unauthenticatedno key, or a key that is unknown, expired, revoked, or owned by a disabled account
403forbiddenthe key is valid but does not have the scope, or an administrator route was called by someone who is not an administrator
402licence_requiredthe license does not include the REST API
{
  "error": {
    "code": "unauthenticated",
    "message": "sign in to continue"
  }
}

PATCH /api/v1/sync-jobs/{id}

Change one.

Who. An administrator, with a key that has the admin scope. An administrator's key that does not have that scope is refused. The key needs a license that includes the REST API.

Parameters.

NameInTypeMeaning
idpathstringrequiredThe resource's id.

Request body. JSON.

A field the server does not know is refused with 400.

FieldTypeMeaning
namestringoptionalThe name.
sourcePathstringoptional
destinationstringoptional
schedulestringoptional
destKindstringoptional
enabledbooleanoptional
{
  "name": "Rush delivery",
  "sourcePath": "projects/rush",
  "destination": "example",
  "schedule": "example",
  "destKind": "example",
  "enabled": true
}

Success. 200.

FieldTypeMeaning
idstringrequiredThe id.
namestringrequiredThe name.
sourceRootstringrequired
sourceRootNamestringrequired
sourcePathstringrequired
destinationstringrequired
schedulestringrequired
enabledbooleanrequired
pausedReasonstringoptional, left out when empty
lastRunAtstringoptional, left out when emptyA time, as RFC 3339.
destKindstringrequiredWhat the destination means. unset is a row from before kinds existed; the runner refuses those rather than guessing.
nextRunAtstringoptional, left out when emptyWhen the schedule says it should next go. Absent for a job that is not on a timer.
lastErrorstringoptional, left out when emptyWhy it is not working, in the runner's words.
createdAtstringrequiredA time, as RFC 3339.
{
  "id": "k7Qm2sLp9vX4aB1c",
  "name": "Rush delivery",
  "sourceRoot": "example",
  "sourceRootName": "example",
  "sourcePath": "projects/rush",
  "destination": "example",
  "schedule": "example",
  "enabled": true,
  "destKind": "example",
  "createdAt": "2026-10-05T18:00:00Z"
}

Errors. The body always has the shape in Errors. Match on code.

StatuscodeWhen
404not_foundnot there, or not visible to this caller
401unauthenticatedno key, or a key that is unknown, expired, revoked, or owned by a disabled account
403forbiddenthe key is valid but does not have the scope, or an administrator route was called by someone who is not an administrator
402licence_requiredthe license does not include the REST API
{
  "error": {
    "code": "not_found",
    "message": "not found"
  }
}

DELETE /api/v1/sync-jobs/{id}

Remove one.

Who. An administrator, with a key that has the admin scope. An administrator's key that does not have that scope is refused. The key needs a license that includes the REST API.

Parameters.

NameInTypeMeaning
idpathstringrequiredThe resource's id.

Success. 200.

The reply has no body.

Errors. The body always has the shape in Errors. Match on code.

StatuscodeWhen
404not_foundnot there, or not visible to this caller
401unauthenticatedno key, or a key that is unknown, expired, revoked, or owned by a disabled account
403forbiddenthe key is valid but does not have the scope, or an administrator route was called by someone who is not an administrator
402licence_requiredthe license does not include the REST API
{
  "error": {
    "code": "not_found",
    "message": "not found"
  }
}

POST /api/v1/sync-jobs/{id}/dry-run

What a run would change. Reads both sides and writes nothing, so it needs no license.

Who. An administrator, with a key that has the admin scope. An administrator's key that does not have that scope is refused. The key needs a license that includes the REST API.

Parameters.

NameInTypeMeaning
idpathstringrequiredThe resource's id.

Request body. None.

Success. 200.

FieldTypeMeaning
addintegerrequired
changeintegerrequired
currentintegerrequired
bytesintegerrequiredSize in bytes.
samplearray of objectsrequiredUp to [PLAN_SAMPLE] entries, each add or change.

Each item is an object:

FieldTypeMeaning
pathstringrequiredA path relative to the space or the storage location, with / between folders and no leading slash.
whatstringrequired
bytesintegerrequiredSize in bytes.
truncatedbooleanrequiredTrue when the walk hit its ceiling, so the counts are a floor and the screen must not present them as the whole picture.
deleteintegerrequiredAlways zero, and present so the screen can say so. Deletes are not mirrored at all; see the module note.
{
  "add": 1,
  "change": 1,
  "current": 1,
  "bytes": 1048576,
  "sample": [
    {
      "path": "projects/rush",
      "what": "2026-10-05T18:00:00Z",
      "bytes": 1048576
    }
  ],
  "truncated": true,
  "delete": 1
}

Errors. The body always has the shape in Errors. Match on code.

StatuscodeWhen
400bad_requestthe source or the destination could not be read
404not_foundnot there, or not visible to this caller
401unauthenticatedno key, or a key that is unknown, expired, revoked, or owned by a disabled account
403forbiddenthe key is valid but does not have the scope, or an administrator route was called by someone who is not an administrator
402licence_requiredthe license does not include the REST API
{
  "error": {
    "code": "bad_request",
    "message": "the source or the destination could not be read"
  }
}

POST /api/v1/sync-jobs/{id}/run

Run it now rather than at its next scheduled time.

Who. An administrator, with a key that has the admin scope. An administrator's key that does not have that scope is refused. The key needs a license that includes the REST API. This call can also answer 402 when this installation's license does not cover automation.

Parameters.

NameInTypeMeaning
idpathstringrequiredThe resource's id.

Request body. None.

Success. 200.

JSON object.

Errors. The body always has the shape in Errors. Match on code.

StatuscodeWhen
400bad_request{e:#}
402licence_requiredthis installation's license does not cover automation
404not_foundnot there, or not visible to this caller
401unauthenticatedno key, or a key that is unknown, expired, revoked, or owned by a disabled account
403forbiddenthe key is valid but does not have the scope, or an administrator route was called by someone who is not an administrator
{
  "error": {
    "code": "bad_request",
    "message": "{e:#}"
  }
}

Event rules

GET /api/v1/rules

Your event rules, and the ready-made ones to start from.

Who. Any user with a key that has the read scope. A key with the admin scope includes the others. The key needs a license that includes the REST API.

An event rule waits for something to happen on the server, such as a file arriving or a transfer failing, and runs steps in response. Event rules need the automation feature; in Free mode one rule runs at no charge. An administrator sees every rule; everyone else sees their own. Besides the rules the reply says whether this license includes automation (included), how many more rules Free mode can run (freeJobsLeft), whether the caller may save a step that runs a command (mayUseCommands, administrators only), and whether webhooks to private addresses are allowed.

Success. 200.

FieldTypeMeaning
rulesarray of objectsrequired

Each item is an object:

FieldTypeMeaning
idstringrequiredThe id.
namestringrequiredThe name.
ownerIdstringoptionalThe id.
ownerEmailstringoptionalAn email address.
triggerstringrequired
triggerConfigobjectrequired

It is an object:

FieldTypeMeaning
stableSecsintegeroptional
cronstringoptional
everyMinutesintegeroptional
dailyAtstringoptionalHH:MM, in the server's time zone.
weekdaysarray of integeroptional0 is Sunday, as in cron.
conditionsarray of objectsrequired

Each item is an object:

FieldTypeMeaning
kindobjectrequired
fieldstringoptionalThe field a formFieldIs condition reads.
valuestringrequired
stepsarray of objectsrequired

Each item is an object:

FieldTypeMeaning
namestringrequiredThe name.
kindobjectrequired
configvalueoptional
retriesintegerrequired
onFailureobjectrequired
timeoutSecsintegerrequired
confirmedbooleanoptional
enabledbooleanrequired
pausedReasonstringoptional
hasCommandbooleanrequired
notifyOwnerOnFailurebooleanrequired
maxConcurrentintegerrequired
secretNamesarray of stringrequiredNames only. The values are never sent back.
lastRunAtstringoptionalA time, as RFC 3339.
nextRunAtstringoptionalA time, as RFC 3339.
createdAtstringrequiredA time, as RFC 3339.
templatesarray of objectsrequired

Each item is an object:

FieldTypeMeaning
idstringrequiredThe id.
titlestringrequired
whatstringrequired
needsstringoptionalWhat the server needs for it to work, for example "ffmpeg".
ruleobjectrequired

It is an object:

FieldTypeMeaning
namestringrequiredThe name.
triggerstringrequired
triggerConfigTriggerConfigoptional

It is an object:

FieldTypeMeaning
stableSecsintegeroptional
cronstringoptional
everyMinutesintegeroptional
dailyAtstringoptionalHH:MM, in the server's time zone.
weekdaysarray of integeroptional0 is Sunday, as in cron.
conditionsarray of RuleConditionoptional

Each item is an object:

FieldTypeMeaning
kindobjectrequired
fieldstringoptionalThe field a formFieldIs condition reads.
valuestringrequired
stepsarray of objectsrequired

Each item is an object:

FieldTypeMeaning
namestringrequiredThe name.
kindobjectrequired
configvalueoptional
retriesintegeroptional
onFailureOnFailureoptional
timeoutSecsintegeroptional
confirmedbooleanoptional
enabledbooleanoptional
notifyOwnerOnFailurebooleanoptional
maxConcurrentintegeroptional
secretsBTreeMap<String, String>optionalWritten once; never read back.
includedbooleanrequired
freeJobsLeftintegerrequired
mayUseCommandsbooleanrequired
allowPrivateWebhooksbooleanrequired
{
  "rules": [
    {
      "id": "k7Qm2sLp9vX4aB1c",
      "name": "Rush delivery",
      "trigger": "example",
      "triggerConfig": {
        "stableSecs": 1,
        "cron": "example",
        "everyMinutes": 1,
        "dailyAt": "2026-10-05T18:00:00Z",
        "weekdays": [
          1
        ]
      },
      "conditions": [
        {
          "kind": {},
          "field": "example",
          "value": "example"
        }
      ],
      "steps": [
        {
          "name": "Rush delivery",
          "kind": {},
          "config": {
            "file": {
              "name": "rush.mov"
            }
          },
          "retries": 1,
          "onFailure": {},
          "timeoutSecs": 1,
          "confirmed": true
        }
      ],
      "enabled": true,
      "hasCommand": true,
      "notifyOwnerOnFailure": true,
      "maxConcurrent": 1,
      "secretNames": [
        "a-secret-shown-once"
      ],
      "createdAt": "2026-10-05T18:00:00Z"
    }
  ],
  "templates": [
    {
      "id": "k7Qm2sLp9vX4aB1c",
      "title": "example",
      "what": "2026-10-05T18:00:00Z",
      "needs": "example",
      "rule": {
        "name": "Rush delivery",
        "trigger": "example",
        "steps": [
          {
            "name": "Rush delivery",
            "kind": {},
            "config": {
              "file": {
                "name": "rush.mov"
              }
            },
            "retries": 1,
            "onFailure": {},
            "timeoutSecs": 1,
            "confirmed": true
          }
        ]
      }
    }
  ],
  "included": true,
  "freeJobsLeft": 1,
  "mayUseCommands": true,
  "allowPrivateWebhooks": true
}

Errors. The body always has the shape in Errors. Match on code.

StatuscodeWhen
401unauthenticatedno key, or a key that is unknown, expired, revoked, or owned by a disabled account
403forbiddenthe key is valid but does not have the scope, or an administrator route was called by someone who is not an administrator
402licence_requiredthe license does not include the REST API
{
  "error": {
    "code": "unauthenticated",
    "message": "sign in to continue"
  }
}

POST /api/v1/rules

Make an event rule.

Who. Any user with a key that has the write scope. A key with the admin scope includes the others. The key needs a license that includes the REST API. This call can also answer 402 when this server's license has no room for another automation job.

The reply is the rule and its webhookSecret, the key a receiver checks webhook calls with; it can be shown again later with the signing key call. Values a step needs, such as a token, go in secrets once and are never returned; steps read them as {{secret.name}}. Only an administrator can save a rule with a step that runs a command. The rule starts at once unless enabled is false, and takes one of the jobs the license allows.

Request body. JSON.

FieldTypeMeaning
namestringrequiredThe name.
triggerstringrequired
triggerConfigTriggerConfigoptional, left out when empty

It is an object:

FieldTypeMeaning
stableSecsintegeroptional
cronstringoptional
everyMinutesintegeroptional
dailyAtstringoptionalHH:MM, in the server's time zone.
weekdaysarray of integeroptional0 is Sunday, as in cron.
conditionsarray of RuleConditionoptional, left out when empty

Each item is an object:

FieldTypeMeaning
kindobjectrequired
fieldstringoptionalThe field a formFieldIs condition reads.
valuestringrequired
stepsarray of objectsrequired

Each item is an object:

FieldTypeMeaning
namestringrequiredThe name.
kindobjectrequired
configvalueoptional
retriesintegeroptional
onFailureOnFailureoptional
timeoutSecsintegeroptional
confirmedbooleanoptional
enabledbooleanoptional, left out when empty
notifyOwnerOnFailurebooleanoptional, left out when empty
maxConcurrentintegeroptional, left out when empty
secretsBTreeMap<String, String>optional, left out when emptyWritten once; never read back.
{
  "name": "Rush delivery",
  "trigger": "example",
  "steps": [
    {
      "name": "Rush delivery",
      "kind": {},
      "config": {
        "file": {
          "name": "rush.mov"
        }
      },
      "retries": 1,
      "onFailure": {},
      "timeoutSecs": 1,
      "confirmed": true
    }
  ]
}

Success. 200.

FieldTypeMeaning
ruleobjectrequired

It is an object:

FieldTypeMeaning
idstringrequiredThe id.
namestringrequiredThe name.
ownerIdstringoptionalThe id.
ownerEmailstringoptionalAn email address.
triggerstringrequired
triggerConfigobjectrequired

It is an object:

FieldTypeMeaning
stableSecsintegeroptional
cronstringoptional
everyMinutesintegeroptional
dailyAtstringoptionalHH:MM, in the server's time zone.
weekdaysarray of integeroptional0 is Sunday, as in cron.
conditionsarray of objectsrequired

Each item is an object:

FieldTypeMeaning
kindobjectrequired
fieldstringoptionalThe field a formFieldIs condition reads.
valuestringrequired
stepsarray of objectsrequired

Each item is an object:

FieldTypeMeaning
namestringrequiredThe name.
kindobjectrequired
configvalueoptional
retriesintegerrequired
onFailureobjectrequired
timeoutSecsintegerrequired
confirmedbooleanoptional
enabledbooleanrequired
pausedReasonstringoptional
hasCommandbooleanrequired
notifyOwnerOnFailurebooleanrequired
maxConcurrentintegerrequired
secretNamesarray of stringrequiredNames only. The values are never sent back.
lastRunAtstringoptionalA time, as RFC 3339.
nextRunAtstringoptionalA time, as RFC 3339.
createdAtstringrequiredA time, as RFC 3339.
webhookSecretstringrequired
{
  "rule": {
    "id": "k7Qm2sLp9vX4aB1c",
    "name": "Rush delivery",
    "trigger": "example",
    "triggerConfig": {
      "stableSecs": 1,
      "cron": "example",
      "everyMinutes": 1,
      "dailyAt": "2026-10-05T18:00:00Z",
      "weekdays": [
        1
      ]
    },
    "conditions": [
      {
        "kind": {},
        "field": "example",
        "value": "example"
      }
    ],
    "steps": [
      {
        "name": "Rush delivery",
        "kind": {},
        "config": {
          "file": {
            "name": "rush.mov"
          }
        },
        "retries": 1,
        "onFailure": {},
        "timeoutSecs": 1,
        "confirmed": true
      }
    ],
    "enabled": true,
    "hasCommand": true,
    "notifyOwnerOnFailure": true,
    "maxConcurrent": 1,
    "secretNames": [
      "a-secret-shown-once"
    ],
    "createdAt": "2026-10-05T18:00:00Z"
  },
  "webhookSecret": "a-secret-shown-once"
}

Errors. The body always has the shape in Errors. Match on code.

StatuscodeWhen
400bad_requestno name or one over 100 characters, an unknown trigger, a schedule that cannot work, a condition or step that is not valid (no steps, more than 20, a name used twice, a required setting missing, or a delete step without `confirmed`), a secret name or value that is not allowed, or `maxConcurrent` outside 1 to 8
402licence_requiredthis server's license has no room for another automation job
403forbiddena step runs a command and the caller is not an administrator
409conflicta rule with that name already exists
401unauthenticatedno key, or a key that is unknown, expired, revoked, or owned by a disabled account
{
  "error": {
    "code": "bad_request",
    "message": "no name or one over 100 characters, an unknown trigger, a schedule that cannot work, a condition or step that is not valid (no steps, more than 20, a name used twice, a required setting missing, or a delete step without `confirmed`), a secret name or value that is not allowed, or `maxConcurrent` outside 1 to 8"
  }
}

GET /api/v1/rules/runs

Past runs of event rules, newest first.

Who. Any user with a key that has the read scope. A key with the admin scope includes the others. The key needs a license that includes the REST API.

Up to 200 runs, each step's output shortened; fetch one run for the rest. Secrets are replaced by ***. An administrator sees every run; everyone else sees the runs of their own rules.

Parameters.

NameInTypeMeaning
rulequerystringoptionalOnly this rule's runs.
statequerystringoptionalqueued, running, done, failed, skipped or interrupted.
fromquerystringoptionalRFC 3339, inclusive.
toquerystringoptionalRFC 3339, exclusive.

Success. 200.

FieldTypeMeaning
runsarray of objectsrequiredThe runs, newest first, up to 200.

Each item is an object:

FieldTypeMeaning
idstringrequiredThe id.
ruleIdstringrequiredThe id.
ruleNamestringrequired
eventIdstringoptionalThe id.
statestringrequiredWhere this record is in its life.
startedBystringrequired
conditionsPassedbooleanrequired
dryRunbooleanrequired
errorstringoptional
startedAtstringrequiredA time, as RFC 3339.
finishedAtstringoptionalA time, as RFC 3339.
stepsarray of objectsrequired

Each item is an object:

FieldTypeMeaning
namestringrequiredThe name.
kindobjectrequired
statestringrequiredWhere this record is in its life.
attemptsintegerrequired
exitCodeintegeroptional
httpStatusintegeroptional
outputstringrequired
planstringoptional
startedAtstringoptionalA time, as RFC 3339.
finishedAtstringoptionalA time, as RFC 3339.
{
  "runs": [
    {
      "id": "k7Qm2sLp9vX4aB1c",
      "ruleId": "k7Qm2sLp9vX4aB1c",
      "ruleName": "example",
      "state": "active",
      "startedBy": "example",
      "conditionsPassed": true,
      "dryRun": false,
      "startedAt": "2026-10-05T18:00:00Z",
      "steps": [
        {
          "name": "Rush delivery",
          "kind": {},
          "state": "active",
          "attempts": 1,
          "output": "example"
        }
      ]
    }
  ]
}

Errors. The body always has the shape in Errors. Match on code.

StatuscodeWhen
400bad_requesta date that is not written like 2031-03-04T10:00:00Z
401unauthenticatedno key, or a key that is unknown, expired, revoked, or owned by a disabled account
403forbiddenthe key is valid but does not have the scope, or an administrator route was called by someone who is not an administrator
402licence_requiredthe license does not include the REST API
{
  "error": {
    "code": "bad_request",
    "message": "a date that is not written like 2031-03-04T10:00:00Z"
  }
}

GET /api/v1/rules/runs/{id}

One run of an event rule, with the output of every step.

Who. Any user with a key that has the read scope. A key with the admin scope includes the others. The key needs a license that includes the REST API.

The last 64 KB of each step's output is kept, with every secret replaced by ***. For a dry run each step also has a plan: what it would have done.

Parameters.

NameInTypeMeaning
idpathstringrequiredThe resource's id.

Success. 200.

FieldTypeMeaning
idstringrequiredThe id.
ruleIdstringrequiredThe id.
ruleNamestringrequired
eventIdstringoptionalThe id.
statestringrequiredWhere this record is in its life.
startedBystringrequired
conditionsPassedbooleanrequired
dryRunbooleanrequired
errorstringoptional
startedAtstringrequiredA time, as RFC 3339.
finishedAtstringoptionalA time, as RFC 3339.
stepsarray of objectsrequired

Each item is an object:

FieldTypeMeaning
namestringrequiredThe name.
kindobjectrequired
statestringrequiredWhere this record is in its life.
attemptsintegerrequired
exitCodeintegeroptional
httpStatusintegeroptional
outputstringrequired
planstringoptional
startedAtstringoptionalA time, as RFC 3339.
finishedAtstringoptionalA time, as RFC 3339.
{
  "id": "k7Qm2sLp9vX4aB1c",
  "ruleId": "k7Qm2sLp9vX4aB1c",
  "ruleName": "example",
  "state": "active",
  "startedBy": "example",
  "conditionsPassed": true,
  "dryRun": false,
  "startedAt": "2026-10-05T18:00:00Z",
  "steps": [
    {
      "name": "Rush delivery",
      "kind": {},
      "state": "active",
      "attempts": 1,
      "output": "example"
    }
  ]
}

Errors. The body always has the shape in Errors. Match on code.

StatuscodeWhen
404not_foundno such run, or it belongs to someone else's rule
401unauthenticatedno key, or a key that is unknown, expired, revoked, or owned by a disabled account
403forbiddenthe key is valid but does not have the scope, or an administrator route was called by someone who is not an administrator
402licence_requiredthe license does not include the REST API
{
  "error": {
    "code": "not_found",
    "message": "not found"
  }
}

POST /api/v1/rules/runs/{id}/rerun

Run a past run again.

Who. Any user with a key that has the write scope. A key with the admin scope includes the others. The key needs a license that includes the REST API.

Queues a new run of the same rule with the event the old run kept, even if the event itself has since been cleared away. The conditions are not checked again. The old run stays as it was.

Parameters.

NameInTypeMeaning
idpathstringrequiredThe resource's id.

Request body. None.

Success. 200.

FieldTypeMeaning
idstringrequiredThe id.
ruleIdstringrequiredThe id.
ruleNamestringrequired
eventIdstringoptionalThe id.
statestringrequiredWhere this record is in its life.
startedBystringrequired
conditionsPassedbooleanrequired
dryRunbooleanrequired
errorstringoptional
startedAtstringrequiredA time, as RFC 3339.
finishedAtstringoptionalA time, as RFC 3339.
stepsarray of objectsrequired

Each item is an object:

FieldTypeMeaning
namestringrequiredThe name.
kindobjectrequired
statestringrequiredWhere this record is in its life.
attemptsintegerrequired
exitCodeintegeroptional
httpStatusintegeroptional
outputstringrequired
planstringoptional
startedAtstringoptionalA time, as RFC 3339.
finishedAtstringoptionalA time, as RFC 3339.
{
  "id": "k7Qm2sLp9vX4aB1c",
  "ruleId": "k7Qm2sLp9vX4aB1c",
  "ruleName": "example",
  "state": "active",
  "startedBy": "example",
  "conditionsPassed": true,
  "dryRun": false,
  "startedAt": "2026-10-05T18:00:00Z",
  "steps": [
    {
      "name": "Rush delivery",
      "kind": {},
      "state": "active",
      "attempts": 1,
      "output": "example"
    }
  ]
}

Errors. The body always has the shape in Errors. Match on code.

StatuscodeWhen
403forbiddenthe rule runs a command and the caller is not an administrator
404not_foundno such run, or it belongs to someone else's rule
409conflictthe rule is paused; the message says why
401unauthenticatedno key, or a key that is unknown, expired, revoked, or owned by a disabled account
402licence_requiredthe license does not include the REST API
{
  "error": {
    "code": "forbidden",
    "message": "you do not have access to this"
  }
}

PATCH /api/v1/rules/{id}

Change an event rule.

Who. Any user with a key that has the write scope. A key with the admin scope includes the others. The key needs a license that includes the REST API. This call can also answer 402 when switching it on, when this server's license has no room for another automation job.

Send only what changes. A secret sent with an empty value is removed, and one left out is kept. Switching a rule on takes one of the license's jobs; editing it or switching it off does not. Only an administrator can add a command step, or edit a rule that already has one other than switching it off.

Parameters.

NameInTypeMeaning
idpathstringrequiredThe resource's id.

Request body. JSON.

FieldTypeMeaning
namestringoptionalThe name.
triggerstringoptional
triggerConfigTriggerConfigoptional

It is an object:

FieldTypeMeaning
stableSecsintegeroptional
cronstringoptional
everyMinutesintegeroptional
dailyAtstringoptionalHH:MM, in the server's time zone.
weekdaysarray of integeroptional0 is Sunday, as in cron.
conditionsarray of RuleConditionoptional

Each item is an object:

FieldTypeMeaning
kindobjectrequired
fieldstringoptionalThe field a formFieldIs condition reads.
valuestringrequired
stepsarray of StepInputoptional

Each item is an object:

FieldTypeMeaning
namestringrequiredThe name.
kindobjectrequired
configvalueoptional
retriesintegeroptional
onFailureOnFailureoptional
timeoutSecsintegeroptional
confirmedbooleanoptional
enabledbooleanoptional
notifyOwnerOnFailurebooleanoptional
maxConcurrentintegeroptional
secretsBTreeMap<String, String>optional
{
  "name": "Rush delivery",
  "trigger": "example",
  "triggerConfig": {
    "stableSecs": 1,
    "cron": "example",
    "everyMinutes": 1,
    "dailyAt": "2026-10-05T18:00:00Z",
    "weekdays": [
      1
    ]
  },
  "conditions": [
    {
      "kind": {},
      "field": "example",
      "value": "example"
    }
  ],
  "steps": [
    {
      "name": "Rush delivery",
      "kind": {},
      "config": {
        "file": {
          "name": "rush.mov"
        }
      },
      "retries": 1,
      "onFailure": {},
      "timeoutSecs": 1,
      "confirmed": true
    }
  ],
  "enabled": true,
  "notifyOwnerOnFailure": true,
  "maxConcurrent": 1
}

Success. 200.

FieldTypeMeaning
idstringrequiredThe id.
namestringrequiredThe name.
ownerIdstringoptionalThe id.
ownerEmailstringoptionalAn email address.
triggerstringrequired
triggerConfigobjectrequired

It is an object:

FieldTypeMeaning
stableSecsintegeroptional
cronstringoptional
everyMinutesintegeroptional
dailyAtstringoptionalHH:MM, in the server's time zone.
weekdaysarray of integeroptional0 is Sunday, as in cron.
conditionsarray of objectsrequired

Each item is an object:

FieldTypeMeaning
kindobjectrequired
fieldstringoptionalThe field a formFieldIs condition reads.
valuestringrequired
stepsarray of objectsrequired

Each item is an object:

FieldTypeMeaning
namestringrequiredThe name.
kindobjectrequired
configvalueoptional
retriesintegerrequired
onFailureobjectrequired
timeoutSecsintegerrequired
confirmedbooleanoptional
enabledbooleanrequired
pausedReasonstringoptional
hasCommandbooleanrequired
notifyOwnerOnFailurebooleanrequired
maxConcurrentintegerrequired
secretNamesarray of stringrequiredNames only. The values are never sent back.
lastRunAtstringoptionalA time, as RFC 3339.
nextRunAtstringoptionalA time, as RFC 3339.
createdAtstringrequiredA time, as RFC 3339.
{
  "id": "k7Qm2sLp9vX4aB1c",
  "name": "Rush delivery",
  "trigger": "example",
  "triggerConfig": {
    "stableSecs": 1,
    "cron": "example",
    "everyMinutes": 1,
    "dailyAt": "2026-10-05T18:00:00Z",
    "weekdays": [
      1
    ]
  },
  "conditions": [
    {
      "kind": {},
      "field": "example",
      "value": "example"
    }
  ],
  "steps": [
    {
      "name": "Rush delivery",
      "kind": {},
      "config": {
        "file": {
          "name": "rush.mov"
        }
      },
      "retries": 1,
      "onFailure": {},
      "timeoutSecs": 1,
      "confirmed": true
    }
  ],
  "enabled": true,
  "hasCommand": true,
  "notifyOwnerOnFailure": true,
  "maxConcurrent": 1,
  "secretNames": [
    "a-secret-shown-once"
  ],
  "createdAt": "2026-10-05T18:00:00Z"
}

Errors. The body always has the shape in Errors. Match on code.

StatuscodeWhen
400bad_requestany of the refusals for making a rule
402licence_requiredswitching it on, when this server's license has no room for another automation job
403forbiddenthe change adds or edits a command step and the caller is not an administrator
404not_foundno such rule, or it is someone else's
409conflicta rule with that name already exists
401unauthenticatedno key, or a key that is unknown, expired, revoked, or owned by a disabled account
{
  "error": {
    "code": "bad_request",
    "message": "any of the refusals for making a rule"
  }
}

DELETE /api/v1/rules/{id}

Delete an event rule.

Who. Any user with a key that has the write scope. A key with the admin scope includes the others. The key needs a license that includes the REST API.

The rule stops at once and gives its job back. Needs the write scope rather than delete, like every other change to a rule.

Parameters.

NameInTypeMeaning
idpathstringrequiredThe resource's id.

Success. 200.

The reply has no body.

Errors. The body always has the shape in Errors. Match on code.

StatuscodeWhen
404not_foundno such rule, or it is someone else's
401unauthenticatedno key, or a key that is unknown, expired, revoked, or owned by a disabled account
403forbiddenthe key is valid but does not have the scope, or an administrator route was called by someone who is not an administrator
402licence_requiredthe license does not include the REST API
{
  "error": {
    "code": "not_found",
    "message": "not found"
  }
}

GET /api/v1/rules/{id}/signing-key

Show the key a rule's webhook receivers check.

Who. Any user with a key that has the write scope. A key with the admin scope includes the others. The key needs a license that includes the REST API.

Only to the rule's owner or an administrator, and each time it is read is written to the audit log. It is a call of its own so that the rule itself, which is listed and cached, never carries it.

Parameters.

NameInTypeMeaning
idpathstringrequiredThe resource's id.

Success. 200.

FieldTypeMeaning
signingKeystringrequired
{
  "signingKey": "example"
}

Errors. The body always has the shape in Errors. Match on code.

StatuscodeWhen
404not_foundno such rule, or it is someone else's
401unauthenticatedno key, or a key that is unknown, expired, revoked, or owned by a disabled account
403forbiddenthe key is valid but does not have the scope, or an administrator route was called by someone who is not an administrator
402licence_requiredthe license does not include the REST API
{
  "error": {
    "code": "not_found",
    "message": "not found"
  }
}

POST /api/v1/rules/{id}/run

Run an event rule now, for real or as a dry run.

Who. Any user with a key that has the write scope. A key with the admin scope includes the others. The key needs a license that includes the REST API.

With eventId the rule runs against that past event from the events list; without one, against a made-up event of the rule's kind. A dry run shows what each step would do and does none of it, and the reply comes when it has finished. A real run is queued, so the reply may still say queued or running; read the run again to follow it. If the event does not meet the rule's conditions the run is recorded as skipped. A paused rule can be dry-run but not run, and only an administrator can run a rule that has a command step for real.

Parameters.

NameInTypeMeaning
idpathstringrequiredThe resource's id.

Request body. JSON.

The body may be left out.

FieldTypeMeaning
eventIdstringoptionalThe id.
dryRunbooleanoptional
{
  "eventId": "k7Qm2sLp9vX4aB1c",
  "dryRun": false
}

Success. 200.

FieldTypeMeaning
idstringrequiredThe id.
ruleIdstringrequiredThe id.
ruleNamestringrequired
eventIdstringoptionalThe id.
statestringrequiredWhere this record is in its life.
startedBystringrequired
conditionsPassedbooleanrequired
dryRunbooleanrequired
errorstringoptional
startedAtstringrequiredA time, as RFC 3339.
finishedAtstringoptionalA time, as RFC 3339.
stepsarray of objectsrequired

Each item is an object:

FieldTypeMeaning
namestringrequiredThe name.
kindobjectrequired
statestringrequiredWhere this record is in its life.
attemptsintegerrequired
exitCodeintegeroptional
httpStatusintegeroptional
outputstringrequired
planstringoptional
startedAtstringoptionalA time, as RFC 3339.
finishedAtstringoptionalA time, as RFC 3339.
{
  "id": "k7Qm2sLp9vX4aB1c",
  "ruleId": "k7Qm2sLp9vX4aB1c",
  "ruleName": "example",
  "state": "active",
  "startedBy": "example",
  "conditionsPassed": true,
  "dryRun": false,
  "startedAt": "2026-10-05T18:00:00Z",
  "steps": [
    {
      "name": "Rush delivery",
      "kind": {},
      "state": "active",
      "attempts": 1,
      "output": "example"
    }
  ]
}

Errors. The body always has the shape in Errors. Match on code.

StatuscodeWhen
400bad_requestthe event is no longer kept
403forbiddenthe rule runs a command and the caller is not an administrator
404not_foundno such rule, or it is someone else's
409conflictthe rule is paused; the message says why
401unauthenticatedno key, or a key that is unknown, expired, revoked, or owned by a disabled account
402licence_requiredthe license does not include the REST API
{
  "error": {
    "code": "bad_request",
    "message": "the event is no longer kept"
  }
}

Events

GET /api/v1/events

Past events, to test a rule against.

Who. Any user with a key that has the read scope. A key with the admin scope includes the others. The key needs a license that includes the REST API.

Newest first, of the kind asked for or of every kind, up to 200. Events name files and the addresses of the people who sent them, across every folder, so only an administrator is shown any; everyone else gets an empty list instead of an error, which keeps the test screen working with a made-up event.

Parameters.

NameInTypeMeaning
kindquerystringoptionalOnly events of this trigger kind, such as file.arrived.
limitqueryintegeroptional1 to 200. Default 50. Clamped, not refused.

Success. 200.

FieldTypeMeaning
eventsarray of objectsrequiredNewest first. Empty for anyone who is not an administrator.

Each item is an object:

FieldTypeMeaning
idstringrequiredThe event's id.
kindstringrequiredThe trigger kind, such as file.arrived.
atstringrequiredWhen it happened, as RFC 3339.
pathstringrequiredThe file path the event is about. Empty when it is not about a path.
actorEmailstringrequiredThe address of the account that caused it, when there is one.
bodyvaluerequiredThe rest of the event: file, link, form, package, transfer, job, or scan.
{
  "events": [
    {
      "id": "k7Qm2sLp9vX4aB1c",
      "kind": "file.arrived",
      "at": "2026-10-05T18:00:00Z",
      "path": "projects/rush",
      "actorEmail": "[email protected]",
      "body": {
        "file": {
          "name": "rush.mov"
        }
      }
    }
  ]
}

Errors. The body always has the shape in Errors. Match on code.

StatuscodeWhen
401unauthenticatedno key, or a key that is unknown, expired, revoked, or owned by a disabled account
403forbiddenthe key is valid but does not have the scope, or an administrator route was called by someone who is not an administrator
402licence_requiredthe license does not include the REST API
{
  "error": {
    "code": "unauthenticated",
    "message": "sign in to continue"
  }
}