Webhooks
Subscribe to real-time events so your systems can react to customer and billing changes without polling.
Setup
Configure webhooks in Settings → Webhooks. Each webhook has a URL, a list of event subscriptions, and an auto-generated signing secret. You can register multiple endpoints (e.g., one for billing, one for support tooling).
Available events
| Event | When it fires |
|---|---|
| customer.created | A new customer was successfully provisioned. |
| customer.updated | Plan, seats, add-ons, or status changed. |
| customer.deleted | Customer was soft-deleted. Includes the refund amount. |
| subscription.created | Subscription activated for a customer. |
| subscription.updated | Subscription plan or period changed. |
| subscription.cancelled | Subscription cancelled (typically alongside customer deletion). |
| credits.low | Your partner credit balance dropped to $10 or less. |
| credits.depleted | Your partner credit balance hit zero. |
| dicom.report.attached | You attached a medical report to a DICOM study via the Partner API. Payload includes studyInstanceUid + report metadata. |
| dicom.report.detached | You detached a partner-uploaded report. |
Payload format
All webhook payloads use this envelope:
{
"event": "customer.created",
"timestamp": "2026-05-13T15:42:11.000Z",
"data": {
"customer": {
"id": "pc_42_1715600000000",
"email": "acme@example.com",
"name": "Acme Co",
"organizationId": "org_42_1715600000001",
"createdAt": "2026-05-13T15:42:11.000Z"
}
}
}Signature verification
Every webhook request includes an X-Webhook-Signature header — an HMAC-SHA256 of the raw JSON body using your webhook's signing secret. Verify it on every request to confirm the payload came from BigMind and hasn't been tampered with.
import crypto from 'node:crypto';
export function verifySignature(rawBody, signatureHeader, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(rawBody)
.digest('hex');
// timing-safe compare
const a = Buffer.from(expected);
const b = Buffer.from(signatureHeader);
return a.length === b.length && crypto.timingSafeEqual(a, b);
}Headers
Each delivery includes:
X-Webhook-Event— event name, e.g.customer.createdX-Webhook-Timestamp— ISO 8601 delivery timeX-Webhook-Attempt— attempt number (1 for first delivery, 2–3 for retries)X-Webhook-Signature— HMAC-SHA256 hex
Retries
Failed deliveries (non-2xx responses or timeouts) are retried up to 3 times with exponential backoff (1s, 2s, 4s). Every attempt is recorded in your webhook delivery log — visible in the Webhooks settings page.
Your endpoint should:
- Return a 2xx response within 10 seconds. Queue any heavy work for async processing.
- Be idempotent — the same event may arrive multiple times during retries.
- Tolerate out-of-order delivery — use
timestampif ordering matters.