Template Expressions
Dynamic value interpolation in integration.yaml using ${{ }} syntax
Template Expressions
Expressions are evaluated at runtime and interpolated into input field values in integration.yaml. Always use the ${{ ... }} syntax. Works identically in TypeScript and Python steps:
input:
email: "${{ trigger.body.email }}"
plan: "${{ trigger.query.plan }}"Expression Reference
| Expression | Resolves to |
|---|---|
${{ trigger.body.field }} | Field from the inbound trigger payload body (POST/PUT body or manual run payload) |
${{ trigger.query.field }} | URL query parameter from the inbound webhook request |
${{ trigger.headers.x-api-key }} | Inbound trigger request header |
${{ steps.STEP_ID.output.field }} | Output field from a previously completed step |
${{ config.KEY }} | Workspace config / environment variable named KEY |
${{ error.message }} | Error message (available in on_failure steps) |
${{ error.step }} | ID of the step that failed (available in on_failure steps) |
Nested field access uses dot notation: ${{ trigger.body.deal.contact.email }}.
pinned-trigger-payload.json
This file pins a static trigger payload used instead of the live event during manual and test runs. It must mirror the exact runtime structure:
Webhook triggers
{
"query": { "plan": "Growth", "hours": "10" },
"body": {},
"headers": {}
}Common mistake: A flat object like
{ "plan": "Growth" }causes${{ trigger.query.plan }}to resolve to empty because there is noquerykey. Fallback logic in step code (e.g.input.get('plan') or 'Growth') may silently mask this.
Manual triggers
{
"email": "test@example.com",
"plan": "Growth"
}For manual triggers, the payload is injected directly as trigger.body.