Skip to main content
Every page in this section is generated from Conduit’s OpenAPI spec. Each endpoint page shows its path, method, parameters, request scopes, and response schema directly from the source of truth, so the reference never drifts from the running service.
The reference is built from openapi.json. If an endpoint, parameter, or field appears in the spec, it is live. If it does not appear there, it is not part of the public contract.

Base URL

All paths are relative to a single host.
https://data.quantoraresearch.com
Every data path lives under /v1, and every response reports meta.api_version = "v1". Conduit is read-only and GET-only.

Authentication

Send your API key on every request to a /v1 route. Two header forms are accepted.
curl https://data.quantoraresearch.com/v1/public/observations/latest \
  -H "x-api-key: $CONDUIT_API_KEY"
A small set of routes need no key: GET /health, GET /ready, GET /openapi.json, GET /llms.txt, and GET /llms-full.txt. Keys carry scopes. Most product and data routes require data:read. Operational routes require ops:read. Sensitive admin routes require admin, which also satisfies the lower scopes. A key without the required scope returns 403 forbidden.
Keys are issued on request today. There is no self-serve signup form yet. See Support to request access. Keys are hashed server-side and are never returned, so store yours securely when issued.

The response envelope

Every response shares one shape, so you can write parsing once and reuse it everywhere. List responses wrap an array in data and carry pagination in meta.pagination. Item responses wrap a single object in data. Errors carry a stable machine-readable code. The request_id (also mirrored as top-level requestId) identifies the exact request and is what you quote when you contact support.
{
  "data": [ /* ... */ ],
  "meta": {
    "request_id": "8f1c0e2a-6b3d-4f0a-9c11-1d2e3f4a5b6c",
    "requestId": "8f1c0e2a-6b3d-4f0a-9c11-1d2e3f4a5b6c",
    "api_version": "v1",
    "pagination": {
      "limit": 100,
      "cursor": null,
      "next_cursor": null,
      "has_more": false
    }
  },
  "requestId": "8f1c0e2a-6b3d-4f0a-9c11-1d2e3f4a5b6c"
}

Error codes

Errors use a stable error.code. Branch on the code, not the message.
CodeHTTPMeaning
bad_request400Malformed input, or an unknown query parameter.
unauthorized401Missing or invalid API key.
forbidden403Key is valid but lacks the required scope.
not_found404The resource does not exist.
rate_limited429Rate limit exceeded for this client and scope.
internal_error500Unexpected server error.
Unknown query parameters fail closed. A parameter Conduit does not recognize is rejected with bad_request, never silently ignored. This catches typos before they return misleading data.

Pagination

List endpoints page with an opaque cursor. Set limit (1 to 500, default 100). When meta.pagination.has_more is true, pass meta.pagination.next_cursor back as cursor to fetch the next page. sort and order (asc or desc, default asc) control ordering on endpoints that support them.

Rate limits

Limits are enforced per client, per required scope, in a fixed window. Every /v1 response includes x-ratelimit-policy, x-ratelimit-limit, x-ratelimit-remaining, and x-ratelimit-reset (ISO timestamp). On exceed you get 429 rate_limited with details carrying required_scope, limit, and window_seconds.
ScopeDefault limitWindow
data:read1000 requests60s
ops:read500 requests60s
admin250 requests60s

Explore the spec

OpenAPI spec

The raw machine-readable contract. Import it into Postman, Insomnia, or your own code generator.

Coverage

A live breadth summary: catalog totals, public indicator categories, and covered countries.