Config-driven webhook gateway. Receive HTTP webhooks, validate them, and route messages to queues.
External service (GitHub, Stripe, Coolify, etc.)
→ POST https://hooks.yourdomain.com/webhooks/github
→ Hookpipe matches the webhook from config
→ validates the request (signature, bearer token, IP)
→ picks targets, optionally by header or JSON body (JSONPath)
→ wraps the request in a message envelope
→ publishes to brokers (RabbitMQ, Kafka, SQS, HTTP, stdout, …)
→ returns 202 Accepted
docker run -p 8080:8080 \
-v ./config:/app/config \
-e RABBITMQ_URL=amqp://guest:guest@rabbitmq:5672 \
ghcr.io/runax-software/runax-hookpipe:latestReleases up to 0.2.1 were published as ghcr.io/runax-software/hookpipe. The next release is the
first under the new name.
git clone https://github.com/runax-software/runax-hookpipe.git
cd runax-hookpipe
cp .env.example .env
# Start RabbitMQ + Kafka (optional)
docker compose up -d
dotnet run --project src/Runax.Hookpipe.ApiThe engine is the Runax.Hookpipe library, which the service above is built on:
builder.Services.AddRunaxHookpipe(hookpipe => hookpipe.LoadYaml("config/hookpipe.yaml"));
// ...
app.MapHookpipe();
app.MapHookpipeHealth();The package isn't on NuGet yet; reference src/Runax.Hookpipe until it is.
curl -X POST http://localhost:8080/webhooks/test-webhook \
-H "Content-Type: application/json" \
-d '{"hello":"world"}'Define brokers and webhooks in config/hookpipe.yaml. Webhooks publish to targets written
broker:topic:
version: 2
brokers:
rabbit:
type: rabbitmq
settings:
uri: ${RABBITMQ_URL}
exchange_name: webhooks
webhooks:
github: # POST /webhooks/github
validate:
- type: hmac-sha256
header: X-Hub-Signature-256
secret: ${GITHUB_WEBHOOK_SECRET}
message:
headers: [X-GitHub-Event, X-GitHub-Delivery]
route:
- when: { header: X-GitHub-Event, eq: ping }
to: none # acknowledge and drop
- when: { jsonpath: "$.action", in: [opened, reopened] }
to: rabbit:github.opened
- to: rabbit:github.eventsThe loader is strict: unknown keys, missing secrets, and unknown brokers fail startup with the config path of each problem. See Configuration for the full reference, and Upgrading to move a v1 file over.
Hookpipe watches the config file and reloads automatically when it changes. Validators, routes, targets, message config, and allowed methods change without a restart. See Configuration for details.
| Broker | Type | Topic means |
|---|---|---|
| Stdout | stdout |
— |
| HTTP relay | http |
URL path (optional) |
| RabbitMQ | rabbitmq |
Routing key |
| Kafka | kafka |
Topic |
| SQS | sqs |
Queue (mapped to a URL) |
| SNS | sns |
Topic (mapped to an ARN) |
| EventBridge | eventbridge |
Detail type |
| Redis Streams | redis |
Stream key |
| Google Pub/Sub | google-pubsub |
Topic ID |
| Azure Service Bus | azure-servicebus |
Queue or topic |
| Azure Event Hubs | azure-eventhubs |
Event hub |
See Brokers for details.
| Validator | Type | Use case |
|---|---|---|
| Bearer token | bearer |
Coolify, custom webhooks |
| HMAC-SHA256 | hmac-sha256 |
GitHub, Shopify |
| Stripe | stripe-v1 |
Stripe webhooks |
| API key | api-key |
Custom header + key |
| IP allowlist | ip-allowlist |
Restrict by IP/CIDR |
See Validators for details.
Every webhook is wrapped in a standardized envelope:
{
"id": "13979c7e-108c-48b1-aac5-ff9220a3875b",
"webhookId": "github",
"receivedAt": "2026-05-07T16:23:55.644839+00:00",
"method": "POST",
"path": "/webhooks/github",
"remoteAddress": "192.30.252.1",
"headers": { "X-GitHub-Event": "push" },
"body": { "ref": "refs/heads/main" },
"metadata": {}
}See Message Envelope for full format.
| Variable | Description | Default |
|---|---|---|
HOOKPIPE_CONFIG_PATH |
Path to YAML config | config/hookpipe.yaml |
SEQ_URL |
Seq server URL | — (disabled) |
LOKI_URL |
Grafana Loki URL | — (disabled) |
The request body limit is a config key, not an env var: server.max_body_size for the whole
process, and max_body_size on a webhook for just that route.
Broker connection strings and secrets are whatever variables your config references with
${…}. See Configuration for all env vars and Logging
for log destinations.
| Method | Path | Description |
|---|---|---|
GET |
/health |
Liveness check |
GET |
/health/brokers |
Live probe of every broker |
GET |
/metrics |
Prometheus metrics |
| config | /webhooks/* |
Webhooks from config (prefix configurable) |
See Metrics for available metrics and Prometheus scrape config.
See CONTRIBUTING.md.