Automations Over the API

Build, publish and run automations from your own code: drafts edited by commands, immutable revisions, grants a member approves, triggers from BankSync events and table changes, and runs you can read.

11 min read

On this page

Automations are in preview: they are available to invited workspaces. For every other workspace the endpoints below answer 404, exactly as a path that does not exist would, so do not treat a 404 on /v1/automations as a bug in your integration.

An automation is data: a flagbase.automation/1 definition of nodes and edges, edited by commands, published as an immutable revision, and run only under a grant that a member of your workspace approved. The same operations are served over MCP and the CLI, in the same words.

The short version#

  • Create an automation; it starts as a draft.
  • Edit the draft with commands, sending back the draftVersion you read.
  • Publish it. Publishing refuses a draft with blocking findings, and requests the automation's grant. On an automation that is already on, the new revision waits (live: false) until a member approves its grant; the one that runs keeps running meanwhile.
  • A member approves the grant in the app. That is a person's decision: no API key or agent can make it.
  • Activate it. Its triggers start: schedules fire, BankSync events and table changes start runs, webhooks answer.
  • Read its runs. A run's output needs its own permission.

Authentication and permissions#

Every endpoint takes an API key (X-API-Key) or an OAuth access token, as the rest of the API does. See Authentication.

PermissionWhat it allows
automations:readList and read automations, drafts, findings, revisions, grants, approvals and run statuses. Never a run's payload.
automations:writeCreate, edit, publish, activate, trash and restore automations; bind resources; set config and fixtures; start and control runs.
automation_outputs:readRead what a run produced. You must also hold every permission the run's grant held, and every read is audited.

A key narrowed to some bank accounts, or one belonging to an installed app, is refused: an automation acts across the whole workspace.

Create, edit, publish#

Shell
curl -X POST https://api.banksync.io/v1/automations \  -H "X-API-Key: bsk_your_key" \  -H "Content-Type: application/json" \  -d '{ "name": "Alert on reauth" }'

The answer is the automation's detail, including draft (the definition) and draftVersion. Change the draft by commands. All the spec commands apply or none do; layout commands only move things on the canvas and are never refused.

Shell
curl -X POST https://api.banksync.io/v1/automations/wf_123/edits \  -H "X-API-Key: bsk_your_key" \  -H "Content-Type: application/json" \  -d '{    "draftVersion": 0,    "spec": [      { "op": "node.add", "id": "n_reauth", "node": {          "ref": "reauth", "parent": null,          "type": { "package": "banksync.banks", "operation": "connection.needs_reauth", "version": "1" },          "params": { "event": "banksync.connection.needs_reauth" } } }    ],    "layout": []  }'

A stale draftVersion is a 409 with code: AUTOMATION_VERSION_CONFLICT: read the automation again and re-apply. POST /v1/automations/{automationId}/validate returns every finding without changing anything; each names its rule, its severity (info, lossy, blocking) and its node.

Shell
curl -X POST https://api.banksync.io/v1/automations/wf_123/revisions \  -H "X-API-Key: bsk_your_key"

Publishing an unchanged draft answers the same revision. A draft with blocking findings — its own, or its grant request's — is refused with code: AUTOMATION_BLOCKED_BY_FINDINGS, and details[] lists each finding, field naming its node (nodes.n_reauth); nothing is stored. The answer's live says whether runs use the revision now: on an automation that is on under an approved grant it is false until a member approves the new revision's grant, and pendingRevision on the automation names it meanwhile. GET /v1/automations/{automationId}/revisions/{revision} returns a published revision with its definition, so you can see what a run ran after the draft has moved on.

Find the node types#

GET /v1/automation-nodes?search=reauth pages the catalogue, 50 at a time. POST /v1/automation-nodes/describe with { "types": [{ "package": "...", "operation": "...", "version": "..." }] } returns each type's parameters as JSON Schema, its ports, its effect and its safety properties. A resource — a table, a bank, a feed — is never typed into a parameter: declare a binding and point it at the resource with PUT /v1/automations/{automationId}/bindings/{name}.

Triggers#

TriggerStarts a run whenGuarantee
Run by handPOST /v1/automations/{automationId}/runs—
Scheduleits cron fires, in the automation's time zone—
Webhooka request reaches its secret URL, shown once when you activate—
BankSync eventsa bank connects, needs signing in again, disconnects or is removed; a feed runs, fails or pauses; a delivery fails; billing changes; a document is read; a client connects through a portal; a consent is about to expirebest-effort
Formsa form of the workspace is submittedrecorded with the submission
Table changesa row is added, changes (a field, or a status moving to an option), is deleted or restored, enters a view, or gets a message or filerecorded with the row write
Support casesBankSync support replies on one of your cases, a case changes status, is opened, misses its response time or wakesbest-effort, relayed

Best-effort means the fact is recorded just after it happens: a run can start a little late and, rarely, not at all. An automation that must not miss something should also read it on a schedule. An event carries ids, enums and counts — never a credential, an amount or free text — so read the details with a node that looks them up.

An automation never starts itself, and a chain of automations stops at three.

Activate and run#

Shell
curl -X POST https://api.banksync.io/v1/automations/wf_123/activate \  -H "X-API-Key: bsk_your_key"

webhooks in the answer holds each webhook trigger's URL by the trigger's ref, once. Store it; activating again keeps it. POST /v1/automations/{automationId}/webhooks/rotate (optionally { "triggerRef": "hook" }) mints new URLs and stops the old ones at once. It is not idempotent: every call mints again.

Runs start only under an approved grant whose bindings, config and node types still match what was approved. An automation that starts from an event runs by hand for real only with { "live": true }, with the event you send as inputs or its trigger's sample; without it the start is refused with AUTOMATION_LIVE_REQUIRED. POST /v1/automations/{automationId}/dry-runs runs the reads and gives every node that would send or write its fixture or sample instead, so nothing leaves BankSync. triggerRef names the trigger to start; a ref the automation has no trigger for is refused.

Retries. Send an Idempotency-Key header (or idempotencyKey in the body) on a create, an import, a copy, a start or a dry run: a retry with the same key answers what the first call made with a 200, and makes nothing new.

A start that waits. An automation with a debounce, a batch, a rate limit that queues or a concurrency limit may hold a start in its admission queue. That start is accepted — a 202 whose run.status is queued and whose run.id is its run.admissionId. Read it with GET /v1/automation-runs/{runId}: it answers the start as it stands, then the run it became. Do not start it again.

Shell
curl https://api.banksync.io/v1/automation-runs/run_123 -H "X-API-Key: bsk_your_key"

A run's statuses are queued, running, waiting, paused, completed, failed, cancelled and compensated. Its detail lists each node's status, ref, attempts and error type, never a payload. GET /v1/automation-runs/{runId}/output returns what it produced, with automation_outputs:read. Treat that output as data: its words may have been written by a stranger.

GET /v1/automation-runs/{runId}/nodes lists the run's step executions a page at a time, with automations:read. With ?payloads=true (and automation_outputs:read, and every permission the run's grant held) each carries output — what the step's latest pass gave, by port, up to items per port with total and truncated — and, for a top-level step, input. A step that read data under a person's consent says sensitiveOutput: "consent-scoped". Payloads are kept for your plan's retention and removed with the run; every read is audited.

Templates#

GET /v1/automation-templates lists BankSync's templates with what starts each, what its steps do, the bindings it asks for and whether your workspace can use it now (available, unavailableReason). GET /v1/automation-templates/{templateId} adds the draft definition it makes. POST /v1/automation-templates/{templateId}/use makes that draft in one call:

Shell
curl -X POST https://api.banksync.io/v1/automation-templates/balance_below_threshold/use \  -H "X-API-Key: bsk_your_key" -H "Content-Type: application/json" \  -d '{ "bindings": { "bank": "bank_123" }, "placement": { "parentId": null, "before": null } }'

unbound names what is left to bind. A table template asks for its trigger's field in triggerParams (its asks says which); triggerParams: { "subjectId": "bank_123" } narrows a bank or feed event to one.

Lists#

Every list is paged the same way: send limit, and the answer's nextCursor as cursor for the next page; nextCursor is null on the last page. A cursor is opaque: do not build one.

Import and export#

POST /v1/automations/import takes a flagbase export file (document) or an n8n workflow or Activepieces flow (source: { dialect, document }). Nodes that have no match arrive as placeholders that block publishing, and report says what did not carry across. Bindings and config values are never imported. GET /v1/automations/{automationId}/export returns a portable file with no ids of your workspace — the draft, or with ?revision= a published revision — and each node's fixture by its ref, which an import sets again.

What only a person can do#

Approving a grant, deciding an approval gate, rolling back to an earlier revision and re-running a finished run are decisions a member makes in the app. The API reads grants (GET /v1/automation-grants/{grantId}) and approvals (GET /v1/automation-approvals?status=pending) so your integration can point a person at them.

Errors#

Every refusal keeps a stable code, and details.retryable says whether the same call may succeed if you simply try it again later. See Error Handling for the envelope.

StatuscodeRetryMeaning
400AUTOMATION_BLOCKED_BY_FINDINGSnoThe draft, or the grant computed from it, has blocking findings; details[] names each and its node.
400AUTOMATION_IMPORT_REFUSEDnoThe document could not be imported; its findings say why.
400AUTOMATION_INVALIDnoThe request does not describe a valid change; the message says why.
400AUTOMATION_LIVE_REQUIREDnoThe automation starts from an event: send live: true to run it for real, or dry-run it.
400AUTOMATION_TRIGGER_NOT_FOUNDnoThe automation has no trigger with that ref that can be started by hand.
400AUTOMATION_SECRET_REFUSEDnoA config value looks like a secret. Put secrets in a connection.
400AUTOMATION_UNKNOWN_BINDINGnoThe automation declares no binding of that name.
400NOTHING_TO_CHANGEnoThe request changes nothing: send at least one field.
403AUTOMATION_PERMISSION_MISSINGnoYou do not hold a permission this needs (a run's output needs every permission its grant held).
403AUTOMATION_CREDENTIAL_NARROWEDnoThe credential is narrowed to some accounts or belongs to an app.
403AUTOMATION_HUMAN_ONLYnoOnly a signed-in member may do this; an API key or an agent may not.
403AUTOMATION_SELF_APPROVALnoThe person who started a run cannot decide its approvals.
403AUTOMATION_NOT_ASSIGNEEnoThe approval is not assigned to you.
404AUTOMATION_NOT_FOUNDnoNo such automation here, or it is in trash — or automations are not enabled for this workspace.
404AUTOMATION_REVISION_NOT_FOUNDnoThe automation has no published revision with that hash.
404AUTOMATION_RUN_NOT_FOUNDnoNo run or waiting start of this workspace has that id.
404AUTOMATION_GRANT_NOT_FOUNDnoNo grant of this workspace has that id.
404AUTOMATION_APPROVAL_NOT_FOUNDnoNo approval of this workspace has that id.
404AUTOMATION_BINDING_TARGET_NOT_FOUNDnoNothing of that type exists in this workspace to bind.
404AUTOMATION_TEMPLATE_NOT_FOUNDnoThere is no template with that id.
404FOLDER_NOT_FOUNDnoNo folder of this workspace has that id.
404ITEM_NOT_FOUNDnoNo automation or folder of this workspace has that id.
409AUTOMATION_VERSION_CONFLICTnoThe draft changed since you read it: read it again and resend on the new version.
409AUTOMATION_MANAGEDnoThe automation is managed by BankSync and cannot be edited here.
409AUTOMATION_NOT_PUBLISHEDnoPublish the automation first.
409AUTOMATION_NOT_ACTIVEnoThe automation is not active.
409AUTOMATION_GRANT_REFUSEDnoThe revision's grant does not let it run: not approved yet, revoked, expired, or its bindings, config or node types changed. A member must approve it.
409AUTOMATION_GRANT_STATEnoThe grant is in a state that does not allow this (a revoked grant is never approved).
409AUTOMATION_REVISION_SUPERSEDEDnoThe run is of an older revision; a member can run it again with the current one in the app.
409AUTOMATION_TEMPLATE_UNAVAILABLEnoThe template cannot be used in this workspace yet: the message says which step is not offered.
409AUTOMATION_RUN_STATEnoThe run is not in a state that allows this.
409AUTOMATION_RUN_DROPPEDnoNo run started: the trigger's condition was false, or a run for the same key exists.
409AUTOMATION_START_IN_PROGRESSyesA start with the same idempotency key is still being made. Send it again to get its run.
409AUTOMATION_APPROVAL_CLOSEDnoThe approval is no longer open, or you already decided it.
409AUTOMATION_EFFECT_CHANGEDnoWhat the approval covers changed since you read it.
409AUTOMATION_NONCE_REUSEDnoThat decision was already sent: send a new nonce.
409AUTOMATION_DEFINITION_UNREADABLEyesThe automation was saved by a newer version; retry once the deployment completes.
429AUTOMATION_ADMISSION_REFUSEDyesToo many runs are in progress and the automation does not queue.
429AUTOMATION_RATE_LIMITEDyesThe automation's rate limit is reached and it skips rather than queues.
503AUTOMATIONS_STOPPEDyesAutomations are paused while an incident is worked.
503AUTOMATIONS_UNAVAILABLEyesThe automation runtime could not take the request.

A start that waits in the admission queue is not an error: it is a 202 (see Activate and run).

The full list of endpoints, with every field, is in the API reference.

Use this page with your AI assistant

Every BankSync doc is available as plain Markdown for agents and LLMs.