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 was published
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 (n8n-nodes-orimora). Alternatively, use an n8n Webhook trigger node and paste the test URL when creating the Orimora webhook.