Part 1: Introduction & Authentication
PAYchat Partner API
Build seamless USDT payments into your app with our simple REST API.
Welcome
PAYchat Partner API lets you:
β’
Accept payments - Generate payment links and get paid in USDT
β’
Send money - Instantly transfer USDT to any Telegram user
β’
Track everything - Real-time webhooks and detailed analytics
Base URL: https://paychat.me/api/partner
Official SDK
Install our Node.js SDK for the easiest integration:
npm install paychat-sdk
Bash
볡μ¬
import PAYchatClient from 'paychat-sdk';
const client = new PAYchatClient('pk_your_api_key');
// Create payment
const payment = await client.createPayment({
amount: 10,
description: 'Limited Edition T-Shirt'
});
console.log(payment.payment.payment_url);
JavaScript
볡μ¬
Authentication
Every API request requires your API Key in the header.
Your Credentials
Key | Format | Purpose |
API Key | pk_xxxx... | Authenticate API requests |
Secret Key | sk_xxxx... | Verify webhook signatures |
How to Authenticate
Add your API Key to the request header:
X-API-Key: pk_your_api_key_here
Plain Text
볡μ¬
Example Request
curl https://paychat.me/api/partner/balance \
-H "X-API-Key: pk_abc123..."
Bash
볡μ¬
Keep Your Keys Safe
β’
Never expose keys in client-side code
β’
Don't commit keys to version control
β’
Use environment variables
β’
Regenerate immediately if compromised
Part 2: Plans & Pricing
Plans & Pricing
Plan
Plan | Rate Limit |
Founding Member | 500/min |
One-time payment. Lifetime access.
Volume Discount (Based on Total Holdings)
Your discount rate is based on total holdings:
$$
\text{Total Holdings} = \text{Your Balance} + \text{Referred Users' Balances}
$$
The more you hold, the higher your discount rate (up to 100% off).
How It Works
1.
Pay once β Get lifetime API access
2.
API fees deducted from your balance per call
3.
More holdings = Higher discount = Lower fees
4.
Refer users β Their balances count toward your discount!
Part 3: Rate Limits
Rate Limits
Protect your integration and our infrastructure with sensible rate limits.
Limits
Endpoint | Limit |
POST /payments | 500/min |
POST /withdrawals | 250/min |
All GET requests | 1,500/min |
Response Headers
Every response includes rate limit info:
Header | Meaning |
X-RateLimit-Limit | Max requests per window |
X-RateLimit-Remaining | Requests left |
X-RateLimit-Reset | Seconds until reset |
When You Hit the Limit
{
"success": false,
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Too many requests. Please retry later."
}
}
JSON
볡μ¬
Tip: Check the Retry-After header to know when to retry.
Part 4: API Endpoints Overview
API Endpoints
Quick Reference
Method | Endpoint | Description |
POST | /payments | Create a payment link |
GET | /payments/:id | Check payment status |
POST | /withdrawals | Send USDT to a user |
GET | /balance | Check your balance |
GET | /transactions | List transactions |
GET | /deposit-address | Get deposit address |
PUT | /webhook | Set webhook URL |
POST | /webhook-test | Test your webhook |
Public Endpoints (No Auth Required)
Method | Endpoint | Description |
GET | /plans | View available plans |
GET | /me?telegram_id= | Check partner status |
POST | /register | Register as partner |
Part 5: Create Payment
Create a Payment
Generate a payment link that customers can use to pay you.
Endpoint: POST /api/partner/payments
Request Body
Field | Type | Required | Description |
amount | number | Amount in USDT (min: 0.000001) | |
description | string | What the payment is for | |
metadata | object | Your custom data (stored, returned in webhooks) | |
idempotency_key | string | Prevent duplicate payments |
Example Request
curl -X POST https://paychat.me/api/partner/payments \
-H "X-API-Key: pk_your_key" \
-H "Content-Type: application/json" \
-d '{
"amount": 29.99,
"description": "Limited Edition T-Shirt",
"metadata": {
"user_id": "user_123",
"item": "tshirt_black_L"
}
}'
Bash
볡μ¬
Example Response
{
"success": true,
"payment": {
"id": "pay_abc123xyz",
"link_id": "x7k2m9",
"amount": 29.99,
"currency": "USDT",
"description": "Limited Edition T-Shirt",
"status": "pending",
"payment_url": "https://t.me/paychat_aibot?start=x7k2m9",
"expires_at": "2025-01-08T12:00:00.000Z",
"metadata": {
"user_id": "user_123",
"item": "tshirt_black_L"
},
"created_at": "2025-01-07T12:00:00.000Z"
}
}
JSON
볡μ¬
What to Do Next
1.
Redirect your customer to payment_url
2.
They'll complete payment in Telegram
3.
You'll receive a payment.completed webhook
4.
Funds are instantly added to your balance
Check Payment Status
See if a payment has been completed.
Endpoint: GET /api/partner/payments/:id
Example Request
curl https://paychat.me/api/partner/payments/x7k2m9 \
-H "X-API-Key: pk_your_key"
Bash
볡μ¬
Example Response (Completed)
{
"success": true,
"payment": {
"id": "x7k2m9",
"amount": 29.99,
"currency": "USDT",
"description": "Limited Edition T-Shirt",
"status": "completed",
"payer": {
"telegram_id": "987654321"
},
"paid_at": "2025-01-07T12:30:00.000Z",
"created_at": "2025-01-07T12:00:00.000Z"
}
}
JSON
볡μ¬
Payment Status Values
Status | Meaning |
pending | Waiting for payment |
completed | Payment received |
Part 6: Send Withdrawal
Send a Withdrawal
Instantly send USDT to any Telegram user.
Endpoint: POST /api/partner/withdrawals
Request Body
Field | Type | Required | Description |
telegram_id | string | Recipient's Telegram ID | |
amount | number | Amount in USDT (min: 0.000001) | |
memo | string | Message shown to recipient |
Example Request
curl -X POST https://paychat.me/api/partner/withdrawals \
-H "X-API-Key: pk_your_key" \
-H "Content-Type: application/json" \
-d '{
"telegram_id": "123456789",
"amount": 10.00,
"memo": "Referral bonus - Thanks!"
}'
Bash
볡μ¬
Example Response
{
"success": true,
"withdrawal": {
"id": "wd_xyz789abc",
"telegram_id": "123456789",
"amount": 10.00,
"status": "completed",
"created_at": "2025-01-07T12:00:00.000Z"
}
}
JSON
볡μ¬
Good to Know
Feature | How It Works |
Instant delivery | Funds arrive immediately |
Auto-registration | New users get a PAYchat account automatically |
Notifications | Recipients get a Telegram message |
Referral registration | First withdrawal registers the user as your referral |
Part 7: Check Balance
Check Your Balance
See how much USDT you have available.
Endpoint: GET /api/partner/balance
Example Response
{
"success": true,
"balance": {
"available": 1250.50,
"currency": "USDT",
"total_holdings": 5500.00,
"referral_holdings": 2500.00
}
}
JSON
볡μ¬
Field | Description |
available | USDT you can withdraw or send |
total_holdings | Total holdings (your balance + referred users' balances) |
referral_holdings | Total balance of your referred users |
Get Deposit Address
Get the address to fund your partner account.
Endpoint: GET /api/partner/deposit-address
Example Response
{
"success": true,
"deposit": {
"address": "TXxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"network": "TRON (TRC20)",
"currency": "USDT",
"memo": "partner_abc123",
"note": "Include the memo when sending to identify your deposit"
}
}
JSON
볡μ¬
Important: Always include the memo when sending funds so we can credit your account.
Part 8: Transactions & History
List Transactions
View your transaction history with filtering options.
Endpoint: GET /api/partner/transactions
Query Parameters
Parameter | Type | Default | Description |
type | string | all | payment or withdraw |
status | string | all | Filter by status |
from | string | - | Start date (ISO 8601) |
to | string | - | End date (ISO 8601) |
limit | number | 20 | Results per page (max 100) |
offset | number | 0 | Pagination offset |
Example Request
curl "https://paychat.me/api/partner/transactions?type=payment&limit=10" \
-H "X-API-Key: pk_your_key"
Bash
볡μ¬
Example Response
{
"success": true,
"transactions": [
{
"id": 1,
"type": "payment",
"telegram_id": "123456789",
"amount": 29.99,
"status": "completed",
"created_at": "2025-01-07T12:00:00.000Z"
},
{
"id": 2,
"type": "withdraw",
"telegram_id": "987654321",
"amount": 10.00,
"status": "completed",
"created_at": "2025-01-07T11:30:00.000Z"
}
],
"pagination": {
"total": 156,
"limit": 10,
"offset": 0
}
}
JSON
볡μ¬
Part 9: Webhooks
Webhooks
Get real-time notifications when events happen.
Available Events
Event | Description | When It Fires |
payment.completed | Payment received | Customer completes payment |
withdraw.completed | Withdrawal sent | Funds delivered to user |
test | Test event | You send a test webhook |
Setting Up Webhooks
1. Set your webhook URL:
curl -X PUT https://paychat.me/api/partner/webhook \
-H "X-API-Key: pk_your_key" \
-H "Content-Type: application/json" \
-d '{"webhook_url": "https://your-server.com/webhooks/paychat"}'
Bash
볡μ¬
2. Test it:
curl -X POST https://paychat.me/api/partner/webhook-test \
-H "X-API-Key: pk_your_key"
Bash
볡μ¬
Webhook Headers
Every webhook includes these headers:
Header | Description |
Content-Type | application/json |
X-PAYchat-Event | Event type |
X-PAYchat-Signature | HMAC signature for verification |
X-PAYchat-Delivery-ID | Unique delivery ID |
Webhook Payload: payment.completed
{
"event": "payment.completed",
"data": {
"payment_id": "x7k2m9",
"amount": 29.99,
"payer": {
"telegram_id": "987654321"
}
},
"created_at": "2025-01-07T12:00:00.000Z"
}
JSON
볡μ¬
Webhook Payload: withdraw.completed
{
"event": "withdraw.completed",
"data": {
"withdrawal_id": "wd_xyz789",
"telegram_id": "123456789",
"amount": 10.00,
"memo": "Referral bonus"
},
"created_at": "2025-01-07T12:00:00.000Z"
}
JSON
볡μ¬
Part 10: Webhook Security & Retries
Verifying Webhooks
Always verify webhook signatures to ensure they're from PAYchat.
How Signatures Work
1.
We create a message: {timestamp}.{payload}
2.
We sign it with your Secret Key using HMAC-SHA256
3.
We send the signature in X-PAYchat-Signature header
Signature Format
X-PAYchat-Signature: t=1704628800,v1=abc123def456...
Plain Text
볡μ¬
Part | Description |
t | Unix timestamp |
v1 | HMAC-SHA256 signature |
Verification Code (Node.js)
const crypto = require('crypto');
function verifyWebhook(payload, signatureHeader, secretKey) {
// Parse the signature header
const [tPart, v1Part] = signatureHeader.split(',');
const timestamp = tPart.replace('t=', '');
const signature = v1Part.replace('v1=', '');
// Recreate the signed message
const message = `${timestamp}.${JSON.stringify(payload)}`;
// Calculate expected signature
const expected = crypto
.createHmac('sha256', secretKey)
.update(message)
.digest('hex');
// Compare signatures
return signature === expected;
}
// In your webhook handler
app.post('/webhooks/paychat', (req, res) => {
const isValid = verifyWebhook(
req.body,
req.headers['x-paychat-signature'],
process.env.PAYCHAT_SECRET_KEY
);
if (!isValid) {
return res.status(401).send('Invalid signature');
}
// Process the webhook...
res.status(200).send('OK');
});
JavaScript
볡μ¬
Webhook Retries
If your server doesn't respond with a 2xx status, we'll retry automatically.
Retry Schedule
Attempt | Wait Time |
1st | Immediate |
2nd | 1 minute |
3rd | 5 minutes |
4th | 30 minutes |
5th | 2 hours |
Final | Marked as failed |
Requirements for Success
Requirement | Details |
Status code | Any 2xx (200-299) |
Timeout | Respond within 10 seconds |
Response body | Not required |
Part 11: Error Handling
Error Handling
All errors follow a consistent format.
Error Response Format
{
"success": false,
"error": {
"code": "ERROR_CODE",
"message": "Human readable description"
}
}
JSON
볡μ¬
HTTP Status Codes
Code | Meaning |
200 | Success |
400 | Bad request (check your input) |
401 | Authentication failed |
403 | Forbidden (account inactive) |
404 | Resource not found |
429 | Rate limit exceeded |
500 | Server error (retry later) |
Common Error Codes
Code | HTTP | Meaning | Solution |
INVALID_API_KEY | 401 | Missing or invalid API Key | Check your X-API-Key header |
PARTNER_INACTIVE | 403 | Account is disabled | Contact support |
RATE_LIMIT_EXCEEDED | 429 | Too many requests | Wait and retry |
INVALID_AMOUNT | 400 | Amount too small | Minimum is 0.000001 |
INSUFFICIENT_BALANCE | 400 | Not enough funds | Deposit more USDT |
PAYMENT_NOT_FOUND | 404 | Payment doesn't exist | Check the payment ID |
INVALID_WEBHOOK_URL | 400 | Bad webhook URL | Must start with https:// |
Error Examples
Authentication Failed
{
"success": false,
"error": {
"code": "INVALID_API_KEY",
"message": "API Key is required"
}
}
JSON
볡μ¬
Insufficient Balance
{
"success": false,
"error": {
"code": "INSUFFICIENT_BALANCE",
"message": "Insufficient balance"
}
}
JSON
볡μ¬
Part 12: Code Examples
Using the Official SDK (Recommended)
The easiest way to integrate PAYchat:
npm install paychat-sdk
Bash
볡μ¬
import PAYchatClient from 'paychat-sdk';
const client = new PAYchatClient('pk_your_api_key');
// Create payment
const payment = await client.createPayment({
amount: 29.99,
description: 'Limited Edition Hoodie',
metadata: { user_id: '123' }
});
// Send withdrawal
const withdrawal = await client.createWithdrawal({
telegramId: '123456789',
amount: 5.00,
memo: 'Referral bonus'
});
// Check balance
const balance = await client.getBalance();
// Verify webhook
const isValid = PAYchatClient.verifyWebhook(payload, signature, 'sk_your_secret_key');
JavaScript
볡μ¬
Quick Start Examples
Node.js Setup
const axios = require('axios');
const paychat = axios.create({
baseURL: 'https://paychat.me/api/partner',
headers: {
'X-API-Key': process.env.PAYCHAT_API_KEY,
'Content-Type': 'application/json'
}
});
JavaScript
볡μ¬
Create a Payment
async function createPayment(amount, description, metadata = {}) {
try {
const { data } = await paychat.post('/payments', {
amount,
description,
metadata,
idempotency_key: `pay_${Date.now()}_${Math.random()}`
});
console.log('Payment URL:', data.payment.payment_url);
return data.payment;
} catch (error) {
console.error('Error:', error.response?.data?.error?.message);
throw error;
}
}
// Usage
const payment = await createPayment(29.99, 'Limited Edition Hoodie', { user_id: '123' });
JavaScript
볡μ¬
Send Money to a User
async function sendReward(telegramId, amount, memo) {
try {
const { data } = await paychat.post('/withdrawals', {
telegram_id: telegramId,
amount,
memo
});
console.log(`Sent $${amount} to ${telegramId}`);
return data.withdrawal;
} catch (error) {
if (error.response?.data?.error?.code === 'INSUFFICIENT_BALANCE') {
console.error('Not enough balance! Please deposit more funds.');
}
throw error;
}
}
// Usage
await sendReward('123456789', 5.00, 'Thanks for your referral!');
JavaScript
볡μ¬
Handle Webhooks (Express)
const express = require('express');
const crypto = require('crypto');
const app = express();
app.use(express.json());
app.post('/webhooks/paychat', (req, res) => {
// Verify signature
const signature = req.headers['x-paychat-signature'];
if (!verifySignature(req.body, signature)) {
return res.status(401).send('Invalid signature');
}
// Handle events
const event = req.headers['x-paychat-event'];
switch (event) {
case 'payment.completed':
handlePayment(req.body.data);
break;
case 'withdraw.completed':
handleWithdrawal(req.body.data);
break;
}
res.status(200).send('OK');
});
function handlePayment(data) {
console.log(`π° Payment received!`);
console.log(` Amount: $${data.amount}`);
console.log(` From: ${data.payer.telegram_id}`);
// Update your database, send confirmation email, etc.
}
function handleWithdrawal(data) {
console.log(`β
Withdrawal completed!`);
console.log(` Amount: $${data.amount}`);
console.log(` To: ${data.telegram_id}`);
}
function verifySignature(payload, header) {
const [t, v1] = header.split(',');
const timestamp = t.replace('t=', '');
const signature = v1.replace('v1=', '');
const message = `${timestamp}.${JSON.stringify(payload)}`;
const expected = crypto
.createHmac('sha256', process.env.PAYCHAT_SECRET_KEY)
.update(message)
.digest('hex');
return signature === expected;
}
app.listen(3000);
JavaScript
볡μ¬
Part 13: FAQ
Frequently Asked Questions
General
Q: What if my balance is too low?
A: Auto-charge triggers if enabled. Otherwise, API returns error.
Q: How do referred users affect my discount?
A: First withdrawal to a user registers them as your referral. Their balance counts toward your total holdings, increasing your discount rate.
Q: What if my API key is exposed?
A: Regenerate it immediately:
curl -X POST https://paychat.me/api/partner/regenerate-key \
-H "X-API-Key: pk_your_current_key"
Bash
볡μ¬
Your old key becomes invalid instantly.
Payments
Q: How long do payment links last?
A: 24 hours. After that, they expire and can't be used.
Q: What currencies are supported?
A: Currently USDT on the TRON network (TRC-20). More options coming soon!
Q: When do I receive funds?
A: Instantly! As soon as a customer completes payment, it's added to your balance.
Withdrawals
Q: What if the recipient doesn't have PAYchat?
A: We automatically create an account for them. They'll receive a Telegram message with instructions to access their funds.
Q: Is there a minimum withdrawal?
A: Yes, 0.000001 USDT (practically any amount).
Q: How fast are withdrawals?
A: Instant! The recipient sees the funds immediately.
Webhooks
Q: What if my webhook endpoint is down?
A: We retry up to 5 times over ~2.5 hours. You can also manually retry failed webhooks later.
Q: Do I need to respond to webhooks?
A: Yes, with any 2xx status code within 10 seconds. The response body doesn't matter.
Security
Q: What's the idempotency_key for?
A: It prevents duplicate transactions if you accidentally send the same request twice. Use a unique value for each transaction.
Q: How do I verify webhooks are really from PAYchat?
A: Check the X-PAYchat-Signature header using your Secret Key. See the Webhook Security section for code examples.
Need Help?
Changelog
Date | Version | Changes |
2025-01-07 | 1.0.0 | Initial release |
2025-01-10 | 2.0.0 | Updated to holdings-based discount system |
Questions β https://t.me/paychat_group
Start β https://t.me/paychat_aibot?start=partner
