Async state and webhook-style integrations
Hilt’s public developer contract today is polling-first. That means the safest production pattern is:- create or read the product
- start checkout and keep the
payment_id - let the buyer finish payment
- poll Hilt until the payment reaches a terminal state
- fan that final result into your own event or webhook pipeline
Why polling is the durable contract
The buyer can finish the wallet step before your backend sees the final Hilt result. That is normal. The durable answer is the Hilt payment object, not:- a wallet popup
- a screenshot
- a single browser callback
CONFIRMED, you can then read:
- memberships for access state
- receipts for proof
- support for the human trail
Recommended worker model
Most production integrations work well with a simple worker loop:- your checkout flow stores the
payment_id - a background worker polls
GET /v1/payments/{payment_id} - when the payment becomes
CONFIRMED, the worker reads memberships and receipts - the worker then emits an application event or calls your own webhook consumer
Suggested polling cadence
Use a progression that is fast at the start and calmer later:| Window | Suggested cadence |
|---|---|
| First 15 seconds after checkout starts | every 2 to 3 seconds |
While PENDING_CONFIRMATION is clearly active | every 5 to 10 seconds |
| Once a payment is older than expected | every 20 to 30 seconds |
CONFIRMEDFAILED
410 during the active checkout flow. Treat that as terminal for that session and start a fresh one.
What your worker should persist
Persist these fields when checkout starts:payment_idproduct_idslug- your own buyer reference if you already know it
- your own job timestamp
tx_signaturemembership_idreceipt_id
A good worker state machine
| Hilt state | Meaning | Worker action |
|---|---|---|
PENDING_SIGNATURE | Buyer session exists but the signature has not been completed yet | keep the payment open and continue polling |
PENDING_CONFIRMATION | Hilt is waiting for final settlement | continue polling with the same payment_id |
CONFIRMED | Hilt has accepted the payment as final | fetch membership and receipt data, then emit your own event |
FAILED | The payment will not complete successfully | stop polling and mark the job failed |
Fan confirmed payments into your own webhook consumers
If your platform already relies on webhooks, let Hilt be the source and your application be the broadcaster. Example event payload:TypeScript worker example
Python worker example
What to do after CONFIRMED
Once the worker gets a confirmed payment:
- fetch the membership if access should exist
- fetch the receipt if proof should exist
- emit your own application event or call your own webhook consumer
- open or continue a support ticket only if the flow still needs human help
Good practices for webhook-oriented teams
- always key background jobs by
payment_id - treat repeated reads as safe
- deduplicate your own emitted events by
payment_id - do not create a second payment while the first is still pending
- do not grant access until Hilt shows
CONFIRMED

