Skip to content

Webhooks

Webhooks send HTTP POST requests to your URL when events occur in your workspace. Use them with n8n, Zapier, Make, or custom servers.

  • Settings → Developers access (capability Webhooks or team admin)
  • A publicly reachable HTTPS endpoint (localhost works only with a tunnel like ngrok)
  • Server env: PUBLISHING_ENCRYPTION_KEY must be set (see Installation)
  1. Go to Settings → Developers → Webhooks
  2. Click Add webhook
  3. Enter a name and URL (HTTPS recommended)
  4. Select events to subscribe to (or all)
  5. Save — the signing secret is shown once. Store it securely.
EventFires when
document.createdNew document
document.updatedDocument content or metadata changed
document.deletedDocument removed
document.publishedDocument published to a channel
collection.createdNew collection
collection.updatedCollection renamed or moved
collection.deletedCollection removed
notification.createdIn-app notification created (per recipient)

Each delivery is JSON:

{
"id": "delivery-uuid",
"createdAt": "2026-05-22T10:00:00.000Z",
"event": "document.updated",
"payload": {
"id": "document-uuid",
"model": {}
}
}

The model object contains a sanitized snapshot of the affected resource.

Every request includes:

HeaderValue
Content-Typeapplication/json
X-Orimora-EventEvent name (e.g. document.updated)
X-Orimora-Signaturet=<unix_seconds>,v=<hex_hmac>
User-AgentOrimora-Webhooks/1.0

The signature is HMAC-SHA256 over the string "<timestamp>.<raw_body>" using your webhook secret.

Verification steps:

  1. Read the raw request body (before JSON parsing)
  2. Parse X-Orimora-Signature — extract t and v
  3. Reject if t is too old (replay protection — e.g. ±5 minutes)
  4. Compute HMAC-SHA256(secret, t + "." + body) as hex
  5. Compare with v using a timing-safe comparison
import { createHmac, timingSafeEqual } from 'crypto';
function verifyOrimoraWebhook(secret, signatureHeader, rawBody, maxAgeSec = 300) {
const parts = Object.fromEntries(signatureHeader.split(',').map((p) => p.split('=')));
const t = Number(parts.t);
const v = parts.v;
if (!t || !v || Math.abs(Date.now() / 1000 - t) > maxAgeSec) return false;
const expected = createHmac('sha256', secret).update(`${t}.${rawBody}`).digest('hex');
try {
return timingSafeEqual(Buffer.from(v, 'hex'), Buffer.from(expected, 'hex'));
} catch {
return false;
}
}
  • Deliveries run asynchronously via a background queue
  • Failed deliveries are retried with backoff
  • Webhooks with high failure rates are auto-disabled (configurable via WEBHOOK_FAILURE_* env vars)
  • Delivery logs are retained for debugging (see Settings UI)

URLs must not point to private IPs or cloud metadata endpoints (SSRF protection).

Orimora ships an n8n community node (packages/n8n-nodes-orimora). Alternatively, use an n8n Webhook trigger node and paste the test URL when creating the Orimora webhook.