Skip to main content
POST
/
v1
/
webhooks
curl -X POST "https://api.unipay.com/v1/webhooks" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-app.com/webhooks/unipay",
    "events": [
      "transaction.completed",
      "transaction.failed"
    ],
    "secret": "your-webhook-secret-key"
  }'
{
  "webhookId": "wh_1234567890abcdef",
  "url": "https://your-app.com/webhooks/unipay",
  "events": [
    "transaction.completed",
    "transaction.failed"
  ],
  "createdAt": "2026-04-22T12:40:00Z"
}
Register webhook endpoints to receive real-time notifications about transaction status changes. Webhooks are essential for tracking private mode transactions that may take 30-120 seconds to complete.

Request Body

url
string
required
Your webhook endpoint URL (must be HTTPS)
events
array
required
Array of event types to subscribe to:
  • transaction.pending
  • transaction.confirmed
  • transaction.completed
  • transaction.failed
secret
string
Secret key for webhook signature verification (recommended)

Response

webhookId
string
Unique webhook identifier
url
string
Your webhook endpoint URL
events
array
Subscribed event types
createdAt
string
Webhook creation timestamp (ISO 8601)
curl -X POST "https://api.unipay.com/v1/webhooks" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-app.com/webhooks/unipay",
    "events": [
      "transaction.completed",
      "transaction.failed"
    ],
    "secret": "your-webhook-secret-key"
  }'
{
  "webhookId": "wh_1234567890abcdef",
  "url": "https://your-app.com/webhooks/unipay",
  "events": [
    "transaction.completed",
    "transaction.failed"
  ],
  "createdAt": "2026-04-22T12:40:00Z"
}

Webhook Events

Event Types

transaction.pending

Transaction submitted to network

transaction.confirmed

Transaction confirmed on-chain

transaction.completed

Transaction fully processed (final state)

transaction.failed

Transaction failed or reverted

Event Payload

All webhook events include this payload structure:
{
  "event": "transaction.completed",
  "transactionId": "tx_abcdef1234567890",
  "timestamp": "2026-04-22T12:45:00Z",
  "data": {
    "transactionId": "tx_abcdef1234567890",
    "status": "completed",
    "mode": "private",
    "type": "send",
    "signature": "5VERv8NMvQakCcXn7JQVpMhHkPfft9kTrYpo9wqtKn5V...",
    "blockTime": 1640995200,
    "fee": "0.000005",
    "recipients": [
      {
        "address": "9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM",
        "amount": "100.0"
      }
    ]
  }
}

Webhook Security

Signature Verification

Webhooks include a signature header for verification:
X-Unipay-Signature: sha256=a8b7c6d5e4f3g2h1...
Verification Example:
const crypto = require('crypto');

function verifyWebhook(payload, signature, secret) {
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');
    
  const receivedSignature = signature.replace('sha256=', '');
  
  return crypto.timingSafeEqual(
    Buffer.from(expectedSignature, 'hex'),
    Buffer.from(receivedSignature, 'hex')
  );
}

// Usage
const isValid = verifyWebhook(
  req.body,
  req.headers['x-unipay-signature'],
  'your-webhook-secret-key'
);

Security Best Practices

1

Use HTTPS

Webhook URLs must use HTTPS for security
2

Verify Signatures

Always verify webhook signatures to prevent spoofing
3

Validate Payload

Check that transaction IDs match your records
4

Idempotency

Handle duplicate webhook deliveries gracefully

Webhook Endpoint Requirements

Response Requirements

Your webhook endpoint must:
  • Respond with HTTP 200 status code
  • Respond within 10 seconds
  • Return any response body (ignored)
// Express.js example
app.post('/webhooks/unipay', (req, res) => {
  const { event, transactionId, data } = req.body;
  
  // Verify signature
  if (!verifyWebhook(req.body, req.headers['x-unipay-signature'], secret)) {
    return res.status(401).send('Invalid signature');
  }
  
  // Process webhook
  console.log(`Transaction ${transactionId} is now ${data.status}`);
  
  // Respond with 200
  res.status(200).send('OK');
});

Retry Policy

Failed webhook deliveries are retried with exponential backoff:
AttemptDelayTotal Time
1Immediate0s
21 minute1m
35 minutes6m
415 minutes21m
51 hour1h 21m
66 hours7h 21m
After 6 failed attempts, webhook delivery is abandoned.

Testing Webhooks

Webhook Testing Tool

Use tools like ngrok for local development:
# Install ngrok
npm install -g ngrok

# Expose local server
ngrok http 3000

# Use the HTTPS URL for webhook registration
# https://abc123.ngrok.io/webhooks/unipay

Test Events

You can trigger test webhook events:
curl -X POST "https://api.unipay.com/v1/webhooks/wh_1234567890abcdef/test" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{"event": "transaction.completed"}'

Managing Webhooks

List Webhooks

curl -H "Authorization: Bearer YOUR_API_KEY" \
     https://api.unipay.com/v1/webhooks

Update Webhook

curl -X PUT "https://api.unipay.com/v1/webhooks/wh_1234567890abcdef" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "events": ["transaction.completed", "transaction.failed", "transaction.pending"]
  }'

Delete Webhook

curl -X DELETE "https://api.unipay.com/v1/webhooks/wh_1234567890abcdef" \
  -H "Authorization: Bearer YOUR_API_KEY"

Error Responses

error.code
string
Error code identifier
error.message
string
Human-readable error message
error.details
object
Additional error context

Common Errors

CodeDescription
INVALID_URLWebhook URL is not valid HTTPS
INVALID_EVENTSUnknown event types specified
URL_UNREACHABLECannot reach webhook URL during validation
WEBHOOK_LIMIT_EXCEEDEDToo many webhooks registered

Rate Limits

Webhook registration is subject to rate limits:
TierWebhooksRegistrations/Hour
Free310
Pro1050
Enterprise50200

Next Steps

Transaction Status

Learn about transaction status polling as an alternative

API Introduction

Review authentication and rate limiting details