Core concepts
import { Aside } from ‘@astrojs/starlight/components’
Understanding these four concepts covers everything Hookman does.
Organisation (org)
An organisation is the top-level container for all your Hookman resources. Every project, deployment, API key, and webhook log belongs to an org.
When you sign up, Hookman automatically creates a personal org for you. On the free tier this is invisible — your dashboard goes straight to your projects. Named orgs with multiple members are a Pro/Team feature.
Your org slug appears in your endpoint URLs:
https://hookman.dev/w/{org}/{project} ^^^See Organisations for details on named orgs and team management.
Project
A project maps to one webhook integration. Think of it as the answer to: “what is this webhook about?”
Good examples:
payments— your Stripe checkout and subscription webhooksgithub-events— webhooks from your GitHub repositoriesnotifications— your Paddle billing webhooks
Each project has:
- A slug that forms part of its endpoint URL (immutable after creation)
- A set of registered deployments
- A routing configuration — which method to use to pick a deployment
- An active deployment — the current target when using manual switching
- A log of every inbound webhook
A project does not map 1:1 with an application or repository. You might have one app and three projects (payments, notifications, platform-events), or one project used across multiple apps if they share the same webhook path.
Deployment
A deployment is a registered target URL — one branch of your application.
label: feature/checkouttarget URL: https://pr-42.myapp.com/api/webhooks/stripeDeployments have:
- A label — typically the branch name. Used as the routing key for header and payload routing.
- A target URL — the full URL that Hookman will POST to, including path.
- An active flag — when using manual switch routing, the active deployment receives all webhooks.
Deployment labels are unique within a project. Registering a label that already exists updates the URL — it doesn’t create a duplicate. This makes hookman register safe to call on every deploy.
Routing
Routing is how Hookman decides which deployment to forward an incoming webhook to.
There are three strategies:
| Strategy | How it works | When to use it |
|---|---|---|
| Manual switch | You explicitly set which deployment is active. All webhooks go there until you change it. | When you’re the only developer, or you want full control. |
| Header routing | Hookman reads a specific request header to pick the deployment. | When your CI/CD or calling service can inject a header. |
| Payload routing | Hookman reads a field from the JSON body to pick the deployment. | When your webhook payload already contains environment/branch info. |
The strategies are evaluated in order: header → query param → payload → active deployment (manual switch). If none resolve, Hookman returns a 422.
See Routing strategies for configuration details.
The proxy
The proxy is the part of Hookman that actually forwards webhooks. It runs on Cloudflare Workers at the edge.
When a webhook arrives at https://hookman.dev/w/{org}/{project}:
- The proxy looks up the project config from Cloudflare KV (typically < 1ms)
- It resolves which deployment to use (based on your routing config)
- It forwards the request to the deployment’s target URL — same method, same headers, same body
- It adds a small set of
x-hookman-*headers to the forwarded request (see Proxy headers) - It streams the response back to the original caller
- After responding, it logs the event and writes usage metrics (non-blocking)
The proxy adds < 5ms of overhead in the P99 case. It does not modify, buffer, or inspect the body beyond what’s needed for payload routing.
Webhook log
Every inbound webhook is logged. The log entry captures:
- Timestamp, HTTP method, source IP
- Which routing method was used and what key was resolved
- Which deployment it was forwarded to
- The HTTP status and latency of the response from your target
- Whether the payload is stored for replay
Log retention depends on your plan: 7 days (Free), 30 days (Pro), 90 days (Team).