@mindbill/react
v0.77.3
Published
Native React components and hosted workflows for MindBill billing
Maintainers
Readme
@mindbill/react
Native React billing components and connected lifecycle hooks. Install with:
npm install @mindbill/react @mindbill/nodeConnected lifecycle
ConnectedBillLifecycle starts after BillSubmissionForm atomically submits an immutable bill. Its only bill input is billId; getSession returns the short-lived token. The component fetches the submitted snapshot, progress, human-readable history, rejection details, EOR/remittance amounts, payments, and available actions from MindBill. Do not pass lifecycle seed data or duplicate this state in the host app. The only persistent header action is Download packet, which opens the authenticated PDF packet directly in a new browser tab; status-dependent actions remain visible in a sticky bottom action bar when MindBill makes them available. Actions that require input open a focused form dialog.
import { ConnectedBillLifecycle } from "@mindbill/react";
<ConnectedBillLifecycle
billId={billId}
getSession={getMindBillSession}
appearance={{ preset: "qme-companion" }}
/>Sandbox and live responses use the same component contract. Simulation controls
are hidden by default, including when the connected organization is a sandbox.
Only a dedicated developer playground should opt in with
sandboxControls={true}; production applications should omit the prop.
Appearance
Choose a complete preset, then override only the tokens your design system owns. The preset applies to review, payer search, attachments, submission, status, EOR, payment, denial, resubmission, and close states.
<ConnectedBillLifecycle
billId={billId}
appearance={{ preset: "midnight-cyan" }}
/>midnight-cyan gives every billing surface a spacious pale-blue canvas, crisp white panels, midnight actions and typography, cyan-compatible accents, and pill-shaped controls. No extra CSS is required.
Available presets are mindbill, qme-companion, orange-bright, clinical-blue, and midnight-cyan. Preset names describe visual styles rather than customer or partner brands. Supported overrides include accent, accent text, background, surface, input background, text, muted text, border, font, panel radius, control radius, shadow, danger, success, and warning colors.
Add one authenticated route to your app. It maps the signed-in user's role to billing permissions, then mints an exact-origin token for that user in your MindBill organization. The Partner API key stays on the server.
// Any server framework: POST /api/mindbill/session
import { mindbill } from "@/lib/mindbill";
export async function POST(request: Request) {
const user = await requireUser(request); // your existing auth
const session = await mindbill.createBrowserSession({
subject: user.id,
allowedOrigin: new URL(request.url).origin,
permissions: billingPermissionsFor(user.role),
expiresIn: 900,
});
return Response.json({
token: session.token,
expiresAt: session.expiresAt,
});
}The API key binds every session to one organization. subject identifies the user and permissions express the role. MindBill enforces the organization boundary on every bill request. A permanent Partner API key must never enter frontend code.
Compact status
Use ConnectedBillStatus when the partner page only needs a small status and aging surface. It reuses the same session route.
import { ConnectedBillStatus } from "@mindbill/react";
<ConnectedBillStatus
billId={billId}
sessionEndpoint="/api/mindbill/session"
appearance={{ preset: "qme-companion" }}
/>Use useBillStatus({ billId }) when you want to render custom status UI. It returns data, error, isLoading, isRefreshing, and refresh. Use createBillStatusClient outside React.
The public lifecycle is Submitted → Accepted → Processed → Closed. Rejections and denials remain detailed states inside the Processed stage so the progress rail stays stable while the sticky action bar explains what the user can do next. Partner APIs and components do not expose draft or queued states. Once the payer responds, the Details tab leads with one consolidated Explanation of Review reconciliation surface: billed, allowed, payer-reported payment, posted payment, penalty and interest, balance, denial reason, payment records, and the EOR document.
Read-only bill details
Use BillReadOnlyForm when you already loaded BillLifecycleData and only need the immutable detail surface. It uses the same section order and responsive layout as BillSubmissionForm, but renders values, calculated fees, routing details, and attachments without form controls. Its claims-administrator name is the canonical directory selection from the submitted delivery snapshot; selecting it opens a responsive directory dialog with Main, Bill Review, Authorization, Mailing Address, and Claim Number Pattern tabs when those fields are available from the API.
import { BillReadOnlyForm } from "@mindbill/react";
<BillReadOnlyForm data={billLifecycleData} onOpenAttachment={openAttachment} />ConnectedBillLifecycle composes this component with the Details / Bill history switch, so most partners should not assemble these pieces themselves.
ConnectedBillingWorkspace is the complete task, search, procedure,
productivity, and bill-detail experience. It measures the space remaining in
the browser viewport and owns vertical scrolling, so dashboard shells cannot
trap content below the fold. Hosts can still give it an explicit height:
<main style={{ height: "100dvh", minHeight: 0 }}>
<ConnectedBillingWorkspace
sessionEndpoint="/api/mindbill/session"
onCreateBill={() => router.push("/billing/new")}
/>
</main>For flex or grid shells, setting min-height: 0 on the workspace's ancestors
remains a useful layout default. An explicit height or maxHeight in the
component's style prop continues to take precedence.
Optional RFA tab
Set showRfas (default false) on ConnectedBillingWorkspace or
BillingDashboard. Pass rfaDashboard for authorized UI permissions, actor reference, callbacks, and optional dedicated
session. The connected workspace inherits its main connection; initialView="rfas"
opens the tab immediately.
<ConnectedBillingWorkspace
sessionEndpoint="/api/mindbill/session"
showRfas
rfaDashboard={{
permissions: ["create", "edit", "sign", "send", "act"],
actorReference: authenticatedUser.id,
environment: "sandbox",
canCreateClaim: true,
canManageProviderSignatures: true,
}}
/>The tab includes saved patient/injury and physician selection, unsigned draft creation,
contact details, per-service diagnoses, clinical PDF uploads, reviewed signing, and
confirmed fax/email delivery or packet download. An RFA belongs to an injury and does not
require a bill. Creation requires create permission; an optional initialDraft skips
selection for hosts with a prepared case.
canCreateClaim offers new patient and injury setup. canManageProviderSignatures
offers authorized signature PNG setup directly before signing. Both default to false;
the trusted session also needs their scopes. Saving a signature does not sign or send a
request. Use signatureSession={{ getSession: getSignatureSetupSession }} on
RfaDashboard (or within rfaDashboard) for a separate signature setup session with
organization:manage and rfas:sign; previews and signing still use the main RFA session.
UI permissions do not grant server access, and sandbox disables external fax
and email delivery. See the RFA dashboard guide for session
scopes, contact snapshots, and the reviewed delivery workflow.
Built-in Settings tab
React 0.64.0 adds a Settings tab, enabled by default, to
ConnectedBillingWorkspace and BillingDashboard. It includes practice identity,
billing providers, rendering providers, service locations, W-9 upload, and setup
readiness. Settings load only when the tab opens.
<ConnectedBillingWorkspace
sessionEndpoint="/api/mindbill/session"
showSettings={isAdministrator}
billingSettings={{ sessionEndpoint: "/api/mindbill/settings-session" }}
onSettingsSaved={(profile) => refreshHostBillingProfile(profile)}
/>Use showSettings={false} to hide the tab. Your server must authorize the signed-in
user before minting a settings session with org:manage; tab visibility does not
grant access. With no billingSettings, the connected workspace reuses its main
connection. The data-driven BillingDashboard uses /api/mindbill/session unless
you pass billingSettings. No settings request is made while the tab is hidden.
Use initialView="settings" on the workspace to open setup immediately; if settings
are hidden, it opens Bill tasks instead.
Saved profiles become available when bill creation/correction forms next load.
onSettingsSaved lets hosts refresh separately mounted forms or their own caches.
Continue passing the same billingSettings to a standalone BillSubmissionForm
for its inline “Add or manage” action. You can still mount BillingSettings
separately when your product has its own settings navigation.
BillRejectionNotice is also exported for custom lifecycle layouts. It presents every API-provided rejection issue in order, keeps technical acknowledgement codes alongside the actionable descriptions, and shows when the bill was sent and rejected. The connected lifecycle includes it automatically whenever the current state is rejected.
<BillRejectionNotice
submittedAt="2026-08-31T17:24:00.000Z"
rejection={{
reason: "Correct the submitted dates.",
source: "Jopari",
receivedAt: "2026-09-01T16:11:00.000Z",
issues: [
{ code: "A6:187", description: "From Date of Service cannot be in the future" },
{ code: "A6:88", description: "Thru Date of Service cannot be in the future" },
],
}}
/>For older responses without issues, the component falls back to the singular reason and code fields. appearance.dangerColor can override the rejection color without changing the rest of the theme.
For the server-authorized Correct and resubmit action,
ConnectedBillLifecycle opens BillSubmissionForm with the complete submitted
snapshot and authenticated copies of its documents. API-provided rejection
fieldPaths call attention to likely problem controls, and payer contact
guidance remains visible while the user corrects the bill. Submitting creates
the next immutable attempt under the same logical billId; the original
attempt and rejection remain in history. Submit first opens a required delivery
confirmation for the corrected administrator and selected subpayor, where the
biller can verify or switch among e-bill, fax, email, and mail. Nothing is sent
until that second confirmation is submitted. The host application does not
build a second correction form or pass bill seed data back into the lifecycle.
For a closed bill the server authorizes exactly two actions — Reopen
and Submit New Bill. Submit New Bill opens the same BillSubmissionForm,
prefilled from the closed bill's snapshot with its documents carried forward,
and a Cancel button returns to the closed-bill view. Submitting creates a
fresh original bill linked to the closed predecessor: the closed bill stays
closed and keeps its record, and the submissions ribbon/timeline chains both
bills. Failures surface inline in the dialog, exactly like the correction
flow.
Lifecycle actions
MindBill returns the actions that are valid for the bill's current state. Render that server-authoritative list instead of duplicating rejection, EOR, denial, review, payment, and closure rules in your application.
import { BillLifecycleActions } from "@mindbill/react";
<BillLifecycleActions
actions={bill.data.lifecycle.actions}
onAction={(action) => {
switch (action.id) {
case "view_eor": return bill.openEor();
case "post_payment": return setPaymentOpen(true);
case "second_review": return setSecondReviewOpen(true);
case "close": return bill.closeBill({ reason: "Resolved" });
case "reopen": return bill.reopenBill({ reason: "Follow-up is continuing" });
}
}}
/>Disabled actions are hidden by default. Set showUnavailable to show them with the reason returned by the API.
Set maxVisible={1} for a compact workspace that shows the recommended action and puts the remaining authorized actions in a host-provided overflow menu.
Activity timeline
BillActivityTimeline renders the ordered, human-readable lifecycle events returned by MindBill. Partners do not need to store or reconstruct bill history.
import { BillActivityTimeline } from "@mindbill/react";
<BillActivityTimeline events={bill.data.activity} />Browser callbacks such as onChanged are for immediate UI, navigation, optimistic state, and analytics. MindBill remains authoritative for durable history; signed webhooks are available when your backend also needs event-driven synchronization.
Bill submission form
BillSubmissionForm owns the complete pre-submission experience: the bill field schema, required-field rules and red asterisks, validation, service-line editing, source-document selection, PDF uploads, and the single Submit action. Its bill value is structurally identical to the server SDK's CreateBillRequest.
The partner application only loads initial values and mints a short-lived browser session. Uploaded files stay in the browser until the user submits; the component validates and sends the immutable snapshot and PDF bytes directly to MindBill.
import { BillSubmissionForm } from "@mindbill/react";
<BillSubmissionForm
initialBill={bootstrap.bill}
attachments={bootstrap.attachments}
getSession={() => fetch("/api/mindbill/session", { method: "POST" }).then(r => r.json())}
appearance={{ preset: "qme-companion" }}
onSubmitted={({ billId }) => saveLocalBillLink(billId)}
/>The component includes the interaction model, not just the markup:
- a responsive two-column review form (one column on narrow screens);
- paste-friendly
MM/DD/YYYYdate fields and required-field asterisks; - ZIP-to-city/state completion through MindBill's authenticated postal directory;
- complete, server-backed ICD-10 search with an alphabetized 100-code first page, automatic 100-code scroll paging, common-injury quick picks, and removable chips;
- an authenticated claims-administrator browser that opens to an alphabetized 50-item page, loads later pages on scroll, searches from the first character, and preserves exact-name and claim-number evidence;
- explicit routing-payer selection when the administrator requires it, with aliases, affiliated entities, claim-number hints, delivery type, clearinghouse routes, and payer identifiers shown in context;
- QME, AME, Psych QME, and Psych AME evaluation modes with medical-legal modifier defaults; psychiatric QME evaluations combine
95and96, while psychiatric AME evaluations combine94and96. Both psychiatric modes seedZ04.6when no more specific diagnosis was supplied, and exposes it as a Psych quick pick; - a searchable rendering-provider taxonomy combobox that accepts either a human-readable specialty search or an exact 10-character taxonomy code;
- searchable workers-comp procedure/modifier controls, medical-legal fee-schedule amounts, totals, valid manual CPT/HCPCS entry, and an automatically maintained empty line;
- removable source documents with new-tab previews and a full-width click, panel-drop, or whole-page PDF upload area. Auto-attached documents can be removable when the host sets
removable: true; otherwise they remain locked by default. Med-legal mode assigns every document toJ4 - Med-Legal Reportwithout showing another control; professional mode shows the complete searchable PWK01 report-type directory. Override that presentation withattachmentReportTypeMode,attachmentReportTypes, anddefaultAttachmentReportType.
Partners supply tenant-specific bootstrap data, one short-lived browser session callback, and optionally an onSubmitted callback to persist the returned billId. Required fields, validation, ZIP lookup, ICD-10 and payer directories, service-line behavior, PDF encoding, wire-format serialization, atomic submission, attachments, and submission UX stay inside @mindbill/react, so every integration receives the same billing workflow. Optional diagnosisOptions, procedureOptions, modifierOptions, and lookup callbacks extend or replace defaults when a partner has licensed or organization-specific data.
Validation is component-owned as well. A missing routing payer is highlighted immediately; Submit highlights every invalid control with a specific message, focuses and scrolls to the first problem, and continues validating as the user corrects the form.
The complete immutable snapshot requires patient identity and address; employer, injury date, service date, and a canonical claims-administrator directory selection; at least one ICD-10 diagnosis and procedure line; billing provider name, Tax ID, NPI, phone, and address; rendering provider name, NPI, and taxonomy; and service address plus place-of-service code. Address line 2 remains optional. License number, license state, specialty, and service-facility display name are not requested by the standard component. For California workers-comp CMS-1500 output, renderingProvider.taxonomy is the 10-character provider taxonomy placed in shaded Box 24J with qualifier ZZ; it is not replaced by the physician license number.
BILL_SUBMISSION_REQUIRED_FIELDS and validateBillSubmission expose the same contract for tests and non-visual integrations. The component never creates a draft; onSubmitted fires only after MindBill accepts a locally valid immutable snapshot. The legacy onSubmit escape hatch remains optional for unusual deployments, but connected integrations should omit it so the library owns the complete contract.
BillReviewForm remains available for legacy integrations that already own a custom review model. New integrations should use BillSubmissionForm.
Compose individual submission sections
BillSubmissionForm is also the form-state provider. Put its named children in your own page shell when you want the same MindBill behavior in a partner-specific layout. The sections do not duplicate required-field, directory, fee, attachment, or submission logic.
import {
BillSubmissionActions,
BillSubmissionAttachmentsSection,
BillSubmissionClaimSection,
BillSubmissionForm,
BillSubmissionHeader,
BillSubmissionPatientSection,
BillSubmissionProvidersSection,
BillSubmissionServiceLinesSection,
} from "@mindbill/react";
<BillSubmissionForm {...submissionProps}>
<BillSubmissionHeader />
<BillSubmissionPatientSection />
<BillSubmissionClaimSection />
<BillSubmissionProvidersSection />
<BillSubmissionServiceLinesSection />
<BillSubmissionAttachmentsSection />
<BillSubmissionActions />
</BillSubmissionForm>Omit a section when another step in your product already supplies that information, or reorder sections to match your workflow. BillSubmissionActions remains the only submit control and always validates the complete immutable snapshot.
Billing dashboard, aging, bill list, and reports
The dashboard components accept plain bill summaries, so they work with @mindbill/node's listBills() response, a server-rendered loader, or a partner-owned cache. They never require an API key in the browser.
import {
BillingDashboard,
BillingReport,
buildBillingReportCsv,
type BillingDashboardBill,
} from "@mindbill/react";
const bills: BillingDashboardBill[] = apiBills.map((bill) => ({
id: bill.id,
billNumber: bill.billNumber,
patientName: `${bill.patient.firstName} ${bill.patient.lastName}`,
claimNumber: bill.claim.claimNumber,
payerName: bill.claim.claimsAdministrator?.name,
state: bill.state,
// Supply agingDays from your status/lifecycle response, or submittedAt when
// your server-side bill summary includes it.
agingDays: agingByBillId[bill.id] ?? 0,
totalCharge: bill.amounts.charged,
totalPaid: bill.amounts.paid,
balanceDue: bill.amounts.balance,
href: `/billing/${bill.id}`,
}));
<BillingDashboard
bills={bills}
appearance={{ preset: "orange-bright" }}
onSelectBill={(bill) => router.push(`/billing/${bill.id}`)}
/>
<BillingReport bills={bills} groupBy="payer" />Use the smaller pieces independently when a page already has its own shell:
BillAgingSummary— outstanding balance, open count, collected, total billed, and 0–30 / 31–60 / 61–90 / 91+ buckets;BillList— responsive desktop table and mobile cards;BillingReport— grouped totals bystatus,payer, oraging;BillStatusAgingMatrix— the management view billers expect: one row per lifecycle status, one column per aging bucket, clickable counts with outstanding balances, and row/column totals;summarizeBillingDashboard,buildBillingReportRows, andbuildBillStatusAgingMatrix— presentation-free aggregates;buildBillingReportCsvandbuildBillStatusAgingCsv— the same rows as downloadable CSV text.
<BillStatusAgingMatrix
bills={bills}
appearance={{ preset: "clinical-blue" }}
onSelectCell={(cell) => showDrillDown(cell.state, cell.bucket, cell.bills)}
/>Each cell carries the exact bills behind its count, so a drill-down never needs a second query. Pass stateOrder to pin your own lifecycle ordering; unknown states append alphabetically.
Pass only synthetic data to public examples and tests. In production, load organization-scoped bills on the server and authorize each bill-detail route independently.
Use BillStatusSummary only when your application already owns status loading and wants a presentation-only component:
<BillStatusSummary
status={status.state}
totalCharge={status.totalCharge}
totalPaid={status.totalPaid}
balanceDue={status.balanceDue}
agingDays={42}
updatedAt={status.updatedAt}
actions={[
{ id: "eor", label: "View EOR", onClick: openEor },
{ id: "review", label: "Start second review", onClick: startReview, primary: true },
]}
/>MindBillBillReview and MindBillBillTimeline are available when a hosted flow is a better fit. Native and hosted UI paths use the same bill ID.
Never send a Partner API key or long-lived credential to React/browser code.
Bill tasks worklist, submissions ribbon, and payer status calls
BillTasksDashboard is a Bill Tasks worklist: one tone-colored card per task section, rows bucketed by age (1-30 / 31-60 / 61-90 / 91-180 / 181+ days), clickable counts that carry the bill refs behind them, and a grand-total card. It is purely props-driven — aggregate your own work items with buildBillTasksDashboard (re-exported from @mindbill/browser):
import { BillTasksDashboard, buildBillTasksDashboard } from "@mindbill/react";
const data = buildBillTasksDashboard(workItems, [
{ id: "payment_due", label: "Payment Due", agingBasisLabel: "Bill Sent Date", tone: "violet" },
{ id: "denials", label: "Denials", agingBasisLabel: "EOR Date", tone: "red" },
]);
<BillTasksDashboard
data={data}
heading="Bill Tasks"
onSelectCell={(cell) => openWorklist(cell.sectionId, cell.rowId, cell.bucketId, cell.refs)}
/>BillSubmissionsRibbon renders a horizontal row of selectable submission chips
(Original Bill, Second Review, Duplicate Bill, …). Each chip summarizes its
attempt's latest acknowledgement or payment state — for example 277 Reject
or Payment in 30 working days — plus delivery, sent date, and the relevant
reject/effective date. billSubmissionsRibbonFromHistory derives those chips
from one unified history across every attempt. In ConnectedBillLifecycle, a
chip click keeps the Details tab open and shows that transmission's receipt,
delivery, sent date, and status. The immutable bill detail remains below it;
the complete cross-attempt audit trail is available only through the explicit
Bill history tab.
The connected lifecycle also renders server-owned bill notes and an Add note
control. Custom compositions can call useBillLifecycle({ billId }).addNote({
note, actorName }); note activity is shared with other authorized partner and
MindBill users.
ReportBillStatusDialog records the outcome of a payment-status phone call to the Claims Administrator / Bill Review vendor: payer contacts, the host-rendered submission receipt (for example a BillHistoryTable), and the five standard reported statuses (REPORT_BILL_STATUS_OPTIONS). The host posts the resulting ReportBillStatusInput through its own lifecycle action call.
Organization onboarding and billing settings
OrganizationOnboarding captures the practice identity, billing provider, locations, and W-9 once — saved straight to your MindBill organization through the browser session — so your users never visit the MindBill dashboard. BillingSettings is the compact edit-after-setup variant of the same surface.
import { OrganizationOnboarding } from "@mindbill/react";
<OrganizationOnboarding
sessionEndpoint="/api/mindbill/session"
appearance={{ preset: "clinical-blue" }}
onCompleted={() => enableBillingFeatures()}
/>The session must be minted with the optional organization:manage permission. Each step saves independently through idempotent upserts that never delete records created elsewhere; the review step mirrors MindBill's onboarding checklist and onCompleted fires when everything required is in place.
Dental and authorization drafts
DentalDraftEditor captures dental services, tooth details, and nullable extended
practice charges. RfaDraftForm prepares unsigned requests for authorization,
including review type, independent written confirmation, rationale, contact snapshots,
and requested services with per-line diagnoses. Both save through your
host-server callback; saving does not transmit or authorize anything. See
treatment draft integration for input types,
revision handling, charge semantics, and signing boundaries.
Stable creation keys
BillSubmissionForm accepts an optional idempotencyKey. Generate and persist it on the host backend once per logical case bill, return it with the authorized case state, and reuse it across retries and tabs. The form forwards it to the browser SDK's submission request. The host must still enforce unique case associations and verify the returned bill; a key or recovery callback is not database concurrency control. See examples/quickstart for the complete flow.
Authorization destinations
RfaAuthorizationDestination provides an explicit office/contact choice for an RFA using claims-administrator directory data. Fax and email are separate options; missing or withdrawn profiles allow a fax confirmed with the handling adjuster. When using this selector alone, the host owns signing, destination confirmation, and delivery. RfaDashboard supplies the connected signing, packet review, and confirmed fax/email delivery workflow.
See the RFA directory guide for the contextKey, loading/error, and onChange contract.
Treatment lines offer 25, GP/GO/GN and CQ/CO, with dated telehealth meanings
for 93/95. Medical-legal lines retain evaluator defaults and modifier meanings.
Treatment-only bills hide the evaluator selector. Modifier choices do not promise
pricing: unresolved quotes remain subject to fee review, with readable help text
that wraps on mobile. See modifier guidance.
RFA response workflows include a task board, reviewed incoming-fax matching, per-treatment Post UR decisions, and supporting PDFs during request creation. See the RFA dashboard guide for permissions and integration details.
