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) |
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 — obligatoria cuando se usa paid_btn_name |
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. 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, y en las facturas fiat pagadaspaid_asset/paid_amount/paid_fiat_rate: la cripto realmente cobrada y el tipo usado. - 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. - Tal como se creó:
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 (activo y fiat mezclados),
400 invalid_amount, 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).
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 servidor ajusta la duración solicitada
al intervalo admitido. 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. Devuelve
{"items": [invoice, …]}, las más recientes primero.
deleteInvoice
POST /pay/api/deleteInvoice — ámbito invoices. Un parámetro:
invoice_id. Cancela una factura sin pagar y devuelve true. Errores:
404 invoice_not_found, 409 invoice_already_paid — una factura pagada no se
puede eliminar, 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, y el par de spend_id 409 idempotency_conflict /
409 idempotency_in_progress.
¿Te sirvió este artículo?
Gracias por tu comentario.