tgpay cryptoAPI
crypto-payapitransferspayouts

Referencia de la API: transferencias y cheques

7 min de lecturaActualizado el 9 oct 2026

Estos métodos permiten enviar pagos. Una transferencia envía fondos del saldo de tu app a la billetera de un usuario de Telegram o los retiene hasta que un nuevo destinatario abra el bot. Un cheque es un enlace canjeable que financias por adelantado. Las convenciones (autenticación, formato de las respuestas, montos, spend_id) están en la página de referencia de la API para comerciantes.

Los tres métodos de pago se rigen por el modo de pagos de la app: una app nueva le paga a cualquiera desde el principio; si el dueño lo restringió, solo se les puede pagar a los destinatarios de la lista (403 recipient_not_allowed) o a nadie (403 payouts_disabled). El modo lo fija el dueño en la Mini App; no se puede cambiar por API. Los usos permitidos de estos pagos se establecen en las condiciones de la API para comerciantes.

transfer

POST /pay/api/transfer — ámbito payouts, límite de 30 por minuto. Si el destinatario ya usa la app, recibe el pago al instante. Si el username es desconocido, se crea una transferencia con estado pending: los fondos quedan retenidos en escrow hasta que el destinatario abra el bot con ese nombre de usuario. Los fondos sin reclamar se devuelven al saldo de la app después del vencimiento a los 30 días (expires_at). Comprueba que el estado sea status: "returned" antes de contabilizar la devolución. Envía tú el invite_url: el bot no puede escribirle a alguien que nunca lo inició. El estado final es completed o returned. Para seguirlo, suscríbete a los webhooks opcionales transfer_completed y transfer_returned, o consulta getTransfers.

ParámetroTipoObligatorioSignificado
user_idintegerexactamente uno de user_id / usernameid de Telegram del destinatario; debe ser un usuario existente de la app
usernamestringexactamente uno de user_id / usernamenombre de usuario del destinatario, con o sin @; un nombre desconocido crea un pago pendiente
assetstringsícódigo del activo
amountstringsícadena decimal positiva; sujeta también al mínimo y al máximo por transferencia de la plataforma, calculados en dólares a los tipos de cambio actuales
spend_idstringsíclave de idempotencia, de 1 a 64 caracteres, única por pago
commentstringnohasta 1024 caracteres, se muestra al destinatario
disable_send_notificationbooleannotrue = no notificar al destinatario por Telegram en un pago inmediato; al recibir un pago que estaba pendiente, el destinatario siempre recibe una notificación

El resultado es el objeto de transferencia: transfer_id, hash, user_id, recipient_username, asset, amount, amount_minor, spend_id, comment, status (pending / completed / returned), created_at, completed_at, expires_at, invite_url. user_id puede ser null mientras se espera al nuevo destinatario; completed_at es null hasta que se completa la transferencia.

Errores: 403 payouts_disabled / 403 recipient_not_allowed (el modo de pagos), 404 user_not_found (el id es desconocido o el destinatario no está disponible), 400 invalid_recipient (el nombre de usuario del destinatario tiene un formato inválido), 400 amount_too_small / 400 amount_too_big (fuera de los límites por transferencia), 409 insufficient_funds, 400 unknown_asset, 400 invalid_amount, y el par de spend_id 409 idempotency_conflict / 409 idempotency_in_progress.

transferBatch

POST /pay/api/transferBatch — ámbito payouts, límite de 10 por minuto. Una extensión para pagos masivos: hasta 100 transferencias en una llamada.

Un parámetro: items, un array donde cada elemento contiene todos los parámetros de transfer (user_id o username, asset, amount, spend_id, y los opcionales comment y disable_send_notification). Los spend_id tienen que ser únicos dentro del lote, o toda la llamada falla con 400 duplicate_spend_id antes de ejecutar nada. Una estructura inválida, el modo de pagos de la app o su límite diario también pueden causar el rechazo de toda la solicitud antes de enviar ningún pago. Si se acepta, los resultados se devuelven en result.items.

Los elementos se procesan de forma independiente y en orden: un elemento fallido nunca revierte a los demás. La llamada devuelve HTTP 200 con ok: true incluso cuando algunos elementos fallaron, así que revisa siempre cada uno:

  • éxito: {"ok": true, "spend_id": "…", "result": <transfer object>}
  • fallo: {"ok": false, "spend_id": "…", "error": {"code": …, "name": "…"}} con los mismos nombres de error que un transfer individual.

Los elementos del lote comparten el espacio de idempotencia con las transferencias individuales: reintentar el lote entero —o reenviar un elemento como un transfer individual con el mismo spend_id— devuelve el resultado anterior sin pagar dos veces.

getTransfers

GET /pay/api/getTransfers — ámbito read. Filtros: asset, transfer_ids (separados por comas), spend_id (coincidencia exacta: busca un pago por tu propia clave), status (pending / completed / returned), más offset / count. Devuelve {"items": [transfer, …]}, los más recientes primero.

createCheck

POST /pay/api/createCheck — ámbito checks, límite de 60 por minuto. Por defecto, crea un cheque de un solo uso con el saldo de tu app. Puede canjearlo cualquiera que tenga el enlace o solo el usuario designado. La extensión recipients permite crear una lista de destinatarios con un monto individual para cada uno. El total se retiene al crear el cheque (pasa de available a onhold en getBalance). La creación de cheques está sujeta a los mismos límites de monto y de pagos diarios que las transferencias.

ParámetroTipoObligatorioSignificado
assetstringsícódigo del activo
amountstringsalvo que se use recipientscadena decimal positiva; con recipients, el total se calcula a partir de la lista
pin_to_user_idintegernosolo este ID de Telegram puede canjearlo
pin_to_usernamestringnosolo este @usuario puede canjearlo (la @ es opcional; se ignora cuando también se usa pin_to_user_id). El nombre de usuario debe pertenecer a un usuario existente de la app
spend_idstringnoclave de idempotencia (extensión); usa una
recipientsarraynoextensión: de 1 a 100 elementos, cada uno con user_id o username y un amount como cadena decimal positiva. No se puede combinar con un usuario designado
passwordstringnoextensión: contraseña necesaria para canjearlo; hasta 64 caracteres
expires_inintegernoextensión: duración en segundos; omitido o 0 = sin vencimiento

El resultado es el objeto de cheque: check_id, hash, asset, amount, amount_minor, bot_check_url (el enlace de canje de t.me), status (active / activated), pin_to_user_id, created_at, activated_at, expires_at y recipients (null en un cheque normal; en caso contrario, cada elemento contiene user_id, username, amount, amount_minor y claimed_at). Cada canje genera el webhook opcional check_activated; si es un cheque con lista de destinatarios, incluye también activated_slot. Al expirar se devuelve el monto sin canjear; si tiene una lista de destinatarios, puede enviarse check_expired.

La respuesta actual indica status: "active" para todos los cheques que no se hayan canjeado por completo, incluso si han expirado. Consulta también expires_at: el estado active por sí solo no demuestra que el enlace siga siendo canjeable.

Errores: 403 payouts_disabled / 403 recipient_not_allowed (el modo de pagos: en el modo allowlist, todos los destinatarios, tanto el usuario designado como los de una lista, deben estar autorizados), 400 unknown_asset, 400 invalid_amount, 404 user_not_found (el nombre de usuario designado no corresponde a nadie), 409 insufficient_funds y el par de spend_id.

deleteCheck

POST /pay/api/deleteCheck — ámbito checks. Un parámetro: check_id. Cancela un cheque activo y devuelve la parte sin canjear al saldo de tu app; devuelve true. Errores: 404 check_not_found, 409 check_not_active (canjeado por completo, expirado o eliminado).

getChecks

GET /pay/api/getChecks — ámbito read. Filtros: asset, check_ids (separados por comas), status (active / activated), más offset / count. Devuelve {"items": [check, …]}, los más recientes primero; los cheques eliminados nunca se devuelven.