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 (au plus une fois par heure et par application) 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é. Un corps avec tout autreContent-Type(text/plain, ou aucun) est ignoré : seuls les paramètres d’URL sont lus. Les paramètres de type tableau (transferBatch.items,createCheck.recipients) ne fonctionnent que dans un corps JSON. - 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, y compris dans les requêtes :{"amount": 10.5}renvoie400 invalid_request; envoyez plutôt{"amount": "10.5"}. Il en va de même pour tous les autres paramètres texte (asset,spend_id,comment, …). - Un montant comportant plus de décimales que l’actif n’en admet est arrondi
à la précision de l’actif (au plus proche, avec arrondi supérieur en cas d’égalité) au lieu
d’être refusé ; un montant qui devient nul après arrondi renvoie
400 invalid_amount. - Les réponses portent aussi
amount_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). transfer et les
éléments de transferBatch partagent le même espace de clés. 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. Une requête qui a
échoué avec une erreur 4xx ne consomme pas sa clé : la réessayer avec la même
clé l’exécute de nouveau.
Les limites de débit
Les limites s’appliquent par application et sont partagées entre tous ses
tokens, avec un compteur distinct pour chaque méthode. 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 |
Deux autres limites protègent contre les tentatives de deviner des tokens ou des destinataires :
- Authentification échouée : après 30 requêtes avec un token absent ou
invalide depuis une même adresse IP en une minute, toutes les requêtes de
cette adresse reçoivent
429 rate_limitedjusqu’à la fin de la minute — même avec un token valide. Ne laissez pas une tâche mal configurée partager l’adresse IP de votre trafic de production. - Destinataires inconnus : après 10 recherches d’un
user_idou d’un@usernameinexistant dans une application en une minute (transfer, éléments detransferBatch,createCheckavecpin_to_username), toute recherche de destinataire dans cette application renvoie429 rate_limitedjusqu’à la fin de la 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 (URL HTTPS publique de 256 caractères maximum ; une chaîne vide la supprime) et webhook_events (tableau ou liste de noms d’événements supplémentaires pris en charge, séparés par des virgules). Une liste vide ne conserve que invoice_paid. Renvoie les mêmes champs d’application que getMe.
Erreurs : 400 invalid_request (name hors de 1–64 caractères, ou webhook_url qui n’est pas une adresse HTTPS publique ou dépasse 256 caractères), 400 invalid_name (nom ressemblant à un lien ou à un @username), 400 app_name_reserved (nom utilisant celui de TgPay Crypto) et 400 invalid_webhook_events (nom d’événement inconnu ; invoice_paid est aussi rejeté dans cette liste, car il ne nécessite aucune activation).
getBalance
GET /pay/api/getBalance — aucun paramètre. Renvoie un tableau avec une
ligne par actif pris en charge, même à zéro (un actif désactivé n’apparaît
que tant que l’application en détient encore) : 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),
is_valid, is_crypto et is_fiat. 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 couvre 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. volume et conversion sont des nombres JSON, pas des chaînes.
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.