Build on it guides
Build on it
Inbound webhooks
Tenant-scoped public routes, signature checks, replay windows, and canonical ingest.
Updated September 4, 2026 1 min read
Provider inbound events land under src/app/api/public/[tenantSlug]/webhooks/<provider>/. The tenant slug is in the path so the handler can resolve tenant context before it touches data.
What the handler does
- Resolve the tenant from the slug. Unknown slug fails closed.
- Verify the provider signature with
timingSafeEqual. Reject the request if it does not match. - Reject replays outside a bounded time window.
- Call a canonical service (
inbound.ts,identity.ts,activities.ts, or the provider's adapter ingest function). Do not insert operational rows in the route. - Return a truthful receipt. HTTP 200 is not proof if the service returned a failure.
What the handler must not do
- Use
createPlatformServiceRoleClientfor tenant writes. UsecreateServiceRoleClient(provider.context)so every row carriestenant_id. - Log raw payloads, signatures, or tokens.
- Call a provider SDK that the existing adapter path already covers.
New providers belong as an integration adapter plus a webhook folder named for that provider. WhatsApp and HubSpot are the current examples on that generic path.