# Issue stablecoin-backed cards with Bridge

Onboard customers with Bridge and issue Stripe cards funded by Bridge, Privy, or other non-custodial wallets.

Build a stablecoin-backed card program with Stripe Issuing and [Bridge](https://apidocs.bridge.xyz/). Verify customers with the Bridge API, then use the Stripe API to create cards funded by a Bridge wallet, a [Privy](https://docs.privy.io/) wallet, or another non-custodial wallet. Bridge pulls funds from the linked wallet at authorization.

To learn which company handles each part of the program, see [how Stripe, Bridge, and Privy work together](https://docs.stripe.com/issuing/stablecoin-cards/how-it-works.md). If you use Privy for non-custodial wallets, you can also integrate client-side with Privy’s [prebuilt components for cards](https://docs.privy.io/financial-flows/cards/pre-built-components/overview).

## Before you begin

Before you start your integration, make sure you have the following:

- A signed program addendum. Learn more about [onboarding](https://docs.stripe.com/issuing/stablecoin-cards/onboarding.md).
- A Bridge developer account and API key. If you don’t already use Bridge, Stripe sets up your Bridge developer account during onboarding.
- A Stripe account. For commercial programs, [set up the account as a Connect platform](https://dashboard.stripe.com/connect).
- A [funding strategy](https://docs.stripe.com/issuing/stablecoin-cards/funding-strategies.md): Bridge wallets, non-custodial wallets, or both.

Build and test your integration in a [Stripe sandbox](https://docs.stripe.com/sandboxes.md) connected to a Bridge sandbox before you go live. See [test stablecoin-backed cards](https://docs.stripe.com/issuing/stablecoin-cards/testing.md).

## Connect Bridge to your Stripe account

Stripe sends you a Stripe App install link during onboarding. Open the link and install the app on your Stripe account. This connects your Bridge developer account to your Stripe account and activates Stripe Issuing for stablecoin-backed cards.

To connect a sandbox follow the steps to [connect your Stripe and Bridge sandboxes](https://docs.stripe.com/issuing/stablecoin-cards/testing.md#connect-sandboxes).

## Create and verify a customer

Each cardholder or business starts as a customer in Bridge. Create the customer with the [Bridge Customers API](https://apidocs.bridge.xyz/platform/customers/overview), then request the `cards` endorsement. Bridge verifies the customer and creates the matching Stripe object after approving the endorsement.

You can collect verification details in two ways:

- **Bridge-hosted KYC**: [Request a KYC link](https://apidocs.bridge.xyz/platform/cards/overview/kyc#request-a-kyc-link-for-a-cards-endorsement) for the `cards` endorsement and send your customer to it.
- **API**: Submit the customer’s information yourself with the [Bridge Customers API](https://apidocs.bridge.xyz/platform/customers/customers/api), then request the `cards` endorsement.

This example requests a KYC link:

```shell
curl "https://api.bridge.xyz/v0/customers/{{BRIDGE_CUSTOMER_ID}}/kyc_link?endorsement=cards" \
  -H "Api-Key: {{BRIDGE_API_KEY}}"
```

Bridge reports the endorsement status in the customer’s `endorsements` array and `customer` webhook events. If the endorsement is incomplete, check its `issues` array for details. Learn how to [resolve common eligibility issues](https://apidocs.bridge.xyz/platform/cards/overview/kyc).

#### Consumer

For consumer programs, create an [individual customer](https://apidocs.bridge.xyz/api-reference/customers/create-a-customer#individual-customer). After Bridge approves the `cards` endorsement, it creates a Stripe [Cardholder](https://docs.stripe.com/api/issuing/cardholders/object.md) and returns its ID as `stripe_cardholder_id`. Stripe also sends an `issuing_cardholder.created` event.

```json
{
  "id": "1e210e5b-700e-41e6-a62a-0eb0b6ac1967",
  "type": "individual",
  "status": "active",
  "first_name": "Jenny",
  "last_name": "Rosen",
  "email": "jenny.rosen@example.com",
  "stripe_cardholder_id": "ich_1SVf3CG6FooBAru7mB2MSrDY",
  "endorsements": [
    {
      "name": "cards",
      "status": "approved",
      "requirements": {
        "complete": ["terms_of_service_v1", "first_name", "last_name", "..."],
        "pending": [],
        "missing": null,
        "issues": []
      }
    }
  ]
}
```

Bridge manages the cardholder for you. The cardholder is read-only in the Stripe API, but you use its ID to create cards.

Create the customer’s first card within 24 hours after Bridge approves the `cards` endorsement. Otherwise, Bridge revokes the endorsement and changes the cardholder’s status to `inactive`. To reactivate the cardholder, request the endorsement again so the customer can confirm their information.

#### Commercial

For commercial programs, create a [business customer](https://apidocs.bridge.xyz/api-reference/customers/create-a-customer#business-customer). After Bridge approves the `cards` endorsement, it creates a [connected account](https://docs.stripe.com/api/accounts/object.md) on your Connect platform and returns its ID as `stripe_account_id`.

```json
{
  "id": "fc7c8079-1c66-4b42-b470-fb49ee502f19",
  "type": "business",
  "status": "active",
  "email": "business@example.com",
  "stripe_account_id": "acct_1THowoRnOOaEdKcg",
  "endorsements": [
    {
      "name": "cards",
      "status": "approved",
      "requirements": {
        "complete": ["terms_of_service_v1", "business_name", "business_type", "..."],
        "pending": [],
        "missing": null,
        "issues": []
      }
    }
  ]
}
```

Use the connected account ID to create cardholders and cards for the business. The connected account has Issuing capabilities but not payments capabilities, so the Dashboard might show its status as restricted.

## Create a card

Create a card with the [Cards API](https://docs.stripe.com/api/issuing/cards/create.md). Select your program type to see the steps. Set `currency` to `usd`, and use the `crypto_wallet` parameter to link the wallet that the card draws funds from.

#### Consumer

Bridge creates the cardholder for consumer programs, so you can create the card directly. This example creates a virtual card that draws OUSD from a non-custodial wallet on Tempo:

```curl
curl https://api.stripe.com/v1/issuing/cards \
  -u "<<YOUR_SECRET_KEY>>:" \
  -d "cardholder={{ISSUINGCARDHOLDER_ID}}" \
  -d currency=usd \
  -d type=virtual \
  -d status=active \
  -d "crypto_wallet[chain]=tempo" \
  -d "crypto_wallet[currency]=ousd" \
  -d "crypto_wallet[type]=standard" \
  -d "crypto_wallet[address]=0x1234567890abcdef1234567890abcdef12345678"
```

To spend from a Bridge wallet instead, set `crypto_wallet[type]` to `bridge_wallet` and `crypto_wallet[address]` to the address of the customer’s Bridge wallet.

#### Commercial

For commercial programs, Bridge doesn’t create cardholders. Create a cardholder for each authorized user of the business, then create their card. Make both requests with the `Stripe-Account` header set to the business’s connected account ID.

### Create a cardholder

You must present the sponsor bank’s authorized user terms to each cardholder and record the date and IP address of their acceptance. Bridge doesn’t create cardholders for the associated persons on a business customer, so create a cardholder for each person who needs a card.

```curl
curl https://api.stripe.com/v1/issuing/cardholders \
  -u "<<YOUR_SECRET_KEY>>:" \
  -H "Stripe-Account: {{CONNECTEDACCOUNT_ID}}" \
  -d "name=Jenny Rosen" \
  --data-urlencode "email=jenny.rosen@example.com" \
  --data-urlencode "phone_number=+18008675309" \
  -d status=active \
  -d type=individual \
  -d "individual[first_name]=Jenny" \
  -d "individual[last_name]=Rosen" \
  -d "individual[dob][day]=1" \
  -d "individual[dob][month]=11" \
  -d "individual[dob][year]=1981" \
  -d "individual[user_terms_acceptance][lead][date]=1470266163" \
  -d "individual[user_terms_acceptance][lead][ip]=91.121.146.224" \
  -d "billing[address][line1]=510 Townsend Street" \
  -d "billing[address][city]=San Francisco" \
  -d "billing[address][state]=CA" \
  -d "billing[address][postal_code]=94111" \
  -d "billing[address][country]=US"
```

### Create a card

This example creates a virtual card that draws OUSD from a non-custodial wallet on Tempo:

```curl
curl https://api.stripe.com/v1/issuing/cards \
  -u "<<YOUR_SECRET_KEY>>:" \
  -H "Stripe-Account: {{CONNECTEDACCOUNT_ID}}" \
  -d "cardholder={{ISSUINGCARDHOLDER_ID}}" \
  -d currency=usd \
  -d type=virtual \
  -d status=active \
  -d "crypto_wallet[chain]=tempo" \
  -d "crypto_wallet[currency]=ousd" \
  -d "crypto_wallet[type]=standard" \
  -d "crypto_wallet[address]=0x1234567890abcdef1234567890abcdef12345678"
```

Commercial cards can also draw funds from Bridge wallets. Set `crypto_wallet[type]` to `bridge_wallet` and `crypto_wallet[address]` to the address of the business’s Bridge wallet.

The `crypto_wallet` parameter has the following child parameters:

| Parameter | Description |
| --- | --- |
| `chain` | The chain that the wallet is on, such as `tempo`, `base`, or `solana`. See [supported stablecoins and chains](https://docs.stripe.com/stablecoins/availability.md#issuing). |
| `currency` | The stablecoin used to fund card payments, such as `ousd` or `usdc`. This is separate from the card’s `currency`, which is always `usd`. Contact your Stripe account manager to confirm support for your stablecoin. |
| `type` | The funding strategy:
- `bridge_wallet`: A Bridge wallet that Bridge holds in custody.
- `standard`: A non-custodial wallet with an onchain approval for the Stripe card contract. |
| `address` | The wallet address. For Bridge wallets, use the `address` of the Bridge wallet. For Solana non-custodial wallets, use the wallet’s owner address instead of the associated token account address. Bridge derives the token account from the address and currency. |

To issue a physical card, set [type](https://docs.stripe.com/api/issuing/cards/create.md#create_issuing_card-type) to `physical` and provide a shipping address with the [shipping](https://docs.stripe.com/api/issuing/cards/create.md#create_issuing_card-shipping) parameter. Learn more about [physical cards](https://docs.stripe.com/issuing/cards/physical.md).

## Fund the card

How you fund the card depends on its wallet type:

- **Bridge wallet**: Add funds to the wallet using the [Bridge wallets API](https://apidocs.bridge.xyz/platform/wallets/overview). The card can draw funds from the wallet’s balance as soon as it’s active.
- **Non-custodial wallet**: [Set up an onchain approval](https://docs.stripe.com/issuing/bridge-stablecoin-cards/noncustodial-wallets.md) that allows the Stripe card contract to pull funds from the wallet. Stripe declines authorizations if the approval isn’t active, if the approved amount is lower than the purchase amount, or if the wallet doesn’t have enough funds.

## Test your integration

Test card purchases in a Stripe sandbox connected to a Bridge sandbox. Bridge submits real onchain transactions on test networks, so you can reconcile authorizations against onchain data. See [test stablecoin-backed cards](https://docs.stripe.com/issuing/stablecoin-cards/testing.md).

To view a card’s details, use the [Stripe Dashboard](https://dashboard.stripe.com/issuing/cards) or embed [Issuing Elements](https://docs.stripe.com/issuing/elements.md) in your application.

## See also

- [Authorizations and webhooks for stablecoin-backed cards](https://docs.stripe.com/issuing/stablecoin-cards/authorizations.md)
- [Manage your stablecoin-backed card program](https://docs.stripe.com/issuing/stablecoin-cards/manage.md)
