> ## 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.

# With the Headless SDK

> Add the Rx clinical flow to any external site — React, Vue, plain HTML, or AI-generated — with tagada.rx.

# Tagada Rx with the Headless SDK

Running your storefront on your own hosting (Vercel, Netlify, Shopify headless, an AI-generated site)? The [Headless SDK](/developer-tools/headless-sdk/introduction) ships a first-class **`tagada.rx`** module that mirrors the public storefront endpoints — no API key in the browser, ever.

```bash theme={null}
npm install @tagadapay/headless-sdk
```

```ts theme={null}
import { createHeadlessClient } from '@tagadapay/headless-sdk';

const tagada = createHeadlessClient({ storeId: 'store_xxx' });
// tagada.rx is ready — no extra config
```

<Info>
  **Auth model:** there is no key. `isRequiredForProduct` is public; the case routes prove ownership with the `(orderId, checkoutToken)` pair your checkout flow already holds. PHI transits to the clinical network and is never persisted by Tagada.
</Info>

<Warning>
  **Hosting rule in affiliate (MoR) mode:** you build headless on your own
  stack, but the resulting storefront must be **deployed on your Tagada
  subdomain** (`your-brand.tgdcare.com`) — LegitScript certification is tied
  to Tagada-hosted domains. Reserve the subdomain in the CRM storefront
  wizard, then work with your account manager to wire the deploy of your
  build onto it. Serving the storefront from your own root domain is a
  direct-mode capability — **coming soon**.
</Warning>

***

## The three calls

### 1. Is this an Rx product?

```ts theme={null}
const check = await tagada.rx.isRequiredForProduct(productId);

if (check.required) {
  // gate the purchase behind your intake quiz
  // check.requiresIdVerification → plan for photo-ID upload post-purchase
  // check.requiresLabs           → surface lab expectations in the copy
}
```

### 2. Submit the case after payment

Run your normal headless checkout (`tagada.checkout` + `tagada.payment`). Once the order is paid:

```ts theme={null}
const result = await tagada.rx.submitCase({
  orderId,                 // from the paid order
  checkoutToken,           // from your checkout session
  productId,
  patient: {
    firstName: 'Jane',
    lastName: 'Doe',
    email: 'jane@example.com',
    dateOfBirth: '1990-04-12',      // YYYY-MM-DD
    sexAtBirth: 'female',
    address: {
      line1: '1 Main St',
      city: 'Austin',
      state: 'TX',
      zip: '78701',
      country: 'US',                 // ISO 3166-1 alpha-2
    },
  },
  intakeAnswers: [
    { questionId: 'allergies', value: 'none' },
    { questionId: 'goals', value: 'lose_weight,improve_sleep' }, // multiselect → comma-joined
  ],
});

// result.rxCaseId    → 'rxcase_xxx'
// result.status      → 'submitted'
// result.accrualAmountMinor → your commission (affiliate mode; 0 in direct mode)
```

<Warning>
  Submit **synchronously after payment, from the browser**. Do not stash `patient` / `intakeAnswers` in your own database or queue "for later" — that would make *you* a PHI processor. If the call fails, keep the data in memory and offer a retry button.
</Warning>

### 3. Poll status on the thank-you page

```ts theme={null}
const { cases } = await tagada.rx.getCasesForOrder({ orderId, checkoutToken });

const status = cases[0]?.status;
// 'submitted' → "Sent to a licensed clinician"
// 'in_review' → "A clinician is reviewing your information"
// 'approved'  → "Approved — preparing your shipment"
// 'shipped'   → "On its way" (lastShipmentShippedAt is set)
```

Poll every \~10 seconds while the tab is open; the statuses come from the processed clinical webhooks, so they're authoritative.

***

## Full example: React thank-you page

```tsx theme={null}
function RxStatus({ orderId, checkoutToken }: Props) {
  const [status, setStatus] = useState<string | null>(null);

  useEffect(() => {
    const tick = async () => {
      const { cases } = await tagada.rx.getCasesForOrder({ orderId, checkoutToken });
      if (cases[0]) setStatus(cases[0].status);
    };
    tick();
    const id = setInterval(tick, 10_000);
    return () => clearInterval(id);
  }, [orderId, checkoutToken]);

  const copy: Record<string, string> = {
    submitted: 'Your information was sent to a licensed clinician.',
    in_review: 'A clinician is reviewing your information.',
    approved: 'Approved! Your treatment is being prepared.',
    shipped: 'Your treatment is on its way.',
    declined: 'A clinician determined this treatment isn’t right for you — the hold on your card has been released.',
  };

  return <p>{status ? copy[status] ?? status : 'Submitting…'}</p>;
}
```

***

## Install the same Funnel v2 (CRM canvas)

A headless build still needs the six-step Funnel v2 so operators see landing,
quiz, checkout, offer, thank-you, and portal in the CRM. Create it with the
[Node SDK](/developer-tools/rx/node-sdk) (API key, server-side) — the
browser SDK only runs the bricks.

Working example: [`rx-storefront/`](https://github.com/TagadaPay/examples/tree/main/rx-storefront)
in [tagada-examples](https://github.com/TagadaPay/examples). `pnpm seed`
calls `tagada.funnels.create` with this graph; you can also import
[`funnel.bundle.json`](https://github.com/TagadaPay/examples/blob/main/rx-storefront/funnel.bundle.json)
from **Funnels → Import bundle**.

```ts theme={null}
import { Tagada } from '@tagadapay/node-sdk';

const tagada = new Tagada(process.env.TAGADA_API_KEY!);

await tagada.funnels.create({
  storeId: 'store_xxx',
  isDefault: true,
  config: {
    id: 'rx-storefront',
    name: 'Harbor Clinic storefront',
    version: '1.0.0',
    metadata: { rxStorefront: true },
    nodes: [
      { id: 'rx_landing', name: 'Landing', kind: 'step', type: 'landing', isEntry: true, isDefault: true, position: { x: 0, y: 0 }, config: { path: '/' } },
      { id: 'rx_quiz', name: 'Marketing quiz', kind: 'step', type: 'custom', position: { x: 280, y: 0 }, config: { path: '/quiz', matchSubPaths: true } },
      { id: 'rx_checkout', name: 'Checkout', kind: 'step', type: 'checkout', position: { x: 560, y: 0 }, config: { path: '/checkout' } },
      { id: 'rx_offer', name: 'Offer', kind: 'step', type: 'offer', position: { x: 840, y: 0 }, config: { path: '/offer' } },
      { id: 'rx_thankyou', name: 'Thank you', kind: 'step', type: 'thankyou', isConversion: true, position: { x: 1120, y: 0 }, config: { path: '/thank-you' } },
      { id: 'rx_portal', name: 'Patient portal', kind: 'step', type: 'custom', position: { x: 1400, y: 0 }, config: { path: '/portal', matchSubPaths: true } },
    ],
    edges: [
      { id: 'edge_rx_landing_quiz', source: 'rx_landing', target: 'rx_quiz' },
      { id: 'edge_rx_quiz_checkout', source: 'rx_quiz', target: 'rx_checkout' },
      { id: 'edge_rx_checkout_offer', source: 'rx_checkout', target: 'rx_offer', conditions: { when: 'payment.success' } },
      { id: 'edge_rx_offer_thankyou', source: 'rx_offer', target: 'rx_thankyou' },
      { id: 'edge_rx_thankyou_portal', source: 'rx_thankyou', target: 'rx_portal' },
    ],
  },
});
```

Your router must serve those exact paths. Medical intake stays on
`/thank-you` **after** payment (`getQuestionsForProduct` → `submitCase` →
poll). The marketing quiz on `/quiz` has no medical questions.

<Warning>
  Reserve `your-brand.tgdcare.com` in the CRM, then deploy this build onto
  that subdomain (LegitScript). Own root domain is coming soon (direct mode).
</Warning>

## What the headless module does *not* cover

| Need                                  | Where it lives                                                                                                                              |
| ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| Creating the Funnel v2 graph          | Node SDK `tagada.funnels.create` — see above, or the [rx-storefront example](https://github.com/TagadaPay/examples/tree/main/rx-storefront) |
| Patient portal (messaging, ID upload) | Portal endpoints with a customer CMS session — see [Patient portal](/developer-tools/rx/patient-portal)                                     |
| Activation, product mapping, ops      | Server-side — [Node SDK](/developer-tools/rx/node-sdk)                                                                                      |
| A hosted storefront on Tagada infra   | [Plugin SDK](/developer-tools/rx/plugin-sdk)                                                                                                |
