Versioning and compatibility
API v3 evolves along four independent axes. A release can change one of them without touching the others, and you track each one through a different channel.
The four axes
| Axis | Where it appears | Changes when |
|---|---|---|
| Major route version | /api/v3 in the path | The contract changes in a breaking way. v4 ships with its own OpenAPI document, and v3 keeps being served until the Sunset date of each operation |
| Contract release | X-Cademi-Release on every response, info.version in the OpenAPI document, the release field of GET /capabilities | Every compatible release: a minor release adds an operation, field, or enum value; a patch release fixes text or documentation without changing the shape |
| OpenAPI document format | openapi: 3.1.0 at the top of the document | The OpenAPI specification version used to describe the API. It is not an API version |
| Event version | version in the event envelope, next to type | The shape of the event payload changes. A webhook destination pins payload_version and receives events in the version it subscribed to |
Compatible changes
These changes fit within the same major version (3.x) and do not break existing integrations:
- a new operation;
- a new optional request field;
- a new response field;
- a new value in an enum marked
x-extensible: true(treat unknown values as opaque); - a new filter, a new header, or relaxed validation;
- a new error code under an already documented status.
Example: a resource response gains a new field. Clients that already read the JSON keep working, because nothing they received before is missing.
{
"id": "prd_01J9X8Y7Z6A5B4C3D2E1F0G9H8",
"object": "product",
"name": "Curso de Marcenaria",
"status": "published",
"visibility": "public"
}Breaking changes
These changes only ship in v4:
- removing or renaming an operation, field, parameter, or enum value;
- changing the type, format, or meaning of a field;
- making an optional field required;
- changing the HTTP status or the
codeof an already documented case; - changing the default ordering of a list;
- lowering a limit (page size, batch size, upload size);
- adding a value to an enum marked
x-extensible: false.
Example: renaming name to title in the same response breaks every client that reads name. A change like this only exists under another major version, never within /api/v3:
{
"id": "prd_01J9X8Y7Z6A5B4C3D2E1F0G9H8",
"object": "product",
"title": "Curso de Marcenaria",
"status": "published"
}Each enum declares its policy in the OpenAPI document. Closed enums (x-extensible: false) include state enums such as publication status, operation.status, and credential.status, as well as format and denial_reason. Open enums (x-extensible: true) include event type and operation type, and can gain new values without breaking your client.
Runtime deprecation
An operation scheduled for removal gets at least six months of notice before it stops responding:
- the OpenAPI document marks the operation with
deprecated: true,x-cademi-deprecated-at(the announcement date), andx-sunset(the cutoff date); - every response from that operation includes these headers:
Deprecation: @1798761600
Sunset: Thu, 01 Jul 2027 00:00:00 GMT
Link: <https://api.cademi.com.br/docs/deprecations>; rel="deprecation"GET /capabilitieslists deprecated operations indeprecations[]:
{
"data": {
"object": "capabilities",
"release": "3.2.0",
"deprecations": [
{
"operation_id": "products.legacy_export",
"deprecated_at": "2027-01-01",
"sunset_at": "2027-07-01"
}
]
}
}- between the announcement and the cutoff, the operation keeps responding normally;
- after the
Sunsetdate, the operation stops executing and returns410with the error code below.
Errors
| Code | Status | When |
|---|---|---|
operation_sunset | 410 | The operation was called after its announced Sunset date |
No /api/v3 operation is deprecated at this time. This section describes the process that applies once one is.
Versioned events
Each release publishes, alongside the OpenAPI document, the catalog of public events at that point (type, version, visibility, and payload keys). A published event never changes shape without a new version: removing or renaming a field, or changing its visibility, produces a new version of the same type.
An event delivered to a webhook destination is always the JSON recorded when the event occurred, never rebuilt from the current payload shape. Replaying an older event (POST /webhooks/{id}/replays, GET /events/{id}) returns exactly what was recorded, in the version it was recorded in. Each webhook destination pins payload_version when you register it and receives events in that version. See Webhooks and Events.
Tracking changes
- The changelog for each release describes what changed and what you need to do (nothing, for compatible changes).
- The
X-Cademi-Releaseheader on any response tells you which release served the call. GET /openapi.jsonalways serves the document for the latest published release, never an earlier one.GET /capabilitiesreturnsreleaseanddeprecations[], so your integration can track both programmatically without reading the changelog.
Version boundaries
API v3 runs on the same host as the legacy APIs (/api/v1, /api/v2, /api/third), but credentials from one are not valid on the other:
- a v3 credential secret (
ck_live_…/ck_test_…) sent to/api/v1,/api/v2, or/api/thirdis rejected with401; - a legacy authentication token sent to
/api/v3is rejected with401 unauthenticated; - a signed-in administrator session does not authenticate requests to
/api/v3. Calls to v3 always require an API credential. See Authentication.
Compatibility matrix
One row per published v3 release. No operation was removed or changed in a breaking way between them: each release only added.
| Release | Date | What it added | CLI |
|---|---|---|---|
| 3.0.0 | September 22, 2026 | Contract foundation: credentials and access policy, the HTTP request pipeline and base resources, the OpenAPI document, idempotency and concurrency control, asynchronous batch operations, file uploads, public events, auditing and usage limits, sandbox and reproducible scenarios | no client published |
| 3.1.0 | September 22, 2026 | Showcases, banners, and navigation; products and modules; lessons, content, and taxonomies; users, tags, and custom fields; appearance, security, email, and profile settings; administrators and credential governance; webhooks (destinations, deliveries, and replays) | no client published |
| 3.2.0 | September 23, 2026 | Enrollments, release rules, and progress; exams, questions, and results; certificates and legal terms; support tickets; sales, deliveries, and gateway integrations; gamification, points, and rankings; funnels, triggers, and automations; account domains and replicas; imports, exports, and reports; validation plans and batch application | no client published |
| 3.3.0 | September 23, 2026 | No new operations. Replica behavior: publishing a product or module through the API also publishes its copies in replicated accounts; replicated products, modules, showcases, and banners accept status in PATCH; copies from or to a replica, new modules in a replicated product, and lessons moved to a replicated product return 403 replica_readonly; the showcase deletion description was corrected (the showcase's products are deleted with it). | no client published |
| 3.3.1 | September 24, 2026 | No new operations. The OpenAPI document groups its tags with the x-tagGroups extension, used by documentation tools to organize the navigation. | no client published |
| 3.3.2 | September 24, 2026 | No new operations. The Sales, Account, and Settings tags are split into smaller resource tags, and x-tagGroups gains separate Account and Settings groups. Operation IDs and paths are unchanged. | no client published |