Skip to content

Webhooks

Bindly can POST signed events to your endpoint the moment things happen in your workspace — an insured finishes an application, a submission goes out to a market, a signature envelope completes. Webhooks are the push complement to the workspace API: use the event to learn that something happened, then pull whatever you need (including the filled PDFs) with the API.

  1. In the app, open Integrations → Webhooks and add your endpoint URL. Pick the events you want; every endpoint gets its own signing secret (whsec_…), shown once.

  2. Click Send test event. Bindly POSTs a webhook.test delivery so you can verify your handler and signature check end to end.

  3. Return any 2xx quickly. Do slow work after responding — deliveries time out at 10 seconds per attempt.

If you use Zapier instead of your own endpoint, the Bindly Zapier app (available from Integrations → Zapier in the app) subscribes to the same events for you — no endpoint or signature handling required.

Event Fires when Payload highlights
fill_session.completed An application reaches complete — the intake finished and the forms rendered session_id, insured_name, state, form_keys, completed_at
submission.sent A submission email leaves the workspace (Gmail, Microsoft, or a connected market) session_id, to, cc, subject, form_keys, provider, sent_at
esign.completed A signature envelope completes session_id, envelope_id, completed_at

Every delivery is a JSON POST with a fixed top-level shape:

{
"id": "5f0c4d0e-…",
"event": "fill_session.completed",
"created_at": "2026-08-21T18:03:11.482Z",
"data": {
"session_id": "fa697249-…",
"org_id": "91d91b20-…",
"insured_name": "Bluebonnet Handyman Services LLC",
"state": "TX",
"status": "complete",
"form_keys": ["ACORD_125"],
"completed_at": "2026-08-21T18:02:58.113Z"
}
}

Headers on every delivery:

Header Value
X-Bindly-Event The event name
X-Bindly-Delivery The delivery id (same as body id)
X-Bindly-Signature sha256=<hex HMAC-SHA256 of the raw body>

The signature is an HMAC-SHA256 of the raw request body bytes, keyed with your endpoint’s whsec_… secret, hex-encoded, prefixed with sha256=. Always verify against the raw body — parsing and re-serializing the JSON can reorder keys and break verification.

import { createHmac, timingSafeEqual } from "node:crypto";
function verifyBindlySignature(rawBody, header, secret) {
const expected = "sha256=" + createHmac("sha256", secret).update(rawBody).digest("hex");
const a = Buffer.from(header ?? "");
const b = Buffer.from(expected);
return a.length === b.length && timingSafeEqual(a, b);
}
// Express: capture the raw body, then verify before trusting the payload.
app.post("/bindly-webhook", express.raw({ type: "application/json" }), (req, res) => {
if (!verifyBindlySignature(req.body, req.get("X-Bindly-Signature"), process.env.BINDLY_WHSEC)) {
return res.status(401).end();
}
const delivery = JSON.parse(req.body);
res.status(200).end(); // respond fast, work after
handle(delivery);
});
  • Each delivery makes up to 3 attempts (immediately, then after 2s and 5s) with a 10-second timeout per attempt. Any 2xx counts as delivered; anything else after the last attempt is recorded as failed.
  • Failed deliveries are visible (with the response status and error) on the endpoint’s delivery log in Integrations → Webhooks. Bindly does not re-drive failed deliveries across runs in v1 — treat webhooks as notifications and reconcile with the API if you need guarantees.
  • Deliveries are idempotent per event: internal retries of the same completion round, or races between two observers of the same envelope, produce at most one delivery per endpoint per natural key (session_id + completed_at for completions, envelope_id for e-sign). Duplicate X-Bindly-Delivery ids never occur; if your handler retries internally, key your own idempotency on the delivery id.

The payload is deliberately light. Typical follow-ups with the workspace API:

  • GET /org/sessions/{id} — the session’s current state and answers.
  • GET /org/sessions/{id}/forms/{form_key}/pdf — a rendered, filled PDF (one call per entry in form_keys).
  • GET /org/sessions/{id}/risk-summary — the narrative risk summary.