{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-guides/sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":[]},"type":"markdown"},"seo":{"title":"Retries & reliability","description":"Start today using our public API to power your next project."},"dynamicMarkdocComponents":[],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"retries--reliability"},"children":["Retries & reliability"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Jeeves delivers events with at-least-once semantics. Your handler must be idempotent."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"automatic-retries"},"children":["Automatic retries"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["If your endpoint does not return ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["2xx"]}," in time, Jeeves retries with exponential back-off:"]},{"$$mdtype":"Tag","name":"div","attributes":{"className":"md-table-wrapper"},"children":[{"$$mdtype":"Tag","name":"table","attributes":{"className":"md"},"children":[{"$$mdtype":"Tag","name":"thead","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Attempt"},"children":["Attempt"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Delay after previous failure"},"children":["Delay after previous failure"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["1st (initial delivery)"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Immediate"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["2nd retry"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["2 minutes"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["3rd retry"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["30 minutes"]}]}]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["After all retries are exhausted the delivery is marked ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["exhausted"]},". You can still trigger a manual retry."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"what-triggers-a-retry"},"children":["What triggers a retry"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["HTTP ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["5xx"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["HTTP ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["429"]}," — Jeeves honors the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Retry-After"]}," header if set"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Network errors: connection refused, DNS failure, connection timeout"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Retries are NOT triggered by:"]}," ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["2xx"]}," (success) or other ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["4xx"]}," (treated as permanent failures)."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"concurrency-limit"},"children":["Concurrency limit"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Jeeves caps each subscription at ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["5 concurrent in-flight requests"]},". If you need to back off further, return ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["429"]}," with a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Retry-After"]}," header."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"manual-retries"},"children":["Manual retries"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"header":{"controls":{"copy":{}}},"source":"POST /v1/webhooks/events/{eventId}/retry\n"},"children":[]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Re-delivers the event to every active subscription subscribed to its type"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["One-shot — a failed manual retry does ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["not"]}," trigger another automatic retry"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Returns ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["409"]}," if any active subscription still has an in-flight delivery for this event"]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"circuit-breaker"},"children":["Circuit breaker"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["After ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["50 consecutive failed deliveries"]},", a subscription is automatically set to ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["disabled"]}," and an alert email is sent to every address in ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["developerEmail"]},". Re-enable once your endpoint is healthy:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"PATCH /v1/webhooks/subscriptions/{id}\n{ \"status\": \"active\" }\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The consecutive-failure counter resets after the first successful delivery."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"idempotency"},"children":["Idempotency"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Use ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["X-Webhook-Event-Id"]}," (or the envelope ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["id"]},") as a unique constraint in your database. A reliable pattern:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"sql","header":{"controls":{"copy":{}}},"source":"-- Pseudocode\nINSERT INTO processed_events (event_id, processed_at)\nVALUES (:event_id, NOW())\nON CONFLICT (event_id) DO NOTHING;\n\nIF rows_affected == 0:\n    return  -- already processed — skip\n\n-- safe to apply business logic\n","lang":"sql"},"children":[]}]},"headings":[{"value":"Retries & reliability","id":"retries--reliability","depth":1},{"value":"Automatic retries","id":"automatic-retries","depth":2},{"value":"What triggers a retry","id":"what-triggers-a-retry","depth":2},{"value":"Concurrency limit","id":"concurrency-limit","depth":2},{"value":"Manual retries","id":"manual-retries","depth":2},{"value":"Circuit breaker","id":"circuit-breaker","depth":2},{"value":"Idempotency","id":"idempotency","depth":2}],"frontmatter":{"seo":{"title":"Retries & reliability"}},"lastModified":"2026-06-15T18:50:49.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/guides/integration-guides/webhooks/retries","userData":{"isAuthenticated":false,"teams":["anonymous"]}}