Workflow API

Start a workflow from your own backend, follow its runs and read the data tables it uses. For example, when a subscription payment fails, your server can start the workflow that opens a proactive conversation with that customer.

Before you start

Before you start
Allow API startTurn it on in the workflow's trigger, under Automation, then Workflows. A workflow without it answers 403 with the code start_not_allowed.
Scopesworkflows:write to start a run, workflows:read to read runs, tables:read and tables:write for data tables.
Retries are safeSend an Idempotency-Key with every start. One key starts at most one run of a workflow, however many times you retry.

Start a workflow

POST/workflows/{id}/runs

Starts one run for a contact or a conversation. The workflow's audience, frequency caps and consent rules still apply.

Request body
Body fieldTypeDescription
subject.typestring, requiredcontact or conversation.
subject.external_idstringThe user ID you pass to identify. Send this or subject.id.
paramsobjectValues the workflow can read in its steps and messages, up to 50 keys.
curl -X POST "$BASE/workflows/wf_payment_failed/runs" \
  -H "Authorization: Bearer $GRIPZ_API_KEY" \
  -H "Idempotency-Key: 9b2e41c7-5d0a-4f3e-8c61-2a7f0e4d1b58" \
  -H "Content-Type: application/json" \
  -d '{
    "subject": { "type": "contact", "external_id": "usr_4821" },
    "params": { "invoice": "INV-2041", "reason": "card_declined" }
  }'

What comes back

{
  "id": "wfr_3Kd81Q",
  "object": "workflow_run",
  "workflow_id": "wf_payment_failed",
  "status": "started",
  "subject": { "type": "contact", "id": "ct_9d3m" },
  "created_at": "2026-10-02T10:42:11Z"
}
Run status
startedThe run is queued. Follow it with the runs endpoint below.
skippedNothing ran, and reason says why: audience, frequency_cap, consent or workflow_paused. A skip is not an error, so do not retry it.
failedThe run could not start. The error names the problem, for example subject_not_found, and carries a request ID you can quote to support.

Runs and data tables

Read what a run did, step by step, and keep the tables your workflows look up in sync with your own systems.

Runs and data tables endpoints
GET/workflow_runs/{id}One run with its status and the result of each step.
GET/workflow_runsRuns of one workflow, newest first. Filter by workflow_id and status.
GET/data_tables/{id}/rowsRows of a data table, for example office hours or escalation contacts.
POST/data_tables/{id}/rowsAdd or update rows. Columns are typed, and a row that does not match is rejected with the column named.

Verify requests from your workflows

When an HTTP step in a workflow calls your server, the request is signed exactly like a webhook delivery: an HMAC-SHA256 signature over the request ID, the timestamp and the raw body, made with the workflow's signing secret. Reject anything older than five minutes.

Signature headers
gripz-webhook-idUnique per request. Use it to ignore repeats.
gripz-webhook-timestampSeconds since the epoch, when the request was signed.
gripz-webhook-signatureThe signature to compare in constant time.
Copy the verification recipe from Webhooks