1. Create a project
Create an account with Email me a code (a 6-digit code, valid for 10 minutes) or Continue with GitHub. There is no password. Your first sign-in creates your workspace, with an empty project called Default. Open Projects in the side navigation and choose Create a project. Give it a name, such asOrders, leave Start with on Endpoints — one endpoint, ready to receive events, and choose Create.
The project opens on its Endpoints tab. Hookie has made one endpoint for you, named after the project (Orders endpoint), tagged new, and storing what it receives in the dataset default.
2. Copy the endpoint URL
The endpoint’s card shows its public URL, with a copy button:action, or your own code. If it leaks, Rotate URL… in the card’s menu gives the endpoint a new URL and keeps the old one working for an overlap you choose.
Show curl on the card gives you a ready-to-paste command, and so does the project’s Overview tab, under Send events to this project.
3. Send a test event
Choose Send test event on the endpoint’s card. It is a button under the URL, next to View records and Show curl, not an item in the card’s menu. Owners, admins and developers see it, and it is disabled while the endpoint is disabled. The dialog holds a sample JSON payload under Event payload (JSON). Edit it if you like, then choose Send test event. The dialog posts to the endpoint’s real URL, so the event is stored, routed and fanned out exactly like one from a provider, and it counts against your monthly event quota like one. It then shows three stages:- Sending, then Waiting for acknowledgement, with the status and the time taken, such as
201 · 143 ms. - Fan-out to destinations, which follows the event for up to 30 seconds. With no destination yet, it says the event was stored and that no enabled destination accepts its dataset, and it offers Add a destination to forward events.
submission_id names the raw body Hookie stored, and routed lists the datasets the event landed in.
4. See the record
Choose See the record in default in the dialog, or View records on the endpoint’s card. Both open the endpoint’s dataset on the project’s Datasets tab, newest record first. Open a record with its eye icon (Open record) to see all of it, and the Request it arrived in: the method, content type, source IP, query string and headers, such asX-GitHub-Event. Credentials such as Authorization and Cookie are stored as [redacted].
A record is what Hookie routed into a dataset. The body exactly as it arrived is kept as well, as a submission: find it on the Observability tab under Submissions. Export CSV and Export XLSX on the dataset export all of it, not just the page you see. See Datasets and records.
5. Add a destination
A destination is an https URL of yours that Hookie sends each new record to, signed. For this step, any https URL that answers with a2xx status will do, such as a request inspector or a route on your own server.
Open the project’s Connections tab. Under Destinations · outbound, choose Add destination and fill in:
- Name, such as
My server; - Type: leave HTTPS webhook selected. A destination can also post to Slack or write to an S3-compatible bucket;
- URL, which must be
https; - Dataset filter (optional): leave it empty to receive every dataset.
whsec_…) under Signing secret — shown once. Copy it: your receiver uses it to check that a request came from Hookie. Owners and admins can see it again later with Reveal secret on the destination’s tile.
The Free plan runs one destination. See Limits and plans.
6. Watch the delivery arrive
Go back to the Endpoints tab and choose Send test event again. This time Fan-out to destinations ends withDelivered to My server (200). If your URL refused the request or could not be reached, the dialog says so, and whether Hookie will try again.
Now open the project’s Deliveries tab. Each row is one delivery: one event sent to one destination.
The eye icon (Details) lists every attempt and the latest response body your URL sent back. A delivery that failed for good has a Replay button.
Every delivery is signed twice with the destination’s secret: as
Hookie-Signature, and as the Standard Webhooks headers. It also carries Hookie-Event-Id, which stays the same on every retry and replay of that event. Verify the signature before you trust a request, and dedupe on the event id, because delivery is at-least-once. Destinations and deliveries covers retries, holds and replays.
Trace an event later
The Observability tab searches Events, Submissions, Deliveries, AI runs and AI calls over the last 24 hours by default. Widen it with Time range, down to a custom window to the minute. Each kind has its own filters, such as a delivery’s status, destination and response code, or a submission’s routing status. Trace an id takes any record, submission, delivery, AI run or workflow run id, such as theHookie-Delivery-Id your receiver logged, and shows the chain it belongs to. Switch on Live to watch events arrive as you send them. The filters are kept in the page address, so a search can be shared as a link.
When a provider says Hookie returned an error, choose Activity in the endpoint’s menu. It lists what the endpoint received and refused over the last 7 days, and why each request was refused: IP allowlist, rate limit, quota, disabled endpoint, content type, signature and more. Refused requests never count against your quota.
Point an HTML form at it
An endpoint accepts what a browser actually posts, so a plain form needs no JavaScript and no backend of your own. Setaction to your endpoint URL:
application/x-www-form-urlencoded and multipart/form-data. A few details worth knowing:
- A field that repeats (checkboxes, a multi-select) becomes an array rather than losing all but one value.
- Field names are kept verbatim and flat. A field called
user.emailstays the keyuser.emailand does not become a nested object, so a mapping sees exactly what the form sent. - Every form value arrives as text.
gt,gte,ltandltestill compare a field such asamount=150as the number 150. In workflows and triggersequalsandincompare exactly, so match"150"there, not150; rules and endpoint criteria compare as text, so either works. - A file part is recorded as a descriptor and its bytes are discarded, in the record and in the raw submission. Hookie stores records, not files, so you get proof something was attached without the contents:
- Everything else is still parsed as JSON regardless of its
Content-Type, which is what most webhook providers send. A body that is not JSON but is sent as text, such astext/plain, XML, CSV or NDJSON, is stored as{ "body": "<the text>", "content_type": "text/plain" }. See the API reference.
Send visitors to a thank-you page
Because the browser navigates to the endpoint on submit, a visitor lands on Hookie’s own thank-you page, with a link back to your form. To send them to your page instead, give the endpoint a redirect URL: on the Endpoints tab, choose Edit… in the endpoint’s menu and set Redirect after a form submit to your page (it must behttps://). A native form post is then answered 303 See Other to that page once the submission is stored. fetch() calls and server senders still get the JSON, and a resubmitted form that was already stored is sent to the same page.
Submit with fetch()
To keep the visitor on your page, submit withfetch(). A browser only lets a page read the answer from an origin that allows it, so add your site under Allowed browser origins in the same form: one origin per line, such as https://example.com, or * for any page. Nothing is allowed by default. For an allowed origin the endpoint answers the OPTIONS preflight that a JSON body triggers, and every response carries Access-Control-Allow-Origin, so your page can show the error on a 429 too.
Safe retries
A retry returns the original submission (200, with "idempotent": true) instead of creating a duplicate, and it never counts twice against your quota. Hookie recognises the delivery ids that webhook providers already send and keep across their retries, so Stripe, GitHub, Shopify, GitLab, Twilio, Linear, Twitch, Atlassian, Slack, Svix and every Standard Webhooks sender are deduplicated with nothing to configure. deduplicated_by in the answer says which id matched. Duplicates are tracked per endpoint, so two endpoints never collide.
From your own code, send an Idempotency-Key:
Send from your own servers
A server can send with an ingest key (ik_live_…) instead of an endpoint URL. Create one on the project’s Ingest keys tab: it is shown once, stored hashed, and can carry an expiry and an IP allowlist.
default unless you chose another when you created the key), and the response says fallback: true.
See Endpoints and ingest keys and Rules and mappings.
Next
- Read the Concepts pages, starting with Projects, to see how the pieces fit together.
- Verify signatures on your receiver.
- Tail the live stream over SSE or WebSocket.
- Browse the API reference.
- Look up any term in the Glossary.