Automation
Event-triggered DAGs across email / push / SMS / webhook / branch / wait / ai_action / update_profile. Visual builder mirrors API shape 1:1. IaC bundles for import / export.
Features
- **8 starter blueprints** in the template gallery — welcome series, cart abandonment, order confirmation, post-purchase feedback, trial ending, re-engagement, birthday, password reset. Clone in one click.
- **Event-typed trigger** — `{ eventType, filters }` with wildcard matching. Any event from any module (auth.user_created, csat.detractor, push.delivered, kb.article_viewed, …) can fire a workflow. Filters narrow by event properties.
- **8 step types** — `send_email`, `send_push`, `send_sms`, `webhook`, `update_profile`, `wait`, `branch`, `ai_action`. Each implemented in `apps/backend/src/modules/automation/step-executor.ts`.
- **AI step type** — `ai_action` step with `feature: generate | decide | extract` via gpt-oss:120b / ministral:14b on Ollama Cloud (or BYOK per-org).
- **Branching** — branch step jumps to ifTrue / ifFalse indexes based on profile trait equality. Standalone delay via `wait` step.
- **Run history** — filter by status (running / paused / completed / failed), cancel an in-flight run, drill into per-step outcomes + audit log.
- **Pause / resume mid-flight** — flips `workflow_runs.status` to `paused`; new triggers queue; resume picks up at next step.
- **Promote.failed webhook** + delivery-health metrics in Health module — broken journeys surface, not silently rot.
- **Real audience targeting** — Audiences from Customers module evaluate at send-time inside the email/push/sms steps. Real-time audience membership; no nightly CDP sync.
Common use cases
- Replace Customer.io / Iterable for event-driven lifecycle journeys where the branch + send happens over Sendora-emitted events directly.
- Cross-channel campaigns (Push → wait 1h → Email → wait 3d → SMS) without stitching three vendors and three reputations — same `user_id` across all 4 sender step types.
- AI-driven personalization — `ai_action: generate` drafts an email body inline, `decide` picks the next branch, `extract` writes a profile trait, all inside the workflow.
Key concepts
- Workflow step types
- `email`, `push`, `sms`, `webhook`, `branch` (ifTrue / ifFalse jump), `wait`, `ai_action`, `update_profile`.
- Template interpolation
- `{{ user.email }}` / `{{ event.amount }}` / `{{ profile.plan }}` resolved per-recipient at step run.
- Bundle export
- JSON bundle of workflows + audiences for IaC. Diffable. Import roundtrip-stable.
Workflows
Trigger a workflow from any SDK event
FREEWorkflows subscribe to event names. Fire the matching `track()` call from any SDK and the workflow runs server-side — no extra API needed. Workflows are per-project (ADR-013): event's projectId scopes which workflows fire.
// Workflow trigger: { eventType: "checkout_completed" }
sendora.track("checkout_completed", { amount: 49.99 });Create a workflow
STARTER+Define triggers + steps via API instead of the visual builder. Step types: `send_email`, `send_push`, `send_sms`, `update_profile`, `webhook`, `branch`, `wait`, `ai_action`. Each step's `config` shape is type-specific.
curl -X POST https://api.sendoracloud.com/api/v1/orgs/<ORG_UUID>/automation/workflows \
-H "x-api-key: pk_prod_…" \
-d '{
"name": "Welcome series",
"trigger": { "eventType": "user.signed_up" },
"isActive": true,
"steps": [
{ "type": "send_email", "config": { "templateId": "<TEMPLATE_UUID>", "to": "{{event.userEmail}}" } },
{ "type": "wait", "config": { "reason": "let user finish onboarding" }, "delayMinutes": 1440 },
{ "type": "send_push", "config": { "title": "Tips for day 1", "body": "{{user.firstName}}, here are 3 tips..." } }
]
}'Step `config` shapes
STARTER+Per-step-type config schema. Templates use `{{handlebars}}` substitution against trigger context (`{{event.*}}`, `{{user.*}}`, `{{trait.*}}`).
# send_email { templateId, to } OR { subject, bodyHtml, to } — BYOD verified domain required
# send_push { title, body } — fans out to ctx.userId's tokens
# send_sms { to, body } — Twilio configured required
# update_profile { traits: { ... } } — merges into ctx.user profile
# webhook { url, method?, headers?, body? } — HMAC-signed; SSRF-guarded
# branch { condition: { trait/event, op, value }, ifTrue, ifFalse } — jumps to step label
# wait { reason? } + delayMinutes — uses workflow_runs.next_step_at
# ai_action { flavor: "generate"|"decide"|"extract", prompt, saveTo? } — Ollama Cloud, jsonMode optionalDry-run a workflow
STARTER+Send a sample event through the engine without writing rows or firing side effects — returns a step-by-step trace for debugging. EDITOR role required.
curl -X POST https://api.sendoracloud.com/api/v1/orgs/<ORG_UUID>/automation/workflows/<WORKFLOW_UUID>/test-run \
-H "x-api-key: pk_prod_…" \
-d '{
"eventType": "checkout_completed",
"properties": { "amount": 49.99 }
}'Query workflow runs
STARTER+Inspect each run's step trace + outcome. Per-step outcomes: `sent | suppressed | ai_unavailable | ai_pending | error | skipped-missing-config | byod_required | rate_limited`.
# List
curl 'https://api.sendoracloud.com/api/v1/orgs/<ORG_UUID>/automation/runs?workflowId=<WORKFLOW_UUID>&pageSize=20' \
-H "x-api-key: pk_prod_…"
# Detail (full step trace)
curl https://api.sendoracloud.com/api/v1/orgs/<ORG_UUID>/automation/runs/<RUN_UUID> \
-H "x-api-key: pk_prod_…"Export / import workflow bundles (IaC)
STARTER+Versioned bundle format for git-tracking workflows + CI promotion (dev → staging → prod). Importer is idempotent by name. Bundle includes `$schema` URL for VS Code autocomplete + validation.
# Export single workflow
curl https://api.sendoracloud.com/api/v1/orgs/<ORG_UUID>/automation/workflows/<WORKFLOW_UUID>/export \
-H "x-api-key: pk_prod_…" > welcome-series.workflow.json
# Export every workflow in a project
curl 'https://api.sendoracloud.com/api/v1/orgs/<ORG_UUID>/automation/workflows/export?projectId=<PROJECT_UUID>' \
-H "x-api-key: pk_prod_…" > all.workflows.json
# Import (idempotent — same name updates, new name creates)
curl -X POST 'https://api.sendoracloud.com/api/v1/orgs/<ORG_UUID>/automation/workflows/import?projectId=<PROJECT_UUID>' \
-H "x-api-key: pk_prod_…" \
-H "Content-Type: application/json" \
-d @welcome-series.workflow.json