انتقل إلى المحتوى الرئيسي

Webhooks

Webhooks let your systems react to ORKSTRA events without polling. Subscribe to specific event types, receive HMAC-signed POSTs to your callback URL, and process them idempotently.

Subscribing

Admin → API → Webhooks → New subscription (UI), or via the API:

curl -X POST https://api.orkstra.com/v1/webhooks \
-H "Authorization: Bearer YOUR_TOKEN" \
-d '{
"url": "https://your-app.example.com/orkstra-webhook",
"events": ["ipc.certified", "vo.agreed", "ncr.created"]
}'

Response includes a secret — store this securely; you need it to verify signatures.

Signature verification

Every POST carries:

  • X-Orkstra-Signature: <hex> — HMAC-SHA256 over the raw body using your subscription secret.
  • X-Orkstra-Event-Id: <uuid> — unique event ID for dedupe.
  • X-Orkstra-Event-Type: <type> — e.g., ipc.certified.
  • X-Orkstra-Timestamp: <unix> — issuance timestamp.

Python verification:

import hmac
import hashlib

def verify(body_bytes: bytes, sig_header: str, secret: str) -> bool:
expected = hmac.new(secret.encode(), body_bytes, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, sig_header)

Always compute the HMAC against the raw bytes before JSON parsing — middleware that re-serializes can change byte-level whitespace and break the signature.

Node.js verification:

import crypto from "crypto";

function verify(bodyBuf, sigHeader, secret) {
const expected = crypto
.createHmac("sha256", secret)
.update(bodyBuf)
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(sigHeader)
);
}

Idempotency

Retries can deliver the same event twice. Dedupe using X-Orkstra-Event-Id — track seen IDs in your store (e.g., Redis with 7-day TTL).

Event types (highlights)

EventPayload
ipc.createdIPC ID, project, draft amount
ipc.submittedIPC ID, submitter, amount
ipc.certifiedIPC ID, certified amount, certificate URL
ipc.paidIPC ID, payment ref
vo.createdVO ID, project, description
vo.pricedVO ID, total cost impact
vo.agreedVO ID, final amount, time impact
vo.absorbedVO ID, new BOQ revision
ncr.createdNCR ID, project, severity
ncr.closedNCR ID, closure date
hse.incident.reportedIncident ID, classification
permit.issuedPermit ID, type, validity
permit.expiringPermit ID, hours until expiry
dms.transmittal.sentTransmittal ID, recipients, doc count

Full list: docs.orkstra.com/api/events.

Retry policy

If your endpoint doesn't return 2xx within 10 seconds:

  • Retry at 1m, 5m, 30m, 2h, 6h, 24h.
  • After 24h with no success, the delivery is marked permanently failed.
  • Permanently failed deliveries appear in Admin → API → Webhooks → Deliveries.
  • Replay manually any time.

Best practices

  1. Verify the signature first. Reject unsigned or wrong-signature requests with 401.
  2. Return 2xx immediately. Queue the work and process async. ORKSTRA will retry if you exceed 10s.
  3. Dedupe on X-Orkstra-Event-Id.
  4. Handle out-of-order delivery. Retries can deliver out of order; use the payload's event_timestamp to handle.
  5. Treat secrets as secrets. Never log them. Rotate annually.

Testing

  • Ping test: every new subscription receives a webhook.ping event. Use it to validate your endpoint.
  • Manual fire: Admin → API → Webhooks → [sub] → Fire test event.
  • Local dev: use ngrok or Cloudflare Tunnel to expose your local server.

See also: API reference, API & Webhooks module.