Send your first event in 5 minutes
The fastest path is: create a workspace, create a source, point your producer at the ingest URL, and watch the event arrive in the dashboard.
Axel docs are split into four lanes: get started, primitives, operate, and reference. Each page is short by design — if a page can't be skimmed in 60 seconds, it's split into smaller ones.
The fastest path is: create a workspace, create a source, point your producer at the ingest URL, and watch the event arrive in the dashboard.
Webhook sources accept events. Routes evaluate declarative, eval-free filters and transforms. Destinations are where clean records land. Idempotency keys make every fan-out safe.
Everything you need to know when something is on fire: replays, failed deliveries, transform errors, and how to tune queue shards as you grow.
Canonical event payload, queue message shapes, retry policy defaults, and ClickHouse schemas for log queries.
CLI or curl. Under two minutes to a durable, searchable event.
curl -X POST https://api.axelapp.ai/v1/sources \
-H "Authorization: Bearer $AXEL_API_KEY" \
-d '{ "name": "my-webhook", "max_events_per_minute": 600 }'The response includes a per-source ingest token. Store it as a secret in your producer's environment.
POST https://ingest.axelapp.ai/in/{source_id}
x-axel-token: <token>
content-type: application/json
{ "type": "order.created", "id": "ord_123", ... }The endpoint returns 202 in under 250ms p95. Your event is durable in R2 before the response.
# Open https://app.axelapp.ai
# → Overview shows the event count tick up
# → Usage tab shows the source-level breakdown
# → Deliveries shows any failed attemptsEvery event you accept is searchable in ClickHouse for 30 days, including the raw payload and headers.
Prefer the CLI? axel auth login, axel sources create, then axel listen or point your webhook producer at the ingest URL shown in the dashboard.
Any producer that can POST JSON (or form / bytes) is supported.
Create a source with curl or the dashboard, then POST to https://ingest.axelapp.ai/in/{source_id} with the x-axel-token header you received. No signature required.
curl -X POST https://ingest.axelapp.ai/in/src_01H... \
-H "x-axel-token: axel_tok_..." \
-H "content-type: application/json" \
-d '{ "type": "order.created", "id": "ord_123", ... }'You can also bring a custom HMAC secret and Axel will verify an X-Signature (or configurable header) using constant-time verification.
Sources are the entry points. Each source has its own token (or signing secret), rate limit, body size cap, and nesting depth guard.
Routes decide where events go and what they look like. Rules are data, not code.
payments.live matches invoice.paid etc.).JSONB column.Deliver exactly once (with retries) to the systems you already run.
Every delivery attempt uses a stable key of the form workspace:event:route:destination. Retries and replays reuse the same key so duplicate work is impossible even across queue shards.
Reproduce any event you ever received, exactly.
From the dashboard or CLI:
# Dashboard: click any event → Replay
# CLI (exact bytes to your laptop)
axel replay evt_01HZQ8R7XK --forward-to http://localhost:3000/webhookEvery delivery attempt is recorded. Permanent failures (after all retries) land in the Inbox with one-click Retry and Mute. No SQL, no digging through DLQ tables.
The trace view shows every hop: receipt, R2 persist, route match, each transform, each HTTP attempt + status + reason (TLS error, 503, timeout, schema guard, etc.).
If a declarative transform or filter rejects an event (e.g. depth > 24, required field missing after select), the event is marked and either dropped or dead-lettered according to your source settings. You see the exact evaluation in the trace.
Every stored event carries the original payload plus Axel metadata. Example shape:
{
"event_id": "evt_01HZQ8R7XK",
"source": "my-webhook",
"event": "order.created",
"received_at": "2026-06-16T14:22:09.123Z",
"headers": { "x-my-signature": "..." },
"payload": { "id": "evt_...", "type": "order.created", ... },
"routes": ["orders.live"]
}Up to 12 delivery attempts with exponential backoff. Retries are never billable. You can tune per-source in the dashboard.
All receipt, routing, transform, and delivery rows are queryable in ClickHouse for 30 days (full raw payload + headers + failure reasons). The dashboard search and the axel CLI use these tables. Export or run your own queries from the usage / deliveries views.
Docs are intentionally concise. If something is missing or unclear, email the founders — we read every message and improve the site from real questions.