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

# Import a card

> Send a card to MoonPay from your server, then buy crypto with it.

Send a card to MoonPay from your server and get a card `id`. Then quote and buy
with it, as in [Pay with card](https://dev.moonpay.com/platform/guides/pay-with-card.md).

See the [Going Live](https://dev.moonpay.com/platform/overview/going-live.md) section for requirements you
must meet before taking this integration to production.

## Prerequisites

* Card import enabled on your MoonPay account. Contact your MoonPay account
  team to enable it.
* A PCI-compliant server to send card data from.
* A [connected customer](https://dev.moonpay.com/platform/guides/connect-a-customer.md).

## How it works

> [!NOTE]
>
> Import the card before every purchase, even when MoonPay already has it. Each
> purchase needs a fresh CVC.

### New customer

```mermaid theme={null}
sequenceDiagram
    autonumber
    actor C as Customer
    participant FE as Your frontend
    participant BE as Your server
    participant API as MoonPay API
    participant MF as MoonPay frames

    FE->>API: getConnection()
    API-->>FE: connectionRequired
    FE->>MF: Render login frame
    C->>MF: Logs in
    MF-->>FE: complete (status: active)

    C->>FE: Enters card details
    FE->>BE: accessToken
    BE->>API: POST /platform/v1/payment-methods/cards
    API-->>BE: 201 { id, ... }

    FE->>API: getQuote({ paymentMethod: { type: "card", id } })
    C->>MF: Confirms purchase
    MF-->>FE: complete({ transaction })
```

### Returning customer

```mermaid theme={null}
sequenceDiagram
    autonumber
    actor C as Customer
    participant FE as Your frontend
    participant BE as Your server
    participant API as MoonPay API
    participant MF as MoonPay frames

    FE->>API: getConnection()
    alt Login expired
        API-->>FE: connectionRequired
        FE->>MF: Render login frame
        C->>MF: Logs in
    end

    C->>FE: Re-enters the CVC
    FE->>BE: accessToken
    BE->>API: POST /platform/v1/payment-methods/cards
    API-->>BE: 200 { id, ... } (same id)

    FE->>API: getQuote({ paymentMethod: { type: "card", id } })
    C->>MF: Confirms purchase
    MF-->>FE: complete({ transaction })
```

### 1. Connect the customer

[Connect the customer](https://dev.moonpay.com/platform/guides/connect-a-customer.md). Then get their
access token with
[`client.getCredentials()`](https://dev.moonpay.com/platform/sdk-reference/web/get-credentials) and
pass it to your server.

> [!WARNING]
>
> Hold the access token in memory only. Don't log it or write it to disk.

### 2. Import the card

Call `POST /platform/v1/payment-methods/cards` from your server, with the
customer's access token as a Bearer token. The token needs the
`payment-methods.create` scope.

Send the request to MoonPay's PCI proxy, not `api.moonpay.com`. Use the host
that matches the access token:

| Mode | Host |
| - | - |
| Live | `https://secure.moonpay.com` |
| Test | `https://secure-sandbox.moonpay.com` |

We recommend sending the customer's `deviceIp` and `userAgent`. MoonPay uses
them for fraud checks.

```ts Import a card theme={null}
const res = await fetch(
  "https://secure.moonpay.com/platform/v1/payment-methods/cards",
  {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${accessToken}`,
    },
    body: JSON.stringify({
      number: card.number,
      expirationMonth: "03",
      expirationYear: "2028",
      cvc: card.cvc,
      billingAddress: {
        street: "123 Main St",
        town: "New York",
        postCode: "10001",
        state: "NY",
        country: "USA",
      },
      deviceIp: "203.0.113.7",
      userAgent: customerUserAgent,
    }),
  },
);

const { data } = await res.json();
```

```json Response (201) theme={null}
{
  "data": {
    "id": "b1c2d3e4-5678-90ab-cdef-1234567890ab",
    "type": "card",
    "cardType": "credit",
    "brand": "visa",
    "last4": "4242",
    "expirationMonth": "03",
    "expirationYear": "2028",
    "availability": { "active": true }
  }
}
```

#### Request body

| Field | Required | Description |
| - | - | - |
| `number` | Yes | The card number. |
| `expirationMonth` | Yes | 2-digit month, for example `"03"`. |
| `expirationYear` | Yes | 4-digit year, for example `"2028"`. |
| `cvc` | Yes | The card security code. |
| `billingAddress.street` | Yes | Street line. |
| `billingAddress.subStreet` | No | Second street line. |
| `billingAddress.town` | Yes | Town or city. |
| `billingAddress.postCode` | Yes | Postal code. |
| `billingAddress.state` | No | State or province. Required for the United States and Canada. |
| `billingAddress.country` | Yes | ISO 3166-1 alpha-3 country code, for example `"USA"`. |
| `deviceIp` | No | The customer's device IP address, IPv4 or IPv6. Recommended. |
| `userAgent` | No | The customer's browser or app user agent, up to 1024 characters. Recommended. |

#### Responses

* **`201 Created`**: MoonPay added the card.
* **`200 OK`**: the customer already has this card. MoonPay returns the same
  `id` and stores the new CVC. Retries are safe.

While `lastMicroAuthVerification.status` is `started`, `pending` or
`expired`, the card can't be used for a purchase.

#### Errors

| Status | `code` | Meaning |
| - | - | - |
| `400` | `card_not_supported` | MoonPay doesn't accept this card. Ask the customer for a different card. |
| `400` | `invalid_request` | The request is invalid or MoonPay can't add the card. `errors` lists any invalid fields. |
| `401` | `unauthorized` | The access token is missing, invalid or expired, or a live token was sent to the test host. |
| `403` | `forbidden` | The token lacks the `payment-methods.create` scope, card import isn't enabled, or a live request didn't come through the PCI proxy. |
| `409` | `conflict` | The request conflicts with the customer's current state. |
| `422` | `unprocessable_entity` | MoonPay can't add a card for this customer, for example because card payments aren't available to them. |

### 3. Quote and buy

Get a quote with `paymentMethod: { type: "card", id }`, then run the purchase.

* [Get a quote](https://dev.moonpay.com/platform/guides/pay-with-card.md#get-a-quote)
* [Execute the transaction](https://dev.moonpay.com/platform/guides/pay-with-card.md#execute-the-transaction),
  or use the [buy button](https://dev.moonpay.com/platform/guides/pay-with-buy-button.md)
* [Handle challenges](https://dev.moonpay.com/platform/guides/handling-challenges.md)
* [Track the transaction](https://dev.moonpay.com/platform/guides/pay-with-card.md#track-the-transaction)
