# Dispatched > Declarative, HTTP-native workflow orchestration engine. Define workflows as JSON or YAML, execute them as DAGs of HTTP calls to external services. Event-sourced, zero-knowledge encrypted, built with Elixir and Phoenix. Dispatched is a workflow engine that coordinates external services by making HTTP calls. Workflows are defined as data (no code required). Each step is an HTTP request, and steps can depend on each other, run in parallel, fan out over collections, race, or wait for external signals. All tenant data is encrypted at rest using envelope encryption — the operator cannot read it. ## Docs - [Getting Started](https://dispatched.work/docs/getting-started): Account setup, first workflow, running and monitoring - [Workflows](https://dispatched.work/docs/workflows): Workflow definition format, steps, patterns (fan-out, race, scatter, wait, conditionals, compensation) - [Expressions](https://dispatched.work/docs/expressions): Interpolation syntax, path expressions, JSONPath, sandboxed Lua - [Secrets](https://dispatched.work/docs/secrets): Encrypted secret management, available as {{ secrets.NAME }} - [Integrating Services](https://dispatched.work/docs/integrating-services): Guide for services called by workflows — request headers, response headers, directives, idempotency - [API Reference](https://dispatched.work/api): Interactive OpenAPI reference for sessions, workflows, runs, secrets - [CLI](https://dispatched.work/docs/cli): Install and use the dispatched CLI for auth, workflows, and secrets - [Authentication](https://dispatched.work/docs/authentication): DH handshake, browser sign-in, run sessions - [Encryption](https://dispatched.work/docs/encryption): Zero-knowledge envelope encryption model, what's protected, key rotation - [Full documentation for LLMs](https://dispatched.work/llms-full.txt): Complete documentation in a single file ## Core Concepts - **Workflows**: JSON/YAML documents defining HTTP steps with dependencies, triggers, retry policies, and execution strategies - **Steps**: Individual HTTP calls within a workflow. Each step has a request (method, url, headers, body) and can reference outputs of previous steps - **Triggers**: How workflows start — HTTP requests, cron schedules, or events - **Expressions**: `{{ }}` interpolation using dot-path, JSONPath, or Lua to reference trigger data, step outputs, secrets, and run metadata - **Strategies**: Execution patterns — scatter (all concurrent), race (first wins), fan-out (bounded concurrency), batch, reduce - **Signals**: Pause a workflow step until an external event arrives via the signal API - **Compensation**: Automatic saga-style rollback — each step can define a compensate request that runs if a later step fails ## API Overview Authentication uses a Diffie-Hellman handshake (POST /api/session, POST /api/session/confirm) that establishes a session token. All subsequent requests use the `Dispatched-Session` header. ### Key Endpoints - `PUT /api/workflows/:name` — Register a workflow (JSON or YAML body) - `POST /workflows/:name` — Trigger a workflow run (use `Prefer: respond-async` for 202) - `GET /api/runs/:id` — Get run status - `GET /api/runs/:id/events` — Poll run events (?after=N) - `POST /api/runs/:id/signal/:name` — Send a signal to a waiting step - `PUT /api/secrets/:name` — Store an encrypted secret - `DELETE /api/runs/:id` — Cancel a run ## Workflow Example ```json { "name": "process-order", "version": 1, "triggers": [{"type": "http"}], "steps": { "validate": { "request": { "method": "POST", "url": "https://api.example.com/validate", "body": "{{ trigger.body }}" } }, "charge": { "after": ["validate"], "request": { "method": "POST", "url": "https://api.stripe.com/v1/charges", "headers": {"authorization": "Bearer {{ secrets.STRIPE_KEY }}"}, "body": {"amount": "{{ steps.validate.response.body.amount }}"} }, "retry": {"on": [500, 503], "max": 3}, "compensate": { "method": "POST", "url": "https://api.stripe.com/v1/refunds" } }, "notify": { "after": ["charge"], "request": { "method": "POST", "url": "https://api.example.com/notify", "body": {"order_id": "{{ trigger.body.id }}", "charge_id": "{{ steps.charge.response.body.id }}"} } } } } ``` ## Expression Context | Path | Description | |------|-------------| | `trigger.body.*` | Trigger request body | | `trigger.headers.*` | Trigger request headers | | `steps..response.status` | Step HTTP status code | | `steps..response.body.*` | Step response body | | `steps..response.headers.*` | Step response headers | | `secrets.` | Encrypted tenant secret | | `run.id` | Current run ID | | `run.session` | Run-scoped session token (24h TTL) | ## Tech Stack Elixir 1.18, OTP 27, Phoenix 1.8 with LiveView, SQLite via ecto_sqlite3, Litestream for replication, Finch for HTTP, AES-256-GCM envelope encryption with X25519 DH sessions.