Guide
Provider Event Routing
Provider event routing is the practical pattern behind Stripe billing webhooks, GitHub automation, Shopify operations, Twilio notifications, and internal webhook producers.
In FastHook, the provider sends to a source URL. FastHook captures an accepted request, then each connection branch decides whether to filter, transform, delay, retry, and deliver to its destination.
Use one source per provider account and environment, one connection per consumer branch, and one destination per receiver endpoint. If several branches feed the same receiver URL, reuse the same destination_id instead of creating duplicate destinations.
Provider Route Model
A provider route should be visible in the resource graph. The source owns ingress: the public hook URL, allowed HTTP methods, source authentication, disabled state, custom response, and request evidence. Connections own branch behavior: filters, transformations, delays, retry policy, pause state, and event evidence.
Destinations represent receiver endpoints. The backend rejects duplicate destination endpoint URLs, so a shared receiver should be one destination record connected from multiple provider branches.
- Create one source for each provider account and environment, such as stripe-prod or github-staging.
- Create one destination for each unique receiver endpoint URL.
- Create one connection for each consumer branch that needs its own filter, transform, retry, or pause behavior.
- A single accepted request can produce several branch events.
- Event and attempt status are branch-local, so one destination failure does not make sibling branches failed.
Provider dashboard
-> FastHook source URL
-> req_* accepted
-> connection billing -> des_billing_api
-> connection fulfillment -> des_fulfillment_api
-> connection analytics -> des_analytics_or_shared_receiverConfigure Provider Ingress
Paste the FastHook source URL into the provider dashboard, then configure the source to match what that provider can send. Most public provider routes should accept only POST and should use HMAC, Basic Auth, or API key verification when the provider supports it.
When FastHook returns 2xx from the source URL, the accepted request has been captured as durable request evidence. That does not mean every destination branch already processed the event.
- Register the exact FastHook source URL in the provider dashboard.
- Limit allowed_http_methods to the methods the provider actually uses.
- Enable source auth before production traffic when the provider supports signatures or secrets.
- Use custom_response only for the acknowledgement body or content type the provider expects.
- Send one provider test event and inspect the Request before adding many branches.
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-prod",
"type": "WEBHOOK",
"status": "enabled",
"config": {
"allowed_http_methods": ["POST"],
"auth_type": "HMAC",
"auth": {
"secret": "whsec_provider_secret",
"signature_header": "stripe-signature"
},
"custom_response": {
"content_type": "json",
"body": "{\"received\":true}"
}
}
}'Branch By Consumer
Put routing decisions on connections, not on the source. That keeps each consumer independently explainable: the billing branch can filter invoice events, the warehouse branch can transform order events, and the analytics branch can use a different retry or rate-limit posture.
Connection rule shapes are saved in the rules array. Keep existing rules when patching a connection; replacing the array with only a new filter can accidentally remove retry, delay, transform, or deduplication behavior.
- Use filter rules for stable provider fields such as event type, topic, action, headers, path, or query.
- Use a transform rule only on the branch whose receiver needs a different contract.
- Use retry and delay rules per destination branch, not globally across every consumer.
- Use one shared destination_id when multiple connections deliver to the same receiver URL.
- Pause one connection when one receiver is down; do not disable the source unless provider ingress itself is unsafe.
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-invoice-paid-to-billing",
"source_id": "src_stripe_prod",
"destination_id": "des_billing_api",
"rules": [
{
"type": "filter",
"body": {
"type": "invoice.paid"
}
},
{
"type": "transform",
"transformation_id": "trs_invoice_contract"
},
{
"type": "retry",
"strategy": "exponential",
"interval": 1000,
"count": 5,
"response_status_codes": ["429", "500-599", "!501"]
}
]
}'Choose Stable Provider Fields
Provider payloads are not all shaped the same way. Pick fields that stay stable across retries and API versions, and avoid filtering on values that are meant to change on every delivery.
- Stripe: filter by body.type, body.data.object.id, body.livemode, and keep receiver idempotency around provider event ids.
- GitHub: filter by x-github-event, x-github-delivery, action, ref, repository, and branch context.
- Shopify: filter by topic, shop, order id, inventory item id, or the provider header/body fields your app already trusts.
- Twilio and notification providers: expect quick retries after timeout and keep destination rate limits conservative.
- Internal producers: include event_id, type, version, tenant, and idempotency keys so deduplication and replay stay precise.
{
"type": "filter",
"headers": {
"x-github-event": "push"
},
"body": {
"ref": "refs/heads/main",
"repository": {
"full_name": "example/api"
}
}
}Inspect First Provider Events
After sending the first provider test event, inspect from ingress outward. The Request confirms source acceptance or rejection. Events and ignored_events explain connection branch decisions. Attempts show destination delivery and receiver response.
Do not debug receiver logs first when the branch was filtered, paused, deduplicated, failed in transformation, or never created an outbound attempt.
- Use request evidence to confirm source_id, method, path, headers, body, accepted status, and verified flag.
- Use events to inspect branches that were created for delivery.
- Use ignored_events to explain branches skipped by routing rules.
- Use attempts to inspect receiver status, response body, and retry history.
- Store req_*, evt_*, and att_* ids in incident notes before retry or replay.
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" \
-H "Authorization: Bearer fhp_xxx" \
-H "x-team-id: tm_xxx"Operate Provider Incidents
Treat provider recovery as a scoped operation. If one receiver is down, pause or retry that connection branch. If routing was wrong at ingress or source config, replay accepted requests through the current route after the fix. If many matching rows failed, start with one event retry before bulk recovery.
Filter metrics and bulk recovery by the exact ids you already saw: source_id for provider ingress, connection_id for branch behavior, destination_id for receiver health, and time windows for incident boundaries.
- Pause one connection when only one consumer is unhealthy.
- Retry one failed event after the receiver accepts a fresh test.
- Replay requests when the source gate or route shape was wrong at the time of ingest.
- Use bulk recovery only after the filter exactly matches the intended provider, branch, status, and time window.
- Record provider ids and FastHook ids together in the postmortem.
curl "https://api.fasthook.io/v1/metrics/deliveries?source_id=src_stripe_prod&connection_id=conn_billing&from=2026-05-30T00:00:00Z&to=2026-05-30T01:00:00Z" \
-H "Authorization: Bearer fhp_xxx" \
-H "x-team-id: tm_xxx"
curl -X POST "https://api.fasthook.io/v1/events/evt_xxx/retry" \
-H "Authorization: Bearer fhp_xxx" \
-H "x-team-id: tm_xxx"Common Mistakes
- Using one source for production and staging provider traffic.
- Hiding several consumer branches behind one connection and one receiver.
- Trying to create duplicate destinations with the same receiver URL instead of reusing one destination_id.
- Copying staging source_id, destination_id, or transformation_id into production route automation.
- Filtering on provider delivery ids or timestamps that change on each retry.
- Replacing the whole rules array and accidentally removing retry, delay, transform, or deduplicate rules.
- Treating a FastHook 2xx source response as proof that every destination processed the event.