Live
Webhooks
Signed webhook delivery, event payloads, verification headers, and replay semantics.
Webhooks
Nimriz webhooks deliver signed lifecycle events to workspace-scoped HTTPS endpoints for plans with webhook access.
Event catalog
Business subscriptions in v1:
link.createdlink.updatedlink.takedown_updateddomain.verification_updated
Operator-only synthetic event:
nim.webhook.test
Delivery semantics
- Delivery is asynchronous and at-least-once.
- Consumers must tolerate duplicates and out-of-order arrival.
- Nimriz preserves the same stable event id on manual replay.
- Test sends use the same signed delivery pipeline as live events, but they are not part of the normal business subscription catalog.
Signed request headers
Every POST includes:
X-Nim-Event-IdX-Nim-Event-TypeX-Nim-TimestampX-Nim-SignatureX-Nim-Delivery-AttemptX-Nim-Delivery-Reason
The signature input is:
${X-Nim-Timestamp}.${raw_request_body}
The signature format is:
v1=<hex hmac sha256>
Envelope shape
{
"id": "9f4d5dbd-c8b8-4c89-a080-b4f70fce8f53",
"type": "link.updated",
"api_version": "2026-03-30",
"created_at": "2026-03-30T12:34:56.789Z",
"organization_id": "org_uuid",
"workspace_id": "workspace_uuid",
"data": {
"link_id": "link_uuid",
"domain_id": "domain_uuid",
"event_action": "destination_updated",
"changed_fields": ["destination"],
"before": {
"destination_host": "example.com",
"destination_url_capped": "https://example.com/path"
},
"after": {
"destination_host": "example.org",
"destination_url_capped": "https://example.org/new-path"
}
}
}
Safe payload posture
- Nimriz sends safe destination fields such as
destination_hostanddestination_url_capped. - Raw query-bearing
long_urlvalues are not included in webhook payloads. - Signing secrets, passwords, cookies, and other sensitive credentials never appear in emitted webhook bodies.
Verification example
import crypto from 'node:crypto';
function verifyNimWebhook({ secret, timestamp, rawBody, signatureHeader }) {
const expected = `v1=${crypto
.createHmac('sha256', secret)
.update(`${timestamp}.${rawBody}`)
.digest('hex')}`;
return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signatureHeader ?? ''));
}
Example payloads
link.created
{
"link_id": "link_uuid",
"domain_id": "domain_uuid",
"domain_name": "go.example.com",
"short_code": "launch24",
"short_url": "https://go.example.com/launch24",
"status": "active",
"redirect_status_code": 302,
"expires_at": null,
"password_protected": false,
"destination_host": "example.com",
"destination_url_capped": "https://example.com/landing"
}
link.takedown_updated
{
"link_id": "link_uuid",
"domain_id": "domain_uuid",
"short_code": "launch24",
"before_status": "active",
"after_status": "disabled"
}
domain.verification_updated
{
"domain_id": "domain_uuid",
"domain_name": "go.example.com",
"before": {
"is_verified": false,
"verification_status": "pending",
"ready_for_traffic": false
},
"after": {
"is_verified": true,
"verification_status": "verified",
"ready_for_traffic": true
}
}
Operator tools
Use the dashboard integrations screen to:
- create and edit endpoints
- rotate signing secrets
- queue a test delivery
- inspect delivery history
- replay recent deliveries
Build downstream consumers around the stable event id, not the delivery attempt number.