Reference
Webhook events
All 48 event types MindBill sends to webhooks and the events stream, with the signed envelope.
Webhooks and GET /partner/v2/events carry the same event types and data. A webhook tells you something changed; reread the bill or RFA for its current state. Delivery is at least once and can arrive out of order, so deduplicate by id and use sequence to order events within an organization.
Envelope and signature
Each delivery is a JSON POST. The body includes organizationId so one receiver can route events for several customer organizations. The events stream returns the same fields without organizationId, because it is already scoped to one organization.
POST /mindbill/webhooks HTTP/1.1
content-type: application/json
user-agent: MindBill-Webhooks/1.0
mindbill-event-id: evt_example
mindbill-signature: t=1791910800,v1=5f0c…hex HMAC-SHA256…
{
"id": "evt_example",
"organizationId": "org_example",
"sequence": "4218",
"type": "rfa.decision_recorded",
"apiVersion": "2026-08-16",
"createdAt": "2026-10-08T17:02:11.000Z",
"data": {
"rfaId": "rfa_example",
"decidedAt": "2026-10-08",
"itemIds": ["rfaitem_example"],
"status": "approved"
}
}Verify mindbill-signature before trusting the body: compute an HMAC-SHA256 of {t}.{raw body} with the endpoint's signing secret and compare it with v1. Reject stale timestamps. Return a 2xx response only after you have durably stored the event; MindBill retries failures up to ten times with increasing delays.
import crypto from "node:crypto";
// rawBody is the exact request body string; do not re-serialize parsed JSON.
export function verifyMindBillWebhook(rawBody: string, header: string, secret: string) {
const parts = Object.fromEntries(header.split(",").map((part) => part.split("=")));
const expected = crypto.createHmac("sha256", secret).update(`${parts.t}.${rawBody}`).digest("hex");
const valid = typeof parts.v1 === "string" && parts.v1.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(parts.v1), Buffer.from(expected));
const fresh = Math.abs(Date.now() / 1000 - Number(parts.t)) < 300;
return valid && fresh;
}Subscribe to specific events
Create an endpoint with eventTypes to receive a subset, or omit it to receive every type. Set organizationId to limit an endpoint to one customer organization. See partner integration for account-wide endpoints.
curl https://app.mindbill.org/partner/v2/developer/account/webhook-endpoints \
--header "Authorization: Bearer $MINDBILL_ACCOUNT_KEY" \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: rfa-webhook-1' \
--data '{"url":"https://example.com/mindbill/webhooks","eventTypes":["rfa.submitted","rfa.received","rfa.decision_recorded","rfa.follow_up_due"]}'Bills
Lifecycle changes for a submitted bill. data carries billId plus event-specific fields; reread the bill for its current state.
bill.createdA bill was created.
bill.submittedThe bill was submitted through its delivery route.
bill.acceptedThe clearinghouse or payer acknowledged the submission. Acceptance is not payment.
bill.rejectedThe submission was rejected and needs correction.
bill.deniedThe claims administrator denied the bill.
bill.partially_paidA payment left a balance due.
bill.paidThe bill was paid in full.
bill.second_reviewA Second Bill Review was requested.
bill.ibrIndependent Bill Review was requested.
bill.lienThe bill moved to a lien.
bill.closedThe bill was closed.
bill.written_offThe remaining balance was written off.
bill.no_responseNo payer response arrived within the follow-up threshold.
bill.aging_bucket_changedThe bill moved to a new aging bucket.
bill.follow_up_openedA no-response follow-up task opened. data: billId, followUpId, kind, dueAt.
bill.follow_up_resolvedThe follow-up task was resolved by response or payment evidence, dismissal, or closure.
bill.note_addedA note was added to the bill.
bill.courtesy_copy_sentA user sent a courtesy copy of the bill.
bill.autofill_completedReport autofill finished extracting suggestions.
Payments and EORs
Money and payer responses. Reconcile amounts from the bill's EOR and payment reads, not from callback order.
payment.postedA payment was posted to the bill.
eor.receivedAn Explanation of Review (EOR) or remittance was received.
Organization
Customer organization setup.
org.onboarding_completedThe organization completed onboarding and can submit bills.
RFA activity
Changes to a Request for Authorization. data carries rfaId plus opaque IDs for the change; clinical notes and reasons are not included.
rfa.createdA draft RFA was created.
rfa.updatedThe request changed, for example a draft edit, signature, or treatment closure (action treatment_closed or treatment_reopened).
rfa.document_addedA document was attached to the RFA.
rfa.transmission_recordedDelivery or receipt evidence was recorded for a transmission.
rfa.information_requestedThe claims administrator requested more information.
rfa.information_request_respondedA response to an information request was recorded.
rfa.information_receipt_reviewedRequested-information receipt was reviewed.
rfa.decision_recordedUtilization review decisions were recorded for one or more treatments. data: rfaId, decidedAt, itemIds, status.
rfa.decision_correctedA recorded decision was corrected; the previous decision stays in history.
RFA status
Emitted when the request's status changes to the named value. lifecycleStatus on the RFA read summarizes delivery separately.
rfa.draftDraft.
rfa.readySigned and ready to send.
rfa.submittedSent to the claims administrator.
rfa.receivedReceipt by the claims administrator was recorded.
rfa.incompleteMarked incomplete.
rfa.under_reviewUnder utilization review.
rfa.deferredReview deferred.
rfa.approvedAll treatments approved.
rfa.modifiedTreatments approved with modification.
rfa.deniedAll treatments denied.
rfa.mixedTreatments have different outcomes.
rfa.canceledCanceled.
rfa.closedEvery treatment has a final decision or administrative closure.
RFA follow-ups
Backend-derived follow-up tasks such as no response, deadline review, Post UR, and scheduling. data carries opaque IDs and the task kind, without contact notes.
rfa.follow_up_openedA follow-up task opened.
rfa.follow_up_dueA follow-up task became due.
rfa.follow_up_updatedA follow-up task was assigned, snoozed, or updated.
rfa.follow_up_resolvedThe underlying work was completed and the task resolved.
RFA events require the organization's treatmentBilling capability. See treatment billing for which events to act on.