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
# API key
curl https://your-instance/api/workflows \
-H "Authorization: Bearer ask_your_api_key"Rate Limits
| Scope | Limit |
|---|---|
| Global | 200 req/min per IP |
| Write operations | 30 req/min per user |
| Deploy operations | 10 req/min per user |
| Credential verification | 10 req/min per user |
Pagination
All list endpoints support cursor-based pagination via cursor and limit query parameters.
{
"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.
| Param | In | Required | Description |
|---|---|---|---|
cursor | query | no | Pagination cursor |
limit | query | no | Items 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.
| Param | In | Required | Description |
|---|---|---|---|
version | query | no | Specific version ID to load |
POST /workflows write
Create a new workflow or function.
Request body:
{
"name": "My Workflow",
"description": "",
"kind": "workflow"
}| Field | Required | Description |
|---|---|---|
name | yes | Display name |
description | no | Optional description |
kind | no | "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:
{
"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:
{ "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, andwait_for_eventare rejected — they require a durable instance the script doesn't have. - No
WORKFLOWself-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/triggerreturns 400. Invoke the deployed Worker URL directly via HTTP POST. kindis immutable. Set at create time only; not accepted on PATCH.
Invocation
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:
{
"name": "My Project",
"slug": "my-project",
"description": ""
}PATCH /projects/:id write
Update a project's name or description.
Request body:
{ "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:
{ "ir": { ... } }PATCH /workflows/:workflowId/versions/:versionId write
Lock or unlock a version. Locked versions cannot be deployed.
Request body:
{ "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:
{
"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 → COMPLETEDPOST /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:
{
"connectionId": "connection-id",
"params": { "key": "value" }
}Response:
{
"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:
{ "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:
{
"provider": "cloudflare",
"credentials": { "apiToken": "...", "accountId": "..." },
"name": "My Connection"
}POST /connections/verify-token write
Verify provider credentials before saving.
Request body:
{ "provider": "cloudflare", "credentials": { "apiToken": "..." } }Response:
{
"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:
{ "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:
{ "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:
{ "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:
{ "nodeId": "stripe" }POST /marketplace/update write
Update an installed node to a newer version.
Request body:
{ "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:
{
"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.