Webhooks Guide
Receive InFlow, TrueSight, deal, and usage events in your system.
Webhooks let B2 Systems notify your system when asynchronous work finishes.
Configure webhook endpoints in the B2 Systems dashboard. Each endpoint has a signing secret and a set of enabled events.
Events
Supported events:
inflow.parsing.completedinflow.parsing.failedtruesight.matching.completedtruesight.matching.faileddeal.createddeal.updatedusage.credits_consumed
Use webhooks to trigger CRM updates, but use the GET endpoints as the source of truth.
deal.created is sent when an InFlow or TrueSight request creates a dashboard deal. deal.updated is sent when a public TrueSight matching run updates its API-created deal with completed matching results.
These events are not subscriptions to every dashboard interaction. Dashboard-managed offers, information requests, contracts, final-and-stips actions, notes, and document changes do not currently produce public API webhook events.
Delivery Headers
B2 Systems sends these headers with each webhook:
B2-Webhook-Id: unique webhook event id.B2-Webhook-Timestamp: Unix timestamp in seconds.B2-Webhook-Signature: HMAC SHA-256 signature in the formatv1=<hex>.
Acknowledge Receipt
Return any 2xx response to acknowledge receipt.
If your endpoint returns a non-2xx response, times out, or cannot be reached, the delivery is recorded as failed in the dashboard.
Verify Signatures
Verify the signature using the raw JSON body exactly as received.
The signed payload is:
timestamp.raw_bodyNode.js example:
import crypto from "node:crypto";
function verifyB2Webhook({ rawBody, timestamp, signatureHeader, signingSecret }) {
const expected = crypto
.createHmac("sha256", signingSecret)
.update(`${timestamp}.${rawBody}`)
.digest("hex");
const received = signatureHeader?.startsWith("v1=")
? signatureHeader.slice(3)
: "";
const expectedBuffer = Buffer.from(expected, "hex");
const receivedBuffer = Buffer.from(received, "hex");
if (expectedBuffer.length !== receivedBuffer.length) return false;
return crypto.timingSafeEqual(expectedBuffer, receivedBuffer);
}Reject requests with invalid signatures.
For replay protection, reject requests with an old B2-Webhook-Timestamp. A common window is 5 minutes.
Idempotency
Use the webhook id or B2-Webhook-Id as an idempotency key.
Your endpoint should be safe to receive the same event more than once. Store processed event ids and ignore duplicates.
B2 Systems queues webhook deliveries. If a delivery is retried, the webhook event id stays the same so your idempotency check can treat retries as the same logical event.
Recommended Handler Flow
- Read the raw request body.
- Verify
B2-Webhook-Signature. - Check timestamp freshness.
- Store the event id.
- Return
2xxquickly. - Process the event asynchronously in your system.
- Fetch the latest B2 Systems object with the relevant GET endpoint.
Updated 8 days ago

