Skip to content

Commit 0c7a7aa

Browse files
committed
docs(learnings/webhooks): default to exponential backoffPlan with 4xx exclusions
Server URL configs lose deliverable events on a single failed POST. Document the backoffPlan pattern (exponential, maxRetries 3, baseDelaySeconds 1) plus excludedStatusCodes for the 4xx family — semantic rejections that retrying won't fix. Recommend this as the default for any new server.url definition so end-of-call-reports survive transient webhook hiccups.
1 parent 4b04f7b commit 0c7a7aa

1 file changed

Lines changed: 30 additions & 0 deletions

File tree

docs/learnings/webhooks.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,36 @@ They don't inherit from each other.
3939

4040
---
4141

42+
## Retry & Backoff for Server Delivery
43+
44+
A single failed POST to your `server.url` should not be the difference between getting an `end-of-call-report` and losing it. Configure an explicit `backoffPlan` on the `server` block so transient failures (502/503/504, network blips, brief handler restarts) get retried, while semantic errors that won't change on retry (4xx) short-circuit immediately.
45+
46+
```yaml
47+
server:
48+
url: https://your-webhook-endpoint.example.com/vapi
49+
timeoutSeconds: 20
50+
backoffPlan:
51+
type: exponential
52+
maxRetries: 3
53+
baseDelaySeconds: 1
54+
excludedStatusCodes: [400, 401, 403, 404, 413, 422]
55+
```
56+
57+
**Field meanings:**
58+
59+
| Field | Effect |
60+
|---|---|
61+
| `type: exponential` | Delay doubles each retry. With `baseDelaySeconds: 1` and `maxRetries: 3` the schedule is roughly 1s → 2s → 4s (~7s wall clock). |
62+
| `maxRetries` | Upper bound on retry attempts (not counting the initial request). |
63+
| `baseDelaySeconds` | First retry delay; subsequent retries double from this base when `type` is exponential. |
64+
| `excludedStatusCodes` | Status codes that skip retry entirely. The request fails immediately on receipt. |
65+
66+
**Why exclude the 4xx family.** A 4xx response means your server understood the request and rejected it for a deterministic reason — bad auth (401/403), missing route (404), validation failure (400/422), payload too large (413). Retrying produces the same response, just later. `excludedStatusCodes` tells Vapi to give up on those codes and reserve the retry budget for genuinely transient failures (5xx, network errors, request timeouts).
67+
68+
**Recommendation: make `backoffPlan` part of the default whenever you define a `server.url`.** The cost is one config block; the benefit is that the `end-of-call-report` event — your post-call analytics ground truth — survives a brief webhook hiccup instead of being silently lost. Keep `server.timeoutSeconds` shorter than your slowest downstream dependency so a hanging handler doesn't compound across retries.
69+
70+
---
71+
4272
## Credential Resolution
4373

4474
If `credentialId` is set on the server or tool, that specific credential is used. If omitted, Vapi picks one from the call's available credentials automatically.

0 commit comments

Comments
 (0)