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

# Off-Ramp (Crypto to Fiat)

> Accept crypto from your users and deliver local fiat currency directly to their bank accounts using the VelaFi crypto-to-fiat off-ramp API.

The VelaFi crypto-to-fiat off-ramp converts crypto from your merchant crypto balance into local fiat currency — such as MXN, ARS, BRL, or COP — deposited directly into your users' bank accounts. The API handles rate quoting, debiting the crypto from your merchant balance, conversion, and bank transfer initiation, so you can offer seamless cash-out flows without managing local payment infrastructure yourself.

### Confirm prerequisites

Before creating an off-ramp order, make sure the following setup is in place:

* **Merchant account activated** — your merchant record must exist and its fiat account must be active for the off-ramp direction.
* **Beneficiary added** — the user's bank account must be registered as a beneficiary in your VelaFi account. The beneficiary record's `userPaymentId` is required to create an off-ramp order. See [Creating a Beneficiary](https://docs.velafi.com/docs/guides/managing-beneficiaries.md) for the registration steps.
* **Crypto balance funded** — the crypto for the order is debited from the merchant's crypto balance. Check it with [Crypto Balance](https://docs.velafi.com/api-reference/merchant/get-crypto-assets-balance.md) and top it up through the merchant's [deposit address](https://docs.velafi.com/api-reference/merchant/get-crypto-deposit-address.md).
* **API credentials available** — all requests require the `X-BH-TOKEN` header containing a business token from `GET /v2/token/generate`.

### Get a quote (optional)

Request a real-time exchange rate before placing the order. The `price` is in units of fiat per 1 unit of crypto. With `createQuoteId=true`, the response also includes a `quoteId` that locks the rate.

**Endpoint:** `GET /v2/user/crypto-quote`

**Query parameters:**

**country** `string` *required*

Name of the country where the fiat payout will be delivered (e.g., `"Mexico"`).

**from** `string` *required*

The cryptocurrency being sold (e.g., `"USDT"`).

**to** `string` *required*

The fiat currency to receive (e.g., `"MXN"`).

**createQuoteId** `boolean`

Set to `true` to generate a `quoteId` you can pass when creating the order to lock the quoted price.

**Example response:**

```json theme={null}
{
  "code": 200,
  "msg": "SUCCESS",
  "data": {
    "price": "21.4104",
    "quoteId": "e46836d68a4a4a6f8f2f609352cffb2f"
  }
}
```

> [!TIP]
>
> The `quoteId` is valid for **10 seconds** in production (300 seconds in the sandbox) and is single-use by default. Pass it in the order creation request to guarantee the quoted rate. If you omit it, the order uses the rate at the time of placement.

### Create the off-ramp order

Submit a `POST` request to `/v2/order/crypto_to_fiat`. VelaFi debits the crypto from the merchant's crypto balance, converts it at the agreed rate, and pays the fiat out to the beneficiary's account. The response returns an `orderId` for tracking.

**Endpoint:** `POST /v2/order/crypto_to_fiat`

#### Request parameters

**country** `string` *required*

Name of the country where the fiat payout will be sent (e.g., `"Mexico"`).

**crypto** `string` *required*

Cryptocurrency the user is selling (e.g., `"USDT"`).

**fiat** `string` *required*

Fiat currency the user will receive (e.g., `"MXN"`).

**userPaymentId** `number` *required*

ID of the beneficiary's registered bank account (returned when you add a beneficiary). See [Get Beneficiaries](https://docs.velafi.com/api-reference/beneficiary/get-beneficiary.md).

**cryptoAmount** `decimal`

Amount of cryptocurrency to sell (e.g., `1000.00`). Provide either `cryptoAmount` or `fiatAmount`.

**fiatAmount** `decimal`

Target fiat amount the user should receive (e.g., `21410.40`). Provide either `fiatAmount` or `cryptoAmount`.

**quoteId** `string`

Quote ID from `GET /v2/user/crypto-quote`. Pass this to lock the quoted exchange rate for this order.

**clientId** `string`

Your own order reference ID, up to 40 characters, unique across all your `fiat_to_crypto` and `crypto_to_fiat` orders. A repeated `clientId` is rejected, so you can safely retry a create request with the same value. Returned as-is in subsequent order queries. See [Idempotency and retries](https://docs.velafi.com/api-reference/order/create-a-fiat-to-crypto-order.md#idempotency-and-retries).

**merchantId** `number` *required*

ID of the merchant the order belongs to. The crypto is debited from this merchant's balance. Requests without a valid `merchantId` are rejected.

**remark** `string`

Free-text note attached to the order for your reference.

#### Example request

```bash theme={null}
curl -X POST https://api.velafi.com/v2/order/crypto_to_fiat \
  -H "X-BH-TOKEN: YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "country": "Mexico",
    "clientId": "my-offramp-001",
    "merchantId": 3,
    "crypto": "USDT",
    "fiat": "MXN",
    "cryptoAmount": 1000.00,
    "userPaymentId": 91,
    "quoteId": "e46836d68a4a4a6f8f2f609352cffb2f",
    "remark": "Off-ramp for user #5678"
  }'
```

#### Example response

```json theme={null}
{
  "code": 200,
  "msg": "SUCCESS",
  "data": {
    "orderId": 1123123123
  }
}
```

Store the returned `orderId` — you will use it to monitor the order as it progresses through validation, conversion, and payout.

### System processes the conversion and bank transfer

After the order is accepted, VelaFi automatically:

1. **Debits the crypto** — takes the crypto amount from the merchant's crypto balance when the order is created. If the balance is too low, order creation fails with an insufficient-balance error, unless post-funded off-ramp is enabled for your account; then the order waits in `status: 32` (after compliance review, if the order needs it) until the balance covers it or `orderExpireTimestamp` passes. See [Funding the order](https://docs.velafi.com/api-reference/order/create-a-crypto-to-fiat-order.md#funding-the-order).
2. **Converts to fiat** — exchanges the crypto at the locked or current market rate.
3. **Initiates the bank transfer** — sends the fiat amount to the beneficiary's registered bank account via the local payment rail (e.g., SPEI for Mexico, PIX for Brazil).

> [!NOTE]
>
> For an order in status `50` (Paid), [`POST /v2/order/confirm`](https://docs.velafi.com/api-reference/order/confirm-a-specific-order) with `orderType` set to `crypto_to_fiat` completes the order (status `60`).

### Monitor order status

Poll `GET /v2/order/detail` with the `orderId` and `orderType=crypto_to_fiat`, or configure a [webhook](https://docs.velafi.com/docs/guides/webhooks.md) to receive real-time push notifications on every status change.

**Endpoint:** `GET /v2/order/detail?orderId={orderId}&orderType=crypto_to_fiat`

#### Example request

```bash theme={null}
curl -X GET "https://api.velafi.com/v2/order/detail?orderId=1123123123&orderType=crypto_to_fiat" \
  -H "X-BH-TOKEN: YOUR_TOKEN"
```

#### Example response

```json theme={null}
{
  "code": 200,
  "msg": "SUCCESS",
  "data": {
    "orderId": "1123123123",
    "clientId": "my-offramp-001",
    "merchantId": 3,
    "userPaymentId": 91,
    "country": "Mexico",
    "crypto": "USDT",
    "fiat": "MXN",
    "orderType": "crypto_to_fiat",
    "orderPrice": "21.4104",
    "cryptoAmount": "1000.0000",
    "fiatAmount": "21410.40",
    "fiatFee": "0",
    "orderStatus": 60,
    "traceNumber": "20241223907069062e51744c4f0e57",
    "paymentInfo": {
      "Cuenta CLABE": "000000000000000001"
    },
    "failCode": 0,
    "failReason": "",
    "createTime": "1740214865000",
    "completedTime": "1740215740000"
  }
}
```

#### Response fields

**orderId** `string`

Unique identifier for this order.

**clientId** `string`

Your own reference ID, echoed back from the create request.

**merchantId** `number`

ID of the merchant associated with this order.

**userPaymentId** `number`

ID of the beneficiary's registered bank account used for the fiat payout.

**country** `string`

Country where the fiat payout is delivered.

**crypto** `string`

Cryptocurrency sold by the user.

**fiat** `string`

Fiat currency received by the user.

**orderType** `string`

Always `crypto_to_fiat` for off-ramp orders.

**orderPrice** `string`

Exchange rate captured at order creation.

**cryptoAmount** `string`

Amount of cryptocurrency sold.

**fiatAmount** `string`

Amount of fiat currency delivered to the beneficiary.

**fiatFee** `string`

Fee charged in fiat currency for this order.

**orderStatus** `number`

Current status code. See [Order Statuses](https://docs.velafi.com/docs/order-statuses.md).

**traceNumber** `string`

National central bank reference number for the payout.

**paymentInfo** `object`

Bank account details used for the payout. Contents vary by country and payment method.

**failCode** `integer`

Error code recorded for a failed order. `0` when no failure code is recorded.

**failReason** `string`

Human-readable description of why the order failed.

**createTime** `string`

Order creation timestamp in milliseconds (Unix epoch).

**completedTime** `string`

Order completion timestamp in milliseconds (Unix epoch).

#### Order status codes

| Status | Label | Description |
| - | - | - |
| `10` | Reviewing | The order is in compliance review. |
| `11` | Request for information | RFI triggered — supporting documents required. |
| `12` | RFI uploaded | Documents uploaded and awaiting compliance approval. |
| `30` | Approved | Order awaiting user acceptance. |
| `31` | Support documents pending | Required documents must be submitted before processing. |
| `32` | Awaiting crypto deposit | Post-funded order waiting for the merchant's crypto balance to cover it. |
| `40` | Pending payment | Crypto debited from the merchant balance. |
| `50` | Paid | Fiat payout in progress. |
| `60` | Released | Order complete — fiat delivered to beneficiary. |
| `70` | Canceled | Order canceled (e.g., review rejection or timeout). |
| `72` | Refunded | Crypto refunded to the user. |
| `73` | Refunding | Crypto refund in progress. |

> [!WARNING]
>
> The `userPaymentId` must reference a beneficiary that is already registered in your VelaFi account. Attempting to create an order with an unknown `userPaymentId` will result in an error.


## Related topics

- [Introduction](https://docs.velafi.com/docs/introduction.md)
- [Quickstart](https://docs.velafi.com/docs/quickstart.md)
- [Get a Crypto/Fiat Quote](https://docs.velafi.com/api-reference/quote/get-user-quote-for-crypto-fiat.md)
- [Order Statuses](https://docs.velafi.com/docs/order-statuses.md)
- [On-Ramp (Fiat to Crypto)](https://docs.velafi.com/docs/guides/on-ramp.md)


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