Currently Available: Need a skilled Software Developer for your next project?
Categories
APIs

Designing a Webhook Failure Dashboard

A webhook sends an HTTP notification from one service to an endpoint hosted by another service. When delivery fails, operators need to know whether the receiver responded, how many attempts the sender made, and whether they can recover the event. A failure dashboard should show these facts while keeping the notification separate from each attempt to deliver it.

An event is the notification being sent. A delivery attempt is one effort to send that event. Store events and attempts as separate records. One event can have several attempts, including automatic retries and redeliveries started by an operator. Providers handle retries, record attempts, and offer recovery options differently. Use consistent fields in the dashboard, and keep the values each provider reports so operators can investigate failures.

Show the five fields with clear definitions

Field What to show Design decision
Event age Elapsed time since the event was created Use the provider’s event-creation timestamp when available. Show time since the last attempt separately.
Attempt count Total recorded attempts, including the initial delivery State how the count is calculated and show it as unknown when records are incomplete.
Last status code The HTTP response code from the most recent attempt Show no response when the endpoint timed out or the connection failed.
Error reason A short failure category and the provider’s diagnostic detail Distinguish receiver responses from connection, timeout, and certificate failures.
Replay eligibility Whether an operator can retry or recover the event now Show available, unavailable, or unknown, with the reason when known.

Event age and attempt time answer different questions. Square includes an event’s created_at timestamp, while delivery records from GitHub include delivered_at. A delivery timestamp indicates when an attempt occurred; it does not necessarily say when the event was created. If the provider does not supply an event-creation time, display event age as unavailable rather than calculating it from delivery time. Include “time since last attempt” as its own value so an operator can tell whether an old event was contacted recently.

Attempt counts also need a declared convention. Square’s square-retry-number excludes the original notification, while GitHub records each delivery and marks redeliveries. Show a consistent total that includes the first attempt. Keep the provider’s retry value or delivery records so operators can verify the total. The Square notification documentation and GitHub delivery API illustrate why provider values cannot be treated as interchangeable.

Preserve status codes and failure reasons

A status code describes an HTTP response from the receiver. It cannot describe every failed attempt. A connection timeout or certificate verification error can occur before the sender receives any HTTP response, so the dashboard should allow the status-code field to be empty while still showing a failure reason.

Show the actual code and the provider’s classification of the outcome. GitHub’s API classifies status codes as successful or failures. HTTP status codes in the 2xx range indicate success. GitHub’s troubleshooting documentation recommends that a receiver return a 2xx response. Show the provider’s classification alongside any dashboard status, and explain how the dashboard assigns that status.

For scanning, normalize detailed errors into a small set of categories, such as timeout, receiver response, connection failure, or certificate failure. Keep the provider’s reason and diagnostic text in the delivery details. Square, for example, documents retry reasons for timeouts, non-2xx responses, SSL errors, and other errors in its event notification guidance. A normalized label helps operators compare failures across providers; the original detail helps them investigate a specific one.

Organize the dashboard around events and attempts

Show one row for each event sent to an endpoint in the main failure queue, rather than one row for each attempt. Each row can include the event identifier and type, endpoint, event age, time since the last attempt, total attempt count, last status code, latest error reason, and replay eligibility. Let operators sort or filter by age, endpoint, event type, and eligibility to find old failures and events they can act on.

Group failures in the summary by endpoint, event type, and a shared error category. Many failures at one endpoint call for a different investigation than failures affecting only one event type. Show counts and age ranges so operators can tell whether the backlog is growing or contains only a few recent failures.

When an operator selects a row, open the event’s delivery history. Show the time and response code for each attempt, when available, along with the provider’s diagnostic. If the provider distinguishes automatic attempts from ones started by an operator, show that too. Include the stable event identifier and enough event context to investigate the failure without treating each redelivery as a new event.

Make replay eligibility provider-specific

A failed delivery does not automatically qualify for replay. Eligibility depends on the provider’s recovery options, the event’s age, and the operator’s permissions. Show “unknown” when the dashboard cannot verify these conditions. Keep replay controls disabled until the dashboard confirms that the operator can replay the event.

Provider policies illustrate why the interface should explain the recovery path. Square documents automatic retries for unsuccessful notifications for up to 24 hours and points operators to its Events API for recovery and reconciliation. GitHub does not automatically redeliver failed deliveries, but permits manual redelivery for deliveries from the past three days; its documentation also specifies different permission requirements for repository and organization webhooks. These are distinct mechanisms, not shared defaults. See Square’s retry behavior and GitHub’s redelivery rules.

Before an operator replays an event, show what the action will affect and any known restrictions. The receiver can process the same event again after a replay. Square documents event_id as a value for identifying repeated events, and GitHub redeliveries retain the original X-GitHub-Delivery header. Show the provider’s stable identifier and remind operators that the receiver should recognize duplicates when the provider supports that behavior. Providers do not all use the same identifiers or duplicate-handling rules.

What I'm building

Delegate tasks. Get software.

Give Vroni a GitHub issue, bug report, spec, or rough idea. It reads the repo, plans the change, writes code, runs checks, and works toward a review-ready pull request.

Take a look at vroni.com

Email updates

Usually a new article and a few links I found interesting.

No spam. Unsubscribe with one click.

Leave a Reply

Your email address will not be published. Required fields are marked *