Params and templates

Map values into a destination — params from a field or a fixed value, required params, {{…}} variables in URLs, headers, bodies and texts, and how each place encodes them for you.

Destinations work with two tools: params, the named values a destination carries, and templates, the {{…}} variables you write in its URLs, headers, bodies and texts.

Params

{
  "params": {
    "message": { "from": "state.message", "required": true },
    "route": { "from": "result.route" },
    "lead_score": { "from": "composites.lead_score" },
    "team": { "value": "inbound" }
  }
}

A param takes its value from a field of the run (from) or is a fixed value (value): a string of up to 500 characters, a number, true, false or null. A destination has up to 30 params, named with letters, digits and _ — up to 48 characters, not starting with a digit.

Sources

fromValue
stateThe whole state: an object, a string or an array.
state.<field>A field declared in an object state schema.
result.<question>The answer: an option, a level label or a probability.
confidence.<question>The answer's confidence, 0 to 1.
scores.<question>The weighted level of a score question.
composites.<key>A composite's value.
actionThe final action: continue, block, escalate or fallback.
decision.slugThe decision's slug.
decision.versionThe version that answered — null in the Playground, which runs the draft.
execution.idThe run's exec_… ID.

Values keep their JSON type: confidence.route is a number, state an object. A value that doesn't exist — an optional field the caller didn't send, any answer after an engine-error fallback — is null.

Required params

Mark a param required when the destination makes no sense without it — a CRM lead without an e-mail. When it resolves to null or an empty string, the destination doesn't fire and the response says why:

{ "key": "create_lead", "type": "http", "status": "skipped", "reason": "missing_param", "param": "email" }

Where params go

TypeParams are…
webhooksent in the event, under data.params.
workflowsent as top-level JSON fields — what n8n, Make and Zapier map directly.
httpthe JSON body of POST, PUT and PATCH requests without a body template, and the query string of GET and DELETE requests whose URL doesn't use them.
agentsent in the request body, under params.
functionpassed to your handler as its first argument.
reply, llmonly used through {{params.…}} in their texts.

Use params for anything that reaches a third party: a webhook or a workflow never receives the state itself, only the params you map — send what the receiver needs and nothing more.

Templates

Write {{ and }} around a variable — spaces inside are allowed: {{ params.awb }}.

VariableValue
{{params.<name>}}A param of this destination.
{{state}}, {{state.<field>}}The state, or a declared field of an object state.
{{result.<question>}}, {{confidence.<question>}}, {{scores.<question>}}An answer, its confidence, a weighted level.
{{composites.<key>}}A composite's value.
{{action}}, {{decision.slug}}, {{decision.version}}, {{execution.id}}The run.
{{delivery.id}}The dlv_… ID of this delivery — the same on every attempt.
{{secrets.<NAME>}}A workspace secret.

The editor's Insert… menu next to each field lists the variables you can use there.

Encoding is automatic

You never escape anything by hand: Dcision encodes each value for the place it goes.

WhereHow values are insertedSecrets
URLs — webhook.url, http.url, agent.url, workflow.urlURL-encoded. A secret is inserted as-is, so it can hold a whole URL.Allowed
Header values — http.headers, agent.headersAs text, with line breaks replaced by spaces — a value can't add a header.Allowed
http.bodyAs JSON — see below.Allowed
Texts — reply.text, reply.buttons, llm.instructions, llm.input, agent.instructionsAs text, line breaks kept.Not allowed: the text is returned to the caller or sent to a model.

As text, strings are inserted as they are, numbers and booleans are printed, objects and arrays become JSON and null becomes an empty string.

JSON bodies

An http body template is JSON with variables, and a variable's place decides how it is written:

  • Outside quotes, it becomes a JSON value — a string with its quotes, a number, true, null, an object.
  • Inside quotes, it becomes text inside that string, escaped as needed.

For a decision whose object state has email and company_size fields, with a param email taken from state.email:

Body template
{
  "email": {{params.email}},
  "company_size": {{state.company_size}},
  "summary": "Route {{result.route}} at {{confidence.route}} — lead score {{composites.lead_score}}",
  "lead": {{state}}
}
Body sent
{
  "email": "ana@acme.com",
  "company_size": 500,
  "summary": "Route sales at 0.85 — lead score 0.8414",
  "lead": { "message": "We need pricing for 500 users.", "email": "ana@acme.com", "company_size": 500 }
}

So write {{state.company_size}} — not "{{state.company_size}}" — to send the number 500 instead of the text "500". {{params.email}} needs no quotes either: its value is a string, so it is written with its quotes.

The body must be valid JSON once the variables are filled in: the editor checks it with sample values when you save, and an invalid template is refused with "The body must be JSON once variables are filled in…". A body is up to 10,000 characters. Leave it empty on POST, PUT and PATCH to send the params as a JSON object; GET and DELETE requests have no body.

Template checks

Templates are validated when you save or deploy:

  • every variable must exist: {{params.awb}} needs a param named awb, {{state.company_size}} a field of an object state, {{result.route}} a question named route;
  • secret names are UPPER_SNAKE_CASE, such as {{secrets.CRM_TOKEN}};
  • every {{ needs its }}, with one variable inside;
  • secrets can't be used in texts.

A missing secret isn't a schema error — secrets change without a deploy — but a delivery that references one fails until it is set. See Workspace secrets.

On this page