Error codes
import { Aside } from ‘@astrojs/starlight/components’
Proxy errors
These are returned to the webhook sender (Stripe, Paddle, etc.) by the proxy endpoint.
project_not_found — 404
{ "error": "project_not_found", "project": "acme/payments" }Cause: The org slug or project slug in the URL doesn’t match any registered project.
Fix: Check the endpoint URL configured in your webhook provider. The format is https://hookman.dev/w/{org}/{project}.
no_route_resolved — 422
{ "error": "no_route_resolved", "hint": "Rules were evaluated but none matched — set a default catch-all or add a matching rule", "trace": [ /* per-rule evaluation results */ ]}Cause: No routing rule matched the request and there is no active (default) deployment to fall back to.
Fix:
- Set an active deployment so unmatched webhooks have somewhere to go, or
- Add/adjust a routing rule so it matches the incoming request. The
tracearray shows how each rule was evaluated, so you can see why none matched.
quota_exceeded — 429
{ "error": "quota_exceeded", "used": 1000, "limit": 1000, "plan": "free"}Cause: Your org has exceeded its monthly webhook quota.
Fix: Upgrade your plan, or wait until the quota resets at the start of the next billing period (the 1st of each month). Note: Stripe and similar services will retry on 429 — check that this isn’t causing a retry storm.
rate_limited — 429
{ "error": "rate_limited", "retryAfter": 60 }Cause: Too many requests per minute from a single IP to a single project.
Fix: This is unusual in normal webhook delivery (senders don’t typically send hundreds per minute). If you’re seeing this during testing, space out your test requests.
Management API errors
These are returned by api.hookman.dev endpoints.
unauthorized — 401
{ "error": "unauthorized" }Cause: No valid session cookie or API key was provided, or the key has been revoked.
Fix: Include a valid Authorization: Bearer hm_live_xxx header, or re-authenticate your session.
forbidden — 403
{ "error": "forbidden", "reason": "insufficient_role" }Cause: Your API key or session has insufficient permissions for this action. For example, a member role attempting to delete an org.
Fix: Check the role permissions table. Use an API key or account with the required role.
not_found — 404
{ "error": "not_found", "resource": "deployment" }Cause: The resource (org, project, deployment, etc.) doesn’t exist, or you don’t have access to it.
validation_error — 422
{ "error": "validation_error", "fields": { "targetUrl": "Must be a valid HTTPS URL", "label": "Must be 1–100 characters" }}Cause: The request body failed validation.
Fix: Check the fields object for per-field error messages.
plan_limit_reached — 422
{ "error": "plan_limit_reached", "resource": "projects", "limit": 1, "current": 1, "upgradeUrl": "https://hookman.dev/pricing"}Cause: You’ve hit a plan limit — for example, trying to create a second project on the Free tier.
Fix: Upgrade your plan, or remove an existing resource to free up a slot.
Upstream behaviour
Hookman mirrors your deployment’s response verbatim — same status, body and headers. If your target returns a 5xx, the sender sees that 5xx; if it returns 200, the sender sees 200. Hookman does not rewrite upstream statuses.
The only status Hookman synthesises is 502, returned when your target is unreachable (so there’s no response to mirror):
{ "error": "upstream_timeout" }| Log error | Returned status | Meaning |
|---|---|---|
upstream_timeout | 502 | The target URL did not respond within 10 seconds. |
upstream_connection_refused | 502 | Could not connect to the target URL (bad hostname, refused connection, etc.). |
In both cases the webhook payload is still stored for replay if your plan supports it, so you can re-deliver once the target is back up.