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​