Orchestration
Deterministic, durable DAG workflow runner that calls the rest of the Quantum Elixir suite (and your own HTTP services) on your behalf. Built for chained business processes like KYC → screening → underwriting → monitoring.
What it does
| Capability | API |
|---|---|
| Workflow definitions | DAG of typed nodes (service_call · decision · transform · wait · webhook_emit · human_approval) |
| Triggered execution | API, webhook, or scheduled |
| Service connections | Per-org registry of sibling Quantum Elixir products + your own services |
| Catalog discovery | Programmatic catalog of all sibling endpoints with I/O schemas |
| Human approval gates | Pause runs; resume on signed approve/reject |
| Retries + idempotency | Per-step retry policy, idempotent on externalId |
| Audit trail | Postgres-trigger-enforced; every state transition logged |
| Outbound webhooks | Subscribe to execution + step events |
When to use it
Orchestration shines when:
- You're stitching 3+ Quantum Elixir products into a single user-facing flow (KYC onboarding, loan underwriting, dispute resolution).
- The flow has approval gates ("MLRO must sign off after AML screening").
- You need durable retry — a step failing shouldn't lose the whole run.
- You want a single audit-grade record of "this customer went through this flow at this time."
It's overkill when:
- Your flow is 2 sibling calls in sequence — just call them directly from your service.
- You need LLM steps or AI-driven branching — use AI Automation instead.
- You want fire-and-forget background jobs unrelated to the suite — use your own queue.
Orchestration vs AI Automation
Both run workflows. The difference:
- Orchestration is deterministic. Every node is a typed call. No LLM steps. Use when the steps are known and the routing is rule-based.
- AI Automation has LLM steps and agentic tools. Use when the flow needs reasoning, summarization, or natural-language decision-making.
Many teams use both: Orchestration for the spine of the business process, AI Automation as one of the nodes the spine calls.
Core concepts
| Concept | What it is |
|---|---|
| Workflow | A versioned DAG definition. draft → active after publish. |
| Execution | One run of a workflow. Has its own inputs, steps[], status. |
| Step | One node firing inside an execution. Stores input, output, status, error. |
| Service connection | An entry in your org's service registry pointing at a sibling product. Stores base URL + encrypted API key. |
| Catalog | Auto-discovered list of all sibling endpoints with their JSON-Schema I/O specs. |
Node types
| Type | What it does |
|---|---|
service_call | HTTP call to a sibling product or a registered external service. Templated body + headers. |
decision | Branches on the value of a previous step's output (if/else/switch). |
transform | Pure data shaping: jq-style expression over prior step output. |
wait | Sleeps for a duration or until a timestamp. |
webhook_emit | Fires an outbound webhook (separate from your event subscriptions). |
human_approval | Pauses run; resumes on POST /api/executions/{id}/approve. |
Templating
Inside any string field in a node spec, you can reference prior step output:
${trigger.customerId} ← top-level trigger payload
${step.run_kyc.output.customerId} ← output of a prior named step
${step.run_kyc.output.kycLevel}
${env.SLACK_WEBHOOK_URL} ← env-configured runtime valueTemplating uses a JS-evaluated expression syntax — limited surface, no arbitrary code, safe.
Common integration shape
Indonesian fintech KYC + onboarding workflow
- 1Your appCustomer fills your onboarding form.
- 2POST
/api/workflows/kyc/executeOrchestration starts. - 3`service_call` (Identity).POST `/api/identity/document/ktp/capture`
- 4`decision` — route on KTP verdict.If passed → Step 4. If requires_review → Step 6 (`human_approval`).
- 5`service_call` (AML).POST `/api/screenings` with `lane=onboarding`.
- 6`decision` — route on screening result.If `confirmed_hit` → Step 7 (`human_approval`). Else → Step 6.
- 7`webhook_emit` to your backend — "customer onboarded successfully".
- 8MLRO`human_approval` — pause until MLRO acts.
Endpoints at a glance
| Group | Endpoints |
|---|---|
| Workflows | GET/POST /api/workflows · GET/PATCH /api/workflows/{id-or-slug} · POST /api/workflows/{id-or-slug}/publish · POST /api/workflows/{id-or-slug}/execute |
| Executions | GET /api/executions · GET /api/executions/{id} · POST /api/executions/{id}/approve · POST /api/executions/{id}/cancel |
| Service connections | GET/POST /api/service-connections · GET /api/catalog/services |
| Webhooks | GET/POST /api/webhooks |
| API keys | GET/POST /api/api-keys |
| Audit log | GET /api/audit-log |
Production considerations
| Concern | Answer |
|---|---|
| Data residency | Workflow specs + execution rows + step outputs live in id-jkt-1. service_call outbound to siblings stays in-region. Egress to a custom: external service goes wherever your baseUrl resolves — that's on you. |
| Rate limits | Per-org default: 600 workflow executions/min. Per-service_call step inherits the sibling product's rate limit. See Rate limits →. |
| Idempotency | POST /api/workflows/{id}/execute does not dedup today — see Executions → Idempotency. Roadmap 2026 Q3. |
| Execution retention | Executions + step outputs retained 90 days by default. Step outputs >100 KB move to object storage and are linked from the step row. Compliance-tier orgs get 7 years. |
| Audit log | Every workflow create/publish/edit, execution start/approve/cancel, service-connection change is audit-logged with actor + before/after. Immutable, 7-year retention. |
| Webhook signing | HMAC-SHA256 over the raw JSON body, hex-encoded, sent as X-QEOR-Signature: sha256=.... See Webhooks → Signature verification. |
| Service-connection auth | Siblings use the gateway-issued service-principal key. custom: services accept a single apiKey sent as Authorization: Bearer <apiKey> on outbound service_call. |