HTTP requests
Call any API after a decision — method, URL, headers and a JSON body built from variables and workspace secrets — delivered with retries, an Idempotency-Key and a signature.
An API request destination (type http) calls any HTTP API with a request you design — create a lead in your CRM, open a ticket, post to Slack — in the background, with retries. Tokens stay in workspace secrets, never in the decision.
Configure it
{
"key": "create_lead",
"type": "http",
"when": { "conditions": [{ "field": "route", "on": "output", "operator": "eq", "value": "sales" }] },
"params": {
"email": { "from": "state.email", "required": true },
"score": { "from": "composites.lead_score" }
},
"http": {
"method": "POST",
"url": "https://api.crm.example.com/v2/leads?source={{decision.slug}}",
"headers": [{ "name": "Authorization", "value": "Bearer {{secrets.CRM_TOKEN}}" }],
"body": "{\"email\": {{params.email}}, \"score\": {{params.score}}, \"note\": \"Routed to {{result.route}} by Dcision\"}"
}
}| Field | Type | Default | Description |
|---|---|---|---|
method | string | POST | GET, POST, PUT, PATCH or DELETE. |
url | string | — | https://… or {{secrets.NAME}} holding the whole URL; up to 2,048 characters, variables URL-encoded. |
headers | array | [] | Up to 20 { "name", "value" } pairs; values up to 2,048 characters, with variables and secrets. |
body | string | the params as JSON | POST, PUT and PATCH only: a JSON template of up to 10,000 characters. |
The body
The body is a JSON template: outside quotes a variable becomes a JSON value, inside quotes it becomes text — see JSON bodies. With the destination above, the CRM receives:
{ "email": "ana@acme.com", "score": 0.8414, "note": "Routed to sales by Dcision" }- No body template on
POST,PUTorPATCH: the params are sent as a JSON object. Content-Type: application/jsonis set unless you add your ownContent-Typeheader.GETandDELETEhave no body — a body on them is a schema error. Their params are added to the query string (?email=ana%40acme.com&score=0.8414), unless the URL already uses{{params.…}}.
Headers
Your headers are sent with Dcision's:
| Header | Value |
|---|---|
| Your headers | Their values rendered as text — line breaks become spaces. |
Content-Type | application/json when there is a body, unless you set it. |
User-Agent | Dcision-Destinations/1.0 (+https://docs.dcision.io/destinations), unless you set it. |
Idempotency-Key | The delivery ID, dlv_…, unless you set it — the same on every attempt, so APIs that support idempotency keys never apply a retry twice. |
Dcision-Delivery, Dcision-Attempt, Dcision-Event, Dcision-Signature | As for webhooks. |
Some names are set by Dcision or the HTTP layer and can't be used: Host, Content-Length, Connection, Transfer-Encoding, Upgrade, Keep-Alive, TE, Trailer, Expect, and any name that starts with Proxy- or Dcision-.
Authentication
Put credentials in a header with a secret — Authorization: Bearer {{secrets.CRM_TOKEN}} — or in the URL as a secret when the API expects a secret URL ({{secrets.SLACK_WEBHOOK}}). Credentials in the URL itself (https://user:password@…) are refused.
The signature
API requests are signed like webhooks, over the exact body sent — an empty body for GET and DELETE. If the receiving API is yours, verify Dcision-Signature with verifySignature (TypeScript) or verify_signature (Python): the body is your template, not a webhook event. See Verify the signature.
Example: a Slack message
Slack's incoming webhooks expect their own JSON, so use an API request with the webhook URL stored as a secret:
{
"key": "escalation_alert",
"type": "http",
"when": { "actions": ["escalate"] },
"params": { "message": { "from": "state.message" } },
"http": {
"method": "POST",
"url": "{{secrets.SLACK_WEBHOOK}}",
"body": "{\"text\": \"{{decision.slug}} asks for a person ({{action}}): {{params.message}}\"}"
}
}The message is written inside quotes, so the param is inserted as escaped text — quotes and line breaks in the lead's message can't break the JSON.
Webhooks
Receive the signed decision.completed event at your URL — the envelope, its headers, verifying Dcision-Signature with and without the SDKs, raw bodies in Express and Next.js, rotation and deduplication.
Functions
Let your own code act on a result — the response names the function and its params, and the TypeScript and Python SDKs call the handler you registered, in order and once per call.