Webhook Delivery and Retry
This page describes what QI Tech does when a webhook delivery fails, and the endpoints that let you inspect the delivery history and force a resend. For the list of emitted events, see Bookkeeping Events; to register the destination URL, see Webhook Configuration.
Every event is recorded before it is delivered. The first delivery is synchronous, at the moment the event is created; if it fails, the event enters the retry queue.
Retry policy
A delivery fails when your endpoint answers with a 3xx, 4xx or 5xx status, or when the request gets no response at all (DNS failure, refused connection or timeout).
Each event is delivered at most 8 times: the first attempt plus 7 retries, with a growing gap between them.
| Attempt | Gap since the previous one | Time since the first |
|---|---|---|
| 1 | — | 0 |
| 2 | 1 minute | 1 minute |
| 3 | 5 minutes | 6 minutes |
| 4 | 15 minutes | 21 minutes |
| 5 | 1 hour | 1h21 |
| 6 | 3 hours | 4h21 |
| 7 | 6 hours | 10h21 |
| 8 | 12 hours | 22h21 |
Once the 8 attempts are exhausted, the event moves to failed and is never sent again.
The retry queue is processed every 5 minutes, so the effective gap can be up to 5 minutes longer than the one in the table.
If your system processes the event and the response does not reach us, through a timeout or an error after the processing, the delivery is counted as a failure and the event is sent again.
The body is identical on every attempt. The event_datetime marks when the event was created, not when it was sent, so it does not change between attempts: use the combination of event_type, event_datetime and the identifiers inside event_data to recognize what you have already processed.
Webhook status
| Status | Description |
|---|---|
pending_shipment | The last delivery failed. The next_attempt_at field tells when the next one is due. |
on_queue | Retry queued, waiting to be processed. |
sent | Delivered. Your endpoint answered 2xx. |
failed | The 8 attempts are exhausted. The event will not be sent again. |
List Webhooks (GET)
Returns your tenant's events, from the most recent to the oldest. Use this query to reconcile what QI Tech sent with what your system processed.
Request
Query Params
| Field | Type | Description |
|---|---|---|
status | string | Filters by delivery status. Accepts pending_shipment, on_queue, sent or failed. |
event_type | string | Filters by event type, for example commercial_paper.operation_status_change. |
created_after | string | Returns the events created from this date and time on, formatted YYYY-MM-DDTHH:MM:SS. |
created_before | string | Returns the events created up to this date and time, same format. |
page | integer | Page to return, starting at 1. Defaults to 1. |
page_size | integer | Records per page. Default and maximum 100. |
Response
Response Body
{
"data": [
{
"webhook_key": "46804f32-101e-4702-8fbc-c2dbc4c2caec",
"tenant_key": "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
"status": "pending_shipment",
"number_of_attempts": 2,
"next_attempt_at": "2026-05-05T13:27:01",
"webhook_data": {
"event_type": "commercial_paper.operation_status_change",
"event_datetime": "2026-05-05T13:22:01Z",
"event_data": {
"operation_key": "072a7cc4-1fbf-419b-8a41-f57bd86ee753",
"operation_status": "issued"
}
},
"created_at": "2026-05-05T13:22:01"
}
],
"pagination": {
"current_page": 1,
"next_page": null,
"rows_per_page": 100,
"total_pages": 1,
"total_rows": 1
}
}
Response Body Params
| Field | Type | Description |
|---|---|---|
webhook_key | string | Unique key of the event (UUID v4). It is the identifier used to resend it. |
tenant_key | string | Key of the tenant that owns the event. |
status | string | Current delivery status. status enumerators |
number_of_attempts | integer | How many deliveries failed. An accepted delivery does not increment it. |
next_attempt_at | string | Date and time of the next retry. null when no retry is scheduled. |
webhook_data | object | Body sent to your endpoint, identical to the delivered one. |
created_at | string | Date and time the event was created. |
Get a Webhook (GET)
Request
Path Params
| Field | Type | Description | Characters |
|---|---|---|---|
WEBHOOK-KEY | string | Unique key of the event (UUID v4). | 36 |
Response
Response Body
{
"webhook_key": "46804f32-101e-4702-8fbc-c2dbc4c2caec",
"tenant_key": "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
"status": "pending_shipment",
"number_of_attempts": 2,
"next_attempt_at": "2026-05-05T13:27:01",
"webhook_data": {
"event_type": "commercial_paper.operation_status_change",
"event_datetime": "2026-05-05T13:22:01Z",
"event_data": {
"operation_key": "072a7cc4-1fbf-419b-8a41-f57bd86ee753",
"operation_status": "issued"
}
},
"created_at": "2026-05-05T13:22:01"
}
The fields are the same described in Response Body Params.
Manual Resend (PUT)
Sends the event right away, without waiting for the next window of the retry policy. Use it when your system came back before the next gap elapses.
A manual attempt follows the same rules as the automatic ones: if it fails, it increments the counter and schedules the next step; on the eighth failure, the event moves to failed.
Only events in pending_shipment or on_queue can be resent.
Request
Path Params
| Field | Type | Description | Characters |
|---|---|---|---|
WEBHOOK-KEY | string | Unique key of the event (UUID v4). | 36 |
Response
The response has no body. The 202 confirms the attempt was made, not that your endpoint accepted it: query the event to learn the outcome.
Errors
| HTTP Code | Error Code | Description (eng) | Translation (pt-BR) |
|---|---|---|---|
| 404 | OWB0000001 | Webhook not found. | Webhook não encontrado. |
| 400 | OWB0000005 | You do not have access to this tenant. | Você não tem acesso a este tenant. |
| 409 | OWB0000007 | Webhook is {webhook_status} and cannot be sent again. | O webhook está {webhook_status} e não pode ser reenviado. |
| 409 | OWB0000008 | Webhook is already being sent by another process. | O webhook já está sendo enviado por outro processo. |