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

# Convertir moneda local a stablecoins

> Compra USDT o USDC con moneda local mediante una orden fiat_to_crypto, pagada desde tu saldo Pending Fund o por un pagador en cada orden, y entrega la cripto a tu billetera o a una dirección externa.

Esta receta convierte moneda local (por ejemplo, MXN, ARS, COP o BRL) en una stablecoin con una orden `fiat_to_crypto`. Tú eliges cómo se paga cada orden: con fiat que ya tienes en el saldo Pending Fund del comercio, o mediante un pagador que envía una transferencia bancaria para esa orden en particular. Cuando la orden se completa, la cripto se abona a la billetera de VelaFi del comercio. Desde ahí la conservas, la retiras o haces que se envíe automáticamente a una dirección externa.

Para la referencia completa de campos, consulta la guía [On-ramp (fiat a cripto)](https://docs.velafi.com/es/docs/guides/on-ramp.md) y [Crear una orden de on-ramp](https://docs.velafi.com/es/api-reference/order/create-a-fiat-to-crypto-order.md).

## Elige un modelo de fondeo

| | Prefondeado (recomendado) | Pago por orden |
| - | - | - |
| Cómo se paga la orden | Desde el saldo Pending Fund del comercio en esa moneda | El pagador envía una transferencia bancaria a los datos de pago devueltos para la orden |
| `paymentId` | `70` (VelaFi Pending Fund) | El canal de la cuenta de moneda, por ejemplo `105` (SPEI, Finco Pay) |
| Revisión del saldo | Al crearla: la solicitud se rechaza si el saldo no cubre la orden | Ninguna al crearla |
| Resultado típico | Se completa a los pocos segundos de crearse | Se completa cuando llega el pago. Si no llega ningún pago dentro de la ventana de pago, la orden se cancela |
| Lo que tú manejas | Mantener el saldo recargado | Mostrar las instrucciones de pago, los retrasos de los pagadores, las órdenes expiradas |

> [!TIP]
>
> Si tu negocio puede mantener un saldo en moneda local, usa el modelo prefondeado. La orden se paga en el momento en que se crea, así que no puede expirar sin pago, y sabes si los fondos están disponibles antes de comprometerte con la operación. El pago por orden depende de que el pagador envíe el monto exacto antes de que se cierre la ventana, y muchas órdenes de pago por orden expiran sin pago.

## Cómo funciona

```mermaid theme={null}
flowchart TD
    A[Opcional: obtén una cotización con quoteId] --> B{Modelo de fondeo}
    B -->|Prefondeado| C["POST /v2/order/fiat_to_crypto<br/>paymentId 70"]
    C --> D[Orden pagada desde el saldo Pending Fund]
    B -->|Pago por orden| E["POST /v2/order/fiat_to_crypto<br/>paymentId del canal"]
    E --> F[Muestra paymentInfo al pagador]
    F --> G{¿Pagada dentro de la ventana?}
    G -->|Sí| D2[Depósito abonado y asignado a la orden]
    G -->|No| X["Orden cancelada: orderStatus 70"]
    D --> H["Orden completada: orderStatus 60<br/>cripto en la billetera del comercio"]
    D2 --> H
    H --> I{Entrega la cripto}
    I -->|Conservar| J[Mantener en la billetera del comercio]
    I -->|Retiro automático| K[Enviada a la dirección de la orden<br/>ON_RAMP_WITHDRAW_WEBHOOK]
    I -->|Retiro manual| L["POST /v2/assets/withdraw<br/>CRYPTO_WITHDRAW_WEBHOOK"]
```

## Antes de empezar

* **Acceso a la API.** Una clave de API, las IP de tus servidores en la lista blanca y un token de negocio para el header `X-BH-TOKEN`. Consulta [Autenticación](https://docs.velafi.com/es/api-reference/authentication.md).
* **Un comercio verificado.** El `merchantId` de la orden debe ser un comercio de tu cuenta que haya pasado la verificación. Consulta [Comercios](https://docs.velafi.com/es/docs/merchants.md).
* **Una cuenta de moneda activada.** El comercio necesita una cuenta activa para la moneda fiat. Consulta [Activar la cuenta de un comercio](https://docs.velafi.com/es/docs/guides/activating-merchant-account.md).
* **Webhooks registrados.** Registra `ORDER_WEBHOOK`, además de `FUNDING_WEBHOOK` si prefondeas y `CRYPTO_WITHDRAW_WEBHOOK` si retiras. Consulta [Webhooks](https://docs.velafi.com/es/docs/guides/webhooks.md). Tu endpoint debe devolver HTTP `2xx` con el cuerpo `{"callbackStatus":"SUCCESS"}`; de lo contrario, la entrega cuenta como fallida. Consulta [Entrega y reintentos](https://docs.velafi.com/es/api-reference/webhooks/webhook-setup.md#delivery-and-retries).

## Construye el flujo

**1. Solo prefondeado: fondea el saldo Pending Fund**

Obtén los datos de depósito de la cuenta de moneda del comercio con [Obtener la cuenta Pending Fund](https://docs.velafi.com/es/api-reference/merchant/get-pending-fund-account.md) (`GET /v2/merchant/addfunds`) y envía el fiat ahí. Cada depósito abonado dispara un evento `FUNDING_WEBHOOK` con `type` `DEPOSIT` y `status` `2`.

Revisa el saldo actual con [Listar cuentas de comercio](https://docs.velafi.com/es/api-reference/merchant/get-a-list-of-merchant-accounts.md) (`balance`) antes de crear órdenes grandes.

Si ya cobras pagos en la cuenta de moneda del comercio, esos depósitos forman este saldo. Consulta [Cobrar pagos locales con cuentas virtuales](https://docs.velafi.com/es/docs/use-cases/collect-with-virtual-accounts.md).

**2. Opcional: fija el tipo de cambio con una cotización**

Llama a [Obtener una cotización cripto/fiat](https://docs.velafi.com/es/api-reference/quote/get-user-quote-for-crypto-fiat.md) con `from` igual al fiat, `to` igual a la cripto y `createQuoteId=true`. El `price` está expresado en fiat por 1 unidad de cripto.

```bash theme={null}
curl "https://api.velafi.com/v2/user/crypto-quote?country=Mexico&from=MXN&to=USDT&createQuoteId=true" \
  -H "X-BH-TOKEN: YOUR_TOKEN"
```

Un `quoteId` es válido durante 10 segundos en producción (300 segundos en el sandbox), es de un solo uso y está vinculado al `country`, el fiat y la cripto para los que se emitió. Solicítalo justo antes de crear la orden. Sin un `quoteId`, la orden se cotiza al momento de crearse.

**3. Crea la orden**

Llama a `POST /v2/order/fiat_to_crypto`. Envía siempre un `clientId` único (hasta 40 caracteres) para que puedas reintentar de forma segura y encontrar la orden después.

> [tab] Prefondeado
>
> Establece `paymentId` en `70` (VelaFi Pending Fund).
>
> ```bash theme={null}
> curl -X POST https://api.velafi.com/v2/order/fiat_to_crypto \
>   -H "X-BH-TOKEN: YOUR_TOKEN" \
>   -H "Content-Type: application/json" \
>   -d '{
>     "merchantId": 100001,
>     "clientId": "onramp-0001",
>     "country": "Mexico",
>     "fiat": "MXN",
>     "crypto": "USDT",
>     "fiatAmount": 1000,
>     "paymentId": 70,
>     "quoteId": "YOUR_QUOTE_ID"
>   }'
> ```
>
> VelaFi revisa el saldo del comercio en esa moneda cuando crea la orden. Si el saldo no cubre el monto de la orden, la solicitud se rechaza con un error de saldo insuficiente y no se crea ninguna orden. Si el saldo la cubre, la orden se paga desde el saldo justo después de crearse y pasa a `60` (Completada), a menos que primero requiera revisión o documentos (`10`, `11` o `31`). El cargo aparece en [Registros de fondeo](https://docs.velafi.com/es/api-reference/merchant/retrieve-funding-records.md) como un registro `BUY_CRYPTO`.

> [tab] Pago por orden
>
> Establece `paymentId` en el canal de la cuenta de moneda del comercio, por ejemplo `105` para SPEI (Finco Pay). Consulta [Métodos de pago](https://docs.velafi.com/es/docs/payment-methods.md). Si le das a cada pagador su propia cuenta virtual, envía también el `depositAlias` de esa cuenta.
>
> ```bash theme={null}
> curl -X POST https://api.velafi.com/v2/order/fiat_to_crypto \
>   -H "X-BH-TOKEN: YOUR_TOKEN" \
>   -H "Content-Type: application/json" \
>   -d '{
>     "merchantId": 100001,
>     "clientId": "onramp-0002",
>     "country": "Mexico",
>     "fiat": "MXN",
>     "crypto": "USDT",
>     "fiatAmount": 1000,
>     "paymentId": 105,
>     "depositAlias": "PAYER0001"
>   }'
> ```
>
> La orden empieza en `40` (Pago pendiente), o en `10`, `11` o `31` cuando se requiere revisión o documentos.

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

Si la solicitud excede el tiempo de espera, busca la orden por `clientId` antes de reintentar. Consulta [Idempotencia y reintentos](https://docs.velafi.com/es/api-reference/order/create-a-fiat-to-crypto-order.md#idempotency-and-retries).

**4. Solo pago por orden: muestra las instrucciones de pago**

Llama a [Obtener una orden](https://docs.velafi.com/es/api-reference/order/retrieve-a-specific-order.md) con `orderType=fiat_to_crypto` y muestra al pagador el contenido de `paymentInfo` (por ejemplo, la CLABE para SPEI) y el `fiatAmount` exacto.

Cuando se abona la transferencia del pagador, VelaFi la aplica a las órdenes abiertas de la misma cuenta de moneda. Un depósito que es exactamente igual al monto de una orden se aplica primero a esa orden. De lo contrario, los depósitos se aplican a la orden abierta más antigua. Una orden con `depositAlias` solo se paga con depósitos a esa cuenta virtual. Una orden sin él se puede pagar con cualquier depósito en la cuenta de moneda, incluido el fiat que ya está en el saldo Pending Fund.

> [!WARNING]
>
> Una orden solo se paga cuando el monto completo está disponible. Un pago incompleto no completa la orden. Pide a los pagadores que envíen el monto exacto y dale a cada pagador una cuenta virtual (`depositAlias`) para que la transferencia de un pagador no pueda pagar la orden de otro.

**5. Da seguimiento a la orden hasta que se complete**

Espera los eventos `ORDER_WEBHOOK` o consulta periódicamente `GET /v2/order/detail?orderType=fiat_to_crypto&clientId={clientId}`. La orden está terminada cuando `orderStatus` es `60`, y falló cuando es `70`, `80` u `81`. Cuando consultas, una orden rechazada en revisión se muestra como `80` y una rechazada en revisión de riesgos como `81`; el webhook envía ambas como `70`. Consulta [Estados de las órdenes](https://docs.velafi.com/es/docs/order-statuses.md). La cripto (`cryptoAmount`) queda entonces en la billetera del comercio. Revísala con [Obtener el saldo cripto](https://docs.velafi.com/es/api-reference/merchant/get-crypto-assets-balance.md).

**6. Opcional: envía la cripto fuera de la billetera**

Tienes dos opciones:

* **Retiro automático por orden.** Si VelaFi habilitó el retiro automático de on-ramp para tu cuenta, agrega `network` y `address` a la solicitud de creación. Después de que la orden se completa, VelaFi retira `cryptoAmount` a esa dirección y envía `ON_RAMP_WITHDRAW_WEBHOOK` cuando el retiro es exitoso. En producción, `network` debe ser `POL` o `SPL20`. Envía ambos campos o ninguno. Las cuentas sin esta función se rechazan con "You are currently not a user of the onRamp automatic withdrawal service." Consulta [Evento de retiro de on-ramp](https://docs.velafi.com/es/api-reference/webhooks/on-ramp-withdraw-message-push.md).
* **Retírala tú mismo.** Agrega el destino a tu [lista blanca de retiros](https://docs.velafi.com/es/api-reference/crypto-wallet/add-whitelist-address.md) y después llama a [Crear un retiro cripto](https://docs.velafi.com/es/api-reference/crypto-wallet/create-crypto-withdrawal.md) (`POST /v2/assets/withdraw`) con tu propio `clientId` único. Usa [Obtener la cuota de retiro](https://docs.velafi.com/es/api-reference/crypto-wallet/get-withdrawal-quota.md) para conocer los valores válidos de `chainType` y los mínimos.

Ambos tipos de retiro también disparan `CRYPTO_WITHDRAW_WEBHOOK` cuando llegan a un estado final. En un retiro automático, su `clientId` es el `orderId` del on-ramp.

## Webhooks que debes manejar

| Evento | Cuándo | Clave | Qué hacer |
| - | - | - | - |
| `ORDER_WEBHOOK` (solo órdenes creadas mediante la API) | La orden entra a `10`, `11`, `12`, `31`, `40`, `50`, `60`, `70` o `72` | `orderId` + `orderStatus` (`orderType` es `BUY`) | Marca la orden como completada en `60` y como fallida en `70`. Las órdenes rechazadas en revisión se envían como `70`. |
| `FUNDING_WEBHOOK` | Se completa un registro de Pending Fund: `DEPOSIT` (recarga o transferencia del pagador), `BUY_CRYPTO` (fiat aplicado a una orden) | `txId` + `status` | Da seguimiento al saldo fiat. |
| `ON_RAMP_WITHDRAW_WEBHOOK` | Un retiro automático fue exitoso | `orderId` | Registra el `txHash`. Los retiros fallidos no envían este evento. |
| `CRYPTO_WITHDRAW_WEBHOOK` | Un retiro llegó a `SUCCESS`, `FAILED` o `CANCELLED` | `withdrawId` + `status` | Marca el retiro como final. |

Los eventos pueden llegar más de una vez y fuera de orden, y se pueden omitir estados intermedios. Elimina duplicados y lee la orden con `GET /v2/order/detail` cuando un evento no coincida con el estado que tienes. Consulta [Entrega y reintentos](https://docs.velafi.com/es/api-reference/webhooks/webhook-setup.md#delivery-and-retries).

## Maneja las fallas

| Lo que ves | Causa probable | Qué hacer |
| - | - | - |
| Creación rechazada con un error de saldo insuficiente (prefondeado) | El saldo Pending Fund no cubre la orden | Recarga el saldo o reduce el monto, y después crea la orden otra vez con un nuevo `clientId` y una nueva cotización. |
| Creación rechazada como envío repetido | El `clientId` ya se usó, posiblemente en tu propia solicitud anterior que excedió el tiempo de espera | Busca la orden por `clientId`. No la vuelvas a crear. |
| Creación rechazada después de enviar un `quoteId` | La cotización expiró, ya se usó o se emitió para otro par de monedas | Solicita una nueva cotización. Una creación rechazada todavía puede consumir un `quoteId`. |
| `orderStatus` `70` en una orden de pago por orden | No llegó un pago completo dentro de la ventana de pago, o la orden fue cancelada | Crea una nueva orden con un nuevo `clientId` y muestra al pagador las nuevas instrucciones. |
| `orderStatus` `80` u `81` al consultar (`70` en el webhook) | Rechazada en revisión o en revisión de riesgos | No la vuelvas a enviar sin cambios. Contacta a VelaFi si necesitas el motivo. |
| La orden se queda en `10`, `11` o `31` | Se requiere revisión, revisión de riesgos o documentos de soporte | Sube los documentos con [Subir documentos de una orden](https://docs.velafi.com/es/api-reference/order/upload-invoice-documents-for-a-specific-order.md) cuando se te pidan. Consulta [Estados de las órdenes](https://docs.velafi.com/es/docs/order-statuses.md). |
| `ON_RAMP_WITHDRAW_WEBHOOK` nunca llega | El retiro automático falló o no se realizó | Revisa el saldo cripto y [Listar retiros cripto](https://docs.velafi.com/es/api-reference/crypto-wallet/get-crypto-withdrawal-history.md) con `clientId` igual al `orderId` del on-ramp. Si la cripto sigue en la billetera, retírala tú mismo. |

### La ventana de pago

Una orden de pago por orden espera en `40` solo por un tiempo limitado. VelaFi define la ventana para tu cuenta. No se devuelve en el detalle de la orden, así que pide el valor a tu contacto en VelaFi y muestra al pagador una fecha límite basada en `createTime`. Cuando pasa la ventana sin un pago completo, la orden se cancela. Se reporta como `orderStatus` `70` en el detalle de la orden y en `ORDER_WEBHOOK`. Una orden cancelada no se puede reabrir.

Si el pagador paga después de que la orden fue cancelada, la transferencia igual se abona al saldo Pending Fund del comercio (recibes un `FUNDING_WEBHOOK` `DEPOSIT`). No se aplica a la orden cancelada. Crea una nueva orden por ese monto, que entonces se paga desde el saldo, o dispersa el dinero con [Reclamar fondos Pending Fund](https://docs.velafi.com/es/api-reference/merchant/claim-pending-fund.md).

## Concilia

* **Órdenes:** [Obtener una orden](https://docs.velafi.com/es/api-reference/order/retrieve-a-specific-order.md) por `orderId` o `clientId` es la fuente de verdad de cada orden: `orderStatus`, `fiatAmount`, `fiatFee`, `cryptoAmount`, `orderPrice`, `failCode` y `failReason`. Usa [Listar órdenes](https://docs.velafi.com/es/api-reference/order/retrieve-a-list-of-orders.md) con un rango de tiempo para los totales diarios. También lista órdenes que no se crearon mediante la API.
* **Saldo fiat:** [Listar registros de fondeo](https://docs.velafi.com/es/api-reference/merchant/retrieve-funding-records.md) muestra cada `DEPOSIT` y `BUY_CRYPTO`, para ambos modelos de fondeo. [Listar flujos fiat](https://docs.velafi.com/es/api-reference/merchant/get-a-list-merchant-fiat-flow.md) da el libro contable línea por línea con saldos acumulados.
* **Salida de cripto:** [Listar retiros cripto](https://docs.velafi.com/es/api-reference/crypto-wallet/get-crypto-withdrawal-history.md) por `clientId`, hasta que `status` sea `6` (exitoso), `7` (fallido) o `9` (cancelado).

Ejecuta un proceso programado que vuelva a leer cada orden que siga abierta de tu lado. Los webhooks se pueden perder después de tres intentos de entrega fallidos.

## Prueba en el sandbox

* Usa `https://api-test.velafi.com`. Los webhooks **no** se envían en el sandbox, así que consulta periódicamente `GET /v2/order/detail`.
* Fondea el saldo de un comercio de prueba, o paga una orden de pago por orden, con el simulador de depósitos fiat (`depositAlias` apunta a una cuenta virtual). Consulta [Herramientas de prueba del sandbox](https://docs.velafi.com/es/docs/sandbox.md#sandbox-testing-tools).
* En el sandbox, un `quoteId` dura 300 segundos, y el retiro automático acepta `POL` o `TSPL20` como `network`.
* Los simuladores solo producen depósitos exitosos. No puedes simular un pago devuelto. Prueba el camino de expiración creando una orden de pago por orden y no pagándola.

## Lista de verificación para salir a producción

* [ ] Cada solicitud de creación envía un `clientId` único, y los timeouts se resuelven buscando el `clientId` antes de reintentar.
* [ ] Los flujos prefondeados revisan el saldo y manejan el rechazo por saldo insuficiente sin reintentar la misma solicitud en un ciclo.
* [ ] Los flujos de pago por orden muestran `paymentInfo`, el monto exacto y una fecha límite, y crean una nueva orden después de `70`.
* [ ] Cada pagador tiene una cuenta virtual (`depositAlias`) si usas pago por orden para varios pagadores en una misma cuenta de moneda.
* [ ] El endpoint de `ORDER_WEBHOOK` verifica la firma, devuelve `{"callbackStatus":"SUCCESS"}` con HTTP `2xx` y elimina duplicados sobre `orderId` + `orderStatus`.
* [ ] Un proceso programado concilia las órdenes abiertas, los registros de fondeo y los retiros contra la API.
* [ ] Los destinos de retiro están en la lista blanca, o el retiro automático está habilitado y probado con `network` y `address`.

Consulta la [lista de verificación para salir a producción](https://docs.velafi.com/es/docs/use-cases/go-live-checklist.md) completa.


## Related topics

- [Casos de uso principales](https://docs.velafi.com/es/docs/use-cases/overview.md)
- [Agent Skills](https://docs.velafi.com/es/docs/developer-tools/agent-skills.md)
- [Dispersar moneda local fondeada con stablecoins](https://docs.velafi.com/es/docs/use-cases/payouts-funded-by-stablecoins.md)
- [Introducción](https://docs.velafi.com/es/docs/introduction.md)
- [Documentación de la API de VelaFi](https://docs.velafi.com/es/index.md)


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