Skip to content

REST API

All endpoints require authentication via API key (Authorization: Bearer ask_...) or session cookie.

API keys are scoped: read (queries), write (create/update/delete), deploy (deploy/trigger/takedown/run control). All keys require at least read scope.

Base URL: https://your-instance/api

Authentication

bash
# API key
curl https://your-instance/api/workflows \
  -H "Authorization: Bearer ask_your_api_key"

Rate Limits

ScopeLimit
Global200 req/min per IP
Write operations30 req/min per user
Deploy operations10 req/min per user
Credential verification10 req/min per user

Pagination

All list endpoints support cursor-based pagination via cursor and limit query parameters.

json
{
  "data": [...],
  "nextCursor": "abc123_2026-03-29T10:00:00.000Z"
}

When nextCursor is null, there are no more pages.


Workflows

GET /workflows read

List all workflows in the active project.

ParamInRequiredDescription
cursorquerynoPagination cursor
limitquerynoItems per page (1–100, default 50)

GET /workflows/:id read

Get a single workflow by ID.


GET /workflows/:id/full read

Get a workflow with its current version, all version summaries, and active deployment.

ParamInRequiredDescription
versionquerynoSpecific version ID to load

POST /workflows write

Create a new workflow or function.

Request body:

json
{
  "name": "My Workflow",
  "description": "",
  "kind": "workflow"
}
FieldRequiredDescription
nameyesDisplay name
descriptionnoOptional description
kindno"workflow" (default) or "script". Functions (kind: "script") are fetch-only Workers — no durable runtime, no Runs. Set at create time only; cannot be changed via PATCH. See Functions for constraints and invocation.

PATCH /workflows/:id write

Update a workflow's name, description, environment variables, trigger code, dependencies, or deploy config.

Request body:

json
{
  "name": "Updated Name",
  "description": "optional",
  "envVars": [{ "name": "KEY", "value": "val", "isSecret": false }],
  "triggerCode": "optional trigger code string",
  "dependencies": { "lodash": "^4.0.0" },
  "deployConfig": {
    "route": {
      "pattern": "api.example.com/my-workflow/*",
      "zoneName": "example.com"
    }
  }
}

PATCH /workflows/:id/move write

Move a workflow to another project within the same organization.

Request body:

json
{ "targetProjectId": "project-id" }

DELETE /workflows/:id write

Delete a workflow and all its versions, deployments, and runs.


Functions

Functions are workflows with kind: "script". They share the same routes (POST /workflows to create, PATCH to update, DELETE to remove, POST /versions to compile a new version, POST /deploy to deploy) but compile to a fetch-only Cloudflare Worker instead of a WorkflowEntrypoint class.

Constraints

  • HTTP-only trigger. Script IR requires trigger: { type: "http" }. Cron, event, and manual triggers are rejected at validation.
  • No durable-runtime nodes. sleep, sleep_until, and wait_for_event are rejected — they require a durable instance the script doesn't have.
  • No WORKFLOW self-binding. The generated Worker has no Workflow binding to itself. Sub-workflow bindings (calls into other deployed workflows) and resource bindings (KV/D1/R2/etc.) are still detected.
  • No instance lifecycle. No Runs, no pause/resume/terminate. POST /workflows/:id/trigger returns 400. Invoke the deployed Worker URL directly via HTTP POST.
  • kind is immutable. Set at create time only; not accepted on PATCH.

Invocation

bash
curl -X POST https://<your-worker-url> \
  -H "Content-Type: application/json" \
  -d '{ "anything": "here" }'

The body is parsed and exposed to nodes as event.payload. The default response is Response.json(graph) where graph contains only nodes whose display name was prefixed with EXPORT_. Override the fetch handler body via the workflow's triggerCode field (PATCH /workflows/:id); the auto-generated runGraph(env, event) function and graph.* outputs stay stable across edits.

See Compilation → Full Generated Worker Shape for the emitted code, and Workflow IR → Scripts vs Workflows for the type-level split.


Projects

GET /projects read

List all projects in the active organization.


POST /projects write

Create a new project.

Request body:

json
{
  "name": "My Project",
  "slug": "my-project",
  "description": ""
}

PATCH /projects/:id write

Update a project's name or description.

Request body:

json
{ "name": "Updated Name", "description": "optional" }

DELETE /projects/:id write

Delete a project.


Versions

GET /workflows/:workflowId/versions read

List all versions for a workflow.


GET /workflows/:workflowId/versions/:versionId read

Get a specific version including its IR and generated code.


POST /workflows/:workflowId/versions write

Create a new version by submitting a workflow IR. The IR is validated and compiled to code.

Request body:

json
{ "ir": { ... } }

PATCH /workflows/:workflowId/versions/:versionId write

Lock or unlock a version. Locked versions cannot be deployed.

Request body:

json
{ "locked": true }

POST /workflows/:workflowId/versions/:versionId/revert write

Revert to a previous version. Creates a new version with the target version's IR.


DELETE /workflows/:workflowId/versions/:versionId write

Delete a version. Cannot delete the active, deployed, or locked version.


Deployments

GET /deployments read

List all deployments across all workflows.


GET /workflows/:workflowId/deployments read

List deployments for a specific workflow.


POST /workflows/:workflowId/deploy deploy

Deploy a workflow version to a connection. Validates environment variables and credentials before deploying.

Request body:

json
{
  "connectionId": "connection-id",
  "versionId": "optional-version-id"
}

POST /workflows/:workflowId/deploy-stream deploy

Deploy with real-time progress updates via Server-Sent Events. Same request body as /deploy.

Progress stages:

INITIALIZING → GENERATING_CODE → CODE_READY → DETECTING_BINDINGS →
BINDINGS_READY → CREATING_WORKER → DEPLOYING → WORKER_DEPLOYED →
UPDATING_WORKFLOW → COMPLETED

POST /workflows/:workflowId/trigger deploy

Trigger an execution of a deployed workflow. Params payload is capped at 100 KB.

Functions only

This endpoint is for kind: "workflow" only. Calling it on a function (kind: "script") returns 400 — functions have no instance lifecycle. Invoke the deployed Worker URL directly via HTTP POST instead. See Functions → Invocation.

Request body:

json
{
  "connectionId": "connection-id",
  "params": { "key": "value" }
}

Response:

json
{
  "id": "run-id",
  "instanceId": "cf-instance-id",
  "status": "queued"
}

POST /workflows/:workflowId/takedown deploy

Remove a deployment and clear the workflow's active version.

Request body:

json
{ "connectionId": "connection-id" }

Runs

GET /runs read

List all runs across all workflows.


GET /workflows/:workflowId/runs read

List runs for a specific workflow.


GET /workflows/:workflowId/runs/:runId read

Get a specific run. If the run is in a non-terminal state, live status is fetched from Cloudflare.


POST /workflows/:workflowId/runs/:runId/pause deploy

Pause a running workflow instance.


POST /workflows/:workflowId/runs/:runId/resume deploy

Resume a paused workflow instance.


POST /workflows/:workflowId/runs/:runId/terminate deploy

Terminate a running or paused workflow instance.


Connections

GET /connections read

List all connections. Credential values are redacted in the response.


POST /connections write

Create a new provider connection.

Request body:

json
{
  "provider": "cloudflare",
  "credentials": { "apiToken": "...", "accountId": "..." },
  "name": "My Connection"
}

POST /connections/verify-token write

Verify provider credentials before saving.

Request body:

json
{ "provider": "cloudflare", "credentials": { "apiToken": "..." } }

Response:

json
{
  "valid": true,
  "accounts": [{ "id": "abc123", "name": "My Account" }]
}

PATCH /connections/:id write

Update a connection's name or credentials.


DELETE /connections/:id write

Delete a connection.


Environment Variables

GET /env-vars read

List all global environment variables. Secret values are masked.


POST /env-vars write

Create a global environment variable. Name must match ^[A-Z][A-Z0-9_]*$.

Request body:

json
{ "name": "MY_VAR", "value": "my-value", "isSecret": false }

PATCH /env-vars/:id write

Update an environment variable's name, value, or secret flag.


DELETE /env-vars/:id write

Delete an environment variable.


Resources

All resource endpoints require a connectionId query parameter pointing to a valid Cloudflare connection.

GET /resources/kv/namespaces read

List KV namespaces.


GET /resources/kv/namespaces/:namespaceId/keys read

List keys in a KV namespace. Supports prefix, cursor, and limit query params.


GET /resources/kv/namespaces/:namespaceId/values/:key read

Get the value of a KV key.


GET /resources/d1/databases read

List D1 databases.


POST /resources/d1/databases/:databaseId/query read

Execute a SQL query against a D1 database.

Request body:

json
{ "connectionId": "connection-id", "sql": "SELECT 1", "params": [] }

GET /resources/r2/buckets read

List R2 buckets.


GET /resources/r2/buckets/:bucketName/objects read

List objects in an R2 bucket. Supports prefix, cursor, and limit query params.


Nodes

GET /nodes read

List all available node definitions from the registry.


GET /nodes/templates read

Get node template resolver data.


GET /nodes/:nodeId read

Get a single node definition.


Marketplace

GET /marketplace read

Get the full marketplace catalog with installation status for the current organization.


GET /marketplace/:nodeId read

Get details for a specific marketplace node, including available versions and installation status.


GET /marketplace/installed read

List installed marketplace nodes for the current organization.


POST /marketplace/install write

Install a node from the marketplace.

Request body:

json
{ "nodeId": "stripe", "version": "1.0.0" }

version is optional — defaults to the latest available version.


POST /marketplace/uninstall write

Uninstall a previously installed node.

Request body:

json
{ "nodeId": "stripe" }

POST /marketplace/update write

Update an installed node to a newer version.

Request body:

json
{ "nodeId": "stripe", "version": "1.1.0" }

API Keys session only

These endpoints require session authentication and are not accessible via API key.

GET /api-keys

List all API keys for the current organization.


POST /api-keys

Create a new API key scoped to a project. The full key is returned only once.

Request body:

json
{
  "name": "My Key",
  "projectId": "project-id",
  "scopes": ["read", "write"],
  "expiresAt": "2025-12-31T00:00:00Z"
}

expiresAt is optional.


DELETE /api-keys/:id

Revoke an API key.