Docs
Webhooks
Webhooks
Set up organization webhooks and verify signed events from your Inrconnect workspace.
Overview
Webhooks let your system receive real‑time events from your Inrconnect organization. When configured, Inrconnect sends an HTTP POST to your endpoint whenever selected events occur.
Supported triggers
- CONTACT_CREATED
- CONTACT_UPDATED
- CONTACT_DELETED
You can choose one or more triggers per webhook.
Create a webhook
- In the Dashboard, go to
Settings → Organization → Developers → Webhooks
. - Click “Create Webhook”.
- Enter your HTTPS endpoint URL (e.g.,
https://api.example.com/inrconnect/webhooks
). - Select the triggers you want to receive.
- Provide a signing secret (recommended). This is used to verify authenticity.
- Save.
You can create multiple webhooks per organization.
Event delivery
Requests are sent as POST application/json
with the following body:
{
"trigger": "CONTACT_CREATED",
"createdAt": "2025-08-14T21:10:00.000Z",
"payload": {
"contact": {
"id": "uuid",
"record": "person|company",
"name": "Jane Doe",
"email": "jane@example.com",
"phone": "+1 555-0100",
"stage": "lead|qualified|...",
"tags": ["vip", "newsletter"]
}
}
}
For updates:
{
"trigger": "CONTACT_UPDATED",
"createdAt": "2025-08-14T21:10:00.000Z",
"payload": {
"contact": { "id": "uuid", "name": "Jane Doe", "...": "..." },
"changes": {
"name": { "old": "Jane", "new": "Jane Doe" },
"tags": { "old": "vip", "new": "vip,newsletter" }
}
}
}
For deletes:
{
"trigger": "CONTACT_DELETED",
"createdAt": "2025-08-14T21:10:00.000Z",
"payload": {
"contact": { "id": "uuid" }
}
}
Security and signature verification
If you set a secret when creating the webhook, each request includes:
X-Webhook-Signature-256
: HMAC-SHA256 hex digest of the raw JSON body using your secret
Verify by computing the HMAC over the exact raw request body and comparing in constant time.
Node/Next.js example
import crypto from 'node:crypto';
import { NextResponse } from 'next/server';
const SECRET = process.env.INRCONNECT_WEBHOOK_SECRET!;
export async function POST(req: Request) {
const signature = req.headers.get('x-webhook-signature-256') || '';
const rawBody = await req.text();
const expected = crypto
.createHmac('sha256', SECRET)
.update(rawBody)
.digest('hex');
const ok =
signature.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
if (!ok)
return NextResponse.json({ error: 'Invalid signature' }, { status: 401 });
const event = JSON.parse(rawBody);
// TODO: handle event.trigger and event.payload
return NextResponse.json({ ok: true });
}
Express example
import crypto from 'node:crypto';
import express from 'express';
const app = express();
app.use(express.text({ type: 'application/json' })); // preserve raw body
const SECRET = process.env.INRCONNECT_WEBHOOK_SECRET!;
app.post('/inrconnect/webhooks', (req, res) => {
const signature = req.header('x-webhook-signature-256') || '';
const expected = crypto
.createHmac('sha256', SECRET)
.update(req.body)
.digest('hex');
const ok =
signature.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
if (!ok) return res.status(401).json({ error: 'Invalid signature' });
const event = JSON.parse(req.body);
res.json({ ok: true });
});
Retries
Deliveries are attempted up to 3 times. If your endpoint returns a non-2xx status or times out, we retry with exponential backoff.
Best practices
- Use a unique, sufficiently long secret per webhook
- Respond with 2xx quickly (queue heavy work)
- Log request IDs and timestamps
- Treat unknown triggers as no-ops for forward compatibility
Troubleshooting
- 401: Check your secret and signature computation against the raw body
- 4xx: Validate your endpoint accepts
application/json
- 5xx/timeouts: Ensure your handler returns quickly; move processing to a queue