CryptPay API
Accept cryptocurrency payments on your website or application. Create payment addresses, receive real-time webhook callbacks, and settle funds directly to your wallet.
Base URL: https://your-domain.com/api
Authentication
Public payment endpoints do not require authentication. Your integration is identified by the callback_url and address_out parameters you provide when creating a payment address.
No API keys, no registration — just call the API and start accepting payments.
Supported Chains
| Chain | Ticker | Tokens | Confirmations | Speed |
|---|---|---|---|---|
| Ethereum | eth | Native ETH + ERC-20 | 12 | ~2-4 min |
| BNB Chain | bsc | Native BNB + BEP-20 | 15 | ~45s |
| Polygon | polygon | Native POL + ERC-20 | 128 | ~4-6 min |
| Bitcoin | bitcoin | Native BTC | 2 | ~20 min |
Create Payment Address
Generate a unique deposit address for a customer payment. CryptPay monitors this address, confirms the payment, forwards it (minus fees) to your address_out, and notifies you via the callback_url.
Alternative format: /api/{ticker}/create — e.g., /api/eth/create, /api/bsc/usdt/create
Parameters
| Parameter | Type | Description |
|---|---|---|
| callback_url required | string | URL to receive payment notifications. |
| address_out required | string | Your wallet address to receive forwarded payments. Must match the chain format. |
| pending optional | 0 | 1 | Receive a callback on pending (unconfirmed) deposits. Default: 0 |
| confirmations optional | integer | Override required confirmations (1–100). Default: chain-specific value. |
| priority optional | string | Gas priority: slow, default, fast |
| multi_token optional | 0 | 1 | Accept any supported token on this address. Default: 0 |
| post optional | 0 | 1 | Send callback as POST body instead of GET params. Default: 0 |
| json optional | 0 | 1 | Send callback as JSON body (requires post=1). Default: 0 |
Example Request
curl -X POST https://your-domain.com/api/bsc/usdt/create \
-d callback_url=https://merchant.com/payment-hook \
-d address_out=0x742d35Cc6634C0532925a3b844Bc9e7595f2bD18 \
-d json=1 \
-d post=1
Response
{
"status": "success",
"address_in": "0x9a8f1e2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f",
"address_out": "0x742d35Cc6634C0532925a3b844Bc9e7595f2bD18",
"callback_url": "https://merchant.com/payment-hook",
"chain": "bsc",
"token": "usdt",
"confirmations": 15,
"priority": "default"
}
Payment Logs
Retrieve transaction history for a payment address.
| Parameter | Type | Description |
|---|---|---|
| callback_url required | string | Your callback URL (identifies the payment address) |
| address_out required | string | Your receiving address |
Payment Info
Get current status and details for a specific payment address.
| Parameter | Type | Description |
|---|---|---|
| callback_url required | string | Your callback URL |
| address_out required | string | Your receiving address |
List Cryptocurrencies
List all supported chains and tokens.
Response
{
"chains": [
{
"chain": "bsc",
"name": "BNB Smart Chain",
"tokens": [
{ "ticker": "bnb", "name": "BNB", "decimals": 18, "is_native": true },
{ "ticker": "usdt", "name": "Tether USD", "decimals": 18 },
{ "ticker": "usdc", "name": "USD Coin", "decimals": 18 }
]
},
{
"chain": "bitcoin",
"name": "Bitcoin",
"tokens": [
{ "ticker": "btc", "name": "Bitcoin", "decimals": 8, "is_native": true }
]
}
]
}
Callback Payload
When a payment is confirmed and forwarded, CryptPay sends a callback to your callback_url. The callback is sent as GET parameters by default, or as a POST JSON body if post=1 and json=1 were set during address creation.
| Field | Type | Description |
|---|---|---|
| uuid | string | Unique callback identifier |
| address_in | string | Customer deposit address |
| address_out | string | Your receiving address |
| txn_in | string | Deposit transaction hash |
| txn_out | string | Forwarding transaction hash |
| value_coin | string | Original deposit amount |
| value_forwarded_coin | string | Amount forwarded to you (after fees) |
| fee_percent | string | Service fee percentage applied |
| fee_coin | string | Fee amount deducted |
| chain_ticker | string | Chain identifier (eth, bsc, bitcoin, etc.) |
| symbol | string | Token symbol (ETH, USDT, BTC) |
| confirmations | integer | Block confirmations at callback time |
| result | string | done for confirmed, pending for unconfirmed |
Example Callback (JSON POST)
POST https://merchant.com/payment-hook
Content-Type: application/json
{
"uuid": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d",
"address_in": "0x9a8f1e2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f",
"address_out": "0x742d35Cc6634C0532925a3b844Bc9e7595f2bD18",
"txn_in": "0xabc123def456789...",
"txn_out": "0xdef456abc789012...",
"value_coin": "100.000000",
"value_forwarded_coin": "98.500000",
"fee_percent": "1.50",
"fee_coin": "1.500000",
"chain_ticker": "bsc",
"symbol": "USDT",
"confirmations": 15,
"result": "done"
}
200 with the body containing *ok* to acknowledge receipt. Any other response triggers a retry.Signature Verification
Every callback includes an X-CryptPay-Signature header containing an RSA-SHA256 signature. Use our public key to verify that the callback was sent by CryptPay and has not been tampered with.
How it works
1. Fetch CryptPay's public key from the /api/pubkey endpoint (cache it — it rarely changes).
2. Determine the signed data:
| Callback Type | Data that was signed |
|---|---|
| GET | The full callback URL including all query parameters |
| POST (JSON) | The raw JSON request body |
| POST (form) | The URL-encoded form body |
3. Verify the X-CryptPay-Signature header (base64-encoded) against the signed data using RSA-SHA256.
Verification Examples
// Node.js
const crypto = require('crypto');
function verifySignature(publicKeyPem, data, signatureBase64) {
const verifier = crypto.createVerify('SHA256');
verifier.update(data);
return verifier.verify(publicKeyPem, signatureBase64, 'base64');
}
// For JSON POST callbacks:
app.post('/payment-webhook', (req, res) => {
const signature = req.headers['x-cryptpay-signature'];
const rawBody = JSON.stringify(req.body);
if (!verifySignature(PUBLIC_KEY, rawBody, signature)) {
return res.status(401).send('Invalid signature');
}
// Signature verified -- process payment
res.status(200).send('*ok*');
});
# PHP / Laravel
use Illuminate\Http\Request;
public function handlePayment(Request $request)
{
$signature = $request->header('X-CryptPay-Signature');
$rawBody = $request->getContent();
$publicKey = openssl_pkey_get_public($publicKeyPem);
$valid = openssl_verify(
$rawBody,
base64_decode($signature),
$publicKey,
OPENSSL_ALGO_SHA256
) === 1;
if (!$valid) {
return response('Invalid signature', 401);
}
// Signature verified -- process payment
return response('*ok*', 200);
}
X-CryptPay-Signature header.Callback Retry Logic
If your callback URL doesn't return a successful response, CryptPay retries with escalating intervals:
| Attempt | Delay | Cumulative |
|---|---|---|
| 1 | Immediate | 0 |
| 2 | 5 min | 5 min |
| 3 | 10 min | 15 min |
| 4 | 15 min | 30 min |
| 5 | 20 min | 50 min |
After 5 failed attempts, the callback is marked as FAILED.
Public Key
Retrieve CryptPay's RSA public key for verifying webhook signatures.
Returns the PEM-encoded public key as text/plain. Cache this key on your end — it only changes if the operator regenerates it.
Response
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...
-----END PUBLIC KEY-----
Returns HTTP 503 if signing keys have not been configured yet.
Health Check
Returns {"status":"ok"} if the service is running.
Error Codes
| Code | Meaning |
|---|---|
| 200 | Success |
| 400 | Bad Request — invalid or missing parameters |
| 404 | Not Found — invalid chain or ticker |
| 422 | Validation Error — check the errors object for details |
| 500 | Internal Server Error |
| 503 | Service Unavailable — system is temporarily degraded |
Error Response Format
{
"status": "error",
"error": "A destination address is required.",
"errors": {
"address_out": ["A destination address is required."]
}
}
Integration Guide
Quick Start (3 Steps)
1. Create a payment address when your customer initiates checkout:
POST /api/bsc/usdt/create
{
"callback_url": "https://yoursite.com/payment-webhook",
"address_out": "0xYOUR_WALLET_ADDRESS",
"post": 1,
"json": 1
}
2. Display the deposit address (address_in from the response) to your customer. Optionally show a QR code.
3. Handle the callback when the payment is confirmed:
// Node.js example
app.post('/payment-webhook', (req, res) => {
const { txn_in, value_forwarded_coin, result } = req.body;
if (result === 'done') {
// Payment confirmed — credit the customer
markOrderPaid(txn_in, value_forwarded_coin);
}
res.status(200).send('*ok*');
});
# PHP / Laravel example
public function handlePayment(Request $request)
{
if ($request->input('result') === 'done') {
// Payment confirmed — credit the customer
Order::markPaid(
$request->input('txn_in'),
$request->input('value_forwarded_coin')
);
}
return response('*ok*', 200);
}
txn_in hash against the blockchain explorer before crediting high-value transactions.