Webhooks
Hilt supports native outbound webhooks. Use them as the main system-to-system integration path for payment settlement, membership changes, receipt creation, delivery failures, and support events. PollingGET /v1/payments/{payment_id} still works and remains useful during a live buyer session, but you no longer need to build your own relay just to make the rest of your application event-driven.
Quickstart
- create a webhook endpoint in Hilt
- copy the signing secret once and store it safely
- subscribe the endpoint to the event types you actually need
- verify the Hilt signature against the raw request body
- deduplicate by Hilt event
id - treat the webhook payload as the operational snapshot for your app
- register endpoints from the Hilt workspace or the session-authenticated webhook APIs
- use API keys for your own server-to-server product, payment, membership, and support calls
/v1/integrations/zapier/hooks so the Zapier app can subscribe and unsubscribe its own hook URLs with a read + execute API key. Use that route only for Zapier-owned hooks.
Create an endpoint
- the endpoint record
- the signing secret for that endpoint
Send a signed test event
Once the endpoint exists, send a signed test event before you rely on it for real settlement or access automation.- your endpoint is reachable
- signature verification is wired correctly
- your handler is idempotent
- your own logging and alerting capture the Hilt event cleanly
Smallest possible receiver: Node
Smallest possible receiver: Python
Event catalog
Hilt currently emits these event types:| Event | What it means |
|---|---|
payment.confirmed | The payment is final in Hilt and it is safe to unlock access. |
payment.failed | The payment did not complete successfully. |
receipt.created | Proof is available and a receipt verify URL can be used. |
membership.activated | A membership or access record is active. |
membership.renewed | A renewal or extension was applied. |
membership.entered_grace | The membership moved into grace instead of remaining fully active. |
membership.expired | Access has ended and downstream systems should treat it as inactive. |
membership.reapproval_required | A recurring membership needs operator or buyer review before the next period. |
delivery.failed | A Telegram, Discord, redirect, or post-payment delivery step failed. |
support.ticket.created | A new support issue was opened inside the Hilt payment trail. |
payment.confirmed, but Hilt becomes more useful when you also consume the events around it:
- receipt creation
- membership activation or renewal
- grace and expiry
- failed delivery
- support escalation
- paid-through timing
- grace entry
- access expiry
- native collection or access extension completion
Payload shape
Every webhook event has:idtypeapi_versioncreated_atlivemodedata
payment.idpayment.product.idmembership.idwhen access existsreceipt.idwhen proof exists
Example event
Signature verification
Each delivery includes these headers:X-Hilt-EventX-Hilt-Event-IdX-Hilt-Delivery-IdX-Hilt-TimestampX-Hilt-Signature
TypeScript verification example
Python verification example
Verification rules
For a production consumer:- verify against the raw request body
- reject obviously stale timestamps
- store and deduplicate by event
id - return
2xxonly when your handler has actually finished
Delivery behaviour
Hilt currently delivers webhooks as:- signed HTTP
POST - JSON payloads
- one endpoint per URL and signing secret
- exact event subscriptions per endpoint
- optional product filters per endpoint
| Attempt | Delay |
|---|---|
| Initial delivery | immediate |
| Retry 1 | 30 seconds |
| Retry 2 | 2 minutes |
| Retry 3 | 10 minutes |
| Retry 4 | 30 minutes |
| Retry 5 | 2 hours |
2xx responses count as a successful delivery.
Everything else is treated as a failure and is retried until the schedule is exhausted.
Idempotency and ordering
Treat Hilt webhook deliveries as notifications from the source of truth, not as permission to skip idempotency on your side. Recommended pattern:- verify the signature
- persist the Hilt event
id - ignore duplicate event IDs
- process the payload snapshot
- read back from Hilt if your downstream action needs extra confirmation
payment_id, but deduplication should happen on the webhook event id.
Do not assume event arrival order alone is enough to keep your own system safe.
Endpoint filters and delivery logs
Hilt currently supports:- endpoint list and status
- exact event subscriptions
- optional product filters
- delivery history with attempt counts and response codes
- signed test events from the same endpoint record
- event timelines tied back to payment or membership context
- self-serve re-send controls for retry-scheduled and dead-letter deliveries from the merchant dashboard
- signing-secret rotation
Re-send webhook is now visible to merchants inside Dashboard -> Advanced, where recent delivery logs show self-serve re-send controls for deliveries that are stuck in retry windows or have fallen into dead letter.
Event timeline
Hilt now keeps an event timeline you can inspect bypayment_id or membership_id.
That timeline is useful when you need to answer:
- did Hilt emit the event you expected
- which webhook deliveries succeeded or failed around that payment
- whether a delivery failure happened before or after membership activation
- whether support or delivery rescue actions followed the payment
- find the
payment_idormembership_id - inspect the Hilt event timeline
- inspect the endpoint delivery rows
- re-send the webhook only if the downstream system is now ready to consume the same event safely
Merchant delivery-log workflow
For merchants and support operators, the strongest delivery-log flow is:- filter the log to one endpoint
- open the event timeline for the affected payment or membership
- check whether the issue is Hilt delivery, downstream processing, or both
- re-send the webhook only after the consumer has been fixed
Migration from polling
If you already built a polling-first integration, do not throw it away. The clean migration is:- keep the same
payment_idcorrelation model - add webhook consumers for longer-running automation
- keep polling only where the live buyer session still benefits from immediate progress updates
- access grants should move to
payment.confirmed - receipt workflows should move to
receipt.created - member automation should move to membership lifecycle events
- support notifications should move to support events
When polling still makes sense
Polling is still useful when:- the buyer is actively waiting on a checkout screen
- you want a quick progress loop while the transaction is still settling
- you are debugging a live integration
- use webhooks as the longer-running system-to-system integration layer
- use polling only where the live buyer experience genuinely benefits from it
Common questions
What Hilt events should I subscribe to first?
Start withpayment.confirmed, payment.failed, receipt.created, and the membership events that match your product. Add delivery and support events once your operations workflow is ready to act on them.
How do I verify a Hilt webhook?
Verify theX-Hilt-Signature header against the raw request body using the endpoint signing secret, reject stale timestamps, and deduplicate by Hilt event id before triggering downstream work.

