Recargar saldo (TopUp Cripto)
Generar una billetera cripto para recibir un depósito en tu cuenta de QvaPay. Funciona tanto para usuarios recargando su propio saldo como para apps/merchants que integren depósitos.
POST /api/topup
Crea una transacción de depósito y genera una billetera cripto (BTC, USDT, ETH, etc.) en la red elegida. Cuando se envíen fondos a esa billetera, el proveedor cripto notificará a QvaPay, QvaPay acreditará el saldo en USD a la cuenta y, si se proporcionó webhook_url, disparará un webhook saliente (ver TopUp Webhook).
Autenticación
Acepta dos modos:
- Bearer token de usuario (
Authorization: Bearer <token>) — caso típico de un usuario recargando su propio saldo. El TOPUP queda asociado aapp_id = 0y los webhooks (si se configurawebhook_url) se enviarán sin firma. - Credenciales de App (
app-id+app-secreten headers) — pensado para integraciones merchant que quieran recibir webhooks firmados con HMAC.
Rate limit
5 requests por minuto por usuario (ArcJet, token bucket). Usuarios vip quedan exentos.
Request
{
"amount": 100,
"pay_method": "BTC",
"webhook_url": "https://mitienda.com/webhook/topup"
}Parámetros
| Parámetro | Tipo | Requerido | Descripción |
|---|---|---|---|
amount | number | Si | Monto en USD a recibir (mayor al min_in de la moneda, máximo 100,000) |
pay_method | string | Si | Tick de la moneda (ej: BTC, USDT, ETH, TRX, SOL, LTC, DOGE, BTCLN...) |
webhook_url | string | No | URL pública (HTTPS recomendado) donde QvaPay enviará la notificación al acreditarse el pago. Máx. 191 caracteres. |
fee_mode | string | No | Solo depósitos con tarjeta (CARD). on_top (default): el fee se suma al cobro y se acredita el amount completo. included: se cobra exactamente el amount y se acredita el amount menos el fee. |
refund_address | string | No | Solo monedas que se convierten al recibirse (ver Monedas convertidas): dirección propia en la moneda enviada a la que se devuelven los fondos si el envío no se puede convertir. Sin ella, una devolución se tramita por soporte. |
compliance | object | No* | Atestación de propósito del fondeo. *Obligatoria en todo depósito de una cuenta US person, por cualquier método y canal; y para el navegador web en depósitos por transferencia bancaria (BANK). En los demás casos es opcional (recomendada). Ver Atestación en depósitos bancarios |
Response
{
"result": "OK",
"data": {
"wallet": "1A1z7agoat8Hs3zNx2EN1234567890",
"memo": null,
"coin": "BTC",
"value": 0.0025,
"price": 43000,
"transaction_id": "1234567",
"transaction_uuid": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"transaction_url": "https://pay.qvapay.com/?token=N2M5ZTY2NzktNz...",
"payment_id": "abc123",
"redirect_url": null
}
}Campos de respuesta
| Campo | Tipo | Descripción |
|---|---|---|
wallet | string | Dirección de la billetera donde se debe enviar los fondos |
memo | string | null | Memo o tag (cuando aplica, ej. Stellar/TON/Cosmos). Si viene, es obligatorio incluirlo en el envío |
coin | string | Tick de la moneda |
value | number | Cantidad de cripto que se debe enviar para acreditar el amount solicitado en USD |
price | number | Precio de la moneda en USD al momento de la cotización |
transaction_id | string | ID numérico interno de la transacción (BigInt como string) |
transaction_uuid | string | UUID único de la transacción — guárdalo para reconciliar contra el webhook |
transaction_url | string | URL de pago corta de QvaPay (opcional para redirigir al usuario) |
payment_id | string | ID interno del proveedor cripto |
redirect_url | string | null | URL de redirección si el proveedor lo provee (PayPal, etc.) |
Cómo se recibe cada moneda
QvaPay elige el camino según pay_method; la forma de la respuesta es siempre la misma:
- Dirección de depósito propia (BTC, LTC, TRX, USDT, USDC, ETH, SOL, TON, BNB, MATIC, ARB y otras):
walletes una dirección de un solo uso para este depósito. - Lightning (
BTCLN):walletes una factura Lightning (bolt11) por exactamentevalueBTC; caduca en 1 hora. Se acredita elamounten cuanto se paga. - Monedas convertidas al recibirse (
DOGE,ZEC,ATOM,BCH,AVAXen C-Chain,ADA,VET,XTZ,DASH,ALGO,SUI,XRP,LINK,SHIByCAKEen BSC,DAIen Ethereum,TRUMPen Solana,HMSTRyNOTen TON,USDCALGO,RVN): ver la sección siguiente.
Monedas convertidas al recibirse
Estas monedas se convierten automáticamente a USD al llegar, a la tasa de mercado del momento (tasa flotante):
valuees una estimación de cuánto enviar para que se acreditenamountUSD. Se acredita lo que realmente resulte de la conversión, menos el fee de la moneda: si se envía de más se acredita el excedente (con el recargo de sobrepago) y si se envía de menos se acredita lo recibido (is_partial: trueen el webhook).- La acreditación tarda lo que tarde la conversión (normalmente 5–30 minutos tras las confirmaciones de la red de origen). El webhook llega igual que en el resto de depósitos.
- Si
memoviene informado (p. ej.ATOM,USDCALGO, o el destination tag deXRP), el envío debe llevarlo. - Cada moneda tiene un mínimo por debajo del cual la conversión no sale (o cuesta demasiado: algunas redes tienen un coste fijo por envío). La respuesta lo indica con
400BELOW_MINymin_usd, que puede cambiar con el mercado.
Atestación de cuentas US person
Una cuenta US person (se declaró persona estadounidense, verificó con un documento emitido en EE. UU. o sus territorios, o tiene SSN/ITIN en su ficha) tiene que enviar el objeto compliance en todo depósito, sea cripto, bancario o de cualquier otro método, y desde cualquier canal (web, apps móviles, apps de comercio y clientes API). Si falta o no es válido, la respuesta es 400 con code: "US_PERSON_ATTESTATION_REQUIRED". Vigente desde el 29 sep 2026. El formato y los códigos (P-1…P-4) son los mismos de la sección siguiente.
Atestación en depósitos bancarios
Un depósito por transferencia bancaria (pay_method: "BANK") entra en la cuenta bancaria estadounidense de QvaPay, por lo que el cliente declara el propósito del fondeo con el mismo objeto compliance que usan los retiros:
{
"amount": 500,
"pay_method": "BANK",
"compliance": {
"purposeCode": "P-1",
"attestations": {
"notProhibitedOfficial": true,
"notProhibitedPartyMember": true,
"notRestrictedList": true,
"lawfulPurpose": true
}
}
}Códigos válidos en este ámbito: P-1 (remesa familiar), P-2 (pago al sector privado), P-3 (donativo), P-4 (recarga / telecomunicaciones). Las cuatro casillas de attestations deben ser true.
La exigencia se despliega por canal: el navegador web recibe 400 si falta; las apps móviles (x-qvapay-client-platform: ios|android), las apps de comercio (app-id) y los clientes API con Bearer propio pueden omitirla hoy (se registra la ausencia) y deberían enviarla desde ya. Los depósitos cripto no la requieren, salvo que la cuenta sea US person (ver arriba).
Errores
| Código | Descripción |
|---|---|
400 | Datos inválidos: amount fuera de rango, pay_method no soportado, webhook_url no válida |
400 | Depósito BANK desde el navegador sin el objeto compliance |
400 | US_PERSON_ATTESTATION_REQUIRED: depósito de una cuenta US person sin compliance válido, en cualquier canal |
400 | BELOW_MIN: monto por debajo del mínimo de conversión de la moneda en este momento (min_usd trae el mínimo) |
403 | KYC_REQUIRED: la cuenta no tiene verificación de identidad aprobada (kyc_url indica dónde completarla) |
403 | COMPANY_ACCOUNT_REQUIRED: depósito BANK desde una cuenta no elegible (ver nota) |
401 | Credenciales de app o bearer token ausentes/inválidos |
429 | Rate limit excedido (más de 5 requests por minuto) |
429 | CARD_DAILY_LIMIT: tope diario de depósitos con tarjeta de la cuenta (ver nota) |
400 | DEPOSIT_MONTHLY_LIMIT: la cuenta deposita por el nivel «SSN verificado» y este CARD/PAYPAL supera su tope de 30 días (cap, used, remaining, window_days, resets_at; ver nota) |
429 | RATE_LIMITED: en el nivel «SSN verificado», un depósito CARD/PAYPAL cada 5 segundos |
500 | Error interno al crear la transacción o billetera |
503 | DEPOSIT_UNAVAILABLE: la conversión de esa moneda no está disponible en este momento; reintentar en unos minutos |
Notas importantes
BANKsolo para cuentas elegibles: los depósitos por transferencia bancaria están disponibles para cuentas VIP, cuentas con TrustScore de 85 o más, y cuentas empresa (cuenta de tipo empresa o titular de una empresa registrada y aprobada en Ajustes) — la misma regla quePAYPAL. Cualquier otra cuenta recibe403concode: "COMPANY_ACCOUNT_REQUIRED"(el código se mantiene por compatibilidad); el wizard de depósito no muestra el método a esas cuentas.CARD(depósito con tarjeta): misma elegibilidad quePAYPALy, además, la petición debe venir desde fuera de Cuba. Monto entremin_inymax_inde la moneda. El tope diario cuenta intentos (cada depósito creado, se pague o no): 3 por día en cuentas personales, que depositan a su propio saldo. Una cuenta empresa puede cobrar a sus clientes con tarjeta por este método (crea el depósito conwebhook_urly envía al cliente atransaction_url; el webhook de TopUp llega al acreditarse), por lo que tiene un tope diario propio y mucho mayor. Al superarlo,429concode: "CARD_DAILY_LIMIT". El contracargo de una tarjeta de cliente se descuenta del saldo de la cuenta que cobró.- Nivel «SSN verificado» (solo apps móviles): una persona de EE. UU. GOLD que verificó su SSN (ver Verificación del SSN) puede depositar con
CARDyPAYPALsin ser VIP, TrustScore ≥ 85 ni empresa, con un tope combinado de $500 sobre lo cobrado en los últimos 30 días (ventana rodante). Solo desdex-qvapay-client-platform: ios|android. Antes de ofrecer el método, consultaGET /user/deposit-eligibility, que devuelve el nivel (fullsin tope,ssncon tope) y el cupo restante. - Cap al monto solicitado: si se envía cripto que excede el
amountsolicitado, QvaPay solo acredita elamounty el excedente queda en cuenta interna. Pide el monto exacto que indicavalueen la respuesta. - Subpago: si se envía menos del solicitado, se acredita lo que valga en USD después del fee. El webhook indicará
is_partial: true(ver TopUp Webhook). - Idempotencia del webhook: el mismo
transaction_uuidpuede llegar 1–3 veces al webhook (política de reintentos). Tu endpoint debe ser idempotente.