Webhooks
Register HTTPS endpoints and Orbis Shield will call them when an inspection completes — so you can react to spam/phishing in real time without polling.
Configuring a webhook
In the portal, go to Developer → Webhooks → Add a webhook:
- Name — a label for your reference.
- Endpoint URL — your HTTPS receiver.
- Events — any of
inspection.spam,inspection.phishing,inspection.clean.
You can pause/resume, test, and delete each webhook. The list shows the last
delivery status. Every webhook has a signing secret (whsec_…) shown on the page.
Delivery format
Shield sends a POST with a JSON body:
{
"event": "inspection.phishing",
"timestamp": "2026-07-05T20:00:00.000Z",
"data": {
"inspectionId": "…",
"verdict": "phishing",
"score": 88,
"channel": "sms",
"sender": "+15550100",
"subject": "…"
}
}
Headers:
| Header | Value |
|---|---|
X-Shield-Event | The event name, e.g. inspection.phishing |
X-Shield-Signature | sha256=<hex> — HMAC-SHA256 of the raw body using your secret |
Deliveries time out after 5 seconds. Delivery is best‑effort and does not block the inspection that triggered it.
Verifying the signature
Always verify X-Shield-Signature before trusting a payload. Compute HMAC‑SHA256 over the
exact raw request body using your webhook secret and compare (constant‑time) to the hex
after sha256=.
Node.js:
import { createHmac, timingSafeEqual } from 'crypto';
function verify(rawBody, header, secret) {
const expected = 'sha256=' + createHmac('sha256', secret).update(rawBody).digest('hex');
const a = Buffer.from(header);
const b = Buffer.from(expected);
return a.length === b.length && timingSafeEqual(a, b);
}
Python:
import hmac, hashlib
def verify(raw_body: bytes, header: str, secret: str) -> bool:
expected = "sha256=" + hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, header)
Recommendations
- Respond quickly with
2xx; do heavy work asynchronously. - Treat events as at‑least‑once — deduplicate on
data.inspectionId+event. - Keep the secret server‑side; rotate by recreating the webhook.