Start a run
const url = 'https://api.usesonora.com/v1/workflows/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/runs';const options = { method: 'POST', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"account":{"id":"example","idType":"sonora"},"recipients":{"roles":["example"],"emails":["hello@example.com"],"contactIds":["2489E9AD-2EE2-8E00-8EC9-32D5F69181C0"]},"variables":{"additionalProperty":"example"}}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://api.usesonora.com/v1/workflows/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/runs \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "account": { "id": "example", "idType": "sonora" }, "recipients": { "roles": [ "example" ], "emails": [ "hello@example.com" ], "contactIds": [ "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0" ] }, "variables": { "additionalProperty": "example" } }'Start the workflow for one account, or — with a JSON array body — for up to 100 accounts at once (207, one result per element, each what that account’s own call would have answered). The progress of a run is GET /workflow-runs/{runId}, under workflows:read.
Requires the workflows:trigger scope. API keys only.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”The workflow’s chain root id (GET /workflows); a version id is 404.
Header Parameters
Section titled “Header Parameters”1–255 printable characters. A retry with the same key and request answers with the first call’s result instead of acting twice.
Request Bodyrequired
Section titled “Request Bodyrequired”Start one run of an API-triggered workflow.
object
The account the run is about.
object
The account’s id, in the system idType names.
How id names the account: sonora (the default; Sonora’s customer id), salesforce, hubspot, domain, or custom_field:<key>.
Who the run emails, for a workflow whose email steps send to people the call names. Required there, refused elsewhere.
object
Contact role slugs (GET /contact-roles); everyone at the account in one of them.
Values for the workflow’s declared variables (GET /workflows): strings, numbers or booleans.
object
Start the workflow for up to 100 accounts, each named once.
Start one run of an API-triggered workflow.
object
The account the run is about.
object
The account’s id, in the system idType names.
How id names the account: sonora (the default; Sonora’s customer id), salesforce, hubspot, domain, or custom_field:<key>.
Who the run emails, for a workflow whose email steps send to people the call names. Required there, refused elsewhere.
object
Contact role slugs (GET /contact-roles); everyone at the account in one of them.
Values for the workflow’s declared variables (GET /workflows): strings, numbers or booleans.
object
Responses
Section titled “Responses”An idempotent replay: the body the original call got.
What a start call started: the run’s fields fixed at acceptance. Its progress is GET links.self.
object
object
The workflow’s chain root id.
The version the run executes.
Who an API call named and the run reaches; empty otherwise.
One person an API call named that the run reaches.
object
This resource’s canonical URL on the API host.
What the API call that started a run asked for, and who it skipped.
object
object
The roles the call matched, as slugs.
object
A person the call named who won’t be emailed.
object
recently_triggered only: the run that last reached them through this workflow.
recently_triggered only: when the resend window lets a call reach them again.
Example
{ "origin": "auto", "recipients": [ { "matchedBy": [ { "type": "role" } ] } ], "trigger": { "skippedRecipients": [ { "reason": "unsubscribed", "matchedBy": [ { "type": "role" } ] } ] }}The run started.
What a start call started: the run’s fields fixed at acceptance. Its progress is GET links.self.
object
object
The workflow’s chain root id.
The version the run executes.
Who an API call named and the run reaches; empty otherwise.
One person an API call named that the run reaches.
object
This resource’s canonical URL on the API host.
What the API call that started a run asked for, and who it skipped.
object
object
The roles the call matched, as slugs.
object
A person the call named who won’t be emailed.
object
recently_triggered only: the run that last reached them through this workflow.
recently_triggered only: when the resend window lets a call reach them again.
Example
{ "origin": "auto", "recipients": [ { "matchedBy": [ { "type": "role" } ] } ], "trigger": { "skippedRecipients": [ { "reason": "unsubscribed", "matchedBy": [ { "type": "role" } ] } ] }}A batch: one result per element, in order.
object
One result per element, in order.
One element’s outcome.
object
What the single call for this element would have answered.
What a start call started: the run’s fields fixed at acceptance. Its progress is GET links.self.
object
object
The workflow’s chain root id.
The version the run executes.
Who an API call named and the run reaches; empty otherwise.
One person an API call named that the run reaches.
object
This resource’s canonical URL on the API host.
What the API call that started a run asked for, and who it skipped.
object
object
The roles the call matched, as slugs.
object
A person the call named who won’t be emailed.
object
recently_triggered only: the run that last reached them through this workflow.
recently_triggered only: when the resend window lets a call reach them again.
The one error shape every endpoint answers with.
object
object
Stable snake_case code to branch on; see the error table.
For humans; may change.
object
Quote it when asking for help.
Example
{ "data": [ { "body": { "origin": "auto", "recipients": [ { "matchedBy": [ { "type": "role" } ] } ], "trigger": { "skippedRecipients": [ { "reason": "unsubscribed", "matchedBy": [ { "type": "role" } ] } ] } } } ]}invalid_json: The request body is not valid JSON.
invalid_request: A parameter or body field is missing, malformed or unknown; details.issues names each.
The one error shape every endpoint answers with.
object
object
Stable snake_case code to branch on; see the error table.
For humans; may change.
object
Quote it when asking for help.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": { "additionalProperty": "example" }, "requestId": "example" }}unauthorized: The Authorization header is missing, or the key is invalid, revoked or expired.
The one error shape every endpoint answers with.
object
object
Stable snake_case code to branch on; see the error table.
For humans; may change.
object
Quote it when asking for help.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": { "additionalProperty": "example" }, "requestId": "example" }}insufficient_scope: The key or token lacks the scope this endpoint needs, and details.required names it; or an OAuth access token called an endpoint only an API key can.
The one error shape every endpoint answers with.
object
object
Stable snake_case code to branch on; see the error table.
For humans; may change.
object
Quote it when asking for help.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": { "additionalProperty": "example" }, "requestId": "example" }}account_not_found: No account matches the id (and idType) the call named.
workflow_not_found: No API-triggered workflow with that id.
The one error shape every endpoint answers with.
object
object
Stable snake_case code to branch on; see the error table.
For humans; may change.
object
Quote it when asking for help.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": { "additionalProperty": "example" }, "requestId": "example" }}recently_triggered: Everyone the call named was reached by this workflow within its resend window.
run_active: The account already has an active run of this workflow.
workflow_has_no_owner: The workflow’s author was removed; someone must take it over before it can send.
workflow_inactive: The workflow is a draft; activate it first.
The one error shape every endpoint answers with.
object
object
Stable snake_case code to branch on; see the error table.
For humans; may change.
object
Quote it when asking for help.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": { "additionalProperty": "example" }, "requestId": "example" }}payload_too_large: The request body is too large; details.maxBytes gives the limit.
The one error shape every endpoint answers with.
object
object
Stable snake_case code to branch on; see the error table.
For humans; may change.
object
Quote it when asking for help.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": { "additionalProperty": "example" }, "requestId": "example" }}account_archived: The account is archived.
idempotency_key_mismatch: The Idempotency-Key was used before with a different request.
invalid_variable: A variable’s value has the wrong type.
missing_variable: A required variable is missing.
no_recipients: Nobody the call named can be emailed.
recipient_not_found: An email or contact id the call named isn’t a contact at the account.
recipients_not_accepted: The workflow doesn’t send to people a call names, so recipients would be ignored.
recipients_required: The workflow sends to the people a call names, and the call named nobody.
role_field_not_configured: The call named roles, but no contact role field is set on Settings → API.
too_many_recipients: The call names more people than a run may reach.
unknown_role: A role isn’t one of the role field’s slugs; details.validRoles lists them.
unknown_variable: A variable isn’t one the workflow declares.
workflow_not_api_triggered: The workflow isn’t started by the API.
The one error shape every endpoint answers with.
object
object
Stable snake_case code to branch on; see the error table.
For humans; may change.
object
Quote it when asking for help.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": { "additionalProperty": "example" }, "requestId": "example" }}rate_limited: Too many requests for this key; retry after Retry-After seconds.
The one error shape every endpoint answers with.
object
object
Stable snake_case code to branch on; see the error table.
For humans; may change.
object
Quote it when asking for help.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": { "additionalProperty": "example" }, "requestId": "example" }}internal_error: Something went wrong on Sonora’s side. Retry, and quote requestId if it persists.
The one error shape every endpoint answers with.
object
object
Stable snake_case code to branch on; see the error table.
For humans; may change.
object
Quote it when asking for help.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": { "additionalProperty": "example" }, "requestId": "example" }}Try it
Try it runs the reference's read endpoints, and this one changes data, so it needs an API key with the workflows:trigger scope. Create a key in Sonora under Settings → API and call it from your own code.