Delivery and retries
What counts as success, when we retry, and what the logs record.
The request we send
POST /your-endpoint HTTP/1.1
Content-Type: application/json
User-Agent: Pengine-Webhooks
X-Pengine-Signature: sha256=6f2d1c8b4a09e73f5d2b8c1a0e94f7b3...| Property | Value |
|---|---|
| Method | POST, always. |
| Body | The event JSON. See Events. |
| Timeout | 10 seconds, from connection to last byte. |
| Redirects | Not followed. A 301 or 302 is a failed delivery. |
Your URL
Set one URL per event in your store's API settings in the Pengine app. The rules are checked when you save it and again before every delivery:
- HTTPS only.
- No credentials in the URL.
- The hostname must resolve to a public address. Private ranges and loopback are refused, so
localhostand10.xreceivers cannot be reached. Use a tunnel while you develop.
Changing the URL takes effect immediately. Removing it stops delivery, including for events already queued and waiting on a retry.
Success and failure
Any 2xx response is successful. Pengine retries other status codes, timeouts, redirects, TLS errors,
and DNS failures.
Answer fast, work later
The ten-second timeout covers the entire response. Store the event, return 200, and process it
asynchronously.
Retries
Five attempts in total, with exponential backoff starting at ten minutes.
| Attempt | Sent |
|---|---|
| 1 | Immediately |
| 2 | ~10 minutes after the first failure |
| 3 | ~20 minutes later |
| 4 | ~40 minutes later |
| 5 | ~80 minutes later |
After the fifth failure, Pengine stops retrying the event. The schedule spans about two and a half
hours. If your endpoint misses events, recover by listing recently updated resources:
GET /stores/:storeId/orders?sort[updatedAt]=desc.
Test deliveries sent from the app are never retried. They are one attempt, so you see the real result.
Ordering and duplicates
Delivery order is not guaranteed. Retries and concurrent events can deliver an older event after a
newer one. An event can also repeat if Pengine does not receive your 2xx response.
Deduplicate on the event id, which remains stable across retries, and fetch the resource to get its
current state.
What we record
Every attempt is logged for 14 days, and you can read it in your store's API settings:
| Field | What it holds |
|---|---|
| Event | The topic, event ID, and resource ID |
| Attempt | Which of the five this was |
| Outcome | Your status code, or the transport error if we never got one |
| Duration | How long you took to answer |
| Response | The first kilobyte of your response body |
If your framework returns an HTML error page, the log stores its first kilobyte to help diagnose the failure.