# Handle webhooks reliably

Each event is sent until your endpoint accepts it or the retries run out (so you may receive an event more than once), in no particular order. A receiver built like this, together with the reconciliation in step 3, doesn't lose or double-count events.

## 1. Verify, store, answer

In the request handler, only:

1. read the raw body and verify the signature ([Verifying webhook signatures](https://docs.rephut.com/developers/webhooks/signatures));
2. store the event in a table or queue, keyed by its `id` (ignore it when the id is already there);
3. answer `200` straight away.

Do nothing slow in the handler. The time limit is 10 seconds, and slow answers turn into failed attempts and retries.

## 2. Process from the queue

A worker takes stored events one by one:

1. fetch the resource with its `GET` endpoint, using `data.id`;
2. save what `GET` returned;
3. mark the event as done.

Because you always act on the current state from `GET`, it doesn't matter that events arrive late, twice or out of order. If `GET` fails with a `5xx` or a network error, leave the event in the queue and try later.

## 3. Reconcile

Run a periodic catch-up with the API, such as [Incremental sync](https://docs.rephut.com/developers/incremental-sync) for orders. For purchase orders, shipments, requests and quotes, re-read the first page of the list to find new ones (lists are newest first by creation time and have no `updatedSince`), and `GET` the older ones you still consider open. It covers events from while your endpoint was turned off, which are not sent again.

## 4. Watch your endpoint

- Check **Recent deliveries** on the endpoint's page in the portal when something looks wrong.
- After 50 failed attempts in a row the endpoint is turned off and you get a notification. Turn it back on once it is fixed, then reconcile.
- Use **Send test event** after every deployment of your receiver.

## 5. Rotate secrets safely

Creating a new secret replaces the old one at once. Deploy the new secret right after creating it; attempts that fail in the meantime are retried with the new signature.
