Manage endpoints with an API key that has webhooks:manage, or in the app under
Settings → Company → API & integrations.
These are separate from Slack / Teams notification destinations under Automations.
1. Register an endpoint
POST /api/v1/webhooks
Authorization: Bearer ir_…
Content-Type: application/json
{
"url": "https://your-app.example.com/hooks/inboxrider",
"events": ["message.inbound"]
}
The response includes secret once (whsec_…). Store it securely.
- List:
GET /api/v1/webhooks - Deactivate:
DELETE /api/v1/webhooks/:id
URL rules
- HTTPS only
- Localhost, private networks, link-local, and cloud metadata hosts are rejected
- DNS answers are checked so the host cannot resolve to a private address
2. Event: message.inbound
Fired when a new inbound message is ingested (not a duplicate Message-ID, not a historical import). Delivery failures never roll back message storage.
{
"id": "evt_<messageId>",
"type": "message.inbound",
"createdAt": "2026-09-07T12:00:00.000Z",
"organizationId": "org_…",
"data": {
"messageId": "msg_…",
"conversationId": "conv_…",
"inboxId": "inb_…",
"channelId": "ch_…",
"fromEmail": "alex@acme.com",
"fromName": "Alex",
"toEmails": ["sales@example.com"],
"subject": "Re: Quick question",
"body": "<p>…</p>",
"internetMessageId": "<…@mail.gmail.com>",
"inReplyTo": "<…>",
"createdAt": "…"
}
}
3. Verify signatures
| Header | Value |
|---|---|
X-InboxRider-Event | message.inbound |
X-InboxRider-Event-Id | evt_… |
X-InboxRider-Timestamp | Unix seconds |
X-InboxRider-Signature | sha256=<hex> |
Canonical string:
{timestamp}.{rawRequestBody}
- Read the raw body bytes (do not re-serialize JSON).
- Compute
HMAC-SHA256(secret, "{timestamp}.{rawBody}")as hex. - Compare to the signature with constant-time equality.
- Reject if
|now − timestamp| > 300seconds.
Node.js example
import crypto from "crypto";
function verifyInboxRiderWebhook({ rawBody, timestamp, signature, secret }) {
const age = Math.abs(Date.now() / 1000 - Number(timestamp));
if (!Number.isFinite(age) || age > 300) return false;
const expected =
"sha256=" +
crypto.createHmac("sha256", secret).update(`${timestamp}.${rawBody}`).digest("hex");
const a = Buffer.from(expected);
const b = Buffer.from(String(signature || ""));
if (a.length !== b.length) return false;
return crypto.timingSafeEqual(a, b);
}
4. Retries
| Attempt | Delay |
|---|---|
| 1 | immediate |
| 2 | ~30s |
| 3 | ~2m |
| 4 | ~10m |
| 5 | ~30m |
Return 2xx quickly; do heavy work asynchronously. Treat deliveries as idempotent on id / data.messageId.
5. Handler checklist
- Verify signature and timestamp skew.
- Confirm
type === "message.inbound". - Deduplicate on event / message id.
- Optionally load the thread with
GET /api/v1/conversations/:id— see the API reference.
curl -sS https://api.inboxrider.com/api/v1/webhooks \
-H "Authorization: Bearer ir_…" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-app.example.com/hooks/inboxrider",
"events": ["message.inbound"]
}'