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

# Migrate from V1

> Guide for migrating from the Sync API to the Universal Checkout API.

Migration is organized into three phases — do them in order, but each phase can be deployed independently:

1. **Product catalog** — how you discover and keep product data fresh
2. **Ordering** — how you place a purchase
3. **Post-purchase** — tracking, webhooks, returns

Migrating can be done in under a week of concerted effort, thanks to the simpler API surface of the Universal Checkout API.

## At-a-glance

|                     | V1 — Sync API                                                 | V2 — Universal Checkout                                               |
| ------------------- | ------------------------------------------------------------- | --------------------------------------------------------------------- |
| Protocol            | GraphQL, single endpoint                                      | REST, resource-per-URL                                                |
| Base URL            | `https://graphql.api.rye.com` / `staging.graphql.api.rye.com` | `https://api.rye.com/api/v1/` / `https://staging.api.rye.com/api/v1/` |
| Supported merchants | Amazon + Shopify                                              | Any merchant                                                          |
| Primary resource    | `Cart` → `Store[]` → `Order[]`                                | `CheckoutIntent` (state machine)                                      |
| Status model        | Fat webhooks + polling                                        | Thin webhooks + polling                                               |

### Use the SDK (applies to all phases)

We **strongly recommend adopting the official SDK** (TypeScript, Python, or Java) rather than hand-rolling HTTP requests. The SDK handles auth, pagination, retry, and schema typing so you stay insulated from future protocol-level changes.

Your existing API key is unchanged; simply hand it to the SDK client:

```ts theme={null}
import { CheckoutIntents } from "checkout-intents";
const rye = new CheckoutIntents({
  // RYE/production-xyz...
  apiKey: process.env.RYE_API_KEY,
});
```

```python theme={null}
from checkout_intents import CheckoutIntents
rye = CheckoutIntents(api_key=os.environ["RYE_API_KEY"])
```

***

## Phase 1 — Product catalog

**V1 model:** required explicit opt-in to track individual products via `requestAmazonProductByURL` / `requestShopifyProductByURL`, then product data could be queried via GraphQL.

**V2 model:** on-demand lookup + push-based updates for Shopify.

### How to get product data

* Use the [lookup product endpoint](/api-v2/api-reference/products/lookup-product) on whatever cadence makes sense for your use case (e.g. on-demand at render time, nightly refresh of a curated catalog, etc.). There is no pre-sync step; you can immediately look up product data for anything you have a URL for.
* For Shopify merchants onboarded via your [Shopify app installation link](https://docs-v1.rye.com/sync-api/shopify-merchant-onboarding/shopify-generate-installation-link), you continue to receive real-time catalog updates via webhooks, in the form of `product.updated` events.

### Product webhooks

* Product webhooks in V2 are snapshots, similar to webhooks in the GraphQL API: the payload contains the current product state. You do **not** need to call the API back to fetch updated data.
* To start receiving V2 product webhooks, **re-save your webhook URL in the developer console**. The same URL can be re-submitted — the re-save is what migrates the subscription onto V2 delivery.
* The V2 signature header is `x-rye-signature` (HMAC-SHA256). Also consume `x-rye-event-id` (for idempotency) and `x-rye-timestamp` (for replay windows).

### What to do

* Update your code to use the new Universal Checkout API `Product` type.
* Look up product data with the [lookup product endpoint](/api-v2/api-reference/products/lookup-product), instead of `productByID` or `productsByDomainV2` queries.
* Delete `requestAmazonProductByURL` / `requestShopifyProductByURL` pre-sync calls.
* Sub out any `PRODUCT_UPDATED` webhook handlers for `product.updated` handlers.

***

## Phase 2 — Ordering

The V1 `Cart` model collapses into V2's `CheckoutIntent`. One intent maps to one product URL and one buyer.

Most GraphQL integrations only ordered one product per cart, but if you require multi-item or multi-merchant checkout you can do this by creating multiple checkout intents and aggregating the results in your code.

### Flow mapping

| V1 GraphQL op                       | V2 REST call                                                            | Notes                                                                                   |
| ----------------------------------- | ----------------------------------------------------------------------- | --------------------------------------------------------------------------------------- |
| `createCart`                        | `POST /api/v1/checkout-intents`                                         |                                                                                         |
| *(wait for offer)*                  | `GET /api/v1/checkout-intents/{id}` until `state=awaiting_confirmation` | Poll or use the `checkout_intent.offer_retrieved` webhook.                              |
| `updateCartBuyerIdentity`           | `POST /api/v1/checkout-intents`                                         | Checkout intents are immutable; create a new one if you need to change shipping address |
| `updateCartSelectedShippingOptions` | *(gone)*                                                                | Rye selects shipping during offer retrieval.                                            |
| `submitCart`                        | `POST /api/v1/checkout-intents/{id}/confirm`                            | Submit checkout intent for purchase.                                                    |
| `orderByID` / `checkoutByCartID`    | `GET /api/v1/checkout-intents/{id}`                                     | When intent reaches `completed` state, it carries merchant order IDs.                   |

State machine: `retrieving_offer → awaiting_confirmation → placing_order → completed | failed`.

### Payment providers

The Universal Checkout API supports [many different payment providers](/api-v2/payment-providers), but our general recommendations are:

* **B2C apps → `basis_theory_token`.** Cards are tokenized via Basis Theory and forwarded to the merchant vault where possible. Either Rye or the merchant is MoR.
* **B2B apps → `drawdown`.** Pre-fund a Rye balance and draw down per purchase. No per-transaction tokenization. You are MoR.

### Gotchas

* **Rate limits are split across multiple buckets.** See the [Rate Limits](/api-v2/rate-limits) guide for the full breakdown — request an increase before cutover if you move more volume than the defaults.
* **Error shape changed.** V1 returns `errors` inside the GraphQL payload; V2 returns HTTP status codes + a REST error body. Your retry/backoff code will need to be updated if you don't use an official SDK.
* **Variants:** V2 accepts either a variant-deep-link URL or `variantSelections`.

***

## Phase 3 — Post-purchase

### Shipments & tracking

V1 exposed shipments via `Order.shipments`. V2 has first-class endpoints:

* `GET /api/v1/shipments` — cursor-paginated (`after`, `before`, `ids`), filterable.
* `GET /api/v1/shipments/{id}`
* `GET /api/v1/checkout-intents/{id}/shipments`

Replace nested-object reads with REST paginated fetches.

### Order-state webhooks

V1 published rich event-specific payloads (`ORDER_PLACED`, `PAYMENT_SUCCEEDED/FAILED/REFUNDED`, `REFUND_CREATED`, …). V2 ships four thin events carrying only `{id, type, source:{type, id}}` — you re-fetch the intent on receipt.

| V2 event                          | Roughly replaces                                 |
| --------------------------------- | ------------------------------------------------ |
| `checkout_intent.offer_retrieved` | signal to move from `retrieving_offer` → confirm |
| `checkout_intent.offer_failed`    | cart-level errors surfaced at create time        |
| `checkout_intent.completed`       | `ORDER_PLACED` + `PAYMENT_SUCCEEDED`             |
| `checkout_intent.order_failed`    | `PAYMENT_FAILED` / order failure paths           |

We have a guide for setting up webhooks [here](/api-v2/webhooks).

### Returns

* V1 had return queries; V2 does not expose a returns API.
* **Initiate returns by emailing `orders@rye.com`** with the order/intent ID and return reason.
* Plan for out-of-band handling in your support tooling.

***

## Suggested cutover sequence

1. Install the V2 SDK (TypeScript / Python / Java) and wire it up with your existing API key. No key rotation needed.
2. **Phase 1:** re-save webhook URL in the console; migrate product-data reads to the lookup endpoint; drop pre-sync calls.
3. **Phase 2:** port one low-volume merchant flow to `POST /checkout-intents` + polling. Pick Basis Theory (B2C) or Drawdown (B2B) for payments.
4. **Phase 3:** swap `Order.shipments` reads for `/shipments` endpoints; update the webhook handler to re-fetch intents; route return requests to `orders@rye.com`.
5. Drain in-flight V1 carts at cutover — don't dual-write.
6. `requestAmazon/ShopifyProductByURL` and `updateCartSelectedShippingOptions` callsites.
