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.

rfa.decision_recorded delivery
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.

server/verify-webhook.ts
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.

Create an RFA webhook endpoint
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.created

A bill was created.

bill.submitted

The bill was submitted through its delivery route.

bill.accepted

The clearinghouse or payer acknowledged the submission. Acceptance is not payment.

bill.rejected

The submission was rejected and needs correction.

bill.denied

The claims administrator denied the bill.

bill.partially_paid

A payment left a balance due.

bill.paid

The bill was paid in full.

bill.second_review

A Second Bill Review was requested.

bill.ibr

Independent Bill Review was requested.

bill.lien

The bill moved to a lien.

bill.closed

The bill was closed.

bill.written_off

The remaining balance was written off.

bill.no_response

No payer response arrived within the follow-up threshold.

bill.aging_bucket_changed

The bill moved to a new aging bucket.

bill.follow_up_opened

A no-response follow-up task opened. data: billId, followUpId, kind, dueAt.

bill.follow_up_resolved

The follow-up task was resolved by response or payment evidence, dismissal, or closure.

bill.note_added

A note was added to the bill.

bill.courtesy_copy_sent

A user sent a courtesy copy of the bill.

bill.autofill_completed

Report 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.posted

A payment was posted to the bill.

eor.received

An Explanation of Review (EOR) or remittance was received.

Organization

Customer organization setup.

org.onboarding_completed

The 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.created

A draft RFA was created.

rfa.updated

The request changed, for example a draft edit, signature, or treatment closure (action treatment_closed or treatment_reopened).

rfa.document_added

A document was attached to the RFA.

rfa.transmission_recorded

Delivery or receipt evidence was recorded for a transmission.

rfa.information_requested

The claims administrator requested more information.

rfa.information_request_responded

A response to an information request was recorded.

rfa.information_receipt_reviewed

Requested-information receipt was reviewed.

rfa.decision_recorded

Utilization review decisions were recorded for one or more treatments. data: rfaId, decidedAt, itemIds, status.

rfa.decision_corrected

A 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.draft

Draft.

rfa.ready

Signed and ready to send.

rfa.submitted

Sent to the claims administrator.

rfa.received

Receipt by the claims administrator was recorded.

rfa.incomplete

Marked incomplete.

rfa.under_review

Under utilization review.

rfa.deferred

Review deferred.

rfa.approved

All treatments approved.

rfa.modified

Treatments approved with modification.

rfa.denied

All treatments denied.

rfa.mixed

Treatments have different outcomes.

rfa.canceled

Canceled.

rfa.closed

Every 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_opened

A follow-up task opened.

rfa.follow_up_due

A follow-up task became due.

rfa.follow_up_updated

A follow-up task was assigned, snoozed, or updated.

rfa.follow_up_resolved

The 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.