Skip to content

Response envelope

Every successful /api/v1/* response uses the same envelope shape. This page documents the envelope, the error variant, the conventions for cache control and warnings, and how to read partial results.

The locked decision is ADR 0012; the full grammar is in the Backend API spec.

Success envelope

{
"data": { ... },
"meta": {
"api_version": "v1",
"catalog_version_id": "math-2026-spring",
"request_id": "req_01H...",
"evaluated_at": "2026-05-15T21:33:00Z"
},
"warnings": [
{ "code": "graph_view_truncated", "message": "..." }
],
"unknowns": [
{
"target": "course:MATH 999",
"unknown_reason": "unparsed_requirement",
"source_reference_id": "sref_..."
}
],
"source_references": [
{ "source_reference_id": "sref_...", "kind": "course_prerequisite_text", "...": "..." }
]
}

Field-by-field:

FieldRequiredPurpose
datasuccess-onlyThe primary payload for this endpoint.
metaalwaysAPI version, catalog version pinned to this response, request id, evaluation timestamp.
warningsalwaysNon-fatal advisories (truncation, partial data, deprecation).
unknownsalwaysThings the engine could not resolve, with reason codes. Distinct from warnings.
source_referencesalwaysFull record for every referenced source-reference id in this response.

The arrays may be empty but they are always present, so client code can iterate without null checks.

Error envelope

{
"error": {
"code": "bad_request",
"message": "...",
"details": { ... }
},
"meta": {
"api_version": "v1",
"request_id": "req_01H..."
}
}

Error responses never carry data. HTTP status follows RFC 9110 semantics. The error code is a machine-readable token; see Errors.

HTTP semantics

  • Method semantics follow RFC 9110. GET is safe and idempotent; POST is non-idempotent (state-creating or query-evaluating); PATCH is non-idempotent state mutation; PUT is idempotent replacement; DELETE is idempotent removal.
  • Caching follows RFC 9111. State-bearing responses (/api/v1/state/current/*) include Cache-Control: no-store. Read-only catalog responses may carry validation freshness signals.

Truncation

Bounded-by-design endpoints (graph views, Advisory enumeration) may return less than the conceptual answer. Truncation is not an error:

  • Status remains 200 OK.
  • The response includes a graph_view_truncated (or similar) entry in warnings.
  • A reciprocal omitted count appears in meta so the client can display “showing N of M”.

Bounded-breach (request exceeds hard maxima) returns 400 bad_request, because the client asked for something the server has been configured to refuse. See ADR 0009 §“hard maxima” and the graph-view response spec.

Warnings vs unknowns

  • Warnings describe a property of the response (truncated, deprecated, slow). They are advice to the caller, not facts about academic content.
  • Unknowns describe a property of the academic content (this sub-requirement is unresolved). They survive end-to-end so the frontend can render unknown statuses with click-through reason codes.

Catalog version pinning

Every response includes meta.catalog_version_id. If a client passes a state pinned to a different catalog version, the mismatch is reported explicitly in the envelope rather than silently coerced.

Want the full spec?