Webhook Guides

What Are Webhooks? Developer Guide

Webhooks are HTTP callbacks sent when something happens in another system. Instead of polling an API on a schedule, your application receives event notifications as soon as the provider is ready to send them.

They are the backbone of many SaaS integrations: Stripe sends payment updates, GitHub sends push and pull request events, Shopify sends order changes, Twilio sends message status updates, and internal services send lifecycle events to automation workflows.

This page explains how webhooks work in production, where webhook integrations usually break, and how FastHook helps you receive traffic through sources, route it through connections, inspect requests, debug failed attempts, and replay events safely.

What is a webhook?

A webhook is an HTTP request sent by a provider to a URL you control. The URL is usually called a webhook endpoint, callback URL, source URL, or receiver URL. The request usually includes HTTP headers, an event type, and a JSON payload that describes what changed.

In a normal API workflow, your application asks another service for data. In a webhook workflow, the provider calls your application when it has something to report. That difference sounds small, but it changes how you design reliability: webhooks need fast acknowledgment, durable request capture, retry handling, duplicate protection, signature validation, and useful delivery logs.

Webhooks vs APIs and polling

Webhooks do not replace APIs. Most integrations use both. APIs are useful when your application needs to read or mutate current state. Webhooks are useful when another system needs to notify your application about changes without waiting for your next polling interval.

PatternWho starts the requestBest forOperational risk
API callYour applicationFetching current state or performing a commandRate limits, auth errors, slow responses
PollingYour application on a scheduleSimple sync jobs where delay is acceptableWasted requests, stale data, missed edge cases
WebhookThe provider or event producerReal-time event delivery and automationRetries, duplicates, signature errors, endpoint downtime

How webhooks work

  1. Create a webhook endpoint or FastHook source URL.
  2. Register that URL in the provider dashboard or internal event producer.
  3. The provider sends an HTTP request when an event happens.
  4. FastHook captures the inbound request, headers, and body before routing.
  5. Matching connections create destination-specific events.
  6. Each connection can apply filters, transformations, retries, delays, deduplication, or throughput limits.
  7. FastHook delivers the event to the configured destination and records the attempt status.
  8. Your destination returns a 2xx response when it accepts the event.
Webhook delivery lifecycle from provider event to FastHook source, request record, routed event, destination attempt, retries, and replay.
A production webhook flow should separate provider acknowledgment from downstream delivery evidence. FastHook stores the request first, then routes events through connection rules and records each destination attempt.

Webhook request anatomy

Most webhook requests are simple HTTP POST requests, but the details matter during debugging and signature validation. Treat the request as a contract between the provider, your ingress layer, and your destination service.

  • Method and URL: usually POST to a dedicated webhook endpoint or FastHook source URL.
  • Headers: often include content type, event type, delivery id, user agent, signature, and timestamp fields.
  • Payload: usually JSON with an event id, event type, creation time, and provider-specific data object.
  • Signature: an HMAC or provider-specific signature that should be verified against the raw request body.
  • Response: a fast 2xx response tells the sender the request was accepted; it does not prove every downstream side effect completed.

Common webhook use cases

  • Payment and billing updates, such as invoice paid, payment failed, or subscription changed.
  • Developer workflow events, such as GitHub push, pull request, deployment, issue, or workflow run events.
  • Commerce events, such as order created, order fulfilled, product updated, or inventory changed.
  • Messaging and communications events, such as delivery status, inbound SMS, call events, or email bounces.
  • Internal automation, such as user lifecycle changes, audit events, service notifications, and data sync jobs.

Common webhook problems

  • Endpoint downtime: the provider cannot reach your receiver, or the receiver returns a non-2xx response.
  • Timeouts: the receiver does too much synchronous work before returning a response.
  • Duplicate events: retries repeat the same event and the destination applies the same side effect twice.
  • Signature validation failures: the receiver validates against parsed JSON instead of the raw body or uses the wrong signing secret.
  • Schema drift: provider payloads change, optional fields disappear, or event types differ from the test fixture.
  • Low observability: payloads, headers, attempts, response codes, and response bodies are not visible together.
  • Retry storms: traffic spikes and provider retries overload a destination that is already failing.
Map of webhook failure points across ingress, routing, delivery, receiver processing, and recovery.
Debugging is faster when ingress, routing, destination delivery, receiver processing, and replay are visible as separate stages instead of one opaque endpoint log.

How FastHook solves this

FastHook acts as a webhook gateway between event producers and your downstream services. It gives you stable source URLs, request inspection, outbound event history, delivery attempts, filtering, transformations, retries, deduplication, throughput controls, pause/resume workflows, and replay.

That separation lets you accept provider traffic even when one destination is unhealthy. You can inspect the original request, see which route failed, read the destination response, fix the receiver, and replay only the events that need another delivery attempt.

Webhook testing checklist

A good webhook test covers more than one successful curl request. Before production traffic arrives, test the behaviors that usually fail during incidents.

  • Send realistic payloads for each event type you expect to support.
  • Confirm the inbound request is captured with headers and raw body.
  • Validate signature handling with the same raw-body behavior used in production.
  • Send duplicate events and verify idempotency before side effects run twice.
  • Simulate destination 4xx, 5xx, and timeout responses.
  • Inspect retry attempts and confirm backoff does not overload the receiver.
  • Replay a failed event into staging or localhost before replaying a production batch.

Webhook security basics

A public webhook endpoint should not trust payload fields just because the request reached the URL. Security starts at ingress and continues at destination delivery.

  • Use provider signatures or FastHook source authentication where available.
  • Verify signatures against the raw request body, not a re-serialized JSON object.
  • Use separate source URLs and signing secrets for production, staging, and local testing.
  • Restrict allowed HTTP methods, content types, and destination behavior where possible.
  • Rotate secrets deliberately and keep enough logging to debug failed verification.

Webhook retry and replay strategy

Webhooks are usually at-least-once delivery. That means duplicates are normal, especially when a provider times out or a receiver returns a non-2xx response. Your receiver should treat the event id, delivery id, or business object id as an idempotency boundary before creating side effects.

Retries are best for temporary destination failures. Replay is best when you need to redeliver stored events after fixing code, credentials, schema handling, or a downstream outage. In both cases, inspect the original payload and destination response before redelivering a large batch.

FastHook API shape

The workflow examples below match the current FastHook control API implementation. Authenticated control API calls use a project API key or session token, tenancy comes from x-team-id, and the /v1 prefix is supported for sources, requests, events, and attempts.

  • Sources return a generated url such as https://hook-xxxxxx.fasthook.io/.
  • Source configs support auth_type, auth, custom_response, and allowed_http_methods.
  • Request lists support from, to, source_id, status, cursors, and include=data.
  • Event lists support source_id, connection_id, destination_id, status, from, and to.
  • Delivery attempts are read from /v1/attempts, and a single failed event can be retried with POST /v1/events/:id/retry.

FastHook workflow examples

Create a source for inbound webhook traffic

Create source
curl -X POST "https://api.fasthook.io/v1/sources" \
  -H "Authorization: Bearer fhp_xxx" \
  -H "x-team-id: tm_3b5335b627084a838b" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Provider webhooks",
    "description": "Ingress for provider webhook traffic",
    "type": "WEBHOOK",
    "status": "enabled",
    "config": {
      "auth_type": null,
      "auth": null,
      "allowed_http_methods": ["POST"]
    }
  }'

Send a test webhook (curl)

Send test webhook
curl -X POST "https://hook-xxxxxx.fasthook.io/" \
  -H "Content-Type: application/json" \
  -H "X-Event-Type: payment.succeeded" \
  -d '{
    "id": "evt_123",
    "type": "payment.succeeded",
    "created_at": "2026-04-20T10:00:00Z",
    "data": {
      "customer_id": "cus_42",
      "amount": 1999,
      "currency": "USD"
    }
  }'

Example webhook payload (JSON)

Payload JSON
{
  "id": "evt_123",
  "type": "invoice.paid",
  "attempt": 1,
  "timestamp": "2026-04-20T10:00:00Z",
  "data": {
    "invoice_id": "inv_001",
    "customer_id": "cus_42",
    "total": 4900,
    "currency": "USD"
  }
}

Inspect captured requests

Inspect requests
curl "https://api.fasthook.io/v1/requests?source_id=src_q6z62b6py5o79b&from=now-24h&to=now&status=accepted&limit=20&include=data" \
  -H "Authorization: Bearer fhp_xxx" \
  -H "x-team-id: tm_3b5335b627084a838b"

Inspect routed events for the source

Inspect events
curl "https://api.fasthook.io/v1/events?source_id=src_q6z62b6py5o79b&from=now-24h&to=now&limit=20" \
  -H "Authorization: Bearer fhp_xxx" \
  -H "x-team-id: tm_3b5335b627084a838b"

Inspect destination attempts for one event

Inspect attempts
curl "https://api.fasthook.io/v1/attempts?event_id=evt_01jv8c4n9p3x7r2t6q5m1k0s8b&order_by=created_at&dir=desc&limit=20" \
  -H "Authorization: Bearer fhp_xxx" \
  -H "x-team-id: tm_3b5335b627084a838b"

Retry a failed destination event

Retry event
curl -X POST "https://api.fasthook.io/v1/events/evt_01jv8c4n9p3x7r2t6q5m1k0s8b/retry" \
  -H "Authorization: Bearer fhp_xxx" \
  -H "x-team-id: tm_3b5335b627084a838b"

Webhook FAQ

What is a webhook in simple terms?

A webhook is an HTTP request sent by one app to another app when an event happens, such as a payment succeeding, a repository receiving a push, or an order being created.

Are webhooks the same as APIs?

No. An API is usually called by your app when it wants data or an action. A webhook is called by another system when that system wants to notify your app about an event.

What should a webhook endpoint return?

A webhook endpoint should return a fast 2xx response after the request is accepted. Expensive processing should usually happen after durable capture so provider timeouts do not create avoidable retries.

Why do duplicate webhook events happen?

Duplicates happen because providers retry after timeouts, network errors, and non-2xx responses. Receivers should use idempotency keys or event ids before applying side effects.

How do you debug webhook delivery failures?

Compare the inbound request, routed event, destination attempt, response code, response body, retry count, and payload shape. FastHook keeps these records together so failures can be inspected and replayed.

Try FastHook

Create a FastHook source, connect it to a destination, send test events, inspect inbound requests, and replay failed outbound events from one place. This gives your team a reliable webhook workflow without rebuilding request logs, local forwarding, retries, and replay tooling inside every application.

Related guides