Referencia de la API: facturas y reembolsos
Los métodos de facturas: createInvoice, getInvoices, deleteInvoice,
refundInvoice. Las convenciones (autenticación, estructura de respuesta, montos,
spend_id) están en la página de
referencia de la API para comerciantes; el recorrido
guiado es Aceptar pagos con facturas.
createInvoice
POST /pay/api/createInvoice — ámbito invoices, límite de 60 por minuto.
| Parámetro | Tipo | Obligatorio | Significado |
|---|---|---|---|
currency_type | string | no | crypto (por defecto) o fiat |
asset | string | modo cripto | el activo a cobrar, por ejemplo USDT. Usa este campo en lugar de fiat |
fiat | string | modo fiat | la moneda fiat en la que está el precio (las filas is_fiat de getCurrencies). Se ignora en modo cripto: para fijar el precio en fiat, envía currency_type: "fiat" |
accepted_assets | string / array | no | solo en modo fiat: los activos admitidos para el pago — una cadena separada por comas ("USDT,GRAM") o un array JSON. Si se omite = todos los activos admitidos |
amount | string | sí, salvo que se use open_amount | cadena decimal positiva: unidades del activo en modo cripto, unidades fiat (máx. 2 decimales) en modo fiat |
open_amount | boolean | no | extensión, solo en modo cripto: sin monto fijo — quien paga ingresa uno al pagar (donaciones y propinas). Excluyente con amount |
description | string | no | hasta 1024 caracteres, se le muestra a quien paga |
hidden_message | string | no | hasta 2048 caracteres, se le revela a quien paga solo después del pago |
payload | string | no | hasta 4096 caracteres de datos propios, devueltos en la factura y en el webhook |
allow_comments | boolean | no | permitir que quien paga adjunte un comentario (por defecto true) |
allow_anonymous | boolean | no | permitir que quien paga oculte su identidad (por defecto true) |
paid_btn_name | string | no | botón posterior al pago: viewItem, openChannel, openBot o callback |
paid_btn_url | string | no | la URL http(s) del botón, de hasta 512 caracteres — obligatoria cuando se usa paid_btn_name y se ignora sin él |
swap_to | string | no | intercambiar automáticamente los pagos recibidos a este activo. Se hace lo posible: si el intercambio no se puede realizar al momento del pago, el pago se completa en el activo original |
expires_in | integer | no | segundos hasta que la factura expira, hasta 2678400 (31 días); omitido o 0 = duración predeterminada, que hoy también es de 31 días. Consulta expiration_date en el resultado |
rate_lock_seconds | integer | no | extensión, solo en modo fiat: congelar los tipos de conversión al crearla durante esta ventana (mira más abajo) |
La descripción, el contenido posterior al pago y el botón pueden permanecer ocultos mientras se revisa el contenido o si no se ha aprobado. El monto de la factura se puede pagar igualmente.
El resultado —y el payload del webhook invoice_paid— es el objeto de
factura. Sus campos clave:
- Identidad y estado:
invoice_id,hash(el id público dentro depay_url),status(active/paid/expired),pay_url— el enlace det.meque le envías a quien paga (bot_invoice_url,mini_app_invoice_urlyweb_app_invoice_urlson alias de él). - Montos:
amount(el valor nominal — unidades fiat en una factura fiat, cripto en el resto;nullmientras una factura de monto abierto está sin pagar),amount_minor(siempre en unidades mínimas de cripto: en una factura en cripto, el valor nominal; en una factura fiat,nullhasta el pago y después las unidades mínimas depaid_asset; en una factura de monto abierto,nullhasta el pago), y en las facturas fiat pagadaspaid_asset/paid_amount/paid_fiat_rate: la cripto realmente cobrada y el tipo usado. En una factura fiat,assetsigue ennullincluso después del pago. - Comisión:
fee_asset/fee_amount, registrados al pagar — la cifra de referencia para tus libros (feeyusd_rateson alias obsoletos de Crypto Bot). Mira comisiones y límites. - Quien paga:
paid_by_user_id(nullcuando eligió el anonimato),paid_anonymously,comment. - Reembolsos (extensión):
refunded_amount/refunded_minor(acumulados) yrefunded_at, registrado una vez reembolsada por completo. - Fijación del tipo (extensión):
rate_lock_untilyrate_lock_rates— los tipos registrados para cada activo,nullcuando no se pidió ninguna fijación. - Fechas y datos del pago:
created_at,paid_at,paid_usd_rate(el tipo de cambio a USD registrado al pagar). - Tal como se creó:
currency_type,accepted_assets,open_amount,is_anonymous,description,hidden_message,payload,paid_btn_name/paid_btn_url,expiration_date(expires_ates un alias), los campos de intercambio (swap_to,is_swapped,swapped_to,swapped_rate,swapped_output, …).
Errores: 400 invalid_currency (en modo cripto falta asset; en modo fiat
falta fiat, se envió también asset o se indicó open_amount),
400 invalid_amount (también un monto que se redondea a cero con la
precisión del activo), 400 unknown_asset, 400 unsupported_fiat,
400 paid_btn_url_required, y para las peticiones con fijación de tipo
400 rate_lock_fiat_only, 409 ratelock_disabled, 409 rate_unavailable (no
hay un tipo de cambio actualizado para un activo aceptado — reintenta).
400 invalid_request indica parámetros mal formados: un valor desconocido de
currency_type o paid_btn_name, un texto que supera su longitud máxima, un
expires_in fuera de 0–2678400 o un monto enviado como número JSON.
Cómo se pagan las facturas
El usuario paga con el saldo de su billetera en la Mini App, al instante
y sin comisión de red, siempre que tenga fondos suficientes y confirme el
pago. También puede aportar fondos desde una billetera externa: cuando
esta opción está disponible, la app muestra una dirección de depósito y una
fecha límite de pago. El depósito se abona a la billetera del propio usuario.
El pago automático requiere un depósito a esa dirección, saldo disponible
suficiente, ausencia de restricciones para los pagos salientes y que tanto
la solicitud de pago como la factura sigan vigentes. Un depósito que llegue
tarde permanece en la billetera del usuario; no demuestra que la factura
esté pagada. En ambos casos recibes lo mismo: una factura normal con estado
paid y un evento invoice_paid si configuraste una URL de webhook. No hay
parámetros ni campos adicionales que debas gestionar.
En una factura fiat, el monto en cripto se calcula al pagar y se redondea hacia arriba a la unidad mínima del activo elegido. Después se descuenta la comisión para comerciantes de ese monto en cripto. Si no hay un tipo fijado vigente ni un tipo de cambio actualizado, el pago falla en lugar de completarse con un tipo de cambio desactualizado.
Fijar el tipo en una factura fiat
Pasa rate_lock_seconds para fijar el tipo de cambio del momento de cada activo aceptado al crearla. Mientras el tipo fijado siga vigente, quien paga ve exactamente los montos fijados y el pago se convierte al tipo fijado: tú asumes el riesgo de tipo de cambio durante ese plazo. El parámetro admite de 0 a 86400 segundos: 0 significa sin bloqueo. Los demás valores se ajustan al plazo admitido: al menos 60 segundos y, como máximo, el límite de la plataforma. Los valores fuera de 0–86400 se rechazan con 400 invalid_request. Consulta rate_lock_until en el resultado para conocer la fecha límite real.
Cuando vence el plazo de fijación, la factura sigue siendo pagable si aún no ha
expirado, al tipo de cambio del momento del pago. Para hacer coincidir ambos
plazos, usa un expires_in dentro del intervalo admitido para la fijación y
compara expiration_date con rate_lock_until en la respuesta.
getInvoices
GET /pay/api/getInvoices — ámbito read. Filtros: asset, fiat,
invoice_ids (separados por comas), status (active / paid /
expired — expired es una extensión; active excluye las facturas que ya
pasaron su fecha límite), más offset / count (100 por defecto, máx. 1000).
Devuelve {"items": [invoice, …]}, las más recientes primero.
deleteInvoice
POST /pay/api/deleteInvoice — ámbito invoices. Un parámetro:
invoice_id. Elimina una factura sin pagar, activa o expirada, y devuelve
true. La factura se borra, no se marca: desaparece de getInvoices, su
pay_url deja de funcionar y no se envía ningún webhook. Si necesitas
un registro de la eliminación, guárdalo en tu sistema. Errores:
404 invoice_not_found, 409 invoice_already_paid — una factura pagada no se
puede eliminar porque el dinero ya se movió.
refundInvoice
POST /pay/api/refundInvoice — ámbito refunds, límite de 30 por minuto.
Esta extensión de la API de Crypto Bot devuelve toda la cripto pagada o parte
de ella desde el saldo de tu app a quien pagó. También funciona con pagos
anónimos sin revelar la identidad del usuario. En una factura fiat, usa
paid_asset y paid_amount: el reembolso no realiza una nueva conversión fiat.
| Parámetro | Tipo | Obligatorio | Significado |
|---|---|---|---|
invoice_id | integer | sí | la factura pagada |
amount | string | no | el monto en cripto que se reembolsará, en el activo del pago original (paid_asset para facturas fiat). Si se omite, se devuelve todo el monto pendiente de reembolso. Los reembolsos parciales se acumulan hasta el monto en cripto originalmente pagado |
spend_id | string | no | clave de idempotencia — usa una, para que, si repites una solicitud tras un tiempo de espera agotado, se devuelva el resultado anterior en vez de reembolsar dos veces |
El resultado es el objeto de factura actualizado con los acumulados
refunded_amount / refunded_minor; refunded_at se registra una vez que la
factura está reembolsada por completo. El estado sigue siendo paid. La
comisión de la plataforma no se devuelve. Tu app necesita saldo suficiente en
el activo del pago original, aunque swap_to haya convertido el ingreso a
otro activo. Cada reembolso genera el
webhook opcional refund_completed.
Errores: 404 invoice_not_found, 409 invoice_not_paid,
409 already_refunded (no queda nada por reembolsar), 409 amount_too_big
(más que el resto sin reembolsar), 409 insufficient_funds,
400 invalid_amount, 400 invalid_request (falta invoice_id o el
spend_id supera los 64 caracteres), 403 verification_required (las
operaciones salientes del dueño están restringidas),
503 merchant_payouts_paused, y el par de spend_id 409 idempotency_conflict /
409 idempotency_in_progress.
¿Te sirvió este artículo?
Gracias por tu comentario.