API Reference
REST API · v1
Hand-written against the OpenAPI spec (packages/contracts/openapi.yaml); a CI drift gate keeps this surface 1:1 with the live app. Base URL: https://api.forumatlas.com/v1.
Query & synthesis
Ask cited questions, causal traces, tutor turns — the synthesis endpoints.
Briefs
Generate and retrieve per-persona briefs, with bibliographies.
Forecasts
Generate and retrieve Monte-Carlo probability distributions with driver attribution.
Entities
Cross-sector entity graph: search, resolve, traverse relationships.
Sources
Ingested public-source catalog with provenance + quality scores.
All endpoints
Every live route, its required scope (see Authentication), and where it's documented.
| Endpoint | Scope | Docs |
|---|---|---|
| GET /v1/health | — (public) | → |
| GET /v1/_edge_timing | any key | → |
| POST /v1/query | query:read | → |
| POST /v1/causal | query:read | → |
| POST /v1/tutor | query:read | → |
| GET /v1/usage | usage:read | → |
| POST /v1/brief | brief:write | → |
| GET /v1/briefs | brief:read | → |
| GET /v1/briefs/{id} | brief:read | → |
| GET /v1/briefs/{id}/bibliography | brief:read | → |
| GET /v1/briefs/{id}/evidence | brief:read | → |
| POST /v1/forecast | forecast:write | → |
| GET /v1/forecasts | forecast:read | → |
| GET /v1/forecasts/{id} | forecast:read | → |
| GET /v1/entities/search | entities:read | → |
| GET /v1/entities/by_alias | entities:read | → |
| GET /v1/entities/cross_sector_matrix | entities:read | → |
| POST /v1/entities/resolve | entities:read | → |
| GET /v1/entities/{id} | entities:read | → |
| GET /v1/entities/{id}/relationships | entities:read | → |
| GET /v1/sources | sources:read | → |
| GET /v1/sources/{id} | sources:read | → |
| GET /v1/documents/{id} | sources:read | → |
| POST /v1/anomalies/subscribe | anomalies:write | → |
| POST /v1/public/entity-requests | — (public) | → |
Common patterns
Pagination. Offset-based via offset + limit on every endpoint that pages. Default limit 20, max 100. Endpoints that return a fixed window rather than a page — /v1/sources/{id}?recent= — take neither. The drift gate reads this sentence and asserts both numbers against every route that declares limit, so an endpoint cannot quietly disagree with it.
Errors. Problem Details (RFC 9457). { "type": "...", "title": "...", "status": 4xx, "detail": "..." }
Verbs. Every GET also answers HEAD (same status and headers, no body), so a HEAD-defaulting uptime monitor reads the API correctly.
CORS. Browser calls are allowed from any origin: Access-Control-Allow-Origin: * with credentials disabled, since /v1 authenticates with a Bearer key in a header and uses no cookies. X-Request-Id and Retry-After are the exposed response headers. Note what this does not make safe: an API key shipped to a browser is readable by anyone using the page — call /v1 from your server, or mint a key scoped to exactly what the browser needs.
Rate limits. Two layers: a per-key requests-per-second limit (set on the key) and a pre-auth per-IP limit. Exceeding either returns 429 with a Retry-After header — that is the only rate-limit header sent.
Request IDs. Every response this API generates carries X-Request-Id; include it when reporting issues. One exception, and it is a request that never reached us: a malformed request line — a NUL byte in the path, for example — is rejected by our CDN’s own HTTP parser before it reaches our edge, and what you get back is the CDN’s plain 400 with no X-Request-Id and no Problem body. Nothing we deploy or configure runs on that path, so it is documented rather than fixed.
Versioning. Path-based /v1. Additive changes only within a major version.