FAQ
Getting Started
Q: How do I register as a partner?
Select a plan on the Partner page in the mini app, and your API Key is issued instantly.
Q: Is there an approval process?
No. It's completely self-service — you can start right away.
Q: Do I need a business registration?
No. Individual developers can sign up too.
Q: Which plan should I pick?
| Plan | Price | Monthly calls | Rate multiplier |
|---|---|---|---|
| Free | $0 | 1,000 | ×1 |
| Founding Member | $140 one-time | Unlimited | ×5 |
Founding Member is a one-time payment with lifetime access.
Q: Is there a test/sandbox mode?
No separate test mode is available. We recommend testing with small amounts in production.
Payments
Q: What payment types are available?
Three, plus direct transfers:
| Type | Best for |
|---|---|
| Payment link | Online stores, subscriptions, invoices |
| QR payment | POS, in-person payments, tip jars |
| Escrow | Marketplaces, freelance, P2P trades |
| Withdrawal | Rewards, payouts, cashback |
Q: What are the minimum amounts?
They differ per resource — this is the most common cause of INVALID_AMOUNT:
| Resource | Minimum |
|---|---|
| Payment link | 0.000001 USDT |
| Withdrawal | 0.000001 USDT |
| QR payment (fixed amount) | 0.01 USDT |
| Escrow | 1 USDT |
| Deposit | 1 USDT |
Q: Is there a maximum payment amount?
Payment links have no cap. Withdrawals may be capped if per-transaction or daily spend limits are configured on your account — see the Spend Limits section in the API docs.
Q: How long are payment links valid?
The create response returns expires_at 24 hours out, but this value is informational — there is no background job that closes the link, and payment is not blocked after that time. There is also no expires_in parameter. If you need a hard cutoff, enforce it in your own code.
Q: Which ID do I use to check a payment?
The payment.id from the create response — a 6-character link_id, also returned as payment.link_id. Pass it to GET /api/partner/payments/:link_id.
Q: What if the user doesn't have a PAYchat account?
An account is created automatically when they pay. No extra handling on your end.
Q: How do I know when a payment is complete?
A payment.completed webhook is sent to your configured webhook URL.Matching the payment to your orde
Q: Is my metadata included in webhooks?
Yes. Whatever you attach on creation is echoed back in the webhook payload for payment.completed, qr.paid, escrow.created, escrow.paid, escrow.released, and escrow.cancelled — no follow-up GET needed. withdraw.completed carries memo instead of metadata.
You can still fetch it any time with GET /payments/:link_id, GET /escrows/:id, or GET /qr-payments/:id.
Q: Can payments be refunded or cancelled?
Due to the nature of blockchain transactions, payments cannot be reversed after completion. For reversible flows, use escrow — an unreleased escrow can be cancelled and refunded to the buyer.
QR Payments
Q: How do I set an expiry?
Pass expires_hours — measured in hours, not seconds. Omit it and the QR never expires.
Q: My QR is past its expiry but still accepts payment. Why?
expires_at is stored for reference only. No background job transitions the record and the payment flow does not check it, so an expired QR still reports active and can still be paid. Enforce expiry in your own code, or call DELETE /qr-payments/:id to close it.
Q: Can customers choose their own amount?
Yes. Set is_fixed_amount: false with min_amount and max_amount. Add single_use: false for a reusable code such as a tip jar.
Q: Which field holds the QR image?
qr_image_url. The Telegram deeplink is payment_url.
Escrow
Q: What does escrow cost?
1% of the amount, deducted from the seller payout. A 100 USDT escrow pays the seller 99 USDT.
Q: What if the seller has no PAYchat account?
An account is created automatically when the escrow is created.
Q: How long does an escrow stay open?
72 hours by default. Adjust with expires_hours.
Q: How do I complete or reverse an escrow?
POST /escrows/:id/release pays the seller. POST /escrows/:id/cancel refunds the buyer. An escrow already mid-transition returns ESCROW_PROCESSING.
Withdrawals
Q: How do I send money to a user?
Call POST /api/partner/withdrawals with the user's telegram_id and the amount.
Q: Are withdrawals processed instantly?
Yes. Funds appear in the user's wallet immediately after the API call.
Q: Does the user receive a notification?
Yes — they automatically receive a Telegram message about the incoming funds.
Q: Can I withdraw to my own account?
No. That returns CANNOT_WITHDRAW_TO_SELF.
Q: How do I prevent double-sending?
Pass idempotency_key in the request body. Keys are retained 24 hours; a replay returns the original response. The key is claimed before funds move, so a concurrent retry gets REQUEST_IN_PROGRESS. If the transfer fails, the claim is released and you can retry.es are charge
Q: What are the fees?
Charged per API call, not as a percentage of transaction volume, and deducted from your balance. Your discount is based on your balance plus the combined balance of users you referred.
See the Pricing page for the full rate and tier tables, or call GET /fee-info for your live rate.
Q: How do referred users affect my discount?
The first withdrawal to a user registers them as your referral. Their balance then counts toward your total holdings, raising your discount tier.
Q: What's the settlement period?
Real-time. Funds are added to your partner balance the moment a payment completes.
Q: How do I check my partner balance?
GET /api/partner/balance, or the Partner page in the mini app. Note this endpoint returns available, monthly_volume, and fee_rate — for total holdings and referral balances, use GET /api/partner/fee-info.
Q: How do I add funds to my partner balance?
Tap "Charge" in the mini app, or call POST /api/partner/deposits (minimum 1 USDT, network tron or ton).
Q: What happens if my balance runs out?
On the Free plan, API access is blocked with BALANCE_TOO_LOW once you fall below the minimum. Transaction endpoints return INSUFFICIENT_BALANCE when there aren't enough funds to cover the transfer.
Q: What are spend limits?
Optional per-partner caps. 0 means unlimited.
| Control | Error code |
|---|---|
| Per-transaction cap | TX_LIMIT_EXCEEDED |
| Daily cap | DAILY_LIMIT_EXCEEDED |
The daily counter resets on the UTC date change. The amount is reserved at check time — if a withdrawal later fails, the reserved amount stays counted until the next reset.
Webhooks
Q: How do I set up my webhook URL?
Partner page → Webhooks tab in the mini app, or PUT /api/partner/webhook.
Q: Why was my webhook URL rejected?
It must be a public HTTPS endpoint. Rejected with INVALID_WEBHOOK_URL: any http:// URL, localhost or .local hostnames, private ranges (10.x, 172.16–31.x, 192.168.x), loopback (127.x, ::1), link-local (169.254.x), CGNAT (100.64–127.x), multicast, bare hostnames with no dot, and integer or hex-encoded IP forms.
Q: Which events fire?
Eight: payment.completed, withdraw.completed, qr.paid, escrow.created, escrow.paid, escrow.released, escrow.cancelled, and test.
There are no qr.created, qr.expired, or deposit events — poll the relevant GET endpoint instead.
Q: What happens if a webhook fails?
We retry up to 5 total attempts with increasing delays:
Immediately → 1 min → 5 min → 30 min → 2 hours
After that the delivery is marked failed. You can replay it manually with POST /webhooks/:id/retry.
Q: What counts as a successful delivery?
Any 2xx status within 10 seconds. The response body doesn't matter.
Q: How do I secure webhooks?
Every webhook carries X-PAYchat-Signature: t=<unix>,v1=<hmac_sha256>. The signed message is timestamp + "." + JSON.stringify(payload), keyed with your Secret Key. Verify it and reject timestamps older than 5 minutes.
Q: How do I test webhooks?
Partner page → Webhooks tab → "Test", or POST /api/partner/webhook-test. This sends a test event.
Technical
Q: What's the base URL?
https://paychat.info/api/partner
Q: How do I authenticate?
The x-api-key request header. This is not a Bearer token.
x-api-key: pk_your_api_key_hereQ: Which networks are supported?
USDT on TRON (TRC-20) and TON. Any other value for network returns INVALID_NETWORK.
Note that GET /deposit-address returns the TRON address only — for TON, create a deposit request with POST /deposits and "network": "ton".
Q: Are there API rate limits?
Yes, per endpoint. All GET endpoints share one counter.
| Endpoint | Free | Founding Member |
|---|---|---|
POST /payments | 100/min | 500/min |
POST /withdrawals | 50/min | 250/min |
All GET requests | 300/min | 1,500/min |
Every response includes X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset. On 429 you also get Retry-After.
Q: Is there an SDK?
Yes — the official Node.js SDK, v2.0.1:
npm install paychat-sdkimport PAYchatClient from 'paychat-sdk';
const client = new PAYchatClient('pk_your_api_key');
// Payment link
const payment = await client.createPayment({
amount: 10,
description: 'Limited Edition T-Shirt'
});
// QR payment — expiresHours is in HOURS
const qr = await client.createQRPayment({
amount: 15,
description: 'Coffee Shop Order',
expiresHours: 1
});
// Escrow — minimum 1 USDT, 1% fee
const escrow = await client.createEscrow({
amount: 100,
buyerTelegramId: '123456789',
sellerTelegramId: '987654321'
});
// Withdrawal
await client.createWithdrawal({
telegramId: '123456789',
amount: 5.00,
memo: 'Reward payout'
});📖 SDK on npm — https://www.npmjs.com/package/paychat-sdk
Q: Are all endpoints covered by the SDK?
Not yet. These have no SDK method — call them directly with the x-api-key header:
GET /fee-info, GET /webhooks, POST /webhooks/:id/retry, POST /transfer, GET /transfer/:requestId, GET /users/:telegram_id, GET /me, POST /register, POST /register-free, POST /upgrade, POST /reset, PUT /settings
Q: Do list endpoints paginate?
GET /transactions and GET /deposits return a pagination object. GET /escrows and GET /qr-payments do not, and return a subset of fields — use the detail endpoint for the full record.
Q: How do I open the payment screen in a mini app?
window.Telegram.WebApp.openTelegramLink(payment_url)
Account Management
Q: I lost my API Key. What do I do?
Partner page → API Keys tab → regenerate, or POST /api/partner/regenerate-key.
⚠️ This rotates your Secret Key at the same time. Your old API Key stops working instantly, and any webhook verification using the old Secret Key will start failing — update both.
Q: Can I view my Secret Key again?
Yes. Partner page → API Keys tab → tap the eye icon to reveal it, then use the copy button.
Q: What's the difference between the two keys?
| Key | Format | Purpose |
|---|---|---|
| API Key | pk_xxxx... | Sent as the x-api-key header |
| Secret Key | sk_xxxx... | Never sent in requests — verifies webhook signatures only |
Q: How do I keep my keys safe?
- Never expose keys in client-side code
- Don't commit keys to version control
- Use environment variables
- Regenerate immediately if compromised
Support
Questions → https://t.me/paychat_group