Webhooks

Subscribe to session and evidence events, verify the signature, and handle at-least-once delivery correctly.

5 min read

Register an endpoint in the portal under Developers → Webhooks, or through the API. Each endpoint gets a signing secret prefixed whsec_ — shown once, and never an API key.

Events

  • session.scheduled
  • session.started
  • session.ended
  • evidence.ready
  • companion.paired
  • companion.placement_confirmed
  • companion.recording_started
  • companion.recording_stopped
  • companion.interrupted
  • companion.resumed
  • source.health_changed
  • report.finalized
  • report.stale
  • webhook.test

Verify before you parse

The X-Proctor-Signature header carries a versioned HMAC-SHA256 over the timestamp and the raw body. Verify against the raw bytes — parsing first and re-serializing changes them, and the signature will not match. Deliveries older than 300 seconds must be refused, which is what stops a captured delivery being replayed at you later.

The SDK does both checks
import { constructWebhookEvent } from "@proctor/sdk";

app.post("/hooks/proctor", express.raw({ type: "*/*" }), (req, res) => {
  const event = constructWebhookEvent(
    req.body,                                     // raw Buffer, not parsed JSON
    req.header("X-Proctor-Signature")!,
    process.env.PROCTOR_WEBHOOK_SECRET!,
  );

  // Deliveries are at-least-once: dedupe on the event id before acting.
  res.sendStatus(200);
});

Delivery headers

HeaderMeaning
X-Proctor-Event-IdStable id of the event. Dedupe on this.
X-Proctor-Event-TypeThe event type, without parsing the body.
X-Proctor-Delivery-IdThis delivery to this endpoint.
X-Proctor-Delivery-AttemptAttempt number within the delivery.
X-Proctor-TimestampSigned timestamp, checked against the tolerance.

Retries

Delivery is at-least-once. A non-2xx response, a redirect, or no answer within 10 seconds is a failed attempt; there are up to 6 attempts, backing off 10s, 60s, 300s, 1800s, 7200s — roughly a three-hour window. After 10 consecutive failed deliveries the endpoint is disabled and your organization is notified; deliveries stay in the log for 30 days and can be replayed from the portal.