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

# Delivery and retries

> How Subtotal delivers webhook events, when it retries, when it stops, and how to handle redelivered events.

Subtotal sends each event to your destination as an HTTPS `POST`. This page describes the delivery contract so you can build a receiver that stays correct under retries.

The same contract applies to destinations configured under **Webhooks** in the dashboard and to [partner app](/docs/partner-apps/webhooks#delivery-and-retries) webhook endpoints.

## Acknowledging a delivery

* Respond with any **2xx** status within **10 seconds**. A 2xx marks the event as delivered; the response body is ignored.
* Queue the event and return 2xx before doing slow work. Subtotal does not wait for your processing to finish.
* Respond directly from the configured URL. Redirects are not followed.
* [Verify the signature](/docs/webhooks/verifying-signatures) before you act on the payload.

## Retry schedule

Each attempt is a single `POST`. When an attempt fails for a retryable reason, Subtotal schedules the next one. A delivery gets up to **six attempts over roughly 17 hours 35 minutes**.

| Attempt | Delay after the previous attempt | Approximate time after the event |
| :- | :- | :- |
| 1 | — | Immediately |
| 2 | 5 minutes | 5 minutes |
| 3 | 30 minutes | 35 minutes |
| 4 | 2 hours | 2 hours 35 minutes |
| 5 | 5 hours | 7 hours 35 minutes |
| 6 | 10 hours | 17 hours 35 minutes |

Each delay is measured from when the previous attempt actually ran, so later attempts can arrive a few minutes after these times. The schedule is fixed; a `Retry-After` header does not change it.

Once Subtotal records a successful 2xx response for an event, retries to that destination stop. Pending retries go to the destination's current URL, so fixing the URL in the dashboard lets the remaining attempts succeed. Pending retries stop if you delete the destination or stop subscribing it to that event type.

If the sixth attempt fails, the delivery is recorded as failed and is not retried automatically.

## What is retried

| Result of an attempt | Outcome |
| :- | :- |
| Any **2xx** | Delivered. |
| **5xx**, **408**, or **429** | Retried on the schedule above. |
| Connection refused, DNS failure, TLS failure, or connection reset | Retried on the schedule above. |
| No response within 10 seconds | Retried on the schedule above. Your endpoint may have received the request, so it can see this event again. |
| Any other **4xx** (for example 400, 401, 403, or 404) | Terminal. Recorded as failed and not retried. |
| Any **3xx** | Terminal. The redirect is not followed. |

<Note>
  A destination that keeps failing is **not** disabled automatically. It continues to receive new events, and each one follows the schedule above. Deliveries that exhaust their retries or fail for a terminal reason require [redelivery](#redelivery) after your endpoint recovers.
</Note>

## Redelivery

Subtotal can redeliver failed events on request, either a single event or every failed event to a destination over a time window. Contact support with the destination and the time range you need.

A redelivery reuses the original event `id` and is sent only to destinations that have not already accepted the event. If a redelivered event fails again, it starts a new six-attempt schedule.

## Idempotency

Every event carries an `id` that is stable across retries and redeliveries. Store the `id` of each event you have processed and ignore any later request with the same `id`.

Duplicates are possible. If your endpoint processes a request but the 2xx does not reach Subtotal within 10 seconds, the event is sent again on the next attempt. Deduplicating on `id` makes this harmless.

For `purchase.created`, each `id` identifies one purchase for one connection. If the same customer has more than one connection to your account, the same purchase arrives under a different `id` for each connection.

## Ordering and fan-out

* Events are delivered independently and are not guaranteed to arrive in the order they occurred. A retried event can arrive after newer events. Do not rely on arrival order; when you need a connection's current status, read it from the [API](/docs/subtotal-api).
* When a customer's connection is activated for the first time, Subtotal sends one `purchase.created` event per historical purchase already on record for that account. A new connection can produce many requests in a short burst.
* Each destination is delivered to independently. A failure at one destination does not affect delivery to another.


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