Your first webhook, delivered.
Create an application and customer, connect that customer’s HTTPS endpoint, then send an event with its customer ID. Hooka Relay stores it durably and delivers it in the background.
Send your first event
Copy the Application API key from your application page and keep it on your server.
The app holds your key. Each customer owns its endpoints and events.
Subscribe it to order.shipped or *.
The API accepts it with 202 Accepted; delivery runs asynchronously.
import { HookaRelay } from "hooka-relay-node";
const relay = new HookaRelay(process.env.HOOKA_API_KEY);
const event = await relay.sendEvent({
customerId: "cus_123",
type: "order.shipped",
payload: { orderId: "ord_1042" },
idempotencyKey: "order-1042-shipped",
});
console.log(event.id);Use the same idempotencyKey when retrying an uncertain send. A repeated key returns the original event, even if the new payload differs.
Payloads can be up to 256 KB. An endpoint receives an event only when it belongs to the specified customer and subscribes to the event's exact type or *.
Trust the webhook before processing it
Every new endpoint uses Standard Webhooks and has its own whsec_ signing secret.
Keep the body exactly as sent. Parsing and serializing it again changes the signed bytes.
Use the SDK and the endpoint secret to check the ID, timestamp, and body.
Save the verified webhook-id with your business change so a retry has no second effect.
import { verifyWebhook } from "hooka-relay-node";
// rawBody is the exact request body, before JSON parsing.
const payload = verifyWebhook(rawBody, {
"webhook-id": request.headers["webhook-id"],
"webhook-timestamp": request.headers["webhook-timestamp"],
"webhook-signature": request.headers["webhook-signature"],
}, process.env.HOOKA_SIGNING_SECRET);
// Persist the verified webhook-id with your business change.
console.log(payload);Which key goes where?
Your Application API key sends events. An endpoint's signing secret verifies deliveries. Keep both on the server.
Rotation and time
During rotation, either signing key verifies for seven days by default. Verification rejects timestamps outside five minutes.
When a receiver does not respond
Return any 2xx response after accepting a verified event. A timeout or non-2xx response schedules another attempt.
Standard policy has five total HTTP attempts. Each request has a 10-second deadline. After the final failure, the delivery becomes DEAD_LETTERED.
30s · 2m · 5m · 15m
30s · 30s · 30s · 2m · 2m · 5m
5m · 15m · 30m
What the circuit breaker does
Normal delivery. Five consecutive endpoint failures open the circuit.
Requests are skipped without using an HTTP attempt. The endpoint cools down for ten minutes.
One probe tests recovery. Success closes the circuit; failure restarts the cooldown.
For example, if your server is down after accepting an event, a retry can arrive later. Keep handlers idempotent. Delivery order is not guaranteed across retries or replays.
Try a demo receiver
When adding an endpoint, choose succeed, fail, hang, or flaky to see how delivery responds.
Diagnose and recover
Inspect endpoint attempts and advisory failure diagnosis. After a fix, send a synthetic test or replay an exhausted event.
Connect an external provider
Open an application's Webhook Sources tab to start the Setup Wizard.
Select a provider from payments, commerce, messaging, forms, support, or social platforms.
Enter its signing secret and configure the ingestion URL. GitHub repository hooks can be registered from the wizard.
Add a public destination, listen on your local machine, or use both. You can leave setup and resume later.
Hooka Relay requires a valid provider signature before accepting an inbound event. The destination receives a Hooka Relay signed JSON payload with provider, sourceId, providerEventId, and data. Retries, circuit protection, idempotency, and delivery logs use the same engine as normal outbound events.
Each listed provider has a signature verifier. Meta callbacks also answer the Verify Token challenge, and Zoom answers URL validation. Custom supports configurable HMAC-SHA256 or HMAC-SHA1. PayPal requires a separate certificate or verification API flow and is not available yet.
A source URL is a private token. Its provider secret is encrypted. Failed signature checks appear in the source dashboard with a generic public rejection. Inbound bodies are limited to 256 KB and JSON depth 32, with the existing event quotas.
For a provider test, trigger a real signed event in its dashboard. Twilio and Custom offer an explicitly labeled simulation that tests the forwarding path, without claiming to verify the provider.
Route to more than one destination
Every destination in the group starts together with its own retries, circuit breaker, and attempt log.
Choose whether all destinations or any one destination must succeed.
Always run, run after success, or run after failure. Skipped groups appear in the event trace.
Fan-out and monitoring
Put several URLs in one group for parallel fan-out. Put monitoring in a second group set to Always.
Fallback and pipelines
Set group 2 to If previous failed for a backup, or If previous succeeded for a pipeline.
For redundant primary receivers, choose Any may succeed for group 1 and place the backup in group 2. The backup starts only if every primary ultimately fails. A group waits for all its destinations to finish, including their full retry schedules. Pausing a destination can delay later groups. The source event inspector shows each actual group outcome and destination delivery.
Listen locally and inspect requests
Run hooka listen --source SOURCE_ID --forward-to http://localhost:3000/webhooks. The worker forwards each verified request to the CLI over an authenticated live connection. Your local server receives the original body bytes and provider signature header. The source page shows when a listener is connected.
The source event log retains received requests even while no listener is online. Filter by date, verification result, or body text; open a request to inspect headers, body, routing trace, delivery attempts, and replay history. A manual replay sends the saved original bytes through the current destination route and to connected local listeners. Only authenticated workspace users can inspect verification failures; the provider still receives a generic rejection.
Explore the HTTP API
Use your Application API key for ingestion; dashboard routes use your signed-in session.
GET/POST /api/v1/applications/:id/customersList or create customersPOST /api/v1/eventsAccept a new eventPOST /api/inbound/:ingestionTokenAccept a signed provider webhookGET /api/sources/:id/routingRead ordered destination groupsPUT /api/sources/:id/routingSave groups and conditionsGET /api/v1/applications/:id/eventsRead an event backlogGET /api/endpoints/:id/attemptsInspect delivery attemptsPOST /api/events/:id/replayReplay an eventUse the interactive explorer with a test application key. “Try it out” sends real requests to this deployment. Authorization stays in this page's memory and clears on reload.
Endpoint registration accepts public HTTPS URLs. Private addresses, redirects, and embedded credentials are rejected.
Build with the tools you prefer
Use a server SDK in your application, or work from the terminal with the CLI.
Node.js and Python SDKs
The SDKs send customer-scoped events and verify Standard Webhooks. They make one request per send, with no automatic retries; reuse an explicit idempotency key if a network result is uncertain.
npm install hooka-relay-node
Command-line companion
Install hooka-relay-cli, then authenticate with an Application API key. The CLI can send, tail, inspect endpoints, replay deliveries, and forward inbound requests to localhost. Use --customer-id when sending or adding an endpoint.
npm install -g hooka-relay-cli hooka login hooka customers list hooka customers add --external-id demo --name "Demo customer" hooka send --customer-id CUSTOMER_ID --type order.shipped --payload-file payload.json hooka tail hooka replay EVENT_ID hooka listen --source SOURCE_ID --forward-to http://localhost:3000/webhooks
hooka login saves your key locally. Run hooka logout to remove it. An ingest-only key can send with --no-wait; inspection and replay require broader key access.
Frequently asked questions
What happens when my endpoint goes offline?
Accepted events remain in the durable outbox. By default, Hooka Relay retries failed deliveries up to five total attempts, with delays of 30 seconds, 2 minutes, 5 minutes and 15 minutes.
Can I receive the same event twice?
Yes. Delivery is at least once. For new Standard Webhooks endpoints, verify the signature first, then store the authenticated webhook-id atomically with your business operation. Return a successful response for an already processed event.
Why is my circuit breaker open?
Five consecutive endpoint failures open the circuit. After ten minutes, one recovery request tests the endpoint. A success closes it; another failure restarts the cooldown.
How do I verify a webhook signature?
Endpoints use Standard Webhooks. Verify webhook-id, webhook-timestamp, webhook-signature and the exact raw body with the standardwebhooks library, then deduplicate the verified webhook-id.
Can I work from my terminal?
Install hooka-relay-cli from npm, run hooka login, then use hooka customers list, hooka send --customer-id ID, hooka tail and hooka replay. The CLI uses your Application API key.
Which cookies does Hooka Relay use?
Essential cookies keep you signed in and protect authentication requests. This site does not load advertising or optional analytics cookies. Your banner dismissal is stored locally in your browser.