Skip to content

Versioning

This content is not available in your language yet.

The public API is versioned in the URL path: every route lives under /api/v1/.... This is currently the only version.

  • We only ever add fields, endpoints, and event types to v1 — additive, non-breaking changes ship without a version bump.
  • A genuinely breaking change (removing a field, changing a field’s type or meaning, removing an endpoint) ships as a new version (/api/v2/...), never as an in-place change to v1.
  • v1 will keep working, unannounced-breaking-change-free, for as long as it is not formally deprecated (see below).

When we do deprecate a route or an entire version, we announce it ahead of the shutdown date and mark every response from the deprecated route with two RFC 8594 headers:

HeaderMeaning
Deprecationtrue, or an HTTP-date marking when the route became deprecated
SunsetAn HTTP-date — the route stops being served after this date
Link: <url>; rel="deprecation"Optional — a link to the migration guide for the deprecated route
HTTP/1.1 200 OK
Deprecation: true
Sunset: Wed, 01 Apr 2026 00:00:00 GMT
Link: <https://docs.clienta.ai/api/migration-v2>; rel="deprecation"

We give a minimum notice window before any Sunset date takes effect; the exact window is stated in the deprecation announcement itself, since it depends on how disruptive the specific change is.

Every response — success or error — carries a Request-Id header. Include it when contacting support about a specific request; it is the fastest way for us to find the exact request in our logs.

Request-Id: 1f2e4b6a-9c3d-4a11-8b7e-6d5f0a1c2b3d

Every error response (any non-2xx) from /api/v1 uses the same JSON shape:

{
"error": {
"type": "VALIDATION_ERROR",
"message": "Invalid request. Please check your input and try again.",
"requestId": "1f2e4b6a-9c3d-4a11-8b7e-6d5f0a1c2b3d"
}
}

requestId always matches the Request-Id response header for that same response.

List endpoints use cursor-based pagination — never page numbers or offsets, which shift under concurrent writes.

GET /api/v1/conversations?limit=20
{
"success": true,
"data": [ /* ... */ ],
"nextCursor": "eyJjcmVhdGVkQXQiOiIyMDI2LTA3LTE2VDA0OjAwOjAwLjAwMFoiLCJpZCI6ImNvbnZfMTIzIn0"
}
  • limit defaults to 20 and is clamped to a maximum of 100 — an out-of-range value is silently clamped, never rejected.
  • Pass the previous response’s nextCursor as the cursor query parameter to fetch the next page.
  • nextCursor is null on the last page.
  • A cursor is an opaque, base64url-encoded token — don’t parse or construct it yourself; a corrupted/tampered cursor is rejected with 400 VALIDATION_ERROR rather than silently resetting to page one.