Skip to main content

Webhooks Overview

Webhooks enable real-time notifications when events occur in your Azotte account, allowing you to build responsive integrations.

How Webhooks Work

Azotte Platform              Your Server
│ │
[Event Occurs] │
│ │
│─── HTTP POST ──────▶│
│ (Event Data) │
│ │
│◀─── 200 OK ────────│
│ │

Common Event Types

Subscription Events

  • subscription.created - New subscription activated
  • subscription.updated - Subscription details changed
  • subscription.cancelled - Subscription cancelled
  • subscription.renewed - Billing cycle renewed
  • subscription.trial_ending - Trial period ending soon

Payment Events

  • payment.succeeded - Payment processed successfully
  • payment.failed - Payment attempt failed
  • payment.refunded - Refund issued
  • payment.disputed - Chargeback initiated

Customer Events

  • customer.created - New customer registered
  • customer.updated - Customer information changed
  • customer.deleted - Customer account removed

Webhook Configuration

Setting Up Endpoints

  1. Create an endpoint on your server
  2. Add the endpoint URL in Azotte Portal
  3. Select which events to receive
  4. Test the webhook configuration

Endpoint Requirements

  • HTTPS only for security
  • Return 200 status to confirm receipt
  • Process within 30 seconds to avoid timeout
  • Idempotent handling for duplicate events

Event Structure

Standard Event Format

{
"id": "evt_1234567890",
"type": "subscription.created",
"created": 1678886400,
"data": {
"object": {
"id": "sub_1234567890",
"customer": "cus_1234567890",
"status": "active",
"current_period_start": 1678886400,
"current_period_end": 1681564800
}
},
"request": {
"id": "req_1234567890",
"idempotency_key": null
}
}

Security

Webhook Signatures

// Verify webhook signature
const crypto = require('crypto');

function verifySignature(payload, signature, secret) {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');

return signature === `sha256=${expectedSignature}`;
}

Best Practices

  • Always verify webhook signatures
  • Use HTTPS for webhook endpoints
  • Implement proper error handling
  • Log webhook events for debugging

Handling Webhooks

Basic Webhook Handler

const express = require('express');
const app = express();

app.post('/webhooks/azotte', express.raw({type: 'application/json'}), (req, res) => {
const signature = req.headers['azotte-signature'];
const payload = req.body;

// Verify signature
if (!verifySignature(payload, signature, process.env.WEBHOOK_SECRET)) {
return res.status(401).send('Invalid signature');
}

const event = JSON.parse(payload);

// Handle the event
switch (event.type) {
case 'subscription.created':
handleSubscriptionCreated(event.data.object);
break;
case 'payment.failed':
handlePaymentFailed(event.data.object);
break;
default:
console.log(`Unhandled event type: ${event.type}`);
}

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

Retry Policy

Automatic Retries

  • First retry: 1 minute after failure
  • Second retry: 5 minutes after first retry
  • Third retry: 15 minutes after second retry
  • Final retry: 1 hour after third retry

Failure Handling

  • Non-2xx responses trigger retries
  • Timeouts (>30 seconds) trigger retries
  • Connection errors trigger retries
  • After final retry, webhook is marked as failed

Testing Webhooks

Local Development

# Use ngrok to expose local server
ngrok http 3000

# Use the ngrok URL in webhook configuration
# https://abc123.ngrok.io/webhooks/azotte

Test Events

# Send test webhook from Azotte Portal
# Or use API to trigger test events
curl -X POST https://api.azotte.com/v1/webhooks/test \
-H "x-api-key: sk_dev_..." \
-H "x-tn: tenant_..." \
-d '{"type": "subscription.created"}'

Monitoring

Webhook Logs

  • Delivery attempts and status
  • Response codes and timing
  • Error messages and retries
  • Success/failure rates

Alerting

  • Failed webhook deliveries
  • High error rates
  • Endpoint timeouts
  • Signature verification failures

Next Steps