Referensi API: webhook
Webhook mengirim event ke servermu setelah event terjadi. Isi Webhook URL (opsional) aplikasimu di Lainnya → Merchant API; setelah itu platform mem-POST body JSON bertanda tangan untuk tiap event yang kamu ikuti.
Envelope
{
"update_id": 123,
"update_type": "invoice_paid",
"request_date": "2026-08-11T12:00:00Z",
"payload": { … }
}
update_id tetap sama di setiap pengiriman ulang event yang sama — pakai
itu sebagai kunci deduplikasi. request_date dicatat per percobaan
pengiriman. payload berisi objek lengkap sesuai tipe event-nya: objek
faktur untuk event faktur, objek cek, objek transfer, atau objek langganan (bentuknya ada
di halaman referensi masing-masing).
Tipe event
update_type | Terjadi saat | Payload |
|---|---|---|
invoice_paid | faktur dibayar — tidak perlu diaktifkan terpisah | objek faktur |
invoice_expired | faktur lewat tenggatnya tanpa dibayar | objek faktur |
check_activated | cek atau bagian satu penerima diklaim | objek cek; klaim penerima dalam daftar juga memiliki activated_slot |
check_expired | cek dengan daftar penerima kedaluwarsa dan bagian yang belum diklaim kembali ke aplikasi | objek cek dengan recipients dan nilai claimed_at masing-masing |
transfer_completed | transfer selesai, atau pembayaran on-chain dikonfirmasi | objek transfer atau penarikan |
transfer_returned | transfer yang belum diklaim kembali ke aplikasi, atau pembayaran on-chain gagal dan dana yang ditahan dikembalikan | objek transfer atau penarikan |
refund_completed | pengembalian dana dijalankan | objek faktur dengan field refunded_* |
subscription_activated | pengguna menyetujui paket | objek langganan |
subscription_charged | pembayaran satu periode berhasil dipotong — charge.kind menyebut yang mana: initial, renewal, atau resubscribe | objek langganan + charge: {period_no, kind, asset, amount, fee, paid_at} |
subscription_cancelled | langganan dibatalkan salah satu pihak | objek langganan |
subscription_expired | masa tenggang habis tanpa dibayar | objek langganan |
Pembayaran on-chain yang dibuat di aplikasi memakai event transfer yang sama. Payload-nya memiliki kind: "withdrawal", field blockchain seperti network, address, dan txid, serta status completed atau failed. Nilai transfer_id memakai urutan ID tersendiri; bedakan payload menurut kind sebelum memakainya. Referensi OpenAPI yang bisa diunduh menjelaskan kedua bentuk payload.
Selain invoice_paid, semuanya harus diaktifkan dulu (ekstensi di luar
Crypto Bot — penerima yang ketat mengikuti bentuk Crypto Bot tidak akan
pernah bertemu update_type asing kecuali kamu memang memintanya).
Aktifkan per aplikasi di Event webhook tambahan pada bagian Webhook — pilihannya memakai identifier dari tabel di atas. Simpan URL webhook untuk menerima event.
Memverifikasi tanda tangan
Tiap pengiriman membawa header TgPayCrypto-API-Signature
(TgCryptoPay-API-Signature dan Crypto-Pay-API-Signature adalah alias
kompatibilitas dengan nilai yang sama): HMAC-SHA256 dalam heksadesimal atas body permintaan mentah, dengan
kunci berupa digest SHA-256 dari token API utama aplikasimu. Skemanya
sama persis dengan Crypto Bot, jadi kode verifikasi yang sudah ada tetap
jalan tanpa diubah:
import hashlib, hmac
secret = hashlib.sha256(API_TOKEN.encode()).digest()
expected = hmac.new(secret, raw_body, hashlib.sha256).hexdigest()
ok = hmac.compare_digest(expected, headers["TgPayCrypto-API-Signature"])
Verifikasi atas byte mentah yang diterima — hasil parse yang diserialisasi ulang bisa berbeda byte demi byte dan membuat pemeriksaannya gagal. Hanya token utama yang menandatangani; token terbatas tidak pernah. Mengganti token utama langsung mengganti kunci tanda tangan webhook, jadi perbarui juga secret di servermu di saat yang sama.
Pengiriman dan percobaan ulang
- Pengiriman dianggap berhasil jika respons 2xx diterima sebelum percobaan mencapai timeout. Balas segera dan proses pekerjaan yang lama secara terpisah.
- Status error, timeout, atau kegagalan koneksi memicu percobaan ulang dengan jeda yang meningkat, sampai batas percobaan platform. Pengiriman tidak dijamin; gunakan
getInvoicesuntuk mencocokkan pembayaran setelah gangguan. - Setelah percobaan terakhir, pengirimannya dibuang. Webhook URL-nya sendiri tidak pernah dimatikan otomatis — endpoint yang sering gagal tidak diam-diam membuat aplikasimu berhenti berlangganan.
- Karena pengiriman bisa diulang, handler-mu harus idempoten:
saring duplikat berdasarkan
update_idsebelum bertindak.
⚠️ Verifikasi dulu, baru penuhi pesanannya
Siapa pun bisa mem-POST ke webhook URL-mu. Sebelum pemeriksaan tanda
tangannya lolos, anggap body-nya sebagai input yang tidak tepercaya: jangan
kirim pesanan, jangan tambahkan saldo pengguna, jangan tandai apa pun
sebagai lunas. Urutan yang aman: verifikasi tanda tangan → saring duplikat
berdasarkan update_id → baru bertindak.
Artikel ini membantu?
Terima kasih atas masukannya.