> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tagada.io/llms.txt
> Use this file to discover all available pages before exploring further.

# End-to-end tutorial

> From an activated store to a first prescription and its first refill — the complete Tagada Rx flow in seven steps.

# Tutorial: your first prescription

This walkthrough covers the **complete** flow — activation is assumed done ([do that first](/developer-tools/rx/crm-activation)). We use the raw HTTP endpoints so the flow is crystal clear; the [Plugin SDK](/developer-tools/rx/plugin-sdk) and [Headless SDK](/developer-tools/rx/headless-sdk) pages show the same steps as one-liners.

**Cast of characters:**

| Actor                | Credential                                      |
| -------------------- | ----------------------------------------------- |
| Storefront (browser) | none — public endpoints + `checkoutToken` proof |
| Your backend / CRM   | Tagada API key                                  |
| Patient (portal)     | email OTP → CMS session token                   |

***

<Steps>
  <Step title="1 — Check if the product is an Rx product">
    At product-page load, ask whether the clinical flow is needed:

    ```bash theme={null}
    curl "https://api.tagada.io/api/public/v1/rx/required-for-product?productId=product_xxx"
    ```

    ```json theme={null}
    {
      "required": true,
      "clinicalNetworkId": "clinnet_xxx",
      "externalOfferingId": "3f6a…",
      "requiresLabs": false,
      "requiresIdVerification": true,
      "isDeaControlled": false
    }
    ```

    If `required` is `false`, sell it like any normal product and skip the rest of this page.
  </Step>

  <Step title="2 — Marketing quiz, then check out">
    Run a **marketing** quiz before payment (vertical, goals, preferences). No medical questions, no PHI.

    Then run a standard Tagada checkout with **`mode: 'auth'`** (card hold, not a capture). When the hold succeeds you have **`orderId`** and **`checkoutToken`**.

    <Warning>
      Make the copy explicit: *a card hold is not medical approval*. A licensed clinician still reviews the case. Approve captures the hold; decline voids it. Nothing is refunded because nothing was captured.
    </Warning>
  </Step>

  <Step title="3 — Medical intake on the thank-you page, then submit the case">
    **After** the hold, fetch the network-authored questionnaire and collect the intake on `/thank-you`. Then submit. The `(orderId, checkoutToken)` pair proves ownership — no API key in the browser. Keep `patient` / `intakeAnswers` in memory only until `submitCase` succeeds.

    ```bash theme={null}
    curl -X POST "https://api.tagada.io/api/public/v1/rx/cases/submit" \
      -H "Content-Type: application/json" \
      -d '{
        "orderId": "order_xxx",
        "checkoutToken": "chkt_…",
        "productId": "product_xxx",
        "patient": {
          "firstName": "Jane", "lastName": "Doe",
          "email": "jane@example.com",
          "dateOfBirth": "1990-04-12",
          "sexAtBirth": "female",
          "address": {
            "line1": "1 Main St", "city": "Austin",
            "state": "TX", "zip": "78701", "country": "US"
          }
        },
        "intakeAnswers": [
          { "questionId": "allergies", "value": "none" },
          { "questionId": "goals", "value": "lose_weight,improve_sleep" }
        ]
      }'
    ```

    ```json theme={null}
    {
      "rxCaseId": "rxcase_xxx",
      "externalCaseId": "837858f1-…",
      "status": "submitted",
      "accrualAmountMinor": 2500,
      "accrualCurrency": "USD"
    }
    ```

    <Note>
      **Intake answer values** must be `string`, `number`, or `boolean`. For multi-select questions, join the selections into one comma-separated string (`"lose_weight,improve_sleep"`) — arrays are joined automatically but the canonical wire format is the flat string.
    </Note>
  </Step>

  <Step title="4 — Show live status on the thank-you page">
    Poll the public lookup with the same ownership proof:

    ```bash theme={null}
    curl -X POST "https://api.tagada.io/api/public/v1/rx/cases/lookup" \
      -H "Content-Type: application/json" \
      -d '{ "orderId": "order_xxx", "checkoutToken": "chkt_…" }'
    ```

    ```json theme={null}
    { "cases": [ { "id": "rxcase_xxx", "status": "in_review", … } ] }
    ```

    Render it as: *"A licensed clinician is reviewing your information."* → *"Approved — your treatment ships soon."*
  </Step>

  <Step title="5 — Let the webhooks do their thing">
    From here, everything is event-driven. The clinical network calls Tagada's webhook receiver and the case advances on its own:

    * `case.in_review` → clinician picked it up
    * `case.approved` → prescription issued
    * `shipment.shipped` → tracking attached, **next rebill scheduled at ship day + 30**
    * `shipment.delivered` → done for this cycle

    Watch it live in **CRM → your store → Tagada Rx → Cases**, or via the merchant API:

    ```ts theme={null}
    const { case: c, events } = await tagada.rx.cases.retrieve('rxcase_xxx');
    // events = full append-only timeline
    ```
  </Step>

  <Step title="6 — The patient uses the portal">
    Point patients to your storefront's portal page (the Oakwell template ships one at `/portal`). They log in with an **email OTP**, see their treatments and timelines, **message the care team**, and upload a **photo ID** when the offering requires identity verification. Details: [Patient portal](/developer-tools/rx/patient-portal).

    When a clinician replies, Tagada emails the patient a content-free notification ("You have a new message") linking back to the portal.
  </Step>

  <Step title="7 — Refills happen by themselves">
    On every shipment, Tagada schedules the next charge for **the ship day + cycle** (default 30 days). An hourly scan rebills due cases that are still `shipped`/`delivered`. You do nothing; declined or cancelled cases never rebill.
  </Step>
</Steps>

***

## What can go wrong (and what to do)

| Situation                 | What happens                                      | Your move                                |
| ------------------------- | ------------------------------------------------- | ---------------------------------------- |
| Clinician declines        | `case.declined` event; affiliate accrual reversed | Refund the order, email the patient      |
| Network is down at submit | `rx.submitCase` fails (PHI is never queued)       | Show a retry UI; the order stays paid    |
| Patient never uploads ID  | Case stalls in review                             | Portal nags; you can nudge via messaging |
| Duplicate webhook         | Dropped by idempotency                            | Nothing                                  |

***

## Next

<CardGroup cols={3}>
  <Card title="Plugin SDK" icon="puzzle-piece" href="/developer-tools/rx/plugin-sdk">
    The same flow inside a Tagada-hosted storefront.
  </Card>

  <Card title="Headless SDK" icon="plug" href="/developer-tools/rx/headless-sdk">
    The same flow from your own site.
  </Card>

  <Card title="Node SDK" icon="server" href="/developer-tools/rx/node-sdk">
    Server-side ops: activation, cases, refills.
  </Card>
</CardGroup>
