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"}'

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

EventDescription
payment.succeededA payment was successfully processed
payment.failedA payment attempt failed
payment.refundedA payment was refunded
subscription.createdA new subscription was created
subscription.renewedA subscription was renewed
subscription.canceledA subscription was canceled
subscription.pausedA subscription was paused
subscription.resumedA subscription was resumed
subscription.past_dueA subscription became past due
invoice.createdA new invoice was generated
invoice.paidAn invoice was paid
invoice.voidedAn 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 updates
  • POST /webhooks/flutterwave - Flutterwave payment updates
  • POST /webhooks/paystack - Paystack payment updates
  • POST /webhooks/mpesa - M-Pesa payment updates

Configure these URLs in your payment provider dashboards.

Copyright © 2026