Client API Blog
Making Webhooks Reliable: Delivery, Retries, and Event Design for Customer-Facing Integrations
Webhook failures are usually operational, not product-level. Design delivery, retries, and events to minimize duplicates, reduce latency, and keep downstream systems predictable.
Why webhooks matter
Customer-facing integrations succeed or fail on reliability. When a webhook that creates a work order or updates billing is delayed, duplicated, or lost, the consequences are immediate: confused customers, manual fixes, more support tickets, and eroded trust.
This post gives practical patterns for delivery, retry behavior, and event design so your integrations behave predictably in production.
Delivery guarantees to design for
Aim for at-least-once delivery: retry until the receiver ACKs. It’s simple and practical, but receivers must handle duplicates.
Exactly-once semantics require additional infrastructure (distributed transactions, coordinated ACKs, or centralized brokers). For most customer-facing integrations, at-least-once plus idempotency and deduplication in the payload is the right trade-off.
Document your promises: number of delivery attempts, retry schedule, and retention window should be explicit in your docs and API portal.
Design events for idempotency and debuggability
Include these fields in every webhook envelope:
- event_id: globally unique identifier (UUID)
- event_type: semantic name (invoice.created, assignment.updated)
- created_at: ISO8601 timestamp
- resource_id: primary object referenced
- version: event schema or contract version
With event_id and resource_id, most receivers can detect and ignore duplicates. event_type and version let consumers evolve integration logic without breaking older implementations.
Payload size and what to include
Keep payloads small. Prefer references (resource_id with an API link) so consumers can fetch the current state when processing the event. Smaller payloads reduce delivery latency and timeout failures.
If you must include a snapshot, send a compact diff or minimal representation and document size limits. Large payloads increase failure rates and make retries more expensive.
Practical retry strategy
Retry policies that look good on paper often fail at scale. Use exponential backoff with jitter to avoid thundering herds. A practical schedule might be:
- Initial attempt
- Retry after ~1–5 seconds
- Retry after ~30 seconds
- Retry after ~5 minutes
- Retry after ~1 hour
- Final attempts spread over subsequent hours up to your retention window (e.g., 24–72 hours)
Don’t retry forever. Define a clear retention window and a final failure path (dashboard alert, dead-letter webhook, or email to the integration owner).
Honor receiver signals
Treat all 2xx responses as success and stop retries. Other responses should guide retry behavior:
- 2xx: ACK — stop retries
- 4xx: client error — usually do not retry until the consumer fixes configuration (exception: 429)
- 5xx: server error — retry
Support HTTP 202 Accepted with a Location header for asynchronous processing. This avoids spurious retries when the receiver accepted the event but needs time to finish processing.
Idempotency keys and deduplication
Recommend receivers implement idempotency keyed on event_id. Include event_id in both header and body. Receivers should store processed event_ids for at least the retry window so duplicate deliveries are discarded.
Example: a field service app receiving assignment.created twice can check the event_id and avoid creating two assignments or double-notifying a technician.
Ordering and stateful workflows
Many workflows depend on order: assignment.created then assignment.updated. Webhooks can arrive out of order because of retries and network latency. If order matters, add a sequence number or last_known_version so receivers can decide to apply, delay, or stash a message.
For strict ordering, use a single-threaded consumer or a reconciliation step: trigger a lightweight update and have the receiver fetch the canonical resource before making stateful decisions.
Security and replay protection
Sign every webhook and publish your public keys or secret-rotation policy. Include a timestamp and TTL, and reject signatures older than your replay window.
Log signature failures and provide tools for customers to test and rotate secrets. Make security errors visible in webhook dashboards so integration owners can act quickly.
Operational visibility: telemetry and dead-letter queues
Visibility is where most integrations fail. Provide customers and internal teams with:
- Delivery logs showing attempts, response codes, latency, and response bodies
- Retry counts and next-attempt timestamps
- Dead-letter queue for events that exhausted retries, with an easy replay option
- Metrics and alerts: failed delivery rate, average latency, top failing endpoints
At scale, surface delivery SLAs and publish customer-facing incident updates when delivery is degraded.
Backoff strategies for rate limits and downstream congestion
When a receiver returns 429 with Retry-After, back off appropriately. If many consumers fail at once, consider a circuit breaker: pause retries for the failing endpoint for a short window and notify the integration owner.
Real-world example: field service dispatch
A dispatch platform that assigns technicians by webhooks faces two common issues: duplicate assignment.created events can double-book technicians, and delayed events without timestamps can show stale assignments in the mobile app.
Mitigations:
- Use event_id to de-duplicate
- Include created_at and version so clients can ignore stale updates
- Keep payloads small and include a resource link so clients fetch the latest state before notifying users
- Surface dead-letter alerts so ops can fix unprocessed assignments within SLA
How to communicate behavior to integrators
Publish a clear webhook contract that covers:
- Fields in the event envelope and their meaning
- Retry schedule and retention window
- Expected response codes and their effects
- Signing and replay protection details
- Debugging tools (test endpoints, delivery logs, replay buttons)
Good documentation reduces support load and increases adoption.
Where platform tooling helps
Platform tooling can handle reliable delivery, retries, and delivery logs so your product team doesn’t need to maintain a custom retry engine. Surface delivery dashboards and a replay feature so customers can debug and recover without creating support tickets.
Checklist: quick operational steps
- Add event_id, event_type, created_at, resource_id, and version to every event
- Keep payloads small; provide resource links for full fetches
- Use exponential backoff with jitter and a bounded retry window
- Treat 2xx as success; use 4xx vs 5xx to guide retries
- Require idempotency handling on receivers (event_id dedupe)
- Sign webhooks, include timestamps, and publish rotation policy
- Provide delivery logs, dead-letter queues, replay tools, and alerts
Treat webhooks as product-level hygiene
Webhooks are a user-facing contract. Design for predictable behavior, instrument thoroughly, document clearly, and provide recovery tools. That approach reduces manual remediation and improves trust in your integrations.
More reading
Recent posts
How to Expose the Right Job and Customer Data in Your Portal — Without Giving Full Backend Access
Customer portals should give users the information they need without turning your backend into an open book. This post outlines practical patterns and controls for exposing job and customer data safely, with good UX and minimal operational coupling.
Field Service Reporting APIs: Cut Manual Work and Give Better Visibility to Operations and Customers
Field service reporting APIs let operations automate job data capture, deliver real‑time visibility to customers and managers, and replace manual paperwork with auditable records. This reduces rework and speeds billing and compliance.
How to Expose the Right Customer and Job Data in Your Portal Without Opening Your Backend
Customer portals need to show up-to-date job and account information without exposing internal systems or sensitive data. This post outlines practical patterns to surface the right data safely and reliably.