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

# Integration cookbook

> End-to-end patterns for wiring Rewards UI components against the Universal Checkout API.

The components are presentation-only — your backend is the only thing that talks to Rye's API. This cookbook covers the most common integration patterns.

<Note>
  All examples assume you've already installed the relevant components (see [Install](/rewards/install)) and have a Rye API key with access to [Universal Checkout](/api-v2/introduction).
</Note>

## The drawdown checkout pattern

The most common rewards-program flow: user picks a product, applies some or all of their points balance, your backend creates a checkout intent against the Rye API, and `<PaymentSheet />` walks them through confirmation.

### 1. Browse catalog → product detail page

Render `<ProductCard />` tiles in your catalog grid. When a user clicks one, route to a PDP rendered with `<ProductDetails />`. Both components are presentational — your server fetches the product from Rye (or your own backend that mirrors Rye), passes data in via props, and receives selection changes via callbacks.

### 2. Variant selection + quantity

Inside `<ProductDetails />`, the `<Variants />` and `<Quantity />` slots manage selection and quantity locally. Persist the selection in your own state — you'll need it for the checkout intent.

When a variant goes out of stock between page load and checkout, surface a `revalidationError` on `<ProductDetails />`; it renders an inline alert above the variant pickers.

### 3. Create a checkout intent

When the user clicks the `<ProductDetails.Redeem />` CTA, your server creates a checkout intent. See [the Universal Checkout intent lifecycle](/api-v2/checkout-intent-lifecycle) for the full state machine.

```ts theme={null}
import CheckoutIntents from "checkout-intents";

const client = new CheckoutIntents({ apiKey: process.env.RYE_API_KEY });

const intent = await client.checkoutIntents.create({
  // ... product, buyer, variant picks, etc.
});
```

### 4. Confirmation sheet with mixed tender

Render `<PaymentSheet />` with the intent data. Use `<PayWithPoints />` inside a `<PaymentSheet.Section />` to let the user pick how many points to apply.

The `<PayWithPoints.Summary />` slot's `orderTotal` prop pairs nicely with `<PaymentSheet.CostBreakdown />` — both show the user how the order splits between points and cash.

When the user clicks `<PaymentSheet.Confirm />`, your server calls `intent.confirm()` (or `intent.purchase()` depending on the flow) and triggers the payment method.

### 5. Post-purchase

After the order places, route to an `<OrderTracking />` page. Poll your own backend (which polls Rye) and update the `<StatusPill />` and `<Timeline />` props as the order progresses through the lifecycle.

For the stuck/investigation state, swap `<StatusCard />` for `<InvestigationCard />` and surface `<InvestigationActions />` so the user can decide how they want to proceed (wait, reattempt, refund).

## The member-benefit pattern

For partners who run a discount-pass-through program (e.g. credit-card members get 5% off without applying points), skip `<PayWithPoints />` and use `<PaymentSheet.MemberBenefit />` to surface the discount as a line item.

```tsx theme={null}
<PaymentSheet>
  <PaymentSheet.Header title="Confirm your order" subtitle="Includes your member benefit" />
  <PaymentSheet.Item item={item} />
  <PaymentSheet.Shipping buyer={buyer} />
  <PaymentSheet.MemberBenefit
    title="Member benefit applied"
    description="5% off, automatically applied at checkout."
    amount={{ currency: "USD", value: "-13.35" }}
  />
  <PaymentSheet.CostBreakdown lines={lines} total={total} />
  <PaymentSheet.Confirm onClick={onConfirm}>Confirm · {total}</PaymentSheet.Confirm>
</PaymentSheet>
```

## Address entry

For first-time buyers or address edits, `<AddressForm />` produces the canonical `Buyer` shape that the rest of the SDK consumes. Wire it to your own validation layer:

```tsx theme={null}
<AddressForm
  value={buyer}
  onChange={setBuyer}
  fieldErrors={validate(buyer)}
  onSubmit={async (next) => {
    await persistAddress(next);
    router.push("/checkout");
  }}
>
  <AddressForm.Name />
  <AddressForm.Address />
  <AddressForm.Region />
  <AddressForm.Contact />
  <AddressForm.Submit>Save address</AddressForm.Submit>
</AddressForm>
```

The `Buyer` from `AddressForm` plugs straight into `<PaymentSheet.Shipping buyer={buyer} />` and into intent creation. Same shape, no remapping.

## Reference demo

[rewards.rye.com](https://rewards.rye.com) is a full Next.js implementation of the patterns above. The [source](https://github.com/rye-com/rewards-sdk-demo) is MIT-licensed — clone it as a starting template.
