Skip to content

Concepts

A source is an ingest endpoint. Each source has a unique slug that becomes part of its webhook URL:

POST /webhooks/{slug}

Sources have a mode:

  • active — webhooks are queued for immediate fan-out to all attached actions.
  • record — webhooks are stored but not dispatched. You can inspect payloads and forward them manually when ready.

Sources can also have a transform script — a JavaScript function that runs on every delivery before dispatch. See Scripting.

An action defines where and how a delivery gets dispatched. Actions are attached to a source — when a webhook arrives, all active actions on that source are triggered.

Each action has a type:

TypeDescription
webhookForward the payload to an HTTP endpoint
slackPost to a Slack channel via incoming webhook
smtpSend an email with the payload
twilioSend an SMS via Twilio
javascriptRun a JavaScript function with the payload

Actions can be toggled active/inactive without deleting them.

Each action can also have its own transform script that modifies the payload specifically for that action, or skips the action entirely by returning null.

See Action Types for configuration details.

A delivery is a single inbound webhook event. When a POST hits /webhooks/{slug}, nitrohook:

  1. Stores the raw payload and headers in Postgres
  2. Publishes the delivery ID to a Redis Stream
  3. Returns 202 Accepted with the delivery ID

Deliveries track their lifecycle with a status:

StatusMeaning
pendingQueued, waiting for the worker
processingWorker is dispatching to actions
completedAll actions succeeded (or were skipped)
failedAt least one action exhausted its retries
recordedStored in record mode, not dispatched

Each action dispatch creates a delivery attempt. If an action fails, it retries with exponential backoff up to a configurable maximum (default: 5 attempts).

Attempts store the response status code, response body, and error message for debugging.

The full flow:

Webhook POST → Store in Postgres → XADD to Redis Stream
Worker XREADGROUP
Run source transform script (optional)
For each active action:
→ Run action transform script (optional)
→ Dispatch via action type handler
→ Record attempt result
Roll up delivery status

Workers run as a consumer group, so you can scale horizontally by adding more worker replicas.