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

# Offramp: stablecoin to fiat

> Your customer sends USDC and receives fiat in their bank or mobile money wallet.

In an offramp, your customer sends stablecoins and receives fiat in a bank account or mobile money wallet.

```mermaid theme={null}
sequenceDiagram
  participant You as Your app
  participant BC as Bridge
  participant C as Your customer
  You->>BC: Get a quote
  BC-->>You: Quote (qte_...)
  You->>BC: Create offramp (quote + payout account + sending wallet)
  BC-->>You: Payment (pay_...) + deposit address
  You->>C: Show the address to send to
  C->>BC: Sends stablecoin
  BC-->>You: Webhooks at each step
  BC->>C: Pays fiat to bank or wallet
  BC-->>You: payment.offramp.completed
```

## Before you start

You need a [customer](https://docs.bridge.linkio.world/flows/onboard-customer.md) and an offramp [quote](https://docs.bridge.linkio.world/flows/quotes.md) that hasn't expired. Get the bank or network code from [List banks](https://docs.bridge.linkio.world/api-reference/lookups/banks.md) or [List mobile money networks](https://docs.bridge.linkio.world/api-reference/lookups/momo-networks.md).

## Step 1: Create the offramp

Send the quote, the account that should receive the fiat, and the wallet the stablecoin will come from.

> [tab] To a bank account (NGN)
>
> ```bash theme={null}
> curl -X POST https://sandbox.core.linkio.world/api/payments/offramp \
>   -H "X-BRIDGE-API-Key: $BRIDGE_API_KEY" \
>   -H "API-Version: 2026-10-29-atlas" \
>   -H "Content-Type: application/json" \
>   -H "Idempotency-Key: withdrawal-2001" \
>   -d '{
>     "customer_id": "cus_4hT9pL2mQx8VnR3tY7wZ1cB5dE",
>     "quote_id": "qte_1wZ4cB6dE8fK2mQ9xLp3VnR7tY",
>     "payment_details": {
>       "type": "bank_transfer",
>       "currency": "NGN",
>       "details": {
>         "bank_code": "058",
>         "account_number": "0123456789",
>         "account_name": "Ada Obi"
>       }
>     },
>     "source_wallet": {
>       "currency": "USDC",
>       "address": "6KhMtrKUhYGqVVgV6fcr1Vr1XnQtZCrDwpXTNZHPiReR",
>       "network": "solana"
>     }
>   }'
> ```

> [tab] To mobile money (GHS)
>
> ```bash theme={null}
> curl -X POST https://sandbox.core.linkio.world/api/payments/offramp \
>   -H "X-BRIDGE-API-Key: $BRIDGE_API_KEY" \
>   -H "API-Version: 2026-10-29-atlas" \
>   -H "Content-Type: application/json" \
>   -H "Idempotency-Key: withdrawal-2002" \
>   -d '{
>     "customer_id": "cus_4hT9pL2mQx8VnR3tY7wZ1cB5dE",
>     "quote_id": "qte_6dE8fK2mQ9xLp3VnR7tY1wZ4cB",
>     "payment_details": {
>       "type": "momo",
>       "currency": "GHS",
>       "details": {
>         "bank_code": "0004",
>         "account_number": "0241234567",
>         "account_name": "Kwame Mensah"
>       }
>     },
>     "source_wallet": {
>       "currency": "USDC",
>       "address": "0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed",
>       "network": "base"
>     }
>   }'
> ```

| Field | What it means |
| - | - |
| `customer_id` | Must be the same customer as on the quote. |
| `quote_id` | The offramp quote to use. Each quote can only be used once. |
| `party` | Optional. `1st` (default) if the money goes to the customer, `3rd` if it goes to someone else. |
| `payment_details.type` | Must match the quote's `payout_method`: `bank_transfer` or `momo`. |
| `payment_details.currency` | Must match the quote's `target_currency`. |
| `payment_details.details` | The payout account. See [Payout account details](https://docs.bridge.linkio.world/before-you-build/currencies.md#payout-account-details). |
| `source_wallet` | The wallet your customer sends the stablecoin from. Its `currency` must match the quote's `source_currency`. |

> [!NOTE]
>
> We check the payout account before creating the payment: the bank code must exist, the account number must have the right number of digits, and the name must be filled in. For NGN, the account is also verified with the bank.

## Step 2: Show the deposit address

You get back `202 Accepted`, with where your customer must send the stablecoin:

```json theme={null}
{
  "status": "success",
  "message": "Offramp payment initiated",
  "payment": {
    "id": "pay_3VnR7tY1wZ4cB6dE8fK2mQ9xLp",
    "status": "pending",
    "state": "initiated",
    "event_id": "evt_7tY1wZ4cB6dE8fK2mQ9xLp3VnR",
    "deposit": {
      "type": "stablecoin",
      "currency": "USDC",
      "details": {
        "address": "7thMtrKUhYGqVVgV6fcr1Vr1XnQtZCrDwpXTNZHPiRe5",
        "network": "solana",
        "tag": null
      }
    }
  }
}
```

| Field | What it means |
| - | - |
| `deposit.details.address` | The address your customer sends the stablecoin to. |
| `deposit.details.network` | The network to send on. **It must match.** |
| `deposit.details.tag` | A memo or tag. If it isn't `null`, your customer must include it. |

> [!WARNING]
>
> Your customer must send the exact `source_amount` from the quote, on the network shown, within 30 minutes. If nothing arrives in that time, the payment fails. Sending a different amount puts the payment on hold for a review (`flagged`). Sending on another network can lose the funds.

## Step 3: Wait for webhooks

As the payment moves, we send you [webhooks](https://docs.bridge.linkio.world/webhooks/offramp-events.md). You can also check at any time with [Get a payment](https://docs.bridge.linkio.world/api-reference/payments/details.md).

## Every state

| State | Status | What it means | What to do |
| - | - | - | - |
| `initiated` | `pending` | We've created the payment. | Show the deposit address. |
| `quote_locked` | `pending` | The price is held for this payment. | Nothing. |
| `stable_pending` | `pending` | We're waiting for your customer's stablecoin. They have 30 minutes. | Remind your customer to send it. |
| `stable_received` | `pending` | The stablecoin has arrived. | Tell your customer it's on its way. |
| `processing` | `pending` | We're paying the fiat to the account. | Nothing. |
| `completed` | `success` | The fiat has been paid. | Show success. |
| `failed` | `failed` | The payment couldn't be finished, for example no stablecoin arrived within 30 minutes. | Tell your customer. Contact support if stablecoin was received. |
| `canceled` | `failed` | The payment was canceled. | Tell your customer. |
| `reversed` | `failed` | The payout was returned, for example the bank rejected it. | Contact support. |
| `flagged` | `pending` | On hold for a review, for example the amount sent didn't match. | Wait. After the review, the payment moves to `completed` or `failed`. |
| `paused` | `pending` | On hold. | Wait for `resumed`. |

> [!NOTE]
>
> The state is `stable_pending` / `stable_received`, but the webhook event names are `payment.offramp.stables_pending` / `payment.offramp.stables_received` (with an extra `s`).

```mermaid theme={null}
flowchart LR
  initiated --> quote_locked --> stable_pending --> stable_received --> processing --> completed
  stable_pending --> failed
  stable_pending --> canceled
  stable_pending --> flagged
  processing --> flagged
  flagged --> completed
  flagged --> failed
  processing --> failed
  completed --> reversed
```

## What can go wrong when you create it

The same errors as an [onramp](https://docs.bridge.linkio.world/flows/onramp.md#what-can-go-wrong-when-you-create-it) can happen, plus these `validation_failed` messages:

| Field | Message |
| - | - |
| `source_wallet` | `source_wallet is required` |
| `source_wallet.currency` | `source_wallet currency must be a stablecoin` |
| `payment_details.currency` | `Payout currency must match the quote target_currency` |
| `payment_details.type` | `Payout type momo must match the quote payout_method (bank_transfer)` |
| `payment_details.details.account_name` | `account_name must be a first and last name` (third-party payouts) |
| `payment_details.details.*` | The bank code, account number, or name isn't valid. |
| `customer_id` | `Customer first_name and last_name are required to initiate an offramp` |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.