CFFBRWCFFBRWDocumentation
⚠Auto-generated documentation — This content was generated with AI assistance and is currently under review. Information may be incomplete or inaccurate. When in doubt, contact our support team.

API Reference

Complete reference for the CFFBRW API.

Base URL: https://api.cffbrw.com

Authentication

All API endpoints (except webhooks) require authentication. Include your API key in the Authorization header:

Authorization: Bearer wfk_your-api-key-here

API keys are managed in the dashboard under Settings → API Keys.

Note: API keys can only trigger published workflows. To run draft workflows, use the dashboard.


Workflows

POST /v1/workflows

Create a new workflow.

Request body:

{
  "name": "HN Trend Analyzer",
  "markdown": "# HN Trend Analyzer\n\n## Steps\n\n### 1. Fetch top stories\n..."
}

Response:

{
  "id": "wf_abc123",
  "name": "HN Trend Analyzer",
  "created_at": "2026-04-03T10:00:00Z",
  "updated_at": "2026-04-03T10:00:00Z"
}

GET /v1/workflows

List all workflows in your workspace.

Query parameters:

ParamTypeDescription
pagenumberPage number (default: 1)
limitnumberItems per page (default: 20, max: 100)

GET /v1/workflows/:id

Get a single workflow by ID.

PUT /v1/workflows/:id

Update a workflow's name or markdown content.

DELETE /v1/workflows/:id

Delete a workflow.


Compilation

POST /v1/workflows/:id/compile

Compile workflow markdown into an execution plan.

Request body:

{
  "markdown": "# My Workflow\n\n## Steps\n\n### 1. Fetch data\n..."
}

Response:

{
  "plan": {
    "steps": [
      {
        "id": "step_0",
        "type": "http_request",
        "config": {
          "method": "GET",
          "url": "https://api.example.com/data"
        },
        "dependsOn": []
      }
    ]
  },
  "planHash": "sha256:abc123...",
  "aiCost": 10
}

Credits: Compilation costs 10 credits. Cached plans (same markdown content) cost 0.


Runs

POST /v1/workflows/:id/run

Execute a workflow. The workflow must be published when using API keys.

Request body:

{
  "variables": {
    "API_KEY": "sk-...",
    "REPO": "owner/repo"
  }
}

Response:

{
  "runId": "run_xyz789",
  "status": "running",
  "planHash": "sha256:abc123..."
}

GET /v1/runs/:id

Get run status and results.

Response:

{
  "id": "run_xyz789",
  "workflowId": "wf_abc123",
  "status": "completed",
  "startedAt": "2026-04-03T10:00:00Z",
  "completedAt": "2026-04-03T10:00:05Z",
  "steps": [
    {
      "id": "step_0",
      "status": "completed",
      "duration": 234,
      "output": {}
    }
  ]
}

GET /v1/runs

List all runs.

Query parameters:

ParamTypeDescription
workflowIdstringFilter by workflow
statusstringFilter: running, completed, failed, pending_approval
pagenumberPage number
limitnumberItems per page

POST /v1/runs/:runId/approve/:stepIndex

Approve, reject, or retry a human approval gate. Accepts Clerk JWT auth or a valid signed review token (from the public approval page).

Request body:

{
  "action": "approve",
  "comment": "Looks good, proceed"
}
FieldTypeDescription
actionstring"approve", "reject", or "retry_with_hint"
commentstring?Optional comment (available to downstream steps)
reviewTokenstring?Signed review token (for public page auth bypass)

GET /v1/approve/:token

Signed token approval link. Three token types:

  • review — Renders a public approval page with step context
  • approve — One-click approve, returns confirmation page
  • reject — One-click reject, returns confirmation page

POST /v1/approve/:token

Form submission from the public review page. Accepts action (approve/reject) and optional comment.


Triggers

POST /v1/trigger/:workflowId

Trigger a published workflow via webhook. Accepts wfk_ API key or API_SECRET auth.

Request body:

{
  "variables": {
    "message": "Hello from webhook"
  }
}

POST /v1/workflows/:id/schedule

Set a cron schedule for a workflow.

Request body:

{
  "cron": "0 9 * * 1-5"
}

GET /v1/workflows/:id/schedule

Get the current cron schedule.

DELETE /v1/workflows/:id/schedule

Remove the cron schedule.


Queue Trigger

POST /v1/enqueue/:workflowId

Enqueue a message onto a queue-triggered workflow. The platform batches messages and fires one run per drain when either the time window elapses or the batch size is reached, whichever is first.

Auth: optional per-workflow X-Webhook-Secret header (set on the trigger config). If the workflow has a secret configured, requests without it return 401. If blank, the endpoint is public.

Request body: any JSON under 64 KB. Two accepted shapes:

{ "event": "lead.created", "email": "alice@example.com" }

or wrapped with optional metadata:

{
  "payload": { "event": "lead.created", "email": "alice@example.com" },
  "source": "webhook-A",
  "dedupeKey": "order-123"
}

dedupeKey is optional. When provided, the platform rejects any subsequent enqueue with the same key while the message is still in the queue (not yet drained). Use it to prevent duplicate processing when your producer retries on network errors. The key is scoped to the queue — the same key can be reused after the message is drained.

Response 200:

{ "enqueued": true, "queueDepth": 4, "msgId": 42 }

Errors:

  • 401 UNAUTHORIZED — wrong or missing X-Webhook-Secret
  • 404 NOT_FOUND — workflow not found or not published
  • 409 NOT_QUEUE_TRIGGER — workflow's trigger type is not queue
  • 409 DEDUPE — a message with the same dedupeKey is already in the queue
  • 413 PAYLOAD_TOO_LARGE — body over 64 KB
  • 429 QUEUE_FULL — queue at maxQueueDepth. Response includes details.queueDepth and details.maxQueueDepth.

GET /v1/queues/:workflowId

Inspect queue state. Clerk-authenticated (dashboard session).

Response:

{
  "depth": 3,
  "inFlightRunId": "run_abc...",
  "nextFireAt": 1777030154222,
  "oldestMsgAt": 1777029800000,
  "deadLetterCount": 0
}

GET /v1/queues/:workflowId/messages?limit=50

List queued (not yet drained) messages. Returns up to 200 via limit query param.

DELETE /v1/queues/:workflowId/messages/:id

Remove a single queued message. :id must be a positive integer.

DELETE /v1/queues/:workflowId

Purge all queued messages. Returns { "purged": N }. Admin escape hatch.

GET /v1/queues/:workflowId/dead-letter?limit=50

List dead-letter entries, messages whose dispatched run terminally failed or whose batch exceeded the platform's per-run size cap. Each entry includes batch_id, run_id, failed_at, failure_reason.

POST /v1/queues/:workflowId/dead-letter/replay

Re-enqueue dead-letter messages. Request body:

{ "ids": [5, 9, 11] }

or

{ "all": true }

Replay preserves each message's original received_at. If replaying would push currentDepth + replayed > maxQueueDepth, returns 409 REPLAY_EXCEEDS_CAPACITY with details, paginate instead of silently truncating.

DELETE /v1/queues/:workflowId/dead-letter/:id

Permanently purge a single dead-letter entry. :id must be a positive integer.


MCP Servers

POST /v1/mcp/servers

Register an MCP server.

Request body:

{
  "name": "my-slack-server",
  "url": "https://mcp.example.com/slack",
  "headers": {
    "Authorization": "Bearer xoxb-..."
  }
}

GET /v1/mcp/servers

List registered MCP servers.

GET /v1/mcp/servers/:id/tools

List available tools from an MCP server.

DELETE /v1/mcp/servers/:id

Unregister an MCP server.


Usage & Plans

GET /v1/usage

Get current period usage summary.

GET /v1/plan

Get the current workspace's plan and limits.

Response:

{
  "tier": "pro",
  "credits": { "used": 320, "total": 1000, "remaining": 680 },
  "workflows": { "used": 12, "total": 50 },
  "runs": { "used": 150, "total": 500 },
  "mcpServers": { "used": 3, "total": 10 }
}

Error Responses

All errors follow this format:

{
  "error": "Error message describing what went wrong",
  "code": "ERROR_CODE"
}
HTTP StatusMeaning
400Bad request — invalid input
401Unauthorized — missing or invalid API key
403Forbidden — insufficient permissions or unpublished workflow
404Not found — resource doesn't exist
429Rate limited — too many requests
500Internal server error