Skip to content

Webhooks

BoxBilling sends webhook notifications when key events occur. Webhooks are delivered as HTTP POST requests with JSON payloads to your configured endpoints.

Terminal window
curl -X POST /v1/webhook_endpoints \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://yourapp.com/webhooks/boxbilling",
"signature_algo": "hmac"
}'

You can create multiple endpoints — each will receive all webhook events.

FieldTypeDescription
iduuidUnique endpoint identifier
urlstringDelivery URL (max 2048 chars)
signature_algostringSignature algorithm (default: hmac)
statusstringEndpoint status (active, inactive)
created_atdatetimeCreation timestamp
updated_atdatetimeLast update timestamp

You can update the URL, signature algorithm, or status of an existing endpoint:

Terminal window
curl -X PUT /v1/webhook_endpoints/{endpoint_id} \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://yourapp.com/webhooks/v2",
"status": "active"
}'
Terminal window
curl /v1/webhook_endpoints \
-H "Authorization: Bearer $API_KEY"

Supports skip, limit, and order_by query parameters.

EventTrigger
invoice.createdNew invoice generated
invoice.finalizedInvoice finalized and ready for payment
invoice.paidInvoice fully paid
invoice.voidedInvoice voided
EventTrigger
payment.createdPayment record created
payment.succeededPayment completed successfully
payment.failedPayment failed
EventTrigger
subscription.createdNew subscription created
subscription.startedSubscription activated
subscription.plan_changedPlan upgrade or downgrade applied
subscription.trial_endedTrial period expired
subscription.canceledSubscription canceled
subscription.terminatedSubscription terminated
EventTrigger
customer.createdNew customer created
customer.updatedCustomer record updated
EventTrigger
credit_note.createdCredit note created
credit_note.finalizedCredit note finalized
EventTrigger
wallet.createdWallet created
wallet.terminatedWallet terminated
wallet.transaction.createdWallet transaction recorded
EventTrigger
usage_threshold.crossedUsage threshold exceeded
EventTrigger
payment_request.createdDunning payment request created
payment_request.payment_succeededDunning payment succeeded
payment_request.payment_failedDunning payment failed

Each webhook delivery record contains full details about the event and delivery status:

FieldTypeDescription
iduuidUnique webhook ID
webhook_endpoint_iduuidTarget endpoint
webhook_typestringEvent type (e.g. invoice.finalized)
object_typestringEntity type (e.g. invoice)
object_iduuidEntity UUID
payloadobjectFull event payload
statusstringDelivery status (pending, succeeded, failed)
retriesintegerCurrent retry count
max_retriesintegerMaximum retry limit
last_retried_atdatetimeLast retry timestamp
http_statusintegerHTTP response code from endpoint
responsestringResponse body from endpoint
created_atdatetimeCreation timestamp
updated_atdatetimeLast update timestamp
{
"webhook_type": "invoice.finalized",
"object_type": "invoice",
"object_id": "550e8400-e29b-41d4-a716-446655440000",
"payload": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"invoice_number": "INV-20250115-0001",
"status": "finalized",
"total": 9900,
"currency": "USD"
}
}

Every webhook includes signature headers for verification:

HeaderDescription
X-Bxb-SignatureHMAC-SHA256 hex digest of the payload
X-Bxb-Signature-AlgorithmSignature algorithm (default: hmac)
X-Bxb-Webhook-IdUnique webhook delivery ID
import hmac
import hashlib
def verify_webhook(payload: bytes, signature: str, secret: str) -> bool:
expected = hmac.new(
secret.encode(),
payload,
hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, signature)
const crypto = require('crypto');
function verifyWebhook(payload, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signature)
);
}

Failed webhook deliveries are automatically retried with exponential backoff:

RetryDelay
1st2 minutes
2nd4 minutes
3rd8 minutes
4th16 minutes
5th32 minutes

Formula: delay = 2^retries minutes

The retry task runs every 5 minutes. After the maximum number of retries (default: 5), the webhook is marked as permanently failed.

StatusDescription
pendingQueued for delivery
succeededDelivered successfully (2xx response)
failedDelivery failed after all retries

Each delivery attempt is tracked individually with its own response details:

FieldTypeDescription
iduuidDelivery attempt ID
webhook_iduuidParent webhook
attempt_numberintegerSequential attempt number
http_statusintegerHTTP response code
response_bodystringResponse body text
successbooleanWhether the attempt succeeded
error_messagestringError details if failed
attempted_atdatetimeWhen the attempt was made
Terminal window
curl /v1/webhook_endpoints/hooks/{webhook_id}/delivery_attempts \
-H "Authorization: Bearer $API_KEY"

Returns all delivery attempts for a webhook, ordered by attempt number.

Get aggregate delivery stats per endpoint to monitor webhook health:

Terminal window
curl /v1/webhook_endpoints/delivery_stats \
-H "Authorization: Bearer $API_KEY"

Response:

[
{
"endpoint_id": "endpoint-uuid",
"total": 1250,
"succeeded": 1200,
"failed": 50,
"success_rate": 96.0
}
]
FieldTypeDescription
endpoint_idstringWebhook endpoint ID
totalintegerTotal deliveries
succeededintegerSuccessful deliveries
failedintegerFailed deliveries
success_ratenumberSuccess percentage
Terminal window
curl "/v1/webhook_endpoints/hooks/list?status=failed" \
-H "Authorization: Bearer $API_KEY"

Supports skip, limit, webhook_type, and status query filters.

Terminal window
curl -X POST /v1/webhook_endpoints/hooks/{webhook_id}/retry \
-H "Authorization: Bearer $API_KEY"

Only webhooks with failed status can be retried.

BoxBilling also receives inbound webhooks from payment providers to update payment and invoice status:

POST /v1/payments/webhook/{provider}

Supported providers: stripe, manual, ucp, gocardless, adyen

Each provider uses its own signature header for verification:

ProviderSignature Header
StripeStripe-Signature
UCPX-UCP-Signature
OthersWebhook-Signature
MethodPathDescription
POST/v1/webhook_endpointsCreate endpoint
GET/v1/webhook_endpointsList endpoints
GET/v1/webhook_endpoints/{id}Get endpoint
PUT/v1/webhook_endpoints/{id}Update endpoint
DELETE/v1/webhook_endpoints/{id}Delete endpoint
MethodPathDescription
GET/v1/webhook_endpoints/hooks/listList deliveries
GET/v1/webhook_endpoints/hooks/{id}Get delivery details
GET/v1/webhook_endpoints/hooks/{id}/delivery_attemptsGet delivery attempts
POST/v1/webhook_endpoints/hooks/{id}/retryRetry a delivery
GET/v1/webhook_endpoints/delivery_statsGet delivery stats per endpoint
MethodPathDescription
POST/v1/payments/webhook/{provider}Handle inbound payment provider webhook