Skip to navigation

Versions and changes

The path stays /v1, and each request names its contract revision in Truvo-Version. A breaking change ships only in a new revision, and the older revision keeps working for at least 6 months after notice.

View as Markdown

The Truvo API has one path, /v1, and its contract has revisions, which the changelog lists. A revision is a version of the API contract. A version, such as resource.version on an event or version on a quote request, is a step in the history of one object.

Pre-release

Until the REST API opens to outside developers, Truvo serves one revision, with the pre-release ID 2026-09-26.

When the REST API opens, the first public revision gets its own ID, and Truvo stops serving the pre-release ID. A request that names 2026-09-26 in Truvo-Version then gets 400 invalid_version, and the error lists the IDs that Truvo serves.

The notice period and the 6-month promise start with the first public revision, so the pre-release ID 2026-09-26 is replaced then with no alias.

Revision IDs

A revision ID is a date in the form YYYY-MM-DD, and revisions are in the order that they ship. The ID format may change before the first public revision. A change that breaks nothing reaches every served revision in place, so a revision’s ID never changes. Send an ID exactly as the changelog lists it.

GET https://api.truvo.com/v1/revisions lists the revisions, with no key. current is the newest served revision, and each revision has a status: current, supported or retired. /v1/openapi/<revision>.json is the OpenAPI document of one served revision, and /v1/openapi.json is the document of the current one.

{
"current": "2026-09-26",
"revisions": [{ "id": "2026-09-26", "status": "current", "sunset_at": null }]
}

Send Truvo-Version on every API request

Every request to an API operation sends the ID of the revision that your code is built for in the Truvo-Version header:

curl https://api.truvo.com/v1/capabilities \
-H "Authorization: Bearer $TRUVO_API_KEY" \
-H "Truvo-Version: 2026-09-26"

The answer names the same revision in its own Truvo-Version header, and its fields follow that revision.

Two kinds of request don’t need the header. /v1/mcp always answers in the current revision, as The MCP server uses the current revision explains. The other kind is the public discovery documents: /v1/openapi.json, /v1/openapi/<revision>.json, /v1/revisions, /llms.txt and /.well-known/api-catalog.

Truvo matches the header exactly. A missing header, or one that names no revision that Truvo serves, gets 400 with the code invalid_version. The message says which revision to send, and the field error’s allowed_values lists each revision that Truvo serves, newest first, so your code can correct itself in one retry:

{
"error": {
"code": "invalid_version",
"message": "This request has no Truvo-Version header. Send Truvo-Version: 2026-09-26 on every REST request. GET https://api.truvo.com/v1/revisions lists every revision.",
"field_errors": [
{
"path": "Truvo-Version",
"message": "Send Truvo-Version: 2026-09-26. allowed_values lists each revision that Truvo serves, newest first.",
"code": "not_allowed",
"allowed_values": [
"2026-09-26"
]
}
],
"retry_action": {
"type": "correct_input",
"summary": "Send Truvo-Version: 2026-09-26, or another revision in allowed_values, and send the request again."
},
"doc_url": "https://docs.truvo.com/v1/errors/invalid_version"
},
"request_id": "req_d329dfd06b162cdb"
}

The revision lives in your code, so an upgrade or a rollback is a code change, and the sandbox and live answer the same way. The API reference gives each request’s revision as the only value of its Truvo-Version header, so a client built from it sends the header for you.

Move to a new revision

When a new revision ships, read its changelog entry, change your code for each breaking change, and send the new ID. Each request names its own revision, so you can move one request at a time.

The MCP server uses the current revision

/v1/mcp always answers in the current revision, and each answer names it in Truvo-Version. The MCP server doesn’t need the header and ignores it. Code that needs a stable contract should call the REST API.

When a new revision makes a breaking change to a tool’s input, /v1/mcp keeps accepting the old input for the 6-month notice period. After that, it answers with a field error that names the new field.

Webhook events

Webhook events have no revision. An event names the resource that changed and the version it reached, and its wrapper is the same in every revision. To see the change, read the resource over REST, with your own Truvo-Version.

The event feed, GET /v1/events, is an API operation. It sends Truvo-Version, and its answer follows that revision, as every API answer does.

What counts as a breaking change

A breaking change ships only in a new revision. These changes are breaking:

  • A removal or a rename.
  • A new required input.
  • Narrower bounds.
  • A new type or unit.
  • A new null in an output.
  • A new meaning for a status, a permission, a default, an error, an order, a cursor, or a key.

Each resource’s status is closed, so a new status value is a breaking change too. The reason in its status_details is open.

What can change in any revision

New fields can arrive in any revision, so read answers with a reader that accepts them. Any field in an answer can also get new values without a new revision, except each resource’s status and retry_action.type. A new meaning for an existing value is still a breaking change.

Ignore a field that you don’t know. When you branch on a value, add a default branch for a value that you don’t know:

switch (error.code) {
case "needs_information":
// Ask the person for the facts in error.field_errors.
break;
default:
show(error.message, error.doc_url);
}

For a next action of a type that you don’t know, the default branch skips that action.

How long a revision keeps working

A revision keeps working for at least 6 months after notice. The changelog and an email announce each new revision and the end date of the revision before it. Before a revision retires, its answers also carry Deprecation and Sunset headers.

After the end date, Truvo refuses the revision. A request that names it gets 400 invalid_version, and the message names the last day that Truvo served it and the revision to send. Truvo never answers a retired revision with the fields of another revision.

Answers in the current revision

A 404, and a refusal that Truvo sends before it knows your revision, use the current revision. Those refusals are a 401, a 413, a 429 for failed authentication, and a 400 invalid_version. Each of these answers names the current revision in Truvo-Version.

These answers can’t follow your revision, so the top level of the error envelope stays compatible from one revision to the next: error.code, error.message, error.retry_action, error.doc_url, and request_id.