Webhook Guides

How to Create a Webhook

To create a webhook, you need a URL that can receive HTTP requests, a sender that knows when to call that URL, a payload contract, authentication, and a way to see whether delivery succeeded. The small demo is easy; the production version needs logs, retries, replay, and duplicate protection.

With FastHook, the public webhook URL is a source. The receiver is a destination. A connection links them and can add filters, transformations, retries, delays, and delivery controls. This keeps creation, testing, and recovery in one workflow instead of scattering scripts across every receiver.

Creation checklist

  1. Decide which event should trigger the webhook.
  2. Create a FastHook source and copy the generated Source URL.
  3. Register that URL in the provider dashboard or internal event producer.
  4. Create a destination for your receiver, local CLI tunnel, mock target, Google Sheet, or Gmail workflow.
  5. Connect the source to the destination with filters for the event type you want.
  6. Send a realistic test request and inspect request, event, and attempt records.
  7. Add source authentication, idempotency, retry policy, and replay runbooks before production.

Create a source URL

A source is the public ingress URL. Use a dedicated source per provider, environment, or signing secret so debugging and secret rotation stay clear.

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": "Order events",
    "type": "WEBHOOK",
    "status": "enabled",
    "config": {
      "auth_type": null,
      "auth": null,
      "allowed_http_methods": ["POST"]
    }
  }'

Create a destination

The destination is where FastHook sends accepted and routed events. For production APIs, use HTTP. For localhost development, use CLI. For testing, use mock. For operations workflows, use Google Sheet or Gmail.

Create HTTP destination
curl -X POST "https://api.fasthook.io/v1/destinations" \
  -H "Authorization: Bearer fhp_xxx" \
  -H "x-team-id: tm_3b5335b627084a838b" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Orders API",
    "type": "HTTP",
    "config": {
      "url": "https://api.example.com/webhooks/orders",
      "http_method": "POST",
      "auth_type": "FASTHOOK_SIGNATURE",
      "auth": {}
    }
  }'

Connect and filter events

Filters prevent every request from reaching every receiver. Start with event type and provider headers, then add business-specific fields only when the provider payload is stable.

Create connection
curl -X POST "https://api.fasthook.io/v1/connections" \
  -H "Authorization: Bearer fhp_xxx" \
  -H "x-team-id: tm_3b5335b627084a838b" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "orders-created-to-api",
    "source_id": "src_q6z62b6py5o79b",
    "destination_id": "des_TU9ioCk5EHUU",
    "rules": [
      {
        "type": "filter",
        "body": {
          "type": { "$eq": "order.created" }
        }
      }
    ]
  }'

Send a test webhook

A good test uses realistic headers, an event id, an event type, and enough business data for the receiver to behave like production.

Test delivery
curl -X POST "https://hook-xxxxxx.fasthook.io/" \
  -H "Content-Type: application/json" \
  -H "X-Event-Type: order.created" \
  -d '{
    "id": "evt_123",
    "type": "order.created",
    "order": {
      "id": "ord_456",
      "total": 4900,
      "currency": "USD"
    }
  }'

Design the payload contract

A webhook is easier to maintain when the payload contract is explicit. Every event should have a stable event id, a type, a creation time, and a data object that contains the business resource that changed. If the sender is internal, write that contract down before other teams start building receivers around it.

Provider payloads are not always under your control, so your receiver should handle missing optional fields and unknown event types gracefully. If you control the sender, keep payloads small and predictable. If the receiver needs more context, it can call an API after the webhook is accepted.

FieldPurposeExample
idIdempotency and replay safety.evt_123
typeRouting and receiver branching.order.created
created_atStale-event checks and incident windows.2026-06-17T10:00:00Z
dataBusiness object that changed.{ order: {...} }
tenant or account idMulti-tenant routing and isolation.acct_456

Choose environments

Do not reuse one webhook URL for local, staging, and production. Separate sources make it obvious which provider secret, destination, and replay policy applies. They also stop local tests from appearing in production analytics or support workflows.

  • Use one source per provider and environment.
  • Use separate signing secrets for local, staging, and production.
  • Use CLI destinations for local development instead of exposing a laptop directly.
  • Use mock destinations before a production receiver exists.
  • Record source ids, destination ids, and provider dashboard URLs in the integration runbook.

Inspect the first delivery

The first successful request is not done until you inspect all three stages: request, event, and attempt. A provider dashboard may show success while your destination still fails later, especially when the source accepted the request but a downstream receiver returned an error.

Inspect source traffic
curl "https://api.fasthook.io/v1/requests?source_id=src_q6z62b6py5o79b&limit=20&include=data" \
  -H "Authorization: Bearer fhp_xxx" \
  -H "x-team-id: tm_3b5335b627084a838b"

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

Launch checklist

  1. Send at least one provider-generated test event, not only a hand-written cURL request.
  2. Force a destination 500 and confirm retry behavior is visible.
  3. Send a duplicate event id and confirm the receiver does not repeat side effects.
  4. Rotate the webhook secret in staging and document the process.
  5. Replay one stored event into staging before enabling production replay workflows.
  6. Add alerts for repeated rejected requests or destination failures.

Production hardening

  • Add provider signatures, HMAC, API key, or Basic Auth before accepting production traffic.
  • Verify raw-body signatures before trusting payload fields.
  • Use event ids or delivery ids for idempotency.
  • Return a fast 2xx only after accepted work is durable.
  • Inspect failed attempts and retry one event before replaying a window.
  • Use separate sources for local, staging, and production.

Related guides