Testing webhooks
Local development with a tunnel
Your laptop isn’t reachable from api.soxara.com. Use a tunnel to expose your local server.
ngrok
# install: brew install ngrok
ngrok http 3000
# → forwards https://abc-123.ngrok.app → http://localhost:3000Cloudflare Tunnel (free, no sign-in needed for quick try)
brew install cloudflared
cloudflared tunnel --url http://localhost:3000Take the public URL and register it as your test webhook endpoint, using an sxm_test_ key:
curl -X POST https://api.soxara.com/v1/api/webhook-endpoints \
-H "Authorization: Bearer $SOXARA_TEST_KEY" \
-d '{
"url": "https://abc-123.ngrok.app/webhooks/soxara",
"events": ["payment.completed", "payment.failed"]
}'Now any test payment that settles fires a webhook to your laptop.
Redelivering a failed delivery
Soxara keeps a per-endpoint delivery log (Developers → Webhooks → an endpoint → Deliveries in
the dashboard). A delivery that ended failed or dead_letter (after exhausting the 7-attempt
retry schedule — see Overview) can be forced back to
pending for one more try — “Redeliver” next to that row.
Useful for:
- Retrying a real delivery your handler dropped because it was down at the time
- Confirming a fix to your handler against an event it previously failed on
This redelivers the same event — same Soxara-Delivery id — so your handler must dedupe on
it, the same as any retry.
There’s no bulk “replay all events since a date” tool today — this is per-delivery, from the endpoint’s own log.
Triggering specific events in test mode
Use an sxm_test_ key throughout. The reliable way to fire a payment event on demand is
simulate — it runs a test payment link through the
exact same fan-out as production, so you get a real webhook without real money:
curl -X POST $SOXARA_BASE/v1/api/payment-links/{id}/simulate \
-H "Authorization: Bearer $SOXARA_TEST_KEY" \
-d '{"method": "card", "outcome": "completed"}'| To trigger | Do this |
|---|---|
payment.completed | simulate with "outcome": "completed" |
payment.failed | simulate with "outcome": "failed" |
payroll_run.completed / .partial / .failed | Create a test-key payroll run and approve it — a test mandate/run resolves immediately rather than waiting on a real disbursement |
catalog.published | Publish a catalog version against your test merchant |
inventory.low_stock | Record an inventory movement that takes an item’s quantity at or below its low_stock_threshold |
Inspecting webhook payloads without a server
If you just want to see what Soxara sends without writing a handler yet:
- webhook.site gives you a free unique URL that captures whatever you POST to it. Register that as a test endpoint, fire some test events, inspect the JSON.
- Beeceptor is similar.
Don’t use either for live mode — they don’t verify signatures.
Signature verification in tests
Test deliveries are signed the same way live deliveries are. Don’t disable signature verification in your test environment. That’s how you find verification bugs before they bite you in production.
Use your test endpoint’s signing secret (different from your live secret) when verifying test deliveries. Store both in your environment:
SOXARA_TEST_WEBHOOK_SECRET=KciRV7ED9... # the secret from your test endpoint's registration
SOXARA_LIVE_WEBHOOK_SECRET=Ab3xQp1Ln... # the secret from your live endpoint's registrationThere’s no fixed prefix on the secret (it’s 43 random base64url characters) — it’s whatever came
back in the secret field when you registered the endpoint.
In your handler, pick the right secret based on which endpoint received the request (or based on data.payment.environment — "test" or "live" — in the payload, after a one-time parse-then-verify dance — but the URL-based pick is simpler).