Orchestration API

Send tasks to Elixion and have AI agents run them autonomously.

Orchestration API

Send tasks to Elixion and have AI agents run them autonomously.

Authentication

Both endpoints accept either an Elixion API key via the X-API-Key header (preferred for server-to-server) or a bearer JWT. Each API key is scoped to a project; calls must reference a project the key owns.

Submit a task

POST /api/v1/tasks

Request body (JSON):

  • title (string, required) - short human-readable name for the task.
  • description (string, optional) - full prompt for the agent.
  • project_id (UUID, required) - must match a project the API key has access to.
  • task_type (string, optional, default feature) - one of feature, bug, spec, chore. Used to pick the right agent.
  • callback_url (string, optional) - HTTPS URL Elixion will POST the result to when the workflow finishes. Must start with https://. Omit to use polling.
  • metadata (object, optional) - arbitrary JSON passed through; useful for caller-side correlation ids.

Response (201): {execution_id, status_url, websocket_room, callback_secret}. Save callback_secret if you supplied a callback_url - you need it to verify webhook signatures.

Polling for status

GET /api/v1/tasks/{execution_id} returns the same shape as the workflow detail used by the Orchestration page: state, progress, per-step status, timestamps, errors.

State enum: initializing then planning then executing then one of completed / failed / cancelled / escalated. paused is a transient state if a human pauses the workflow from the UI.

Webhook callback

When the workflow reaches a terminal state (completed, failed, escalated) Elixion POSTs the result to your callback_url.

Payload (JSON):

{
  "execution_id": "<uuid>",
  "status": "completed | failed | escalated",
  "duration_ms": 123456,
  "started_at": "2026-05-16T...",
  "completed_at": "2026-05-16T...",
  "output": { },
  "errors": [ ]
}

Verifying the signature

Header X-Elixion-Signature: sha256=<hex> is an HMAC-SHA256 of the raw request body, keyed by the callback_secret from the original POST response. Verify it before trusting the payload:

import hmac, hashlib

expected = "sha256=" + hmac.new(secret.encode(), body, hashlib.sha256).hexdigest()
if not hmac.compare_digest(expected, signature):
    abort(401)

Retry policy

Failed deliveries (non-2xx response, connection error, timeout) are retried up to 3 attempts total with exponential backoff between attempts (1s after the first failure, 4s after the second). Every attempt is persisted in workflow_webhook_deliveries (Elixion-side audit log). If all attempts fail, Elixion does not retry further - use polling as a fallback.

Idempotency

Webhooks are not deduplicated by Elixion. If your handler can crash mid-processing, key your idempotency on execution_id.

Real-time updates (optional)

If you want live step-by-step progress instead of waiting for the terminal webhook, connect to the workflow WebSocket room. The websocket_room returned from the POST is the channel name (workflow:<execution_id>); the WebSocket URL is wss://<your-elixion-host>/ws with ?token=<jwt> for auth.

Status enum reference

| State | Meaning | |---|---| | initializing | row created, runner not started yet | | planning | agents being chosen | | executing | at least one step running | | paused | human paused from the UI; Continue resumes | | completed | terminal; result delivered | | failed | terminal; one or more steps unrecoverable | | cancelled | terminal; user/admin stopped the run | | escalated | terminal; agents asked for a human handoff |