API
Everything in Stella Loop is reachable through /api/v1 — the CLI and the MCP server are thin clients over it, and there are no private endpoints behind either. The API is self-describing: an unauthenticated GET /api/v1 returns discovery information, and the complete OpenAPI 3.1 document is served at GET /api/v1/openapi.json.
Authentication
Send an API key as a bearer token:
curl -H "Authorization: Bearer $STELLA_API_KEY" \
https://<your-api-origin>/api/v1/projects/ATLAS/tasks
Keys carry scopes (read < work < admin) and project grants; requests outside them return permission_denied with the missing requirement named. Every request is attributed to the key’s actor. Keys are created, rotated (with a grace window), and revoked in settings → API keys — the secret is shown once.
One envelope
Success responses share one shape, errors another:
{ "data": { … }, "requestId": "req_…", "pageInfo": { "cursor": "…" } }
{ "error": { "code": "task_already_claimed", "message": "…" }, "requestId": "req_…" }
- Every response carries a request ID for support and correlation.
- Collections paginate by cursor.
- Error codes are a stable, machine-readable taxonomy shared with the CLI’s exit codes —
unauthenticated,permission_denied,not_found, domain conflicts liketask_already_claimed(409),rate_limited(429 withRetry-After),validation_failed.
Display-ID addressing
Human-readable IDs are first-class addresses. These are equivalent:
GET /api/v1/projects/ATLAS/epics/EPC-12
stella epic show EPC-12
SIG-n, INT-n, RPT-n, PRP-n, EPC-n, and TSK-n resolve everywhere an ID is accepted.
Idempotency and rate limits
- Mutating requests accept an
Idempotency-Keyheader; replays return the recorded response with anIdempotent-Replayheader, so retry loops are safe. The CLI sends one automatically. - Rate limits are classed (read / write / expensive) with burst allowances;
429responses carryRetry-Afterand rate-limit headers.
Events out
Two ways to be told instead of polling:
- Event feed —
GET …/eventswith cursor pagination, type filters, and await=long-poll hold; orGET …/events/streamfor server-sent events with heartbeats andLast-Event-IDlossless resume. - Webhooks — register HTTPS destinations, receive HMAC-signed deliveries (
X-Stella-Signatureovertimestamp.body), verify, and process. Deliveries retry with backoff and dead-letter after repeated failure; a synchronous test ping exists for setup. Webhooks can also serve as an agent actor’s notification channel —task.assignedwakes the agent that should claim.
Gates apply here too
The API enforces exactly what the UI enforces: promotion passes the epic.promote checkpoint, merges pass epic.merge, invalid stage transitions are rejected with the legal edges named, and approval decisions respect approver policy. A held transition returns its approval reference so your automation can wait for the decision — or surface it to a human.