Embed treatment bills with expected OMFS payment and the complete Request for Authorization workflow in your application.
A treatment integration has two connected parts. Billers enter a treatment (CMS-1500 professional) bill and see the expected California OMFS payment for every line as they type. Clinicians and staff request authorization for that treatment with a DWC Form RFA, send it, and record the utilization review (UR) decision. MindBill links the two: an approved treatment can be attached to the bill line it authorizes.
Install @mindbill/react 0.79.0, which brings @mindbill/browser 0.52.0:
Terminal
npm install @mindbill/react@0.79.0
Enable the organization
Treatment billing, RFAs, and fee quotes require the treatmentBilling capability on the customer organization. MindBill enables it during onboarding. Until then, these endpoints return HTTP 403 with problem code treatment_billing_not_enabled. Show a clear "not enabled for this practice" state rather than retrying. Enabling the capability does not grant any user access: every request still needs the matching scope or browser permission.
The organization also needs saved records the workflow refers to by ID: rendering providers (with a saved signature for physicians who sign RFAs), service locations, and a billing provider. Manage them in billing settings. Live RFA delivery uses the organization's managed return fax number, which MindBill configures; sandbox never sends.
Session permissions
Your server authenticates the user and mints a short-lived, exact-origin browser session. RFA and fee-quote routes need an organization-wide session; bill-scoped sessions are rejected.
Capability
Browser permission
Server scope
Expected OMFS payment, related records, UR decisions on a bill
bills:read (+ rfas:read for related records)
bills:read (+ rfas:read)
Submit the treatment bill
bills:create
bills:write
List and resume bill drafts / save, replace, and delete them
bills:read / bills:create
bills:read / bills:write
Attach UR decisions to an unsent bill
bills:act
bills:write
List, view, export RFAs; form and packet previews
rfas:read (+ documents:read for stored PDFs)
rfas:read
Creation choices, new drafts, draft preview
rfas:create
rfas:write
Edit drafts, upload documents, close a treatment
rfas:edit
rfas:write
Sign; save a physician signature (+ organization:manage)
rfas:sign
rfas:sign
Deliver, forward, record receipt and decisions, read UR responses, tasks
rfas:act
rfas:write
server/treatment-session.ts
// server: POST /api/mindbill/treatment-session (any framework)// Map the signed-in user's role to the smallest set of permissions they need.const session = await mindbill.createBrowserSession({ subject: user.id, allowedOrigin: process.env.APP_ORIGIN!, // exact origin, e.g. https://app.example.com permissions: [ "bills:read", "bills:create", "bills:act", // treatment bills and UR attachments "rfas:read", "rfas:create", "rfas:edit", // RFA list, drafts, documents ...(user.canSign ? ["rfas:sign"] : []), // physician signature ...(user.canSend ? ["rfas:act"] : []), // delivery, receipt, decisions, tasks "documents:read", "payers:read", // PDF previews, recipient directory ], expiresIn: 900,});return Response.json({ token: session.token, expiresAt: session.expiresAt });
See authentication for origin checks and error handling. Never send a permanent API key to the browser.
Create a treatment bill with expected OMFS payment
ConnectedTreatmentBillForm is the treatment bill form with three columns per service line: an editable Charge, the Expected (OMFS) payment, and the Difference. Every line of the visit is priced together, exactly as MindBill prices the saved bill, so multiple-procedure, bundling, add-on, NCCI, and same-day rules apply across lines. A line can instead show Bundled, Not payable, or Needs review with a short note. Totals never present a final amount while a line needs review. Visit-wide notes, such as a per-visit cap or the LC 4604.5 therapy visit count, appear once under the heading.
ConnectedTreatmentBillForm with synthetic lines: a modifier note on 99213, 97014 not payable, and visit totals.
Try it live: the preview below runs the published component against a mocked encounter quote. Change a code, units, modifier, or charge to reprice the visit.
ConnectedTreatmentBillFormMocked encounter quote and drafts · edit lines, save a draft
import{useState}from"react";import{ConnectedTreatmentBillForm}from"@mindbill/react";constaddress = {line1:"100 Example Way",city:"Oakland",state:"CA",postalCode:"94612"};constinitialBill = {externalId:"visit_demo_1",billingMode:"professional",patient:{firstName:"Alex",lastName:"Morgan",dateOfBirth:"1988-03-05",address},claim:{claimNumber:"WC-44871",employer:"Northstar Foods",dateOfInjury:"2026-05-30",claimsAdministrator:{id:"payer_demo",name:"Example Claims Administrator"},},service:{date:"2026-10-08"},billingProvider:{name:"Example Spine Group",taxId:"123456789",npi:"1234567890",phone:"5105550100",address},renderingProvider:{name:"Sam Example, D.C.",npi:"1098765432",taxonomy:"111N00000X"},serviceLocation:{name:"Example Office",placeOfServiceCode:"11",address},diagnoses:["M54.50"],serviceLines:[{code:"99213",modifiers:["25"],units:1,charge:180,serviceDate:"2026-10-08",diagnosisPointers:[1]},{code:"97110",units:2,charge:120,serviceDate:"2026-10-08",diagnosisPointers:[1]},{code:"97014",units:1,charge:40,serviceDate:"2026-10-08",diagnosisPointers:[1]},],};// Mock of POST /partner/v2/fee-quotes/encounter with a tiny synthetic fee table (cents per unit).constfees = {"99213":9000,"97110":4650,"97140":4200,"98941":5400};functionquote(body){constlines = body.lines.map((line)=>{if(line.code === "97014")return{id:line.id,assessment:"not_separately_payable",findings:[],displayNotes:["97014 is not payable under the California schedule; bill G0283 or omit."],quote:{status:"not_separately_payable",reason:"code_not_payable",provenance:[]}};constunit = fees[line.code];if(!unit)return{id:line.id,assessment:"requires_review",findings:[],displayNotes:["Not in this demo's fee table."],quote:{status:"requires_review",reason:"fee_schedule_code_not_found",provenance:[]}};constamountCents = unit * (line.units || 1);constnotes = line.code === "99213" && line.modifiers?.includes("25") ? ["Modifier 25: document a separately identifiable visit."] : [];return{id:line.id,assessment:"priced",findings:[],displayNotes:notes,quote:{status:"priced",amountCents,scheduleMaximumCents:amountCents,basis:"ca_physician_rbrvs",notes:[],provenance:[],...(line.chargeCents ? {chargeAmountCents:line.chargeCents} : {})}};});constpriced = lines.filter((line)=>line.assessment === "priced");constreview = lines.filter((line)=>line.assessment === "requires_review").length;constsubtotal = priced.reduce((sum,line)=>sum + line.quote.amountCents,0);return{status:review ? "requires_review" : "priced",lines,totals:{submittedChargeCents:body.lines.reduce((sum,line)=>sum + (line.chargeCents || 0),0),pricedSubtotalCents:subtotal,estimatedPayableCents:review ? null : subtotal,scheduleMaximumCents:review ? null : subtotal,reviewLineCount:review},claimEdits:[],limitations:[],medicalLegalLineIds:[],visitNotes:["Therapy visit 3 of 24 (LC 4604.5)"],};}// Mock of POST/PATCH /partner/v2/bill-drafts: keeps one draft in memory and bumps its revision per save.letsavedDraft = null;functionsaveDraft(method,body){constnow = new Date().toISOString();savedDraft = {id:"billdraft_demo",externalId:body.externalId ?? savedDraft?.externalId ?? null,status:"draft",revision:method === "POST" ? 1 : savedDraft.revision + 1,claimId:null,patientId:null,bill:body.bill,encounter:body.encounter ?? savedDraft?.encounter ?? null,serviceLineCount:(body.bill.serviceLines || []).length,submittedBillId:null,createdAt:savedDraft?.createdAt ?? now,updatedAt:now,submittedAt:null,};returnsavedDraft;}asyncfunctionmockApi(input,init = {}){consturl = new URL(String(input),location.href);if(url.pathname.endsWith("/partner/v2/fee-quotes/encounter"))returnResponse.json({data:quote(JSON.parse(init.body))});if(url.pathname.includes("/partner/v2/bill-drafts") && (init.method === "POST" || init.method === "PATCH")){returnResponse.json({data:saveDraft(init.method,JSON.parse(init.body))},{status:init.method === "POST" ? 201 : 200});}returnResponse.json({data:[]});}exportdefaultfunctionApp(){const[total,setTotal] = useState(null);const[draft,setDraft] = useState(null);return<mainclassName="review-demo"><pclassName="notice">Expected payment for this visit: {total == null ? "needs review" : "$" + (total / 100).toFixed(2)}</p>{draft ? <pclassName="notice">Draft {draft.id} saved, revision {draft.revision}. Nothing was sent.</p> : null}<ConnectedTreatmentBillFormgetSession={async()=>({token:"demo_session"})}fetch={mockApi}initialBill={initialBill}encounter={{renderingProviderId:"rp_demo",placeOfServiceId:"loc_demo",claimId:"claim_demo"}}onEncounterQuote={(estimate)=>setTotal(estimate?.totals.estimatedPayableCents ?? null)}draftsdraftExternalId="visit_demo_1"onDraftSaved={setDraft}deliveryRoutePicker="off"appearance={{preset:"mindbill"}}onSubmit={async()=>alert("The demo submits nothing.")}/></main>;}
The encounter IDs are saved MindBill records, not free text:
renderingProviderId: from GET /rfas/creation-context (renderingProviders[].id) or the organization billing profile.
placeOfServiceId: a saved service location, locations[].id from GET /partner/v2/organization/billing-profile (see billing settings). Provider type, facility setting, and practice charges come from these saved records.
claimId (optional): the claim's claims administrator is used, and prior therapy visits count toward LC 4604.5 limits. billingProviderId is optional; the organization default applies when omitted.
Submission is unchanged: the form submits a professional bill through POST /bills. Link a line to an approved treatment with serviceLines[].rfaItemId; the server validates the relationship, and the ID alone is not evidence of approval.
Save and resume drafts
A biller often starts a treatment bill before every detail is known. From React 0.79.0, pass drafts to show a Save draft button next to Submit. It saves the bill exactly as entered, even if incomplete, plus the encounter pricing IDs, to POST /bill-drafts; later saves replace the same draft at its current revision. Saving validates nothing for submission, prices nothing as final, and sends nothing. A draft is not a bill: it does not appear in bill lists, events, or usage.
Pass draftId to resume. The form loads the draft, its saved bill replaces initialBill, and any encounter IDs you leave out come from the draft. When the biller presses Submit, the form sends the bill through POST /bills with draft: { id, revision }. MindBill reserves the draft, creates the bill, and marks the draft submitted with submittedBillId. If no bill is created, the draft is released so the biller can fix it and try again. A submitted draft cannot be edited, and opening one shows that it was already submitted.
TreatmentVisitBill.tsx
"use client";import { ConnectedTreatmentBillForm } from "@mindbill/react";export function TreatmentVisitBill({ visit, ids }: { visit: Visit; ids: SavedIds }) { return <ConnectedTreatmentBillForm sessionEndpoint="/api/mindbill/treatment-session" // bills:read + bills:create initialBill={visit.bill} encounter={{ renderingProviderId: ids.renderingProviderId, placeOfServiceId: ids.locationId, claimId: ids.claimId }} drafts // shows "Save draft" draftId={visit.mindbillDraftId} // omit for a new bill; set to resume a saved one draftExternalId={`visit_${visit.id}`} // optional: your reference for a new draft onDraftSaved={(draft) => saveVisitDraftId(visit.id, draft.id)} onDraftError={() => clearVisitDraftId(visit.id)} // the saved draft could not be opened onSubmitted={(result) => openBill(result.billId)} />;}
Prop
Purpose
drafts
Show Save draft. The session needs bills:create.
draftId
Resume this saved draft; submitting it marks the draft submitted.
draftExternalId
Your reference for a new draft, unique per organization. Reusing one returns external_id_owned.
onDraftSaved(draft)
Called after each save. Store draft.id with your visit to resume later.
onDraftError(error)
Called when draftId cannot be loaded, for example after it was deleted.
Using your own BillSubmissionForm? It accepts onSaveDraft(bill) (a secondary button that skips validation), saveDraftLabel, and draft: { id, revision }, which it forwards on submission. Call the drafts client yourself:
Server integrations use the same routes: list, save, read, replace, and delete. Writes need an Idempotency-Key; reads need bills:read and writes bills:write (browser bills:create).
Save, then submit a draft
# Save (201) — later saves PATCH with the current revisioncurl https://app.mindbill.org/partner/v2/bill-drafts \ --request POST \ --header "Authorization: Bearer $MINDBILL_API_KEY" \ --header "Idempotency-Key: visit_example-draft" \ --header "Content-Type: application/json" \ --data '{"externalId":"visit_example","bill":{"billingMode":"professional","claim":{"id":"clm_example"},"serviceLines":[{"code":"99213","units":1,"charge":150}]},"encounter":{"renderingProviderId":"rp_example","placeOfServiceId":"loc_example"}}'# Submit the completed bill through the normal create-bill requestcurl https://app.mindbill.org/partner/v2/bills \ --request POST \ --header "Authorization: Bearer $MINDBILL_API_KEY" \ --header "Idempotency-Key: visit_example-submit" \ --header "Content-Type: application/json" \ --data '{"bill": { …the complete bill… }, "draft": {"id":"billdraft_example","revision":2}}'
Price a visit from your own UI
Call POST /fee-quotes/encounter from your server or with a browser session. Amounts are integer cents. A quote creates and changes nothing.
server/quote-visit.ts
const response = await fetch("https://app.mindbill.org/partner/v2/fee-quotes/encounter", { method: "POST", headers: { Authorization: `Bearer ${process.env.MINDBILL_API_KEY}`, "Content-Type": "application/json" }, body: JSON.stringify({ claimId: "clm_example", renderingProviderId: "rp_example", placeOfServiceId: "loc_example", dateOfService: "2026-09-18", lines: [ { id: "line-1", code: "99213", units: 1, modifiers: ["25"], chargeCents: 18000 }, { id: "line-2", code: "97110", units: 2, chargeCents: 12000 }, ], }),});const { data } = await response.json();for (const line of data.lines) { // Only priced lines have an expected amount. Never substitute the charge. const expected = line.assessment === "priced" ? (line.paymentAdjustment?.amountCents ?? line.quote.amountCents) : null; render(line.id, expected, line.displayNotes);}renderVisitNotes(data.visitNotes); // shown once for the visit
To keep your own BillSubmissionForm layout, pass an encounter quoter instead:
encounter-pricing.ts
import { createBillReferenceClient, createEncounterQuoter, encounterQuoteRequest } from "@mindbill/browser";const client = createBillReferenceClient({ sessionEndpoint: "/api/mindbill/treatment-session" });// Pass to your own <BillSubmissionForm onQuoteEncounter={...} />const onQuoteEncounter = createEncounterQuoter(client, { renderingProviderId, placeOfServiceId, claimId });// Or call it directly:const estimate = await client.quoteEncounter(encounterQuoteRequest(lines, { renderingProviderId, placeOfServiceId }));
Run the full RFA workflow
RfaDashboard embeds the complete workflow: search and filter requests, create a request on the official DWC Form RFA, attach clinical PDFs, preview the form, sign, review the exact packet, send by fax or email, and then record receipt, information requests, and UR decisions per treatment. Its task board covers no-response follow-up, matching incoming responses, and posting decisions.
Authorizations.tsx
"use client";import { RfaDashboard } from "@mindbill/react";export function Authorizations({ user, claimId }: { user: SignedInUser; claimId?: string }) { return <RfaDashboard sessionEndpoint="/api/mindbill/treatment-session" officialForm // DWC Form RFA field order and labels layout="simple" // All RFAs list + bill-style request detail claimId={claimId} // optional: restrict to one claim actorReference={user.id} // the authenticated human who signs or sends permissions={user.rfaControls} // e.g. ["create", "edit", "sign", "send", "act"] environment="sandbox" // "live" only for approved organizations />;}
officialForm lays out creation in DWC Form RFA order (request type, Employee, Requesting Physician, Claims Administrator, Requested Treatment) with the official labels. Values that come from saved records are read-only.
layout="simple" opens on the searchable All RFAs list and shows each request like a bill detail page: a milestone status card, RFA details, documents, review and send (or utilization review after delivery), history, and a sticky next-action bar.
Built-in defaults from React 0.78.0: when you do not supply your own handlers, form and draft previews open in the built-in PDF viewer (previewForm, previewDraft), UR responses are read with readResponse to prefill decisions for the user to confirm, and treatment templates load and save through the API (listTemplates, saveTemplate). Host props such as formPreviewUrl and onPreviewRequest still take precedence.
Nothing is signed or sent on render. Signing and delivery each need explicit confirmation by an authorized user, and permissions only controls which buttons appear; the server enforces access.
For a custom interface, createRfaClient() exposes the same operations, including previewForm(rfaId, { packet: true }), previewDraft(draft), readResponse(rfaId, documentId), listTemplates(), saveTemplate(input), and exportCsv(filters). The RFA guide covers drafts, signing, delivery evidence, review clocks, and corrections in detail.
Show authorizations on claim, RFA, and bill pages
Three components connect authorization records to the rest of your application. Each accepts the same session options, or a host loader if your backend serves the data.
RfaClaimIndex: every RFA on a claim
Treatment counts (Incomplete, No response, Approved, Modified, Denied), an RFAs tab and a Requested treatments tab, sortable columns, and an Add RFA action. Unsent requests count once as Incomplete; a treatment closed as no longer needed shows "Not required".
RfaClaimIndex, RFAs tab (synthetic claim).Requested treatments tab: one row per treatment with code, decision, and authorization number.
RfaClaimIndexMocked RFA list · synthetic claim
import{RfaClaimIndex}from"@mindbill/react";constitem = (id,service,code,outcome,extra = {})=>({id,diagnosisCode:"M54.50",serviceDescription:service,procedureCode:code,frequency:"2x/week",duration:"4 weeks",outcome,quantity:8,units:null,authorizationNumber:outcome === "approved" || outcome === "modified" ? "DEMO-AUTH-" + id : null,decisionReason:null,decidedAt:outcome === "pending" ? null : "2026-09-10T17:00:00Z",...extra,});constrfa = (id,status,lifecycleStatus,provider,created,submitted,items,extra = {})=>({id,status,lifecycleStatus,renderingProviderId:"rp_" + provider.length,providerName:provider,expedited:false,requestType:"initial",contentRevision:1,claimId:"claim_demo",patientId:"patient_demo",claimsAdminId:null,employeeName:"Alex Morgan",claimNumber:"WC-44871",reviewType:"prospective",createdAt:created,updatedAt:created,signedAt:submitted,submittedAt:submitted,receivedAt:null,decisionDueAt:submitted ? "2026-09-20T00:00:00Z" : null,decisionDeadlineBasis:null,incompleteReason:null,deferredReason:null,closedReason:null,readiness:{ready:true,missing:[]},items,documents:[],...extra,});constrfas = [rfa("rfa_5f2c91aa01","approved","closed","Morgan Chen, MD","2026-08-20T10:00:00Z","2026-08-21T10:00:00Z",[item("a1","Physical therapy, lumbar spine","97110","approved"),item("a2","Lumbar MRI without contrast","72148","denied"),]),rfa("rfa_7b13e0cc02","submitted","sent","Riley Park, DO","2026-09-12T10:00:00Z","2026-09-13T10:00:00Z",[item("b1","Chiropractic manipulative treatment, spinal, 3-4 regions","98941","pending"),],{expedited:true}),rfa("rfa_9d44a1ee03","draft","incomplete","Morgan Chen, MD","2026-09-15T10:00:00Z",null,[item("c1","Acupuncture, 1 or more needles","97810","pending"),]),];constrelated = {claimId:"claim_demo",hasMore:false,data:[{id:"bill_1042",label:"Bill #1042",treatments:["Physical therapy, lumbar spine"],relationship:"Linked authorization",status:"submitted",serviceDate:"2026-09-12"},{id:"bill_1031",label:"Bill #1031",treatments:["Office visit, established patient"],relationship:"Same injury",status:"paid",serviceDate:"2026-08-30"},]};constdecisions = {editable:true,linked:[{rfaId:"rfa_5f2c91aa01",rfaItemId:"a1",service:"Physical therapy, lumbar spine",form:{state:"attached"},decision:{state:"attached",authorizationNumber:"DEMO-AUTH-a1"}},],decisions:[{documentId:"doc_1",rfaId:"rfa_5f2c91aa01",filename:"ur-decision.pdf",decidedAt:"2026-09-10T17:00:00Z",attached:false,matchesBill:true,treatments:[{service:"Physical therapy, lumbar spine",code:"97110",outcome:"approved",authorizationNumber:"DEMO-AUTH-a1",effectiveFrom:"2026-09-10",effectiveTo:"2026-10-10"},{service:"Lumbar MRI without contrast",code:"72148",outcome:"denied",authorizationNumber:null,effectiveFrom:null,effectiveTo:null},]},{documentId:"doc_2",rfaId:"rfa_7b13e0cc02",filename:"ur-decision-2.pdf",decidedAt:null,attached:true,matchesBill:false,treatments:[{service:"Office visit",code:"99213",outcome:"modified",authorizationNumber:"DEMO-AUTH-x",effectiveFrom:"2026-09-01",effectiveTo:"2026-09-30"},]},]};// Mock of the partner API routes these components call through a browser session.asyncfunctionmockApi(input,init = {}){constpath = new URL(String(input),location.href).pathname;if((init.method || "GET") !== "GET")returnResponse.json({data:{attached:1}});if(path.endsWith("/rfas/related"))returnResponse.json(related);if(path.endsWith("/ur-decisions"))returnResponse.json({data:decisions});if(path.endsWith("/rfas"))returnResponse.json({data:rfas,nextCursor:null,summary:{total:rfas.length,byStatus:{}}});returnResponse.json({error:{message:"Not in this demo: " + path}},{status:404});}constsession = {getSession:async()=>({token:"demo_session"}),fetch:mockApi,appearance:{preset:"mindbill"}};exportdefaultfunctionApp(){return<mainclassName="review-demo"><RfaClaimIndex{...session}claimId="claim_demo"canCreateonCreateRfa={()=>alert("Open your RFA creation page")}onSelectRfa={(rfaId)=>alert("Open " + rfaId)}/></main>;}
RelatedAuthorizationRecords: bills and RFAs on the same claim
On an RFA page (rfaId) it lists bills; on a bill page (billId) it lists RFAs. Records where a bill line uses one of the request's approved treatments ("Linked authorization") come first; other records for the injury are folded below.
RelatedAuthorizationRecords on an RFA page.
RelatedAuthorizationRecordsMocked related records · synthetic claim
import{RelatedAuthorizationRecords}from"@mindbill/react";constitem = (id,service,code,outcome,extra = {})=>({id,diagnosisCode:"M54.50",serviceDescription:service,procedureCode:code,frequency:"2x/week",duration:"4 weeks",outcome,quantity:8,units:null,authorizationNumber:outcome === "approved" || outcome === "modified" ? "DEMO-AUTH-" + id : null,decisionReason:null,decidedAt:outcome === "pending" ? null : "2026-09-10T17:00:00Z",...extra,});constrfa = (id,status,lifecycleStatus,provider,created,submitted,items,extra = {})=>({id,status,lifecycleStatus,renderingProviderId:"rp_" + provider.length,providerName:provider,expedited:false,requestType:"initial",contentRevision:1,claimId:"claim_demo",patientId:"patient_demo",claimsAdminId:null,employeeName:"Alex Morgan",claimNumber:"WC-44871",reviewType:"prospective",createdAt:created,updatedAt:created,signedAt:submitted,submittedAt:submitted,receivedAt:null,decisionDueAt:submitted ? "2026-09-20T00:00:00Z" : null,decisionDeadlineBasis:null,incompleteReason:null,deferredReason:null,closedReason:null,readiness:{ready:true,missing:[]},items,documents:[],...extra,});constrfas = [rfa("rfa_5f2c91aa01","approved","closed","Morgan Chen, MD","2026-08-20T10:00:00Z","2026-08-21T10:00:00Z",[item("a1","Physical therapy, lumbar spine","97110","approved"),item("a2","Lumbar MRI without contrast","72148","denied"),]),rfa("rfa_7b13e0cc02","submitted","sent","Riley Park, DO","2026-09-12T10:00:00Z","2026-09-13T10:00:00Z",[item("b1","Chiropractic manipulative treatment, spinal, 3-4 regions","98941","pending"),],{expedited:true}),rfa("rfa_9d44a1ee03","draft","incomplete","Morgan Chen, MD","2026-09-15T10:00:00Z",null,[item("c1","Acupuncture, 1 or more needles","97810","pending"),]),];constrelated = {claimId:"claim_demo",hasMore:false,data:[{id:"bill_1042",label:"Bill #1042",treatments:["Physical therapy, lumbar spine"],relationship:"Linked authorization",status:"submitted",serviceDate:"2026-09-12"},{id:"bill_1031",label:"Bill #1031",treatments:["Office visit, established patient"],relationship:"Same injury",status:"paid",serviceDate:"2026-08-30"},]};constdecisions = {editable:true,linked:[{rfaId:"rfa_5f2c91aa01",rfaItemId:"a1",service:"Physical therapy, lumbar spine",form:{state:"attached"},decision:{state:"attached",authorizationNumber:"DEMO-AUTH-a1"}},],decisions:[{documentId:"doc_1",rfaId:"rfa_5f2c91aa01",filename:"ur-decision.pdf",decidedAt:"2026-09-10T17:00:00Z",attached:false,matchesBill:true,treatments:[{service:"Physical therapy, lumbar spine",code:"97110",outcome:"approved",authorizationNumber:"DEMO-AUTH-a1",effectiveFrom:"2026-09-10",effectiveTo:"2026-10-10"},{service:"Lumbar MRI without contrast",code:"72148",outcome:"denied",authorizationNumber:null,effectiveFrom:null,effectiveTo:null},]},{documentId:"doc_2",rfaId:"rfa_7b13e0cc02",filename:"ur-decision-2.pdf",decidedAt:null,attached:true,matchesBill:false,treatments:[{service:"Office visit",code:"99213",outcome:"modified",authorizationNumber:"DEMO-AUTH-x",effectiveFrom:"2026-09-01",effectiveTo:"2026-09-30"},]},]};// Mock of the partner API routes these components call through a browser session.asyncfunctionmockApi(input,init = {}){constpath = new URL(String(input),location.href).pathname;if((init.method || "GET") !== "GET")returnResponse.json({data:{attached:1}});if(path.endsWith("/rfas/related"))returnResponse.json(related);if(path.endsWith("/ur-decisions"))returnResponse.json({data:decisions});if(path.endsWith("/rfas"))returnResponse.json({data:rfas,nextCursor:null,summary:{total:rfas.length,byStatus:{}}});returnResponse.json({error:{message:"Not in this demo: " + path}},{status:404});}constsession = {getSession:async()=>({token:"demo_session"}),fetch:mockApi,appearance:{preset:"mindbill"}};exportdefaultfunctionApp(){return<mainclassName="review-demo"><RelatedAuthorizationRecords{...session}rfaId="rfa_5f2c91aa01"onSelectBill={(billId)=>alert("Open " + billId)}getClaimHref={(claimId)=>"#" + claimId}/></main>;}
Shows the signed RFA and UR decision for each authorization linked to a service line, then every other UR decision on the bill's patient and claim. While the bill is unsent and canEdit is set, a biller can attach selected decision letters or retry the linked attachments. Attaching copies documents onto the bill; nothing is sent.
BillUrDecisions on an unsent treatment bill.
BillUrDecisionsMocked UR decisions · nothing is sent
import{useState}from"react";import{BillUrDecisions}from"@mindbill/react";constitem = (id,service,code,outcome,extra = {})=>({id,diagnosisCode:"M54.50",serviceDescription:service,procedureCode:code,frequency:"2x/week",duration:"4 weeks",outcome,quantity:8,units:null,authorizationNumber:outcome === "approved" || outcome === "modified" ? "DEMO-AUTH-" + id : null,decisionReason:null,decidedAt:outcome === "pending" ? null : "2026-09-10T17:00:00Z",...extra,});constrfa = (id,status,lifecycleStatus,provider,created,submitted,items,extra = {})=>({id,status,lifecycleStatus,renderingProviderId:"rp_" + provider.length,providerName:provider,expedited:false,requestType:"initial",contentRevision:1,claimId:"claim_demo",patientId:"patient_demo",claimsAdminId:null,employeeName:"Alex Morgan",claimNumber:"WC-44871",reviewType:"prospective",createdAt:created,updatedAt:created,signedAt:submitted,submittedAt:submitted,receivedAt:null,decisionDueAt:submitted ? "2026-09-20T00:00:00Z" : null,decisionDeadlineBasis:null,incompleteReason:null,deferredReason:null,closedReason:null,readiness:{ready:true,missing:[]},items,documents:[],...extra,});constrfas = [rfa("rfa_5f2c91aa01","approved","closed","Morgan Chen, MD","2026-08-20T10:00:00Z","2026-08-21T10:00:00Z",[item("a1","Physical therapy, lumbar spine","97110","approved"),item("a2","Lumbar MRI without contrast","72148","denied"),]),rfa("rfa_7b13e0cc02","submitted","sent","Riley Park, DO","2026-09-12T10:00:00Z","2026-09-13T10:00:00Z",[item("b1","Chiropractic manipulative treatment, spinal, 3-4 regions","98941","pending"),],{expedited:true}),rfa("rfa_9d44a1ee03","draft","incomplete","Morgan Chen, MD","2026-09-15T10:00:00Z",null,[item("c1","Acupuncture, 1 or more needles","97810","pending"),]),];constrelated = {claimId:"claim_demo",hasMore:false,data:[{id:"bill_1042",label:"Bill #1042",treatments:["Physical therapy, lumbar spine"],relationship:"Linked authorization",status:"submitted",serviceDate:"2026-09-12"},{id:"bill_1031",label:"Bill #1031",treatments:["Office visit, established patient"],relationship:"Same injury",status:"paid",serviceDate:"2026-08-30"},]};constdecisions = {editable:true,linked:[{rfaId:"rfa_5f2c91aa01",rfaItemId:"a1",service:"Physical therapy, lumbar spine",form:{state:"attached"},decision:{state:"attached",authorizationNumber:"DEMO-AUTH-a1"}},],decisions:[{documentId:"doc_1",rfaId:"rfa_5f2c91aa01",filename:"ur-decision.pdf",decidedAt:"2026-09-10T17:00:00Z",attached:false,matchesBill:true,treatments:[{service:"Physical therapy, lumbar spine",code:"97110",outcome:"approved",authorizationNumber:"DEMO-AUTH-a1",effectiveFrom:"2026-09-10",effectiveTo:"2026-10-10"},{service:"Lumbar MRI without contrast",code:"72148",outcome:"denied",authorizationNumber:null,effectiveFrom:null,effectiveTo:null},]},{documentId:"doc_2",rfaId:"rfa_7b13e0cc02",filename:"ur-decision-2.pdf",decidedAt:null,attached:true,matchesBill:false,treatments:[{service:"Office visit",code:"99213",outcome:"modified",authorizationNumber:"DEMO-AUTH-x",effectiveFrom:"2026-09-01",effectiveTo:"2026-09-30"},]},]};// Mock of the partner API routes these components call through a browser session.asyncfunctionmockApi(input,init = {}){constpath = new URL(String(input),location.href).pathname;if((init.method || "GET") !== "GET")returnResponse.json({data:{attached:1}});if(path.endsWith("/rfas/related"))returnResponse.json(related);if(path.endsWith("/ur-decisions"))returnResponse.json({data:decisions});if(path.endsWith("/rfas"))returnResponse.json({data:rfas,nextCursor:null,summary:{total:rfas.length,byStatus:{}}});returnResponse.json({error:{message:"Not in this demo: " + path}},{status:404});}constsession = {getSession:async()=>({token:"demo_session"}),fetch:mockApi,appearance:{preset:"mindbill"}};exportdefaultfunctionApp(){const[message,setMessage] = useState("Select a decision letter to attach to this unsent bill.");return<mainclassName="review-demo"><pclassName="notice">{message}</p><BillUrDecisions{...session}billId="bill_1042"canEditopenDocument={(decision)=>setMessage("Preview " + decision.filename)}onSelectRfa={(rfaId)=>setMessage("Open " + rfaId)}onAttached={(result)=>setMessage("Attached " + result.attached + " document. Nothing was sent.")}/></main>;}
"use client";import { BillUrDecisions, RelatedAuthorizationRecords, RfaClaimIndex } from "@mindbill/react";const session = { sessionEndpoint: "/api/mindbill/treatment-session" };// Claim page: every RFA on the claim, by request or by requested treatment.<RfaClaimIndex {...session} claimId={claimId} canCreate createHref={`/rfas/new?claimId=${claimId}`} getRfaHref={(rfaId) => `/rfas/${rfaId}`} />// RFA page: bills that use this authorization, then other bills for the injury.<RelatedAuthorizationRecords {...session} rfaId={rfaId} getBillHref={(billId) => `/bills/${billId}`} />// Bill page: signed RFAs and UR decisions; attach letters while the bill is unsent.<BillUrDecisions {...session} billId={billId} canEdit={bill.unsent} getRfaHref={(rfaId) => `/rfas/${rfaId}`} onAttached={() => refreshDocuments()} />