Skip to main content
We POST to your URL on every customer-observable event in your org. One endpoint per org; the identity is identified inside the payload (data.identity) since one receiver typically handles all your identities. The data is identical to the events stream. Each delivery carries the same seq and id as the corresponding events-stream entry, so you can mix push and pull without duplicating work.

Configure

From the dashboard at inboxbase.ai/app/developers:
  1. Endpoint URL — where we POST. HTTPS only.
  2. Signing secretwhsec_..., shown once at creation. Paste it into your verifier (see Verify).
  3. Statusactive or paused. Returning 410 Gone from your endpoint pauses delivery automatically; you re-set from the dashboard.
  4. Rotate secret — invalidates the old secret. Copy the new one before saving. There is no overlap window — flip your verifier the instant you save.

Retries

Three attempts at 0s / 5s / 30s after the trigger. Per-attempt timeout: 10 seconds. We treat any 2xx as success.
ResponseWhat we do
2xxStop retrying.
410 GonePause the endpoint. No further retries.
Anything else (incl. 5xx)Retry per the schedule above.
Network error / timeoutRetry per the schedule above.
After three failed attempts we give up on that event. Your recovery path is to walk the events stream from the last seq you persisted — it carries every event we tried to push.

Idempotency

Webhooks are at-least-once. If your handler crashes after doing work but before responding 2xx, you’ll see the same event again on retry. Dedup by id (or seq):
if (await db.events.exists(ev.id)) return res.sendStatus(200);
await handleEvent(ev);
await db.events.insert({ id: ev.id, seq: ev.seq, handledAt: Date.now() });
res.sendStatus(200);
The trade-off vs. doing the dedup outside the handler: the inside version costs you one round-trip to the DB on every webhook. For high-volume orgs you’ll want to keep seq per identity in memory and fall back to the DB on cold starts.

Headers we send

Content-Type:        application/json
X-Inboxbase-Event-Type:    email.replied
X-Inboxbase-Event-Id:      evt_01HF6YJZ4N0K3W2X9CPM7B8DG2
X-Inboxbase-Signature:     t=1777278929,v1=<hex(hmac_sha256(secret, "<t>.<body>"))>
Always read the raw body for signature verification. Frameworks that auto-parse JSON before your handler sees the bytes will break the verifier; use express.raw({type: 'application/json'}) or your stack’s equivalent.