Webhooks Crimson Platform

React to talent
events in real time.

Instead of polling, let Crimson push to you. Subscribe an HTTPS endpoint and receive a signed JSON payload the moment a candidate advances, an offer moves, or a benchmark changes.

event.jsonJSON
{ "id": "evt_2Nx9kP...", "type": "candidate.stage_changed", "created": 1744617600, "api_version": "2026-04-01", "data": { "candidate": "cand_3Qp7...", "pipeline": "pipe_8Kx2...", "from_stage": "screen", "to_stage": "onsite" } }

What you can subscribe to.

Pick individual event types per endpoint, or subscribe to all of them. Every event shares the same envelope — an id, a type, a timestamp, and a typed data object.

EVENTcandidate.stage_changedA candidate moved between hiring stages
EVENTpipeline.createdA new search pipeline was opened
EVENToffer.extendedAn offer was sent to a candidate
EVENToffer.acceptedA candidate accepted an offer
EVENToffer.declinedA candidate declined an offer
EVENTcompensation.updatedA benchmark you watch was refreshed

Three steps.

1

Subscribe an endpoint

Register a public HTTPS URL in the dashboard or via the API, and choose which event types it should receive. You can add multiple endpoints and route different events to each.

2

Receive a signed POST

When an event fires, we send a POST with a JSON body and a Crimson-Signature header. Verify the signature, then act on the typed data payload.

3

Respond with 200

Return any 2xx status quickly to acknowledge receipt. Do slow work asynchronously — anything other than a 2xx triggers our retry logic.

Verify every payload.

Every delivery is signed with HMAC-SHA256 using your endpoint's signing secret. Always verify the Crimson-Signature header before trusting a payload — it proves the request came from Crimson and wasn't tampered with in transit.

verify.pyPython
import hmac, hashlib def verify(payload: bytes, header: str, secret: str) -> bool: # header format: "t=<timestamp>,v1=<signature>" parts = dict(p.split("=") for p in header.split(",")) signed = f"{parts['t']}.".encode() + payload expected = hmac.new( secret.encode(), signed, hashlib.sha256 ).hexdigest() return hmac.compare_digest(expected, parts["v1"]) # Reject if verify() is False, or timestamp is older than 5 min

Delivered, guaranteed.

We treat delivery as at-least-once. If your endpoint is down, we keep trying — and you always have a full record of what we attempted.

Automatic retries

Any non-2xx response (or timeout) is retried with exponential backoff over a 24-hour window. Deliveries to a single endpoint preserve order, and repeated failures pause the endpoint and alert you by email.

Delivery log

Every attempt — request body, response code, latency, and retry count — is stored for 30 days and searchable in the dashboard. Inspect any event and replay it to your endpoint with one click.

Ship it right.

Wire up your first webhook.

Add an endpoint in the dashboard, pick your events, grab a signing secret, and you're live in minutes.

Go to the dashboard