Callbacks & Webhooks

Mercuryo sends a POST request to your callback URL every time a transaction status changes. Callbacks are the recommended way to track transaction states.

Setup

  1. Sign in to the Dashboard.
  2. Go to Widgets → select your widget.
  3. Fill in the Callback URL field with your server endpoint.
  4. Copy the Sign Key — you'll need it to verify incoming callbacks.

Go to Widget Callbacks to browse callback history, resend a callback, or send a test callback.


Callback Signature Verification

Each callback includes an X-Signature header containing an HMAC SHA-256 hash of the raw JSON body, generated using your Sign Key.

Important: Use the complete raw JSON body as input — do not extract individual fields from it. Remove all whitespace from the raw body before computing the hash. Different JSON parsers may format whitespace differently, which causes verification failures.

JavaScript

const crypto = require('crypto');

function verifyCallbackSignature(rawBody, signature, signKey) {
  const cleanBody = rawBody.replace(/\s/g, '');
  const hmac = crypto.createHmac('sha256', signKey);
  const calculated = hmac.update(cleanBody).digest('hex');
  return calculated === signature;
}

Python

import hmac
import hashlib

def verify_callback_signature(raw_body: str, signature: str, sign_key: str) -> bool:
    clean_body = ''.join(raw_body.split())
    calculated = hmac.new(sign_key.encode(), clean_body.encode(), hashlib.sha256).hexdigest()
    return calculated == signature

Go

import (
    "crypto/hmac"
    "crypto/sha256"
    "encoding/hex"
    "strings"
)

func verifyCallbackSignature(rawBody, signature, signKey string) bool {
    cleanBody := strings.Join(strings.Fields(rawBody), "")
    h := hmac.New(sha256.New, []byte(signKey))
    h.Write([]byte(cleanBody))
    return hex.EncodeToString(h.Sum(nil)) == signature
}

Callback Delivery & Retry Logic

Mercuryo considers a callback successfully delivered when your server responds with HTTP 200. For any other response code, the system retries automatically:

Attempt Delay
1st retry 60 seconds
2nd retry 120 seconds
3rd retry 240 seconds
Nth retry 2^(N−1) × 60 seconds (N = attempt number, starting at 1)
Maximum interval 4 hours
After reaching max interval Every 4 hours for 3 days
Total retry period 3 days

You can also manually resend callbacks from the Dashboard.


Transaction Callback Payload

For the full payload schema and examples for all transaction types, see Callback Reference.


Identifying Transaction Types

In callbacks, transactions are identified by a combination of type and payment_method fields. See Transaction Types & Statuses for the full reference table.

Note: Spend Card event callbacks (card status changes, card top-ups, card payments) use a separate callback URL and payload format. See Spend Card → Event Callbacks.