API marks a change to the reference surface, Behavior a change to how an endpoint acts, Docs a guide or clarification. Breaking means you must act; Additive means nothing you already built will break.
One timeline, newest first. Entries tagged API are generated automatically from a diff of the published OpenAPI contract — they appear here when a release carrying the change reaches the test environment, so the reference matches the newest staging release, with each operation linking to its page in the API reference. Guide and behavior notes are authored alongside the change that ships them. Both kinds share a single reverse-chronological list, so the most recent change is always at the top.
Added
PUT /v1/account/brands/{brand_id}/offerings/{offering_ref}/billing-cadence— setOwnBillingCadence
POST /v1/account/brands/{brand_id}/starter-merchandising— adoptStarterMerchandising: response field added: data.cadence_auto_set (optional)
Changed
POST /v1/instrument/abandon— abandonInstrument: response field added: patient_readiness (optional)POST /v1/account/question-library/questions— createQualificationLibraryQuestion: response 400, 404, 422, 503 field added: prescriber_case_id (optional)DELETE /v1/account/question-library/questions/{question_id}— deleteQualificationLibraryQuestion: response 404, 503 field added: prescriber_case_id (optional)POST /v1/account/offerings/{offering_ref}/qualification— forkQualificationQuestion: response 400, 404, 409, 422, 503 field added: prescriber_case_id (optional)GET /v1/account/brands/{brand_id}/config— getAccountBrandConfig: response field added: data.consent_holder (optional); response field added: patient_readiness (optional)GET /v1/account/brands/{brand_id}/readiness— getCommerceAccountBrandReadiness: response field added: data.offerings.rows[].lifecycle (required)GET /v1/account/brands/{brand_id}/storefront— getCommerceAccountBrandStorefront: response field added: data.pricing.copy (optional); response field added: data.readiness.offerings.rows[].lifecycle (required)GET /v1/account/question-library/facts— getQualificationLibraryFacts: response 400, 404 field added: prescriber_case_id (optional)GET /v1/account/offerings/{offering_ref}/qualification— getQualificationOverlay: response 400, 404, 503 field added: prescriber_case_id (optional)POST /v1/account/question-library/minted-facts— mintQualificationFact: response 400, 422, 503 field added: prescriber_case_id (optional)POST /v1/instrument/next— nextInstrument: response 200, 422 field added: patient_readiness (optional)POST /v1/account/offerings/{offering_ref}/qualification/publish— publishQualificationOverlay: response 400, 404, 422, 503 field added: prescriber_case_id (optional)DELETE /v1/account/offerings/{offering_ref}/qualification/questions/{question_id}— removeQualificationOverlayQuestion: response 404, 503 field added: prescriber_case_id (optional)PUT /v1/account/offerings/{offering_ref}/qualification/order— reorderQualificationOverlay: response 400, 404, 422, 503 field added: prescriber_case_id (optional)GET /v1/instrument/resolve— resolveInstrument: response field added: patient_readiness (optional)PUT /v1/account/brands/{brand_id}/config— setAccountBrandDisplay: request field added: consent_holder (optional); request field added: legal_documents (optional); response field added: data.consent_holder (optional)PATCH /v1/account/question-library/questions/{question_id}— updateQualificationLibraryQuestion: response 400, 404, 422, 503 field added: prescriber_case_id (optional)PATCH /v1/account/offerings/{offering_ref}/qualification/questions/{question_id}— updateQualificationOverlayQuestion: response 400, 404, 422, 503 field added: prescriber_case_id (optional)
You can now choose how members are billed for each of your offerings.
PUT /v1/account/brands/{brand_id}/offerings/{offering_ref}/billing-cadence
takes {"billing": "monthly"} or {"billing": "upfront"}. Only a cadence that suits the
offering’s supply is accepted, and a refusal lists the cadences you can choose. The shipping
cadence always follows the offering’s supply and is never set by you.When only one billing cadence suits an offering, the platform sets it for you when the offering
is enabled and already has its copy, or when its copy is adopted, whichever comes first, so most
offerings need no call. Your readiness report now shows a
cadence_compatible check per offering. Previously billing terms were confirmed by your
onboarding contact; see Before a price is payable.Added
GET /v1/account/brands/{brand_id}/offerings— listAccountBrandOfferings
Changed
POST /v1/instrument/next— nextInstrument: response added: 402GET /v1/instrument/resolve— resolveInstrument: response added: 402
The test environment has moved to new hosts, and the guides named the old API base. Use the
PURPLE_API_BASE value your welcome kit states: your key works only on the environment it was
issued for. The API reference’s playground now sends its requests to the same test environment.Environments now lists the test environment’s hosts in one place: the API
base, your member portal address and the hosted sign-in page. It also says that custom sign-in
domains are not live in the test environment; see
Login URLs and domains. Every example still reads its
base from $PURPLE_API_BASE.Changed
GET /v1/account/brands/{brand_id}/storefront— getCommerceAccountBrandStorefront: response field added: data.pricing.offering.renewal_interval_days (optional); response field added: data.pricing.offering.shipping_interval_days (optional)
GET /v1/onboardings/{onboarding_id}/progress
is now callable with your API key, for your own onboarding. Send your key and X-Brand-Id set to
one of your brands. The answer says which step you are on out of how many, what is waiting on you,
and, when your onboarding has a LegitScript step, each update’s date and meaning.Another client’s id answers 404, exactly as an id that does not exist, so the API never confirms
whether another client’s onboarding exists.This replaces the 2026-10-10 note below: you no longer need to remove the call or ask your
onboarding contact. See the Onboarding timeline.Changed
GET /v1/onboardings/{onboarding_id}/progress: parameter added: ref:#/components/parameters/BrandIdHeader; response added: 400; response added: 401
The onboarding progress answer can now show where your LegitScript certification stands.
GET /v1/onboardings/{onboarding_id}/progress
gains an optional legitscript_timeline object. It is present when your onboarding includes the
LegitScript step, and absent otherwise.stateisokwhen the certification record was read, orunavailablewhen it could not be read right now. Anunavailabletimeline has no entries; read again later.entrieslists every recorded update, oldest first. Each hasat, the time of the update, andmeaning, what it means in plain words, such as an application status change or a certification granted or lost. There are no vendor status codes and no staff notes.
200 answer of this read. Nothing you already built changes.The
therapy filter accepts two more values.
GET /v1/account/question-library/facts
now accepts therapy=anti_aging_nad_injection and therapy=pt_141. Every value it accepted
before still works. A therapy appearing in this list says what you can author questions for. It is
never a statement of medical readiness.The error body shared by your pricing and starter-merchandising writes declares a new optional
field,
adoption. It summarises a staff catalog import and is set only on refusals from staff
catalog-mapping writes. An error from
PUT /v1/account/brands/{brand_id}/pricing
or
POST /v1/account/brands/{brand_id}/starter-merchandising
does not carry it. Nothing you already built changes.A refusal from the qualification authoring operations can now carry an optional
code. It
appears only when a refusal shares its type with another condition and needs a finer name, for
example decision.bundle_intake_disagrees or decision.bundle_unknown. Branch on type first and
read code only to tell those apart. This applies to every question-library and offering
qualification operation, such as
POST /v1/account/question-library/questions
and
POST /v1/account/offerings/{offering_ref}/qualification/publish.Your brand’s display identity takes an optional
support_phone.
PUT /v1/account/brands/{brand_id}/config
accepts display.support_phone, written as it should be displayed: digits, with an optional
leading +, spaces, parentheses, dots and hyphens, at most 32 characters. A malformed value is
refused with 422. The member support page offers it as a one-tap call. Both that write and
GET /v1/account/brands/{brand_id}/config
return it as data.display.support_phone. Leave it out and nothing changes.Refusals from the qualification authoring operations name more of what went wrong as data, so
you can word them without parsing
message. All new fields are optional, and message is
unchanged.required_role, on a role refusal (403): the least role that may make the write,adminorstaff.issues[].already_asked, onquestion.fact_already_askedandquestion.ask_again_alias_only: the question that already asks the fact, with its section and the prompt a member sees.issues[].missing_values, onquestion.ask_again_options_incompletewhen the fact is a list of options: the option codes your question does not offer. When the fact is free text, a number or a date,issues[].value_typenames its type instead.issues[].refresh_policy, onquestion.ask_again_suppressedandquestion.ask_again_collects_blank: the fact’s refresh policy, which says why the question is not shown as a confirm.
PATCH /v1/account/question-library/questions/{question_id}
and
PATCH /v1/account/offerings/{offering_ref}/qualification/questions/{question_id}.A question can now show the unit its answer is in. The question node returned by
GET /v1/instrument/resolve,
POST /v1/instrument/next
and
POST /v1/instrument/abandon
can carry an optional node.unit, for example in or lb. Show it beside the prompt. When it is
absent, show no unit and never guess one. It is display text only.Qualification authoring refusals say more, as data. All new fields are optional:landed_first, on a stale-edit conflict (409): the change that landed before yours, with who made it, when, and what it was. Itsactioncan beset_create,set_rename,set_remove,set_move,question_add,question_edit,question_removeorquestion_reorder. Whensourceiscurrent_pointer, only the most recent author is known.issues[].readers, onremove.answer_has_readersandwhen.answer_has_readers: the rule, condition or display that still reads the answer, as akindand anidyou can look up in the content you already hold.
Changed
POST /v1/payments/checkout-sessions— createCommerceCheckoutSession: parameter added: ref:#/components/parameters/CommerceHeldCapability
BehaviorBreaking
Starting a checkout session now requires proof that the caller holds the enrollment
Naming an enrollment is no longer enough to buy against it.
The answer is the same whether the enrollment exists, belongs to another patient, or does not
exist. Nothing is created, no payment is attempted, and your
POST /v1/payments/checkout-sessions
now refuses any create that does not prove it holds the enrollment named by its journey_id.
The proof is the enrollment’s capability, sent on the new x-held-capability request header.
Only the hosted checkout sends it: on a checkout-first offering it holds the capability
POST /v1/prospects returned to its own server, and on a questions-first offering it holds the
one your storefront handed over through
the form POST to the checkout door.A create without a capability, or with one that does not match that enrollment and brand, is
refused with 404 and this body:Idempotency-Key is not used up.
Every create carries a journey_id, so every create needs the capability. No create is exempt.This change does not alter the hosted checkout. Where the hosted checkout holds the
capability, it sends it on the patient’s behalf.What you must do: if your server calls POST /v1/payments/checkout-sessions with a bare
journey_id, that call now answers 404. Remove it and let the hosted checkout create the
session: link a checkout-first patient to it, and hand a questions-first patient over with the
form POST described in
handing the patient to checkout.
See also the checkout door and
pricing.A questions-first checkout no longer opens from a link carrying
journey_id. Naming an
enrollment does not prove it belongs to the patient in the browser, so the checkout refuses it.
Instead:- the
POST /v1/instrument/nextresponse whose answer completes the questionnaire now carriesdestination_capability, a one-time checkout pass that lasts about 10 minutes. It is returned only to a session your server started fresh with your secret key, and never on a resumed session. A later call on a session that is already complete returns none. If the platform redelivers the completion internally, the pass is minted fresh, never a stored copy served again. Aphase=qualificationcompletion does not carry one yet; - your storefront hands the patient over with a top-level form POST to
https://{MEMBER_HOST}/api/checkout/door, with the pass in thecapabilityfield and youroffering_refbeside it. The door checks the pass and sends the patient to checkout; - the POST must come from a page on one of your brand’s registered browser origins. Any refusal is the same plain not-found.
Changed
DELETE /v1/account/brands/{brand_id}/domains/{kind}— removeAccountBrandDomain: response added: 502
Changed
PUT /v1/account/brands/{brand_id}/domains/{kind}— setAccountBrandDomain: response added: 502
Changed
POST /v1/account/brands/{brand_id}/starter-merchandising— adoptStarterMerchandising: parameter added: ref:#/components/parameters/BrandIdHeader; parameter removed: ref:#/components/parameters/CatalogResolvedClient; parameter removed: ref:#/components/parameters/CatalogServiceAuthorizationPOST /v1/account/question-library/questions— createQualificationLibraryQuestion: parameter added: ref:#/components/parameters/BrandIdHeaderDELETE /v1/account/question-library/questions/{question_id}— deleteQualificationLibraryQuestion: parameter added: ref:#/components/parameters/BrandIdHeaderPOST /v1/account/offerings/{offering_ref}/qualification— forkQualificationQuestion: parameter added: ref:#/components/parameters/BrandIdHeaderGET /v1/account/brands/{brand_id}/readiness— getCommerceAccountBrandReadiness: parameter added: ref:#/components/parameters/BrandIdHeader; parameter removed: header:X-Client-Brand-Ids; parameter removed: header:X-Client-IdGET /v1/account/brands/{brand_id}/storefront— getCommerceAccountBrandStorefront: parameter added: ref:#/components/parameters/BrandIdHeader; parameter removed: header:X-Client-Brand-Ids; parameter removed: header:X-Client-Id; parameter removed: header:X-Client-Key-ClassGET /v1/account/orders/{order_ref}— getCommerceAccountOrder: parameter added: ref:#/components/parameters/BrandIdHeaderGET /v1/account/question-library/facts— getQualificationLibraryFacts: parameter added: ref:#/components/parameters/BrandIdHeaderGET /v1/account/offerings/{offering_ref}/qualification— getQualificationOverlay: parameter added: ref:#/components/parameters/BrandIdHeaderGET /v1/account/orders— listCommerceAccountOrders: parameter added: ref:#/components/parameters/BrandIdHeaderGET /v1/account/question-library/questions— listQualificationLibrary: parameter added: ref:#/components/parameters/BrandIdHeaderPOST /v1/account/question-library/minted-facts— mintQualificationFact: parameter added: ref:#/components/parameters/BrandIdHeaderPOST /v1/account/offerings/{offering_ref}/qualification/publish— publishQualificationOverlay: parameter added: ref:#/components/parameters/BrandIdHeaderDELETE /v1/account/offerings/{offering_ref}/qualification/questions/{question_id}— removeQualificationOverlayQuestion: parameter added: ref:#/components/parameters/BrandIdHeaderPUT /v1/account/offerings/{offering_ref}/qualification/order— reorderQualificationOverlay: parameter added: ref:#/components/parameters/BrandIdHeaderPUT /v1/account/brands/{brand_id}/pricing— setOwnBrandPricing: parameter added: ref:#/components/parameters/BrandIdHeader; parameter removed: ref:#/components/parameters/CatalogResolvedClient; parameter removed: ref:#/components/parameters/CatalogServiceAuthorizationPATCH /v1/account/question-library/questions/{question_id}— updateQualificationLibraryQuestion: parameter added: ref:#/components/parameters/BrandIdHeaderPATCH /v1/account/offerings/{offering_ref}/qualification/questions/{question_id}— updateQualificationOverlayQuestion: parameter added: ref:#/components/parameters/BrandIdHeader
No endpoint changed — the reference did. Two header mistakes affected 18 operations,
including both storefront reads:
X-Brand-Idwas missing from the storefront and readiness reads, your pricing and starter merchandising writes, both order reads, and the qualification and question-library operations. Every call made with a key needs it, and a call without it is refused with400. With a publishable key it must be the brand the key was issued for.- Headers you never send were listed as parameters, some marked required:
X-Client-Id,X-Client-Brand-Ids,X-Client-Key-Classandx-service-authorization. The platform sets those itself. They are gone from the reference.
X-Brand-Id on every call made with a key. If you generated a client
from the reference, regenerate it so it stops demanding the headers you never send. See
Authentication.Several reference descriptions carried internal notes, section marks and pointers to fields that
are not published. They now say only what you need. Two of them change what you should rely on:
Idempotency-Keyon the brand, domain, offering and webhook writes: send a unique value on every write, but do not assume a repeated request with the same key is de-duplicated. The checkout-session create is unchanged.blocked.codeis an open set: treat a code you don’t recognise as a generic stop.
No endpoint changed — the quickstart did. As written it could not finish a questionnaire:
- it started a session without
offering, which a brand with more than one treatment refuses (422); - its first answer had the wrong shape and sent no
node_id; - its loop waited for
completeonly, so it never stopped onblocked.
?offering= set to the product the patient chose. Send the
served node_id with every answer, and shape the answer by the node’s control: codes for
choices, value for text, email, number, date and phone. Keep submitting only while status is
active, and stop on complete, blocked or abandoned. See the
Quickstart and
how serving works.No endpoint changed — what we told you about one did. The welcome kit named
GET /v1/onboardings/{onboarding_id}/progress as a call you could make any time, and the
reference listed it with no credential. Your API key cannot reach it: today it is served only to
platform staff, and a call made with your API key is refused with 401. The reference now says so.What you must do: remove any call to it from your integration. To find out which onboarding
step you are on and what is waiting on you, ask your onboarding contact and quote your onboarding
id. See the Onboarding timeline.Changed
POST /v1/account/brands/{brand_id}/starter-merchandising— adoptStarterMerchandising: response added: 501PUT /v1/account/brands/{brand_id}/pricing— setOwnBrandPricing: response added: 501
Test patients must carry the
TEST marker. Use only invented test patients whose first or last
name includes the uppercase word TEST. Payments are unchanged: test mode never charges a real
card.What you must do: use only invented patients whose names carry the TEST marker, and never
enter real patient data in this environment. See Environments.The fork-and-own storefront starter lives in
the site kit repository, which is public.
The guide previously said access was provided at onboarding; you can fork the latest tagged
release directly. See
The checkout door.
Changed
POST /v1/account/brands/{brand_id}/starter-merchandising— adoptStarterMerchandising: parameter added: ref:#/components/parameters/CatalogServiceAuthorizationPUT /v1/account/brands/{brand_id}/pricing— setOwnBrandPricing: parameter added: ref:#/components/parameters/CatalogServiceAuthorization
Changed
PUT /v1/account/brands/{brand_id}/domains/member/browser-origins— putAccountBrandBrowserOrigins: response added: 409DELETE /v1/account/brands/{brand_id}/domains/{kind}— removeAccountBrandDomain: response added: 409
Changed
GET /v1/onboardings/{onboarding_id}/progress: response added: 503
Changed
PUT /v1/account/brands/{brand_id}/config— setAccountBrandDisplay: response added: 409
Added
GET /v1/instrument/address/retrieve— retrieveAddress
A new guide, Connect a Lovable storefront, covers wiring a
storefront generated from a written prompt to the platform: which of your three credentials may
ever reach browser code, the two browser-safe reads and the exact-origin allowlist that governs
them, both ways into the flow, and a reusable prompt that holds no credential.It is explicit about what you can build against now and what depends on your brand’s
configuration. The browser read needs two things switched on for your brand — a publishable key
and a registered origin — and until both are in place every cross-origin call is refused, whatever
credential it carries. The questions-first entry is a server-side path end to end: your page can
never call those endpoints itself. And the guide repeats the rule that
costs integrators the most: there is no redirect back to your storefront after payment, so a
payment outcome is read with
GET /v1/payments/{order_ref}/status
or delivered by webhook — never inferred from the browser.One correction of terminology worth reading if you have built against another payment tool: on
this platform a pk_ key is a server secret, and the browser-safe credential is the
publishable brand key beginning pub_test_ or pub_live_.No endpoint changed — what we told you about one did. The guides said an enrollment id was
readable for its status from the moment it existed. The contract declares more
outcomes than that for
GET /v1/journeys/{journey_id}/status:
besides the 400/401/404 refusals, it can return 422 with the type
https://purple.md/problems/journey-status-pending — a typed “no status yet” response for an
enrollment that is yours — and 503 when the status source is unavailable. Code that treats any
non-200 from that read as a failed call, or as a missing enrollment, needs a branch for it.The patient flow now
documents those outcomes and how they differ: branch on the type, and read a 503 as “the read
did not succeed” rather than as a statement about the patient. The
quickstart, how it works, the checkout
door, the identity
handoff and identifiers and error
types are corrected to match. The identity
handoff also no longer implies that verification produces a status change of its own — it does
not, and never did.Changed
PUT /v1/account/brands/{brand_id}/domains/{kind}— setAccountBrandDomain: response added: 403
Added
GET /v1/account/brands/{brand_id}/domains/member/browser-origins— getAccountBrandBrowserOriginsPUT /v1/account/brands/{brand_id}/domains/member/browser-origins— putAccountBrandBrowserOrigins
Added
GET /v1/account/brands/{brand_id}/storefront— getCommerceAccountBrandStorefront
Added
GET /v1/account/brands/{brand_id}/readiness— getCommerceAccountBrandReadiness
Changed
POST /v1/instrument/next— nextInstrument: response added: 500
Changed
POST /v1/instrument/abandon— abandonInstrument: response added: 404POST /v1/instrument/next— nextInstrument: response added: 404
Added
POST /v1/account/brands/{brand_id}/starter-merchandising— adoptStarterMerchandising
Changed
POST /v1/account/offerings/{offering_ref}/qualification— forkQualificationQuestion: parameter added: header:Idempotency-KeyGET /v1/account/offerings/{offering_ref}/qualification— getQualificationOverlay: response added: 503
Changed
POST /v1/account/offerings/{offering_ref}/qualification— forkQualificationQuestion: parameter removed: query:modeGET /v1/journeys/{journey_id}/status— getJourneyStatus: response added: 422; response added: 503
Changed
DELETE /v1/account/question-library/questions/{question_id}— deleteQualificationLibraryQuestion: response added: 204; response removed: 200; response removed: 422DELETE /v1/account/offerings/{offering_ref}/qualification/questions/{question_id}— removeQualificationOverlayQuestion: response added: 204; response removed: 200; response removed: 422PUT /v1/account/offerings/{offering_ref}/qualification/order— reorderQualificationOverlay: response added: 404
Changed
POST /v1/payments/checkout-sessions— createCommerceCheckoutSession: response added: 400; response added: 503GET /v1/instrument/resolve— resolveInstrument: response added: 422
Three new guides join the Integrate section: Pricing — set the price
your patients pay, what the price floor means, and how the hosted checkout resolves your stored
price; The patient flow — the enrollment stages end-to-end,
the eleven-value public status vocabulary, and where the payment step sits; and
Login URLs and domains — building the sign-in link,
the member portal origin, and the self-serve custom-domain ladder. The
welcome kit now lists your API base URL and member portal origin,
and the base-URL wording across the guides is aligned: the test-environment base is issued with
your key.
Added
GET /v1/journeys/{journey_id}/status— getJourneyStatus
GET /v1/journeys/{journey_id}/status
Added
PUT /v1/account/brands/{brand_id}/pricing— setOwnBrandPricing
Changed
POST /v1/account/question-library/questions— createQualificationLibraryQuestion: response added: 503DELETE /v1/account/question-library/questions/{question_id}— deleteQualificationLibraryQuestion: response added: 503POST /v1/account/offerings/{offering_ref}/qualification/questions— forkQualificationQuestion: response added: 503POST /v1/account/question-library/minted-facts— mintQualificationFact: response added: 503POST /v1/account/offerings/{offering_ref}/qualification/publish— publishQualificationOverlay: response added: 503DELETE /v1/account/offerings/{offering_ref}/qualification/questions/{question_id}— removeQualificationOverlayQuestion: response added: 503PUT /v1/account/offerings/{offering_ref}/qualification/order— reorderQualificationOverlay: response added: 503PATCH /v1/account/question-library/questions/{question_id}— updateQualificationLibraryQuestion: response added: 503PATCH /v1/account/offerings/{offering_ref}/qualification/questions/{question_id}— updateQualificationOverlayQuestion: response added: 503
A new guide, How questions work, explains the model behind the question endpoints: facts and the shared catalog, controls, the line between your screening questions and the medical intake, and how the engine serves an intake one question at a time. It deep-links every question-authoring operation on the public reference.
Added
POST /v1/account/question-library/questions— createQualificationLibraryQuestionDELETE /v1/account/question-library/questions/{question_id}— deleteQualificationLibraryQuestionPOST /v1/account/offerings/{offering_ref}/qualification/questions— forkQualificationQuestionGET /v1/account/question-library/facts— getQualificationLibraryFactsGET /v1/account/offerings/{offering_ref}/qualification— getQualificationOverlayGET /v1/account/question-library/questions— listQualificationLibraryPOST /v1/account/question-library/minted-facts— mintQualificationFactPOST /v1/account/offerings/{offering_ref}/qualification/publish— publishQualificationOverlayDELETE /v1/account/offerings/{offering_ref}/qualification/questions/{question_id}— removeQualificationOverlayQuestionPUT /v1/account/offerings/{offering_ref}/qualification/order— reorderQualificationOverlayPATCH /v1/account/question-library/questions/{question_id}— updateQualificationLibraryQuestionPATCH /v1/account/offerings/{offering_ref}/qualification/questions/{question_id}— updateQualificationOverlayQuestion
Added
POST /v1/account/brands/{brand_id}/offerings— enableAccountOfferingPUT /v1/account/offerings/{ref}/merchandising— setAccountOfferingMerchandising
Added
GET /v1/account/brands/{brand_id}/domains/{kind}— getAccountBrandDomainGET /v1/account/brands/{brand_id}/domains— listAccountBrandDomainsDELETE /v1/account/brands/{brand_id}/domains/{kind}— removeAccountBrandDomainPUT /v1/account/brands/{brand_id}/domains/{kind}— setAccountBrandDomainPOST /v1/account/brands/{brand_id}/domains/{kind}/verify— verifyAccountBrandDomain
Added
PUT /v1/account/brands/{brand_id}/config— setAccountBrandDisplay
GET /v1/instrument/resolve— resolveInstrument: parameter added: query:phase; response added: 400
The display identity (name, logo, theme tokens, support email) is now a self-serve write with your own API key at
PUT /v1/account/brands/{brand_id}/config, with the matching readback on GET. The token reference and the copy wording wall are documented in the brand configuration guide.This “API changes” page is now live, with automatic reference-change entries generated from the published contract on every deploy.