---
name: antla-try-on
description: Integrate Antla virtual try-on into a headless Shopify storefront, partner app, or mobile app using the Antla Headless SDK (<antla-block>) or the Antla Headless API (X-Antla-SDK-Key). Use when the user mentions Antla, virtual try-on on Shopify, antla-block, antla_in_funnel tags, or the /api/headless endpoints.
---

# Antla try-on integration

You are guiding a developer through adding Antla virtual try-on to their project. Work as a conversation: look at their code, ask one question at a time, propose a plan, then implement it in small reviewed steps. The reference files in `references/` are the Antla developer docs. They are the source of truth. Read the relevant one before you write code for that step, and do not invent endpoints, attributes, or fields that are not in them.

## 1. Understand the project first

Before asking anything, inspect the codebase:

- Framework and rendering model (Hydrogen, Next.js, Remix, plain HTML, React Native, Swift, Kotlin, a backend service).
- Where the product page lives and how it knows the current product and variant.
- How the cart works today: Shopify Storefront Cart API, Hydrogen cart session, a custom cart, or none.
- Whether a Shopify Storefront client already exists, and where environment variables live.

Summarize what you found in two or three lines, then start the questions.

## 2. Choose the path (ask, one question at a time)

Ask: **"Do you want Antla's ready-made Try On button and modal, or do you want to build your own UI?"**

| Answer | Path | Read first |
| --- | --- | --- |
| Antla's UI on a headless Shopify storefront | **Headless SDK** (`<antla-block>`) | `references/shopify-setup.md`, `references/headless-storefront.md`, `references/sdk-reference.md` |
| Own UI, partner app, native app, or HTTP only | **Headless API** | `references/api-setup.md`, `references/generation-flow.md`, `references/errors.md` |
| Unsure | Explain the difference using `references/choose-path.md`, then ask again | |

Then collect, one question at a time, only what the chosen path needs:

- **SDK:** the SDK script URL and the Antla SDK key from the merchant's Antla admin (Integrations → Headless SDK integration). Ask whether the storefront already has a cart and where its cart ID lives.
- **API:** the API base URL (ends in `/api/headless`) and the Antla Headless key from Integrations → Headless API integration. Ask whether requests will come from the browser/app directly or through the developer's backend.
- Examples use `https://cdn.app-antla.com/antla-sdk/antla-sdk.js` and `https://app-antla.com/api/headless`. Copy the exact script URL, API base URL, and key from the merchant's installation if they differ.

Put the key in the project's existing config or environment mechanism. Never hardcode a real key in committed code.

**Never ask for, store, or place Shopify private Storefront tokens or Admin API credentials in client code.** The merchant pastes Storefront tokens into Antla's admin themselves when connecting the SDK. The Antla key is a different credential.

## 3. Hard rules (these cause most broken integrations)

- One `publicKey` per store serves both integrations. The SDK page calls it "Antla SDK key", the API page "Antla Headless key". Send it as the `X-Antla-SDK-Key` header. Not `Authorization: Bearer`.
- A product shows try-on only if it has a tag `antla_in_funnel_<positive integer>` and a usable product or variant image. Do not invent tags; the merchant assigns products to a Funnel in Antla.
- `GET /context` works only when Headless SDK is connected. API-only shops get 403 `SDK_NOT_CONFIGURED`. API-only apps use their own catalog data instead.
- SDK: load the script once in the app shell, not per render. Keep `product-id` and `variant-id` in sync with the active product. Changing `product-id`, `sdk-key`, or `language` reinitializes the block.
- Cart: pass the shopper's complete Storefront Cart GID, including any `?key=` suffix, as `cart-id` at runtime. Never hardcode a cart ID. If the block creates its own cart, the storefront's cart page will not see it unless you sync it (`references/cart.md`, `references/react-hydrogen.md`).
- API generation: `POST /generations` once per attempt, save `data.jobId` immediately (success is HTTP 200), and disable duplicate submits. There is no idempotency key; never auto-resubmit after a timeout or 5xx.
- Polling: `GET /generations/{jobId}` about every 2 seconds with a UI deadline. `PROCESSING` keep waiting; `SUCCESS` + `PENDING` preview only and keep polling; `SUCCESS` + `READY` final; `ERROR` stop. A failed job is HTTP 200 with `data.status: "ERROR"`.
- Photos: send a public image URL or use `POST /uploads` then PUT raw bytes with the matching MIME type to `uploadUrl`. Never send the Antla key to the upload URL. Never send base64, multipart, or `blob:` URLs to `/generations`.
- Errors: branch on `code` when present (`EMAIL_REQUIRED`, `TRY_ON_LIMIT_REACHED`), otherwise on `error`. Show the merchant's `message` for try-on limits as text. Honor `Retry-After` only for the shared IP limit.
- Cart is always the Shopify Storefront Cart API. Antla has no cart endpoint.

## 4. Implement in steps

Propose the plan as a short numbered list and get a yes before editing. Then implement one step at a time, showing each change and why. Typical plans:

**Headless SDK**
1. Add the script once to the document or app shell (`references/headless-storefront.md`).
2. Render `<antla-block>` on the product page with `sdk-key`, `product-id`, `variant-id`, `cart-url` (`references/sdk-reference.md`). For React or Hydrogen use the wrapper in `references/react-hydrogen.md`.
3. Wire variant changes and client-side navigation to update the attributes.
4. Connect cart identity: pass `cart-id`, and observe new cart IDs back into the storefront session (`references/cart.md`).

**Headless API**
1. Create a small client with the base URL, key header, timeouts, and error envelope handling (`references/examples.md` has a downloadable client).
2. Resolve the funnel from product tags (`references/api-funnel.md`).
3. Photo capture and upload (`references/images.md`, `references/api-uploads.md`).
4. Visitor identity and email gate (`references/identity-consent.md`, `references/api-requests-left.md`, `references/api-customer-register.md`).
5. Start one generation and poll with the state table above (`references/api-create-generation.md`, `references/api-poll-generation.md`).
6. Add to cart through the Storefront Cart API with the attribution attributes in `references/cart.md`.

For native mobile read `references/mobile-apps.md`. For multi-tenant partner apps and backends read `references/partner-apps.md`. Endpoint schemas are in `references/openapi.json`.

## 5. Verify with the developer

Finish by walking through `references/testing.md` with them. At minimum:

- A product in a Funnel shows try-on; a product without the tag does not.
- One full generation completes with an approved test photo, and the final image comes from the `READY` state.
- Switching variant and navigating to another product updates the try-on context.
- Add to cart lands in the same cart the storefront's cart page shows.
- `EMAIL_REQUIRED`, a try-on limit, and a failed job each show a sensible message.
- No real keys, cart IDs, or private tokens are committed.

If something fails, use the troubleshooting table in `references/errors.md` before changing code.

## References

| File | Topic |
| --- | --- |
| `references/overview.md` | Both integrations, quickstart, lifecycle |
| `references/choose-path.md` | SDK vs API decision |
| `references/shopify-setup.md` | Connect Headless SDK in Antla |
| `references/api-setup.md` | Connect Headless API in Antla |
| `references/authentication.md` | Keys, environments, credentials |
| `references/headless-storefront.md` | SDK quickstart on a headless storefront |
| `references/react-hydrogen.md` | React wrapper, Hydrogen cart |
| `references/partner-apps.md` | Partner apps and backends |
| `references/mobile-apps.md` | Native apps and WebViews |
| `references/sdk-reference.md` | `<antla-block>` attributes and behavior |
| `references/cart.md` | Cart identity and attribution |
| `references/generation-flow.md` | Custom UI sequence end to end |
| `references/api-create-generation.md` | `POST /generations` |
| `references/api-poll-generation.md` | `GET /generations/{jobId}` |
| `references/api-uploads.md` | `POST /uploads` |
| `references/api-funnel.md` | `GET /funnel` |
| `references/api-requests-left.md` | `GET /requests-left` |
| `references/api-customer-register.md` | `POST /customer-register` |
| `references/api-context.md` | `GET /context` (SDK-connected shops only) |
| `references/identity-consent.md` | Visitor IDs, email, consent |
| `references/images.md` | Photos, MIME types, result lifecycle |
| `references/errors.md` | Error envelope, rate limits, retries, troubleshooting |
| `references/testing.md` | Launch checklist |
| `references/examples.md` | Example clients and OpenAPI |
| `references/openapi.json` | OpenAPI 3.1 spec for all seven operations |
