Changelog
Version history for the CollectiveX Health partner API.
We follow Semantic Versioning:
- Major (
2.0.0): breaking changes — partners must update. - Minor (
1.1.0): additive changes, backwards-compatible. - Patch (
1.0.1): bug fixes, no contract change.
Version applies to the OpenAPI contract at docs.collectivex.health/api. The model_version field in response bodies is a separate opaque string — don't parse it; it changes on recommendation-engine updates that don't affect the wire contract.
v0.2.0 — 2026-05-05 (sandbox alpha)
Field-shape and error-envelope refinements based on alpha-partner feedback. Contains breaking changes — review the migration notes before pulling.
Breaking changes
Citationwire shape (v2). Each entry inrecommendation.citations[*]now carries exactly six fields:{citation_id, source_title, authors, year, doi, relevance}.title→ renamed tosource_title.cohort_relevance→ renamed torelevance.pdf_urlremoved. There is no replacement; signed-URL infrastructure is out of scope for sandbox alpha.
personal_inforequest shape clarified. The top-levelpersonal_infoblock previously listed in the docs was never accepted by the gateway. The documented path is nowoura.personal_infoonly — see request/response reference. Wire behavior is unchanged (top-level keys were silently dropped before), but client code should targetoura.personal_infogoing forward.
Added
503 Service Unavailable. Transient infrastructure failures (mid-deploy cutovers, upstream cold-start) now returnHTTP 503with the standard{request_id, trace_id, error: {code, message, details}}envelope (error.code: service_unavailable) and aRetry-After: 2header, instead of being collapsed into500. See errors.500is now reserved for genuine logic errors and should not be retried.
Fixed
citation.doiis nevernull. Citations whose underlying source had no DOI are suppressed before serialization. Every returnedrecommendation.citations[*]entry has a non-emptydoi.- Recommendation copy no longer restates wearable capabilities. For the
cxh-sandbox-ourapartner, recommendations are tailored toward wearable-actionable behavior changes and no longer restate that the device captures HRV / sleep / readiness / skin temperature.
Migration notes
- Rename Citation fields in your client:
title→source_title,cohort_relevance→relevance. Remove any code path that readspdf_url. - If your retry policy treats every
5xxthe same way, split it: retry on503(respectRetry-After), surface500to operators. - If your request body sets a top-level
personal_infokey, move its contents underoura.personal_info.
v0.1.0 — 2026-04-28 (sandbox alpha)
Initial public release. Sandbox only — prod cutover is a later milestone.
Endpoints
POST /v1/TENANT/recommendation— cycle-aware wellness recommendation grounded in raw partner biomarkers (HRV, heart rate, sleep stages, VO₂ max, readiness, SpO₂).
Contract
- Authentication via Zuplo-minted API keys (
ApiKey/Bearerheader). - Rate limit: 30 req/min per key.
- Idempotency: 5-minute Redis cache on
(client_id, request_id). - Pure-metrics-only body contract — vendor aggregate scores silently dropped.
- Two safety modes:
strict(rejects clinical queries) /permissive(processes all wellness queries). - Two response shapes: Shape A (explicit query → recommendation primary) / Shape B (implicit trigger → suggested_questions primary).
- Three suppression reasons:
below_platform_threshold,below_client_threshold,insufficient_signal.
Envelope shapes
200,422,500,502: flat{request_id, trace_id, error: {code, message, details}}envelope (success responses have the recommendation shape; error responses use the flat envelope for errors).401,403(gateway + consent): FastAPI-default{detail: "<reason>"}shape.429: Zuplo-emitted body withRetry-Afterheader.
Deprecation policy
Fields and endpoints are never removed without a deprecation window.
How we signal deprecation
- Documentation — the deprecated field or endpoint is marked in these docs and in the auto-generated OpenAPI reference.
- Sunset header — when a response returns content whose schema is scheduled for removal, we include a
SunsetHTTP response header with the planned removal date in HTTP-date format:Code - Changelog entry — an entry in this file announcing the deprecation, the planned removal date, and the replacement path (if any).
Minimum notice period
30 calendar days between the first Sunset-header emission and the actual removal. We aim for 90 days for anything load-bearing.
What counts as a breaking change (major version bump required)
- Removing a field from a request or response body.
- Changing a field's type (
int→string, enum contraction). - Removing an endpoint.
- Changing an error code's HTTP status.
What does NOT count as a breaking change (minor bump ok)
- Adding a new optional field to a request.
- Adding a new field to a response body (you're expected to ignore unknown fields).
- Adding a new value to an enum (you're expected to handle unknown values gracefully).
- Adding a new endpoint.
- Adding a new error code within an existing HTTP status.
- Performance improvements, bug fixes.
Your side of the contract
Forward-compatibility requires partner cooperation:
- Ignore unknown fields in response bodies. We reserve the right to add non-breaking fields (e.g.
warnings, new citation metadata). Your parser must not fail on unknown keys. - Don't assume enum closedness. We may add
cycle_phasevalues (e.g.unknown) without a major bump, but we'll document it in the changelog. Handle unknown enums gracefully (fall back to a safe default in your UI). - Honor
Sunsetheaders. If you see one, plan the migration before the date.
Versioning anti-patterns (what we won't do)
- No URL versioning for trivial changes. We won't bump to
/v2/TENANT/...for an additive field./v1/is the stable path; non-breaking changes ship in place. - No silent contract changes. Anything that could break partner code gets a major version + a Sunset window. If you suspect silent drift, raise it in support.
- No "v1.1.0" URL prefixes. Minor/patch versions are documentation-only — they don't affect the route path.