Reference
Webhook payloads
The shape of every webhook event Bedrock can send, with examples and signature verification details.
Request format
Every webhook is a JSON POST. Bedrock sends two headers and the payload:
X-Bedrock-Event— the event name (e.g.review.completed)X-Bedrock-Signature—sha256=<hex>, an HMAC-SHA256 of the raw request body using your firm webhook secret- The body is the payload itself, not an envelope. The shape varies by event type.
Signature
The signature header has the form sha256=<hex>. Compute HMAC-SHA256 over the raw request bytes using your firm's webhook secret and compare the hex digest in constant time.
import { createHmac, timingSafeEqual } from 'node:crypto';
function verify(rawBody: Buffer, header: string, secret: string) {
const [scheme, provided] = header.split('=');
if (scheme !== 'sha256' || !provided) return false;
const expected = createHmac('sha256', secret).update(rawBody).digest('hex');
const a = Buffer.from(provided, 'hex');
const b = Buffer.from(expected, 'hex');
return a.length === b.length && timingSafeEqual(a, b);
}Event types
Each event delivers the canonical resource as the payload. The shapes below come directly from the schemas in /openapi.json.
review.completed
Header: X-Bedrock-Event: review.completed. Body: the completed Job resource.
{
"id": "job_01HX4...",
"firmId": "firm_01HW1...",
"documentType": "SUITABILITY_REPORT",
"clientReference": "client-12345",
"documentReference": "report-2026-04-07-001",
"status": "COMPLETED",
"outcome": "APPROVED",
"priority": "STANDARD",
"assignedTo": "user_01HW2...",
"createdAt": "2026-04-07T12:30:01.000Z",
"updatedAt": "2026-04-07T12:35:01.000Z"
}document.approved / document.modified / document.rejected
Header: X-Bedrock-Event: document.approved (or document.modified / document.rejected). Body: the outcome LedgerRecord. Subscribe to these instead of the deprecated certificate.issued if you want to know when a review's certificate is on its way — once cert-gen finishes, fetch the PDF via GET /v1/ledger/records/{id}/certificate using the record id from this payload.
{
"id": "rec_01HW2...",
"firmId": "firm_01HW1...",
"eventType": "DOCUMENT_APPROVED",
"reviewJobId": "job_01HX4...",
"documentMetadata": {
"documentReference": "SR-2026-0142",
"documentType": "SUITABILITY_REPORT",
"outcome": "APPROVED",
"reviewerName": "James Hargreaves"
},
"timestamp": "2026-04-07T12:35:02.000Z"
}sla.breached
Header: X-Bedrock-Event: sla.breached. Body: details of the breached job.
{
"reviewJobId": "job_01HX4...",
"firmId": "firm_01HW1...",
"deadline": "2026-04-07T17:00:00.000Z",
"overdueBySeconds": 3600
}Delivery semantics
- At-least-once delivery
- Retries with exponential backoff for any non-2xx response, up to 24 hours
- Dedupe by a stable identifier from the payload (e.g.
id,recordId, orreviewJobId)