Under the hood

Every event takes the same path.

Dispatch runs every webhook through one pipeline: ingest, verify, filter, format, deliver. No special cases, no silent drops. This page walks the path.

The pipeline, end to end

at-least-once delivery · up to 7 attempts over 6h backoff · every attempt logged

01Ingest

Every event starts as a plain HTTP POST to your endpoint. No SDK, no agent: if a service can send a webhook, Dispatch can receive it.

The payload and headers are captured exactly as the provider sent them. The event type is read from the provider's header, like X-GitHub-Event or X-Event-Key, or from a path you configure on the endpoint.

  • One endpoint URL per project, any number of providers
  • Full payload and headers kept for every event
  • Event type extraction from headers or a configured payload path
endpoints docs
POST /hooks/acme-platform

X-GitHub-Event: push

X-Hub-Signature-256: sha256=4f1a9c…

Content-Type: application/json

{

"ref": "refs/heads/main",

"commits": [{ "message": "fix: rate limiting" }],

"sender": { "login": "alice" }

}

02Verify

Before an event is trusted, its signature is checked against the provider's own scheme. GitHub signs with HMAC-SHA256, Slack adds a timestamp to defeat replays, Stripe uses signing secrets, Jira sends a signed JWT.

Events that fail verification are rejected before they enter the pipeline. Forged or tampered payloads never reach a destination.

  • Per-provider schemes handled out of the box
  • Custom signing secrets for your own services
  • Failed verification is rejected, not warned about
verification docs
signature schemes
  • githubHMAC-SHA256
  • slackHMAC + timestamp
  • stripewhsec_ secret
  • jiraHS256 JWT
Verified before storage. Rejected events never fan out.

03Filter

Not every event deserves a delivery. Before fan-out, each event is checked against your filter conditions: match on any header, any field in the body, or the event type.

Conditions combine with AND or OR, and groups of conditions handle the more complex cases. Events that don't match aren't dropped; they're stored as filtered, searchable and replayable like everything else.

  • Evaluated on ingress, before anything is queued for delivery
  • Filtered events stay in your event history
  • Reusable named filters shared across endpoints and routing rules
filters docs
push events onlyAND

header.X-GitHub-Event eq "push"

body.ref contains "main"

body.deleted neq true

eq · neq · contains · not_contains · exists · not_exists · regex

04Format

Raw provider JSON is unreadable in a chat channel. Templates turn the payload into the right shape per platform: Discord embeds, Slack Block Kit, Telegram HTML.

Templates use Go text/template syntax with the full payload in scope. Before formatting, an optional JSONata transform can reshape the payload; if a transform errors, the original payload is used. No template at all? The event ships as a clean JSON embed.

  • One template, per-platform output for every destination
  • JSONata transforms with fail-open behavior
  • Live preview against a real example payload in the editor
templates docs

Template

{{ .sender.login }} pushed {{ len .commits }} commit(s) to {{ .repository.name }}

rendered for discord

alice pushed 1 commit(s) to acme-api

fix: rate limiting

05Deliver

Delivery is where webhooks usually get flaky: rate limits, timeouts, transient 5xx. Dispatch retries with exponential backoff, up to 7 attempts over 6 hours, independently per destination.

Every attempt is logged with its status code and latency. Discord and Slack rate limits are respected automatically, and any event can be replayed with one click. At-least-once delivery, not best-effort.

  • Exponential backoff, per-destination retry overrides
  • Failure alerts by email or straight to a destination
  • One-click replay from the event log
delivery docs
delivery attempts
  • #1 discord · #dev20047ms
  • #1 api.acme.dev503timeout
  • #2 api.acme.dev20089ms · +30s backoff
Retries continue up to 7 attempts over 6 hours, then park in the dead-letter queue.

Run your first event through it.

Create an endpoint, point a provider at it, and watch the deliveries land. Free plan, no credit card required.