Webhook Setup & Configuration

Receive real-time payment notifications via HTTP POST callbacks

Webhooks allow CryptoGate to push payment events to your server the moment they occur — no polling required. When a payment completes, expires, or detects a partial payment, we send a signed HTTP POST to your configured endpoint.

Creating a Webhook

  1. Go to Dashboard → Webhooks → Add Endpoint
  2. Enter your endpoint URL (must be publicly accessible HTTPS)
  3. Select the events you want to receive
  4. Copy your webhook secret — it is only shown once
Save your webhook secret immediately.

The secret is shown only at creation time. If you lose it, you must regenerate it from the dashboard, which will invalidate the old secret.

Webhook Request Headers

Header Description
X-CryptoGate-Signature HMAC-SHA256 signature of the raw request body, formatted as sha256=<hex>
X-CryptoGate-Event Event type, e.g. payment.completed
X-Webhook-ID Unique delivery ID, e.g. WHK-XXXXXXXX. Use for idempotency.
Content-Type application/json

Webhook Payload

Webhook POST body
{
  "event": "payment.completed",
  "timestamp": "2026-03-08T10:30:00Z",
  "transaction_id": "MTX-A1B2C3D4",
  "status": "completed",
  "currency_crypto": "BTC",
  "amount_fiat": "25.00",
  "amount_crypto": "0.00025431"
}

Responding to Webhooks

Your endpoint must return HTTP 200 within 10 seconds. Any other status code or a timeout is treated as a delivery failure. Failed deliveries are retried with exponential backoff.

Always verify signatures.

Never process a webhook without first verifying the X-CryptoGate-Signature header. See Signature Verification.

Example Receiver (Node.js)

Express.js webhook handler
import crypto from 'crypto';
import express from 'express';

const app = express();

// IMPORTANT: use raw body for signature verification
app.post('/webhooks/cryptogate', express.raw({ type: 'application/json' }), (req, res) => {
  const sig = req.headers['x-cryptogate-signature'] || '';
  const secret = process.env.WEBHOOK_SECRET;

  const expected = 'sha256=' + crypto
    .createHmac('sha256', secret)
    .update(req.body)
    .digest('hex');

  if (sig !== expected) {
    return res.status(400).send('Invalid signature');
  }

  const event = JSON.parse(req.body);

  switch (event.event) {
    case 'payment.completed':
      // Fulfil the order
      console.log('Payment completed for', event.transaction_id);
      break;
    case 'payment.partial':
      console.log('Partial payment for', event.transaction_id);
      break;
    case 'payment.expired':
      console.log('Transaction expired:', event.transaction_id);
      break;
  }

  res.status(200).send('OK');
});