Skip to main content
You build the storefront your patients see; the platform runs the questionnaire, the sign-in, and the enrollment behind it. Your integration touches the platform through three sockets — send a patient in, sign the patient in, and observe progress. Everything clinical stays on our side of the API, so your surface stays small on purpose.

1. Send a patient in

There are two ways to start a patient, and they meet at the same place.
  • An entry link is a URL contract. You direct a patient to a link that carries an offering reference and, optionally, a return URL, a pass-through promo token, a contact prefill, and a test-mode flag. The link is a contract over those parameters — it makes no assumption about a hosted page on our side; your storefront owns the presentation.
  • Headless is the same start, driven by your code. Call GET /v1/instrument/resolve to begin an intake session and receive the first question, then POST /v1/instrument/next to submit an answer and receive the next one. POST /v1/instrument/abandon records a drop-off when a patient leaves early, and GET /v1/instrument/address/suggest powers an as-you-type address picker.
A question can capture a file — a photo or a short video — as part of the flow. The bytes upload directly to storage through a short-lived upload URL, and the answer carries only an opaque upload reference, never the file itself.

The platform owns the sequence

The order of questions, the branching, and when the questionnaire is finished are computed per patient and owned by the server. Your storefront presents each question; it never decides what comes next. A patient cannot skip a required question, reorder the flow, or declare themselves finished — POST /v1/instrument/next advances exactly one step, re-validates every answer on the server, and returns status: complete only once every required answer is in. Decisions pin a versioned copy of the questionnaire, so a patient always finishes the same questionnaire they started.

Two kinds of question, one hard line

  • Marketing and qualification screens are yours to shape — the copy, the theme, and the order of your own pre-questionnaire steps. This is the flexible surface.
  • The medical questionnaire is governed by the physician side. Its questions, their sequence, and their branching are never editable from your storefront, and a brand theme can restyle a question but can never alter it.
The platform holds these two apart when it compiles the questionnaire, so the flexible part and the governed part can never be mixed. That separation is the product: you get to brand and arrange the front of the funnel while the clinical intake stays correct by construction.

2. Sign the patient in

Authentication is passwordless by default. Send the patient to GET /v1/auth/login, scoped to your brand — the patient signs in with an emailed code, Google, or Apple, never a password. GET /v1/auth/callback completes the sign-in and starts an encrypted, HttpOnly session cookie for the patient’s browser. GET /v1/auth/logout ends the session. Return URLs are honored only when they are on your brand’s allowlist.

3. Observe progress

You watch enrollment through webhooks plus two read endpoints.
  • Register an endpoint with POST /v1/webhooks/registrations. The response returns an HMAC signing secret one time only — store it right then, because it is held on our side and never returned again. GET /v1/webhooks/event-types lists the event types you can subscribe to; GET /v1/webhooks/registrations lists what you have registered.
  • Test before you go live with POST /v1/webhooks/registrations/{registration_id}/test, which sends one clearly-marked test event through the real delivery and signing path.
  • Deliveries are reference-only. Each delivery carries identifiers and the event type; you fetch the full detail through the authorized read for that resource. Failed deliveries are retried automatically; once retries are exhausted, the platform’s operators handle the dead-lettered delivery — it is not a self-serve read on your side.
  • Read status directly with GET /v1/journeys/{journey_id}/status for a patient’s public enrollment status and GET /v1/onboardings/{onboarding_id}/progress for your own onboarding progress. Both are read-only and carry identifiers and status values only — never patient data. The enrollment read does not always have a status to give you: it may return no status yet — a documented outcome to handle alongside the usual authentication and not-found refusals, not a failure.
An enrollment status like IN_REVIEW or ACTION_NEEDED reflects where the patient actually is. Your storefront surfaces the platform’s decision after it is made — it never tells a patient the outcome before the review returns it.

Where payment fits

A patient’s enrollment includes a payment step, and it runs in test mode until you go live. By default it sits between finishing the questionnaire and the clinical review; programs can instead be configured pay-first, collecting payment before the questionnaire begins — the ordering is a per-program setting, fixed for each enrollment at its start, and the clinical safeguards are identical either way (see the ordering note). The payment endpoints are published: see Identifiers and error types for the checkout and payment-status calls and their responses, and The checkout door for how a patient reaches the hosted payment page. Ready to make the calls? Continue to the Walkthrough.