Documentation
Workflows API
/v1/workflowsList workflows.
const workflows = await client.listWorkflows();
curl https://api.outreachagent.dev/v1/workflows \ -H "Authorization: Bearer $OUTREACHAGENT_API_KEY"
/v1/workflowsCreate a new workflow.
| Parameter | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | Workflow name |
| trigger | string | Yes | "manual", "api", or "event" |
| nodes | WorkflowNode[] | Yes | Array of workflow nodes |
| exitCriteria | ExitCriterion[] | No | Conditions that automatically exit enrolled contacts |
| optOutMode | string | No | "link", "reply" (default), or "header_only". Controls how opt-out is presented in emails. |
const wf = await client.createWorkflow({
name: "Drip Campaign",
trigger: "api",
nodes: [
{ id: "n1", type: "send_email", label: "Intro", templateId: "tmpl_1", nextNodeId: "n2" },
{ id: "n2", type: "delay", label: "Wait 1 day", delayAmount: 1, delayUnit: "days", nextNodeId: "n3" },
{ id: "n3", type: "send_webhook", label: "Notify CRM", webhookUrl: "https://crm.example.com/api", webhookBody: "{\"contact\": \"{{ contact.email }}\"}", nextNodeId: "n4" },
{ id: "n4", type: "exit", label: "End", nextNodeId: null }
],
exitCriteria: [{ trigger: "reply" }, { trigger: "bounce" }]
});curl -X POST https://api.outreachagent.dev/v1/workflows \
-H "Authorization: Bearer $OUTREACHAGENT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Drip Campaign",
"trigger": "api",
"nodes": [
{"id":"n1","type":"send_email","label":"Intro","templateId":"tmpl_1","nextNodeId":"n2"},
{"id":"n2","type":"delay","label":"Wait 1 day","delayAmount":1,"delayUnit":"days","nextNodeId":"n3"},
{"id":"n3","type":"send_webhook","label":"Notify CRM","webhookUrl":"https://crm.example.com/api","webhookBody":"{\"contact\": \"{{ contact.email }}\"}","nextNodeId":"n4"},
{"id":"n4","type":"exit","label":"End","nextNodeId":null}
],
"exitCriteria": [{"trigger":"reply"},{"trigger":"bounce"}]
}'/v1/workflows/:workflowIdGet workflow definition.
const wf = await client.getWorkflow("wf_abc");curl https://api.outreachagent.dev/v1/workflows/wf_abc \ -H "Authorization: Bearer $OUTREACHAGENT_API_KEY"
/v1/workflows/:workflowIdUpdate workflow name, trigger, nodes, exitCriteria, or optOutMode.
await client.updateWorkflow("wf_abc", { name: "Updated Campaign" });curl -X PATCH https://api.outreachagent.dev/v1/workflows/wf_abc \
-H "Authorization: Bearer $OUTREACHAGENT_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "Updated Campaign"}'/v1/workflows/:workflowIdDelete a workflow.
await client.deleteWorkflow("wf_abc");curl -X DELETE https://api.outreachagent.dev/v1/workflows/wf_abc \ -H "Authorization: Bearer $OUTREACHAGENT_API_KEY"
/v1/workflows/:workflowId/publishPublish a draft workflow (draft → active).
await client.publishWorkflow("wf_abc");curl -X POST https://api.outreachagent.dev/v1/workflows/wf_abc/publish \ -H "Authorization: Bearer $OUTREACHAGENT_API_KEY"
/v1/workflows/:workflowId/pausePause an active workflow.
await client.pauseWorkflow("wf_abc");curl -X POST https://api.outreachagent.dev/v1/workflows/wf_abc/pause \ -H "Authorization: Bearer $OUTREACHAGENT_API_KEY"
/v1/workflows/:workflowId/resumeResume a paused workflow.
await client.resumeWorkflow("wf_abc");curl -X POST https://api.outreachagent.dev/v1/workflows/wf_abc/resume \ -H "Authorization: Bearer $OUTREACHAGENT_API_KEY"
/v1/workflows/:workflowId/analyticsGet aggregate analytics for a workflow: enrollment counts, email stats, and rates.
const analytics = await client.getWorkflowAnalytics("wf_abc");
// analytics.totalEnrollments, analytics.completionRate, analytics.emailsSent, ...curl https://api.outreachagent.dev/v1/workflows/wf_abc/analytics \ -H "Authorization: Bearer $OUTREACHAGENT_API_KEY"
/v1/workflows/:workflowId/nodes/:nodeId/pausePause a specific node. Paused nodes are skipped during execution. The node ID is added to the workflow's pausedNodeIds array.
await client.pauseNode("wf_abc", "n3");curl -X POST https://api.outreachagent.dev/v1/workflows/wf_abc/nodes/n3/pause \ -H "Authorization: Bearer $OUTREACHAGENT_API_KEY"
/v1/workflows/:workflowId/nodes/:nodeId/resumeResume a paused node, removing it from pausedNodeIds.
await client.resumeNode("wf_abc", "n3");curl -X POST https://api.outreachagent.dev/v1/workflows/wf_abc/nodes/n3/resume \ -H "Authorization: Bearer $OUTREACHAGENT_API_KEY"
/v1/workflow-templatesList pre-built workflow templates. Built-in templates: Cold Outreach, Onboarding Drip, Re-engagement.
const templates = await client.listWorkflowTemplates();
// templates = [{ id, name, description, category, trigger, nodes, exitCriteria? }]curl https://api.outreachagent.dev/v1/workflow-templates \ -H "Authorization: Bearer $OUTREACHAGENT_API_KEY"
/v1/workflows/from-templateClone a template into a new draft workflow.
| Parameter | Type | Required | Description |
|---|---|---|---|
| templateId | string | Yes | Template ID to clone |
| name | string | No | Optional name for the new workflow |
const wf = await client.cloneFromTemplate("wftpl_cold", "My Cold Outreach");
await client.publishWorkflow(wf.id);curl -X POST https://api.outreachagent.dev/v1/workflows/from-template \
-H "Authorization: Bearer $OUTREACHAGENT_API_KEY" \
-H "Content-Type: application/json" \
-d '{"templateId": "wftpl_cold", "name": "My Cold Outreach"}'/v1/send-limitsList send limits for the organization. Returns per-inbox and org-wide limits.
const limits = await client.listSendLimits();
curl https://api.outreachagent.dev/v1/send-limits \ -H "Authorization: Bearer $OUTREACHAGENT_API_KEY"
/v1/send-limitsCreate or update a send limit. Omit inboxId for org-wide limit. Workflows automatically throttle email sends when the limit is reached.
| Parameter | Type | Required | Description |
|---|---|---|---|
| inboxId | string | No | Inbox to limit (omit for org-wide) |
| dailyLimit | number | Yes | Maximum emails per day |
// Org-wide limit
await client.upsertSendLimit({ dailyLimit: 500 });
// Per-inbox limit
await client.upsertSendLimit({ inboxId: "inb_abc", dailyLimit: 100 });curl -X PUT https://api.outreachagent.dev/v1/send-limits \
-H "Authorization: Bearer $OUTREACHAGENT_API_KEY" \
-H "Content-Type: application/json" \
-d '{"dailyLimit": 500}'/v1/workflows/:workflowId/test-sendSend a test email for a specific workflow node. Renders the template with optional contact data and enrollment variables, then delivers to the specified address.
| Parameter | Type | Required | Description |
|---|---|---|---|
| nodeId | string | Yes | ID of a send_email node in the workflow |
| to | string | Yes | Email address to send the test to |
| contactId | string | No | Contact ID to use for template rendering (populates {{ contact.* }} variables) |
| variables | object | No | Per-enrollment variable overrides (populates {{ vars.* }} in templates) |
const result = await client.testSendWorkflow("wf_abc", {
nodeId: "n1",
to: "you@yourteam.com",
contactId: "con_xyz",
variables: { hook: "your recent product launch" }
});
// result = { subject: "...", html: "...", to: "you@yourteam.com" }curl -X POST https://api.outreachagent.dev/v1/workflows/wf_abc/test-send \
-H "Authorization: Bearer $OUTREACHAGENT_API_KEY" \
-H "Content-Type: application/json" \
-d '{"nodeId": "n1", "to": "you@yourteam.com", "variables": {"hook": "your recent product launch"}}'/v1/workflows/:workflowId/simulateDry-run a workflow without sending real emails. Returns a step-by-step trace showing which nodes would execute and why.
const sim = await client.simulateWorkflow("wf_abc", {
contactId: "con_xyz"
});
// sim.trace = [{ nodeId, nodeType, label, outcome, message }, ...]
// sim.terminalStatus = "completed" | "would_wait" | "blocked" | ...curl -X POST https://api.outreachagent.dev/v1/workflows/wf_abc/simulate \
-H "Authorization: Bearer $OUTREACHAGENT_API_KEY" \
-H "Content-Type: application/json" \
-d '{"contactId": "con_xyz"}'