Braize

The response envelope & versioning

Why every Braize-native response is {data, meta}, how contract versioning works, and what additive-only evolution means for your integration.

Why an envelope at all

Every Braize-native endpoint (everything except the OpenAI-compatible endpoint, which has its own documented exception) returns:

{ "data": { /* the actual payload */ }, "meta": { "request_id": "…", "braize_version": "2026-09-01" } }

The envelope exists so response-level metadata (a request id for support, the contract version a response was generated against, a degraded flag) never has to be smuggled into the payload shape itself or invented as a one-off header per endpoint. meta grows over time without ever touching data's shape.

meta.degraded is worth watching: it's true when a response was produced during a provider outage (e.g. retrieval fell back to lexical-only search because the embedding provider was briefly unavailable). That's not an error — you still got an answer — but you may want to surface it, or retry later for a stronger one.

Additive-only, forever

The contract only ever grows. In practice that means, permanently:

  • A field is never removed or renamed.
  • A field's type or meaning never changes.
  • An optional field never becomes required.
  • An error type URI is never repurposed for a different condition (see Handling errors).
  • New capability arrives as a new field, a new endpoint, or (for MCP) a new tool — never a breaking change to something that already shipped.

The practical implication for your integration: parse tolerantly. Ignore fields and enum values you don't recognize instead of failing on them; a JSON-Schema validator set to additionalProperties: false against an exact snapshot of today's response shape will eventually break on a perfectly normal, non-breaking addition. Several request schemas (QueryRequest, RetrieveRequest) explicitly declare additionalProperties: true for exactly this must-ignore contract.

Pinning a version on purpose

Every response's meta.braize_version names the contract date it was generated against (e.g. 2026-09-01). Because the contract is additive-only, you don't normally need to do anything — new responses stay compatible with code written against an older version. If you want to freeze behavior explicitly anyway (e.g. for a reproducible test suite), send Braize-Version: 2026-09-01 as a request header; see Pinning a contract version in Authentication & regions.

Pagination is opaque

Where a list response paginates (GET /v1/documents), the next_cursor field is an opaque forward token, not something to parse or construct yourself. Pass it back verbatim as ?cursor=. Treating it as opaque is what lets the underlying pagination implementation change without breaking every client that stored a cursor.

What's next

  • Handling errors — the other half of the contract: what a non-success response looks like and why it's typed the same way everywhere.
  • Core concepts — the product principles this contract exists to enforce.