Guide
Receive Webhooks
Receiving webhooks starts with a stable FastHook source URL and a clear owner. Providers send traffic to the source URL; FastHook records the inbound request before routing accepted events to destinations.
This guide is the starting point for provider setup, source configuration, request capture, first-route delivery, and the production checks that keep a webhook route understandable after traffic grows.
The source response proves FastHook accepted or rejected ingress. Destination delivery is proved later with Events and Attempts.
What You Will Build
You will create a webhook ingress route that accepts provider traffic at a FastHook source URL, records every accepted or rejected request, then delivers accepted events to your receiving service.
- A source URL that the provider can call.
- A destination that points at your application, staging service, mock endpoint, or CLI tunnel.
- A connection that links the source to the destination.
- A test webhook that proves the full path from provider to receiver.
- Request, event, and attempt records you can inspect during debugging.
How Receiving Works
FastHook separates inbound receipt from outbound delivery. The source decides whether the provider request is accepted or rejected. Connections decide where an accepted request should go. Destinations receive the final outbound delivery attempt.
A source with no authentication can still accept traffic, but accepted requests are marked verified=false. When source auth is configured and the incoming request passes the check, accepted requests are marked verified=true. That verified flag is about provider ingress, not destination delivery.
- Requests show what FastHook received from the provider, including status accepted or rejected, verified, source_id, events_count, ignored_count, and stored data when include=data is requested.
- Events show each routed delivery branch created from an accepted request.
- Attempts show the actual HTTP response from your destination.
- Rejected requests never become delivery events.
- Ignored branch records can be created by filters or deduplication rules before delivery.
Provider
-> FastHook Source URL
-> Request record
-> Event routing
-> Connection rules
-> Destination delivery
-> Attempt record1. Create A Source
Create one source for the producer that sends the webhook stream. A source gives you a stable public URL and a place to configure inbound method, source authentication, custom provider response, and disabled state.
The dashboard creates sources from the Sources page. The public API exposes the same resource through /v1/sources. type defaults to WEBHOOK, and FastHook returns the source id plus the generated hook URL.
- Open Sources in the dashboard.
- Create a source named after the provider and environment, such as stripe-production or github-staging.
- Copy the generated source URL.
- Confirm config.allowed_http_methods includes only the provider methods you expect.
- Enable BASIC_AUTH, API_KEY, or HMAC source auth when the provider supports verification.
- Use config.custom_response when the provider expects a specific acknowledgement body or content type.
curl -X POST "https://api.fasthook.io/v1/sources" \
-H "Authorization: Bearer fhp_xxx" \
-H "x-team-id: tm_xxx" \
-H "Content-Type: application/json" \
-d '{
"name": "stripe-production",
"type": "WEBHOOK",
"config": {
"auth_type": "HMAC",
"auth": {
"secret": "whsec_provider_secret",
"signature_header": "stripe-signature"
},
"custom_response": {
"content_type": "json",
"body": "{\"received\":true}"
},
"allowed_http_methods": ["POST"]
}
}'2. Register The Source URL
Paste the FastHook source URL into the provider dashboard or producer configuration. The provider should send traffic to FastHook, not directly to your application.
When a provider preserves paths, keep path forwarding in mind for the destination side. The source URL is the ingress endpoint; destination path behavior is controlled by the destination and connection route.
- Use the exact source URL, including its trailing slash when the provider preserves paths.
- Register only the event types you need when the provider supports event selection.
- Keep separate sources for production, staging, and local experiments.
- Send the provider's built-in test event if one is available.
- Keep the provider dashboard open until you see the request appear in FastHook.
3. Configure Verification
Verification lets FastHook reject requests that do not prove they came from the expected provider. Configure verification before sending production traffic whenever the provider supports signatures, basic auth, or API key headers.
- Use HMAC for signed provider payloads, including signature_header, optional timestamp_header, and optional prefix.
- Use API_KEY when the sender can provide a static header value.
- Use BASIC_AUTH when the sender supports HTTP Basic credentials.
- Check that provider timestamp tolerance and header names match the source settings.
- Send a valid provider test event and confirm the request is accepted and verified.
- Send an intentionally invalid request only in staging if you need to confirm rejection behavior.
{
"config": {
"auth_type": "HMAC",
"auth": {
"secret": "whsec_provider_secret",
"signature_header": "x-provider-signature",
"timestamp_header": "x-provider-timestamp",
"prefix": "sha256="
},
"allowed_http_methods": ["POST"]
}
}4. Create A Destination
A destination is the receiver that should get accepted events. It can be a production HTTPS endpoint, a staging service, a mock API destination, or a CLI destination for localhost testing.
Destination auth is separate from source auth. Source auth protects ingress from the provider. Destination auth helps your receiver verify outbound FastHook delivery.
- Use HTTP destinations for deployed receivers.
- Use CLI destinations when you want provider traffic forwarded to localhost through fasthook-cli.
- Choose the HTTP method your receiver expects.
- Set destination auth so the receiver can verify outbound FastHook delivery.
- Set a destination rate limit if the receiver has a known capacity.
curl -X POST "https://api.fasthook.io/v1/destinations" \
-H "Authorization: Bearer fhp_xxx" \
-H "x-team-id: tm_xxx" \
-H "Content-Type: application/json" \
-d '{
"name": "billing-api-production",
"type": "HTTP",
"config": {
"url": "https://api.example.com/webhooks/stripe",
"http_method": "POST",
"auth_type": "FASTHOOK_SIGNATURE",
"auth": {},
"rate_limit": 60,
"rate_limit_period": "minute"
}
}'5. Connect Source To Destination
A connection is the route between one source and one destination. Once the connection is enabled, accepted source requests can create outbound events for that destination.
Use one connection per downstream consumer. If the same provider stream needs billing, analytics, and audit receivers, create three connections so each branch has separate rules, status, attempts, and retry controls.
- Create a connection from the source to the destination.
- Name the route after both sides, for example stripe-to-billing.
- Add filters when the destination only needs some event types.
- Add transformations when the receiver needs a different payload shape.
- Add retry and delay rules when the receiver needs controlled recovery behavior.
curl -X POST "https://api.fasthook.io/v1/connections" \
-H "Authorization: Bearer fhp_xxx" \
-H "x-team-id: tm_xxx" \
-H "Content-Type: application/json" \
-d '{
"name": "stripe-production-to-billing-api",
"source_id": "src_xxx",
"destination_id": "des_xxx",
"paused_at": null,
"disabled_at": null,
"rules": [
{ "type": "filter", "body": { "type": "invoice.created" } },
{
"type": "retry",
"strategy": "exponential",
"interval": 30000,
"count": 5,
"response_status_codes": ["429", "500-599", "!501"]
}
]
}'6. Send A First Test
Use a real provider test event when possible. If you only need to test the FastHook route shape, send a small JSON request to the source URL with curl.
The default FastHook source response includes ok, queued, transport, and request_id. Keep that request_id; it is the fastest way to inspect the exact stored request, routed events, and attempts.
- Use the source URL, not the destination URL.
- Use a method allowed by the source.
- Include headers your filters or verification rules expect.
- Confirm the request appears in Requests.
- Confirm at least one routed event appears in Events.
curl -X POST "https://hook-xxxxxx.fasthook.io/" \
-H "Content-Type: application/json" \
-H "X-Event-Type: invoice.created" \
-d '{
"id": "evt_test_123",
"type": "invoice.created",
"created_at": "2026-05-25T12:00:00Z",
"data": {
"invoice_id": "in_123",
"amount_due": 4200
}
}'Inspect The Delivery Path
Debug from the top of the pipeline downward. Start with the inbound request, then inspect routed events, then inspect attempts for the destination response.
- Requests: confirm FastHook received the webhook, parsed method/path/query/headers/body, and accepted or rejected it.
- Events: confirm the connection created a routed event with the expected source, destination, status, and retry context.
- Attempts: confirm the receiver response status, response body, delivery latency, trigger, and error code.
- Ignored branch records: inspect filter and deduplication skips when a request was accepted but a route did not deliver.
- Metrics: compare request volume, event status, failed attempts, held events, and scheduled retries over the same time window.
curl "https://api.fasthook.io/v1/requests/req_xxx" \
-H "Authorization: Bearer fhp_xxx" \
-H "x-team-id: tm_xxx"
curl "https://api.fasthook.io/v1/requests/req_xxx/events" \
-H "Authorization: Bearer fhp_xxx" \
-H "x-team-id: tm_xxx"
curl "https://api.fasthook.io/v1/requests/req_xxx/ignored_events" \
-H "Authorization: Bearer fhp_xxx" \
-H "x-team-id: tm_xxx"
curl "https://api.fasthook.io/v1/attempts?event_id=evt_xxx&order_by=created_at&dir=desc&limit=100" \
-H "Authorization: Bearer fhp_xxx" \
-H "x-team-id: tm_xxx"Receiver Behavior
A destination should respond quickly and move heavy work to an async worker when possible. Keep the HTTP response focused on acknowledging receipt, then process business logic separately.
Return 2xx only after your app has durably accepted the webhook. Return a non-2xx response when FastHook should treat the delivery as failed and apply retry rules.
- Keep handlers idempotent because providers and operators can replay webhook traffic.
- Validate the outbound FastHook signature when using FastHook-signed delivery.
- Avoid long synchronous database work in the request handler.
- Log the FastHook event id or request id with your internal job id.
- Make 4xx responses intentional and descriptive so failed attempts are easy to inspect.
Production Patterns
- Use one source per provider account and environment.
- Use one connection per downstream consumer so failures are isolated.
- Use filters to keep low-value event types away from constrained receivers.
- Use transformations when each receiver wants a stable internal shape.
- Use destination rate limits for receivers with strict capacity.
- Use pause during receiver maintenance when you want FastHook to hold new routed events.
- Use request retry when you need current routing to run again, and event retry when one destination branch failed.
Common Problems
- No request appears: the provider is not sending to the FastHook source URL, DNS has not updated, or the provider test did not fire.
- Request is rejected: the method, signature, timestamp, or source verification settings do not match the incoming request.
- Request is accepted but no event appears: no enabled connection currently routes from that source, or every route was filtered or deduplicated.
- Branch is ignored: a filter or deduplication rule intentionally skipped the route.
- Event is failed: inspect the latest attempt response body, status code, error code, and requested URL.
- Event is HOLD: the connection is paused and will drain after resume.
- Event is SCHEDULED: delivery is waiting on retry backoff, a delay rule, or destination rate limiting.
Checklist
- Source URL is registered in the provider dashboard.
- Source allowed methods and verification settings match the provider.
- Destination URL, method, auth, path, and rate limit match the receiver.
- Connection is enabled and points from the source to the destination.
- Filters and transformations are tested with real provider payloads.
- Receiver returns quick, intentional 2xx or non-2xx responses.
- Requests, Events, Attempts, and Metrics are checked after the first test.