tgpay cryptoAPI
crypto-payapireferencetokens

Riferimento della Merchant API

9 min di letturaAggiornata il 22 ott 2026

Le convenzioni comuni a tutti i metodi, più i metodi di sola lettura del catalogo. Le pagine metodo per metodo: fatture e rimborsi, trasferimenti e buoni, abbonamenti, webhook.

Per i metodi documentati qui, l’API segue le convenzioni di Crypto Bot. Cambia l’URL di base e il token, poi prova sulla testnet i metodi usati dall’integrazione. Le funzionalità aggiuntive sono indicate come estensione.

È disponibile anche una specifica OpenAPI 3.1 utilizzabile dagli strumenti di sviluppo: crypto-pay-openapi.yaml · crypto-pay-openapi.json. Passala a un generatore di codice, a un client API o ai tuoi strumenti di AI, ma consulta anche le pagine dei singoli metodi: lo schema potrebbe non includere ancora le estensioni più recenti.

Base URL e autenticazione

Tutti i metodi stanno su https://app.tgpaycrypto.com/pay/api/<methodName>. Sulla testnet la base è https://testnet.tgpaycrypto.com/pay/api: app e token separati e fondi di prova senza valore reale.

Autentica ogni richiesta con il token nell’intestazione TgPayCrypto-API-Token (TgCryptoPay-API-Token, il nome in uso prima del 2026-09-07, e Crypto-Pay-API-Token sono accettate come alias di compatibilità; se ne mandi più di una, vince quella ufficiale). Un token mancante, non valido o revocato, un token limitato scaduto, il token di un’app eliminata o quello il cui proprietario è bloccato restituiscono 401 unauthorized.

Il token ha la forma <app_id>:<secret> e si vede una volta sola, alla creazione o alla rigenerazione; il server ne conserva solo l’hash. Vedi iniziare da sviluppatore.

Token e ambiti

Ci sono due tipi di credenziali, che si autenticano allo stesso modo:

  • Il token principale — accesso completo a ogni metodo, ed è l’unica chiave che firma i webhook.
  • I token con permessi limitati (estensione) — fino a 10 non revocati per app, compresi quelli scaduti. Apri Altro → Merchant API, scegli l’app e poi Accesso e token. Creali sotto Token con permessi limitati, ciascuno con un’etichetta e un sottoinsieme di ambiti. Revocarne uno è immediato e non tocca gli altri; nemmeno rigenerare il token principale li tocca. Un token può anche avere una scadenza: dopo quel termine non consente più di autenticarsi.
AmbitoMetodi che sblocca
(qualsiasi token valido)getMe, getCurrencies, getExchangeRates
readgetBalance, getStats, getInvoices, getChecks, getTransfers, getSubscriptionPlans, getSubscriptions
invoicescreateInvoice, deleteInvoice
refundsrefundInvoice
payoutstransfer, transferBatch
checkscreateCheck, deleteCheck
subscriptionscreateSubscriptionPlan, archiveSubscriptionPlan, cancelSubscription
webhooksupdateApp

Gli ambiti si sommano e sono indipendenti: invoices non implica read, quindi un server che si limita a creare fatture può avere un token senza accesso ai saldi o allo storico dei pagamenti. Chiamare un metodo che il token non copre restituisce 403 scope_required. getMe riporta gli scopes del token in uso (null per il token principale) e il suo token_name, così sai sempre che cosa hai in mano.

Modalità dei pagamenti

Un ambito dice quali metodi può chiamare un token; la modalità dei pagamenti dell’app dice a chi può pagare qualsiasi suo token, compreso quello principale. Un’app nuova paga chiunque fin dal primo minuto; il proprietario può restringerla aprendo l’app in Altro → Merchant API, poi Impostazioni dei pagamenti → Pagamenti tramite API. Come il limite giornaliero, limita le conseguenze della perdita del token. Per consentire pagamenti a più destinatari servono la biometria o il PIN; l’API può solo leggerla (getMe → payout_mode).

payout_modeChe cosa possono fare transfer, transferBatch e createCheck
anypagare qualsiasi utente, lasciare in attesa un pagamento per uno @username sconosciuto, creare buoni al portatore: è l’impostazione predefinita, la stessa di Crypto Bot
allowlistpagare solo gli utenti Telegram in elenco. Ogni destinatario riservato o nominativo di un buono deve essere in elenco. Altri destinatari, @username sconosciuti e buoni al portatore restituiscono 403 recipient_not_allowed
offniente: ogni chiamata di pagamento restituisce 403 payouts_disabled; fatture, abbonamenti, rimborsi e webhook funzionano come sempre

Se un pagamento viene rifiutato, il proprietario riceve una notifica su Telegram e può cambiare la modalità. Il limite giornaliero dei pagamenti si applica in aggiunta alla modalità. Per che cosa puoi pagare lo stabiliscono le condizioni della Merchant API.

Richieste e risposte

  • I metodi di lettura sono GET, con i parametri nella query. I metodi che muovono denaro sono solo POST: parametri come corpo JSON, come form-urlencoded o nella query (in caso di conflitto vince il corpo); multipart/form-data viene rifiutato.
  • Le risposte dei metodi API usano un formato JSON comune: in caso di successo {"ok": true, "result": …}, in caso di errore {"ok": false, "error": {"code": <stato HTTP>, "name": "<nome_errore>"}}. Gestisci l’errore in base a error.name: è una stringa stabile, pensata per essere letta dal codice.
  • Un valore di query del tipo sbagliato su un metodo GET (per esempio offset=abc) può essere rifiutato prima dell’esecuzione del metodo API. Controlla lo stato HTTP: non tutte le risposte di errore seguono il formato sopra. Invia i valori della query nei tipi previsti.

Gli importi

  • Gli importi in cripto sono stringhe decimali espresse nell’unità dell’asset ("10.5"), mai numeri JSON. Le risposte portano anche amount_minor (estensione): il valore intero nelle unità minori, come stringa, perché gli interi su scala wei possono superare la precisione intera esatta di un Number di JavaScript.
  • I decimals di ogni asset arrivano da getCurrencies: fai i tuoi conti a partire da lì, invece di scriverli fissi nel codice.
  • Gli importi in valuta fiat hanno al massimo 2 decimali.
  • I tassi sono stringhe a virgola fissa, mai numeri.

La paginazione

I metodi che restituiscono elenchi (getInvoices, getChecks, getTransfers, getSubscriptions) accettano offset (predefinito 0) e count (predefinito 100, al massimo 1000; per getSubscriptions al massimo 500) e restituiscono {"items": […]}, dal più recente. I filtri per ID (invoice_ids, check_ids, transfer_ids) sono elenchi di interi separati da virgola. Le date e gli orari, ovunque, sono stringhe ISO 8601.

Idempotenza: spend_id

I metodi che muovono denaro accettano una chiave spend_id generata da chi chiama (da 1 a 64 caratteri): obbligatoria su transfer e su ogni elemento di transferBatch, facoltativa su createCheck e refundInvoice (estensione: usala lo stesso). Ritentare con la stessa chiave e gli stessi parametri ripete il risultato originale invece di muovere denaro due volte, quindi una richiesta andata in timeout si può sempre ritentare senza rischi. La stessa chiave con parametri diversi restituisce 409 idempotency_conflict; un tentativo mentre l’originale è ancora in esecuzione restituisce 409 idempotency_in_progress.

I limiti di frequenza

Sono per app e condivisi tra tutti i suoi token; superarli restituisce 429 rate_limited:

MetodoLimite
createInvoice, createCheck60 al minuto
refundInvoice30 al minuto
transfer30 al minuto
transferBatch10 al minuto
updateApp10 al minuto
createSubscriptionPlan20 al minuto

Possono applicarsi altri limiti alle richieste. In caso di 429 rate_limited, aumenta l’attesa prima di riprovare. Durante la manutenzione della piattaforma i metodi di scrittura restituiscono 503 maintenance, mentre le letture continuano a funzionare.

Metodi di catalogo e di account

getMe

GET /pay/api/getMe — nessun parametro. Restituisce l’identità dell’app: app_id, name, payment_processing_bot_username, webhook_url, webhook_events (i tipi di webhook estesi che l’app ha attivato), i campi di introspezione del token scopes / token_name descritti sopra, e payout_mode (off / allowlist / any), daily_payout_max_usd_cents (0 = nessun limite impostato dal proprietario) e daily_payout_spent_usd_cents (spesa nelle ultime 24 ore).

updateApp

POST /pay/api/updateApp — ambito webhooks. Parametri facoltativi: name (1–64 caratteri), webhook_url (un URL HTTPS pubblico; una stringa vuota lo rimuove) e webhook_events (un array o un elenco separato da virgole dei nomi degli eventi aggiuntivi supportati). Un elenco vuoto lascia solo invoice_paid. Restituisce gli stessi campi dell’app di getMe.

getBalance

GET /pay/api/getBalance — nessun parametro. Restituisce un elenco con una riga per ogni asset supportato, anche a zero: currency_code, available (il saldo spendibile), onhold (i fondi nei buoni non riscossi e nei pagamenti in attesa a @username) e amount_minor.

getCurrencies

GET /pay/api/getCurrencies — nessun parametro. L’elenco che fa fede su quello che l’API supporta: le righe delle cripto (is_blockchain: true) e le valute fiat in cui si possono prezzare le fatture (is_fiat: true). Ogni riga porta code, name, decimals e il flag is_stablecoin.

getExchangeRates

GET /pay/api/getExchangeRates — nessun parametro. Le quotazioni da cripto a valuta fiat: source, target, rate (una stringa a virgola fissa) e is_valid. Considera i tassi indicativi: is_valid: true non garantisce che una quotazione sia aggiornata. Se non è possibile ottenere i tassi, il risultato può essere un array vuoto. Per riconciliare un pagamento effettivo, usa gli importi e i tassi registrati nella fattura.

getStats

GET /pay/api/getStats — start_at / end_at facoltativi (ISO 8601; per impostazione predefinita la finestra è le ultime 24 ore). Restituisce volume (il valore in dollari delle fatture pagate nella finestra, stimato ai tassi attuali; gli asset senza prezzo contribuiscono per zero), conversion (pagate su create, in percentuale), unique_users_count, created_invoice_count, paid_invoice_count e gli estremi effettivi della finestra. Una data illeggibile restituisce 400 invalid_date.

Errori che può restituire qualsiasi metodo

HTTPerror.nameQuando
401unauthorizedtoken mancante, non valido o revocato
403scope_requiredal token manca l’ambito del metodo
403payouts_disabledla modalità dei pagamenti dell’app è off (solo nei metodi che fanno uscire denaro)
403recipient_not_allowedil destinatario non è nell’elenco dei destinatari dell’app (solo nei metodi che fanno uscire denaro)
400invalid_requestparametri illeggibili o non validi (POST)
403daily_cap_exceededverrebbe superato il limite giornaliero dei pagamenti dell’app
403verification_requiredle operazioni in uscita del proprietario sono limitate; riguarda trasferimenti, buoni e rimborsi
503merchant_payouts_pausedgli addebiti sul saldo dell’app sono temporaneamente sospesi
429rate_limitedlimite di frequenza superato
503maintenancemanutenzione della piattaforma (metodi di scrittura)
500internal_errorerrore imprevisto del server

Gli errori specifici di ogni metodo sono elencati nella sua pagina.

Errori senza la struttura JSON

Una risposta di errore in testo semplice o HTML non basta a identificare il livello da cui proviene. Controlla lo stato HTTP, il corpo e gli header della risposta.

Se Cloudflare restituisce error code: 1010, ha rifiutato il client in base alla firma del browser prima che la richiesta raggiungesse l’API. Gli ambiti del token non sono la causa di questo errore di Cloudflare. Un User-Agent mancante o non standard può attivare la protezione di rete. Prova a inviare un header User-Agent che identifichi il tuo client, come MyShop/1.0, e ripeti la richiesta; non è una soluzione garantita. Se l’errore persiste, invia all’assistenza lo stato HTTP, il corpo e gli header della risposta, dopo aver rimosso token e cookie.