localhost is not reachable on its own, and nothing happens until a company
actually moves. Two tools remove both problems: a tunnel gives your local
handler a public URL, and the sandbox lets you fire any event on demand. The
whole loop runs in test mode with a
clmt_test_ key, so nothing you do here touches a live company.
The loop
1
Expose your handler with a tunnel
Run your webhook handler locally, then point a tunnel at its port to get a
public HTTPS URL. Any tunnel works (for example Webhook URLs must be HTTPS - tunnels give you one. Keep the tunnel
running: a free tunnel’s URL changes each restart, so re-register the
endpoint when it does.
ngrok or cloudflared).2
Register the tunnel URL as a test endpoint
On the Webhooks page of your partner dashboard, in test mode, create an
endpoint pointing at the tunnel URL and store the signing secret
(
whsec_...) it shows once. Endpoints are registered per mode, so a test
endpoint receives test events only - your live traffic is never affected.3
Create a test company
company.created
to your endpoint.4
Fire the events you want
A test company never advances on its own - you drive it with
Most of the catalog is simulable this
way, so you can replay any handler path without waiting on a real formation.
See Modes and the sandbox for the
full event table.
POST /sandbox/companies/{id}/simulate,
which applies the change exactly as a real one would and delivers the
resulting events to your endpoint.5
Verify the delivery
Every delivery is signed. The shortest path is the
standardwebhooks library:
hand it the secret, the three See Verifying a delivery for the
exact signature format and the keyless
webhook-* headers, and the raw request
body.v1a scheme.Without a public endpoint
You do not need a tunnel to develop against events at all. Every webhook is fanned out from the same logGET /events reads,
so you can skip the endpoint and poll instead - simulate an event, then pull it:
Common snags
- Respond
2xxquickly. Acknowledge first, do the work after. A slow handler reads as a failed delivery and is retried. - Re-register when the tunnel URL changes. A free tunnel rotates its URL on restart; the old endpoint then delivers into nothing.
- Test and live never mix. A
clmt_test_key only drives test companies and only reaches test endpoints. Switching toclmt_live_is the same code against real formations - and there a company advances on its own, sosimulateis gone (it answers an error to a live key, exactly as in production). Clemta-Webhook-Idis your idempotency key. Retries and a poll sweep can both deliver the same event; dedupe on that id and a duplicate is free.