Submits the answer to the question the session is currently on. The answer is re-validated on the server and the session advances exactly one step, returning the next question — or status: complete once every required answer is in. The client never decides completion. If the answer fails validation the response is 422 with the specific issues and the session does not advance. Send node_id (the served node.node_id) to KEY the answer to its node: a stale replay of an already-passed node then resyncs cleanly (200, current node re-served) instead of misbinding to the node after a server-side skip, and a submit for a node the session has not reached fails closed with a renderer.node_mismatch issue (422). This op never presents a question that collects a government ID, and never waits on one to report complete — proof of identity is handled in the member portal’s identity step, not here.
An optional id you send to tie this request to your own logs. Send one and it is echoed back unchanged; omit it and one is assigned for you. Either way the id is returned in the X-Correlation-Id response header on every response, including errors, so you can match a response to the request that produced it.
Your brand id (brd_...). It must be one of the brands your API key's account owns; with a publishable key it must be the one brand the key was issued for. A missing or malformed value is refused with 400, and an unknown or foreign brand with 404.
Pattern: ^brd_[A-Za-z0-9][A-Za-z0-9_-]*$
Body
application/json
An answer for the question the session is currently on. Send node_id (recommended) to KEY the answer to the node it was collected for so a server-side skip or a restart can never land it on the wrong node.
A patient's answer for the current question, interpreted per its control type. Coded controls carry codes; scalar controls carry value; a number pair carries pair; a pre-filled-value confirmation carries confirmed; the address control carries address; a video capture carries media (an opaque upload reference + descriptor) and consent.
The id of the node this answer was collected for (echo the served node.node_id). Optional, and recommended on every submit. When present the server binds the answer to that node instead of blindly to the current question: if it matches the current node the submit proceeds; if it names a node ALREADY PASSED (a stale replay after a serve-time skip or a restart) the server re-serves the current node unchanged (idempotent resync — no misbind, no write); if it names a node the session has not reached (or an unknown node) the submit fails closed with a renderer.node_mismatch issue (422), the current node re-presented. When absent, the answer is applied to whatever node the session is on — which is why a client that omits it can lose step after the server skips a question.
Response
the next node, or completion
The result of a resolve, next, or abandon call — the session identity, the current question (or null when finished), the status, any flags (e.g. ship_state_mismatch), and any validation issues. On completion it may carry the entry-link hand-off.
active (a node is presented), complete (server-authoritative completion), abandoned (patient drop-off), or blocked — a terminal, server-authoritative refusal to proceed (a required consent was declined or could not be affirmed). On blocked, node is null and blocked carries the honest stop-screen outcome.
The honest stop-screen outcome. Present only when status is blocked. Carries the machine-readable reason, the node at which the block occurred, the consent scopes that were not granted (codes, never patient data), and a support-routing hint. The stop-screen copy is a presentation concern (the intake kit renders it); no patient data ever rides here. No order lock ever forms without a positive affirmation where one is required.
Present ONLY on the response to the call whose answer completed the questionnaire, and only when that questionnaire was started by your server with your secret key and no enrollment id (a fresh start, not a resume). It is a short-lived credential (about 10 minutes) that proves this browser's patient walked this enrollment. Never put it in a URL, never send it to browser JavaScript, and never log it. Hand the patient to checkout with a top-level form POST to https://member.<your brand domain>/api/checkout/door, with this value in the capability field of the request body and your offering_ref beside it. The form must be submitted from a page on one of your brand's registered browser origins (the browser's Origin header must match one exactly); any other origin is refused. If it has expired, the patient restarts the questionnaire; it is never reissued from the enrollment id. A repeated call on an already-complete session does not carry it again.
Post-completion hand-off carried when a session that began from an entry link completes. Present only when status is complete and the session carried a validated entry context. redirect holds a brand-allowlisted https URL; promo is an opaque pass-through token validated downstream; test is the per-client test-mode flag. Never carries patient data.
A node as presented to the client — PRESENTATION ONLY. The client never owns the sequence, controls, or option order (those come from the compiled bundle; a brand theme cannot alter them). Brand theme/copy, when applied, ride alongside as presentation overlay.
Server-computed progress metadata, present on every resolve/next step: computed from the live effective plan — never client-guessed. position_estimate is the honest fraction of the plan completed (0..1); display nodes participate in the fraction. Whether and how it renders (thin persistent bar, step ring, interstitial pacing, none) is brand-theme presentation.
Show child attributes
{"docsConfig":{"theme":"mint","$schema":"https://mintlify.com/docs.json","name":"Purple Label MD","description":"Public API reference for building a patient storefront on the platform. Generated from the platform's own API contracts, and matches the newest staging release.","colors":{"primary":"#6D28D9","light":"#A78BFA","dark":"#5B21B6"},"logo":{"light":"https://mintcdn.com/purplelabelmd/1P9p4n7lsNL4z3Jc/logo/light.svg?fit=max\u0026auto=format\u0026n=1P9p4n7lsNL4z3Jc\u0026q=85\u0026s=3c0569e3f76e49e04d232187908c2e2e","dark":"https://mintcdn.com/purplelabelmd/1P9p4n7lsNL4z3Jc/logo/dark.svg?fit=max\u0026auto=format\u0026n=1P9p4n7lsNL4z3Jc\u0026q=85\u0026s=c11f42bb461c28528be896c7c1a80efa"},"favicon":"https://mintcdn.com/purplelabelmd/MUdvgTlYoCGY54e8/favicon.svg?fit=max\u0026auto=format\u0026n=MUdvgTlYoCGY54e8\u0026q=85\u0026s=3bd633ab20ff170e0ebebec0406e6972","footer":{"socials":{}},"fonts":{"heading":{"family":"Geist"},"body":{"family":"Geist"}},"styling":{"latex":false},"navigation":{"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"purplelabelmd","hasAudioNarration":false,"actualSubdomain":"purplelabelmd","customDomains":["docs.purplelabelmd.com"],"gitSource":{"type":"github","owner":"purple-label-md","repo":"purple-doc","deployBranch":"main","contentDirectory":"","isPrivate":true,"mountPath":"","label":""},"entitlements":{"AI_CHAT":{"status":"ENABLED"},"WEB_MCP":{"status":"ENABLED"},"NARRATION":{"status":"ENABLED"}},"buildId":"6af545312fc9183f3253a260","clientVersion":"0.0.4111","searchFilterCounts":[{"language":"default","tag":"API reference","count":50},{"language":"default","tag":"Guides","count":21},{"language":"default","tag":"Offering configuration","count":18},{"language":"default","tag":"Integrate","count":16},{"language":"default","tag":"Brand configuration","count":9},{"language":"default","tag":"Webhooks","count":7},{"language":"default","tag":"Payments","count":4},{"language":"default","tag":"Intake","count":3},{"language":"default","tag":"Onboarding","count":3},{"language":"default","tag":"Sessions \u0026 authentication","count":3}]},"assistantConfig":{"enableAskAiButton":false,"enableStarterQuestions":false,"enableContextualStarterQuestions":false,"enableAskAiSearchBar":true},"basePath":"","hasChatPermissions":true,"hasWebMcpPermissions":true,"toggles":[{"name":"kill-isr","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-rbac-roles","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-mintlify-slack","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-integrations-settings","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"rbac-expansion","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-pr-grouping","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-prefix","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"analytics-v7","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"user-flows-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"no-publish-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-onboarding","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"llms-txt-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving-live","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"stripTemperatureMiddleware","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"support-platform-pylon-zendesk","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"instant-rollback","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications-server","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-fable","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fixed-ai-action-pricing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automation-resolve-merge-conflict","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"scoped-publishing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"mintql","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"page-level-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-version-history-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-page-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"full-page-search","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workspace-projects","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"assistant-v5","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fork-pr-previews","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"revalidation-jwt","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-sso-scim","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"hobby-abuse-scan","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"dashboard-inbox","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-signup","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-dual-write","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-enabled","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"approve-review-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-metadata","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"sso-setup-deadline-banner","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-serve","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"live-agents","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false}],"googleFontsInlined":true},"customCss":[{"filePath":"style.css","content":"@media (prefers-reduced-motion: no-preference){.plmd-logo{transform-origin:center;transition:transform 0.12s ease}.plmd-logo .plmd-mark path{transform-box:fill-box;transform-origin:center}.plmd-logo-link:active .plmd-logo{transform:scale(0.85)}.plmd-logo-link:hover .plmd-logo .plmd-mark path:last-child{animation:plmd-carrot-hop 0.55s ease}.plmd-logo-link:hover .plmd-logo .plmd-mark path:nth-child(-n+6){animation:plmd-carrot-twinkle 0.5s ease}.plmd-logo-link:hover .plmd-logo .plmd-mark path:nth-child(even){animation-delay:0.08s}}@keyframes plmd-carrot-hop{0%{transform:translateY(0) rotate(0)}30%{transform:translateY(-14%) rotate(-9deg)}55%{transform:translateY(0) rotate(6deg)}78%{transform:translateY(-5%) rotate(-2deg)}100%{transform:translateY(0) rotate(0)}}@keyframes plmd-carrot-twinkle{0%,100%{transform:scale(1);opacity:1}45%{transform:scale(1.6);opacity:0.7}}"}],"page":{"pagePath":"api-reference/intake/submit-an-answer-and-get-the-next-question","slug":"/api-reference/intake/submit-an-answer-and-get-the-next-question","pageMetadata":{"title":"Submit an answer and get the next question","description":"Submits the answer to the question the session is currently on. The answer is re-validated on the server and the session advances exactly one step, returning the next question — or `status: complete` once every required answer is in. The client never decides completion. If the answer fails validation the response is `422` with the specific issues and the session does not advance. Send `node_id` (the served `node.node_id`) to KEY the answer to its node: a stale replay of an already-passed node then resyncs cleanly (200, current node re-served) instead of misbinding to the node after a server-side skip, and a submit for a node the session has not reached fails closed with a `renderer.node_mismatch` issue (422). This op never presents a question that collects a government ID, and never waits on one to report `complete` — proof of identity is handled in the member portal's identity step, not here.","deprecated":null,"version":null,"openapi":"/openapi/public-openapi.json post /v1/instrument/next","href":"/api-reference/intake/submit-an-answer-and-get-the-next-question","autogeneratedByOpenApi":true},"description":{"compiledSource":"\"use strict\";\nconst {jsx: _jsx, jsxs: _jsxs} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n code: \"code\",\n p: \"p\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsxs(_components.p, {\n children: [\"Submits the answer to the question the session is currently on. The answer is re-validated on the server and the session advances exactly one step, returning the next question — or \", _jsx(_components.code, {\n children: \"status: complete\"\n }), \" once every required answer is in. The client never decides completion. If the answer fails validation the response is \", _jsx(_components.code, {\n children: \"422\"\n }), \" with the specific issues and the session does not advance. Send \", _jsx(_components.code, {\n children: \"node_id\"\n }), \" (the served \", _jsx(_components.code, {\n children: \"node.node_id\"\n }), \") to KEY the answer to its node: a stale replay of an already-passed node then resyncs cleanly (200, current node re-served) instead of misbinding to the node after a server-side skip, and a submit for a node the session has not reached fails closed with a \", _jsx(_components.code, {\n children: \"renderer.node_mismatch\"\n }), \" issue (422). This op never presents a question that collects a government ID, and never waits on one to report \", _jsx(_components.code, {\n children: \"complete\"\n }), \" — proof of identity is handled in the member portal’s identity step, not here.\"]\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{Fragment:_Fragment,jsx:_jsx}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];function _createMdxContent(props){return _jsx(_Fragment,{})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{default:MDXContent}","frontmatter":{},"scope":{"config":{},"pageMetadata":{"title":"Submit an answer and get the next question","description":"Submits the answer to the question the session is currently on. The answer is re-validated on the server and the session advances exactly one step, returning the next question — or `status: complete` once every required answer is in. The client never decides completion. If the answer fails validation the response is `422` with the specific issues and the session does not advance. Send `node_id` (the served `node.node_id`) to KEY the answer to its node: a stale replay of an already-passed node then resyncs cleanly (200, current node re-served) instead of misbinding to the node after a server-side skip, and a submit for a node the session has not reached fails closed with a `renderer.node_mismatch` issue (422). This op never presents a question that collects a government ID, and never waits on one to report `complete` — proof of identity is handled in the member portal's identity step, not here.","deprecated":null,"version":null,"openapi":"/openapi/public-openapi.json post /v1/instrument/next","href":"/api-reference/intake/submit-an-answer-and-get-the-next-question","autogeneratedByOpenApi":true}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[],"codeExamples":{}},"jsLinks":["/_mintlify/custom/purplelabelmd/3b4d4a495cd0c48d/brand.js"],"openApiReferenceData":{"operation":{"description":"Submits the answer to the question the session is currently on. The answer is re-validated on the server and the session advances exactly one step, returning the next question — or `status: complete` once every required answer is in. The client never decides completion. If the answer fails validation the response is `422` with the specific issues and the session does not advance. Send `node_id` (the served `node.node_id`) to KEY the answer to its node: a stale replay of an already-passed node then resyncs cleanly (200, current node re-served) instead of misbinding to the node after a server-side skip, and a submit for a node the session has not reached fails closed with a `renderer.node_mismatch` issue (422). This op never presents a question that collects a government ID, and never waits on one to report `complete` — proof of identity is handled in the member portal's identity step, not here.","operationId":"nextInstrument","parameters":["c50bcf88-4408-4760-a21f-992e11744b47"],"requestBody":"b719cd4e-8274-4d49-b75e-2fbe2c9ebe46","responses":{"200":"6518de41-f319-4e41-81ec-6cffb58809a4","402":"658b8e18-c949-43c8-a24f-5898b017a65d","404":"0c83782e-a60c-4821-af4b-12002649118d","422":"b1a8e61c-bef4-44ce-9365-36642c92d66e","429":"2a4f8ac2-31d9-45bb-97f9-53df5846472e","500":"7cb6a93c-8de3-4e1e-87ac-2a976ec28c71","503":"0b5b1e7b-d5ce-49a9-a08d-4d7a6e987809"},"security":["b179300c-8792-4ce8-aa92-381dbc634731"],"summary":"Submit an answer and get the next question","tags":["Intake"],"method":"post","type":"path","servers":["76f2c082-b62c-4aea-a087-a046f1378296"],"path":"/v1/instrument/next","baseUrlOptions":["https://api.staging.purplelabelmd.com"],"title":"Submit an answer and get the next question","codeSamples":[],"requiredOnlyExamples":false,"requestExampleType":"generated","responseExampleType":"generated"},"dependencies":{"parameters":{"c50bcf88-4408-4760-a21f-992e11744b47":{"description":"An optional id you send to tie this request to your own logs. Send one and it is echoed back unchanged; omit it and one is assigned for you. Either way the id is returned in the X-Correlation-Id response header on every response, including errors, so you can match a response to the request that produced it.","in":"header","name":"X-Correlation-Id","required":false,"schema":{"maxLength":128,"pattern":"^[A-Za-z0-9][A-Za-z0-9._:-]*$","type":"string","isRequired":false,"description":"An optional id you send to tie this request to your own logs. Send one and it is echoed back unchanged; omit it and one is assigned for you. Either way the id is returned in the X-Correlation-Id response header on every response, including errors, so you can match a response to the request that produced it.","uniqueKey":"","typeLabel":"string"}},"06f65c26-2fdc-47d4-a7a2-95a3ee302bc6":{"description":"Your brand id (`brd_...`). It must be one of the brands your API key's account owns; with a publishable key it must be the one brand the key was issued for. A missing or malformed value is refused with `400`, and an unknown or foreign brand with `404`.","in":"header","name":"X-Brand-Id","required":true,"schema":{"pattern":"^brd_[A-Za-z0-9][A-Za-z0-9_-]*$","type":"string","isRequired":true,"description":"Your brand id (`brd_...`). It must be one of the brands your API key's account owns; with a publishable key it must be the one brand the key was issued for. A missing or malformed value is refused with `400`, and an unknown or foreign brand with `404`.","uniqueKey":"","typeLabel":"string"}}},"requestBody":{"content":{"application/json":{"schema":{"description":"An answer for the question the session is currently on. Send `node_id` (recommended) to KEY the answer to the node it was collected for so a server-side skip or a restart can never land it on the wrong node.","properties":{"session_id":{"type":"string","isRequired":true,"uniqueKey":"session_id","typeLabel":"string"},"answer":{"description":"A patient's answer for the current question, interpreted per its control type. Coded controls carry `codes`; scalar controls carry `value`; a number pair carries `pair`; a pre-filled-value confirmation carries `confirmed`; the address control carries `address`; a video capture carries `media` (an opaque upload reference + descriptor) and `consent`.","properties":{"address":{"description":"A selected suggestion (validated) or a manually entered address (unverified).","properties":{"manual":{"properties":{"city":{"type":"string","isRequired":true,"uniqueKey":"answer.address.manual.city","typeLabel":"string"},"country":{"type":"string","isRequired":true,"uniqueKey":"answer.address.manual.country","typeLabel":"string"},"line1":{"type":"string","isRequired":true,"uniqueKey":"answer.address.manual.line1","typeLabel":"string"},"postal_code":{"type":"string","isRequired":true,"uniqueKey":"answer.address.manual.postal_code","typeLabel":"string"},"state":{"description":"ISO 3166-2-style state code, compared to the asserted jurisdiction state","type":"string","isRequired":true,"uniqueKey":"answer.address.manual.state","typeLabel":"string"},"line2":{"type":"string","uniqueKey":"answer.address.manual.line2","typeLabel":"string"}},"required":["line1","city","state","postal_code","country"],"type":"object","uniqueKey":"answer.address.manual","typeLabel":"object"},"override_state_mismatch":{"description":"proceed despite a validated ship-state ≠ asserted-state mismatch","type":"boolean","uniqueKey":"answer.address.override_state_mismatch","typeLabel":"boolean"},"suggestion_id":{"type":"string","uniqueKey":"answer.address.suggestion_id","typeLabel":"string"}},"type":"object","uniqueKey":"answer.address","typeLabel":"object"},"codes":{"items":{"type":"string","uniqueKey":"answer.codes.items.[INDEX]","typeLabel":"string"},"type":"array","uniqueKey":"answer.codes","typeLabel":"string[]"},"confirmed":{"type":"boolean","uniqueKey":"answer.confirmed","typeLabel":"boolean"},"consent":{"description":"A consent-to-record acknowledgment for a question that requires it.","properties":{"acknowledged":{"type":"boolean","isRequired":true,"uniqueKey":"answer.consent.acknowledged","typeLabel":"boolean"},"version":{"type":"string","uniqueKey":"answer.consent.version","typeLabel":"string"}},"required":["acknowledged"],"type":"object","uniqueKey":"answer.consent","typeLabel":"object"},"media":{"description":"A media (video) answer for a file-capture question. `upload_ref` is an opaque handle — the bytes upload directly to storage through a short-lived upload URL and are never inlined here (an inline data URI or an oversized token is refused). The descriptor fields are metadata the server checks against the question's capture bounds.","properties":{"byte_size":{"type":"integer","uniqueKey":"answer.media.byte_size","typeLabel":"integer"},"content_type":{"type":"string","uniqueKey":"answer.media.content_type","typeLabel":"string"},"duration_s":{"type":"number","uniqueKey":"answer.media.duration_s","typeLabel":"number"},"upload_ref":{"description":"opaque vault handle; never inline bytes / a data: URI","maxLength":256,"type":"string","uniqueKey":"answer.media.upload_ref","typeLabel":"string"}},"type":"object","uniqueKey":"answer.media","typeLabel":"object"},"pair":{"items":{"type":"number","uniqueKey":"answer.pair.items.[INDEX]","typeLabel":"number"},"maxItems":2,"minItems":2,"type":"array","uniqueKey":"answer.pair","typeLabel":"number[]"},"value":{"description":"scalar value (number | scale | date | text | file ref | phone | email)","uniqueKey":"answer.value","typeLabel":"any"}},"type":"object","uniqueKey":"answer","typeLabel":"object"},"node_id":{"description":"The id of the node this answer was collected for (echo the served `node.node_id`). Optional, and recommended on every submit. When present the server binds the answer to that node instead of blindly to the current question: if it matches the current node the submit proceeds; if it names a node ALREADY PASSED (a stale replay after a serve-time skip or a restart) the server re-serves the current node unchanged (idempotent resync — no misbind, no write); if it names a node the session has not reached (or an unknown node) the submit fails closed with a `renderer.node_mismatch` issue (422), the current node re-presented. When absent, the answer is applied to whatever node the session is on — which is why a client that omits it can lose step after the server skips a question.","type":"string","uniqueKey":"node_id","typeLabel":"string"}},"required":["session_id"],"type":"object","uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"session_id":"\u003cstring>","answer":{"address":{"override_state_mismatch":true,"suggestion_id":"\u003cstring>"},"codes":["\u003cstring>"],"confirmed":true,"media":{"byte_size":123,"content_type":"\u003cstring>","duration_s":123,"upload_ref":"\u003cstring>"},"pair":[123],"value":"\u003cunknown>"},"node_id":"\u003cstring>"}}},"exampleType":"generated"}},"required":true,"exampleType":"generated"},"responses":{"6518de41-f319-4e41-81ec-6cffb58809a4":{"content":{"application/json":{"schema":{"description":"The result of a resolve, next, or abandon call — the session identity, the current question (or null when finished), the status, any flags (e.g. ship_state_mismatch), and any validation issues. On completion it may carry the entry-link hand-off.","properties":{"journey_id":{"pattern":"^jny_[A-Za-z0-9][A-Za-z0-9_-]*$","type":"string","isRequired":true,"uniqueKey":"journey_id","typeLabel":"string"},"session_id":{"type":"string","isRequired":true,"uniqueKey":"session_id","typeLabel":"string"},"status":{"description":"`active` (a node is presented), `complete` (server-authoritative completion), `abandoned` (patient drop-off), or `blocked` — a terminal, server-authoritative refusal to proceed (a required consent was declined or could not be affirmed). On `blocked`, `node` is null and `blocked` carries the honest stop-screen outcome.","enum":["active","complete","abandoned","blocked"],"type":"string","isRequired":true,"uniqueKey":"status","typeLabel":"enum\u003cstring>"},"blocked":{"description":"The honest stop-screen outcome. Present only when `status` is `blocked`. Carries the machine-readable reason, the node at which the block occurred, the consent scopes that were not granted (codes, never patient data), and a support-routing hint. The stop-screen copy is a presentation concern (the intake kit renders it); no patient data ever rides here. No order lock ever forms without a positive affirmation where one is required.","properties":{"code":{"description":"A stable reason code, for example `consent_declined`, or `declined_therapy` when the questionnaire ends the visit. New codes can be added, so treat an unknown code as a generic stop.","type":"string","isRequired":true,"uniqueKey":"blocked.code","typeLabel":"string"},"node_id":{"description":"the node at which the block occurred (the consent node id, or the id of the node that declared the terminal)","type":"string","isRequired":true,"uniqueKey":"blocked.node_id","typeLabel":"string"},"content":{"additionalProperties":{"type":"string","uniqueKey":"blocked.content.additionalProperties","typeLabel":"string"},"description":"The stop's served words: named display-copy slots (e.g. `headline`, `body`) supplied by the server for this stop. A client renders these; it never picks the stop's wording off `code`. Absent means this stop supplies no copy and the client's own fallback stands. Carries instrument content only — never patient data.","type":"object","uniqueKey":"blocked.content","typeLabel":"object"},"support_route":{"description":"a stable support-routing key (edge owns portal→GHL support routing); never PII","type":"string","uniqueKey":"blocked.support_route","typeLabel":"string"},"ungranted_scopes":{"description":"consent scopes not granted — codes, never patient data","items":{"type":"string","uniqueKey":"blocked.ungranted_scopes.items.[INDEX]","typeLabel":"string"},"type":"array","uniqueKey":"blocked.ungranted_scopes","typeLabel":"string[]"}},"required":["code","node_id"],"type":"object","uniqueKey":"blocked","typeLabel":"object"},"destination_capability":{"description":"Present ONLY on the response to the call whose answer completed the questionnaire, and only when that questionnaire was started by your server with your secret key and no enrollment id (a fresh start, not a resume). It is a short-lived credential (about 10 minutes) that proves this browser's patient walked this enrollment. Never put it in a URL, never send it to browser JavaScript, and never log it. Hand the patient to checkout with a top-level form POST to `https://member.\u003cyour brand domain>/api/checkout/door`, with this value in the `capability` field of the request body and your `offering_ref` beside it. The form must be submitted from a page on one of your brand's registered browser origins (the browser's Origin header must match one exactly); any other origin is refused. If it has expired, the patient restarts the questionnaire; it is never reissued from the enrollment id. A repeated call on an already-complete session does not carry it again.","type":"string","uniqueKey":"destination_capability","typeLabel":"string"},"flags":{"items":{"type":"string","uniqueKey":"flags.items.[INDEX]","typeLabel":"string"},"type":"array","uniqueKey":"flags","typeLabel":"string[]"},"handoff":{"additionalProperties":false,"description":"Post-completion hand-off carried when a session that began from an entry link completes. Present only when `status` is `complete` and the session carried a validated entry context. `redirect` holds a brand-allowlisted https URL; `promo` is an opaque pass-through token validated downstream; `test` is the per-client test-mode flag. Never carries patient data.","properties":{"promo":{"maxLength":256,"type":"string","uniqueKey":"handoff.promo","typeLabel":"string"},"redirect":{"maxLength":2048,"type":"string","uniqueKey":"handoff.redirect","typeLabel":"string"},"test":{"type":"boolean","uniqueKey":"handoff.test","typeLabel":"boolean"}},"type":"object","uniqueKey":"handoff","typeLabel":"object"},"issues":{"items":{"properties":{"code":{"type":"string","isRequired":true,"uniqueKey":"issues.items.[INDEX].code","typeLabel":"string"},"message":{"type":"string","isRequired":true,"uniqueKey":"issues.items.[INDEX].message","typeLabel":"string"},"conflicting_codes":{"description":"Paired with `exclusive_codes`. The option code(s) the exclusive selection contradicted — the other half of \"which options clashed\". When the submission carried only exclusive options, they contradict each other and both lists name them.","items":{"type":"string","uniqueKey":"issues.items.[INDEX].conflicting_codes.items.[INDEX]","typeLabel":"string"},"type":"array","uniqueKey":"issues.items.[INDEX].conflicting_codes","typeLabel":"string[]"},"exclusive_codes":{"description":"Present ONLY on `code: renderer.exclusive_violation`, absent on every other issue. The exclusive (\"none of these\"-class) option code(s) the refused submission carried. A contradictory selection on a clinical-safety question is a SERVE defect, not a client nicety: the server refuses it with a 422 and never a 200-advance, and the refusal must say WHICH selections contradicted so the client can correct the exact ones. These are the caller's OWN submitted codes echoed back to the caller.","items":{"type":"string","uniqueKey":"issues.items.[INDEX].exclusive_codes.items.[INDEX]","typeLabel":"string"},"type":"array","uniqueKey":"issues.items.[INDEX].exclusive_codes","typeLabel":"string[]"}},"required":["code","message"],"type":"object","uniqueKey":"issues.items.[INDEX]","typeLabel":"object"},"type":"array","uniqueKey":"issues","typeLabel":"object[]"},"node":{"oneOf":[{"type":"object","description":"A node as presented to the client — PRESENTATION ONLY. The client never owns the sequence, controls, or option order (those come from the compiled bundle; a brand theme cannot alter them). Brand theme/copy, when applied, ride alongside as presentation overlay.","required":["node_id","kind","section_id"],"properties":{"kind":{"description":"`question` (collects a fact), `display` (an informational node with no answer channel), or `consent` (a consent-capture affirmation surface — its clinician/counsel-locked copy rides `content`, its `consent_version` + `grants` ride alongside). A `consent` node comes in TWO KINDS under ONE shape: the treatment consent (no `consent_kind`; binds no fact; a decline ends the session with an honest stop screen) and `communications_consent` (see `consent_kind`; never blocks, grants nothing, and the server records BOTH outcomes itself).","enum":["question","display","consent"],"type":"string","isRequired":true,"uniqueKey":"node.oneOf.0.kind","typeLabel":"enum\u003cstring>"},"node_id":{"type":"string","isRequired":true,"uniqueKey":"node.oneOf.0.node_id","typeLabel":"string"},"section_id":{"type":"string","isRequired":true,"uniqueKey":"node.oneOf.0.section_id","typeLabel":"string"},"computed_stub":{"type":"boolean","uniqueKey":"node.oneOf.0.computed_stub","typeLabel":"boolean"},"consent_kind":{"description":"the consent node's SUB-KIND. Present ONLY on a `communications_consent` node (the email opt-in and the SMS consents); ABSENT on a treatment consent, whose decline ends the session with an honest stop screen. THE AFFORDANCES DIFFER, which is why it is served: on this kind the client offers one affirmative action AND an explicit \"No thanks\", both outcomes are recorded as an auditable fact with the served copy version, Continue with neither is recorded as not-granted, and NO outcome ever blocks the intake or terminates the session. A client that cannot distinguish the two kinds either hides a lawful decline or offers one that ends a member's intake. It carries no fact code: the server records the outcome under its own write key, and the stable code stays the server's binding.","enum":["communications_consent"],"type":"string","uniqueKey":"node.oneOf.0.consent_kind","typeLabel":"enum\u003cstring>"},"consent_version":{"description":"the consent version served on a `consent` node. The client echoes it on the affirmation; it rides into the recorded consent fact as provenance. The MD/counsel-locked affirmation copy rides `content`; brand can never supply it.","type":"string","uniqueKey":"node.oneOf.0.consent_version","typeLabel":"string"},"content":{"additionalProperties":{"type":"string","uniqueKey":"node.oneOf.0.content.additionalProperties","typeLabel":"string"},"description":"Named display-content slots for a display node — MD-locked copy carried in the compiled instrument bundle, versioned and reviewed with the instrument. Brand config themes presentation only and cannot supply or override these slots, with ONE narrow exception: in the two instrument-furniture slots (`start_greeting`, `acknowledgement_documents`) and in a consent node's counsel-locked text, the platform substitutes the brand's REGISTERED IDENTITY — its display name and its registered legal-document URLs — into fixed token positions the instrument itself authors. That is substitution of an identity value into MD-authored wording, never brand-supplied WORDING: a brand still cannot contribute one word of a clinical question prompt or option label, which remain structurally unreachable. The `copy` field is the separate question-headline channel; its authoritative source is likewise the MD-locked instrument bundle, and the brand overlay can never override it.","type":"object","uniqueKey":"node.oneOf.0.content","typeLabel":"object"},"control":{"type":"string","uniqueKey":"node.oneOf.0.control","typeLabel":"string"},"copy":{"description":"The question headline, as a single string, served from the MD-locked question prompt in the compiled instrument bundle (versioned and reviewed with the instrument). For a question node this is its only source — the per-brand copy overlay can never supply or override it (theming yes, wording never). Absent is valid; the renderer falls back deterministically (for example a formatted fact code).","type":"string","uniqueKey":"node.oneOf.0.copy","typeLabel":"string"},"display":{"enum":["static","computed"],"type":"string","uniqueKey":"node.oneOf.0.display","typeLabel":"enum\u003cstring>"},"fact":{"type":"string","uniqueKey":"node.oneOf.0.fact","typeLabel":"string"},"grants":{"description":"the consent scopes an affirmative answer grants on a `consent` node. Codes, never labels; nothing branches on the copy text. A `communications_consent` node grants nothing, so this is the empty list there — it can never tell a client which kind of consent card it is looking at; `consent_kind` is that signal.","items":{"type":"string","uniqueKey":"node.oneOf.0.grants.items.[INDEX]","typeLabel":"string"},"type":"array","uniqueKey":"node.oneOf.0.grants","typeLabel":"string[]"},"interstitial":{"description":"Marks a display node as an interstitial moment for skin treatment (the tint pair is reserved for these). Presentation flag only; never carried on question nodes.","type":"boolean","uniqueKey":"node.oneOf.0.interstitial","typeLabel":"boolean"},"may_auto_advance":{"type":"boolean","uniqueKey":"node.oneOf.0.may_auto_advance","typeLabel":"boolean"},"media":{"description":"Capture configuration for a file-capture question. When absent, the question is a standard photo or document upload. Presentation and capture-bounds only — the answer is an upload reference and nothing branches on the media content; faces and voices are never matched, recognized, or graphed.","properties":{"kind":{"enum":["image","video"],"type":"string","isRequired":true,"uniqueKey":"node.oneOf.0.media.kind","typeLabel":"enum\u003cstring>"},"accept":{"description":"MIME allowlist (e.g. video/mp4, video/webm)","items":{"type":"string","uniqueKey":"node.oneOf.0.media.accept.items.[INDEX]","typeLabel":"string"},"type":"array","uniqueKey":"node.oneOf.0.media.accept","typeLabel":"string[]"},"capture_mode":{"enum":["upload","record","record_or_upload"],"type":"string","uniqueKey":"node.oneOf.0.media.capture_mode","typeLabel":"enum\u003cstring>"},"consent_copy":{"description":"The PLAIN DISPLAY TEXT the member must be shown before any affirmative action, pinned to `consent_version`. The portal renders THIS EXACT text; it is not a key, not a template, and the client never substitutes its own wording — consent to copy the server did not serve is not consent. Optional on the contract because non-video captures may not gate on consent at all, but REQUIRED (nonempty) for a managed video capture alongside `consent_version` and `consent_fact`: all three, or no grant and no recorded consent. Authored and served through the same MediaConfig, so the text the member reads and the version the server records can never drift apart.","type":"string","uniqueKey":"node.oneOf.0.media.consent_copy","typeLabel":"string"},"consent_fact":{"description":"fact code the consent acknowledgment projects to (discrete auditable consent fact)","type":"string","uniqueKey":"node.oneOf.0.media.consent_fact","typeLabel":"string"},"consent_version":{"description":"the version OF RECORD for the consent copy below. The server checks the echoed version against this one and records it on the acknowledgment; there is NO versionless fallback — a managed video capture whose node omits this refuses rather than recording a consent that cannot say which copy was agreed to.","type":"string","uniqueKey":"node.oneOf.0.media.consent_version","typeLabel":"string"},"facing":{"description":"advisory front/rear camera hint; not enforced","enum":["user","environment"],"type":"string","uniqueKey":"node.oneOf.0.media.facing","typeLabel":"enum\u003cstring>"},"max_bytes":{"type":"integer","uniqueKey":"node.oneOf.0.media.max_bytes","typeLabel":"integer"},"max_duration_s":{"type":"number","uniqueKey":"node.oneOf.0.media.max_duration_s","typeLabel":"number"},"min_duration_s":{"type":"number","uniqueKey":"node.oneOf.0.media.min_duration_s","typeLabel":"number"},"require_consent":{"description":"gate capture on a consent-to-record acknowledgment (video ⇒ true)","type":"boolean","uniqueKey":"node.oneOf.0.media.require_consent","typeLabel":"boolean"},"resumable":{"type":"boolean","uniqueKey":"node.oneOf.0.media.resumable","typeLabel":"boolean"}},"required":["kind"],"type":"object","uniqueKey":"node.oneOf.0.media","typeLabel":"object"},"offering_refs":{"items":{"type":"string","uniqueKey":"node.oneOf.0.offering_refs.items.[INDEX]","typeLabel":"string"},"type":"array","uniqueKey":"node.oneOf.0.offering_refs","typeLabel":"string[]"},"option_codes":{"items":{"type":"string","uniqueKey":"node.oneOf.0.option_codes.items.[INDEX]","typeLabel":"string"},"type":"array","uniqueKey":"node.oneOf.0.option_codes","typeLabel":"string[]"},"options":{"description":"Per-option presentation hints for this question. When present, it lists the same codes in the same order as `option_codes` — option order comes from the questionnaire and cannot be altered by theming. When absent, render from `option_codes` alone.","items":{"description":"One selectable option with its presentation hints — presentation only, carried alongside `option_codes`. An `exclusive` option (a \"none of these\"-class choice) cannot be combined with any sibling — selecting it should clear the other selections, and the server rejects an answer that carries an exclusive code together with another selection (`422`, the session does not advance). A banded choice (for example a blood-pressure or frequency range) may carry a `classification_code` alongside its stable option code.","properties":{"code":{"description":"the stable option code submitted as the answer value","type":"string","isRequired":true,"uniqueKey":"node.oneOf.0.options.items.[INDEX].code","typeLabel":"string"},"classification_code":{"description":"classification code carried by a banded choice alongside its stable option code","type":"string","uniqueKey":"node.oneOf.0.options.items.[INDEX].classification_code","typeLabel":"string"},"exclusive":{"description":"marks a \"none of these\"-class option that cannot be combined with any sibling selection","type":"boolean","uniqueKey":"node.oneOf.0.options.items.[INDEX].exclusive","typeLabel":"boolean"},"label":{"description":"MD-locked display label for this option, carried in the compiled instrument bundle and resolved by the stable option code (never positional). Presentation only — the code remains the submitted answer value and the sole binding; consumers fall back to the code when no label is present.","type":"string","uniqueKey":"node.oneOf.0.options.items.[INDEX].label","typeLabel":"string"}},"required":["code"],"type":"object","uniqueKey":"node.oneOf.0.options.items.[INDEX]","typeLabel":"object"},"type":"array","uniqueKey":"node.oneOf.0.options","typeLabel":"object[]"},"page":{"description":"Present ONLY on a question node whose value was staged from the member's OWN checkout destination record (always paired with `prefill: confirm` and a populated `prefilled_value`). Names the one leading page (\"Confirm your details\") the four contact nodes — name, email, phone, state — collapse onto with edit-in-place. A presentation grouping hint only, exactly like `interstitial` above: the server still walks one node at a time (resolve -> next -> ...); a client groups consecutive `confirm_details` nodes onto one screen without any change to the answer protocol. WHAT A CONFIRM DOES: confirming one of these nodes RECORDS that your patient affirmed the value shown — the same durable assertion any other confirm writes. It does not write a correction, because there was nothing to correct. Editing instead writes the edited value, superseding it, exactly like any other answered question. WHAT IS SHOWN IS ALWAYS A VALID ANSWER TO THE QUESTION: for a question whose answers are option codes, the `prefilled_value` is one of that node's own `option_codes`, promoted from the checkout record's postal spelling. A checkout value that cannot be resolved onto one of those options — an unfamiliar spelling, a region the question does not offer, a blank, a half-composed name — is NOT shown: that node arrives as an ordinary open question with no `page` and no `prefilled_value`, and your patient answers it normally. Absent on every other node.","enum":["confirm_details"],"type":"string","uniqueKey":"node.oneOf.0.page","typeLabel":"enum\u003cstring>"},"prefill":{"enum":["collect","suppress","confirm"],"type":"string","uniqueKey":"node.oneOf.0.prefill","typeLabel":"enum\u003cstring>"},"prefilled_value":{"oneOf":[{}],"uniqueKey":"node.oneOf.0.prefilled_value","typeLabel":"any"},"reassurance":{"description":"A single hedged reassurance line for a computed display panel, served from the MD-locked instrument content and reviewed with it. The line is SELECTED server-side by where the primary computed value falls against the served zone (below / in_zone / above) — never served statically — and is PRESENT only when the matching band is authored and the band could be determined; otherwise it is ABSENT (fail to neutral). Display copy only; it carries no eligibility language and defers every decision to the clinician.","type":"string","uniqueKey":"node.oneOf.0.reassurance","typeLabel":"string"},"required":{"type":"boolean","uniqueKey":"node.oneOf.0.required","typeLabel":"boolean"},"theme":{"additionalProperties":true,"type":"object","uniqueKey":"node.oneOf.0.theme","typeLabel":"object"},"unit":{"description":"The unit a question's answer is expressed in (for example \"in\" or \"lb\"), served from the question's MD-locked copy in the compiled instrument bundle, beside its prompt. Present only on a question node whose instrument authors a non-blank unit; absent otherwise. When absent the client shows no unit and never infers one — in particular never from the fact code. The per-brand overlay can never supply or override it. Display text only; nothing branches on it.","type":"string","uniqueKey":"node.oneOf.0.unit","typeLabel":"string"},"values":{"additionalProperties":{"oneOf":[{}],"uniqueKey":"node.oneOf.0.values.additionalProperties","typeLabel":"any"},"description":"Server-supplied display values keyed by fact/derivation CODE (codes, never label text). Derived codes are computed server-side on read from registered pure derivations — the client renders these values and never computes anything of record. A display node whose primary referenced values cannot all be resolved is never emitted (server-skipped, fail-soft). Ancillary echoed values (for example the height and weight behind a computed number) ride this same map alongside the primary value; an echoed value that cannot be resolved is omitted, and never blocks the node.","type":"object","uniqueKey":"node.oneOf.0.values","typeLabel":"object"},"zone":{"description":"A designed-panel band descriptor for a computed display node: a scale from `scale_min` to `scale_max` with a highlighted band from `zone_min` to `zone_max`, named by `zone_label`. The client places the patient's marker and the highlighted band for the picture. Display copy and presentation only — a zone carries no eligibility language and never asserts eligibility; the server remains authoritative on jurisdiction and eligibility.","properties":{"scale_max":{"description":"high end of the rendered scale axis","type":"number","isRequired":true,"uniqueKey":"node.oneOf.0.zone.scale_max","typeLabel":"number"},"scale_min":{"description":"low end of the rendered scale axis","type":"number","isRequired":true,"uniqueKey":"node.oneOf.0.zone.scale_min","typeLabel":"number"},"zone_label":{"description":"label naming the highlighted band (display copy; never an outcome)","type":"string","isRequired":true,"uniqueKey":"node.oneOf.0.zone.zone_label","typeLabel":"string"},"zone_max":{"description":"high bound of the highlighted band (within the scale)","type":"number","isRequired":true,"uniqueKey":"node.oneOf.0.zone.zone_max","typeLabel":"number"},"zone_min":{"description":"low bound of the highlighted band (within the scale)","type":"number","isRequired":true,"uniqueKey":"node.oneOf.0.zone.zone_min","typeLabel":"number"}},"required":["scale_min","scale_max","zone_min","zone_max","zone_label"],"type":"object","uniqueKey":"node.oneOf.0.zone","typeLabel":"object"}},"uniqueKey":"node.oneOf.0","typeLabel":"object"},{"type":"null","uniqueKey":"node.oneOf.1","typeLabel":"null"}],"uniqueKey":"node","typeLabel":"object | null"},"patient_readiness":{"type":"object","description":"Present on a resolve: whether your brand is ready for patients, and what is still missing if not. The questionnaire is served either way.","required":["status","consent_holder","required_documents","missing"],"properties":{"consent_holder":{"description":"who holds the brand's consent documents, as chosen; `not_chosen` until someone chooses.","enum":["purple","client","not_chosen"],"type":"string","isRequired":true,"uniqueKey":"patient_readiness.consent_holder","typeLabel":"enum\u003cstring>"},"missing":{"description":"every required item still unset; empty exactly when `status` is `patient_ready`.","items":{"additionalProperties":false,"properties":{"detail":{"description":"what is missing and how to set it, in plain words.","type":"string","isRequired":true,"uniqueKey":"patient_readiness.missing.items.[INDEX].detail","typeLabel":"string"},"item":{"enum":["display_name","consent_holder","legal_document","readiness_unknown"],"type":"string","isRequired":true,"uniqueKey":"patient_readiness.missing.items.[INDEX].item","typeLabel":"enum\u003cstring>"},"document":{"description":"for `legal_document`, which document is missing.","enum":["terms","privacy","telehealth"],"type":"string","uniqueKey":"patient_readiness.missing.items.[INDEX].document","typeLabel":"enum\u003cstring>"}},"required":["item","detail"],"type":"object","uniqueKey":"patient_readiness.missing.items.[INDEX]","typeLabel":"object"},"type":"array","isRequired":true,"uniqueKey":"patient_readiness.missing","typeLabel":"object[]"},"required_documents":{"description":"the documents the brand's served consents link to (empty when that cannot be told yet).","items":{"enum":["terms","privacy","telehealth"],"type":"string","uniqueKey":"patient_readiness.required_documents.items.[INDEX]","typeLabel":"enum\u003cstring>"},"type":"array","isRequired":true,"uniqueKey":"patient_readiness.required_documents","typeLabel":"enum\u003cstring>[]"},"status":{"enum":["patient_ready","not_patient_ready"],"type":"string","isRequired":true,"uniqueKey":"patient_readiness.status","typeLabel":"enum\u003cstring>"}},"additionalProperties":false,"uniqueKey":"patient_readiness","typeLabel":"object"},"progress":{"description":"Server-computed progress metadata, present on every resolve/next step: computed from the live effective plan — never client-guessed. `position_estimate` is the honest fraction of the plan completed (0..1); display nodes participate in the fraction. Whether and how it renders (thin persistent bar, step ring, interstitial pacing, none) is brand-theme presentation.","properties":{"position_estimate":{"description":"honest fraction of the effective plan completed, 0..1","maximum":1,"minimum":0,"type":"number","isRequired":true,"uniqueKey":"progress.position_estimate","typeLabel":"number"},"scope":{"description":"`instrument`, or a subflow id once named optional sub-flows ship","type":"string","isRequired":true,"uniqueKey":"progress.scope","typeLabel":"string"},"section_label":{"description":"optional server-supplied section label; omitted while bundles carry none","type":"string","uniqueKey":"progress.section_label","typeLabel":"string"}},"required":["scope","position_estimate"],"type":"object","uniqueKey":"progress","typeLabel":"object"}},"required":["session_id","journey_id","status"],"type":"object","uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"journey_id":"\u003cstring>","session_id":"\u003cstring>","status":"active","blocked":{"code":"\u003cstring>","node_id":"\u003cstring>","content":{},"support_route":"\u003cstring>","ungranted_scopes":["\u003cstring>"]},"destination_capability":"\u003cstring>","flags":["\u003cstring>"],"handoff":{"promo":"\u003cstring>","redirect":"\u003cstring>","test":true},"issues":[{"code":"\u003cstring>","message":"\u003cstring>","conflicting_codes":["\u003cstring>"],"exclusive_codes":["\u003cstring>"]}],"node":{"kind":"question","node_id":"\u003cstring>","section_id":"\u003cstring>","computed_stub":true,"consent_kind":"communications_consent","consent_version":"\u003cstring>","content":{},"control":"\u003cstring>","copy":"\u003cstring>","display":"static","fact":"\u003cstring>","grants":["\u003cstring>"],"interstitial":true,"may_auto_advance":true,"media":{"kind":"image","accept":["\u003cstring>"],"capture_mode":"upload","consent_copy":"\u003cstring>","consent_fact":"\u003cstring>","consent_version":"\u003cstring>","facing":"user","max_bytes":123,"max_duration_s":123,"min_duration_s":123,"require_consent":true,"resumable":true},"offering_refs":["\u003cstring>"],"option_codes":["\u003cstring>"],"options":[{"code":"\u003cstring>","classification_code":"\u003cstring>","exclusive":true,"label":"\u003cstring>"}],"page":"confirm_details","prefill":"collect","prefilled_value":"\u003cunknown>","reassurance":"\u003cstring>","required":true,"theme":{},"unit":"\u003cstring>","values":{},"zone":{"scale_max":123,"scale_min":123,"zone_label":"\u003cstring>","zone_max":123,"zone_min":123}},"patient_readiness":{"consent_holder":"purple","missing":[{"detail":"\u003cstring>","item":"display_name","document":"terms"}],"required_documents":["terms"],"status":"patient_ready"},"progress":{"position_estimate":0.5,"scope":"\u003cstring>","section_label":"\u003cstring>"}}}},"exampleType":"generated"}},"description":"the next node, or completion","exampleType":"generated"},"658b8e18-c949-43c8-a24f-5898b017a65d":{"content":{"application/problem+json":{"schema":{"type":"object","description":"RFC 7807 problem+json error body.","required":["type","title","status"],"properties":{"status":{"type":"integer","isRequired":true,"uniqueKey":"status","typeLabel":"integer"},"title":{"type":"string","isRequired":true,"uniqueKey":"title","typeLabel":"string"},"type":{"type":"string","format":"uri-reference","enum":["https://purple.md/problems/intake-payment-required"],"isRequired":true,"uniqueKey":"type","typeLabel":"enum\u003cstring>"},"detail":{"type":"string","uniqueKey":"detail","typeLabel":"string"}},"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"status":123,"title":"\u003cstring>","type":"https://purple.md/problems/intake-payment-required","detail":"\u003cstring>"}}},"exampleType":"generated"}},"description":"This treatment's questions start after payment, and the order for this enrollment has not been paid (no order is authorized, paid or partially refunded). Nothing was started, saved or decided. Finishing checkout is the cure; retrying without it returns the same answer. The body's `title` and `detail` carry the member-facing sentence: \"Finish checkout to start your medical intake.\" A treatment whose questions are designed to come BEFORE payment never answers this, nor does a resolve that names no enrollment, nor the pre-payment `qualification` phase. An order whose checkout began less than 30 minutes ago is answered with the 503 `intake-payment-unconfirmed` instead (its payment may still be arriving).","exampleType":"generated"},"0c83782e-a60c-4821-af4b-12002649118d":{"content":{"application/problem+json":{"schema":{"description":"RFC 7807 problem+json error body.","properties":{"status":{"type":"integer","isRequired":true,"uniqueKey":"status","typeLabel":"integer"},"title":{"type":"string","isRequired":true,"uniqueKey":"title","typeLabel":"string"},"type":{"format":"uri-reference","type":"string","isRequired":true,"uniqueKey":"type","typeLabel":"string\u003curi-reference>"},"detail":{"type":"string","uniqueKey":"detail","typeLabel":"string"}},"required":["type","title","status"],"type":"object","uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"status":123,"title":"\u003cstring>","type":"\u003cstring>","detail":"\u003cstring>"}}},"exampleType":"generated"}},"description":"The questionnaire session named by `session_id` is not available: it never existed, or it has expired. Sessions live in the serving process, so a deployment retires the ones in flight. Start a fresh questionnaire (`/instrument/resolve`) and collect the answers again — retrying the same `session_id` will never succeed. The answer is identical for a malformed, an expired, and an unknown session id, so it carries no signal about which.","exampleType":"generated"},"b1a8e61c-bef4-44ce-9365-36642c92d66e":{"content":{"application/json":{"schema":{"description":"The result of a resolve, next, or abandon call — the session identity, the current question (or null when finished), the status, any flags (e.g. ship_state_mismatch), and any validation issues. On completion it may carry the entry-link hand-off.","properties":{"journey_id":{"pattern":"^jny_[A-Za-z0-9][A-Za-z0-9_-]*$","type":"string","isRequired":true,"uniqueKey":"journey_id","typeLabel":"string"},"session_id":{"type":"string","isRequired":true,"uniqueKey":"session_id","typeLabel":"string"},"status":{"description":"`active` (a node is presented), `complete` (server-authoritative completion), `abandoned` (patient drop-off), or `blocked` — a terminal, server-authoritative refusal to proceed (a required consent was declined or could not be affirmed). On `blocked`, `node` is null and `blocked` carries the honest stop-screen outcome.","enum":["active","complete","abandoned","blocked"],"type":"string","isRequired":true,"uniqueKey":"status","typeLabel":"enum\u003cstring>"},"blocked":{"description":"The honest stop-screen outcome. Present only when `status` is `blocked`. Carries the machine-readable reason, the node at which the block occurred, the consent scopes that were not granted (codes, never patient data), and a support-routing hint. The stop-screen copy is a presentation concern (the intake kit renders it); no patient data ever rides here. No order lock ever forms without a positive affirmation where one is required.","properties":{"code":{"description":"A stable reason code, for example `consent_declined`, or `declined_therapy` when the questionnaire ends the visit. New codes can be added, so treat an unknown code as a generic stop.","type":"string","isRequired":true,"uniqueKey":"blocked.code","typeLabel":"string"},"node_id":{"description":"the node at which the block occurred (the consent node id, or the id of the node that declared the terminal)","type":"string","isRequired":true,"uniqueKey":"blocked.node_id","typeLabel":"string"},"content":{"additionalProperties":{"type":"string","uniqueKey":"blocked.content.additionalProperties","typeLabel":"string"},"description":"The stop's served words: named display-copy slots (e.g. `headline`, `body`) supplied by the server for this stop. A client renders these; it never picks the stop's wording off `code`. Absent means this stop supplies no copy and the client's own fallback stands. Carries instrument content only — never patient data.","type":"object","uniqueKey":"blocked.content","typeLabel":"object"},"support_route":{"description":"a stable support-routing key (edge owns portal→GHL support routing); never PII","type":"string","uniqueKey":"blocked.support_route","typeLabel":"string"},"ungranted_scopes":{"description":"consent scopes not granted — codes, never patient data","items":{"type":"string","uniqueKey":"blocked.ungranted_scopes.items.[INDEX]","typeLabel":"string"},"type":"array","uniqueKey":"blocked.ungranted_scopes","typeLabel":"string[]"}},"required":["code","node_id"],"type":"object","uniqueKey":"blocked","typeLabel":"object"},"destination_capability":{"description":"Present ONLY on the response to the call whose answer completed the questionnaire, and only when that questionnaire was started by your server with your secret key and no enrollment id (a fresh start, not a resume). It is a short-lived credential (about 10 minutes) that proves this browser's patient walked this enrollment. Never put it in a URL, never send it to browser JavaScript, and never log it. Hand the patient to checkout with a top-level form POST to `https://member.\u003cyour brand domain>/api/checkout/door`, with this value in the `capability` field of the request body and your `offering_ref` beside it. The form must be submitted from a page on one of your brand's registered browser origins (the browser's Origin header must match one exactly); any other origin is refused. If it has expired, the patient restarts the questionnaire; it is never reissued from the enrollment id. A repeated call on an already-complete session does not carry it again.","type":"string","uniqueKey":"destination_capability","typeLabel":"string"},"flags":{"items":{"type":"string","uniqueKey":"flags.items.[INDEX]","typeLabel":"string"},"type":"array","uniqueKey":"flags","typeLabel":"string[]"},"handoff":{"additionalProperties":false,"description":"Post-completion hand-off carried when a session that began from an entry link completes. Present only when `status` is `complete` and the session carried a validated entry context. `redirect` holds a brand-allowlisted https URL; `promo` is an opaque pass-through token validated downstream; `test` is the per-client test-mode flag. Never carries patient data.","properties":{"promo":{"maxLength":256,"type":"string","uniqueKey":"handoff.promo","typeLabel":"string"},"redirect":{"maxLength":2048,"type":"string","uniqueKey":"handoff.redirect","typeLabel":"string"},"test":{"type":"boolean","uniqueKey":"handoff.test","typeLabel":"boolean"}},"type":"object","uniqueKey":"handoff","typeLabel":"object"},"issues":{"items":{"properties":{"code":{"type":"string","isRequired":true,"uniqueKey":"issues.items.[INDEX].code","typeLabel":"string"},"message":{"type":"string","isRequired":true,"uniqueKey":"issues.items.[INDEX].message","typeLabel":"string"},"conflicting_codes":{"description":"Paired with `exclusive_codes`. The option code(s) the exclusive selection contradicted — the other half of \"which options clashed\". When the submission carried only exclusive options, they contradict each other and both lists name them.","items":{"type":"string","uniqueKey":"issues.items.[INDEX].conflicting_codes.items.[INDEX]","typeLabel":"string"},"type":"array","uniqueKey":"issues.items.[INDEX].conflicting_codes","typeLabel":"string[]"},"exclusive_codes":{"description":"Present ONLY on `code: renderer.exclusive_violation`, absent on every other issue. The exclusive (\"none of these\"-class) option code(s) the refused submission carried. A contradictory selection on a clinical-safety question is a SERVE defect, not a client nicety: the server refuses it with a 422 and never a 200-advance, and the refusal must say WHICH selections contradicted so the client can correct the exact ones. These are the caller's OWN submitted codes echoed back to the caller.","items":{"type":"string","uniqueKey":"issues.items.[INDEX].exclusive_codes.items.[INDEX]","typeLabel":"string"},"type":"array","uniqueKey":"issues.items.[INDEX].exclusive_codes","typeLabel":"string[]"}},"required":["code","message"],"type":"object","uniqueKey":"issues.items.[INDEX]","typeLabel":"object"},"type":"array","uniqueKey":"issues","typeLabel":"object[]"},"node":{"oneOf":[{"type":"object","description":"A node as presented to the client — PRESENTATION ONLY. The client never owns the sequence, controls, or option order (those come from the compiled bundle; a brand theme cannot alter them). Brand theme/copy, when applied, ride alongside as presentation overlay.","required":["node_id","kind","section_id"],"properties":{"kind":{"description":"`question` (collects a fact), `display` (an informational node with no answer channel), or `consent` (a consent-capture affirmation surface — its clinician/counsel-locked copy rides `content`, its `consent_version` + `grants` ride alongside). A `consent` node comes in TWO KINDS under ONE shape: the treatment consent (no `consent_kind`; binds no fact; a decline ends the session with an honest stop screen) and `communications_consent` (see `consent_kind`; never blocks, grants nothing, and the server records BOTH outcomes itself).","enum":["question","display","consent"],"type":"string","isRequired":true,"uniqueKey":"node.oneOf.0.kind","typeLabel":"enum\u003cstring>"},"node_id":{"type":"string","isRequired":true,"uniqueKey":"node.oneOf.0.node_id","typeLabel":"string"},"section_id":{"type":"string","isRequired":true,"uniqueKey":"node.oneOf.0.section_id","typeLabel":"string"},"computed_stub":{"type":"boolean","uniqueKey":"node.oneOf.0.computed_stub","typeLabel":"boolean"},"consent_kind":{"description":"the consent node's SUB-KIND. Present ONLY on a `communications_consent` node (the email opt-in and the SMS consents); ABSENT on a treatment consent, whose decline ends the session with an honest stop screen. THE AFFORDANCES DIFFER, which is why it is served: on this kind the client offers one affirmative action AND an explicit \"No thanks\", both outcomes are recorded as an auditable fact with the served copy version, Continue with neither is recorded as not-granted, and NO outcome ever blocks the intake or terminates the session. A client that cannot distinguish the two kinds either hides a lawful decline or offers one that ends a member's intake. It carries no fact code: the server records the outcome under its own write key, and the stable code stays the server's binding.","enum":["communications_consent"],"type":"string","uniqueKey":"node.oneOf.0.consent_kind","typeLabel":"enum\u003cstring>"},"consent_version":{"description":"the consent version served on a `consent` node. The client echoes it on the affirmation; it rides into the recorded consent fact as provenance. The MD/counsel-locked affirmation copy rides `content`; brand can never supply it.","type":"string","uniqueKey":"node.oneOf.0.consent_version","typeLabel":"string"},"content":{"additionalProperties":{"type":"string","uniqueKey":"node.oneOf.0.content.additionalProperties","typeLabel":"string"},"description":"Named display-content slots for a display node — MD-locked copy carried in the compiled instrument bundle, versioned and reviewed with the instrument. Brand config themes presentation only and cannot supply or override these slots, with ONE narrow exception: in the two instrument-furniture slots (`start_greeting`, `acknowledgement_documents`) and in a consent node's counsel-locked text, the platform substitutes the brand's REGISTERED IDENTITY — its display name and its registered legal-document URLs — into fixed token positions the instrument itself authors. That is substitution of an identity value into MD-authored wording, never brand-supplied WORDING: a brand still cannot contribute one word of a clinical question prompt or option label, which remain structurally unreachable. The `copy` field is the separate question-headline channel; its authoritative source is likewise the MD-locked instrument bundle, and the brand overlay can never override it.","type":"object","uniqueKey":"node.oneOf.0.content","typeLabel":"object"},"control":{"type":"string","uniqueKey":"node.oneOf.0.control","typeLabel":"string"},"copy":{"description":"The question headline, as a single string, served from the MD-locked question prompt in the compiled instrument bundle (versioned and reviewed with the instrument). For a question node this is its only source — the per-brand copy overlay can never supply or override it (theming yes, wording never). Absent is valid; the renderer falls back deterministically (for example a formatted fact code).","type":"string","uniqueKey":"node.oneOf.0.copy","typeLabel":"string"},"display":{"enum":["static","computed"],"type":"string","uniqueKey":"node.oneOf.0.display","typeLabel":"enum\u003cstring>"},"fact":{"type":"string","uniqueKey":"node.oneOf.0.fact","typeLabel":"string"},"grants":{"description":"the consent scopes an affirmative answer grants on a `consent` node. Codes, never labels; nothing branches on the copy text. A `communications_consent` node grants nothing, so this is the empty list there — it can never tell a client which kind of consent card it is looking at; `consent_kind` is that signal.","items":{"type":"string","uniqueKey":"node.oneOf.0.grants.items.[INDEX]","typeLabel":"string"},"type":"array","uniqueKey":"node.oneOf.0.grants","typeLabel":"string[]"},"interstitial":{"description":"Marks a display node as an interstitial moment for skin treatment (the tint pair is reserved for these). Presentation flag only; never carried on question nodes.","type":"boolean","uniqueKey":"node.oneOf.0.interstitial","typeLabel":"boolean"},"may_auto_advance":{"type":"boolean","uniqueKey":"node.oneOf.0.may_auto_advance","typeLabel":"boolean"},"media":{"description":"Capture configuration for a file-capture question. When absent, the question is a standard photo or document upload. Presentation and capture-bounds only — the answer is an upload reference and nothing branches on the media content; faces and voices are never matched, recognized, or graphed.","properties":{"kind":{"enum":["image","video"],"type":"string","isRequired":true,"uniqueKey":"node.oneOf.0.media.kind","typeLabel":"enum\u003cstring>"},"accept":{"description":"MIME allowlist (e.g. video/mp4, video/webm)","items":{"type":"string","uniqueKey":"node.oneOf.0.media.accept.items.[INDEX]","typeLabel":"string"},"type":"array","uniqueKey":"node.oneOf.0.media.accept","typeLabel":"string[]"},"capture_mode":{"enum":["upload","record","record_or_upload"],"type":"string","uniqueKey":"node.oneOf.0.media.capture_mode","typeLabel":"enum\u003cstring>"},"consent_copy":{"description":"The PLAIN DISPLAY TEXT the member must be shown before any affirmative action, pinned to `consent_version`. The portal renders THIS EXACT text; it is not a key, not a template, and the client never substitutes its own wording — consent to copy the server did not serve is not consent. Optional on the contract because non-video captures may not gate on consent at all, but REQUIRED (nonempty) for a managed video capture alongside `consent_version` and `consent_fact`: all three, or no grant and no recorded consent. Authored and served through the same MediaConfig, so the text the member reads and the version the server records can never drift apart.","type":"string","uniqueKey":"node.oneOf.0.media.consent_copy","typeLabel":"string"},"consent_fact":{"description":"fact code the consent acknowledgment projects to (discrete auditable consent fact)","type":"string","uniqueKey":"node.oneOf.0.media.consent_fact","typeLabel":"string"},"consent_version":{"description":"the version OF RECORD for the consent copy below. The server checks the echoed version against this one and records it on the acknowledgment; there is NO versionless fallback — a managed video capture whose node omits this refuses rather than recording a consent that cannot say which copy was agreed to.","type":"string","uniqueKey":"node.oneOf.0.media.consent_version","typeLabel":"string"},"facing":{"description":"advisory front/rear camera hint; not enforced","enum":["user","environment"],"type":"string","uniqueKey":"node.oneOf.0.media.facing","typeLabel":"enum\u003cstring>"},"max_bytes":{"type":"integer","uniqueKey":"node.oneOf.0.media.max_bytes","typeLabel":"integer"},"max_duration_s":{"type":"number","uniqueKey":"node.oneOf.0.media.max_duration_s","typeLabel":"number"},"min_duration_s":{"type":"number","uniqueKey":"node.oneOf.0.media.min_duration_s","typeLabel":"number"},"require_consent":{"description":"gate capture on a consent-to-record acknowledgment (video ⇒ true)","type":"boolean","uniqueKey":"node.oneOf.0.media.require_consent","typeLabel":"boolean"},"resumable":{"type":"boolean","uniqueKey":"node.oneOf.0.media.resumable","typeLabel":"boolean"}},"required":["kind"],"type":"object","uniqueKey":"node.oneOf.0.media","typeLabel":"object"},"offering_refs":{"items":{"type":"string","uniqueKey":"node.oneOf.0.offering_refs.items.[INDEX]","typeLabel":"string"},"type":"array","uniqueKey":"node.oneOf.0.offering_refs","typeLabel":"string[]"},"option_codes":{"items":{"type":"string","uniqueKey":"node.oneOf.0.option_codes.items.[INDEX]","typeLabel":"string"},"type":"array","uniqueKey":"node.oneOf.0.option_codes","typeLabel":"string[]"},"options":{"description":"Per-option presentation hints for this question. When present, it lists the same codes in the same order as `option_codes` — option order comes from the questionnaire and cannot be altered by theming. When absent, render from `option_codes` alone.","items":{"description":"One selectable option with its presentation hints — presentation only, carried alongside `option_codes`. An `exclusive` option (a \"none of these\"-class choice) cannot be combined with any sibling — selecting it should clear the other selections, and the server rejects an answer that carries an exclusive code together with another selection (`422`, the session does not advance). A banded choice (for example a blood-pressure or frequency range) may carry a `classification_code` alongside its stable option code.","properties":{"code":{"description":"the stable option code submitted as the answer value","type":"string","isRequired":true,"uniqueKey":"node.oneOf.0.options.items.[INDEX].code","typeLabel":"string"},"classification_code":{"description":"classification code carried by a banded choice alongside its stable option code","type":"string","uniqueKey":"node.oneOf.0.options.items.[INDEX].classification_code","typeLabel":"string"},"exclusive":{"description":"marks a \"none of these\"-class option that cannot be combined with any sibling selection","type":"boolean","uniqueKey":"node.oneOf.0.options.items.[INDEX].exclusive","typeLabel":"boolean"},"label":{"description":"MD-locked display label for this option, carried in the compiled instrument bundle and resolved by the stable option code (never positional). Presentation only — the code remains the submitted answer value and the sole binding; consumers fall back to the code when no label is present.","type":"string","uniqueKey":"node.oneOf.0.options.items.[INDEX].label","typeLabel":"string"}},"required":["code"],"type":"object","uniqueKey":"node.oneOf.0.options.items.[INDEX]","typeLabel":"object"},"type":"array","uniqueKey":"node.oneOf.0.options","typeLabel":"object[]"},"page":{"description":"Present ONLY on a question node whose value was staged from the member's OWN checkout destination record (always paired with `prefill: confirm` and a populated `prefilled_value`). Names the one leading page (\"Confirm your details\") the four contact nodes — name, email, phone, state — collapse onto with edit-in-place. A presentation grouping hint only, exactly like `interstitial` above: the server still walks one node at a time (resolve -> next -> ...); a client groups consecutive `confirm_details` nodes onto one screen without any change to the answer protocol. WHAT A CONFIRM DOES: confirming one of these nodes RECORDS that your patient affirmed the value shown — the same durable assertion any other confirm writes. It does not write a correction, because there was nothing to correct. Editing instead writes the edited value, superseding it, exactly like any other answered question. WHAT IS SHOWN IS ALWAYS A VALID ANSWER TO THE QUESTION: for a question whose answers are option codes, the `prefilled_value` is one of that node's own `option_codes`, promoted from the checkout record's postal spelling. A checkout value that cannot be resolved onto one of those options — an unfamiliar spelling, a region the question does not offer, a blank, a half-composed name — is NOT shown: that node arrives as an ordinary open question with no `page` and no `prefilled_value`, and your patient answers it normally. Absent on every other node.","enum":["confirm_details"],"type":"string","uniqueKey":"node.oneOf.0.page","typeLabel":"enum\u003cstring>"},"prefill":{"enum":["collect","suppress","confirm"],"type":"string","uniqueKey":"node.oneOf.0.prefill","typeLabel":"enum\u003cstring>"},"prefilled_value":{"oneOf":[{}],"uniqueKey":"node.oneOf.0.prefilled_value","typeLabel":"any"},"reassurance":{"description":"A single hedged reassurance line for a computed display panel, served from the MD-locked instrument content and reviewed with it. The line is SELECTED server-side by where the primary computed value falls against the served zone (below / in_zone / above) — never served statically — and is PRESENT only when the matching band is authored and the band could be determined; otherwise it is ABSENT (fail to neutral). Display copy only; it carries no eligibility language and defers every decision to the clinician.","type":"string","uniqueKey":"node.oneOf.0.reassurance","typeLabel":"string"},"required":{"type":"boolean","uniqueKey":"node.oneOf.0.required","typeLabel":"boolean"},"theme":{"additionalProperties":true,"type":"object","uniqueKey":"node.oneOf.0.theme","typeLabel":"object"},"unit":{"description":"The unit a question's answer is expressed in (for example \"in\" or \"lb\"), served from the question's MD-locked copy in the compiled instrument bundle, beside its prompt. Present only on a question node whose instrument authors a non-blank unit; absent otherwise. When absent the client shows no unit and never infers one — in particular never from the fact code. The per-brand overlay can never supply or override it. Display text only; nothing branches on it.","type":"string","uniqueKey":"node.oneOf.0.unit","typeLabel":"string"},"values":{"additionalProperties":{"oneOf":[{}],"uniqueKey":"node.oneOf.0.values.additionalProperties","typeLabel":"any"},"description":"Server-supplied display values keyed by fact/derivation CODE (codes, never label text). Derived codes are computed server-side on read from registered pure derivations — the client renders these values and never computes anything of record. A display node whose primary referenced values cannot all be resolved is never emitted (server-skipped, fail-soft). Ancillary echoed values (for example the height and weight behind a computed number) ride this same map alongside the primary value; an echoed value that cannot be resolved is omitted, and never blocks the node.","type":"object","uniqueKey":"node.oneOf.0.values","typeLabel":"object"},"zone":{"description":"A designed-panel band descriptor for a computed display node: a scale from `scale_min` to `scale_max` with a highlighted band from `zone_min` to `zone_max`, named by `zone_label`. The client places the patient's marker and the highlighted band for the picture. Display copy and presentation only — a zone carries no eligibility language and never asserts eligibility; the server remains authoritative on jurisdiction and eligibility.","properties":{"scale_max":{"description":"high end of the rendered scale axis","type":"number","isRequired":true,"uniqueKey":"node.oneOf.0.zone.scale_max","typeLabel":"number"},"scale_min":{"description":"low end of the rendered scale axis","type":"number","isRequired":true,"uniqueKey":"node.oneOf.0.zone.scale_min","typeLabel":"number"},"zone_label":{"description":"label naming the highlighted band (display copy; never an outcome)","type":"string","isRequired":true,"uniqueKey":"node.oneOf.0.zone.zone_label","typeLabel":"string"},"zone_max":{"description":"high bound of the highlighted band (within the scale)","type":"number","isRequired":true,"uniqueKey":"node.oneOf.0.zone.zone_max","typeLabel":"number"},"zone_min":{"description":"low bound of the highlighted band (within the scale)","type":"number","isRequired":true,"uniqueKey":"node.oneOf.0.zone.zone_min","typeLabel":"number"}},"required":["scale_min","scale_max","zone_min","zone_max","zone_label"],"type":"object","uniqueKey":"node.oneOf.0.zone","typeLabel":"object"}},"uniqueKey":"node.oneOf.0","typeLabel":"object"},{"type":"null","uniqueKey":"node.oneOf.1","typeLabel":"null"}],"uniqueKey":"node","typeLabel":"object | null"},"patient_readiness":{"type":"object","description":"Present on a resolve: whether your brand is ready for patients, and what is still missing if not. The questionnaire is served either way.","required":["status","consent_holder","required_documents","missing"],"properties":{"consent_holder":{"description":"who holds the brand's consent documents, as chosen; `not_chosen` until someone chooses.","enum":["purple","client","not_chosen"],"type":"string","isRequired":true,"uniqueKey":"patient_readiness.consent_holder","typeLabel":"enum\u003cstring>"},"missing":{"description":"every required item still unset; empty exactly when `status` is `patient_ready`.","items":{"additionalProperties":false,"properties":{"detail":{"description":"what is missing and how to set it, in plain words.","type":"string","isRequired":true,"uniqueKey":"patient_readiness.missing.items.[INDEX].detail","typeLabel":"string"},"item":{"enum":["display_name","consent_holder","legal_document","readiness_unknown"],"type":"string","isRequired":true,"uniqueKey":"patient_readiness.missing.items.[INDEX].item","typeLabel":"enum\u003cstring>"},"document":{"description":"for `legal_document`, which document is missing.","enum":["terms","privacy","telehealth"],"type":"string","uniqueKey":"patient_readiness.missing.items.[INDEX].document","typeLabel":"enum\u003cstring>"}},"required":["item","detail"],"type":"object","uniqueKey":"patient_readiness.missing.items.[INDEX]","typeLabel":"object"},"type":"array","isRequired":true,"uniqueKey":"patient_readiness.missing","typeLabel":"object[]"},"required_documents":{"description":"the documents the brand's served consents link to (empty when that cannot be told yet).","items":{"enum":["terms","privacy","telehealth"],"type":"string","uniqueKey":"patient_readiness.required_documents.items.[INDEX]","typeLabel":"enum\u003cstring>"},"type":"array","isRequired":true,"uniqueKey":"patient_readiness.required_documents","typeLabel":"enum\u003cstring>[]"},"status":{"enum":["patient_ready","not_patient_ready"],"type":"string","isRequired":true,"uniqueKey":"patient_readiness.status","typeLabel":"enum\u003cstring>"}},"additionalProperties":false,"uniqueKey":"patient_readiness","typeLabel":"object"},"progress":{"description":"Server-computed progress metadata, present on every resolve/next step: computed from the live effective plan — never client-guessed. `position_estimate` is the honest fraction of the plan completed (0..1); display nodes participate in the fraction. Whether and how it renders (thin persistent bar, step ring, interstitial pacing, none) is brand-theme presentation.","properties":{"position_estimate":{"description":"honest fraction of the effective plan completed, 0..1","maximum":1,"minimum":0,"type":"number","isRequired":true,"uniqueKey":"progress.position_estimate","typeLabel":"number"},"scope":{"description":"`instrument`, or a subflow id once named optional sub-flows ship","type":"string","isRequired":true,"uniqueKey":"progress.scope","typeLabel":"string"},"section_label":{"description":"optional server-supplied section label; omitted while bundles carry none","type":"string","uniqueKey":"progress.section_label","typeLabel":"string"}},"required":["scope","position_estimate"],"type":"object","uniqueKey":"progress","typeLabel":"object"}},"required":["session_id","journey_id","status"],"type":"object","uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"journey_id":"\u003cstring>","session_id":"\u003cstring>","status":"active","blocked":{"code":"\u003cstring>","node_id":"\u003cstring>","content":{},"support_route":"\u003cstring>","ungranted_scopes":["\u003cstring>"]},"destination_capability":"\u003cstring>","flags":["\u003cstring>"],"handoff":{"promo":"\u003cstring>","redirect":"\u003cstring>","test":true},"issues":[{"code":"\u003cstring>","message":"\u003cstring>","conflicting_codes":["\u003cstring>"],"exclusive_codes":["\u003cstring>"]}],"node":{"kind":"question","node_id":"\u003cstring>","section_id":"\u003cstring>","computed_stub":true,"consent_kind":"communications_consent","consent_version":"\u003cstring>","content":{},"control":"\u003cstring>","copy":"\u003cstring>","display":"static","fact":"\u003cstring>","grants":["\u003cstring>"],"interstitial":true,"may_auto_advance":true,"media":{"kind":"image","accept":["\u003cstring>"],"capture_mode":"upload","consent_copy":"\u003cstring>","consent_fact":"\u003cstring>","consent_version":"\u003cstring>","facing":"user","max_bytes":123,"max_duration_s":123,"min_duration_s":123,"require_consent":true,"resumable":true},"offering_refs":["\u003cstring>"],"option_codes":["\u003cstring>"],"options":[{"code":"\u003cstring>","classification_code":"\u003cstring>","exclusive":true,"label":"\u003cstring>"}],"page":"confirm_details","prefill":"collect","prefilled_value":"\u003cunknown>","reassurance":"\u003cstring>","required":true,"theme":{},"unit":"\u003cstring>","values":{},"zone":{"scale_max":123,"scale_min":123,"zone_label":"\u003cstring>","zone_max":123,"zone_min":123}},"patient_readiness":{"consent_holder":"purple","missing":[{"detail":"\u003cstring>","item":"display_name","document":"terms"}],"required_documents":["terms"],"status":"patient_ready"},"progress":{"position_estimate":0.5,"scope":"\u003cstring>","section_label":"\u003cstring>"}}}},"exampleType":"generated"}},"description":"server-side control rejection, a keyed submit for a node the session has not reached (`renderer.node_mismatch`), or a question the served questionnaire cannot define an answer contract for (`renderer.fact_unavailable` — a server-side configuration gap, surfaced with the question re-served and nothing recorded); no advance. MEDIA ATTACHMENT: when the node the session is ON is a `file_capture`, the answer MUST carry an upload reference that resolves to a grant issued to this member for THIS journey and THIS node, whose bytes have landed. Anything else — an unknown reference, an absent one, a reference the grant store no longer holds (a task roll), or media dependencies being unavailable — is refused here under the `intake-media-attachment-refused` problem type, with nothing recorded and no advance. UNLIKE the control-issue 422 above, this one is application/problem+json (EdgeProblem-shaped) rather than a re-presented step — a consumer distinguishes them by content type, and every cause answers the ONE body so the wire carries no oracle. The requirement is derived from the NODE, so ordinary answers to non-capture questions are unaffected and no value is ever inspected to decide whether the rule applies. CONTRADICTORY SELECTIONS: a submission that carries an option DECLARED `exclusive` alongside any other option is refused here under `renderer.exclusive_violation` — a named 422, never a 200-advance, with the question re-served and nothing recorded. The issue names WHICH options contradicted (`exclusive_codes` / `conflicting_codes`). A question whose options declare no `exclusive` flag is unaffected. An option set the server cannot read is refused the same way (`renderer.control.unknown_code`) and never becomes a 5xx.","exampleType":"generated"},"2a4f8ac2-31d9-45bb-97f9-53df5846472e":{"content":{"application/problem+json":{"schema":{"description":"RFC 7807 problem+json error body.","properties":{"status":{"type":"integer","isRequired":true,"uniqueKey":"status","typeLabel":"integer"},"title":{"type":"string","isRequired":true,"uniqueKey":"title","typeLabel":"string"},"type":{"format":"uri-reference","type":"string","isRequired":true,"uniqueKey":"type","typeLabel":"string\u003curi-reference>"},"detail":{"type":"string","uniqueKey":"detail","typeLabel":"string"}},"required":["type","title","status"],"type":"object","uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"status":123,"title":"\u003cstring>","type":"\u003cstring>","detail":"\u003cstring>"}}},"exampleType":"generated"}},"description":"Too many requests. You have exceeded the request rate allowed for this endpoint. Wait the number of seconds given in the Retry-After response header, then retry the request.","headers":{"Retry-After":{"description":"Seconds to wait before you retry.","schema":{"type":"integer"}},"X-Correlation-Id":{"description":"The correlation id for this request, echoed back.","schema":{"type":"string"}}},"exampleType":"generated"},"7cb6a93c-8de3-4e1e-87ac-2a976ec28c71":{"content":{"application/problem+json":{"schema":{"description":"RFC 7807 problem+json error body.","properties":{"status":{"type":"integer","isRequired":true,"uniqueKey":"status","typeLabel":"integer"},"title":{"type":"string","isRequired":true,"uniqueKey":"title","typeLabel":"string"},"type":{"format":"uri-reference","type":"string","isRequired":true,"uniqueKey":"type","typeLabel":"string\u003curi-reference>"},"detail":{"type":"string","uniqueKey":"detail","typeLabel":"string"}},"required":["type","title","status"],"type":"object","uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"status":123,"title":"\u003cstring>","type":"\u003cstring>","detail":"\u003cstring>"}}},"exampleType":"generated"}},"description":"The answer could not be recorded, and sending it again will never change that — this is the one response on this operation you must not retry. A single problem `type` is answered here: `instrument-answer-not-recordable` — the questionnaire service received the submission, understood it, and refused to record it outright, so the identical answer sent again earns the identical refusal at every future moment. The fault is on this service's side, not with anything your patient entered: a rejection your patient can act on is the `422` above, which re-serves the question with the issues named. Nothing was recorded and the session did not advance. No `Retry-After` accompanies this response and no delay clears it — do not retry automatically, and do not offer your patient a retry for it. Send them to human support and quote the correlation id, which is what lets the underlying condition be found and repaired.","exampleType":"generated"},"0b5b1e7b-d5ce-49a9-a08d-4d7a6e987809":{"content":{"application/problem+json":{"schema":{"description":"RFC 7807 problem+json error body.","properties":{"status":{"type":"integer","isRequired":true,"uniqueKey":"status","typeLabel":"integer"},"title":{"type":"string","isRequired":true,"uniqueKey":"title","typeLabel":"string"},"type":{"format":"uri-reference","type":"string","isRequired":true,"uniqueKey":"type","typeLabel":"string\u003curi-reference>"},"detail":{"type":"string","uniqueKey":"detail","typeLabel":"string"}},"required":["type","title","status"],"type":"object","uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"status":123,"title":"\u003cstring>","type":"\u003cstring>","detail":"\u003cstring>"}}},"exampleType":"generated"}},"description":"The step could not be completed right now. Two distinct problem `type`s are declared here and they are cured differently: `instrument-answer-store-unavailable` — the questionnaire served fine but the answer could not be SAVED, so nothing was recorded and the session did not move on; `instrument-bundle-unavailable` — the questionnaire itself is still being loaded. Both are transient — nothing answered, or what answered reported a fault of its own — so re-submitting the same answer shortly is the cure. A refusal that no amount of re-submission can clear is never answered here: it takes the `500` above, under its own problem `type`. In practice this operation answers `instrument-answer-store-unavailable`. A request whose session is not one this brand can recognise is answered with the `404` above before the questionnaire is looked up at all, and a session that passes that check already carries the questionnaire it started under — so this operation never waits for one to load. `instrument-bundle-unavailable` stays declared here, and is the answer to expect from the resolve operation, which is the one that loads a questionnaire. A third type, `intake-payment-unconfirmed`, is answered BEFORE the answer is looked at when this treatment's questions start after payment and the payment could not be confirmed right now (the order read failed). Nothing was recorded; `Retry-After: 60`. It is never an answer that the order is unpaid — that is the `402`.","exampleType":"generated"}},"security":{"b179300c-8792-4ce8-aa92-381dbc634731":{"apiKey":{"description":"Per-client API key (M2M). Presented as `Authorization: Bearer \u003ckey>`.","scheme":"bearer","type":"http","scopes":[],"schemeName":"apiKey"}}},"servers":{"76f2c082-b62c-4aea-a087-a046f1378296":{"url":"https://api.staging.purplelabelmd.com"}},"processedSecurityOptions":[{"schemes":[{"scheme":{"description":"Per-client API key (M2M). Presented as `Authorization: Bearer \u003ckey>`.","scheme":"bearer","type":"http","scopes":[],"schemeName":"apiKey"},"schema":{"title":"Bearer Auth","type":"string","isRequired":true,"description":"Per-client API key (M2M). Presented as `Authorization: Bearer \u003ckey>`.","format":"bearer","typeLabel":"string\u003cbearer>","deprecated":false},"schemeName":"apiKey","name":"Authorization"}],"title":"apiKey"}]},"originalFileLocation":"openapi/public-openapi.json"},"subdomain":"purplelabelmd","siteName":"Purple Label MD","title":"Submit an answer and get the next question - Purple Label MD","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-11-12T04:48:53.064Z","originalFileLocation":"api-reference/intake/submit-an-answer-and-get-the-next-question.mdx"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=null;if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"system\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"Submits the answer to the question the session is currently on. The answer is re-validated on the server and the session advances exactly one step, returning the next question — or status: complete once every required answer is in. The client never decides completion. If the answer fails validation the response is 422 with the specific issues and the session does not advance. Send node_id (the served node.node_id) to KEY the answer to its node: a stale replay of an already-passed node then resyncs cleanly (200, current node re-served) instead of misbinding to the node after a server-side skip, and a submit for a node the session has not reached fails closed with a renderer.node_mismatch issue (422). This op never presents a question that collects a government ID, and never waits on one to report complete — proof of identity is handled in the member portal\u0026#x27;s identity step, not here.\">\u003cmeta data-mint-head name=\"application-name\" content=\"Purple Label MD\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/purplelabelmd/TU4Si8SnCOFGjzcC/_generated/favicon/android-chrome-192x192.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/png\" sizes=\"180x180\" href=\"/mintlify-assets/_mintlify/favicons/purplelabelmd/TU4Si8SnCOFGjzcC/_generated/favicon/apple-touch-icon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/purplelabelmd/TU4Si8SnCOFGjzcC/_generated/favicon/favicon-16x16.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/purplelabelmd/TU4Si8SnCOFGjzcC/_generated/favicon/favicon-32x32.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/purplelabelmd/TU4Si8SnCOFGjzcC/_generated/favicon/favicon.ico\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/purplelabelmd/TU4Si8SnCOFGjzcC/_generated/favicon-dark/android-chrome-192x192.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/purplelabelmd/TU4Si8SnCOFGjzcC/_generated/favicon-dark/favicon-16x16.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/purplelabelmd/TU4Si8SnCOFGjzcC/_generated/favicon-dark/favicon-32x32.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/purplelabelmd/TU4Si8SnCOFGjzcC/_generated/favicon-dark/favicon.ico\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"Submit an answer and get the next question - Purple Label MD\">\u003cmeta data-mint-head property=\"og:description\" content=\"Submits the answer to the question the session is currently on. The answer is re-validated on the server and the session advances exactly one step, returning the next question — or status: complete once every required answer is in. The client never decides completion. If the answer fails validation the response is 422 with the specific issues and the session does not advance. Send node_id (the served node.node_id) to KEY the answer to its node: a stale replay of an already-passed node then resyncs cleanly (200, current node re-served) instead of misbinding to the node after a server-side skip, and a submit for a node the session has not reached fails closed with a renderer.node_mismatch issue (422). This op never presents a question that collects a government ID, and never waits on one to report complete — proof of identity is handled in the member portal\u0026#x27;s identity step, not here.\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"Purple Label MD\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://docs.purplelabelmd.com/api-reference/intake/submit-an-answer-and-get-the-next-question\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://purplelabelmd.mintlify.site/_mintlify/api/og/v2?division=Intake\u0026amp;title=Submit+an+answer+and+get+the+next+question\u0026amp;description=Submits+the+answer+to+the+question+the+session+is+currently+on.+The+answer+is+re-validated+on+the+server+and+the+session+advances+exactly+one+step%2C+returning+th\u0026amp;theme=1cfc55286f6f85a93657a32a\u0026amp;signature=09d8c38d6595ee46a07d5e85cf77a59839d9e9baaacbeb79927c01ca1c6d22b4\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"Submit an answer and get the next question - Purple Label MD\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"Submits the answer to the question the session is currently on. The answer is re-validated on the server and the session advances exactly one step, returning the next question — or status: complete once every required answer is in. The client never decides completion. If the answer fails validation the response is 422 with the specific issues and the session does not advance. Send node_id (the served node.node_id) to KEY the answer to its node: a stale replay of an already-passed node then resyncs cleanly (200, current node re-served) instead of misbinding to the node after a server-side skip, and a submit for a node the session has not reached fails closed with a renderer.node_mismatch issue (422). This op never presents a question that collects a government ID, and never waits on one to report complete — proof of identity is handled in the member portal\u0026#x27;s identity step, not here.\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://purplelabelmd.mintlify.site/_mintlify/api/og/v2?division=Intake\u0026amp;title=Submit+an+answer+and+get+the+next+question\u0026amp;description=Submits+the+answer+to+the+question+the+session+is+currently+on.+The+answer+is+re-validated+on+the+server+and+the+session+advances+exactly+one+step%2C+returning+th\u0026amp;theme=1cfc55286f6f85a93657a32a\u0026amp;signature=09d8c38d6595ee46a07d5e85cf77a59839d9e9baaacbeb79927c01ca1c6d22b4\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"/mintlify-assets/_mintlify/favicons/purplelabelmd/TU4Si8SnCOFGjzcC/_generated/favicon/browserconfig.xml\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"Purple Label MD\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#6D28D9\">\u003clink data-mint-head rel=\"canonical\" href=\"https://docs.purplelabelmd.com/api-reference/intake/submit-an-answer-and-get-the-next-question\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/api-reference/intake/submit-an-answer-and-get-the-next-question.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://docs.purplelabelmd.com/#organization\",\"name\":\"Purple Label MD\",\"url\":\"https://docs.purplelabelmd.com\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://mintcdn.com/purplelabelmd/1P9p4n7lsNL4z3Jc/logo/light.svg?fit=max\u0026auto=format\u0026n=1P9p4n7lsNL4z3Jc\u0026q=85\u0026s=3c0569e3f76e49e04d232187908c2e2e\"}},{\"@type\":\"WebSite\",\"@id\":\"https://docs.purplelabelmd.com#website\",\"name\":\"Purple Label MD\",\"url\":\"https://docs.purplelabelmd.com\",\"publisher\":{\"@id\":\"https://docs.purplelabelmd.com/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://docs.purplelabelmd.com/api-reference/intake/submit-an-answer-and-get-the-next-question#webpage\",\"url\":\"https://docs.purplelabelmd.com/api-reference/intake/submit-an-answer-and-get-the-next-question\",\"name\":\"Submit an answer and get the next question\",\"description\":\"Submits the answer to the question the session is currently on. The answer is re-validated on the server and the session advances exactly one step, returning the next question — or status: complete once every required answer is in. The client never decides completion. If the answer fails validation the response is 422 with the specific issues and the session does not advance. Send node_id (the served node.node_id) to KEY the answer to its node: a stale replay of an already-passed node then resyncs cleanly (200, current node re-served) instead of misbinding to the node after a server-side skip, and a submit for a node the session has not reached fails closed with a renderer.node_mismatch issue (422). This op never presents a question that collects a government ID, and never waits on one to report complete — proof of identity is handled in the member portal's identity step, not here.\",\"dateModified\":\"2026-11-12T04:48:53.064Z\",\"isPartOf\":{\"@id\":\"https://docs.purplelabelmd.com#website\"},\"breadcrumb\":{\"@id\":\"https://docs.purplelabelmd.com/api-reference/intake/submit-an-answer-and-get-the-next-question#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://docs.purplelabelmd.com/api-reference/intake/submit-an-answer-and-get-the-next-question#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Intake\",\"item\":\"https://docs.purplelabelmd.com/api-reference/intake/record-that-your-patient-dropped-off-the-questionnaire\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Submit an answer and get the next question\",\"item\":\"https://docs.purplelabelmd.com/api-reference/intake/submit-an-answer-and-get-the-next-question\"}]},{\"@type\":[\"TechArticle\",\"APIReference\"],\"@id\":\"https://docs.purplelabelmd.com/api-reference/intake/submit-an-answer-and-get-the-next-question#apireference\",\"headline\":\"Submit an answer and get the next question\",\"name\":\"Submit an answer and get the next question\",\"description\":\"Submits the answer to the question the session is currently on. The answer is re-validated on the server and the session advances exactly one step, returning the next question — or status: complete once every required answer is in. The client never decides completion. If the answer fails validation the response is 422 with the specific issues and the session does not advance. Send node_id (the served node.node_id) to KEY the answer to its node: a stale replay of an already-passed node then resyncs cleanly (200, current node re-served) instead of misbinding to the node after a server-side skip, and a submit for a node the session has not reached fails closed with a renderer.node_mismatch issue (422). This op never presents a question that collects a government ID, and never waits on one to report complete — proof of identity is handled in the member portal's identity step, not here.\",\"url\":\"https://docs.purplelabelmd.com/api-reference/intake/submit-an-answer-and-get-the-next-question\",\"mainEntityOfPage\":{\"@id\":\"https://docs.purplelabelmd.com/api-reference/intake/submit-an-answer-and-get-the-next-question#webpage\"},\"dateModified\":\"2026-11-12T04:48:53.064Z\",\"publisher\":{\"@id\":\"https://docs.purplelabelmd.com/#organization\"},\"isPartOf\":{\"@id\":\"https://docs.purplelabelmd.com#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"Purple Label MD\",\"publisher\":{\"@type\":\"Organization\",\"name\":\"Purple Label MD\"},\"provider\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","agentPointerHref":"/api-reference/intake/submit-an-answer-and-get-the-next-question.md","siteName":"Purple Label MD","nav":{"global":null,"tabs":[{"tab":"Guides","pages":[{"title":"Guides","href":"/pages/overview"}]},{"tab":"API reference","groups":[{"group":"Brand configuration","pages":[{"title":"Read back your brand's platform configuration","deprecated":null,"version":null,"openapi":"/openapi/public-openapi.json get /v1/account/brands/{brand_id}/config","href":"/api-reference/brand-configuration/read-back-your-brands-platform-configuration"},{"title":"Set your brand's display identity","deprecated":null,"version":null,"openapi":"/openapi/public-openapi.json put /v1/account/brands/{brand_id}/config","href":"/api-reference/brand-configuration/set-your-brands-display-identity"},{"title":"List your brand's custom domains","deprecated":null,"version":null,"openapi":"/openapi/public-openapi.json get /v1/account/brands/{brand_id}/domains","href":"/api-reference/brand-configuration/list-your-brands-custom-domains"},{"title":"Read the browser origins your storefront may read this brand from","deprecated":null,"version":null,"openapi":"/openapi/public-openapi.json get /v1/account/brands/{brand_id}/domains/member/browser-origins","href":"/api-reference/brand-configuration/read-the-browser-origins-your-storefront-may-read-this-brand-from"},{"title":"Replace the browser origins your storefront may read this brand from","deprecated":null,"version":null,"openapi":"/openapi/public-openapi.json put /v1/account/brands/{brand_id}/domains/member/browser-origins","href":"/api-reference/brand-configuration/replace-the-browser-origins-your-storefront-may-read-this-brand-from"},{"title":"Read one custom-domain row","deprecated":null,"version":null,"openapi":"/openapi/public-openapi.json get /v1/account/brands/{brand_id}/domains/{kind}","href":"/api-reference/brand-configuration/read-one-custom-domain-row"},{"title":"Choose a custom domain for a kind (client self-serve)","deprecated":null,"version":null,"openapi":"/openapi/public-openapi.json put /v1/account/brands/{brand_id}/domains/{kind}","href":"/api-reference/brand-configuration/choose-a-custom-domain-for-a-kind-client-self-serve"},{"title":"Remove a custom domain (revert to the shared domain)","deprecated":null,"version":null,"openapi":"/openapi/public-openapi.json delete /v1/account/brands/{brand_id}/domains/{kind}","href":"/api-reference/brand-configuration/remove-a-custom-domain-revert-to-the-shared-domain"},{"title":"Verify a custom domain and advance provisioning","deprecated":null,"version":null,"openapi":"/openapi/public-openapi.json post /v1/account/brands/{brand_id}/domains/{kind}/verify","href":"/api-reference/brand-configuration/verify-a-custom-domain-and-advance-provisioning"}]},{"group":"Offering configuration","pages":[{"title":"List your brand's enabled offerings","deprecated":null,"version":null,"openapi":"/openapi/public-openapi.json get /v1/account/brands/{brand_id}/offerings","href":"/api-reference/offering-configuration/list-your-brands-enabled-offerings"},{"title":"Enable an offering for your brand","deprecated":null,"version":null,"openapi":"/openapi/public-openapi.json post /v1/account/brands/{brand_id}/offerings","href":"/api-reference/offering-configuration/enable-an-offering-for-your-brand"},{"title":"Choose the billing cadence of an offering on your brand","deprecated":null,"version":null,"openapi":"/openapi/public-openapi.json put /v1/account/brands/{brand_id}/offerings/{offering_ref}/billing-cadence","href":"/api-reference/offering-configuration/choose-the-billing-cadence-of-an-offering-on-your-brand"},{"title":"Set your brand's price for an offering","deprecated":null,"version":null,"openapi":"/openapi/public-openapi.json put /v1/account/brands/{brand_id}/pricing","href":"/api-reference/offering-configuration/set-your-brands-price-for-an-offering"},{"title":"Adopt the starter merchandising pack for your brand","deprecated":null,"version":null,"openapi":"/openapi/public-openapi.json post /v1/account/brands/{brand_id}/starter-merchandising","href":"/api-reference/offering-configuration/adopt-the-starter-merchandising-pack-for-your-brand"},{"title":"Read an offering's composed qualification questions","deprecated":null,"version":null,"openapi":"/openapi/public-openapi.json get /v1/account/offerings/{offering_ref}/qualification","href":"/api-reference/offering-configuration/read-an-offerings-composed-qualification-questions"},{"title":"Add a library question to an offering","deprecated":null,"version":null,"openapi":"/openapi/public-openapi.json post /v1/account/offerings/{offering_ref}/qualification","href":"/api-reference/offering-configuration/add-a-library-question-to-an-offering"},{"title":"Reorder an offering's qualification questions","deprecated":null,"version":null,"openapi":"/openapi/public-openapi.json put /v1/account/offerings/{offering_ref}/qualification/order","href":"/api-reference/offering-configuration/reorder-an-offerings-qualification-questions"},{"title":"Publish an offering's qualification questions","deprecated":null,"version":null,"openapi":"/openapi/public-openapi.json post /v1/account/offerings/{offering_ref}/qualification/publish","href":"/api-reference/offering-configuration/publish-an-offerings-qualification-questions"},{"title":"Remove an offering's qualification question","deprecated":null,"version":null,"openapi":"/openapi/public-openapi.json delete /v1/account/offerings/{offering_ref}/qualification/questions/{question_id}","href":"/api-reference/offering-configuration/remove-an-offerings-qualification-question"},{"title":"Edit an offering's qualification question","deprecated":null,"version":null,"openapi":"/openapi/public-openapi.json patch /v1/account/offerings/{offering_ref}/qualification/questions/{question_id}","href":"/api-reference/offering-configuration/edit-an-offerings-qualification-question"},{"title":"Set the display name and presentation copy for your offering","deprecated":null,"version":null,"openapi":"/openapi/public-openapi.json put /v1/account/offerings/{ref}/merchandising","href":"/api-reference/offering-configuration/set-the-display-name-and-presentation-copy-for-your-offering"},{"title":"List the facts a qualification question may bind","deprecated":null,"version":null,"openapi":"/openapi/public-openapi.json get /v1/account/question-library/facts","href":"/api-reference/offering-configuration/list-the-facts-a-qualification-question-may-bind"},{"title":"Create a new screening fact for your brand","deprecated":null,"version":null,"openapi":"/openapi/public-openapi.json post /v1/account/question-library/minted-facts","href":"/api-reference/offering-configuration/create-a-new-screening-fact-for-your-brand"},{"title":"List your brand's qualification question library","deprecated":null,"version":null,"openapi":"/openapi/public-openapi.json get /v1/account/question-library/questions","href":"/api-reference/offering-configuration/list-your-brands-qualification-question-library"},{"title":"Create a qualification library question","deprecated":null,"version":null,"openapi":"/openapi/public-openapi.json post /v1/account/question-library/questions","href":"/api-reference/offering-configuration/create-a-qualification-library-question"},{"title":"Delete a qualification library question","deprecated":null,"version":null,"openapi":"/openapi/public-openapi.json delete /v1/account/question-library/questions/{question_id}","href":"/api-reference/offering-configuration/delete-a-qualification-library-question"},{"title":"Edit a qualification library question","deprecated":null,"version":null,"openapi":"/openapi/public-openapi.json patch /v1/account/question-library/questions/{question_id}","href":"/api-reference/offering-configuration/edit-a-qualification-library-question"}]},{"group":"Onboarding","pages":[{"title":"Check whether your brand is ready to sell","deprecated":null,"version":null,"openapi":"/openapi/public-openapi.json get /v1/account/brands/{brand_id}/readiness","href":"/api-reference/onboarding/check-whether-your-brand-is-ready-to-sell"},{"title":"Read one offering's price and whether your brand can sell it","deprecated":null,"version":null,"openapi":"/openapi/public-openapi.json get /v1/account/brands/{brand_id}/storefront","href":"/api-reference/onboarding/read-one-offerings-price-and-whether-your-brand-can-sell-it"},{"title":"Read a client's onboarding progress","deprecated":null,"version":null,"openapi":"/openapi/public-openapi.json get /v1/onboardings/{onboarding_id}/progress","href":"/api-reference/onboarding/read-a-clients-onboarding-progress"}]},{"group":"Payments","pages":[{"title":"List your orders across all your brands","deprecated":null,"version":null,"openapi":"/openapi/public-openapi.json get /v1/account/orders","href":"/api-reference/payments/list-your-orders-across-all-your-brands"},{"title":"Read one of your orders by reference","deprecated":null,"version":null,"openapi":"/openapi/public-openapi.json get /v1/account/orders/{order_ref}","href":"/api-reference/payments/read-one-of-your-orders-by-reference"},{"title":"Start a checkout session and get a token to collect payment","deprecated":null,"version":null,"openapi":"/openapi/public-openapi.json post /v1/payments/checkout-sessions","href":"/api-reference/payments/start-a-checkout-session-and-get-a-token-to-collect-payment"},{"title":"Read the payment status of an order","deprecated":null,"version":null,"openapi":"/openapi/public-openapi.json get /v1/payments/{order_ref}/status","href":"/api-reference/payments/read-the-payment-status-of-an-order"}]},{"group":"Sessions \u0026 authentication","pages":[{"title":"Complete login and start the patient session","deprecated":null,"version":null,"openapi":"/openapi/public-openapi.json get /v1/auth/callback","href":"/api-reference/sessions-\u0026-authentication/complete-login-and-start-the-patient-session"},{"title":"Begin Universal Login and redirect to the login page","deprecated":null,"version":null,"openapi":"/openapi/public-openapi.json get /v1/auth/login","href":"/api-reference/sessions-\u0026-authentication/begin-universal-login-and-redirect-to-the-login-page"},{"title":"Log out and end the patient's session","deprecated":null,"version":null,"openapi":"/openapi/public-openapi.json get /v1/auth/logout","href":"/api-reference/sessions-\u0026-authentication/log-out-and-end-the-patients-session"}]},{"group":"Intake","pages":[{"title":"Record that your patient dropped off the questionnaire","description":"Marks the intake session as dropped-off. Call this when a patient leaves without finishing so the drop-off is recorded against the session.","deprecated":null,"version":null,"openapi":"/openapi/public-openapi.json post /v1/instrument/abandon","href":"/api-reference/intake/record-that-your-patient-dropped-off-the-questionnaire"},{"title":"Submit an answer and get the next question","deprecated":null,"version":null,"openapi":"/openapi/public-openapi.json post /v1/instrument/next","href":"/api-reference/intake/submit-an-answer-and-get-the-next-question"},{"title":"Start an intake session and get the first question","description":"Begins an intake questionnaire for your patient and returns the first question to present. On the first call the server mints an enrollment id (returned as `journey_id`) that identifies the session on every later call; send it back in the `X-Journey-Id` request header on a return visit to resume. The server owns the question sequence, branching, and completion — a client cannot skip, hide, or reorder questions, and any value pre-filled from an entry link is always shown for explicit confirmation, never accepted on the patient's behalf. WHICH questionnaire is served follows your brand's configured therapies: a brand with exactly one enabled therapy always serves that therapy's questionnaire; a brand with more than one must name an `offering` on the entry link so the therapy is unambiguous. If that therapy's questionnaire is briefly still loading, the session opens on the platform's shared questionnaire rather than failing. If your brand's therapy has no questionnaire at all — none is published for it, or the brand is configured for a therapy this platform does not serve — the call is REFUSED (422) rather than answered with a different therapy's questions, which would be neither safe nor useful; and an error is likewise answered when no questionnaire is available at all. PROOF-OF-IDENTITY CAPTURE IS NEVER PART OF THIS QUESTIONNAIRE. Questions that collect a government ID are withheld from this surface and are not counted toward its completion, so the patient finishes the intake here and verifies identity in the member portal's own identity step. Clinical photo capture and the consent video are unaffected and continue to be served exactly as before.","deprecated":null,"version":null,"openapi":"/openapi/public-openapi.json get /v1/instrument/resolve","href":"/api-reference/intake/start-an-intake-session-and-get-the-first-question"}]},{"group":"Addresses","pages":[{"title":"Resolve a selected address suggestion to a full address","deprecated":null,"version":null,"openapi":"/openapi/public-openapi.json get /v1/instrument/address/retrieve","href":"/api-reference/addresses/resolve-a-selected-address-suggestion-to-a-full-address"},{"title":"Suggest addresses as your patient types","deprecated":null,"version":null,"openapi":"/openapi/public-openapi.json get /v1/instrument/address/suggest","href":"/api-reference/addresses/suggest-addresses-as-your-patient-types"}]},{"group":"Enrollment","pages":[{"title":"Read a patient's public enrollment status","deprecated":null,"version":null,"openapi":"/openapi/public-openapi.json get /v1/journeys/{journey_id}/status","href":"/api-reference/enrollment/read-a-patients-public-enrollment-status"}]},{"group":"Webhooks","pages":[{"title":"List the webhook event types you can subscribe to","deprecated":null,"version":null,"openapi":"/openapi/public-openapi.json get /v1/webhooks/event-types","href":"/api-reference/webhooks/list-the-webhook-event-types-you-can-subscribe-to"},{"title":"List your webhook registrations","deprecated":null,"version":null,"openapi":"/openapi/public-openapi.json get /v1/webhooks/registrations","href":"/api-reference/webhooks/list-your-webhook-registrations"},{"title":"Register a webhook endpoint (signing secret shown once)","deprecated":null,"version":null,"openapi":"/openapi/public-openapi.json post /v1/webhooks/registrations","href":"/api-reference/webhooks/register-a-webhook-endpoint-signing-secret-shown-once"},{"title":"Read one of your webhook registrations","deprecated":null,"version":null,"openapi":"/openapi/public-openapi.json get /v1/webhooks/registrations/{registration_id}","href":"/api-reference/webhooks/read-one-of-your-webhook-registrations"},{"title":"Delete a webhook registration","deprecated":null,"version":null,"openapi":"/openapi/public-openapi.json delete /v1/webhooks/registrations/{registration_id}","href":"/api-reference/webhooks/delete-a-webhook-registration"},{"title":"Update a registration's URL, events, or enabled flag","deprecated":null,"version":null,"openapi":"/openapi/public-openapi.json patch /v1/webhooks/registrations/{registration_id}","href":"/api-reference/webhooks/update-a-registrations-url-events-or-enabled-flag"},{"title":"Send a test event to a registration","deprecated":null,"version":null,"openapi":"/openapi/public-openapi.json post /v1/webhooks/registrations/{registration_id}/test","href":"/api-reference/webhooks/send-a-test-event-to-a-registration"}]}]}]},"basePath":"","title":"Submit an answer and get the next question - Purple Label MD","buildId":"dpl_DqYu5MPb49gWBBbUGgpHQUmCHY3P","deploymentId":"dpl_DqYu5MPb49gWBBbUGgpHQUmCHY3P","dynamics":["c2aa737661","2b790eda92","b0f84f53ff","a9bb46feb3"],"chunks":["OpenApiReferenceProvider-CybtLBIt.js","utils-BMLj2fvV.js","cloneDeep-izs3Hzxb.js","_Uint8Array-BVIqJ90l.js","isObjectLike-C8vmzPEN.js","isArray-Dcu1dQ5t.js","utils-B6In562Y.js","toString-BX-iyh8G.js","isSymbol-CSH9U2Gm.js","addUniqueKeysToSchema-Dr8Mfhp9.js","snippetPresets-2rmQvMVl.js","style-to-object-BY3JEAdk.js","v4-DIgz8zy6.js","conditional-requirements-CFM0id0Q.js","ApiExamples-WMqJYdZj.js","isEqual-BfaiBbcl.js","usePlaygroundInputsStore-CJ-MlPHu.js","shallow-dY3TMRCk.js","getApiPlaygroundDisplay-v-1B2bKm.js","CodeSnippet-BDhiTB7U.js","CodeSnippets-D9hnzQcS.js","Page-C4GwDT3_.js","getPastedJson-Th2V45jI.js","icon-BQXch1W9.js","MethodPill-BCqUneP3.js","DuplicateIcon-Q_-bhurZ.js","createIcon-DUjLHRqp.js","DynamicMarkdown-B-f2cqXQ.js","SectionHeading-Da5NsV4v.js","axios-vUo_bRtp.js","Markdown-D13FWkIM.js","clsx-D3Isdib3.js","lib-DuNMoZ05.js","lib-B8HbPgcC.js","html-void-elements-mCSPHezU.js","dist-C-XZBk9h.js","katex-YMM-FMeD.js","marked.esm-CZWythHk.js","AssistantPageLink--qIqmmVG.js"]}