Référence de l’API marchand
Les conventions communes à toutes les méthodes, plus les méthodes de catalogue en lecture seule. Les pages méthode par méthode : factures et remboursements, transferts et chèques, abonnements, webhooks.
L’API suit les conventions de Crypto Bot pour les méthodes documentées ici. Changez l’URL de base et le token, puis testez sur le testnet les méthodes utilisées par votre intégration. Nos ajouts sont signalés par extension ci-dessous.
Une spécification OpenAPI 3.1 exploitable par les outils est également disponible : crypto-pay-openapi.yaml · crypto-pay-openapi.json. Donnez-la à vos générateurs de code, clients d’API ou outils d’IA, mais consultez aussi les pages des méthodes : le schéma peut ne pas encore couvrir les extensions les plus récentes.
URL de base et authentification
Toutes les méthodes sont accessibles à
https://app.tgpaycrypto.com/pay/api/<methodName>.
Sur le testnet, la base est
https://testnet.tgpaycrypto.com/pay/api — applications et tokens
distincts, cryptos de test sans valeur réelle.
Authentifiez chaque requête avec le token dans l’en-tête
TgPayCrypto-API-Token (TgCryptoPay-API-Token, le nom d’avant le
2026-09-07, et Crypto-Pay-API-Token sont acceptés comme alias de
compatibilité ; si plusieurs sont envoyés, l’en-tête principal prévaut). Un token
absent, invalide ou révoqué — ainsi qu’un token restreint expiré, le token d’une application supprimée ou celui d’un propriétaire bloqué —
renvoie 401 unauthorized.
Le token a la forme <app_id>:<secret> et n’est affiché qu’une fois, à la
création ou au renouvellement ; le serveur n’en stocke que l’empreinte.
Voir Démarrer en tant que développeur.
Tokens et permissions
Deux sortes d’identifiants s’authentifient de façon identique :
- Le token principal — accès complet à toutes les méthodes, et la seule clé qui signe les webhooks.
- Les tokens restreints (extension) — jusqu’à 10 tokens non révoqués par application, y compris les tokens expirés, créés dans Plus → API marchand : ouvrez l’application, puis Accès et tokens et Tokens restreints. Chacun a un libellé et un sous-ensemble de permissions. En révoquer un est instantané et ne touche pas les autres ; renouveler le token principal ne les touche pas non plus. Un token peut aussi avoir une date d’expiration après laquelle il ne permet plus de s’authentifier.
| Permission | Méthodes qu’elle débloque |
|---|---|
| (tout token valide) | getMe, getCurrencies, getExchangeRates |
read | getBalance, getStats, getInvoices, getChecks, getTransfers, getSubscriptionPlans, getSubscriptions |
invoices | createInvoice, deleteInvoice |
refunds | refundInvoice |
payouts | transfer, transferBatch |
checks | createCheck, deleteCheck |
subscriptions | createSubscriptionPlan, archiveSubscriptionPlan, cancelSubscription |
webhooks | updateApp |
Les permissions s’additionnent et sont indépendantes — invoices
n’implique pas read, donc un serveur qui ne fait que créer des factures
peut utiliser un token sans accès aux soldes ni à l’historique des paiements. Appeler une
méthode que le token ne couvre pas renvoie 403 scope_required. getMe
rapporte les scopes du token courant (null pour le token principal) et
son token_name, pour que vous puissiez identifier le token utilisé et ses permissions.
Mode de paiement sortant
Une permission définit les méthodes qu’un token peut appeler ; le
mode de paiement sortant de l’application définit qui ses tokens peuvent payer, y compris le token principal. Par défaut, une nouvelle application peut payer tout utilisateur. Le propriétaire peut restreindre les destinataires en ouvrant son application dans Plus → API marchand, puis Paramètres des paiements → Paiements via l’API. Comme le plafond quotidien, cette restriction limite les actions possibles en cas de fuite du token.
Pour l’assouplir, il doit confirmer avec son PIN ou la biométrie. L’API permet uniquement de consulter ce mode (getMe →
payout_mode).
payout_mode | Ce que transfer, transferBatch et createCheck peuvent faire |
|---|---|
any | payer n’importe quel utilisateur, mettre en attente un paiement vers un @username inconnu, créer des chèques au porteur — le comportement par défaut, et celui de Crypto Bot |
allowlist | payer uniquement les utilisateurs Telegram autorisés. Chaque destinataire désigné ou membre d’une liste nominative de chèque doit être autorisé. Les autres destinataires, les @username inconnus et les chèques au porteur renvoient 403 recipient_not_allowed |
off | rien — chaque appel de paiement sortant renvoie 403 payouts_disabled ; les factures, les abonnements, les remboursements et les webhooks fonctionnent normalement |
Si un paiement sortant est refusé, le propriétaire en est averti dans Telegram et peut changer le mode. Le plafond quotidien de paiements s’applique en plus du mode. Les usages autorisés des paiements sont définis dans les conditions d’utilisation de l’API marchand.
Requêtes et réponses
- Les méthodes de lecture sont en
GETavec des paramètres d’URL. Les méthodes qui déplacent des fonds sont uniquement enPOST— paramètres en corps JSON, en form-urlencoded ou en paramètres d’URL (le corps l’emporte en cas de conflit) ;multipart/form-dataest refusé. - Les réponses produites par les méthodes de l’API utilisent une enveloppe JSON : succès
{"ok": true, "result": …}, erreur{"ok": false, "error": {"code": <statut HTTP>, "name": "<error_name>"}}. Traitez les erreurs selonerror.name: c’est leur identifiant stable, exploitable par votre code. - Une valeur de paramètre d’URL invalide sur une méthode GET (par exemple
offset=abc) peut être rejetée avant l’exécution de la méthode. Vérifiez le statut HTTP : toutes les erreurs ne suivent pas forcément l’enveloppe ci-dessus. Respectez les types attendus pour les paramètres d’URL.
Les montants
- Les montants en crypto sont des chaînes décimales exprimées dans l’unité de l’actif (
"10.5") — jamais des nombres JSON. Les réponses portent aussiamount_minor(extension) : la valeur entière en unités mineures sous forme de chaîne, car les grands entiers exprimés en wei peuvent dépasser la précision entière exacte d’unNumberJavaScript. - Les
decimalspar actif viennent degetCurrencies— pilotez vos calculs de montants à partir de là plutôt que de les coder en dur. - Les montants en monnaie fiduciaire ont au plus 2 décimales.
- Les taux sont des chaînes à virgule fixe, jamais des nombres.
La pagination
Les méthodes de liste (getInvoices, getChecks, getTransfers,
getSubscriptions) prennent offset (défaut 0) et count (défaut 100,
maximum 1000 ; getSubscriptions maximum 500) et renvoient
{"items": […]}, les plus récents d’abord. Les filtres d’identifiants
(invoice_ids, check_ids, transfer_ids) sont des listes d’entiers
séparées par des virgules. Les horodatages sont partout des chaînes
ISO 8601.
L’idempotence : spend_id
Les méthodes qui déplacent de l’argent prennent une clé spend_id
générée par l’appelant (1 à 64 caractères) : requise sur transfer et sur
chaque élément de transferBatch, facultative sur createCheck et
refundInvoice (extension — utilisez-la quand même). Réessayer avec la
même clé et les mêmes paramètres renvoie le résultat d’origine sans déplacer les fonds deux fois : vous pouvez donc réessayer une requête dont le délai de réponse a été dépassé. La même clé avec des paramètres différents
renvoie 409 idempotency_conflict ; une nouvelle tentative pendant que la requête d’origine
s’exécute encore renvoie 409 idempotency_in_progress.
Les limites de débit
Par application, partagées entre tous ses tokens ; un dépassement renvoie
429 rate_limited :
| Méthode | Limite |
|---|---|
createInvoice, createCheck | 60 par minute |
refundInvoice | 30 par minute |
transfer | 30 par minute |
transferBatch | 10 par minute |
updateApp | 10 par minute |
createSubscriptionPlan | 20 par minute |
D’autres limites de requêtes peuvent s’appliquer. En cas de 429 rate_limited, augmentez le délai avant de réessayer. Pendant une
maintenance de la plateforme, les méthodes d’écriture renvoient
503 maintenance tandis que les lectures continuent de fonctionner.
Méthodes de catalogue et de compte
getMe
GET /pay/api/getMe — aucun paramètre. Renvoie l’identité de
l’application : app_id, name, payment_processing_bot_username,
webhook_url, webhook_events (les types de webhook étendus auxquels
l’application s’est abonnée), les champs d’introspection du token scopes /
token_name décrits plus haut, et payout_mode (off / allowlist /
any), daily_payout_max_usd_cents (0 = aucune limite définie par le propriétaire) et daily_payout_spent_usd_cents (montant utilisé sur les 24 heures glissantes).
updateApp
POST /pay/api/updateApp — permission webhooks. Paramètres facultatifs : name (1 à 64 caractères), webhook_url (une URL HTTPS publique ; une chaîne vide la supprime) et webhook_events (tableau ou liste séparée par des virgules des noms d’événements supplémentaires pris en charge). Une liste vide ne conserve que invoice_paid. Renvoie les mêmes champs d’application que getMe.
getBalance
GET /pay/api/getBalance — aucun paramètre. Renvoie un tableau avec une
ligne par actif pris en charge, même à zéro : currency_code, available
(solde disponible), onhold (fonds des chèques non récupérés et paiements vers des @username en attente) et
amount_minor.
getCurrencies
GET /pay/api/getCurrencies — aucun paramètre. La liste qui fait foi de
ce que l’API prend en charge : les lignes crypto (is_blockchain: true)
et les monnaies fiduciaires dans lesquelles les factures peuvent être
libellées (is_fiat: true). Chaque ligne porte code, name, decimals
et l’indicateur is_stablecoin.
getExchangeRates
GET /pay/api/getExchangeRates — aucun paramètre. Les cotations
crypto-vers-fiat : source, target, rate (une chaîne à virgule fixe)
et is_valid. Ces taux sont indicatifs. La valeur is_valid: true ne garantit pas qu’une cotation soit récente. Si les taux ne peuvent pas être obtenus, le résultat peut être un tableau vide. Pour rapprocher un paiement réel dans votre comptabilité, utilisez les montants et les taux enregistrés sur la facture.
getStats
GET /pay/api/getStats — start_at / end_at facultatifs (ISO 8601 ; la
fenêtre par défaut est les dernières 24 heures). Renvoie volume (valeur
en dollars des factures payées pendant cette période, estimée aux taux actuels ; les actifs sans cours disponible comptent pour zéro), conversion
(payées/créées, en pourcentage), unique_users_count,
created_invoice_count, paid_invoice_count, et les bornes effectives de
la fenêtre. Une date illisible renvoie 400 invalid_date.
Erreurs que toute méthode peut renvoyer
| HTTP | error.name | Quand |
|---|---|---|
| 401 | unauthorized | token absent, invalide ou révoqué |
| 403 | scope_required | le token n’a pas la permission de la méthode |
| 403 | payouts_disabled | le mode de paiement sortant de l’application est off (méthodes de paiement sortant uniquement) |
| 403 | recipient_not_allowed | le destinataire n’est pas dans la liste de destinataires de l’application (méthodes de paiement sortant uniquement) |
| 400 | invalid_request | paramètres illisibles ou invalides (POST) |
| 403 | daily_cap_exceeded | la limite quotidienne de paiements sortants de l’application serait dépassée |
| 403 | verification_required | les opérations sortantes du propriétaire sont restreintes ; concerne les transferts, les chèques et les remboursements |
| 503 | merchant_payouts_paused | les débits du solde de l’application sont temporairement suspendus |
| 429 | rate_limited | limite de débit dépassée |
| 503 | maintenance | maintenance de la plateforme (méthodes d’écriture) |
| 500 | internal_error | erreur serveur inattendue |
Les erreurs propres à chaque méthode sont listées sur sa page.
Erreurs sans l’enveloppe JSON
Une erreur en texte brut ou en HTML ne permet pas, à elle seule, de savoir quelle couche l’a renvoyée. Vérifiez le statut HTTP, le corps et les en-têtes de la réponse.
Si Cloudflare renvoie error code: 1010, le client a été rejeté d’après la signature de son navigateur, avant que la requête n’atteigne l’API. Les permissions du jeton ne sont pas la cause de cette erreur Cloudflare. Un User-Agent absent ou non standard peut déclencher la protection réseau. Essayez un en-tête User-Agent qui identifie votre client, par exemple MyShop/1.0, puis réessayez la requête ; cela ne garantit pas la résolution du problème. Si l’erreur persiste, envoyez au support le statut HTTP, le corps et les en-têtes de la réponse, après avoir retiré les jetons et les cookies.
Cet article vous a-t-il été utile ?
Merci pour votre retour.