Local development
Developing a webhook receiver locally is the same problem every
SaaS has: your laptop isn't reachable from the public internet, so
Cobuntu can't POST to http://localhost:3000/webhook. Three
workable patterns, ordered by ergonomics:
1. Tunnel with ngrok (recommended today)
# In one terminal, run your receiver
npm run dev # listens on http://localhost:3000
# In another, tunnel
ngrok http 3000Ngrok prints a public URL like https://abc123.ngrok-free.app. In
cobuntu-admin → Integrations → Webhooks → Create webhook, paste
that URL with your path appended:
https://abc123.ngrok-free.app/webhookTrigger an event from cobuntu-admin (e.g. invite a test member to
fire member.invited). The webhook hits ngrok → your laptop →
your handler. Inspect the request + response in ngrok's web UI at
http://localhost:4040.
Gotchas:
- The free ngrok URL changes every restart. Update the webhook URL in admin each time, or pay for a reserved subdomain.
- Cobuntu's signing secret is per-webhook, not per-URL. So you can keep the same secret across ngrok URL changes by editing the existing webhook entry instead of creating new ones.
- Don't leave the test webhook configured after you stop tunneling — every event will retry 5 times before giving up (~28h of
PERMANENTLY_FAILEDdeliveries).
2. The forthcoming cobuntu webhooks listen CLI
Stripe-CLI-style ergonomics, on the SDK roadmap:
# Coming soon
cobuntu webhooks listen --forward http://localhost:3000/webhookThe CLI subscribes to your community's webhooks server-side (no public tunnel needed), receives events, and forwards them to your local URL. Same signature your prod handler will see — so your local code runs the verification step.
Not shipping yet. For now, ngrok works.
3. Pull from the deliveries log (no tunnel)
If you just want to inspect payload shapes without a live tunnel:
- Configure the webhook to point at any URL that returns 200 (e.g.
https://webhook.sitegenerates a free disposable URL). - Trigger events from admin.
- Each delivery's full payload is captured in admin → Integrations → Webhook deliveries.
- Copy the JSON, replay against your local receiver with
curl:
curl -X POST http://localhost:3000/webhook \
-H "Content-Type: application/json" \
-H "Cobuntu-Signature: t=1716700000,v1=..." \
-H "Cobuntu-Delivery-Id: del_abc123" \
-H "Cobuntu-Event: member.approved" \
-d @payload.jsonUseful for reproducing a specific historical event you want to handle differently after the fact.
Signature verification in local dev
The signature header is computed over the raw body bytes + a shared secret. In dev:
- If you're using ngrok / a real tunnel: the signing secret is whatever Cobuntu generated for that webhook. Find it in admin → Webhooks → click the webhook → it's shown once at creation, so copy it before navigating away.
- If you're replaying payloads via
curl: skip signature verification entirely (your devCOBUNTU_WEBHOOK_SECRETenv var would be unset). Just be sure to re-enable it before deploying.
See Verify signatures for the verification recipe.
Triggering events from admin
To fire each event for testing:
| Event | How to trigger from admin |
|---|---|
member.requested | Submit the public form (or paste your own email into Members → Add manually) |
member.invited | Members → Invite Members → Send |
member.approved | Find a PENDING request → Approve |
member.rejected | Find a PENDING request → Reject |
article.published | Articles → Draft → Publish |
event.published | Events → Draft → Publish |
broadcast.sent | Communications → New broadcast → Send |
For finance-domain events (sale.completed, payout.confirmed,
subscription.*) you need actual Stripe test-mode transactions —
test cards work in our checkout if your community is in Stripe
test mode.