Tài liệu Merchant API
Các quy ước chung của mọi phương thức, cùng các phương thức tra cứu chỉ đọc. Trang chi tiết từng nhóm: hóa đơn và hoàn tiền, chuyển tiền và Lì xì, gói đăng ký, webhook.
API tuân theo quy ước Crypto Bot cho các phương thức được mô tả ở đây. Đổi base URL và token, rồi thử các phương thức tích hợp đang dùng trên testnet. Các chức năng bổ sung được đánh dấu phần mở rộng bên dưới.
Bản đặc tả OpenAPI 3.1 máy đọc được cũng có tại: crypto-pay-openapi.yaml · crypto-pay-openapi.json. Hãy nạp nó vào trình sinh code, API client hoặc công cụ AI, nhưng hãy xem cả trang từng phương thức: đặc tả có thể chưa cập nhật các phần mở rộng mới.
Base URL và xác thực
Mọi phương thức đều nằm ở https://app.tgpaycrypto.com/pay/api/<methodName>.
Trên mạng thử nghiệm, base là
https://testnet.tgpaycrypto.com/pay/api — ứng dụng và token riêng, coin không
có giá trị.
Hãy xác thực mọi yêu cầu bằng token đặt trong header
TgPayCrypto-API-Token (TgCryptoPay-API-Token, tên dùng trước ngày
2026-09-07, và Crypto-Pay-API-Token được chấp nhận như tên gọi thay thế để
tương thích; nếu gửi nhiều header cùng lúc thì header chuẩn được ưu tiên). Token thiếu, sai
hoặc đã bị thu hồi — cũng như token giới hạn quyền đã hết hạn, token của ứng dụng đã xóa hoặc có chủ sở hữu bị chặn — trả về
401 unauthorized.
Token có dạng <app_id>:<secret> và chỉ hiện một lần, lúc tạo hoặc lúc đổi
token mới; máy chủ chỉ lưu bản băm của nó. Xem
Bắt đầu dành cho lập trình viên.
Token và scope
Hai loại thông tin xác thực dùng chung một cách xác thực:
- Token chính — toàn quyền với mọi phương thức, và là khóa duy nhất ký webhook.
- Token giới hạn quyền (phần mở rộng) — tối đa 10 token chưa thu hồi, kể cả token đã hết hạn, cho mỗi ứng dụng. Mở Thêm → Merchant API, chọn ứng dụng rồi mở Quyền truy cập và token. Tạo token trong mục Token giới hạn quyền, mỗi token có một nhãn và một tập scope con. Thu hồi một token là tức thì và không đụng tới các token khác; đổi token chính cũng không đụng tới chúng. Token có thể có hạn sử dụng; sau đó không còn xác thực được.
| Scope | Phương thức mà nó mở |
|---|---|
| (mọi token hợp lệ) | 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 |
Các scope cộng dồn và độc lập với nhau — invoices không kéo theo read, nên
máy chủ chỉ tạo hóa đơn có thể dùng token không có quyền xem số dư hoặc lịch sử
thanh toán. Gọi phương thức nằm ngoài phạm vi quyền của token sẽ trả về 403 scope_required. getMe cho
biết scopes của token đang dùng (null với token chính) và token_name, nên
bạn có thể kiểm tra quyền của token đang dùng.
Chế độ chi trả
Scope quyết định token được gọi những phương thức nào; còn chế độ chi trả
của ứng dụng quyết định bất kỳ token nào của nó — kể cả token chính — được chi
trả cho ai. Một ứng dụng mới chi trả được cho bất kỳ ai ngay từ phút đầu; chủ
sở hữu có thể giới hạn người nhận bằng cách mở ứng dụng trong Thêm → Merchant API,
rồi vào Cài đặt chi trả → Chi trả qua API. Giống hạn mức hằng ngày, cài đặt này
giới hạn những gì người có token bị lộ có thể làm. Muốn mở rộng lại phạm vi người
nhận, cần mã PIN hoặc sinh trắc học; API chỉ đọc được chế độ này (getMe → payout_mode).
payout_mode | transfer, transferBatch và createCheck được làm gì |
|---|---|
any | chi trả cho bất kỳ người dùng nào, tạm giữ khoản chi trả cho một @username chưa biết, tạo Lì xì không gán người nhận — mặc định, đúng như Crypto Bot |
allowlist | chỉ chi trả cho những người dùng Telegram có trong danh sách người nhận của ứng dụng. Mọi người nhận được gán sẵn hoặc nêu trong danh sách Lì xì đều phải được phép nhận. Người khác, @username chưa biết và Lì xì không gán người nhận đều nhận 403 recipient_not_allowed |
off | không gì cả — mọi lệnh gọi chi trả đều trả về 403 payouts_disabled; hóa đơn, gói đăng ký, hoàn tiền và webhook vẫn chạy bình thường |
Khi một khoản chi trả bị từ chối, chủ sở hữu được báo trong Telegram và có thể đổi chế độ. Hạn mức chi trả mỗi ngày vẫn áp dụng bên cạnh chế độ này. Còn được chi trả cho những mục đích nào thì do điều khoản Merchant API quy định.
Yêu cầu và phản hồi
- Các phương thức đọc dùng
GETvới tham số trên query string. Các phương thức động tới tiền chỉ nhậnPOST— tham số truyền dưới dạng JSON body, form-urlencoded hoặc query param (body thắng khi xung đột);multipart/form-databị từ chối. - Phản hồi do trình xử lý API trả về dùng chung một cấu trúc JSON: thành công
{"ok": true, "result": …}, lỗi{"ok": false, "error": {"code": <HTTP status>, "name": "<error_name>"}}. Hãy rẽ nhánh theoerror.name— đó là chuỗi máy đọc ổn định. - Tham số query sai kiểu trên phương thức GET (ví dụ
offset=abc) có thể bị từ chối trước khi trình xử lý API chạy. Hãy kiểm tra mã trạng thái HTTP; đừng mặc định mọi phản hồi lỗi đều có cấu trúc trên. Gửi tham số query đúng kiểu dữ liệu yêu cầu.
Số tiền
- Số tiền crypto là chuỗi thập phân theo đơn vị tài sản (
"10.5") — không bao giờ là số JSON. Phản hồi còn kèmamount_minor(phần mở rộng): giá trị nguyên theo đơn vị nhỏ nhất, dưới dạng chuỗi, vì số nguyên cỡ wei có thể vượt giới hạn biểu diễn số nguyên chính xác củaNumbertrong JavaScript. decimalscủa từng tài sản lấy từgetCurrencies— hãy để phần tính toán số tiền chạy theo đó thay vì gán cứng.- Số tiền pháp định có tối đa 2 chữ số thập phân.
- Tỷ giá là chuỗi thập phân, không bao giờ là số.
Phân trang
Các phương thức danh sách (getInvoices, getChecks, getTransfers,
getSubscriptions) nhận offset (mặc định 0) và count (mặc định 100, tối đa
1000; getSubscriptions tối đa 500) và trả về {"items": […]}, mới nhất trước.
Bộ lọc theo ID (invoice_ids, check_ids, transfer_ids) là danh sách số
nguyên phân tách bằng dấu phẩy. Mọi dấu thời gian đều là chuỗi ISO 8601.
Idempotency: spend_id
Các phương thức động tới tiền nhận một khóa spend_id do bên gọi tự
sinh (1–64 ký tự): bắt buộc với transfer và với từng phần tử của
transferBatch, tùy chọn với createCheck và refundInvoice (phần mở rộng —
vẫn nên dùng). Thử lại với cùng khóa và cùng tham số sẽ trả về kết quả gốc thay
vì chuyển tiền hai lần, nên một yêu cầu hết thời gian chờ luôn an toàn để thử
lại. Cùng khóa nhưng khác tham số trả về 409 idempotency_conflict; thử lại
trong lúc lần gọi gốc còn đang chạy trả về 409 idempotency_in_progress.
Giới hạn tần suất
Tính theo từng ứng dụng, dùng chung cho mọi token của nó; vượt quá thì trả về
429 rate_limited:
| Phương thức | Giới hạn |
|---|---|
createInvoice, createCheck | 60 mỗi phút |
refundInvoice | 30 mỗi phút |
transfer | 30 mỗi phút |
transferBatch | 10 mỗi phút |
updateApp | 10 lần mỗi phút |
createSubscriptionPlan | 20 lần mỗi phút |
Có thể áp dụng thêm giới hạn yêu cầu. Khi gặp 429 rate_limited, tăng thời gian chờ trước khi thử lại. Trong lúc nền tảng bảo trì, các
phương thức ghi trả về 503 maintenance còn các phương thức đọc vẫn chạy bình
thường.
Phương thức tra cứu và tài khoản
getMe
GET /pay/api/getMe — không có tham số. Trả về danh tính của ứng dụng:
app_id, name, payment_processing_bot_username, webhook_url,
webhook_events (các loại webhook mở rộng mà ứng dụng đã bật), hai trường
cho biết thông tin token scopes / token_name nói ở trên, và payout_mode (off /
allowlist / any), daily_payout_max_usd_cents (0 = chủ sở hữu không đặt hạn mức) và daily_payout_spent_usd_cents (số đã chi trong 24 giờ gần nhất).
updateApp
POST /pay/api/updateApp — scope webhooks. Tham số tùy chọn: name (1–64 ký tự), webhook_url (URL HTTPS công khai; chuỗi rỗng để xóa) và webhook_events (mảng hoặc danh sách phân tách bằng dấu phẩy chứa các tên sự kiện mở rộng được hỗ trợ). Danh sách sự kiện rỗng chỉ giữ lại invoice_paid. Trả về cùng các trường ứng dụng như getMe.
getBalance
GET /pay/api/getBalance — không có tham số. Trả về một mảng, mỗi tài sản được
hỗ trợ một dòng, kể cả khi bằng không: currency_code, available (số dư khả
dụng), onhold (tiền Lì xì chưa được nhận và các khoản chi trả cho @username đang chờ) và
amount_minor.
getCurrencies
GET /pay/api/getCurrencies — không có tham số. Danh sách chuẩn những gì API hỗ
trợ: các dòng crypto (is_blockchain: true) và các loại tiền pháp định mà hóa
đơn có thể định giá theo (is_fiat: true). Mỗi dòng mang code, name,
decimals và cờ is_stablecoin.
getExchangeRates
GET /pay/api/getExchangeRates — không có tham số. Tỷ giá crypto sang tiền pháp
định: source, target, rate (chuỗi thập phân) và is_valid. Các tỷ giá này chỉ mang tính tham khảo. is_valid: true không bảo đảm tỷ giá còn mới. Nếu không lấy được tỷ giá, kết quả có thể là mảng rỗng. Dùng số tiền và tỷ giá đã ghi trên hóa đơn để đối soát thanh toán thực tế.
getStats
GET /pay/api/getStats — tùy chọn start_at / end_at (ISO 8601; cửa sổ mặc
định là 24 giờ gần nhất). Trả về volume (giá trị USD của các hóa đơn đã thanh
toán trong khoảng đó, ước tính theo tỷ giá hiện tại; tài sản không có giá được tính là 0), conversion (đã trả/đã tạo, theo phần trăm),
unique_users_count, created_invoice_count, paid_invoice_count, và hai mốc
thực tế của cửa sổ. Ngày không đọc được sẽ trả về 400 invalid_date.
Lỗi mà mọi phương thức đều có thể trả về
| HTTP | error.name | Khi nào |
|---|---|---|
| 401 | unauthorized | token thiếu, sai hoặc đã bị thu hồi |
| 403 | scope_required | token không có scope của phương thức |
| 403 | payouts_disabled | chế độ chi trả của ứng dụng đang là off (chỉ các phương thức chi trả) |
| 403 | recipient_not_allowed | người nhận không có trong danh sách người nhận của ứng dụng (chỉ các phương thức chi trả) |
| 400 | invalid_request | tham số không đọc được hoặc không hợp lệ (POST) |
| 403 | daily_cap_exceeded | vượt hạn mức chi trả hằng ngày của ứng dụng |
| 403 | verification_required | chủ sở hữu bị hạn chế giao dịch chi tiền; áp dụng cho chuyển tiền, Lì xì và hoàn tiền |
| 503 | merchant_payouts_paused | tạm dừng trừ tiền từ số dư ứng dụng |
| 429 | rate_limited | vượt giới hạn tần suất |
| 503 | maintenance | nền tảng đang bảo trì (các phương thức ghi) |
| 500 | internal_error | lỗi máy chủ ngoài dự kiến |
Các lỗi riêng của từng phương thức được liệt kê trên trang của phương thức đó.
Lỗi không theo cấu trúc JSON
Chỉ dựa vào phản hồi lỗi dạng văn bản thuần hoặc HTML thì chưa thể xác định lỗi đến từ lớp nào. Hãy kiểm tra trạng thái HTTP, nội dung và các header của phản hồi.
Nếu Cloudflare trả về error code: 1010, máy khách đã bị từ chối dựa trên dấu hiệu nhận dạng trình duyệt trước khi yêu cầu đến API. Phạm vi quyền của token không phải nguyên nhân gây ra lỗi Cloudflare này. User-Agent bị thiếu hoặc không chuẩn có thể kích hoạt lớp bảo vệ mạng. Hãy thử gửi header User-Agent có tên nhận diện máy khách của bạn, chẳng hạn MyShop/1.0, rồi gửi lại yêu cầu; cách này không đảm bảo khắc phục được lỗi. Nếu lỗi vẫn còn, hãy gửi cho bộ phận hỗ trợ trạng thái HTTP, nội dung và các header của phản hồi sau khi xóa token và cookie.
Bài viết này có giúp được bạn không?
Cảm ơn phản hồi của bạn.