API changelog · current version 2026-08-22
What changed, when, and how much warning you get.
Additive changes ship without a version bump. A breaking change is announced here, marked deprecated in the specification with a Sunset date at least 180 days out, and only then removed. Nothing is removed without appearing on this page first. The one exception is a change that closes a security gap, which can take effect at once; it is listed here as breaking, with the reason.
2026-11-01includes a breaking change · version 2026-08-22- Changed (breaking) — Every API key is bound to one brand. A key issued without a brand (brand binding was optional for sandbox keys under 2026-08-12 and 2026-08-22) no longer authenticates and is answered 401 unauthenticated, like an unknown key. This took effect without the usual notice period because a key bound to no brand cannot be limited to one brand's data. The Developer Center marks such a key stopped: create a new key bound to the brand with the same scopes, move your integration to it and revoke the old one.
- Added — Headless Connect, for brands that run their own site: your site sells, your Ambition-hosted care site does care. Every endpoint below is in the contract, the reference and the OpenAPI document, and each guide's status block says what runs there. This release is deployed only after all of its database changes are applied, so the endpoints you already use keep answering as before; a new endpoint whose feature is not yet open on a deployment answers 503 with an *_unavailable code.
- Added — GET /catalog/{brand}/programs, /catalog/{brand}/programs/{handle} and /availability?state= — the public brand catalog: opaque program handles, the approved offer exactly as the care site bills it, the disclosure digest and per-state availability. No key; cacheable, with Access-Control-Allow-Origin *. GET /programs serves the same document to a key with catalog.read.
- Added — GET /catalog/{brand}/disclosures — every required disclosure block with its digest and verbatim text, and a sanitized HTML fragment. POST /claims/scan accepts requiredDisclosures and reports each present or missing.
- Added — POST /enrollments, GET /enrollments and GET /enrollments/{id} — server-to-server enrollments under a brand-bound key (enrollments.write, enrollments.read). Creation returns a single-use, 30-minute launch link to the care site; a replay with the same Idempotency-Key returns the same enrollment with a fresh link. Coarse status is treated as health information and reads in_progress without the brand's business associate agreement and downstream-systems attestation.
- Added — POST /sandbox/enrollments/{id}/simulate — sandbox keys only: stand in for the clinician and move a test enrollment to approved, needs_info, not_approved or canceled.
- Added — Webhook events enrollment.created, enrollment.status_changed (gated by the business associate agreement and downstream-systems attestation), subscription.created, subscription.canceled and payment.failed. Commerce payloads (commerce.v2) add the enrollment id and your externalReference, sent only to a receiver whose registrar passes the same business associate agreement and attestation gate as enrollment.status_changed; every other receiver, and every event recorded earlier, gets commerce.v1. Branch on schemaVersion. The OpenAPI document has a webhooks section rendered from the event registry.
- Changed — Webhook delivery: up to five active receivers per connection and environment, each sent every event it subscribed to, and registering a receiver no longer pauses the current one. A delivery gets 19 attempts over at least about 74 hours; every 4xx except 410 is retried, and a 410 disables the receiver.
- Changed — One error envelope with a request_id on every v1 answer, the Ambition-Version request header to pin a dated version, reserve-first idempotency, and a per-key write budget in addition to the request budget.
- Added — Live keys use the ak_live_ prefix and are issued only through governed production access on the live deployment. They are not available yet.
2026-08-22version 2026-08-22- Added — POST /pharmacy/callbacks/{partnerId} — a partner-only status endpoint with raw-body HMAC, five-minute replay protection, stable event identity, strict chronology, and immutable receipts. It returns 202 only after the event is durably accepted for application or identified as a replay.
- Changed — The authentication description now distinguishes scoped developer keys, first-party console sessions, and versioned pharmacy partner signatures.
2026-08-12version 2026-08-12- Added — GET /formulary and GET /formulary/{slug} — the platform's published position on every substance, with the provision that governs it and, for a refusal, the reason in plain language. Public and unauthenticated; alias lookup resolves brand names to their substance.
- Added — GET /rulebook — every marketing-claim rule the platform enforces, with its citation and reasoning. Published so the gate can be audited rather than discovered at publish time. Rule patterns are deliberately omitted.
- Added — POST /claims/scan — evaluates copy against the same engine and the same rulebook version that gates publication, so a result here is the result you get at launch. Requires the claims.scan scope.
- Added — Self-serve API keys. Sandbox keys are created in the console with no sales contact; only a SHA-256 digest is stored, and the secret is shown once. Production keys are not available until production launch is approved; a workspace's launch readiness page shows what that needs.
- Changed — The OpenAPI document at /api/v1/openapi is now rendered from the same Zod schemas the handlers validate with, rather than maintained by hand. It can no longer describe a shape the API does not enforce.
2026-08-09version 2026-08-09- Added — POST /sandbox/orders — deterministic synthetic order previews with Idempotency-Key replay. Nothing is prescribed, transmitted, or charged.
What counts as breaking
Removing an endpoint or a response field; narrowing an accepted input; adding a required request field; changing an error code; or changing the meaning of an existing field. Adding an endpoint, an optional input, a response field, or a new enum member in a response is not breaking — clients must ignore fields they do not recognise.