Documentation

API Base URL: https://hookpipe.app

Quick Start

1. Create an API Key

API keys authenticate you for hook management. The key is shown once at creation — save it.

curl -X POST https://hookpipe.app/api/auth/keys \
  -H "Content-Type: application/json" \
  -d '{"name": "my-key"}'

2. Create a Hook

A hook defines a receive endpoint, optional transform rules, and a destination URL.

curl -X POST https://hookpipe.app/api/hooks \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "github-events",
    "destinationUrl": "https://your-app.com/webhook",
    "transformConfig": {
      "fieldMapping": {
        "repo": "repository.name",
        "actor": "sender.login"
      }
    }
  }'

The response includes an id — that's your hook ID for the receive URL.

3. Point Your Webhooks Here

Use https://hookpipe.app/hooks/YOUR_HOOK_ID as the webhook URL in whatever service you're integrating.

# Example: test it manually
curl -X POST https://hookpipe.app/hooks/YOUR_HOOK_ID \
  -H "Content-Type: application/json" \
  -d '{"repository": {"name": "my-repo"}, "sender": {"login": "dev"}}'

Guides

Detailed walkthroughs for specific use-cases. View all guides →


Transform Rules

Transform rules are optional. If you don't set transformConfig, the payload is forwarded as-is.

Field Mapping

Extract nested fields into a flat structure using dot notation:

"fieldMapping": {
  "repo": "repository.name",      // payload.repository.name → result.repo
  "actor": "sender.login",        // payload.sender.login → result.actor
  "action": "action"              // payload.action → result.action (top-level)
}

Filtering

Only forward payloads that match conditions. If a filter doesn't match, the payload is dropped (HTTP 200 returned to sender, nothing forwarded).

"filters": [
  {"field": "action", "operator": "equals", "value": "opened"},
  {"field": "repository.name", "operator": "contains", "value": "prod"}
]

Supported operators: equals, notEquals, contains, notContains, exists, notExists, greaterThan, lessThan.

Field Renaming

"renames": {
  "old_field_name": "new_field_name"
}

Adding Static Values

Add constant values by including them directly in fieldMapping. Use a non-dot-notation key with a literal string:

"fieldMapping": {
  "repo": "repository.name",
  "source": "github",
  "version": "1.0"
}

API Reference

Authentication

All /api/* endpoints require an API key in the Authorization header:

Authorization: Bearer YOUR_API_KEY

The webhook receive endpoint (POST /hooks/:hookId) is public — no auth required.

POST /api/auth/keys

Create a new API key. No authentication required.

BodyTypeDescription
namestringA label for the key

POST /api/hooks

Create a new hook. Requires auth.

BodyTypeDescription
namestringHook name
destinationUrlstringURL to forward transformed payloads to
transformConfigobjectOptional. See Transform Rules

GET /api/hooks

List all hooks. Requires auth.

GET /api/hooks/:id

Get a specific hook. Requires auth.

DELETE /api/hooks/:id

Delete a hook. Requires auth.

GET /api/hooks/:id/logs

Get request logs for a hook. Requires auth.

QueryTypeDefaultDescription
limitnumber100Max entries to return
offsetnumber0Skip entries

GET /api/hooks/:id/payloads

List stored payloads for a hook (most recent first). Requires auth.

QueryTypeDefaultDescription
limitnumber50Max entries (max 200)
offsetnumber0Skip entries

Response includes rawBody (original payload) and transformedBody (after transform rules, if any).

GET /api/hooks/:id/payloads/:payloadId

Get a single stored payload with full body. Requires auth.

POST /api/hooks/:id/payloads/:payloadId/replay

Re-run the transform → forward pipeline for a stored payload. Useful when the original forward failed (destination was down) and you want to retry. Requires auth.

The replayed request includes an X-Replay: true header so your destination can distinguish replays from original deliveries.

POST /hooks/:hookId

Receive a webhook. Public — no auth required. This is the URL you give to external services.

Payload is validated, stored, transformed (if rules exist), and forwarded to the hook's destination URL. Returns a payloadId for later inspection or replay.

GET /health

Health check. Returns {"status": "healthy"} with uptime.


Signature Validation

Verify that incoming webhooks are authentic by checking their HMAC signatures. Supports GitHub, Stripe, and generic HMAC providers.

Configure Signature Validation

curl -X PATCH https://hookpipe.app/api/hooks/HOOK_ID/signature \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "enabled": true,
    "provider": "github",
    "secrets": ["your-webhook-secret"],
    "debug": true
  }'

Supported providers:

Free tier: 1 signing secret per hook. Pro tier: Up to 5 secrets for key rotation — all secrets are tried until one matches.

Set "debug": true during setup to see detailed error messages in 401 responses. Set to false for production (generic error only).

Disable Signature Validation

curl -X DELETE https://hookpipe.app/api/hooks/HOOK_ID/signature \
  -H "Authorization: Bearer YOUR_API_KEY"

Retry Policy

Failed forwarding attempts are retried automatically with exponential backoff.

Configure Retry Policy (Pro)

curl -X PATCH https://hookpipe.app/api/hooks/HOOK_ID/retry \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"maxRetries": 7, "intervalMs": 5000}'

Limits & Notes

Feature Free Pro ($9/mo)
Rate limit 20 req/min per hook 1,000 req/min per hook
Hooks 5 Unlimited
Retries 3 (fixed 1s backoff) Up to 10 (configurable interval)
Signature secrets 1 per hook 5 per hook (key rotation)
Log retention 7 days 30 days
Payload retention 7 days 30 days