Händler-API-Referenz
Hier findest du die gemeinsamen Konventionen aller Methoden und die lesenden Katalogmethoden. Die einzelnen Methoden sind auf diesen Seiten beschrieben: Rechnungen und Rückerstattungen, Überweisungen und Schecks, Abos, Webhooks.
Die API folgt bei den hier dokumentierten Methoden den Konventionen von Crypto Bot. Ändere die Basis-URL und den Token und teste dann die Methoden, die deine Integration nutzt, im Testnet. Unsere Ergänzungen sind unten als Erweiterung markiert.
Eine maschinenlesbare OpenAPI-3.1-Spezifikation ist ebenfalls verfügbar: crypto-pay-openapi.yaml · crypto-pay-openapi.json. Du kannst sie mit Codegeneratoren, API-Clients oder KI-Werkzeugen verwenden. Prüfe zusätzlich die jeweiligen Methodenseiten: Neuere Erweiterungen können im Schema noch fehlen.
Basis-URL und Authentifizierung
Alle Methoden liegen unter https://app.tgpaycrypto.com/pay/api/<methodName>.
Im Testnet ist die Basis
https://testnet.tgpaycrypto.com/pay/api – eigene Apps und Token, Test-Coins
ohne Wert.
Authentifiziere jede Anfrage mit dem Token im Header
TgPayCrypto-API-Token (TgCryptoPay-API-Token, der Name vor
2026-09-07, und Crypto-Pay-API-Token werden aus Kompatibilitätsgründen
als Alias akzeptiert; werden mehrere gesendet, gewinnt der kanonische).
Ein fehlender, ungültiger oder widerrufener Token liefert 401 unauthorized.
Das gilt auch für einen abgelaufenen eingeschränkten Token, den Token einer
gelöschten App und einen Token, dessen Inhaber gesperrt ist.
Der Token hat die Form <app_id>:<secret> und wird einmal angezeigt, bei der
Erstellung oder Erneuerung; der Server speichert nur seinen Hash. Siehe
Erste Schritte als Entwickler.
Token und Berechtigungen
Zwei Arten von Zugangsdaten authentifizieren sich identisch:
- Der Haupt-Token – voller Zugriff auf jede Methode und der einzige Schlüssel, der Webhooks signiert.
- Eingeschränkte Token (Erweiterung) – bis zu 10 nicht widerrufene Token pro App, einschließlich abgelaufener Token. Öffne Mehr → Händler-API, wähle die App und dann Zugriff und Tokens. Unter Eingeschränkte Token erstellst du sie jeweils mit einer Bezeichnung und den gewünschten Berechtigungen. Einen davon zu widerrufen wirkt sofort und berührt die anderen nicht; den Haupt-Token zu erneuern berührt sie ebenfalls nicht. Token können auch ein Ablaufdatum haben; danach lassen sie sich nicht mehr zur Authentifizierung verwenden.
| Berechtigung | Methoden, die sie freischaltet |
|---|---|
| (jeder gültige Token) | 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 |
Berechtigungen sind additiv und unabhängig – invoices schließt read nicht
ein. Ein Server, der nur Rechnungen erstellt, kann also einen Token ohne Zugriff
auf Guthaben und Zahlungsverlauf verwenden. Eine Methode aufzurufen, die der Token nicht abdeckt, liefert
403 scope_required. getMe meldet die scopes des aktuellen Tokens (null
beim Haupt-Token) und token_name, du kannst also jederzeit prüfen, was du in
der Hand hast.
Auszahlungsmodus
Eine Berechtigung sagt, welche Methoden ein Token aufrufen darf; der
Auszahlungsmodus der App sagt, an wen jeder ihrer Token – den
Haupt-Token eingeschlossen – auszahlen darf. Eine neue App darf sofort jeden
bezahlen. Um den Empfängerkreis einzuschränken, öffnet der Inhaber die App unter
Mehr → Händler-API und dann Auszahlungseinstellungen → Auszahlungen über die API.
Wie das Tageslimit begrenzt diese Einstellung, was mit einem entwendeten Token möglich ist.
Wieder lockern lässt sich die Einschränkung nur mit PIN oder Biometrie; die
API kann den Modus nur lesen (getMe → payout_mode).
payout_mode | Was transfer, transferBatch und createCheck dürfen |
|---|---|
any | an jeden Nutzer zahlen, eine Auszahlung für einen unbekannten @username hinterlegen, Schecks ohne festgelegten Nutzer erstellen – der Standard und das Verhalten von Crypto Bot |
allowlist | nur an Telegram-Nutzer auf der Empfängerliste der App zahlen. Jeder festgelegte oder namentlich angegebene Scheckempfänger muss auf dieser Liste stehen. Andere Empfänger, unbekannte @usernames und Schecks ohne festgelegte Empfänger liefern 403 recipient_not_allowed |
off | nichts – jeder Auszahlungsaufruf liefert 403 payouts_disabled; Rechnungen, Abos, Rückerstattungen und Webhooks funktionieren wie gewohnt |
Wird eine Auszahlung abgelehnt, erhält der Inhaber eine Nachricht in Telegram (höchstens einmal pro Stunde und App) und kann den Modus ändern. Das Tageslimit für Auszahlungen gilt zusätzlich zum Modus. Wofür du zahlen darfst, legen die Bedingungen der Händler-API fest.
Anfragen und Antworten
- Lesende Methoden sind
GETmit Parametern im Query-String. Geldbewegende Methoden sind ausschließlichPOST– Parameter als JSON-Body, form-urlencoded oder als Query-Parameter (bei einem Konflikt gewinnt der Body);multipart/form-datawird abgelehnt. Ein Body mit einem anderenContent-Type(text/plainoder ganz ohne) wird ignoriert, es zählen dann nur die Query-Parameter. Array-Parameter (transferBatch.items,createCheck.recipients) funktionieren nur im JSON-Body. - Antworten aus den API-Handlern verwenden diese JSON-Struktur:
Erfolg
{"ok": true, "result": …}, Fehler{"ok": false, "error": {"code": <HTTP status>, "name": "<error_name>"}}. Verzweige auferror.name– das ist der stabile, maschinenlesbare String. - Ein Query-Wert mit falschem Typ bei einer GET-Methode (z. B.
offset=abc) kann bereits vor dem API-Handler abgelehnt werden. Prüfe den HTTP-Status und gehe nicht davon aus, dass jede Fehlerantwort die obige Struktur verwendet. Sende Query-Werte mit den erwarteten Datentypen.
Beträge
- Krypto-Beträge sind Dezimalstrings in Einheiten des jeweiligen Assets (
"10.5") – nie JSON-Zahlen, auch nicht in Anfragen:{"amount": 10.5}liefert400 invalid_request, sende stattdessen{"amount": "10.5"}. Dasselbe gilt für jeden anderen String-Parameter (asset,spend_id,comment, …). - Hat ein Betrag mehr Nachkommastellen als das Asset, wird er kaufmännisch
auf dessen Genauigkeit gerundet statt abgelehnt; ein Betrag, der dabei auf
null fällt, liefert
400 invalid_amount. - Antworten führen außerdem
amount_minor(Erweiterung): den ganzzahligen Wert in kleinsten Einheiten als String, weil Ganzzahlen in Wei-Größenordnung mit einer JavaScript-Numbernicht mehr exakt darstellbar sind. - Die
decimalspro Asset kommen ausgetCurrencies– steuere deine Betragsrechnung damit, statt sie fest einzuprogrammieren. - Fiat-Beträge haben höchstens 2 Nachkommastellen.
- Kurse sind Festkomma-Strings, nie Zahlen.
Paginierung
Listenmethoden (getInvoices, getChecks, getTransfers,
getSubscriptions) nehmen offset (Standard 0) und count (Standard 100, max.
1000; getSubscriptions max. 500) und liefern {"items": […]}, neueste
zuerst. Die ID-Filter (invoice_ids, check_ids, transfer_ids) sind
kommagetrennte Listen von Ganzzahlen. Zeitstempel sind überall
ISO-8601-Strings.
Idempotenz: spend_id
Methoden, die Geld bewegen, nehmen einen vom Aufrufer erzeugten Schlüssel
spend_id (1–64 Zeichen): Pflicht bei transfer und bei jedem Element von
transferBatch, optional bei createCheck und refundInvoice (Erweiterung –
nutze ihn trotzdem). transfer und die Elemente von transferBatch teilen
sich einen Schlüsselraum. Eine Wiederholung mit demselben Schlüssel und denselben
Parametern gibt das ursprüngliche Ergebnis wieder, statt zweimal Guthaben zu
bewegen; eine Anfrage nach einem Timeout kannst du also immer gefahrlos
wiederholen. Derselbe Schlüssel mit anderen Parametern liefert
409 idempotency_conflict; eine Wiederholung, während die ursprüngliche noch
läuft, liefert 409 idempotency_in_progress. Eine Anfrage, die mit einem
4xx-Fehler gescheitert ist, verbraucht ihren Schlüssel nicht: Wiederholst du
sie mit demselben Schlüssel, wird sie erneut ausgeführt.
Anfragelimits
Die Limits gelten pro App und für alle ihre Token gemeinsam, mit einem eigenen
Zähler für jede Methode. Wer ein Limit überschreitet, erhält
429 rate_limited:
| Methode | Limit |
|---|---|
createInvoice, createCheck | 60 pro Minute |
refundInvoice | 30 pro Minute |
transfer | 30 pro Minute |
transferBatch | 10 pro Minute |
updateApp | 10 pro Minute |
createSubscriptionPlan | 20 pro Minute |
Zwei weitere Limits schützen vor dem Durchprobieren:
- Fehlgeschlagene Authentifizierung: Nach 30 Anfragen mit fehlendem oder
ungültigem Token von einer IP-Adresse innerhalb einer Minute erhält jede
Anfrage von dieser Adresse bis zum Ende der Minute
429 rate_limited– auch mit gültigem Token. Lass einen falsch konfigurierten Job nicht über dieselbe IP laufen wie den Produktivverkehr. - Unbekannte Empfänger: Nach 10 Abfragen einer nicht existierenden
user_idoder eines@usernamein einer App innerhalb einer Minute (transfer, Elemente vontransferBatch,createCheckmitpin_to_username) liefert jede Empfängerabfrage dieser App bis zum Ende der Minute429 rate_limited.
Zusätzliche Anfragelimits können gelten. Warte bei 429 rate_limited länger,
bevor du die Anfrage wiederholst. Während einer Plattformwartung liefern
schreibende Methoden 503 maintenance; lesende Methoden bleiben verfügbar.
Katalog- und Kontomethoden
getMe
GET /pay/api/getMe – keine Parameter. Liefert die Identität der App:
app_id, name, payment_processing_bot_username, webhook_url,
webhook_events (die zusätzlichen Webhook-Typen, die die App aktiviert hat),
die oben beschriebenen Introspektionsfelder des Tokens scopes / token_name
sowie payout_mode (off / allowlist / any),
daily_payout_max_usd_cents (0 = kein vom Inhaber festgelegtes Limit) und
daily_payout_spent_usd_cents (Ausgaben im gleitenden 24-Stunden-Zeitraum).
updateApp
POST /pay/api/updateApp – Berechtigung webhooks. Optionale Parameter: name (1–64 Zeichen), webhook_url (öffentliche HTTPS-URL mit höchstens 256 Zeichen; ein leerer String entfernt sie) und webhook_events (Array oder kommagetrennte Liste unterstützter zusätzlicher Ereignisse). Bei einer leeren Ereignisliste bleibt nur invoice_paid. Gibt dieselben App-Felder wie getMe zurück.
Fehler: 400 invalid_request (name außerhalb von 1–64 Zeichen oder webhook_url keine öffentliche HTTPS-Adresse bzw. länger als 256 Zeichen), 400 invalid_name (Name sieht wie ein Link oder @username aus), 400 app_name_reserved (Name enthält den Namen TgPay Crypto) und 400 invalid_webhook_events (unbekannter Ereignisname; auch invoice_paid ist hier unzulässig, da es keine separate Aktivierung braucht).
getBalance
GET /pay/api/getBalance – keine Parameter. Liefert ein Array mit einer Zeile
pro unterstütztem Asset, auch bei null (ein abgeschaltetes Asset erscheint nur,
solange die App noch Guthaben darin hat): currency_code, available
(verfügbares Guthaben), onhold (Guthaben in noch nicht eingelösten Schecks
und ausstehende Auszahlungen an @usernames) und amount_minor.
getCurrencies
GET /pay/api/getCurrencies – keine Parameter. Die maßgebliche Liste dessen,
was die API unterstützt: Krypto-Zeilen (is_blockchain: true) und die
Fiat-Währungen, in denen Rechnungsbeträge angegeben werden können (is_fiat: true).
Jede Zeile führt code, name, decimals und das Flag is_stablecoin.
getExchangeRates
GET /pay/api/getExchangeRates – keine Parameter. Kurse von Krypto zu Fiat:
source, target, rate (ein Festkomma-String), is_valid, is_crypto und
is_fiat.
Diese Kurse dienen nur als Richtwerte. is_valid: true garantiert nicht,
dass ein Kurs aktuell ist. Können keine Kurse abgerufen werden, kann das
Ergebnis ein leeres Array sein. Verwende für den Abgleich einer tatsächlichen
Zahlung die in der Rechnung gespeicherten Beträge und Kurse.
getStats
GET /pay/api/getStats – optional start_at / end_at (ISO 8601; das
Standardfenster sind die letzten 24 Stunden). Liefert volume (USD-Wert der
im Zeitraum bezahlten Rechnungen, anhand aktueller Kurse geschätzt; Assets
ohne Kurs zählen mit null), conversion (bezahlt/erstellt, in Prozent),
unique_users_count, created_invoice_count, paid_invoice_count und die
tatsächlichen Grenzen des Fensters. volume und conversion sind JSON-Zahlen,
keine Strings. Ein nicht lesbares Datum liefert 400 invalid_date.
Fehler, die jede Methode liefern kann
| HTTP | error.name | Wann |
|---|---|---|
| 401 | unauthorized | fehlender, ungültiger oder widerrufener Token |
| 403 | scope_required | dem Token fehlt die Berechtigung der Methode |
| 403 | payouts_disabled | der Auszahlungsmodus der App ist off (nur Auszahlungsmethoden) |
| 403 | recipient_not_allowed | der Empfänger steht nicht auf der Empfängerliste der App (nur Auszahlungsmethoden) |
| 400 | invalid_request | nicht lesbare oder ungültige Parameter (POST) |
| 403 | daily_cap_exceeded | das Tageslimit der App für Auszahlungen würde überschritten |
| 403 | verification_required | ausgehende Vorgänge des Inhabers sind eingeschränkt; betrifft Überweisungen, Schecks und Rückerstattungen |
| 503 | merchant_payouts_paused | Belastungen des App-Guthabens sind vorübergehend ausgesetzt |
| 429 | rate_limited | Anfragelimit überschritten |
| 503 | maintenance | Plattformwartung (schreibende Methoden) |
| 500 | internal_error | unerwarteter Serverfehler |
Methodenspezifische Fehler stehen auf der Seite der jeweiligen Methode.
Fehler ohne die JSON-Struktur
Eine Fehlermeldung als Klartext oder HTML zeigt allein nicht, auf welcher Ebene sie entstanden ist. Prüfe den HTTP-Status, den Antworttext und die Antwortheader.
Gibt Cloudflare error code: 1010 zurück, wurde der Client anhand seiner Browsersignatur abgelehnt, bevor die Anfrage die API erreicht hat. Token-Berechtigungen sind nicht die Ursache dieses Cloudflare-Fehlers. Ein fehlender oder ungewöhnlicher User-Agent kann den Netzwerkschutz auslösen. Versuche es mit einem aussagekräftigen User-Agent-Header wie MyShop/1.0 und wiederhole die Anfrage; eine Lösung ist damit nicht garantiert. Bleibt der Fehler bestehen, sende dem Support den HTTP-Status, den Antworttext und die Antwortheader. Entferne vorher Token und Cookies.
War dieser Artikel hilfreich?
Danke für dein Feedback.