Skip to content

API Changelog & Versioning Policy

Coalex exposes a single stable API surface under /v1/. We do not cut new URL versions (/v2/) for evolutionary changes. Backward compatibility is preserved through field aliasing and a deprecation window, so a customer on an older SDK keeps working when the platform evolves.

How it works

  • Breaking parameter/response changes keep the old name working for at least one full minor version before removal.
  • When a request uses a deprecated alias, the response carries an X-Deprecation header describing the change and its removal version.
  • The SDKs read X-Deprecation and emit a warning — Python warnings.warn, TypeScript console.warn — so you're notified without anything breaking.
  • Every SDK request sends X-SDK-Version (e.g. coalex-python/1.13.0, coalex-ts/1.14.0), which the platform logs (sdk_version) so we can see which customers are on older SDKs before removing anything.
  • The proxy forwards both headers transparently (no allow-list), so this works end-to-end without per-header wiring.

Current deprecations

Since Endpoint Deprecated Use instead Removal
v1.0 POST /v1/evaluate trace_id request_id Not scheduled — see below

evaluate() accepts trace_id as an alias for request_id. A request that sends trace_id (and not request_id) gets:

X-Deprecation: trace_id->request_id; removal=v1.1

This removal did not happen, and the date was wrong to publish

This row said v1.1. The Python SDK is now at 1.32.0 and the TypeScript SDK at 1.21.0, the alias is still accepted, and the platform still falls back to treating the value as a trace id (routes/evaluate.py). A removal date that passes twenty times over is worse than no date: it tells a customer to migrate by a deadline that was never enforced, and tells us the field is gone when it is not.

The column now says what is true. Rule 3 below is the one that governs it: the field comes out when sdk_version traffic says nobody is still sending it, and the date goes back in this table in the same change that schedules it.

Migrate to request_id regardless — it is the canonical name and the only one the SDKs send. The Python and TypeScript SDKs accept trace_id only as a deprecated keyword argument and emit a client-side warning when you use it.

Policy

  1. No silent breakage. A removed field yields a clear 422 naming the replacement — never a silent failure or a "worked yesterday" surprise.
  2. One-minor-version window. A field goes deprecated → removed across at least one full minor version.
  3. Observability first. We watch sdk_version in logs and do not remove a field while meaningful traffic still uses the old shape.

Adding a deprecation (for contributors)

  1. On the Pydantic request model, accept the old name via Field(validation_alias=AliasChoices("new", "old")) + a model_validator(mode="before") that records the alias in a deprecations list.
  2. In the route, set response.headers["X-Deprecation"] when body.deprecations is non-empty.
  3. Add a row to the table above with the removal version.