# Retries

Networks fail, both ways. Weav retries every webhook it sends you until your server takes it, and you can retry your own calls to Weav without ever doing something twice.

## Retrying your calls to Weav

When a call fails or times out, decide by what came back. Resend a create exactly as it was, with the same `external_reference_id` (or the same `Idempotency-Key`, if you send one) and the same body (see [Idempotency](https://docs.weavpayments.com/idempotency)).

| What came back | Retry? | How |
| --- | --- | --- |
| No response: a timeout or a dropped connection | **Yes** | The same request. If the first one went through, you get its stored response, with `Idempotent-Replayed: true`. |
| `500`, code `5000000` | **Yes** | The same request. Failed requests aren’t stored, so the retry runs fresh. If it keeps happening, contact support. |
| `429`, code `4290000` | **Yes** | After `Retry-After` seconds. Nothing in the request was done. See [Rate limiting](https://docs.weavpayments.com/rate-limiting). |
| `409`, code `4090002` | **Yes** | The first request with this key is still running. Wait a moment, then retry with the same key. |
| `409`, code `4090102` | **Yes** | The provider couldn’t cancel right now. Retry the cancel shortly; the payment stays pending until then. |
| `429`, code `4290201` or `4290202` | Not in a loop | Repost limits. Wait for `Retry-After`; to check a status, [retrieve the payment](https://docs.weavpayments.com/reference/payments/retrieve-payment) instead. |
| `409`, code `4090001` | No | The key was already used for a different request. A new request needs a new key. |
| `400`, `401`, `403`, `404`, `422` | No | The same request will fail the same way. Fix what `code` and `errors` say, then send it again. |

- **Back off.** Wait longer after each failed try (for example 1, 2, 4, then 8 seconds), with a little randomness so your retries don’t all land at once, and give up after a few tries. Always wait at least `Retry-After` when Weav sends one.
- **Decide on `code`** or the HTTP status, never on `message`. See [Response codes](https://docs.weavpayments.com/reference/response-codes).
- **A payment you gave up on can still finish.** If you stop retrying, read the payment with `GET /v1/payments/{reference_id}` or wait for its webhook before you tell your customer it failed.

```mermaid
sequenceDiagram
    autonumber
    participant Server as Your server
    participant Weav
    Server->>Weav: POST /v1/payments<br/>external_reference_id: ORD-1
    Note over Server,Weav: The connection drops before the response arrives
    Server->>Weav: The same request
    Weav-->>Server: The stored 201 response<br/>Idempotent-Replayed: true
    Note over Server: One payment, however many times you retried
```

## When Weav retries a webhook

A delivery counts only when your endpoint answers with a `2xx` within 10 seconds. When an attempt fails, Weav tries again on this schedule. Each wait is counted from the attempt before it.

| Attempt | Wait after the previous attempt | About this long after the first |
| --- | --- | --- |
| 1 | None | Right away |
| 2 | 2 minutes | 2 minutes |
| 3 | 10 minutes | 12 minutes |
| 4 | 10 minutes | 22 minutes |
| 5 | 1 hour | 1 hour 22 minutes |
| 6 | 2 hours | 3 hours 22 minutes |
| 7 | 6 hours | 9 hours 22 minutes |
| 8 to 18 | 15 hours each | Up to about 7 days 6 hours |

- **18 attempts in all:** the first one plus 17 retries, over about 7 days.
- **A failed attempt** is anything other than a `2xx` within 10 seconds: a `4xx` or `5xx`, a timeout, a connection or TLS error, or a redirect. Weav doesn't follow redirects, so point your URL at the final address.
- **Retries are spread out.** Each wait gets up to 10% extra at random, so retries for many events don't hit your server at the same moment.
- **Tell us when you're busy.** If you answer `429` or `503` with a `Retry-After` header in seconds, Weav waits at least that long before the next attempt, up to 15 hours.
- **Every attempt is freshly signed.** Each one carries a new `sent_at` and a new `X-Signature`, so a retry never fails your 5-minute check. The event and its `data` stay the same.
- **After the last attempt**, the delivery is marked failed and stays in the dashboard. You can repost it from there at any time. A repost continues the attempt count.
- **You can see every attempt** under Developers in the dashboard, with its status code, the first 2 KB of your response, and how long it took.

## When a payment’s result comes late

A provider’s confirmation can arrive late or not at all. Weav checks with providers regularly, so a payment the customer paid still completes, even after it expired or was canceled, and you get its webhook then. Always act on the latest status. See [Statuses](https://docs.weavpayments.com/statuses).

To have a payment’s latest webhook sent again, for example after fixing your endpoint, use [Repost a webhook](https://docs.weavpayments.com/reference/webhooks/repost-payment-webhook).
