OpenAPI
The HTTP API is described in one OpenAPI 3.1 document. Point a client generator, an API gateway or a test tool at it.
| On a deployment | /openapi.json, e.g. https://api.antibot.dev/openapi.json |
| In the repository | web/public/openapi.json |
What it covers
Every route handler under web/app/api, one operation per method:
| Tag | |
|---|---|
| Server API | Events, visitors and related visitors, with a secret key |
| Assess | /assess, its outcomes, trap reports, the edge's refusal counts, receipt usage and revocations |
| Agent and mobile SDKs | Identification, integrity keys, pulses, challenges, waiting rooms, the credential lookup, App Attest — and their CORS preflights |
| Management API | Everything under /api/management/v1 |
| Operations | /api/health, /api/ready, /api/metrics |
And what the service sends you: every webhook delivery, under
the document's webhooks — the identification and each type the others
carry (alert.started, session.escalated, script.changed, …), with the
body's schema and the three headers every delivery has. Generate your
receiver's types from it.
The agent and the SDKs call their endpoints for you. They are described so a proxy, a firewall rule or a custom client can be written against them, not because you need to call them.
Each operation says how it authenticates:
- Secret key —
Authorization: Bearer sk_…orAuth-API-Key. The role on the requirement is the use the key needs:identificationfor the Server API,assessfor the assess family. A key that lists no uses may do both. - Management key —
Authorization: Bearer mk_…. The role is the scope the operation needs. Discovery (GET /api/management/v1) needs none. - Public key — in the request body, as
apiKey. OpenAPI cannot describe a credential in a body, so these operations list no security scheme and their body requiresapiKey. - Metrics token —
ANTIBOT_METRICS_TOKEN, as a bearer.
Errors are the shared Error shape, { "error": { "code", "message" } }. Each
error response lists the codes it can carry. See Errors.
What it leaves out
GET /api/auth/sso/callback. It is where an identity provider sends the browser back after single sign-on — a step in signing in to the dashboard, not an API.- The agent script itself (
/agent/v1/antibot.js), which is not under/api. - The dashboard's pages and form actions.
One rule a request body follows is not in its schema: /assess/outcome needs
at least one of account, card, phone, code, content and hold. JSON
Schema generated from the code cannot carry it, so the operation's description
says it instead.
How it is made
It is generated from the code, not written by hand:
cd web
pnpm openapi
- Paths and methods come from the route handlers: every
route.tsunderweb/app/api, read for the methods it exports. - Request bodies the API validates with zod come from those schemas, the
ones the routes import, through
z.toJSONSchema. They live inweb/lib/api/schemas/. - Everything else — summaries, the Management API's bodies, query
parameters, responses and errors — is one table beside the generator,
web/scripts/openapi.operations.ts. Its enums are the code's own constants, so a new scope or rule action reaches the document by itself.
Changing a route, a request schema or that table means running pnpm openapi
and committing the new openapi.json with the change.
CI keeps it honest
pnpm test:openapi fails when:
openapi.jsonis not whatpnpm openapiwrites now — it went stale;- a route handler has no operation, or an operation no route handler, other than the exclusions listed in the table;
- an operationId repeats, a
$refdoes not resolve, or an operation has no responses; - a request body backed by zod is not the schema its route imports and parses with, or a route parses with a schema the document does not know;
- the documented success status is not one the handler returns;
- the code sends a webhook the document does not have, or the document has one the code does not send; a body the code builds, or one the webhooks guide shows, does not fit its schema.
It also sends real requests through the handlers in-process: bodies the document accepts must be accepted and bodies it refuses refused, and every answer must fit the documented response.