webhook

Webhooks

Receive real-time HTTP notifications when payment events occur.

schedule

Near-instant

Seconds after confirmation

replay

Auto-retry

3 attempts, exponential backoff

verified_user

HMAC signed

SHA-256 signature header

Events

EventDescription
payment.createdPayment was created
payment.confirmedDeposit received and confirmed
payment.expiredPayment expired (15 min timeout)

HTTP Headers

HeaderValue
Content-Typeapplication/json
X-PayCrypt-EventEvent name (e.g. payment.confirmed)
X-PayCrypt-SignatureHMAC SHA-256 signature (if webhook secret is set)

Payload Examples

jsonpayment.created
{
  "event": "payment.created",
  "payment_id": "9515b51e-0279-4294-805d-91f7762914c3",
  "order_id": "123",
  "status": "pending",
  "amount": 50,
  "coin": "USDT",
  "network": "ethereum",
  "currency": "USD",
  "deposit_address": "0x742d35Cc6634C0532925a3b844Bc9e7595f2bD68",
  "expires_at": "2026-02-20T10:10:46.000Z",
  "created_at": "2026-02-20T09:55:46.541Z"
}
jsonpayment.confirmed
{
  "event": "payment.confirmed",
  "payment_id": "9515b51e-0279-4294-805d-91f7762914c3",
  "order_id": "123",
  "status": "confirmed",
  "amount": 50,
  "amount_received": 50.02,
  "amount_received_usd": 50.02,
  "commission_rate_percent": 0.2,
  "commission_amount_usd": 0.10,
  "amount_net_usd": 49.92,
  "coin": "USDT",
  "network": "ethereum",
  "currency": "USD",
  "deposit_address": "0x742d35Cc6634C0532925a3b844Bc9e7595f2bD68",
  "tx_hash": "0x8a2f7b3c9d1e5f6a...",
  "confirmations": 12,
  "confirmed_at": "2026-02-20T10:02:15.844Z",
  "customer_email": "customer@example.com",
  "metadata": { "plan": "pro" }
}
jsonpayment.expired
{
  "event": "payment.expired",
  "payment_id": "9515b51e-0279-4294-805d-91f7762914c3",
  "order_id": "123",
  "status": "expired",
  "amount": 50,
  "coin": "USDT",
  "network": "ethereum",
  "currency": "USD",
  "deposit_address": "0x742d35Cc6634C0532925a3b844Bc9e7595f2bD68",
  "expires_at": "2026-02-20T10:10:46.000Z",
  "created_at": "2026-02-20T09:55:46.541Z"
}

Signature Verification

If you set a webhook secret in Dashboard → Integrations, every webhook includes an X-PayCrypt-Signature header. Verify it with HMAC SHA-256.

javascriptNode.js
const crypto = require('crypto');

function verifyWebhookSignature(rawBody, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(rawBody)
    .digest('hex');
  
  const sig = signature.replace('sha256=', '');
  return crypto.timingSafeEqual(
    Buffer.from(sig, 'hex'),
    Buffer.from(expected, 'hex')
  );
}

// Express handler
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
  const signature = req.headers['x-paycrypt-signature'];
  const isValid = verifyWebhookSignature(req.body, signature, 'your_secret');
  
  if (!isValid) return res.status(401).send('Invalid signature');
  
  const event = JSON.parse(req.body.toString());
  console.log('Event:', event.event, event.payment_id);
  res.status(200).send('OK');
});
phpPHP
<?php
$rawBody = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_PAYCRYPT_SIGNATURE'] ?? '';
$secret = 'your_webhook_secret';

$expected = hash_hmac('sha256', $rawBody, $secret);
$sig = str_replace('sha256=', '', $signature);

if (!hash_equals($expected, $sig)) {
    http_response_code(401);
    die('Invalid signature');
}

$event = json_decode($rawBody, true);
// Handle $event['event'], $event['payment_id'], etc.
http_response_code(200);
echo 'OK';

Retry Policy

If your endpoint returns a non-2xx status code or times out, PayCrypt retries with exponential backoff:

AttemptDelay
1st attemptImmediate
2nd attempt~30 seconds
3rd attempt~2 minutes
info
Each delivery attempt is recorded and visible in Dashboard → Integrations → Deliveries.