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

# client.setupBuyButton()

> Render the MoonPay-hosted buy button and run the buy pipeline on tap.

Render the [Buy button frame](/platform/frames/buy-button) into your UI. The frame renders a payment button — card, Apple Pay, or Google Pay, depending on what's available — and runs the buy pipeline on tap. Use it when you want a single payment button instead of orchestrating individual payment-method frames yourself.

<Callout icon="circle-info" iconType="regular">
  Like the headless [Buy frame](/platform/sdk-reference/web/setup-buy), the buy
  button can emit a `challenge` event mid-pipeline. Render a separate challenge
  frame using
  [`client.setupChallenge()`](/platform/sdk-reference/web/setup-challenge) at
  the URL from the event payload.
</Callout>

```ts Setup buy button focus={5-30} theme={null}
import { createClient, type BuyButtonEvent } from "@moonpay/platform-sdk-web";

const client = createClient({ sessionToken: "c3N0XzAwMQ==" });

const buyButtonResult = await client.setupBuyButton({
  quote: quoteResult.value.data.signature,
  container: document.querySelector("#buyButtonContainer"),
  onEvent: (event: BuyButtonEvent) => {
    switch (event.kind) {
      case "ready":
        // Button is rendered — hide any loading placeholder.
        break;
      case "complete":
        // Inspect FrameTransaction before polling.
        if (event.payload.transaction.status !== "failed") {
          pollTransaction(event.payload.transaction.id);
        }
        break;
      case "challenge":
        // Hand off to the challenge frame at the provided URL.
        handleChallenge(event.payload.url);
        break;
      case "error":
        console.error(event.payload.code, event.payload.message);
        break;
    }
  },
});

if (!buyButtonResult.ok) {
  // Handle error
  console.error(buyButtonResult.error.kind, buyButtonResult.error.message);
  return;
}

const buyButton = buyButtonResult.value;
```

***

## Parameters

| Property    | Type                              | Required | Description                                                                              |
| ----------- | --------------------------------- | -------- | ---------------------------------------------------------------------------------------- |
| `quote`     | `string`                          | ✅        | The quote `signature` returned from [`getQuote`](/platform/sdk-reference/web/get-quote). |
| `container` | `HTMLElement`                     | ✅        | A DOM element to render the buy button into.                                             |
| `onEvent`   | `(event: BuyButtonEvent) => void` |          | Callback invoked for buy-button events. See [`BuyButtonEvent`](#buybuttonevent).         |

This method does not require a separate auth token. The client uses stored credentials from an active connection.

### `BuyButtonEvent`

`onEvent` receives events as the buy pipeline progresses.

| kind          | Payload                                                      | When you receive it                                                                                                                                                                            |
| ------------- | ------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `"ready"`     | —                                                            | The button is rendered and ready for the customer to tap. For Apple Pay and Google Pay, this fires once the device is confirmed to support the wallet. Use it to hide any loading placeholder. |
| `"complete"`  | `{ transaction:` [`FrameTransaction`](#frametransaction) `}` | The pipeline finished. Inspect the `FrameTransaction` to detect the failure variant.                                                                                                           |
| `"challenge"` | `{ kind: string; url: string }`                              | Verification is required before the transaction can proceed. Render the [challenge frame](/platform/sdk-reference/web/setup-challenge) at the provided `url`.                                  |
| `"error"`     | [`BuyButtonEventError`](#buybuttoneventerror)                | The flow encountered an error. Surface to logs and tear down the frame.                                                                                                                        |

#### `FrameTransaction`

`FrameTransaction` is a discriminated union — the failure variant carries `failureReason`, the non-failure variant always carries `id`. Pass `id` to [`client.getTransaction()`](/platform/sdk-reference/web/get-transaction) to poll for the final status.

| Field           | Type     | Required | Description                                                                |
| --------------- | -------- | -------- | -------------------------------------------------------------------------- |
| `status`        | `string` | ✅        | The transaction status. On the failure variant, `"failed"`.                |
| `id`            | `string` |          | Required on the non-failure variant; optional when `status` is `"failed"`. |
| `failureReason` | `string` |          | Present only on the failure variant (`status === "failed"`).               |

#### `BuyButtonEventError`

| Field     | Type     | Required | Description                                                                                          |
| --------- | -------- | -------- | ---------------------------------------------------------------------------------------------------- |
| `code`    | `string` | ✅        | The error category. Includes `configurationError`, `invalidQuote`, and backend-specific error codes. |
| `message` | `string` | ✅        | Developer-friendly details. Not intended to be rendered in UI.                                       |

## Result

`client.setupBuyButton()` returns a `Result<BuyButtonFrame, SetupBuyButtonError>`.

### Result envelope

`Result<BuyButtonFrame, SetupBuyButtonError>`

| Field   | Type                                          | Required | Description                      |
| ------- | --------------------------------------------- | -------- | -------------------------------- |
| `ok`    | `boolean`                                     | ✅        | Whether the operation succeeded. |
| `value` | [`BuyButtonFrame`](#buybuttonframe)           |          | Present when `ok` is `true`.     |
| `error` | [`SetupBuyButtonError`](#setupbuybuttonerror) |          | Present when `ok` is `false`.    |

### `BuyButtonFrame`

| Field      | Type                          | Required | Description                                                                                                                                                              |
| ---------- | ----------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `setQuote` | `(signature: string) => void` | ✅        | Updates the quote signature used by the frame. Use this when the current quote expires before the customer taps the button — fetch a new quote and pass its `signature`. |
| `dispose`  | `() => void`                  | ✅        | Unmounts the frame. After you call this, no further events are dispatched to your `onEvent` callback.                                                                    |

### `SetupBuyButtonError`

| Field     | Type                                       | Required | Description                 |
| --------- | ------------------------------------------ | -------- | --------------------------- |
| `kind`    | `"configurationError"` \| `"genericError"` | ✅        | The error category.         |
| `message` | `string`                                   | ✅        | Developer-friendly details. |

<Accordion title="TS Definitions">
  ```ts types.ts theme={null}
  type BuyButtonFrame = {
    setQuote: (signature: string) => void;
    dispose: () => void;
  };

  type FrameTransaction =
    | { id: string; status: string }
    | { id?: string; status: "failed"; failureReason: string };

  type BuyButtonEvent =
    | { kind: "ready" }
    | {
        kind: "complete";
        payload: { transaction: FrameTransaction };
      }
    | {
        kind: "challenge";
        payload: { kind: string; url: string };
      }
    | { kind: "error"; payload: BuyButtonEventError };

  type BuyButtonEventError = {
    code: string;
    message: string;
  };

  type SetupBuyButtonError = {
    kind: "configurationError" | "genericError";
    message: string;
  };
  ```
</Accordion>
