> ## 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.setupAddCard()

> Render the Add Card frame to capture a new card from the customer.

Render the Add Card frame so the customer can save a new credit or debit card.
The provider presents the frame in a full-screen native modal. Card data is
captured inside a PCI-compliant MoonPay-hosted UI and never touches your app
code.

```tsx Setup Add Card focus={5-22} theme={null}
import {
  useMoonPay,
  type AddCardEvent,
} from "@moonpay/platform-sdk-react-native";

export function AddCardScreen() {
  const { client } = useMoonPay();

  const start = async () => {
    const addCardResult = await client.setupAddCard({
      onEvent: (event: AddCardEvent) => {
        switch (event.kind) {
          case "complete":
            // Card added. Use event.payload.card.id to get a quote.
            console.log(event.payload.card);
            break;
          case "error":
            console.error(event.payload.code, event.payload.message);
            break;
        }
      },
    });

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

    const addCard = addCardResult.value;
  };

  // ...
}
```

***

## Parameters

| Property  | Type                            | Required | Description                                                                     |
| --------- | ------------------------------- | -------- | ------------------------------------------------------------------------------- |
| `onEvent` | `(event: AddCardEvent) => void` |          | Callback invoked for Add Card flow events. See [`AddCardEvent`](#addcardevent). |

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

### `AddCardEvent`

`onEvent` receives events as the Add Card flow progresses. Use `event.kind` to
decide how to handle each event.

| kind         | Payload                                       | When you receive it                                      |
| ------------ | --------------------------------------------- | -------------------------------------------------------- |
| `"ready"`    | —                                             | The frame finished loading and the card form is visible. |
| `"complete"` | `{ card: `[`CardResponse`](#cardresponse)` }` | The card was saved successfully.                         |
| `"error"`    | [`AddCardEventError`](#addcardeventerror)     | The flow encountered an error.                           |

#### `CardResponse`

The card object returned when the customer finishes adding a card. Use `id`
directly in [`getQuote`](/platform/sdk-reference/react-native/get-quote) — there
is no need to re-fetch payment methods.

| Field             | Type               | Required | Description                                                               |
| ----------------- | ------------------ | -------- | ------------------------------------------------------------------------- |
| `id`              | `string`           | ✅        | The stored card identifier.                                               |
| `type`            | `string`           | ✅        | The payment method type, typically `"card"`.                              |
| `cardType`        | `string`           | ✅        | The card sub-type (for example, `"credit"` or `"debit"`).                 |
| `brand`           | `string`           | ✅        | The card network brand (for example, `"visa"`, `"mastercard"`).           |
| `last4`           | `string`           | ✅        | The last four digits of the card number.                                  |
| `expirationMonth` | `string`           | ✅        | The card expiration month, as a two-digit string (for example, `"04"`).   |
| `expirationYear`  | `string`           | ✅        | The card expiration year, as a four-digit string (for example, `"2030"`). |
| `availability`    | `{ active: true }` | ✅        | The card is available for new transactions when the frame returns it.     |

#### `AddCardEventError`

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

## Result

`client.setupAddCard()` returns a `Result<AddCardFrame, SetupAddCardError>`.

### Result envelope

`Result<AddCardFrame, SetupAddCardError>`

| Field   | Type                                      | Required | Description                      |
| ------- | ----------------------------------------- | -------- | -------------------------------- |
| `ok`    | `boolean`                                 | ✅        | Whether the operation succeeded. |
| `value` | [`AddCardFrame`](#addcardframe)           |          | Present when `ok` is `true`.     |
| `error` | [`SetupAddCardError`](#setupaddcarderror) |          | Present when `ok` is `false`.    |

### `AddCardFrame`

| Field     | Type         | Required | Description                                                                                           |
| --------- | ------------ | -------- | ----------------------------------------------------------------------------------------------------- |
| `dispose` | `() => void` | ✅        | Unmounts the frame. After you call this, no further events are dispatched to your `onEvent` callback. |

The Add Card frame does not expose a `setQuote` method — quotes are issued
after the card is saved.

### `SetupAddCardError`

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

## Example: Add a card, then buy

After the `complete` event fires, pass `card.id` to
[`getQuote`](/platform/sdk-reference/react-native/get-quote) and use the returned
signature with [`setupBuy`](/platform/sdk-reference/react-native/setup-buy) to
execute the transaction. For the full end-to-end walkthrough, see the [Pay with
card](/platform/guides/pay-with-card) guide.

```tsx Add card, then buy theme={null}
import {
  useMoonPay,
  type AddCardEvent,
  type BuyEvent,
} from "@moonpay/platform-sdk-react-native";

export function AddCardThenBuy() {
  const { client } = useMoonPay();

  const start = async () => {
    const addCardResult = await client.setupAddCard({
      onEvent: async (event: AddCardEvent) => {
        if (event.kind !== "complete") return;

        const cardId = event.payload.card.id;

        // Tear down the Add Card frame — we have the card we need.
        addCardResult.value.dispose();

        // Request a quote for the new card.
        const quoteResult = await client.getQuote({
          source: { asset: { code: "USD" }, amount: "100.00" },
          destination: { asset: { code: "ETH" } },
          wallet: { address: "0x1234567890abcdef1234567890abcdef12345678" },
          paymentMethod: { type: "card", id: cardId },
        });

        if (!quoteResult.ok) {
          // Handle error
          return;
        }

        // Execute the transaction with the headless buy frame.
        const buyResult = await client.setupBuy({
          quote: quoteResult.value.data.signature,
          onEvent: (event: BuyEvent) => {
            // Handle buy events (see the Pay with card guide).
          },
        });

        if (!buyResult.ok) {
          // Handle error
          return;
        }
      },
    });

    if (!addCardResult.ok) {
      // Handle error
      return;
    }
  };

  // ...
}
```

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

  type CardResponse = {
    id: string;
    /** Payment method type, typically "card". */
    type: string;
    /** Card sub-type, for example "credit" or "debit". */
    cardType: string;
    /** Card network brand, for example "visa" or "mastercard". */
    brand: string;
    last4: string;
    /** Two-digit month string, for example "04". */
    expirationMonth: string;
    /** Four-digit year string, for example "2030". */
    expirationYear: string;
    availability: { active: true };
  };

  type AddCardEvent =
    | {
        kind: "ready";
      }
    | {
        kind: "complete";
        payload: {
          card: CardResponse;
        };
      }
    | {
        kind: "error";
        payload: AddCardEventError;
      };

  type AddCardEventError = {
    code: "configurationError" | "generic";
    /** A developer-facing error message. Not intended to be rendered in UI. */
    message: string;
  };

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