n8n
n8n can start a Sonora workflow with a plain HTTP Request node — no custom node to install. A typical flow: a trigger in your stack (a usage alert, a CRM change, a support escalation) → an HTTP Request node that asks Sonora to email the right people at that account → optionally, a second node that checks back on the run.
This page walks through that setup. The Workflows guide explains each call, and the API reference has every field and error code.
1. In Sonora
Section titled “1. In Sonora”- Build a workflow whose trigger is From the API and activate it. Copy its id from the trigger panel.
- If the flow will name people by role, pick your role field under Settings → API → Contact roles. The card lists each role’s slug (
economic_buyer) — that’s what the flow sends. Renaming a role option changes its slug, so update the flow if you do. - Create an API key under Settings → API → API keys with the
workflows:triggerscope (addworkflows:readif you’ll poll runs or list workflows). Copy the key — it’s shown once.
2. Add the key to n8n as a credential
Section titled “2. Add the key to n8n as a credential”In n8n, create a Header Auth credential:
- Name:
Authorization - Value:
Bearer sonora_sk_…(the key you copied, after the wordBearerand a space)
Every HTTP Request node below uses this credential (Authentication → Generic Credential Type → Header Auth), so the key lives in one place and never appears in a node’s parameters.
3. Start the workflow
Section titled “3. Start the workflow”Add an HTTP Request node:
- Method:
POST - URL:
https://api.usesonora.com/v1/workflows/<workflow id>/runs— the same base URL for every workspace; the key says which one - Authentication: the Header Auth credential from step 2
- Send Headers: on, with one header — Name:
Idempotency-Key, Value:{{ $execution.id }}-{{ $itemIndex }} - Send Body: on, Body Content Type: JSON, Specify Body: Using JSON
{ "account": { "id": "{{ $json.salesforceAccountId }}", "idType": "salesforce" }, "recipients": { "roles": ["economic_buyer", "champion"] }, "variables": { "reason": "{{ $json.reason }}" }}Adjust the expressions to your incoming data. idType can also be sonora, hubspot, domain or custom_field:<key>; leave recipients out if the workflow emails the account’s contacts rather than the people a call names. Roles are slugs, as GET /v1/contact-roles lists them — economic_buyer, not Economic Buyer.
The Idempotency-Key header makes retries safe: when the node retries (Retry On Fail), Sonora returns the run it already started instead of starting another. {{ $execution.id }}-{{ $itemIndex }} is stable across those retries and different for every item. Retrying a whole execution from n8n’s Executions list starts a new execution with a new id, so if you do that by hand, build the key from your own data instead — say usage-alert-{{ $json.alertId }}.
A successful call answers 202 with the new run: its id, who it will email (recipients), and anyone skipped and why (trigger.skippedRecipients).
Many accounts in one call
Section titled “Many accounts in one call”When one execution has many accounts to reach — a nightly job that finds every account whose usage dropped, say — you can send up to 100 of them in one request instead of one request per item:
- A Loop Over Items node with Batch Size
100, so each pass carries at most 100 accounts. - Inside the loop, an Aggregate node (All Item Data, output field
data), which turns that pass’s items into one item. - The HTTP Request node, with the body as a JSON array — one element per account — and its output wired back into the loop:
{{ JSON.stringify($json.data.map(a => ({ account: { id: a.salesforceAccountId, idType: "salesforce" }, recipients: { roles: ["economic_buyer"] }, variables: { reason: a.reason }}))) }}Use {{ $execution.id }}-{{ $runIndex }} as the Idempotency-Key: one key covers each request’s batch, stable when the node retries and different for every pass of the loop. The answer is 207 with a data list: one { status, body } result per account, in order, each what that account’s own call would have answered. Route on each result’s status (split data into items with a Split Out node) rather than on the node’s success. See Start runs for several accounts.
Don’t fail the flow on “already handled”
Section titled “Don’t fail the flow on “already handled””Two answers mean Sonora is already on it rather than that something broke:
409 run_active— a run of this workflow is active for the account.409 recently_triggered— everyone named was already reached within the workflow’s resend window.
Under the node’s Settings, set On Error to Continue (using error output), and route the error output through an IF node on {{ $json.error.code }}: treat run_active and recently_triggered as done, and alert on anything else. 429 rate_limited is worth retrying after the Retry-After header’s number of seconds: turn on Retry On Fail with a wait of a few seconds, which is safe because of the idempotency key.
4. Check back on the run (optional)
Section titled “4. Check back on the run (optional)”Add a Wait node (say, a day), then another HTTP Request node with the same credential:
- Method:
GET - URL:
{{ $('Start Sonora workflow').item.json.links.self }}— the run’s own URL, from the start call’s response (orhttps://api.usesonora.com/v1/workflow-runs/{{ $('Start Sonora workflow').item.json.id }})
The response has the run’s status, what it’s waitingOn (review, reply, enrichment, delay), and a messages list with each email’s status and when it was opened, clicked or replied to. Loop back to the Wait node while status is active if you want to act on the outcome — for example, post to Slack when firstRepliedAt is set.
To count how often you’ve triggered a workflow for an account, call GET https://api.usesonora.com/v1/workflow-runs?workflowId=<id>&accountId=<id>&accountIdType=salesforce&limit=1&include=totalCount and read totalCount.
Populating a workflow dropdown
Section titled “Populating a workflow dropdown”GET https://api.usesonora.com/v1/workflows (scope workflows:read) lists the workflows a call can start, with their variables and each one’s runsUrl. Use it in a node that loads options if one n8n flow should be able to start several Sonora workflows.