HTTP node settings for calling Quorum from n8n, Zapier and Make, with a split routed to a person.
Each tool below calls Quorum with its HTTP node. The request is the same in all three.
| Method | POST |
| URL | https://www.quorum.dog/v1/chat/completions |
| Header | Authorization: Bearer <your API key> |
| Header | Content-Type: application/json |
| Timeout | 300 seconds |
Body:
{
"model": "QRUM:STAN",
"messages": [
{ "role": "user", "content": "Should we refund this order? Customer message: ..." }
]
}Create the key in your organization and store it in the tool's credential store. API keys bill the organization's API account. A deliberation runs several models, so raise the node's timeout to the value above.
The answer is at choices[0].message.content. Three fields on quorum tell the workflow what to do next:
| Field | Branch |
|---|---|
quorum.replayed | true on a replay of an earlier call. A replay has no converged, remaining_friction, contested_passage or billed_usd, so check this first. |
quorum.converged | false means the seats split. Send to a person. |
quorum.remaining_friction | Not null also means a split. It is factual_conflict when the judge flagged a factual conflict between seats. |
quorum.contested_passage is an object with seat, quote and why, or null. Put quote in the message to the person.
To see the Mode's surcharge and a verdict before you spend anything, call https://www.quorum.dog/v1/estimate with the same body. It is free. It returns estimated_price_usd and deliberation_value.verdict. The loop is estimate, deliberate, get_receipt, act.
POST. URL https://www.quorum.dog/v1/chat/completions.Authorization, value Bearer <your API key>. Save it as a credential.300000 (milliseconds).Body, with the question taken from the previous node. JSON.stringify escapes quotes and line breaks:
{
"model": "QRUM:STAN",
"messages": [{ "role": "user", "content": {{ JSON.stringify($json.question) }} }]
}Add an IF node after it. Condition, Boolean, is true: {{ $json.quorum.replayed === true || $json.quorum.converged === false || $json.quorum.remaining_friction != null }}. The true branch goes to your review step (Slack message, ticket, approval node) and the false branch continues. The replayed test comes first because a replay has no converged field.
POST. URL https://www.quorum.dog/v1/chat/completions.Authorization set to Bearer <your API key> and Content-Type set to application/json.A question can contain quotes and line breaks. Build the body in a Code by Zapier step with JSON.stringify and map its output into the Data field, so the JSON stays valid.
Add a Paths step. The review path takes a response where quorum__replayed exists, quorum__converged is false, or quorum__remaining_friction exists. A replay has no quorum__converged field, so it needs its own rule.
Zapier limits how long an action waits for a response. Check the current limit for your plan against the 300-second timeout above. If the limit is shorter, call estimate in Zapier and run the deliberation from n8n or Make.
https://www.quorum.dog/v1/chat/completions. Method POST.Authorization set to Bearer <your API key>, Content-Type set to application/json.300 seconds.Build the request content with a Create JSON module or the JSON functions so the question is escaped. Then add a router after the HTTP module with a filter for the person-review route: quorum.replayed equals true, OR quorum.converged equals false, OR quorum.remaining_friction exists. A replay has no converged field, so it needs the first condition.
On any retry-prone trigger, add the header Idempotency-Key with a value that is stable for one question, such as the ticket id plus the step name. A repeat of a call that already succeeded replays the original answer and bills once. The replay matches on the key alone, so a key reused for a different question returns the first answer. The replay carries quorum.replayed: true. A call that ended capped is not replayed: a retry runs again and bills again.
rate_limit_exceeded and concurrency_limit_exceeded are 429 responses that carry a Retry-After header, in seconds. Set the node to retry on 429, 500 and 503, waiting the Retry-After value where the response has one. Branch on error.code, not on the message. All codes are in Errors and rate limits.