Skip to main content
The awaithumans server exposes a small REST API. Most users never touch it directly — the Python and TypeScript SDKs wrap every endpoint. This reference is for:
  • Operators debugging an issue
  • Building a non-SDK client (Go, Rust, etc.)
  • Wiring custom integrations

Base URL

All endpoints under /api/. Static dashboard files live at /, /setup, etc. — those aren’t part of the REST API.

Authentication

Two auth modes: Admin bearer token — for agents / automation:
Session cookie — for the dashboard (set by POST /api/auth/login):
Public endpoints (no auth required): /api/auth/*, /api/setup/*, /api/health, channel webhook receivers (/api/channels/slack/interactions, /api/channels/email/action/*, etc.) — these self-authenticate via signed payloads.

Content types

  • Request bodies: application/json (except channel webhooks, which use application/x-www-form-urlencoded per their respective vendor specs)
  • Response bodies: application/json

Error format

Every error response has the shape:
The error_code is stable across versions; the message and docs URL may change.

OpenAPI spec

Interactive OpenAPI docs at /api/docs (FastAPI’s Swagger UI). The raw spec is at /api/openapi.json. For SDK code-gen against your own clients:

Rate limits

No rate limit on task routes — the bearer token holder is implicitly trusted. If you need to rate-limit your own agent’s task creation, do it in your code (Stripe-style outbox pattern recommended).

Idempotency

Every POST /api/tasks carries a required idempotency_key. The contract is Stripe-style — same key returns the same task, regardless of status, for the lifetime of the row.
  • First call with a fresh key: the task is inserted and the response is 201 Created.
  • Subsequent calls with the same key: the existing task is returned with 201 Created plus an Idempotent-Replayed: true response header. Notifications (email / Slack) do NOT re-fire on replay — that would re-page the human for already-in-flight work.
Clients that need to distinguish a fresh creation from a replay read the header:
Why the status stays 201 (instead of flipping to 200 on replay): strict HTTP semantics reserve 201 for newly-created resources, but Stripe — the model this contract is named after — keeps the original status code on replay and signals replay-vs-fresh via header. That convention breaks zero clients that check status == 201 for success while still being explicit for clients that care. To trigger a fresh task for the same logical event (e.g. retry a refund review after an earlier one was rejected), pass a distinct key — convention is to suffix: "refund-A-4721:retry-1".

Endpoints by resource

Tasks (admin / operator / assignee)

Auth

Setup (first-run bootstrap)

Users (admin / operator)

Channels

Stats

Health

Cross-version stability

  • The /api/tasks/* shape is stable for v1.x — breaking changes are a v2 event.
  • Error codes (error_code field) are stable across all v0.x.
  • The dashboard and channel webhook routes are internal — third-party clients should NOT depend on their shapes.