Referensi Merchant API
Konvensi yang dipakai semua metode, plus metode katalog yang hanya membaca. Halaman per metode: faktur dan pengembalian dana, transfer dan cek kripto, langganan, webhook.
API mengikuti konvensi Crypto Bot untuk metode yang didokumentasikan di sini. Ganti base URL dan token, lalu uji metode yang dipakai integrasimu di testnet. Tambahan kami ditandai ekstensi di bawah.
Spesifikasi OpenAPI 3.1 yang bisa dibaca mesin juga tersedia: crypto-pay-openapi.yaml · crypto-pay-openapi.json. Masukkan saja ke generator kode, klien API, atau alat AI-mu, tetapi periksa juga halaman tiap metode: skema mungkin belum mencakup ekstensi terbaru.
Base URL dan autentikasi
Semua metode ada di https://app.tgpaycrypto.com/pay/api/<methodName>.
Di testnet, base URL-nya
https://testnet.tgpaycrypto.com/pay/api — aplikasi dan tokennya terpisah,
dana uji cobanya tidak bernilai.
Autentikasi tiap permintaan dengan token di header
TgPayCrypto-API-Token (TgCryptoPay-API-Token, nama lama sebelum
2026-09-07, dan Crypto-Pay-API-Token diterima sebagai alias
kompatibilitas; kalau beberapa dikirim sekaligus, yang kanonik yang menang).
Token
yang hilang, tidak valid, atau sudah dicabut — termasuk token terbatas yang kedaluwarsa, token aplikasi yang dihapus, atau token milik pemilik yang diblokir — mengembalikan 401 unauthorized.
Tokennya berbentuk <app_id>:<secret> dan hanya ditampilkan sekali, saat
dibuat atau diganti; server cuma menyimpan hash-nya. Lihat
Mulai sebagai developer.
Token dan scope
Ada dua jenis kredensial, keduanya diautentikasi dengan cara yang sama:
- Token utama — akses penuh ke semua metode, dan satu-satunya kunci yang menandatangani webhook.
- Token terbatas (ekstensi) — maksimal 10 token yang belum dicabut per aplikasi, termasuk yang kedaluwarsa, dibuat di Lainnya → Merchant API: pilih aplikasinya, lalu buka Akses dan token. Buat token di bagian Token terbatas, masing-masing punya label dan sebagian scope saja. Mencabut satu token berlaku seketika dan tidak memengaruhi yang lain; mengganti token utama juga tidak memengaruhi token terbatas. Token juga bisa memiliki tenggat kedaluwarsa; setelah itu token tidak bisa dipakai untuk autentikasi.
| Scope | Metode yang dibuka |
|---|---|
| (token valid apa pun) | 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 |
Scope bersifat kumulatif dan berdiri sendiri — invoices tidak otomatis
memberi read, jadi server yang cuma membuat faktur boleh memegang token
yang tidak bisa membaca saldo atau riwayat pembayaran. Memanggil metode yang tidak dicakup
tokennya mengembalikan 403 scope_required. getMe melaporkan scopes
token yang sedang dipakai (null untuk token utama) dan token_name, jadi
kamu selalu bisa memeriksa token apa yang sedang kamu pegang.
Mode pembayaran
Scope menentukan metode mana yang boleh dipanggil sebuah token; mode
pembayaran aplikasi menentukan kepada siapa token mana pun miliknya —
termasuk token utama — boleh mengirim dana. Aplikasi baru bisa membayar
siapa pun sejak menit pertama; pemiliknya bisa mempersempitnya di
Lainnya → Merchant API: buka aplikasinya, lalu pilih
Pengaturan pembayaran → Pembayaran lewat API sebagai pengaman kalau
token bocor, sama seperti batas harian. Melonggarkannya kembali butuh PIN
atau biometrik; API hanya bisa membacanya (getMe → payout_mode).
payout_mode | Yang boleh dilakukan transfer, transferBatch, dan createCheck |
|---|---|
any | membayar pengguna mana pun, menahan pembayaran untuk @username yang belum dikenal di escrow, membuat cek yang bisa diklaim siapa saja — ini nilai bawaannya, sekaligus perilaku Crypto Bot |
allowlist | hanya membayar pengguna Telegram yang diizinkan. Setiap penerima cek yang dikunci atau disebut dalam daftar penerima harus diizinkan. Penerima lain, @username yang belum dikenal, dan cek yang bisa diklaim siapa saja mengembalikan 403 recipient_not_allowed |
off | tidak ada — setiap panggilan pembayaran mengembalikan 403 payouts_disabled; faktur, langganan, pengembalian dana, dan webhook tetap jalan seperti biasa |
Kalau ada pembayaran yang ditolak, pemiliknya diberi tahu di Telegram dan bisa mengubah modenya. Batas pembayaran harian tetap berlaku bersama mode ini. Apa saja yang boleh kamu bayar lewat API diatur di ketentuan Merchant API.
Permintaan dan respons
- Metode baca memakai
GETdengan parameter di query string. Metode yang memindahkan uang hanyaPOST— parameternya sebagai body JSON, form-urlencoded, atau query param (kalau bentrok, body yang menang);multipart/form-dataditolak. - Respons dari handler API berupa JSON dengan envelope yang sama: sukses
{"ok": true, "result": …}, error{"ok": false, "error": {"code": <HTTP status>, "name": "<error_name>"}}. Pakaierror.nameuntuk percabangan — itu string stabil yang bisa dibaca mesin. - Nilai query bertipe salah di metode GET (misalnya
offset=abc) bisa ditolak sebelum handler API dijalankan. Periksa status HTTP; jangan menganggap semua respons error memakai envelope di atas. Kirim nilai query dengan tipe yang benar.
Jumlah
- Jumlah kripto berupa string desimal dalam satuan aset (
"10.5") — jangan pernah angka JSON. Respons juga membawaamount_minor(ekstensi): nilai satuan terkecil sebagai string bilangan bulat, karena bilangan besar dalam wei bisa melampaui batas ketepatan bilangan bulat padaNumberdi JavaScript. - Nilai
decimalstiap aset datang darigetCurrencies— hitung jumlahnya dari situ, jangan ditulis sebagai konstanta di kode. - Jumlah fiat maksimal 2 angka di belakang koma.
- Kurs berupa string fixed-point, bukan angka.
Paginasi
Metode daftar (getInvoices, getChecks, getTransfers,
getSubscriptions) menerima offset (bawaan 0) dan count (bawaan 100,
maksimal 1000; getSubscriptions maksimal 500) lalu mengembalikan
{"items": […]}, diurutkan dari yang terbaru. Filter ID (invoice_ids,
check_ids, transfer_ids) berupa daftar bilangan bulat yang dipisah koma.
Semua timestamp berupa string ISO 8601.
Idempotensi: spend_id
Metode yang memindahkan uang menerima kunci spend_id yang kamu buat
sendiri (1–64 karakter): wajib di transfer dan di tiap item
transferBatch, opsional di createCheck dan refundInvoice (ekstensi —
pakai saja). Mengulang dengan kunci dan parameter yang sama akan mengulang
hasil aslinya, bukan memindahkan dana dua kali, jadi permintaan yang kena
timeout selalu aman diulang. Kunci yang sama dengan parameter berbeda
mengembalikan 409 idempotency_conflict; percobaan ulang sementara yang
asli masih berjalan mengembalikan 409 idempotency_in_progress.
Batas frekuensi
Per aplikasi, dihitung gabungan untuk semua tokennya; kalau terlampaui akan
mengembalikan 429 rate_limited:
| Metode | Batas |
|---|---|
createInvoice, createCheck | 60 per menit |
refundInvoice | 30 per menit |
transfer | 30 per menit |
transferBatch | 10 per menit |
updateApp | 10 per menit |
createSubscriptionPlan | 20 per menit |
Batas permintaan tambahan mungkin berlaku. Saat menerima 429 rate_limited, tambah jeda sebelum mencoba lagi. Saat platform sedang pemeliharaan,
metode tulis mengembalikan 503 maintenance sementara metode baca tetap
jalan.
Metode katalog dan akun
getMe
GET /pay/api/getMe — tanpa parameter. Mengembalikan identitas
aplikasinya: app_id, name, payment_processing_bot_username,
webhook_url, webhook_events (tipe webhook tambahan yang diaktifkan
aplikasinya), field introspeksi token scopes / token_name yang
dijelaskan di atas, dan payout_mode (off / allowlist / any), daily_payout_max_usd_cents (0 = pemilik tidak menetapkan batas), dan daily_payout_spent_usd_cents (pengeluaran selama 24 jam terakhir).
updateApp
POST /pay/api/updateApp — scope webhooks. Parameter opsional: name (1–64 karakter), webhook_url (URL HTTPS publik; string kosong menghapusnya), dan webhook_events (array atau daftar nama event tambahan yang didukung, dipisah koma). Daftar event kosong menyisakan invoice_paid saja. Mengembalikan field aplikasi yang sama seperti getMe.
getBalance
GET /pay/api/getBalance — tanpa parameter. Mengembalikan array berisi
satu baris per aset yang didukung, termasuk yang saldonya kosong:
currency_code, available (saldo yang bisa dipakai), onhold (dana cek yang belum diklaim dan pembayaran @username yang menunggu), dan amount_minor.
getCurrencies
GET /pay/api/getCurrencies — tanpa parameter. Daftar resmi apa saja yang
didukung API: baris kripto (is_blockchain: true) dan mata uang fiat yang
bisa dipakai untuk memberi harga faktur (is_fiat: true). Tiap baris
membawa code, name, decimals, dan flag is_stablecoin.
getExchangeRates
GET /pay/api/getExchangeRates — tanpa parameter. Kurs kripto ke fiat:
source, target, rate (string fixed-point), dan is_valid. Anggap kurs ini sebagai perkiraan. is_valid: true tidak menjamin kurs masih berlaku saat ini. Jika kurs tidak bisa diperoleh, hasil bisa berupa array kosong. Gunakan jumlah dan kurs yang tercatat di faktur untuk mencocokkan pembayaran yang sudah terjadi.
getStats
GET /pay/api/getStats — start_at / end_at opsional (ISO 8601; rentang
bawaannya 24 jam terakhir). Mengembalikan volume (nilai USD faktur yang
dibayar dalam rentang itu, diperkirakan dengan kurs saat ini; aset tanpa harga dihitung nol), conversion (dibayar/dibuat, dalam persen),
unique_users_count, created_invoice_count, paid_invoice_count, dan
batas rentang yang benar-benar dipakai. Tanggal yang tidak bisa diurai
mengembalikan 400 invalid_date.
Error yang bisa muncul di semua metode
| HTTP | error.name | Kapan |
|---|---|---|
| 401 | unauthorized | token hilang, tidak valid, atau sudah dicabut |
| 403 | scope_required | token tidak punya scope untuk metode itu |
| 403 | payouts_disabled | mode pembayaran aplikasi off (hanya metode pembayaran) |
| 403 | recipient_not_allowed | penerima tidak ada di daftar penerima aplikasi (hanya metode pembayaran) |
| 400 | invalid_request | parameter tidak bisa diurai atau tidak valid (POST) |
| 403 | daily_cap_exceeded | batas pembayaran harian aplikasi akan terlampaui |
| 403 | verification_required | operasi keluar pemilik dibatasi; berlaku untuk transfer, cek, dan pengembalian dana |
| 503 | merchant_payouts_paused | pemotongan saldo aplikasi dihentikan sementara |
| 429 | rate_limited | batas frekuensi terlampaui |
| 503 | maintenance | platform sedang dalam pemeliharaan (metode tulis) |
| 500 | internal_error | error server yang tidak terduga |
Error khusus tiap metode dicantumkan di halaman metodenya masing-masing.
Error tanpa format JSON
Respons error berupa teks biasa atau HTML saja belum menunjukkan lapisan mana yang mengembalikannya. Periksa status HTTP, isi respons, dan header respons.
Jika Cloudflare mengembalikan error code: 1010, klien ditolak berdasarkan signature browser sebelum permintaan mencapai API. Cakupan token bukan penyebab error Cloudflare ini. User-Agent yang tidak ada atau tidak standar dapat memicu perlindungan jaringan. Coba kirim header User-Agent yang mengidentifikasi klienmu, misalnya MyShop/1.0, lalu ulangi permintaan; cara ini tidak menjamin masalah teratasi. Jika error tetap muncul, kirim status HTTP, isi respons, dan header respons ke dukungan setelah menghapus token dan cookie.
Artikel ini membantu?
Terima kasih atas masukannya.