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

# Accept stablecoin payments with automatic fiat conversion

> Accept USDC from Privy wallets and automatically convert payments to USD with Bridge and Stripe Financial Accounts

Accept stablecoin payments without holding or manually converting crypto. This recipe uses Privy wallets to send USDC to a Bridge liquidation address. Bridge automatically converts the payment to USD and deposits it into a Stripe Financial Account through ACH.

This flow works well for:

* **Loyalty and rewards programs** that let users spend tokenized balances at checkout. The user pays in tokens, while the business receives USD.
* **Fintech and neobank apps adding a spending layer** that hold user balances in stablecoins for yield, foreign exchange flexibility, or by design. Users can pay with their balance at checkout, while the merchant receives fiat transparently.

## How it works

```text theme={"system"}
User's Privy wallet
  → Privy Transfer API
    → Bridge liquidation address
      → automatic conversion to USD
        → Stripe Financial Account
```

1. Create a Bridge USD external account for the Stripe Financial Account, then create a liquidation address that uses it. This is a one-time setup.
2. When a user pays, call Privy's Transfer API with the liquidation address as the destination.
3. Bridge detects the incoming USDC, converts it to USD, and sends the USD to the Stripe Financial Account through ACH.

## Prerequisites

* A [Privy app](https://dashboard.privy.io) with server-side API credentials and an embedded wallet that can authorize server-initiated transfers
* A [Bridge account](https://apidocs.bridge.xyz/get-started/introduction/quick-start/get-set-up-with-bridge) with a verified customer ID
* A [Stripe account with Treasury enabled](https://docs.stripe.com/treasury)
* The routing number and account number for the Stripe Financial Account that receives payments

## Set up the payment destination

### Create a Stripe Financial Account

Create a Stripe Financial Account if the business does not already have one. Enable ACH inbound transfers, then save the routing and account numbers from its financial address.

```bash theme={"system"}
curl https://api.stripe.com/v1/treasury/financial_accounts \
  -u "{{STRIPE_SECRET_KEY}}:" \
  -d "supported_currencies[]=usd"
```

The Financial Account's financial address includes the ACH details needed by Bridge:

```json theme={"system"}
{
  "routing_number": "110000000",
  "account_number": "000123456789"
}
```

### Create a Bridge USD external account

Create a USD [Bridge external account](https://apidocs.bridge.xyz/api-reference/external-accounts/create-a-new-external-account) for the Stripe Financial Account. Use the business's legal name and address as the account-owner details, and use the Financial Account's routing and account numbers.

```bash theme={"system"}
curl -X POST https://api.bridge.xyz/v0/customers/<bridge-customer-id>/external_accounts \
  -H "Api-Key: <bridge-api-key>" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: <unique-external-account-idempotency-key>" \
  -d '{
    "currency": "usd",
    "bank_name": "<stripe-financial-account-bank-name>",
    "account_owner_name": "<business-legal-name>",
    "account_type": "us",
    "account": {
      "routing_number": "110000000",
      "account_number": "000123456789",
      "checking_or_savings": "checking"
    },
    "address": {
      "street_line_1": "<business-street-address>",
      "city": "<business-city>",
      "state": "<business-state>",
      "postal_code": "<business-postal-code>",
      "country": "USA"
    }
  }'
```

Bridge returns an external account ID. Store it with the business's payment configuration:

```json theme={"system"}
{
  "id": "<bridge-external-account-id>",
  "customer_id": "<bridge-customer-id>",
  "account_owner_name": "<business-legal-name>",
  "currency": "usd",
  "account_type": "us",
  "active": true
}
```

### Create a Bridge liquidation address

Create a [Bridge liquidation address](https://apidocs.bridge.xyz/api-reference/liquidation-addresses/create-a-liquidation-address) for the business. Pass the external account ID at the top level so Bridge can send converted USD to the Stripe Financial Account through ACH.

```bash theme={"system"}
curl -X POST https://api.bridge.xyz/v0/customers/<bridge-customer-id>/liquidation_addresses \
  -H "Api-Key: <bridge-api-key>" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: <unique-liquidation-address-idempotency-key>" \
  -d '{
    "chain": "tempo",
    "currency": "usdc",
    "external_account_id": "<bridge-external-account-id>",
    "destination_payment_rail": "ach",
    "destination_currency": "usd",
    "return_instructions": {
      "address": "0x<tempo-address-controlled-by-business>"
    }
  }'
```

`return_instructions.address` is the Tempo address that receives the crypto if Bridge returns or fails the drain. The business must control this address, and it must be valid for the source chain.

Bridge returns a liquidation address that automatically liquidates received USDC and routes USD to the configured external account:

```json theme={"system"}
{
  "id": "liq_addr_...",
  "customer_id": "<bridge-customer-id>",
  "external_account_id": "<bridge-external-account-id>",
  "address": "0xAbCdEf1234567890...",
  "chain": "tempo",
  "currency": "usdc",
  "destination_payment_rail": "ach",
  "destination_currency": "usd",
  "state": "active"
}
```

<Tip>
  Store the liquidation address with the business's payment configuration. A single address can
  accept payments from multiple users, so your app does not need to create an address for each
  transaction.
</Tip>

## Send a payment from a Privy wallet

When a user confirms a payment, call the Transfer API with the Bridge liquidation address as the destination.

```bash theme={"system"}
curl -X POST https://api.privy.io/v1/wallets/<wallet-id>/transfer \
  -u "<privy-app-id>:<privy-app-secret>" \
  -H "privy-app-id: <privy-app-id>" \
  -H "Content-Type: application/json" \
  -d '{
    "source": {
      "asset": "usdc",
      "amount": "12.50",
      "chain": "tempo"
    },
    "destination": {
      "address": "0xAbCdEf1234567890..."
    }
  }'
```

The Transfer API creates an asynchronous wallet action. Store its `id` to track the payment:

```json theme={"system"}
{
  "id": "action-id",
  "status": "pending",
  "wallet_id": "wallet-id",
  "created_at": "2026-07-22T20:09:11.929Z",
  "type": "transfer",
  "source_asset": "usdc",
  "source_amount": "12.50",
  "source_chain": "tempo",
  "destination_address": "0xAbCdEf1234567890..."
}
```

Poll the wallet action until its status is `succeeded`, or use your existing wallet-action monitoring flow:

```bash theme={"system"}
curl https://api.privy.io/v1/wallets/<wallet-id>/actions/<action-id>?include=steps \
  -u "<privy-app-id>:<privy-app-secret>" \
  -H "privy-app-id: <privy-app-id>"
```

## Reconcile fiat settlement

A `succeeded` Privy wallet action confirms the onchain USDC transfer. It does not confirm that the USD ACH payment has settled in the Stripe Financial Account.

Bridge processes ACH payouts in daily batches, not in real time. Reconcile each drain through [Bridge drain history](https://apidocs.bridge.xyz/api-reference/liquidation-addresses/get-drain-history-of-a-liquidation-address) and treat `payment_processed` as the successful settlement state. Handle every non-success state before marking the payment as settled.

Subscribe to Bridge's real-time [`liquidation_address.drain` webhooks](https://apidocs.bridge.xyz/platform/additional-information/webhooks/structure) to update the payment status as the drain progresses. The [drain lifecycle](https://apidocs.bridge.xyz/platform/orchestration/liquidation_address/drains) documents the available states.

## Next steps

<CardGroup cols={2}>
  <Card title="Transfer API" icon="arrow-right-arrow-left" href="/wallets/actions/transfer/usage" arrow>
    Review transfer parameters, supported assets, and error handling.
  </Card>

  <Card title="Wallet action status" icon="clock" href="/wallets/actions/status" arrow>
    Track a transfer from pending to a terminal state.
  </Card>
</CardGroup>
