Developer API
The edge REST reference
The edge API is the one surface both the web app and theMCP server talk to — the MCP is a pure client of these same routes, so an integration here sees exactly what an agent sees. This is the lighter reference; the key routes and shapes are below.
Base URL & format
- Base URL:
https://api.billoquy.com. All routes are under/v1(health probes aside). - Requests and responses are JSON. Send
Content-Type: application/json. - CORS is restricted to the billoquy app and site origins. A
x-correlation-idrequest header is accepted (if it looks like an id) and echoed on the response, so you can line your logs up with ours.
Authentication
Pass a token as Authorization: Bearer <token>. There are two scopesof the same token model:
- human — a session from the magic-link sign-in flow.
- agent — an agent key, owner-scoped to the person's account. It can read, start checks, and start checkout, but is refused at human-only routes.
Routes are guarded by one of two checks: requireUser accepts either scope;requireHuman accepts only a human session. Approving a fix and managing agent keys are requireHuman — an agent token gets 403 there.
Error model
Errors are { "error": string }, sometimes with a detail. Status codes:
| Status | Meaning |
|---|---|
400 | Invalid request; body validation failed (may include detail). |
401 | Sign-in required (missing/expired token). |
403 | Forbidden — e.g. an agent token at a human-only route, or a failed human check. |
404 | Not found, or not yours (ownership failures are 404, never a leak). |
409 | Conflict — e.g. checkout on a check that is not complete. |
413 / 415 / 429 | Upload too large / wrong type / rate-limited. |
500 | Unexpected fault. The message is generic; the correlation id is logged. |
Diagnostics — the free funnel
| Route | Auth | Notes |
|---|---|---|
PUT /v1/uploads | optional | Stage a document. Body is the raw file; Content-Type must be PDF/PNG/JPEG/WebP, ≤10 MB. Returns 201 { key }. Anonymous callers are rate-limited per IP; signed-in callers are exempt. |
POST /v1/diagnostics | optional | Start a check. Body { product, intake, documents?, turnstileToken? }. Anonymous callers must pass a Turnstile token; a signed-in person or their agent need not. Returns 202 { id, status }. |
GET /v1/diagnostics/:id | optional | Read a diagnostic. Unclaimed ones are readable by their (unguessable) id; a claimed one is owner-only. |
POST /v1/diagnostics/:id/claim | human/agent | Attach an anonymous diagnostic to the signed-in account. Returns { ok: true }. |
POST /v1/interest | none | Register interest in a check not yet available for an input. Body { assessment, email? }. Returns { ok, count }. |
The signed-in account
| Route | Auth | Notes |
|---|---|---|
POST /v1/auth/magic-link | none | Body { email }. Emails a one-time sign-in link. Returns { ok: true }. The address is not logged. |
POST /v1/auth/redeem | none | Body { token }. Exchanges a magic-link token for a session; 401 if expired. |
GET /v1/me | human/agent | The account: { user, diagnostics, actions, receipts, models }. |
PATCH /v1/me | human/agent | Body { preferredModel } (must be an allowed model). Returns { user }. |
Approvals — the checkpoint
requireHuman — an agent token is refused here
Both routes below use requireHuman, never requireUser. A delegated agent token, even though it is owner-scoped, gets a 403 — approval is the human's action, structurally. Delivery is only ever enqueued after a human approval.
| Route | Auth | Notes |
|---|---|---|
POST /v1/actions/:id/approve | human only | Approve a prepared fix and release it toward delivery. Returns the updated action. |
POST /v1/actions/:id/decline | human only | Decline a prepared fix. Returns the updated action. |
Agent keys
Minting and revoking a key are themselves human-only — an agent cannot manage its own credentials.
| Route | Auth | Notes |
|---|---|---|
POST /v1/agent-tokens | human only | Body { label? }. Mints an agent key; returns 201 { token, label } once (never readable again). |
DELETE /v1/agent-tokens | human only | Body { token }. Revokes an agent key by value (owner-checked). Returns { ok: true }. |
Billing
| Route | Auth | Notes |
|---|---|---|
POST /v1/checkout | human/agent | Body { diagnosticId }. Returns { url } (Stripe Checkout). 409 if the check is not complete with a finding. |
POST /v1/billing/portal | human/agent | Returns { url } (Stripe billing portal). 404 until the first prepared fix creates a billing history. |
POST /v1/webhooks/stripe | Stripe | Stripe-signed webhook. Verified, deduplicated by event id; a paid checkout enqueues fix preparation (which still awaits human approval). |
Health & readiness
GET /health— liveness. Cheap, unauthenticated, no I/O. Returns{ ok, service, correlationId }.GET /ready— readiness. Reports whether required bindings are configured;503 { ready: false, missing }lists missing binding names (never values).