Webhooks

Receive real-time notifications when payment statuses change.

If you provide a callback_url when creating a payment, we will send a POST request to that URL when the payment status changes.

Payload

POST to your callback_url
{
  "payment_id": "vx_a1b2c3d4e5f6a1b2c3d4e5f6_1a2b3c4d",
  "amount": "100.00",
  "currency": "EUR",
  "status": "success",
  "links": [
    {
      "method": "X1",
      "status": "success",
      "amount": "100.00"
    }
  ],
  "updated_at": "2026-03-09T12:05:30.000Z"
}

Signature Verification

Every webhook includes an X-Signature header containing an HMAC-SHA256 signature of the request body. Verify it to ensure the webhook is authentic.

Verification — Node.js
const crypto = require('crypto');

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

// Usage in Express:
app.post('/webhook', (req, res) => {
  const sig = req.headers['x-signature'];
  const raw = req.body; // raw string, not parsed JSON
  if (!verify(raw, sig, YOUR_WEBHOOK_SECRET)) {
    return res.status(403).send('Invalid signature');
  }
  // Process webhook...
  res.status(200).send('OK');
});
Verification — Python
import hmac, hashlib

def verify(body: bytes, signature: str, secret: str) -> bool:
    expected = hmac.new(
        secret.encode(),
        body,
        hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, signature)

Retry Policy

ConditionBehavior
Your server returns 2xxDelivered successfully, no retries
Your server returns non-2xx or times outRetries up to 10 times with exponential backoff (5s, 10s, 20s...)
Your endpoint should respond within 10 seconds and return 200. Process the webhook asynchronously if needed.