Guides
Webhooks
Set up real-time webhook notifications for billing events.
Webhooks
NovaBilling sends webhook notifications to your application when events occur (payments, subscription changes, etc.).
Setup
Configure your webhook URL in your tenant settings:
curl -X PATCH http://localhost:3000/api/tenants/me \
-H "Authorization: Bearer <jwt_token>" \
-H "Content-Type: application/json" \
-d '{"webhookUrl": "https://your-app.com/webhooks/novabilling"}'
import { NovaBillingClient } from 'novabilling';
const client = new NovaBillingClient({ token: 'sk_live_a1b2c3d4...' });
// Set via tenant settings (requires JWT auth)
await client.tenants.updateMe({
webhookUrl: 'https://your-app.com/webhooks/novabilling'
});
from novabilling import NovaBilling
client = NovaBilling(token="sk_live_a1b2c3d4...")
client.tenants.update_me(
webhook_url="https://your-app.com/webhooks/novabilling"
)
Event Payload
All webhook events follow this structure:
{
"event": "payment.succeeded",
"timestamp": "2025-01-15T10:30:00Z",
"data": {
"id": "pay_abc123",
"invoiceId": "inv_xyz789",
"amount": 180000,
"currency": "UGX",
"provider": "STRIPE",
"status": "SUCCEEDED"
}
}
Event Types
| Event | Description |
|---|---|
payment.succeeded | A payment was successfully processed |
payment.failed | A payment attempt failed |
payment.refunded | A payment was refunded |
subscription.created | A new subscription was created |
subscription.renewed | A subscription was renewed |
subscription.canceled | A subscription was canceled |
subscription.paused | A subscription was paused |
subscription.resumed | A subscription was resumed |
subscription.past_due | A subscription became past due |
invoice.created | A new invoice was generated |
invoice.paid | An invoice was paid |
invoice.voided | An invoice was voided |
Handling Webhooks
Example webhook handler in Express.js:
import express from 'express';
const app = express();
app.post('/webhooks/novabilling', express.json(), (req, res) => {
const { event, data } = req.body;
switch (event) {
case 'payment.succeeded':
console.log(`Payment ${data.id} succeeded: ${data.currency} ${data.amount}`);
// Update your records
break;
case 'subscription.canceled':
console.log(`Subscription ${data.id} canceled`);
// Revoke access
break;
default:
console.log(`Unhandled event: ${event}`);
}
// Always respond with 200 to acknowledge receipt
res.status(200).json({ received: true });
});
Retry Policy
If your webhook endpoint returns a non-2xx status code or times out (30 seconds), NovaBilling will retry delivery:
- Attempt 1: Immediate
- Attempt 2: After 5 minutes
- Attempt 3: After 30 minutes
- Attempt 4: After 2 hours
- Attempt 5: After 24 hours
After 5 failed attempts, the webhook is marked as failed and logged in your webhook history.
Inbound Webhooks (Payment Providers)
NovaBilling also receives webhooks from payment providers to update payment statuses. These are handled at:
POST /webhooks/stripe- Stripe payment updatesPOST /webhooks/flutterwave- Flutterwave payment updatesPOST /webhooks/paystack- Paystack payment updatesPOST /webhooks/mpesa- M-Pesa payment updates
Configure these URLs in your payment provider dashboards.