tgpay cryptoAPI
crypto-payapitransferspayouts

Riferimento API: trasferimenti e buoni

6 min di letturaAggiornata il 9 ott 2026

I metodi per effettuare pagamenti. Un trasferimento invia fondi dal saldo della tua app al portafoglio di un utente Telegram oppure li tiene bloccati finché un nuovo destinatario non apre il bot. Un buono è un link da riscattare che finanzi in anticipo. Le convenzioni comuni (autenticazione, struttura delle risposte, importi, spend_id) sono descritte nella pagina Riferimento della Merchant API.

Tutti e tre i metodi che fanno uscire denaro rispettano la modalità dei pagamenti dell’app: un’app nuova paga chiunque fin dall’inizio; se il proprietario l’ha ristretta, si possono pagare solo i destinatari in elenco (403 recipient_not_allowed) oppure nessuno (403 payouts_disabled). La modalità la imposta il proprietario nella Mini App; dall’API non si può. A che cosa possono servire i pagamenti lo stabiliscono le condizioni della Merchant API.

transfer

POST /pay/api/transfer — ambito payouts, limite 30 al minuto. Un destinatario già registrato riceve subito il pagamento. Uno username sconosciuto crea un trasferimento pending: i fondi restano bloccati in garanzia finché il destinatario non apre il bot con quello username. I fondi non riscossi tornano sul saldo dell’app dopo la scadenza di 30 giorni (expires_at). Prima di registrare il rimborso in contabilità, verifica che lo stato sia returned. Inoltra tu l’invite_url: il bot non può scrivere a chi non l’ha mai avviato. Lo stato finale è completed oppure returned; attiva i webhook transfer_completed e transfer_returned per ricevere gli aggiornamenti oppure interroga periodicamente getTransfers. Indica esattamente uno tra user_id e username. Se li ometti entrambi o li invii insieme, la richiesta viene rifiutata perché i parametri non sono validi.

ParametroTipoObbligatorioDescrizione
user_idinterouno tra user_id e usernamel’ID Telegram del destinatario, che deve essere già un utente dell’app
usernamestringauno tra user_id e usernamelo username del destinatario, con o senza @; uno username sconosciuto crea un pagamento in attesa
assetstringasìil codice dell’asset
amountstringasìstringa decimale positiva; deve rispettare anche il minimo e il massimo per trasferimento della piattaforma (un controvalore stimato in dollari ai tassi del momento)
spend_idstringasìchiave di idempotenza, da 1 a 64 caratteri, unica per ogni pagamento
commentstringanofino a 1024 caratteri, mostrato a chi riceve
disable_send_notificationbooleanonotrue disattiva la notifica al destinatario per un pagamento immediato; quando un trasferimento in attesa viene accreditato, la notifica viene comunque inviata

Il risultato è l’oggetto trasferimento: 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 può essere null mentre si attende un nuovo destinatario; completed_at è null fino al completamento.

Errori: 403 payouts_disabled / 403 recipient_not_allowed (la modalità dei pagamenti), 404 user_not_found (ID sconosciuto o destinatario non disponibile), 400 invalid_recipient (username del destinatario non valido), 400 amount_too_small / 400 amount_too_big (fuori dai limiti per trasferimento), 409 insufficient_funds, 400 unknown_asset, 400 invalid_amount, e la coppia dello spend_id: 409 idempotency_conflict / 409 idempotency_in_progress.

transferBatch

POST /pay/api/transferBatch — ambito payouts, limite 10 al minuto. Un’estensione per i pagamenti di massa: fino a 100 trasferimenti in una chiamata sola.

Un parametro solo: items, un array in cui ogni elemento è un set completo di parametri di transfer (user_id o username, asset, amount, spend_id, più comment e disable_send_notification facoltativi). Gli spend_id devono essere unici dentro il lotto, altrimenti tutta la chiamata fallisce con 400 duplicate_spend_id prima di eseguire qualsiasi cosa. Anche una struttura non valida degli elementi, la modalità dei pagamenti o il limite giornaliero dell’app possono far rifiutare l’intera richiesta prima di qualsiasi pagamento. Una volta accettata, i risultati si trovano in result.items.

Gli elementi vengono elaborati in ordine e in modo indipendente l’uno dall’altro: un elemento che non riesce non annulla mai gli altri. La chiamata restituisce un HTTP 200 con ok: true anche quando alcuni elementi non sono riusciti, quindi controllali sempre uno per uno:

  • riuscito: {"ok": true, "spend_id": "…", "result": <oggetto trasferimento>}
  • non riuscito: {"ok": false, "spend_id": "…", "error": {"code": …, "name": "…"}} con gli stessi nomi d’errore di un transfer singolo.

Gli elementi di un lotto condividono lo spazio dell’idempotenza con i trasferimenti singoli: ritentare tutto il lotto — o rimandare un elemento come transfer singolo con lo stesso spend_id — ripete la risposta invece di pagare due volte.

getTransfers

GET /pay/api/getTransfers — ambito read. Filtri: asset, transfer_ids (separati da virgola), spend_id (corrispondenza esatta: ritrovi un pagamento con la tua stessa chiave), status (pending / completed / returned), più offset / count. Restituisce {"items": [trasferimento, …]}, dal più recente.

createCheck

POST /pay/api/createCheck — ambito checks, limite 60 al minuto. Per impostazione predefinita crea un buono a riscatto singolo dal saldo della tua app. Può riscattarlo chiunque abbia il link, oppure solo l’utente a cui lo riservi. L’estensione recipients crea un elenco nominativo con un importo separato per ogni destinatario. Il totale viene bloccato alla creazione (passa da available a onhold in getBalance). Valgono gli stessi limiti di importo e di pagamento giornaliero dei trasferimenti.

ParametroTipoObbligatorioDescrizione
assetstringasìil codice dell’asset
amountstringase non imposti recipientsstringa decimale positiva; con recipients, il totale viene calcolato dall’elenco
pin_to_user_idinteronopuò riscattarlo solo questo id Telegram
pin_to_usernamestringanopuò riscattarlo solo questo @username (la @ è facoltativa; ignorato quando c’è anche pin_to_user_id). Lo username deve appartenere a un utente esistente dell’app
spend_idstringanochiave di idempotenza (estensione): usane una
recipientsarraynoestensione: da 1 a 100 elementi, ciascuno con user_id o username e un amount come stringa decimale positiva. Non si può combinare con un utente riservato
passwordstringanoestensione: password richiesta per il riscatto, fino a 64 caratteri
expires_ininteronoestensione: durata in secondi; assente o 0 = nessuna scadenza

Il risultato è l’oggetto buono: check_id, hash, asset, amount, amount_minor, bot_check_url (il link t.me per riscattare), status (active / activated), pin_to_user_id, created_at, activated_at, expires_at e recipients (null per un buono ordinario; altrimenti ogni voce contiene user_id, username, amount, amount_minor, claimed_at). Ogni riscatto genera il webhook facoltativo check_activated; un riscatto da un elenco nominativo include anche activated_slot. Alla scadenza viene restituito il residuo non riscosso; per un elenco nominativo può essere inviato l’evento check_expired.

La risposta attuale assegna status: "active" a ogni buono non riscattato completamente, anche se è scaduto. Controlla anche expires_at: lo stato active, da solo, non dimostra che il link sia ancora riscattabile.

Errori: 403 payouts_disabled / 403 recipient_not_allowed (la modalità dei pagamenti: in modalità allowlist ogni destinatario riservato o nominativo deve essere nell’elenco), 400 unknown_asset, 400 invalid_amount, 404 user_not_found (lo username riservato non corrisponde a nessuno), 409 insufficient_funds, e la coppia dello spend_id.

deleteCheck

POST /pay/api/deleteCheck — ambito checks. Un parametro solo: check_id. Annulla un buono attivo e restituisce il residuo non riscosso al saldo della tua app; restituisce true. Errori: 404 check_not_found, 409 check_not_active (riscattato completamente, scaduto o eliminato).

getChecks

GET /pay/api/getChecks — ambito read. Filtri: asset, check_ids (separati da virgola), status (active / activated), più offset / count. Restituisce {"items": [buono, …]}, dal più recente; i buoni eliminati non compaiono mai.