Webhooks
Receive real-time notifications when case events occur instead of polling the API.
This guide assumes you've completed the Quickstart.
Overview
Webhooks push event data to your endpoint as cases progress through collection. Subscribe to specific events to keep your systems synchronized without repeated API calls.
Available Events
| Event | Description |
|---|---|
case.created | New case submitted |
case.updated | Case lifecycle state changed |
case.closed | Case resolved (paid, written off, or otherwise closed) |
payment.created | Payment registered on a case |
chat.created | Chat message added to a case |
Create a Webhook Subscription
You can create webhooks via the API (shown below) or through the Debitura portal. See Webhooks in the portal for UI instructions.
POST https://customer-api.debitura.com/webhooks
Content-Type: application/json
XApiKey: YOUR_API_KEY
{
"url": "https://your-domain.com/webhooks/debitura",
"events": ["case.created", "case.updated", "case.closed", "payment.created"]
}
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"url": "https://your-domain.com/webhooks/debitura",
"events": ["case.created", "case.updated", "case.closed", "payment.created"],
"isActive": true,
"createdUtc": "2026-01-31T15:23:45Z",
"secret": "dGhpc2lzYWJhc2U2NGVuY29kZWRzZWNyZXQ="
}
The secret is returned only once during creation. Store it immediately. You cannot retrieve it later.
To regenerate: PATCH /webhooks/{id} with "regenerateSecret": true.
Event Payload Structure
All events use a CloudEvents-inspired format:
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"specVersion": "1.0",
"event": "case.created",
"timestamp": "2026-01-31T15:23:45Z",
"data": {
"caseId": "123e4567-e89b-12d3-a456-426614174000",
"reference": "Q8OAXF3W"
},
"links": {
"self": "https://customer-api.debitura.com/cases/123e4567-e89b-12d3-a456-426614174000"
}
}
| Field | Description |
|---|---|
id | Unique event ID—use for idempotency |
event | Event type |
timestamp | When the event occurred (ISO 8601 UTC) |
data | Event-specific payload |
links.self | API URL for the affected resource |
HTTP Headers:
| Header | Value |
|---|---|
X-Debitura-Signature | t={timestamp},v1={signature} |
X-Debitura-Timestamp | Unix timestamp |
The event type is available in the JSON body under the event field.
Event Payloads
case.created
{
"data": {
"caseId": "123e4567-e89b-12d3-a456-426614174000",
"reference": "Q8OAXF3W"
}
}
case.updated
{
"data": {
"caseId": "123e4567-e89b-12d3-a456-426614174000",
"reference": "Q8OAXF3W",
"oldLifecycle": "Active",
"newLifecycle": "Pending Verification"
}
}
See Case Lifecycle for all lifecycle values and their meanings.
case.closed
{
"data": {
"caseId": "123e4567-e89b-12d3-a456-426614174000",
"reference": "Q8OAXF3W",
"closeCode": "Paid",
"closeComment": "Paid in full by debtor"
}
}
See Case Lifecycle for all close codes and their meanings.
payment.created
{
"data": {
"caseId": "123e4567-e89b-12d3-a456-426614174000",
"reference": "Q8OAXF3W",
"paymentId": "789e4567-e89b-12d3-a456-426614174999",
"amount": 5000.00,
"currency": "EUR",
"date": "2026-01-31T12:00:00Z"
}
}
chat.created
{
"data": {
"caseId": "123e4567-e89b-12d3-a456-426614174000",
"reference": "Q8OAXF3W",
"chatId": "456e4567-e89b-12d3-a456-426614174888",
"role": "Partner",
"message": "Please provide updated payment plan"
}
}
Role values: Partner (collection partner), Creditor (you), ManagedByPartner (partner acting on your behalf)
Signature Verification
Verify every webhook request using webhook signature verification. The signature proves the request came from Debitura and wasn't tampered with.
Quick summary:
- Extract
t(timestamp) andv1(signature) fromX-Debitura-Signature - Construct:
signed_payload = timestamp + "." + raw_json_body - Decode your secret from Base64
- Compute HMAC-SHA256 of signed payload
- Compare signatures using constant-time comparison
- Verify timestamp is within 5 minutes
Processing Best Practices
Respond Quickly
Return 2xx within 10 seconds. Verify the signature, acknowledge immediately, then process the event asynchronously via a queue or background job.
Idempotent Processing
Use the id field to detect duplicates—Debitura may retry delivery. Store processed event IDs and skip duplicates. See idempotent webhook processing for implementation patterns.
Retry Behavior
Debitura retries failed deliveries with exponential backoff:
| Attempt | Delay | Cumulative |
|---|---|---|
| 1 | 0s | 0s |
| 2 | ~60s | ~1 min |
| 3 | ~120s | ~3 min |
| 4 | ~240s | ~7 min |
| 5 | ~480s | ~15 min |
| 6 | ~960s | ~31 min |
| 7-8 | ~1800s | ~1.5 hours |
After 8 consecutive failures, the webhook is automatically disabled. Fix your endpoint and re-enable via the API.
A 410 Gone response immediately disables the webhook.
Managing Webhooks
List subscriptions:
GET https://customer-api.debitura.com/webhooks
Update subscription:
PATCH https://customer-api.debitura.com/webhooks/{id}
{
"url": "https://new-endpoint.com/webhooks",
"events": ["case.created", "payment.created"],
"isActive": true
}
Delete subscription:
DELETE https://customer-api.debitura.com/webhooks/{id}
Test delivery:
POST https://customer-api.debitura.com/webhooks/{id}:test
Test deliveries include X-Debitura-Test: true header.
Common Issues
Webhook not received
Your endpoint must be publicly accessible via HTTPS with a valid TLS certificate. Private IP addresses and localhost are blocked.
Signature verification fails
Ensure you're using the raw request body (not parsed JSON) and decoding the secret from Base64 before computing HMAC.
Webhook disabled
Check disabledReason in the webhook details. Fix the underlying issue, then update with "isActive": true.