Testing
Before going live, test every part of your integration — webhook handling, signature verification, idempotency, and error cases.Test webhook endpoint
Use the Test Webhook endpoint to send a simulated event to your endpoint immediately, without waiting for a real blockchain transaction:X-Webhook-Signature header, so your signature verification logic is tested end-to-end.
Local development with ngrok
Expose your local server to receive webhook deliveries during development:webhookUrl when creating invoices or testing:
Test every event type
Run through each event your integration handles:| Event | What to verify |
|---|---|
invoice.confirmed | Payment confirmed on-chain, order status updated |
invoice.settled | Order is fulfilled, customer is notified |
invoice.overpaid | Overpayment is logged, customer is notified |
invoice.underpaid | Customer receives remaining balance notice |
invoice.expired | Order marked expired, inventory released |
Test the full checkout flow
- Create an invoice using your API key
- Open
invoice.paymentUrlin your browser - Select Ethereum + USDT — verify a deposit address is shown
- Use the Test Webhook endpoint to simulate
invoice.confirmed, theninvoice.settled - Verify your webhook handler fulfills the order on
invoice.settled
Checklist before going live
Handle all relevant event types
At minimum:
invoice.settled (fulfill), invoice.expired (mark failed), invoice.underpaid (notify customer).Webhook signature verification
Set
SETTLX_WEBHOOK_SECRET in your environment and verify X-Webhook-Signature on every incoming request.Idempotency on eventId
Store processed
eventId values and skip duplicates to prevent double-fulfillment.Respond within 30 seconds
Return
200 immediately and process the event asynchronously. Slow responses trigger retries.Settlement wallet configured
Set your settlement wallet address in the dashboard before going live. Double-check the chain matches your wallet.
Expiry times reviewed
Set
expiresInMinutes appropriate for your use case. Use 60+ minutes for Bitcoin payments.Rate limit handling
Implement retry with exponential backoff for API calls. Use webhooks instead of polling where possible.
Common mistakes
Fulfilling orders on invoice.confirmed instead of invoice.settled
Fulfilling orders on invoice.confirmed instead of invoice.settled
invoice.confirmed means on-chain confirmation — but funds are not yet in your wallet. Always fulfill on invoice.settled, which fires once settlement is complete and funds have landed.Not verifying webhook signatures
Not verifying webhook signatures
Without signature verification, anyone can POST a fake payload to your endpoint. Always verify
X-Webhook-Signature before processing any event.Processing duplicate webhooks
Processing duplicate webhooks
Webhooks can be delivered more than once during retries. Store processed
eventId values and skip events you’ve already handled.Not handling invoice.expired
Not handling invoice.expired
If an invoice expires and you don’t handle the event, the order stays in a pending state indefinitely. Always handle expiry explicitly.
Exposing your API key in frontend code
Exposing your API key in frontend code
Your API key is for server-to-server calls only. Never include it in browser JavaScript, mobile apps, or any client-side code.
Parsing the webhook body before verifying
Parsing the webhook body before verifying
HMAC signature verification must run on the raw request body before JSON parsing. If you parse first, the comparison will fail due to whitespace and key ordering differences.