HTTP API
Manage endpoints, read events, and trigger replays from your own code.
These pages describe ShellOrbit as it runs today. Breaking changes to the HTTP API are announced before they ship, and existing request and response shapes stay supported.
How do I authenticate?
Bearer token. Create a key in the dashboard, store it as a secret, and send it on every request.
curl https://api.shellorbit.com/v1/endpoints \
-H "authorization: Bearer $SHELLORBIT_API_KEY"Keys carry a scope, either read or read and write, and can be revoked individually. A revoked key stops working immediately.
What are the main resources?
| Method and path | What it does |
|---|---|
GET /v1/endpoints | List endpoints |
POST /v1/endpoints | Create an endpoint |
GET /v1/endpoints/{id} | Read one endpoint with its configuration |
PATCH /v1/endpoints/{id} | Update destinations, retry policy, or alerts |
DELETE /v1/endpoints/{id} | Delete an endpoint and stop new receipts |
POST /v1/endpoints/{id}/events | Send an event through the endpoint, as a provider would |
GET /v1/events | List events, filtered by endpoint, status, type, or time |
GET /v1/events/{id} | Read one event with headers, body, and attempts |
POST /v1/events/{id}/replay | Replay one event |
POST /v1/replays | Replay a filtered set |
GET /v1/recoveries | List recovery jobs, with a cursor for older history |
POST /v1/recoveries | Prepare a saved selection of retained failed deliveries |
POST /v1/recoveries/{id} | Request a canary, continue after success, or cancel |
GET /v1/recoveries/{id}/items | Read per-destination recovery results, with a cursor |
GET /v1/usage | Current period volume and projected overage |
GET /v1/alerts | Read alert settings, with webhook URLs masked |
PATCH /v1/alerts | Update alert settings |
POST /v1/alerts/test | Send a test alert down every saved channel and report each result |
How is a list paginated?
Cursor based. A response carries next_cursor when more rows exist.
{
"data": [ { "id": "evt_9c41f0", "status": "delivered", "attempts": 3 } ],
"next_cursor": "ZXZ0Xzk1MmEx"
}Pass it back as cursor to continue. Cursors are stable across inserts, so paging through a busy endpoint does not skip or repeat rows.
How does a filtered replay work?
POST /v1/replays traverses every page in the selected time range, including empty filtered pages. It fixes the upper time bound when the request starts. A successful response includes events, queued, run_id, and truncated: false. Rate pacing counts destination deliveries, so an event with two enabled destinations queues two deliveries.
This endpoint queues work during the HTTP request. A timeout or storage/queue error can occur after some deliveries have already been queued. Check event attempts before repeating the selection; retrying the whole request creates a new replay run and can repeat those deliveries. Use the saved recovery workflow for large selections of failed deliveries.
How does saved recovery work?
Prepare a selection with POST /v1/recoveries:
{"endpoint_id":"ep_example","since":"2026-09-29T12:00:00Z","rate_per_second":10}An optional destination_id restricts the selection to an enabled destination. The rate must be an integer from 1 to 100. The upper time bound is fixed when preparation starts. Poll the job list until its state is ready; preparation sends no requests.
Send {"action":"canary"} to POST /v1/recoveries/{id} to test up to five distinct event–destination pairs. A pair can have several retry attempts. If the test succeeds and more deliveries remain, the state becomes awaiting_approval. Send {"action":"continue"} to recover the rest, or {"action":"cancel"} to stop pending requests. Requests already in flight may finish. Selections of five or fewer deliveries complete after a successful canary.
total, queued, delivered, failed, and skipped count destination deliveries, not events or HTTP attempts. queued includes reserved work waiting for queue submission. The item endpoint exposes the individual state and any skipped reason. A failed or unavailable delivery stops the job; a 24-hour deadline from creation also bounds preparation, pauses, and approval waits. History lasts 30 days, without extending payload retention.
Work proceeds in bounded pages. The requested rate spaces deliveries within each batch; it is not a global destination limit or a guaranteed request rate. Automatic retries can change timing. Recovery still uses at-least-once delivery, so application handlers need idempotency.
What do errors look like?
{
"error": {
"type": "invalid_request",
"message": "destination_url must use https",
"param": "destination_url"
}
}Status codes follow the usual meanings: 400 for a bad request, 401 for a missing or revoked key, 403 for a scope problem, 404 for an unknown id, 429 when rate limited, and 5xx for our failures. Retry reads with backoff for 429 and 5xx. Before retrying a write, check whether it already took effect; filtered replays can partially queue work as described above.
Is there a CLI?
There is a small one for local development: the ShellOrbit CLI (npx @shellorbit/cli listen) forwards the events an endpoint receives to a server on your machine. Everything else is the plain HTTP API above, so a few lines of curl or your language’s HTTP client does the same job, and that is what the examples show.