Skip to content

Workflows

The Workflows API exposes graph8’s automation graph engine. A workflow is a directed graph of typed nodes (Action / Delay / Branch / Agent / Skill / Loop / Trigger) plus connections between them. Triggers fire workflows in response to events (form submit, webhook, event stream, manual call).

The whole workflow definition is treated as a single record — node-level CRUD happens client-side by mutating config.nodes / config.connections and submitting via PUT.

30-second start

List your workflows:

Terminal window
curl 'https://be.graph8.com/api/v1/workflows?is_active=true&limit=10' \
-H "Authorization: Bearer $G8_API_KEY"

Quick reference

EndpointMethodPurpose
/workflowsGET / POSTList / create workflows
/workflows/{id}GET / PUT / DELETERead / replace / delete
/workflows/validatePOSTValidate a workflow without saving
/workflows/{id}/executePOSTRun immediately with trigger payload
/workflows/executions/{exec_id}GETExecution status + output
/workflows/executions/{exec_id}/pausePOSTPause an in-flight execution
/workflows/executions/{exec_id}/resumePOSTResume a paused execution
/workflows/executions/{exec_id}/stopPOSTStop (terminal)
/workflows/{id}/trigger-statusGETExternal trigger state
/workflows/{id}/trigger-resetPOSTReset trigger cursor
/workflows/node-types/schemaGETNode-type schemas (or filter via ?type=)
/workflows/integrations/slack/users|channelsGETSlack pickers
/workflows/integrations/roam/users|groupsGETRoam pickers
/workflows/mcp-serversGETAvailable MCP servers for Agent nodes
/workflows/dispositionsGETAvailable call dispositions for voice nodes
/workflows/forms/{form_id}/fieldsGETForm field schema for form-trigger nodes

Workflow shape

interface Workflow {
id: string;
name: string;
description: string | null;
config: {
nodes: Array<{
id: string;
type: "form_trigger" | "webhook_trigger" | "schedule_trigger"
| "action" | "delay" | "branch" | "loop"
| "agent" | "skill" | "sequence_enroll" | "dialer_call"
| "slack_message" | "email_send" | "...";
config: Record<string, unknown>;
input_mappings?: Record<string, string>;
}>;
connections: Array<{
from_node_id: string;
to_node_id: string;
condition?: string;
}>;
trigger?: Record<string, unknown>;
};
trigger_config: Record<string, unknown> | null;
is_active: boolean;
}

Create

Terminal window
POST /api/v1/workflows
Content-Type: application/json
{
"name": "Inbound demo follow-up",
"description": "Triggered when a form is submitted",
"config": {
"nodes": [
{ "id": "n1", "type": "form_trigger", "config": { "form_id": "demo_request" } },
{ "id": "n2", "type": "agent", "config": { "skill_id": "sk_qualify" } },
{ "id": "n3", "type": "slack_message", "config": { "channel_id": "C0123" } }
],
"connections": [
{ "from_node_id": "n1", "to_node_id": "n2" },
{ "from_node_id": "n2", "to_node_id": "n3" }
]
}
}

Update — full config replacement

The PUT endpoint replaces the entire config. To add or change a node:

Terminal window
GET /api/v1/workflows/{id}
# Mutate config.nodes / config.connections client-side
PUT /api/v1/workflows/{id}
Content-Type: application/json
{ "config": <updated config> }

The validator (POST /validate) checks orphan nodes, dangling connections, missing required fields per node type — call it before PUT to fail fast.

Execute

Terminal window
POST /api/v1/workflows/{id}/execute
Content-Type: application/json
{ "trigger_payload": { "contact_id": 5028106, "source": "manual_run" } }

Returns a WorkflowExecution with status: "pending" | "running" | "paused" | "completed" | "failed" | "stopped".

Execution control

Terminal window
GET /api/v1/workflows/executions/{exec_id}
POST /api/v1/workflows/executions/{exec_id}/pause
POST /api/v1/workflows/executions/{exec_id}/resume
POST /api/v1/workflows/executions/{exec_id}/stop

Pause + resume preserve state. Stop is terminal.

Trigger management

For event-stream triggers (Kafka-style cursors):

Terminal window
GET /api/v1/workflows/{id}/trigger-status
POST /api/v1/workflows/{id}/trigger-reset

Reset rewinds the cursor to the beginning of the stream.

Discovery + integration pickers

Terminal window
GET /api/v1/workflows/node-types/schema
GET /api/v1/workflows/node-types/schema?type=agent
GET /api/v1/workflows/integrations/slack/users
GET /api/v1/workflows/integrations/slack/channels
GET /api/v1/workflows/integrations/roam/users
GET /api/v1/workflows/integrations/roam/groups
GET /api/v1/workflows/mcp-servers
GET /api/v1/workflows/dispositions
GET /api/v1/workflows/forms/{form_id}/fields

Use these to power node-config UIs — e.g. an autocomplete for Slack channels when configuring a slack_message node.

Credit costs

OperationCredits
CRUD + validate + readFree
execute — baseFree for the orchestration itself
Inside the execution: each node actionPer-node action cost (see Pricing)

When an execution runs, each node that hits a paid surface charges its own credits (skill execute LLM = 1/1k tokens; sequence_enroll runs real sends; dialer_call is 20/min; etc.).

Errors

StatusCauseFix
401Missing or invalid Authorization: Bearer headerGet a key
402Out of credits (waterfall enrichment, AI generation, voice minutes)Top up in Settings → Billing, or switch to Platform
404Resource ID doesn’t existList first to verify the ID
422Validation error in request bodyInspect error.message + error.field in the response
429Rate limit (5 rps per org)Backoff per Retry-After header. See Rate Limits
5xxgraph8 errorRetry with exponential backoff (5s → 30s → 120s)

The full error envelope shape: { "error": { "code": "...", "message": "...", "field": "...", "request_id": "..." } }. Include the request_id in any support ticket. See Errors for the canonical reference.

See also