API Status Support Dashboard

Webhooks

Receive real-time notifications about events in your AuxVault account.


Overview

Webhooks allow AuxVault to push real-time notifications to your server when important events occur, such as:

Instead of polling our API, webhooks push data to you instantly when events happen.


How Webhooks Work

  1. Event occurs (e.g., transaction approved)
  2. AuxVault sends HTTP POST to your webhook URL
  3. Your server responds with 200 OK
  4. If failed, AuxVault retries with exponential backoff

Setup

1. Create a Webhook Endpoint

Create an endpoint on your server to receive webhook notifications:

// Express.js example
app.post('/webhooks/auxvault', async (req, res) => {
  const signature = req.headers['x-auxvault-signature'];
  const payload = req.body;
  
  // Verify signature
  if (!verifySignature(payload, signature)) {
    return res.status(401).send('Invalid signature');
  }
  
  // Process event
  try {
    await handleWebhookEvent(payload);
    res.status(200).send('OK');
  } catch (error) {
    console.error('Webhook error:', error);
    res.status(500).send('Error processing webhook');
  }
});

2. Register Your Webhook URL

Endpoint: POST /api/v1/webhooks

curl -X POST https://api.auxvault.com/api/v1/webhooks \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "X-Tenant-ID: your-tenant-id" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://yoursite.com/webhooks/auxvault",
    "events": [
      "transaction.approved",
      "transaction.declined",
      "refund.processed",
      "subscription.payment_succeeded",
      "subscription.payment_failed"
    ],
    "description": "Production webhook"
  }'

Response:

{
  "success": true,
  "data": {
    "id": "webhook_abc123",
    "url": "https://yoursite.com/webhooks/auxvault",
    "events": ["transaction.approved", "transaction.declined", ...],
    "secret": "whsec_1234567890abcdef...",
    "status": "active",
    "createdAt": "2026-01-28T00:00:00Z"
  }
}

⚠️ Save the secret! You'll need it to verify webhook signatures.


Webhook Payload Structure

All webhooks follow this format:

{
  "id": "evt_abc123",
  "type": "transaction.approved",
  "createdAt": "2026-01-28T12:34:56Z",
  "data": {
    // Event-specific data
  },
  "tenantId": "your-tenant-id",
  "merchantId": "merchant-123"
}

Fields

Field Type Description
id string Unique event ID
type string Event type (e.g., "transaction.approved")
createdAt datetime When the event occurred
data object Event-specific data
tenantId string Your tenant ID
merchantId string Associated merchant ID

Event Types

Transaction Events

transaction.approved

Sent when a transaction is approved.

{
  "id": "evt_001",
  "type": "transaction.approved",
  "createdAt": "2026-01-28T12:34:56Z",
  "data": {
    "transactionId": "txn_abc123",
    "type": "sale",
    "amount": 150.75,
    "currency": "USD",
    "authCode": "123456",
    "card": {
      "brand": "Visa",
      "last4": "1111"
    },
    "customer": {
      "email": "customer@example.com"
    }
  }
}

transaction.declined

Sent when a transaction is declined.

{
  "id": "evt_002",
  "type": "transaction.declined",
  "createdAt": "2026-01-28T12:35:00Z",
  "data": {
    "transactionId": "txn_declined_123",
    "type": "sale",
    "amount": 50.00,
    "declineCode": "insufficient_funds",
    "declineReason": "Insufficient funds",
    "card": {
      "last4": "2222"
    }
  }
}

transaction.voided

Sent when a transaction is voided.

transaction.settled

Sent when a transaction is settled.


Refund Events

refund.processed

Sent when a refund is processed.

{
  "id": "evt_003",
  "type": "refund.processed",
  "createdAt": "2026-01-28T13:00:00Z",
  "data": {
    "refundId": "ref_abc123",
    "transactionId": "txn_original_123",
    "amount": 150.75,
    "status": "approved",
    "reason": "Customer request"
  }
}

refund.declined

Sent when a refund is declined.


Subscription Events

subscription.created

Sent when a subscription is created.

subscription.payment_succeeded

Sent when a recurring payment succeeds.

{
  "id": "evt_004",
  "type": "subscription.payment_succeeded",
  "createdAt": "2026-01-28T14:00:00Z",
  "data": {
    "subscriptionId": "sub_abc123",
    "transactionId": "txn_recurring_123",
    "amount": 29.99,
    "nextPaymentDate": "2026-02-28T00:00:00Z",
    "customer": {
      "email": "subscriber@example.com"
    }
  }
}

subscription.payment_failed

Sent when a recurring payment fails.

subscription.cancelled

Sent when a subscription is cancelled.

subscription.expired

Sent when a subscription expires.


Invoice Events

invoice.paid

Sent when an invoice is paid.

{
  "id": "evt_005",
  "type": "invoice.paid",
  "createdAt": "2026-01-28T15:00:00Z",
  "data": {
    "invoiceId": "inv_abc123",
    "transactionId": "txn_payment_123",
    "amountPaid": 100.00,
    "amountDue": 0.00,
    "status": "paid",
    "customer": {
      "email": "customer@example.com"
    }
  }
}

invoice.partially_paid

Sent when a partial payment is made on an invoice.

invoice.overdue

Sent when an invoice becomes overdue.


Chargeback Events

chargeback.received

Sent when a chargeback is received.

{
  "id": "evt_006",
  "type": "chargeback.received",
  "createdAt": "2026-01-28T16:00:00Z",
  "data": {
    "chargebackId": "cb_abc123",
    "transactionId": "txn_disputed_123",
    "amount": 150.75,
    "reason": "fraudulent",
    "dueDate": "2026-02-15T00:00:00Z"
  }
}

chargeback.won

Sent when you win a chargeback.

chargeback.lost

Sent when you lose a chargeback.


Signature Verification

Always verify webhook signatures to ensure requests are from AuxVault.

How It Works

AuxVault signs each webhook with HMAC SHA-256 using your webhook secret. The signature is sent in the X-AuxVault-Signature header.

Node.js Example

const crypto = require('crypto');

function verifySignature(payload, signature, secret) {
  const computedSignature = crypto
    .createHmac('sha256', secret)
    .update(JSON.stringify(payload))
    .digest('hex');
    
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(computedSignature)
  );
}

// In your webhook handler
app.post('/webhooks/auxvault', (req, res) => {
  const signature = req.headers['x-auxvault-signature'];
  const secret = process.env.WEBHOOK_SECRET;
  
  if (!verifySignature(req.body, signature, secret)) {
    return res.status(401).send('Invalid signature');
  }
  
  // Process webhook
  res.status(200).send('OK');
});

Python Example

import hmac
import hashlib
import json

def verify_signature(payload, signature, secret):
    computed_signature = hmac.new(
        secret.encode(),
        json.dumps(payload).encode(),
        hashlib.sha256
    ).hexdigest()
    
    return hmac.compare_digest(signature, computed_signature)

# In your webhook handler
@app.route('/webhooks/auxvault', methods=['POST'])
def webhook():
    signature = request.headers.get('X-AuxVault-Signature')
    secret = os.environ['WEBHOOK_SECRET']
    
    if not verify_signature(request.json, signature, secret):
        return 'Invalid signature', 401
    
    # Process webhook
    return 'OK', 200

Handling Webhooks

Best Practices

  1. Respond quickly - Return 200 OK immediately
  2. Process asynchronously - Queue heavy processing
  3. Be idempotent - Handle duplicate events gracefully
  4. Verify signatures - Always verify before processing
  5. Log events - Keep audit trail of all webhooks
  6. Handle retries - Use event IDs to deduplicate

Example Handler

const processedEvents = new Set();

async function handleWebhookEvent(payload) {
  const { id, type, data } = payload;
  
  // Check if already processed (idempotency)
  if (processedEvents.has(id)) {
    console.log(`Event ${id} already processed`);
    return;
  }
  
  // Mark as processed
  processedEvents.add(id);
  
  // Route to appropriate handler
  switch (type) {
    case 'transaction.approved':
      await handleTransactionApproved(data);
      break;
      
    case 'transaction.declined':
      await handleTransactionDeclined(data);
      break;
      
    case 'subscription.payment_failed':
      await handleSubscriptionFailed(data);
      break;
      
    case 'invoice.paid':
      await handleInvoicePaid(data);
      break;
      
    case 'chargeback.received':
      await handleChargebackReceived(data);
      break;
      
    default:
      console.log(`Unhandled event type: ${type}`);
  }
}

async function handleTransactionApproved(data) {
  // Send confirmation email
  await sendEmail(data.customer.email, 'Payment Successful', ...);
  
  // Update database
  await db.updateOrderStatus(data.transactionId, 'paid');
  
  // Trigger fulfillment
  await fulfillOrder(data.transactionId);
}

Retry Logic

If your webhook endpoint fails (non-200 response), AuxVault will retry:

Attempt Delay
1 Immediate
2 1 minute
3 5 minutes
4 30 minutes
5 2 hours
6 12 hours
7+ 24 hours

After 7 days of failed attempts, the webhook will be marked as failed.


Testing Webhooks

Local Development with ngrok

# Install ngrok
npm install -g ngrok

# Start your local server
node server.js  # Running on localhost:3000

# Create tunnel
ngrok http 3000

# Use the ngrok URL as your webhook URL
# https://abc123.ngrok.io/webhooks/auxvault

Test Events

Trigger test events from the dashboard or API:

curl -X POST https://api.auxvault.com/api/v1/webhooks/webhook_abc123/test \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "X-Tenant-ID: your-tenant-id" \
  -d '{"eventType": "transaction.approved"}'

Managing Webhooks

List Webhooks

curl https://api.auxvault.com/api/v1/webhooks \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "X-Tenant-ID: your-tenant-id"

Update Webhook

curl -X PUT https://api.auxvault.com/api/v1/webhooks/webhook_abc123 \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "X-Tenant-ID: your-tenant-id" \
  -d '{
    "events": ["transaction.approved", "transaction.declined"],
    "status": "active"
  }'

Delete Webhook

curl -X DELETE https://api.auxvault.com/api/v1/webhooks/webhook_abc123 \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "X-Tenant-ID: your-tenant-id"

Security Best Practices

✅ DO:

❌ DON'T:


Troubleshooting

Webhook Not Received

  1. Check webhook is active in dashboard
  2. Verify URL is correct and accessible
  3. Check firewall/IP whitelist settings
  4. Review webhook logs in dashboard

Signature Verification Fails

  1. Ensure you're using the correct secret
  2. Verify you're signing the raw JSON body
  3. Check for extra whitespace/formatting
  4. Make sure charset is UTF-8

Webhooks Timing Out

  1. Respond with 200 OK immediately
  2. Queue processing for async handling
  3. Don't wait for external services
  4. Keep response time < 5 seconds

Complete Event Reference

View all webhook events →


Next Steps


Need help? Contact support@auxvault.com