Delivery
Retries and Delivery
How webhook delivery works, the retry schedule, what counts as a failure, and what happens when retries are exhausted.
Delivery in Webhook Watchtower is asynchronous. After an event passes ingest limits and is stored, it is acknowledged to your provider and queued for delivery to your destinations. This means the provider sees a successful response even if your endpoint is temporarily unavailable.
What counts as a failure
A delivery attempt fails if any of the following happen:
- Your endpoint returns a non-2xx HTTP status code (4xx or 5xx)
- Your endpoint doesn't respond within the 10-second timeout
- A network error prevents the connection from being established
A 2xx response, regardless of body content, is treated as success.
Retry schedule
Retries use fixed waits between attempts: 1 minute, 5 minutes, 30 minutes, then 2 hours. There is no random jitter. These are waits after the preceding failure, not absolute times from ingestion.
Current plan defaults, including the first attempt, are Scout 1, Guard 3, Sentinel 5, and Bastion 5. A workspace override can lower its plan ceiling. Grandfathered plans may differ; the API resolves the workspace's actual plan. Scout has one immediate attempt and no automatic retry.
If Watchtower cannot resolve or decrypt a configured outgoing signing secret, it records a configuration failure and retries within this policy. It never silently downgrades that delivery to unsigned. Legacy workspaces with an explicitly unset secret remain unsigned until initialized in Security settings.
When retries are exhausted
Once all retry attempts fail, the delivery is marked Permanently failed. At this point:
- Five consecutive exhausted deliveries open the destination circuit and trigger email and in-app notifications
- The event remains stored in your dashboard with the full delivery history
- You can select destinations and replay the retained payload on an eligible plan
Stored events remain inspectable until their retention window expires. Requests rejected by ingest limits were not stored and cannot be replayed.
Idempotency
Any system that retries deliveries can send the same event more than once. This applies to Watchtower and to your provider directly. Your endpoint should be idempotent: check the event's unique ID before processing and skip it if you've already handled it.
Most providers include a stable unique ID in the payload. For Stripe that's the id field (evt_...). For GitHub it's the X-GitHub-Delivery header. The event ID is stored and visible in the dashboard so you can trace duplicates.
Per-destination retry queues
Each destination has an independent retry queue. A failure on one destination doesn't block or delay delivery to others attached to the same source.
Checking delivery status
Every event in your dashboard shows:
- Current delivery status (Delivered, Failed, Pending, Permanently failed)
- Each attempt with its timestamp, HTTP status returned, and response body
- Total attempt count
Open any event to see the full attempt history. This is the fastest way to diagnose a delivery issue without touching your server logs.
Need more help?
Check the FAQ for quick answers, or email hello@webhookwatchtower.co.uk . Include your event ID or workspace name to get a faster answer.