> ## Documentation Index
> Fetch the complete documentation index at: https://docs.finosu.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Delivery and retries

> Accept events durably, handle duplicates, and recover failed deliveries.

[Verify the signature](https://docs.finosu.com/api-reference/webhooks/verification.md) before accepting an
event. Return `2xx` only after your receiver has accepted responsibility for it.

Subscribed events for test customers arrive at the normal endpoint with
`test: true`. Accept and deduplicate them normally, but route them to test
processing and never apply them to live accounts. They retain their business
event type (for example, `text.sent`) and follow ordinary activation, pause, and
retry rules. Only the separate `webhook.test` event verifies endpoint setup.

## Accept durably, then process

After verification:

1. Parse the JSON and validate the expected company, environment,
   event type, and required fields.
2. Atomically record the event identity and enqueue work in durable storage. Use a
   unique constraint on company plus event ID for a consumer that handles the same
   event across multiple endpoints. Scope deduplication separately if different
   consumers intentionally perform different actions.
3. Return `200` or `204` promptly, then perform downstream work from the durable
   queue. Coordinate deduplication with processing so concurrent deliveries cannot
   apply the same effect twice.

An already accepted duplicate should receive `2xx` too, not `409`. If the durable
store is temporarily unavailable, return `503` so delivery can retry. For an
unsupported event, either durably quarantine it before acknowledging,
or reject it and arrange recovery with Finosu. Never return success and silently
lose work that needs processing.

A `2xx` response means your endpoint accepted responsibility; it does not prove
that an account update was applied. If processing fails after acknowledgment,
recovery is your queue's responsibility. Finosu does not consume the response
body or automatically retry successful acknowledgments.

## Retry behavior

These retries apply after Finosu has queued a webhook delivery. They do not
guarantee capture of every payment transition. See the
[event catalog](https://docs.finosu.com/api-reference/webhooks/events.md) for current-state behavior and
capture limits; reconcile missing updates with Finosu.

| Result | Sender behavior |
| - | - |
| Any `2xx` | Accepted; no automatic retry. |
| Transport failure or timeout | Retry within the attempt budget; the receiver may already have accepted the request. |
| `408`, `429`, or `5xx` | Retry within the attempt budget. |
| Other status, including `3xx`, `400`, `401`, `403`, `404`, `409`, `422` | Terminal failure; redirects are not followed. |

Each delivery has an initial budget of eight HTTP attempts. Scheduled backoff
intervals are 5 seconds, 1 minute, 5 minutes, 15 minutes, 1 hour, 3 hours, then
6 hours. Worker scheduling and endpoint pauses can delay actual attempts. The
sender uses its configured backoff; it does not honor `Retry-After`.

The HTTP transport timeout is at most 15 seconds and can be shorter when the
worker's remaining attempt budget is lower. Return promptly after durable
acceptance. Delivery is not guaranteed exactly once or indefinitely: a timeout can
happen after receiver acceptance, and a terminal or exhausted delivery needs
investigation.

Retries retain the original event body, event ID, and delivery key. Each attempt
gets a new timestamp and signature, so verify freshness against the signature's
`t`, not `occurred_at`.

Each delivery permits at most 32 manual retry grants; after that, contact Finosu
for reconciliation. Previously used request keys remain protected against replay.

Staff can manually retry eligible failed deliveries while preserving event
identity and attempt history. The endpoint must be active, and a newer event for
the same endpoint/subject blocks replay of stale state. Manual retry grants a new
attempt budget; it does not create a new business event. Contact Finosu when
reconciliation is needed instead of replay.

## Ordering and reconciliation

Unresolved deliveries block newer events in the same endpoint/subject lane.
Terminal failures release that lane. There is no global ordering guarantee across
subjects or endpoints.

When replacing a resource snapshot, compare `subject.sequence` only within the
same `company_id`, `subject.type`, and `subject.id`. Persist the last applied
sequence with the state update. A lower sequence must not overwrite newer state.
For event-ledger or financial side effects, reconcile missing events using their
identities and business semantics rather than treating the sequence as a complete
ledger.

Sequence gaps are normal. A sequence is not a global catch-up cursor, commit
watermark, or proof that every intermediate event was received. This contract
provides no historical replay or general snapshot-retrieval API. Contact Finosu
to establish the appropriate reconciliation path for your integration.

## Pausing and changing endpoints

Draft endpoints receive tests only. Paused endpoints retain and continue collecting
subscribed events; resuming releases their backlog. Pending deliveries use the
current destination and credentials. Requests already in progress may finish
after pause or archive. Archived endpoints stop further dispatch and retain their
delivery history.

Changing configuration or rotating the secret requires pausing, updating your
receiver, and passing another test before activation. Rotation replaces the secret;
there is no configured overlap period accepting both secrets at the sender.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.