Webhooks And Integrations
Coil treats webhook ingress as an operational boundary, not just "some HTTP endpoint."
What Is This?
This page covers how to operate inbound webhooks and adjacent integration paths safely.
Why Does This Matter?
Webhook failures are rarely isolated:
- retries pile up
- signatures drift
- releases change payload assumptions
- duplicate side effects appear quickly
A safe integration story needs host-owned verification, idempotent handling, and operator-visible state.
The Canonical Webhook Model
Treat webhook ingress as a four-stage flow:
- accept the request on a dedicated route
- verify the signature or shared secret before business logic runs
- normalize the payload into a known event shape
- record or route the result through the runtime and operator surfaces
That keeps webhook handling from becoming a pile of ad hoc controller code.
What Operators Should Verify
Before trusting a webhook path in production, verify:
- the endpoint is reachable from the provider
- the correct secret is configured
- signature or shared-secret verification is enabled
- duplicate delivery is safe
- downstream dependencies are healthy
- retry behaviour is understood
A Practical Local Test Flow
For provider callbacks, the minimal operator-safe test loop is:
- run the app locally
- configure the local webhook secret
- forward provider traffic to the local callback route
- confirm verification succeeds
- confirm duplicate or invalid calls fail closed
A representative command shape is:
stripe listen --forward-to http://localhost:8080/webhooks/commerce/payment-provider
You can apply the same pattern to non-Stripe providers: forward, verify, observe, and replay carefully.
Linked Rust And Webhook Handling
If the webhook behaviour is truly customer-owned product logic, linked customer Rust is the right place for the business rule.
That still does not mean the webhook should bypass the host. The runtime should own ingress and verification before customer code handles the verified event.
Sidecars And External Integrations
A separate process boundary can still be correct when:
- a provider integration is operationally independent
- the integration needs a different scaling or security posture
- the boundary is genuinely external-facing
Use that boundary intentionally, not because the framework lacks a first-party customization path.
Supporting Repo Examples
The checked-in examples prove two useful variants:
- Shoppr payment-provider callbacks through the main app runtime
- Shoppr's optional CRM webhook sidecar with explicit shared-secret verification
Those examples are worth reading after this page if you want concrete implementation detail, but the pattern above is the primary teaching model.
Common Mistakes
Treating webhook handling as just another controller
Ingress verification and replay safety are operational concerns, not just app code details.
Testing only with unsigned local requests
That produces a fake green path and hides the real verification behaviour.
Ignoring duplicate delivery
A webhook system that cannot tolerate retries is not production-ready.