Skip to main content
Beyond plan actions, workflows can call external systems and send email — and any field can reference earlier values through interpolation.

CALL_WEBHOOK

{
  "actionType": "CALL_WEBHOOK",
  "url": "https://example.com/hook",
  "method": "POST",
  "headers": [ { "key": "X-Source", "value": "solya" } ],
  "queryParams": [ { "key": "ref", "value": "{{workflow.id}}" } ],
  "bodyType": "json",
  "bodyTemplate": "{ \"plan\": \"{{steps.create.output.planId}}\" }",
  "auth": { "type": "bearer", "credentialId": "<uuid>" },
  "timeoutMs": 10000,
  "retries": { "count": 2, "backoffMs": 1000 },
  "successStatusCodes": [200, 201, [200, 299]],
  "saveResponseAs": "hookResult"
}
FieldMeaning
methodGET · POST · PUT · PATCH · DELETE.
url, headers, queryParams, bodyTemplateAll support interpolation.
bodyTypenone · json · form · raw (bodyContentType for raw).
auth{ type: "none" }, or bearer / basic / apiKey referencing a credentialId (apiKey also takes a headerName).
timeoutMs / retriesExecution policy (retries: { count, backoffMs }).
successStatusCodesCodes (or [from, to] ranges) treated as success.
saveResponseAsNames the response output so it’s reachable downstream.

SEND_EMAIL

{
  "actionType": "SEND_EMAIL",
  "to": ["buyer@example.com"],
  "cc": [], "bcc": [], "replyTo": "ops@solya.app",
  "fromAddress": "no-reply@solya.app",
  "fromName": "Solya",
  "subject": "Restock plan {{steps.create.output.planName}} ready",
  "bodyFormat": "markdown",
  "bodyTemplate": "Added **{{steps.add.output.addedCount}}** items.",
  "tags": ["restock"],
  "trackOpens": true,
  "trackClicks": false
}
Sent via Mailgun from a verified sender domain. bodyFormat is text, html, or markdown. Output: messageId.

Credentials

Webhook secrets never live in the flow definition — they’re stored separately and referenced by credentialId.
  • Types: BEARER_TOKEN, BASIC_AUTH, API_KEY.
  • Stored encrypted at rest (AES-256-GCM); the flow only holds the credential’s id.
  • The app exposes a safe view (id, name, type — never the secret); the secret is resolved server-side only when the data platform executes the call.

Date offsets

Plan dates (deadline, startDate, endDate) use a DateOffset:
KindShapeMeaning
absolute{ "kind": "absolute", "iso": "2026-09-01T00:00:00Z" }A fixed ISO date-time.
relative{ "kind": "relative", "offsetDays": 30 }N days from {{now}}.
interpolated{ "kind": "interpolated", "template": "{{steps.x.output.date}}" }Resolved from a template.

Interpolation

Any interpolated field uses {{ … }} with dot-notation. Resolution happens at run time on the data platform (the builder offers autocomplete). Static variables
VariableValue
{{trigger.entityType}} / {{trigger.entityId}}The triggering entity kind / first matched id.
{{org.id}} / {{org.name}}The organization.
{{workflow.id}} / {{workflow.name}}The workflow.
{{now}}ISO timestamp at execution start.
Step outputs{{steps.<nodeId>.output.<field>}}, e.g.:
  • create-plan: planId, planType, planName, isNew
  • add-items: addedCount, skippedCount
  • webhook: your saveResponseAs field
  • email: messageId
Output names line up with the step records — see Runs & examples.