← Back to CryptPay

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.

Ethereum BSC Polygon Bitcoin Solana (soon) TRON (soon)

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

ChainTickerTokensConfirmationsSpeed
EthereumethNative ETH + ERC-2012~2-4 min
BNB ChainbscNative BNB + BEP-2015~45s
PolygonpolygonNative POL + ERC-20128~4-6 min
BitcoinbitcoinNative BTC2~20 min
Coming soon: Solana (SPL tokens) and TRON (TRC-20 tokens) support is in development.

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.

POST GET /api/{chain}/{token}/create

Alternative format: /api/{ticker}/create — e.g., /api/eth/create, /api/bsc/usdt/create

Parameters

ParameterTypeDescription
callback_url requiredstringURL to receive payment notifications.
address_out requiredstringYour wallet address to receive forwarded payments. Must match the chain format.
pending optional0 | 1Receive a callback on pending (unconfirmed) deposits. Default: 0
confirmations optionalintegerOverride required confirmations (1–100). Default: chain-specific value.
priority optionalstringGas priority: slow, default, fast
multi_token optional0 | 1Accept any supported token on this address. Default: 0
post optional0 | 1Send callback as POST body instead of GET params. Default: 0
json optional0 | 1Send 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.

GET /api/{ticker}/logs?callback_url={url}&address_out={addr}
ParameterTypeDescription
callback_url requiredstringYour callback URL (identifies the payment address)
address_out requiredstringYour receiving address

Payment Info

Get current status and details for a specific payment address.

GET /api/{ticker}/info?callback_url={url}&address_out={addr}
ParameterTypeDescription
callback_url requiredstringYour callback URL
address_out requiredstringYour receiving address

List Cryptocurrencies

List all supported chains and tokens.

GET /api/cryptocurrencies

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.

FieldTypeDescription
uuidstringUnique callback identifier
address_instringCustomer deposit address
address_outstringYour receiving address
txn_instringDeposit transaction hash
txn_outstringForwarding transaction hash
value_coinstringOriginal deposit amount
value_forwarded_coinstringAmount forwarded to you (after fees)
fee_percentstringService fee percentage applied
fee_coinstringFee amount deducted
chain_tickerstringChain identifier (eth, bsc, bitcoin, etc.)
symbolstringToken symbol (ETH, USDT, BTC)
confirmationsintegerBlock confirmations at callback time
resultstringdone 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"
}
Important: Your callback endpoint must return HTTP 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 TypeData that was signed
GETThe 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);
}
Note: Signature verification is optional but strongly recommended for production integrations. If CryptPay's signing keys have not been configured, callbacks are sent without the X-CryptPay-Signature header.

Callback Retry Logic

If your callback URL doesn't return a successful response, CryptPay retries with escalating intervals:

AttemptDelayCumulative
1Immediate0
25 min5 min
310 min15 min
415 min30 min
520 min50 min

After 5 failed attempts, the callback is marked as FAILED.

Public Key

Retrieve CryptPay's RSA public key for verifying webhook signatures.

GET /api/pubkey

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

GET /api/health

Returns {"status":"ok"} if the service is running.

Error Codes

CodeMeaning
200Success
400Bad Request — invalid or missing parameters
404Not Found — invalid chain or ticker
422Validation Error — check the errors object for details
500Internal Server Error
503Service 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);
}
Security: Always verify callbacks server-side. Check the txn_in hash against the blockchain explorer before crediting high-value transactions.