WebhooksTesting webhooks

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:3000

Cloudflare Tunnel (free, no sign-in needed for quick try)

brew install cloudflared
cloudflared tunnel --url http://localhost:3000

Take the public URL and register it as your test webhook endpoint:

curl -X POST https://api.soxara.com/v1/webhook-endpoints \
  -H "Authorization: Bearer $SOXARA_TEST_KEY" \
  -d '{
    "url": "https://abc-123.ngrok.app/webhooks/soxara",
    "events": ["payment.succeeded", "payment.failed"]
  }'

Now any test payment that succeeds in the sandbox fires a webhook to your laptop.

Replaying past events

Every event Soxara has ever generated for your merchant is stored for 30 days. From the business dashboard:

  1. Find an event (filter by type, by payment ID, or by date).
  2. Click “Replay” to redeliver it to one of your registered endpoints.

Useful for:

  • Debugging a handler that crashed on a real event you already saw
  • Testing a new endpoint URL against historical traffic before going live
  • Recovering from a deploy that took your handler down

Replays carry the same event.id as the original. Your handler must dedupe by event ID — otherwise replays will re-process events.

Triggering specific events in test mode

To triggerDo this
payment.succeededCreate a PaymentIntent with 4242 4242 4242 4242
payment.failedUse 4000 0000 0000 0002
payment.requires_actionUse 4000 0027 6000 3184 (3DS challenge)
refund.succeededAfter a succeeded payment, POST /v1/refunds against it
transfer.claimedSend a transfer to a phone that isn’t a Soxara user; the test environment auto-completes the claim flow after 10 seconds
bill_payment.succeededInitiate a bill payment in test mode; settles after a 5-second synthetic delay

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=whsec_test_...
SOXARA_LIVE_WEBHOOK_SECRET=whsec_live_...

In your handler, pick the right secret based on which endpoint received the request (or based on event.livemode in the payload, after a one-time parse-then-verify dance — but the URL-based pick is simpler).