Skip to content

How It Works

Sparrow accepts webhook registrations and event definitions, fans out events to matching subscribers, and delivers them reliably with retries and health tracking.

  1. Register an event type — tell Sparrow what events exist in your system.

  2. Register a webhook — provide a URL and the events it should receive. Sparrow creates subscriptions automatically.

  3. Push an event — when something happens, send the event payload to Sparrow:

    Terminal window
    curl -X POST "http://localhost:8080/v1/consumers/default/events?event=order.created" \
    -H "Content-Type: application/json" \
    -H "X-API-Key: sk_live_..." \
    -d '{
    "payload": {"order_id": "ord_123", "total": 49.99},
    "idempotency_key": "idem_ord_123"
    }'
  4. Sparrow fans out — the event worker finds all active subscriptions matching the event name, consumer, and label filters, applies any payload transforms, and creates a delivery job for each.

  5. Webhook delivery — the webhook worker sends an HTTP POST to each URL with the payload, Standard Webhooks signatures (HMAC and/or Ed25519), and Sparrow headers. Failed deliveries are retried with exponential backoff.

  6. Track results — query delivery status, health metrics, and error categories through the API or the web UI.

Flow: Push Event goes to the Event Worker, which finds subscriptions and creates deliveries; the Webhook Worker then either records the result on success or retries with backoff on failure. Flow: Push Event goes to the Event Worker, which finds subscriptions and creates deliveries; the Webhook Worker then either records the result on success or retries with backoff on failure.

An event represents something that happened in your system — order.created, user.signed_up, payment.failed, etc. Event types can be registered explicitly, which lets you attach a description and a JSON Schema:

Terminal window
curl -X POST http://localhost:8080/v1/event-types \
-H "Content-Type: application/json" \
-H "X-API-Key: sk_live_..." \
-d '{"name": "order.created", "description": "Fires when a new order is placed", "active": true}'

Event registrations act as a versioned schema registry. Pushing an unregistered event type returns 404 (set SPARROW_AUTO_REGISTER_EVENTS=true in development to create it on first push); pushing an event type that was deactivated is rejected. Changing a type’s schema creates a new version and keeps the old one, and event types are never deleted. See Event Type Versions and, to promote definitions between environments, Moving Event Types Between Environments.

A webhook is a registered HTTP endpoint that receives event notifications. When you register a webhook, you provide a URL and optionally a secret for HMAC signature verification:

Terminal window
curl -X POST http://localhost:8080/v1/consumers/default/webhooks \
-H "Content-Type: application/json" \
-H "X-API-Key: sk_live_..." \
-d '{
"url": "https://your-app.com/webhooks",
"events": ["order.created"],
"active": true
}'

When you include events during registration, Sparrow automatically creates subscriptions linking that webhook to those event types.

A subscription connects a webhook to an event type. It controls which events a webhook receives and can optionally transform the payload using Go templates.

Subscriptions are created automatically when you register a webhook with events, but you can also manage them explicitly:

Terminal window
curl -X POST http://localhost:8080/v1/consumers/default/subscriptions \
-H "Content-Type: application/json" \
-H "X-API-Key: sk_live_..." \
-d '{
"webhook_id": "YOUR_WEBHOOK_ID",
"event_name": "order.created"
}'

You can enable payload transforms on a subscription to reshape the event payload before delivery — useful for adapting events to third-party formats like Slack or PagerDuty.

A delivery is a single attempt (or series of retry attempts) to send an event payload to a webhook URL. Sparrow tracks every delivery with:

  • HTTP status code and response body
  • Response time
  • Error classification (timeout, DNS, TLS, connection refused, etc.)
  • Retry count and next attempt time
  • Async by default — the push-event endpoint (POST /v1/consumers/{consumer}/events) returns immediately. Processing and delivery happen in background workers via a persistent job queue (River).
  • At-least-once delivery — retryable failures (server errors, timeouts, connection issues, rate limiting) are automatically retried. Non-retryable failures (DNS errors, TLS errors, 4xx responses) are recorded and not retried.
  • Per-webhook health tracking — Sparrow monitors consecutive failures, success rates, and response times for each webhook independently, with a state machine (healthy → degraded → unhealthy).
  • Cryptographic signing — every delivery is signed in the Standard Webhooks format: HMAC-SHA256 by default, or Ed25519 per webhook (Ed25519 webhooks carry both signatures, so consumers verify with a shared secret or a public key).
  • 10-category error classification — failures are classified into specific categories (DNS, TLS, timeout, connection refused, rate limited, client error, server error, etc.) with retryability flags, so you know why a delivery failed.
  • PostgreSQL only — no Redis, no message broker. The River job queue runs inside PostgreSQL, keeping the operational footprint to a single database.
  • Consumers — webhooks and events are organized into consumers for logical separation (e.g., billing, notifications). A default consumer is always available.
  • Soft schema validation — event schemas produce warnings, not errors. Events are always accepted and stored, with a schema_valid flag for filtering.

Sparrow simplifies architecture across multiple common software patterns:

1. Reliable Outbound Webhooks for B2B SaaS Platforms

Section titled “1. Reliable Outbound Webhooks for B2B SaaS Platforms”

If you build a SaaS platform (like Stripe, GitHub, or Shopify) that sends customer-configured webhooks, Sparrow acts as your dedicated outbound gateway:

  • Customers register their endpoints and HMAC secrets.
  • Your backend pushes events to Sparrow with idempotency_key guarantees.
  • Sparrow signs each HTTP request with Standard Webhooks signatures, retries failures with exponential backoff, tracks endpoint health (healthy/degraded/unhealthy), and provides full delivery visibility.

2. Internal Microservice Event Bus & Fan-Out

Section titled “2. Internal Microservice Event Bus & Fan-Out”

Instead of building heavy Kafka or RabbitMQ integrations just to notify internal microservices:

  • Services emit domain events (e.g., user.signup) to Sparrow via simple REST calls.
  • Internal subscribers (Billing, Email Marketing, Analytics, Security Audit) register webhooks.
  • Subscriptions use label filters (env=prod) and payload transforms to ensure services only receive relevant, cleanly shaped data.

3. Automated Third-Party Integration Gateway

Section titled “3. Automated Third-Party Integration Gateway”

With Sparrow’s recipes and satellites, you can integrate core business events with Slack, PagerDuty, Discord, ClickHouse, or S3 with zero custom code:

  • Firing an event automatically creates PagerDuty incidents on critical errors.
  • Posts rich Block Kit cards into Slack channels on sales conversions.
  • Streams full transaction streams into S3/MinIO for audit compliance.