API versioning
API versioning
Section titled “API versioning”Sencai’s backend API is versioned under the /api/v1/ namespace. This page explains what counts
as a breaking change, how long deprecated paths stay alive, and how to migrate existing
integrations.
Namespaces
Section titled “Namespaces”| Path | Status | Notes |
|---|---|---|
/api/v1/* | Current, recommended | Canonical versioned path. Identical behaviour to /api/* today — it is a transparent alias in front of the same routes/controllers, not a separate implementation. |
/api/* | Deprecated, still supported | Kept as a backward-compatible alias so existing integrations are not broken. Every response carries a Warning: 299 header. Not redirected (no 301) and not removed — this is additive. |
Every response from either path carries:
X-API-Version: 1Deprecation: falseDeprecation: false refers to the current API version (v1) itself — v1 is not deprecated.
Only the un-versioned /api/* path is deprecated in favour of /api/v1/*, which is why the
Warning header is scoped to that alias specifically.
Example response from the deprecated alias:
HTTP/1.1 200 OKX-API-Version: 1Deprecation: falseWarning: 299 - "Deprecated path /api, use /api/v1"Sunset: Wed, 01 Oct 2026 00:00:00 GMTAPI Manager (api-manager, port 3200)
Section titled “API Manager (api-manager, port 3200)”The same pattern applies to the API Manager service, which issues Strapi API tokens to other microservices:
| Path | Status |
|---|---|
POST /v1/token/:service, /v1/admin/* | Current, recommended |
/api/token/:service, /api/admin/* | Deprecated alias — still works, carries a Sunset header |
Deprecation-header behaviour is not identical between the two services. Strapi’s legacy
alias middleware sends X-API-Version / Deprecation / Warning / Sunset only — it does not
send a Link header. API Manager’s versioning middleware, when a deprecated version policy
applies, additionally sends a Link: <migration_guide_url>; rel="deprecation" header pointing
at the migration guide, sourced from the matching api-version-policy record. If you build
tooling that parses deprecation headers generically across both services, do not assume a
Link header is present on every deprecated response — check per-service.
Breaking vs non-breaking changes
Section titled “Breaking vs non-breaking changes”Non-breaking (safe to ship without a version bump):
- Adding a new optional field to a response body
- Adding a new endpoint
- Adding a new optional query parameter
- Relaxing a validation rule (accepting previously-rejected input)
- Adding new enum values to a field that is documented as “open” / extensible
Breaking (requires a new version, e.g. /api/v2/):
- Removing or renaming a response field
- Removing or renaming an endpoint
- Changing a field’s type (e.g.
string→number) - Making a previously-optional request field required
- Changing the meaning/semantics of an existing field
- Changing authentication/authorization requirements on an existing endpoint
- Changing default pagination/sort behaviour
If a change is breaking, it ships under a new version prefix (/api/v2/) while /api/v1/
continues to serve the old behaviour until its own sunset date — the same policy documented here
applies to every future version.
Versioning SLA (deprecation timeline)
Section titled “Versioning SLA (deprecation timeline)”-
The un-versioned
/api/*alias is deprecated but has no fixed removal date announced yet — it is tracked via theSunsetresponse header, which is computed from theSUNSET_DATEenvironment variable (ISO date, e.g.2026-10-01) on both the Strapi backend and API Manager. -
If
SUNSET_DATEis not configured, it defaults to 90 days from process start — i.e. the minimum guaranteed notice period before an alias could be sunset is 90 days. -
Reaching the
Sunsetdate does not mean the alias stops working automatically — sunset dates are operational targets, communicated in advance via this header, release notes, and a direct email notification. -
The email notification is sent automatically the moment an admin sets or changes a policy’s
deprecated_atorsunset_atdate (not only once the date has already passed) — every active Owner/Admin across every organisation on the platform receives it, including the effective date and a link to the migration guide when one is configured. This is a best-effort side channel on top of theSunset/Warningheaders, not a replacement for checking them — a failed email dispatch never blocks the policy change itself. -
Organisations with a customer webhook subscribed to
api.version.deprecatedorapi.version.sunsetalso receive the same lifecycle change over that channel. -
Actual removal is a deliberate, separately-announced change.
-
Check the live
Sunsetvalue at any time:Terminal window curl -sI https://api.sencai.space/api/organisations | grep -i sunset
How to migrate
Section titled “How to migrate”Migrating from /api/ to /api/v1/ requires no functional changes — only a base URL update:
- Find every place your integration builds a request URL against the Strapi backend
(
https://api.sencai.space/api/...or the local dev equivalent). - Replace the
/api/prefix with/api/v1/— request/response shapes, authentication (Authorization: Bearer <JWT>), and status codes are unchanged. - Re-run your test suite / smoke tests against
/api/v1/*to confirm parity. - Once migrated, you can safely ignore the
Warning/Sunsetheaders, since your integration no longer hits the deprecated alias.
Example:
GET https://api.sencai.space/api/organisationsGET https://api.sencai.space/api/v1/organisationsFor services using API Manager to fetch Strapi tokens:
GET http://api-manager:3200/api/token/git-connectorGET http://api-manager:3200/v1/token/git-connectorNo other change is required — the /api/v1/* namespace is a transparent alias, not a rewrite of
the underlying implementation, so behaviour is identical to what /api/* already returns today.
Implementation note
Section titled “Implementation note”This versioning scheme was implemented as F3.API.01:
sencai.space:src/middlewares/api-version.ts(+src/middlewares/__tests__/api-version.test.ts)api-manager:src/middleware/api-versioning.ts