Documentation
EventInbox Documentation
Quickstart — your first webhook in 5 minutes
- Sign up at
app.eventinbox.proand create a workspace. - Create an endpoint (dashboard → Endpoints → New): give it a name and the destination URL where you want events delivered. You get an ingest URL of the form:
https://api.eventinbox.pro/in/{workspace-slug}/{endpoint-name} - Send your first event — POST any JSON to that ingest URL:
curl -X POST https://api.eventinbox.pro/in/your-workspace/your-endpoint \ -H "Content-Type: application/json" \ -H "x-ei-event-type: payment.succeeded" \ -d '{"id":"pi_123","amount":4200}'Response (202):{"event_id":"...","delivery_id":"...","status":"accepted","received_at":"..."} - Watch it deliver — open the dashboard. The event flows through the worker, gets signed, and is delivered to your endpoint with automatic retries on failure. Or click "Send test event" on any endpoint to fire a sample through the pipeline.
Core concepts
- Event — a JSON payload you POST to an ingest URL. EventInbox stores it and creates a delivery.
- Endpoint — a destination URL that receives your events, with its own signing secret and retry config (default: 12 attempts, 5 max concurrency, 10s timeout).
- Delivery — one event being sent to one endpoint. Tracks status (pending/processing/delivered/failed), attempt count, and the next retry time.
- Attempt — a single HTTP POST to your endpoint, recording response status, duration, and any error.
Delivery & retries
Every event is delivered at-least-once. On failure (non-2xx response, timeout, or connection error), EventInbox retries with exponential backoff — up to 12 attempts over roughly 72 hours by default. After the final attempt the delivery is marked failed and moves to the dead-letter queue, where you can replay it anytime from the dashboard. Configure max_attempts and timeout_seconds per endpoint.
Verifying webhook signatures
EventInbox signs every delivery using the Standard Webhooks specification (standardwebhooks.com) — the same scheme used by OpenAI, Stripe, and others. Each delivery includes three headers:
webhook-id— unique delivery idwebhook-timestamp— unix timestampwebhook-signature— base64 HMAC-SHA256 over{id}.{timestamp}.{payload}
Verify with the official library — no EventInbox SDK required:
Node
import { Webhook } from "standardwebhooks";
const wh = new Webhook(process.env.WEBHOOK_SECRET); // your endpoint's whsec_ secret
const payload = wh.verify(rawBody, {
"webhook-id": req.headers["webhook-id"],
"webhook-timestamp": req.headers["webhook-timestamp"],
"webhook-signature": req.headers["webhook-signature"],
});Python
from standardwebhooks import Webhook wh = Webhook(webhook_secret) # your endpoint's whsec_ secret payload = wh.verify(raw_body, headers)
Go
import standardwebhooks "github.com/standard-webhooks/standard-webhooks/libraries/go" wh, _ := standardwebhooks.NewWebhook(webhookSecret) err := wh.Verify(payload, headers)
The legacy x-ei-* headers are still sent for backward compatibility.
API reference
- Base URL:
https://api.eventinbox.pro - Auth: Bearer JWT (from signin) OR an API key in the
x-api-keyheader.
Ingress (no auth)
POST /in/{workspace}/{endpoint}— send an event. Optional headersx-ei-event-type,x-ei-idempotency-key. Returns 202.
Endpoints
GET /api/v1/endpoints— listPOST /api/v1/endpoints— create (name, destination_url, optional max_attempts, max_concurrency, timeout_seconds)GET|PUT|DELETE /api/v1/endpoints/{id}POST /api/v1/endpoints/{id}/enable | /disable | /rotate-secret | /test-event
Events
GET /api/v1/events(filters: event_type, endpoint_id, status, limit)GET /api/v1/events/{id}POST /api/v1/events/{id}/replay
Deliveries
GET /api/v1/deliveries(filters: status, endpoint_id, limit)GET /api/v1/deliveries/{id}GET /api/v1/deliveries/{id}/attemptsPOST /api/v1/deliveries/{id}/replay
Settings
GET|POST /api/v1/settings/api-keysDELETE /api/v1/settings/api-keys/{id}