mdvin User Manual

User Manual

mdvin

The complete guide to the platform: what it is, how each role uses it, how the two modules connect, and the full API surface. Including the guards the server enforces no matter what any client sends.

Getting started#

mdvin is a US healthcare orchestration platform that runs Prior Authorization (PA) and Value-Based Care (VBC) on one decision spine. Instead of two disconnected products, a single patient record, workflow engine, versioned policy library and append-only audit trail sit underneath both modules, so an authorization is a step inside a care journey, a care gap knows when it is blocked on a payer decision, and every state change either side makes is visible to the other in real time.

The platform is API-first: every screen you see is a projection of server-side state, and every rule — who may act, which transitions are legal, what a denial requires. Is enforced on the server, never in the browser. That design has a practical consequence for you as a user: if the UI lets you press a button that the rules forbid, the server refuses and tells you why. Several parts of this manual invite you to try exactly that, because watching the platform refuse an illegal action is the fastest way to understand how it protects the people in it.

The demo environment#

Demo environment, all data is synthetic; no PHI. Every patient, member ID, payer, policy and clinical value in this environment is fictional and generated for demonstration. Nothing you do here touches real health information. Security controls (authentication, role gating, audit chaining, tenant isolation) run exactly as they would in production, they are being demonstrated, not simulated.

Signing in#

  1. Open /app. You will see the sign-in screen with the synthetic-data demo banner and the platform points (CMS-0057-F-aligned SLA clocks, Governed AI, Defensible by design).
    What you should seeAn email + password form, and a click-to-fill panel listing the five demo roles.
  2. Enter one of the credential pairs from the table below and press Sign in.
    What you should seeThe app shell loads with a left navigation tailored to your role — a Care Manager lands on My Work; a UM Nurse or Medical Director lands directly on the Review Queue.
  3. Sessions use short-lived JWT access tokens (15 minutes) with a refresh token behind them. If a request returns 401 after a long idle period, sign in again.
Account lockout is real. Five failed password attempts lock the account for 15 minutes and further sign-ins return 423 Account temporarily locked. The login response is deliberately generic (Invalid credentials) so the system never reveals whether an email exists.

Demo credentials#

Five seeded users cover the whole demo. Passwords are published intentionally, this is a synthetic environment.

RoleEmailPasswordWhat this role demonstrates
Care Manager
Jane Smith
jane@demo.acoCareManager!2026x My Work queue, interventions, engagement, launching PAs
VBC Manager
Alex Rivera
alex@demo.acoVbcManager!2026xx Dashboard aggregates, population views
UM Nurse (RN)
Sam Nurse
nurse@demo.payerUmNurse!2026xxxx PA review queue, AI advisory, pend/approve. Attempt a denial and the server will refuse it (an RN cannot deny)
Medical Director
Dr. A. Patel — MD, Ophthalmology
md@demo.payerMedDirector!2026 Adverse determinations with credential + specific reason
Medical Director 2
Dr. B. Rivera — MD, Ophthalmology
md2@demo.payerMedDirector2!26x Independent appeal reviews (the original denier cannot decide an appeal)
Auditor
Avery Auditor
audit@demo.acoAuditor!2026xxxx Read-only decision traces
Platform Admin (backend)
Pat Admin
admin@demo.acoPlatformAdmin!26 Backend administration at https://mdvin.com/app → Administration: runtime branding (rename the product), field registry (add/remove/rename/hide fields per entity, patient, care gap, intervention, prior auth, task). All changes audited and applied platform-wide instantly.

Your first session, by role#

  • Care Manager (jane@demo.aco), start in My Work: one Critical task is waiting (post-ED follow-up for John Doe). Open his 360, then follow the VBC guide end-to-end on Sarah Martinez's retinal-exam gap. It is the one that requires a PA, so you will see both modules cooperate.
  • VBC Manager (alex@demo.aco), start on the Dashboard: every KPI is computed live from the same rows its drill-down shows, so numbers always reconcile. Then browse Patients and open a 360.
  • UM Nurse (nurse@demo.payer), open the Review Queue. If it is empty, have the Care Manager submit a PA first (how). Run the AI advisory, approve or pend, then press Deny and read the server's refusal. That refusal is the product's compliance story in one screen.
  • Medical Director (md@demo.payer). Open the same queue and complete an adverse determination properly: 5-state criterion outcomes, a specific reason code and text, your MD credential recorded on the trace.
  • Auditor (audit@demo.aco), open Authorizations and view any PA's decision trace. Note what you cannot do: no review/decide buttons appear, and any write you attempt (say, Start Intervention on an open gap) is refused by the server with 403. Read-only is enforced server-side, not by the UI.

Core concepts#

Six ideas explain the whole platform. Everything in the role guides below is a combination of these.

Patient 360#

The Patient 360 is the single clinical workspace for one member: identity and coverage, the risk tier (HIGH / RISING / MEDIUM / LOW) with the evidence behind it, all open and closed care gaps, and every intervention with its full event timeline. Risk is never a bare score. Each contributing factor carries its source and date (e.g. HbA1c 9.4% · lab · 2026-06-14), and the risk model version (apex-risk v3.2 in the demo) is displayed with it, so the number is explainable and reproducible.

Care gaps & their states#

A care gap is a measurable difference between recommended and delivered care, tied to a versioned quality measure (e.g. CDC-HBA1C, measure package MY2026.1). Every gap answers two questions on its face: why is it open (the evidence that opened it) and what closes it (the clinical evidence the measure requires). A gap moves through these states:

StateMeaning
CANDIDATEMeasure engine has flagged the member; not yet confirmed into the work stream
OPENConfirmed gap, no active work, this is where Start Intervention appears
IN_PROGRESSAn intervention is actively working the gap
SCHEDULEDThe closing service has an appointment on the books
AWAITING_AUTHBlocked on a pending prior authorization, the cross-module wait state
SATISFIEDMeasure numerator met per the engine; pending confirmation into CLOSED
CLOSEDClosed on qualifying clinical evidence, the only way a gap closes
EXCLUDEDMember meets a measure exclusion; gap leaves the denominator
NOT_APPLICABLEMeasure does not apply to this member
REOPENEDEvidence lapsed or was invalidated; the gap is live again
PA approval never closes a gap. An approved authorization changes what is allowed, not what was done. Only clinical completion evidence that matches the measure (see auto-closure) moves a gap to CLOSED.

Intervention lifecycle#

An intervention is the unit of care-team work on one gap: who owns it, what has happened, what comes next. Its state machine is enforced server-side. Any transition not in this diagram returns 409 Illegal intervention transition.

Teal = the states involved in the cross-module handshake. Dark = terminal success. Red = exception outcomes.

Prior Authorization lifecycle#

A PA request has eleven states. In the demo environment intake validation passes synchronously, so a successful submission lands directly in IN_REVIEW with its SLA clock already running.

Rule & policy packages#

Coverage rules are data, not code. A rule package (e.g. UHC-MA-EYE-014) is versioned and effective-dated, keyed by payer + line of business + service codes, and carries the criteria themselves — each with an ID, plain-language text and the evidence type that satisfies it. The policy resolver picks the newest active version matching the member's coverage and the requested CPT. When a PA is created, the package key and version are snapshotted onto the request, so the decision is always judged. And can always be replayed. Against the exact criteria in force at submission, even after the package is updated.

The audit trail#

Every consequential action. Sign-ins and failures, every patient view, every transition, every decision — appends an event to a hash-chained, append-only audit log: each row carries the hash of the previous row, so any tampering breaks the chain, and an integrity self-check can recompute it end-to-end at any time. Events record the actor, role, object, patient, structured detail (criteria version, credential, denial code…) and a correlation ID that ties one user action to every row it produced. The current correlation ID is shown in the app's top bar. Quote it when reporting an issue and the operator can reconstruct your exact request.

Roles & permissions#

Ten roles are defined. A role is a fixed set of permissions checked on every API call, the UI merely hides what you cannot do; the server is what refuses. The five demo users cover the roles marked below; the others exist in the model for production deployments.

Permission matrix#

Role patient.readvbc.writevbc.admin task.readanalytics.read pa.createpa.readpa.review pa.pendpa.decide policy.readpolicy.write audit.readadmin.all
care_manager YesYesYesYesYes
vbc_manager YesYesYesYesYesYes
executiveYesYes
providerYesYesYesYes
pa_coordinatorYesYesYes
um_nurse YesYesYes
medical_director YesYesYesYes
policy_adminYesYes
platform_adminYesYes
auditor YesYesYes

= has a seeded demo user. admin.all satisfies any permission check — platform_admin effectively holds every permission. Note that medical_director is the only role holding pa.decide, and only care_manager, provider and pa_coordinator can create PAs.

The credential rule#

Adverse determinations require role + credential + reason. A denial only succeeds when all three hold: the actor's role grants pa.decide (medical_director only), the actor's stored credential is a physician credential (MD:…, the demo Medical Director is MD:Ophthalmology), and the request carries a specific denial reason code and text. Missing role or credential → 403; missing reason → 422. An AI advisory row can never produce a denial. The advisory endpoint is physically unable to change state. This guard is designed to align with California SB 1120 ("Physicians Make Decisions Act") and the physician-review norm reflected in the NAIC AI model bulletin now adopted in roughly 25 states.

Tenant isolation is equally absolute: every query filters by the tenant in your token. An object in another tenant returns 404, the platform never reveals whether it exists.

VBC guide, care manager & VBC manager walkthroughs#

Sign in as jane@demo.aco (Care Manager) or alex@demo.aco (VBC Manager) to follow along.

The Dashboard

  1. Open Dashboard in the left navigation.
    What you should seeKPI tiles — Patients, High Risk, Open Care Gaps, Active Interventions, Open Tasks. Computed live from the same rows their drill-downs show. Change anything anywhere in the app and the numbers move with it; they are never hardcoded.

The Patients list

  1. Open Patients.
    What you should seeThe tenant-scoped roster, in the demo, John Doe and Sarah Martinez, both HIGH risk, with member ID, PCP and program. A note reminds you that every view is audited with your identity and a correlation ID. That is literally true; check the audit trail as the Auditor later.

Patient 360 & risk evidence

  1. Click a patient row to open their 360.
    What you should seeThree panels: the header with DOB, member ID and risk badge; a "Risk, why?" box listing each factor with source and date (for John Doe: HbA1c 9.4% · lab, ED visit · adt, Missed follow-up · scheduling) plus the model version apex-risk v3.2; then Care Gaps and Interventions.
  2. Read a gap's row: measure key and version, status, priority, and the why-open narrative (Sarah: "No retinal exam in 24 months; HbA1c 10.1%."). Every gap justifies itself.

Starting an intervention (with automatic PA check)

  1. On an OPEN gap, click Start Intervention.
  2. Before creating anything, the platform silently runs a PA requirement check for the gap's service code against the member's active coverage (a CRD-style discovery call, see the PA guide).
    What you should seeFor Sarah's retinal exam (CPT 92250) the toast reads "Intervention created — PA REQUIRED under UHC-MA-EYE-014 v3". For a service with no matching policy the toast reads "no PA required (policy trace logged)". The check itself is audited either way.
  3. The intervention appears in the Interventions panel in state IDENTIFIED, its first timeline event reading "created, context inherited from care gap". The gap moves to IN_PROGRESS.
  4. Try clicking Start Intervention again for the same gap: the server answers 409 Active intervention exists. One gap, one active intervention, duplicates are blocked at the API.

Outreach → engaged → schedule

  1. On the IDENTIFIED intervention, click Begin outreach → state becomes OUTREACH.
  2. Click Patient respondedENGAGED. Every click appends a timestamped event to the timeline.
  3. Click ScheduleSCHEDULEDunless a linked PA is still pending. If you launched a PA that has not been decided, the server refuses with 409 Scheduling gated: PA-2026-xxxxx is IN_REVIEW.
    What you should seeWhile the PA is pending the intervention sits in AWAITING_AUTH with a stopwatch chip ("awaiting payer decision") and no schedule button at all. The moment the PA is approved, the intervention flips to AUTH_APPROVED automatically and the button returns as Schedule (auth on file).

Recording completion evidence & auto-closure

  1. On a SCHEDULED intervention, click Record completion evidence. This simulates the EHR/claims completion feed a production deployment receives automatically.
  2. Choose the evidence type — lab, encounter or procedure, and enter the CPT observed (e.g. 83036 for the HbA1c gap, 92250 for the retinal exam), then Send event.
  3. The closure rule is deterministic: the evidence type must be clinical and the CPT (or measure key) must match the gap's measure.
    What you should seeOn a match: "Care gap closed automatically; evidence recorded", the intervention passes through COMPLETED to GAP_CLOSED and the gap becomes CLOSED. On a mismatch: "Evidence insufficient, gap stays IN_PROGRESS (logged)" and an audit event records exactly what was offered and rejected.
  4. Try sending mismatched evidence on purpose (wrong CPT). The gap does not close, and notice that an approved PA never closed it either. Approval changes permission, evidence changes state.

My Work

  1. Open My Work.
    What you should seeA prioritized queue where every task answers two questions in its own columns: why am I seeing this (e.g. "Post-ED follow-up + HbA1c gap (ED 08/02, HbA1c 9.4)") and what should I do ("Start Intervention"), with priority and due date. An Open 360 button jumps straight to the patient.

Prior Authorization guide#

Submission side: sign in as jane@demo.aco. Review side: nurse@demo.payer, then md@demo.payer.

The requirement check

Before any request is drafted, POST /pa/requirement-check answers the question providers ask first: does this service need prior authorization under this member's plan? The resolver matches the member's active coverage (payer + line of business) and the CPT code against the versioned policy library and returns a three-valued answer: yes, no, or unknown when no policy matches — unknown is never collapsed into "no". The response names the governing package and version (UHC-MA-EYE-014 v3 for Sarah's retinal exam) and lists the documentation types its criteria demand, and the whole lookup is written to the audit trail. In the UI this runs automatically when you start an intervention; the pattern mirrors Da Vinci CRD (Coverage Requirements Discovery).

Launching a PA from an intervention

  1. On an intervention in IDENTIFIED, click Launch PA.
    What you should seeA form with the member line read-only and the service CPT pre-filled from the care gap — context is inherited, not re-typed. You supply the ICD-10 diagnosis and choose urgency: Standard — 7-day SLA or Expedited — 72h SLA.
  2. Click Submit PA. The request is created with an idempotency key, so a double-click or a network retry returns the same PA instead of creating a duplicate.
    What you should seeA toast with the new reference and its deadline: "PA-2026-xxxxx submitted — SLA due …". The linked intervention parks in AWAITING_AUTH and the gap shows AWAITING_AUTH too.
  3. The policy package and version in force are snapshotted onto the request, and the submission passes intake validation into IN_REVIEW with the decision clock running.

The review queue & SLA clocks

Sign in as the UM Nurse. The Review Queue lists every PA in the tenant, newest first: reference, patient, CPT/ICD-10, status, the SLA due timestamp for anything IN_REVIEW, the policy snapshot and the auth number once issued. Decision deadlines are stamped at submission — 72 hours for expedited requests, 7 calendar days for standard, matching the CMS-0057-F timeframes in force since January 1, 2026. The clock is data on the request itself, so it survives into reporting and the audit trail.

AI advisory, what it does and cannot do

  1. Click Review on an IN_REVIEW PA, then Run criteria analysis in the AI advisory box.
    What you should seeAn advisory panel labeled with the model and version (apex-um v1.8) and the tag "cannot decide", e.g. "Criteria package evaluated: 3/3 MET on available evidence. Approval probability high. Advisory only." The toast confirms: "AI advisory recorded, no state change".
  2. What happened server-side: an advisory row was appended to the decision trace carrying the model version, criteria version and per-criterion outcomes. What cannot happen: the advisory endpoint has no code path that touches PA state. The AI can read, evaluate and recommend. Approving, pending and denying are exclusively human actions, and denial is exclusively a credentialed physician's action.

Approve, pend, and the deny guard

  1. In the review dialog, record the criterion outcomes. Outcomes are 5-stateMET, NOT_MET, UNKNOWN, NOT_APPLICABLE, NEEDS_HUMAN_REVIEW, never collapsed to yes/no.
  2. As the UM Nurse: Pend (needs more information; the PA can re-enter review later) and Approve both succeed, approval issues an auth number valid for 180 days.
  3. Still as the nurse, press Deny.
    What you should seeThe dialog itself warns you: "You are not a physician: the server will refuse a denial regardless of this UI." And it does — 403 Adverse determinations require a medical director. The button exists so you can confirm the server enforces the rule.
  4. Sign in as the Medical Director and deny properly: enter a specific denial reason code and text (e.g. MED-NEC-001 + the clinical rationale). Leave the reason empty and the server answers 422 Denial requires a specific reason code and text. Generic denials are rejected by design, matching the CMS-0057-F specific-denial-reason requirement.
    What you should seeOn a valid denial: PA → DENIED with the reason stored on the request, your MD:Ophthalmology credential recorded on the decision row, and the linked intervention logging a pa.denied event flagging that an appeal or alternative plan is required.

Reading the decision trace

Open any PA's Detail view. Below the service, policy snapshot and auth/denial fields sits the decision trace: one row per review action, in order. Each row shows its kind — ai_advisory (with model version) or human (with the reviewer's credential), the disposition, and the criteria version it was judged against. Together with the hash-chained audit events behind it, the trace makes every decision reproducible: inputs, rule version, evidence outcomes, actor and credential, timestamps. This is the artifact an auditor, an accreditor or opposing counsel would read. And the platform is built so it reads well.

Assistance & readiness#

Two features carry the word "AI" on the screen, and it is worth being precise about what each one is, because the distinction is the reason they are safe to use on a live request.

Neither of them decides anything. The documentation readiness check and Ask mdvin both read your own records, match them against the plan's own criteria, and report what they found. Every statement is computed, and every statement names the record it came from. A language model may be switched on to rephrase a finished sentence, and even then it is handed the conclusion, not the chart.

Documentation readiness#

Roughly a third of pended authorizations are not clinical disagreements. The documentation exists, and nobody attached it. The request goes out incomplete, the payer pends it, and a coordinator spends days chasing a file that was in the chart the whole time.

The readiness check runs before you submit. It resolves the active policy for the service you are requesting and looks for evidence of each criterion in the member's own record. Every criterion lands in one of three states:

StateWhat it meansWhat to do
Evidenced Found in the record, and the panel cites the item, its source and its date, for example HbA1c 10.1% · Lab result · 2026-07-01 Nothing
In the chart, not attached The document exists on the member but is not on this request. This is the case the feature exists to catch Attach it, see below. One click
Not evidenced Nothing in the record satisfies this criterion Obtain the documentation. It is not sitting in the chart
See it in the demo. Open Sarah Martinez, start the Diabetic Retinal Exam intervention and launch the PA. The panel shows three criteria evidenced and one, the ophthalmology referral, sitting unattached in her chart since 2026-07-20.

Attaching what it finds#

Finding the gap is only half the value. What you do next depends on where you are:

  • Before submission there is no request to attach to yet, so the panel offers "Attach this document to the request when I submit", ticked by default. The document is bound as soon as the request is created.
  • On an existing request, in the review screen or through Ask mdvin, each unattached document carries an Attach button that binds it immediately and re-runs the check.

Attaching is recorded as pa.attach_document in the audit trail with the file name and its checksum, because adding evidence to a request is an evidentiary act and the decision trace has to be able to explain it.

The payer sees the same panel on the same request. A UM nurse looking at an incomplete submission sees the documentation sitting in the chart rather than pending it back, which is the point: the pend is avoided instead of issued.

One document, several requests#

A document is not consumed by the request it is attached to. One ophthalmology referral or one HbA1c result routinely supports several requests over a year, and the Documents panel lists every request a file currently evidences. Attaching the same document twice to the same request is refused; attaching it to a second request is normal and expected.

Ask mdvin#

A question box that answers from this tenant's records and shows where each answer came from. It runs as you: it holds no wider view than your role does, and it refuses exactly where the API refuses, naming the permission you are missing rather than pretending the data does not exist.

Every figure it quotes is read from the same service the corresponding screen reads, so the assistant and the interface cannot disagree about a number.

Ask it aboutExampleNeeds
A request's statusWhat is the status of PA-2026-0001?pa.read
What is blocking a requestWhat is blocking my authorizations?pa.read
DeadlinesWhich requests are close to their SLA?pa.read
Why authorization is neededWhy does Sarah Martinez need a prior auth for 92250?pa.read
Open care gapsWhich care gaps are open for John Doe?patient.read
Your queueWhat should I work on next?patient.read
Risk scoringWhat is driving John Doe's risk score?patient.read
RecommendationsWhat do you recommend I do next?patient.read
DischargesWho was discharged recently?patient.read
PopulationHow many members are attributed?patient.read
Quality ratesWhat are our measure rates?analytics.read
CostWhat is our PMPM?analytics.read
Contract positionHow are we tracking against the benchmark?analytics.read
OutcomesWhich outcomes are we actually measuring?analytics.read

Answers arrive with the supporting facts and a deep link to the screen behind them, so nothing has to be taken on trust. Where a claim cannot be substantiated — two of the six outcome claims, for instance — it says so rather than producing a number.

What it will not do#

ControlBehaviour
It cannot widen your permissions The assistant runs as you. Every query filters to your tenant and every question is gated on your own permissions. A UM nurse asking about care gaps is refused, and told which permission is missing, exactly as the API would refuse it
It cannot decide coverage Criteria that are not evidenced are reported UNKNOWN, never not met. Absence of evidence on a request is not evidence that a criterion fails. Adverse determinations remain a licensed physician's act
It cannot invent a clinical fact The matching is deterministic. It reports what it found and where. There is no step in which anything is generated from nothing
Language-model phrasing is optional and off When enabled, a model may only rephrase a finished sentence. It never sees the record, it is refused entirely unless the deployment is marked synthetic-only, and every number in its output must already appear in its input or the rephrasing is discarded and the computed sentence kept. Answers that were rephrased are labelled phrased
Every question is recorded assistant.ask in the audit trail, with the intent and the records read

The golden path, end to end#

This is the sequence that shows both modules cooperating on one journey. Run it with Sarah Martinez's Diabetic Retinal Exam gap. The seeded scenario where the service (CPT 92250) requires prior authorization under UHC-MA-EYE-014 v3.

#ActorActionSystem response
1Care Manager (jane)Patients → open Sarah Martinez's 360 HIGH risk with evidence (HbA1c 10.1% · lab); gap Diabetic Retinal Exam is OPEN
2Care ManagerStart Intervention on the gap Requirement check runs first: PA REQUIRED under UHC-MA-EYE-014 v3. Intervention created IDENTIFIED; gap → IN_PROGRESS; duplicate attempts → 409
3Care ManagerLaunch PA from the intervention; submit (standard urgency) Context inherited (member, CPT 92250); PA created with idempotency key → IN_REVIEW; SLA due stamped (+7 days); intervention parks AWAITING_AUTH; gap AWAITING_AUTH
4Care ManagerAttempt to schedule anyway 409 Scheduling gated: PA-2026-xxxxx is IN_REVIEW, the appointment cannot outrun the authorization
5UM Nurse (nurse)Open Review Queue → Review the PA SLA clock, policy snapshot v3 and criteria context displayed
6UM NurseRun AI criteria analysis Advisory row recorded (apex-um v1.8) — no state change
7UM NursePress Deny 403 Adverse determinations require a medical director, refusal is itself audited
8Medical Director (md)Review → outcomes ALL MET → Approve PA → APPROVED, auth number issued (180-day validity); intervention auto-flips AWAITING_AUTH → AUTH_APPROVED; gap → IN_PROGRESS
9Care ManagerSchedule (auth on file) Gate passes, intervention → SCHEDULED. Note: the gap is still open. Approval ≠ care delivered
10Care ManagerRecord completion evidence: procedure / CPT 92250 Deterministic match → intervention COMPLETEDGAP_CLOSED; gap → CLOSED; toast "Care gap closed automatically; evidence recorded"
11Auditor (audit)Open the PA detail → decision trace Full trace: ai_advisory (model + version) then human approve with MD:Ophthalmology and criteria v3 — every step above also sits in the hash-chained audit log under one correlation ID per action
The alternative ending. At step 8 the Medical Director can instead deny with a specific reason code + text. The PA → DENIED, the intervention logs a pa.denied event calling for an appeal or alternative plan, and the gap stays open, because the patient still hasn't received the care.

The audit trail screen#

Sign in as the Auditor. Audit Trail is the first item in the navigation. Every material action in the platform writes a row here, and the rows are append-only: there is no edit and no delete path anywhere in the application.

Reading the trail, and verifying it#

Filter by action, by object (a PA reference works), or by date range. The action list offers only the actions actually present, so you are choosing from what happened rather than guessing. Each row shows the sequence number, who acted and in what role, the object, the member, the recorded detail, and the row's own hash.

Verify chain recomputes every hash from the beginning. Each row carries the hash of the row before it, so a removed or altered event breaks the sequence and the check reports the exact point where it broke. A clean result reads Chain intact, N events verified. It is a separate button rather than something that runs on every page, because verification rehashes the whole table.

Export writes the current view to CSV for an evidence pack.

Reads are recorded too#

Opening this screen writes an audit.read event recording the filter used and how many rows were returned. Someone trawling a member's history leaves a mark. A log that protects everyone except the people reading it is not an audit log.

Try this. Filter on a PA reference to see that request's whole life in order: submission, the AI advisory with its model version, any document attachments, and the physician's decision with their credential.

Population & intelligence#

Care gaps and risk tiers are computed, not authored. Earlier builds stored a sentence about a clinical fact — "HbA1c 9.4%" — which a reviewer cannot check. The platform now holds the coded, valued, dated fact underneath, and the engines read from it. If a number on screen looks wrong, the fact that produced it is one click away.

The clinical record#

Patient 360 carries labs and vitals (with units, reference ranges and an abnormal flag), the problem list, social drivers of health, medications with adherence, procedures and encounters. Every row names its source and date. Social drivers are stored as observations with Z-codes rather than in a separate store, because they are observations about a member like any other.

Risk scoring#

The risk panel names the engine that produced the tier — currently apex-risk-rules v2 — and lists every contributing factor with its point weight and provenance. It is a deterministic rule engine, not a machine-learning model, and that is a deliberate choice: a tier influences what outreach a member receives, and CA SB 1120, the NAIC AI bulletin and the nH Predict litigation all point the same way — a score that affects care must be explainable and defensible, not merely accurate.

Scores are written to a history table, so the question "which model, which version, on what inputs, when" has an answer for any past decision. The version is bumped whenever a weight changes, so an old score still means what it meant when it was produced.

If no engine has scored a member, the panel says so in those words. It will never display a model version for a model that did not run.

Quality measures#

A measure is versioned, effective-dated data with a denominator, a numerator and exclusions — never logic hidden in code. Evaluation produces one of three outcomes per member: in the denominator and compliant, in the denominator and not (which opens a gap), or excluded. Excluded is not compliant. Confusing those two is the ordinary way a quality rate gets inflated.

Evaluation is idempotent, so it can run after every clinical event without duplicating gaps: a member who becomes compliant has their gap closed with the evidence that closed it.

Measure packages here are synthetic. Real HEDIS and Stars specifications are licensed content, as are CPT value sets. The platform models the shape of a measure — denominator, numerator, exclusions, version — behind an adapter, which is both the BRD's rule and the licensing requirement.

Next best actions#

Ranked recommendations across the population: which member, which action, why them, why now. Ranking combines gap priority, patient risk and whether the action can actually be taken today.

Recommendations are advisory only. Nothing is created, transitioned or sent until a person acts. The engine also will not recommend what the workflow itself would refuse — it never suggests scheduling a service whose authorization is still pending, because the server would reject it.

Attribution, cohorts and enrollment#

Attribution answers "who was ours, for this period" — the denominator under every quality and financial number. Each attributed member records the method used, because when a payer disputes a rate, the method is the argument. Attribution is effective from the start of the performance period, not from the day the roster was loaded.

Cohorts are saved, named population definitions built from a fixed vocabulary — risk tier, condition, programme, open gaps, measure, PCP — and are deliberately not free-form queries.

Programme enrollment is a lifecycle with dates, consent and reasons: eligible, offered, enrolled, declined, disenrolled. A member can be in several programmes at once.

Transitions of care#

The one workflow driven by an external event rather than a standing measure: a member is discharged and a clock starts — contact within 48 hours, a follow-up visit within 7 days.

Both clocks run from the discharge date, never from when the record reached us. A discharge learned about late has less window remaining, not a fresh one. Anchoring to arrival is how organisations end up reporting a follow-up they did not achieve.

The sweep that raises follow-up tasks is idempotent, so it can run on every inbound message without stacking duplicates onto a care manager's queue. Readmissions are reported as observed history, not as a prediction.

Financial performance#

Cost and utilization for the attributed population. PMPM divides allowed dollars by member months, not by member count — a member attributed for four months of a twelve-month period contributes four. Dividing by a head count is the commonest way a PMPM comes out wrong, and it flatters every number downstream.

Utilization is expressed per 1,000 members per year because that is the unit payer benchmarks are published in; raw counts against a small population would be honest and useless.

Contract performance#

A value-based agreement carries its own terms: benchmark PMPM, risk model, shared-savings rate, quality withhold and the minimum quality score that gates earning anything. Settlement is computed as savings against benchmark, gated on quality, then reduced by the withhold.

Every settlement figure is an estimate and is labelled as one. Real settlement is a reconciliation the payer performs months later against run-out claims. A platform that prints it as fact is making a promise it cannot keep.

If savings are generated but the quality gate is not met, the screen says so and shows zero earned rather than quietly paying out.

Outcomes, measured and not#

Four outcome claims are computed from live data: composite quality rate, care-gap closure, avoidable utilization and total cost of care. Each states the method used.

Two are returned as NOT MEASURED, deliberately. Member experience needs survey instrumentation this platform does not collect. Success in value-based contracts cannot be claimed before a payer reconciles settlement. A plausible number would be worse than a blank.

Measured outcomes can be snapshotted and trended, which is what turns "performance improves over time" from an assertion into something checkable.

Master patient index#

When a second source arrives, the same person appears twice under different identifiers and every downstream number double-counts. The index scores candidate matches on identifier, date of birth and name, weighted so that no single field can carry a match alone.

The engine proposes; a person disposes. Matches stay candidates until someone with administrative permission confirms them. A false-positive merge joins two people's charts — a patient-safety event, not a data-quality one — so merges consolidate identity only and remain reversible.

Outreach and templates#

Outreach uses versioned, approved, multilingual templates rather than text typed at send time. An approved template is also what makes an automated send defensible: a person approved the words, the system chose the moment.

Consent is enforced at the moment of sending, against the member's channel opt-in and quiet hours — not at the workflow transition. Inbound replies are handled too: an opt-out keyword is honoured before anything else and then enforced on every subsequent send, and a confirmation advances the intervention from a real member response rather than a staff click.

This deployment cannot deliver a message externally. Sending requires both a configured provider and synthetic-only mode switched off. Being unable to message a real person by accident is the intended property of a demo environment.

API reference#

All endpoints are JSON over HTTPS. Authenticate with JWT bearer tokens: sign in to receive an access token (15-minute lifetime) and a refresh token, then send Authorization: Bearer <access_token> on every call and exchange the refresh token for a new pair as needed. The permission column names the permission the server checks, see the matrix for which roles hold it.

MethodPathPermissionPurpose
POST/auth/loginpublic Sign in; returns access + refresh tokens, role and name. Throttled; lockout after 5 failures (423)
POST/auth/refreshvalid refresh token Exchange a refresh token for a fresh token pair
GET/auth/meany authenticated Current identity: user ID, tenant, role, credential
GET/population/patients/{id}/clinicalpatient.read Longitudinal record: labs, problem list, SDOH, medications, procedures, encounters
GET/population/patients/{id}/riskpatient.read Current score, contributing factors with weights, and scoring history
POST/population/risk/recomputevbc.write Rescore the tenant; writes a new history row per member
GET/population/measurespatient.read Active measure definitions with version and steward
GET/population/qualityanalytics.read Measure rates with denominator, numerator, exclusions and open gaps
POST/population/quality/evaluatevbc.write Re-run evaluation and reconcile care gaps. Idempotent
GET/population/next-best-actionspatient.read Ranked recommendations with reasoning. Advisory only; creates nothing
GET/population/attributionpatient.read Attributed members for the open period, each with its method and rationale
POST/population/attribution/runvbc.admin Attribute the population to the open period. Idempotent
GET/population/cohortspatient.read Saved cohort definitions with live member counts
POST/population/cohortsvbc.write Save a cohort. Unknown filter keys are refused (422), never ignored
GET/population/patients/{id}/enrollmentspatient.read Programme enrollment history with status, dates and consent
POST/population/patients/{id}/enrollmentsvbc.write Record an enrollment transition. Updates the existing row rather than stacking duplicates
GET/finance/costanalytics.read Allowed, paid, member liability, PMPM over member-months, utilization per 1,000/year
GET/finance/claimsanalytics.read Claim headers with service lines
GET/finance/contractsanalytics.read Benchmark vs actual PMPM, quality gate, estimated settlement. Always labelled an estimate
GET/finance/outcomesanalytics.read Outcome metrics with method and trend; unmeasurable claims returned as NOT MEASURED
POST/finance/outcomes/snapshotvbc.admin Freeze today's measured outcomes so they can be trended
GET/mpi/candidatespatient.read Probable duplicate records with match score and the basis for it
POST/mpi/scanvbc.admin Scan the tenant for duplicates, writing candidates
POST/mpi/candidates/{id}/mergevbc.admin Confirm a match. Consolidates identity only, and stays reversible
GET/transitionspatient.read Recent discharges with contact and visit clocks measured from the discharge date
POST/transitions/sweepvbc.write Raise follow-up tasks for open windows. Idempotent
GET/engagement/templatespatient.read Approved outreach templates by channel and locale
POST/engagement/sendvbc.write Send an approved template. Refused on opt-out or quiet hours (409). Cannot deliver externally in a synthetic deployment
POST/engagement/inboundvbc.write Record a member reply. Opt-out keywords honoured first; a confirmation advances the intervention
GET/vbc/patientspatient.read Tenant-scoped patient roster with risk tier, factors and model version
GET/vbc/patients/{id}patient.read Patient 360: demographics, risk evidence, care gaps, interventions with timelines
POST/vbc/interventionsvbc.write Create an intervention from a care gap; blocks duplicates (409); gap → IN_PROGRESS
POST/vbc/interventions/{id}/transitionvbc.write Move an intervention through its state machine; illegal moves and PA-gated scheduling → 409
POST/vbc/events/completionvbc.write Completion-evidence feed (simulates EHR/claims); deterministic gap auto-closure on match
GET/vbc/taskstask.read My Work queue. Each task carries priority, reason (why) and action (what)
GET/vbc/summarypatient.read Dashboard aggregates computed live from rows, so KPIs always reconcile to drill-downs
POST/pa/requirement-checkpa.read CRD-style discovery: is PA required for this member + CPT? Returns yes / no / unknown + policy + docs
POST/papa.create Create + submit a PA (idempotency key honored); snapshots policy version; stamps the SLA deadline
GET/papa.read PA work queue, tenant-scoped, newest first, with SLA due and auth numbers
GET/pa/{ref}pa.read PA detail including the full decision trace (reviews with kind, credential, model, outcomes), the authorization window and, on a denial, the specific reason text as well as its code
GET/pa/readinesspa.read Documentation readiness before a request exists. Takes patient_id and cpt; returns each criterion as evidenced, in-the-chart-unattached, or not evidenced
GET/pa/{ref}/readinesspa.read The same check against an existing request. Both sides of the desk see the same picture
POST/pa/{ref}/attach-documentpa.create Bind an existing member document to this request. Audited with file name and checksum. A repeat on the same request → 409; another member's document → 409
POST/assistant/askany authenticated Ask mdvin. Returns the answer, the facts behind it, the records it read, and the actions offered. Gated on the caller's own permissions, per question
GET/assistant/suggestionsany authenticated Opening questions appropriate to the caller's role, and whether phrasing is enabled
GET/auditaudit.read The audit trail. Filter by action, object, member, actor, correlation ID or date range; keyset paging on before_seq. The read is itself audited
GET/audit/actionsaudit.read The action vocabulary actually present, with counts
GET/audit/verifyaudit.read Recompute the hash chain; returns ok, how many were checked, and the first break
POST/pa/{ref}/ai-advisorypa.review Record an AI advisory row (model + version logged) — cannot change PA state
POST/pa/{ref}/decisionpa.review (deny: + pa.decide + MD credential) Human decision: approve / pend / deny. Deny additionally requires a specific reason code + text
GET/brandingpublic Brand config (name, tagline, company), the SPA reads this at boot
GET/healthpublic Liveness probe

Operations extras: GET /ready (database readiness probe) and GET /ops/audit-verify (recomputes the audit hash chain end-to-end and reports integrity). Every response carries an X-Correlation-ID header matching the audit rows the request produced.

Troubleshooting#

Most "errors" in this platform are guards doing their job. Here is what each status means and what to do.

StatusYou will see it when…What it means & what to do
401Any call after ~15 minutes idle; or a bad password at sign-in Session expired (access tokens live 15 minutes) or credentials wrong, sign in again. Login failures are deliberately generic ("Invalid credentials"): the system never confirms whether an email exists.
403An RN presses Deny; an Auditor tries to write; any role calls an endpoint its permissions don't cover By design. Your role lacks the permission (or, for denials, the physician credential). Switch to a user that holds it, see the matrix. The refused attempt is itself audited.
404Opening an object by ID that doesn't exist, or belongs to another tenant The platform never distinguishes "doesn't exist" from "not yours" (no existence leakage). Check the ID.
409(a) an illegal state transition, e.g. Illegal intervention transition OUTREACH -> COMPLETED; (b) Scheduling gated: PA-2026-xxxxx is IN_REVIEW; (c) Active intervention exists on a second Start Intervention The state machine refused. (a) follow the legal path in the diagrams; (b) wait for, or obtain, the PA decision, scheduling unlocks automatically; (c) use the existing intervention, one gap carries one active intervention.
422Denying without a reason: Denial requires a specific reason code and text; creating a PA for a member with no active coverage; an urgency other than standard/expedited The request was understood but violates a validation rule. For denials, supply a specific reason code and text. Generic denials are rejected in line with CMS-0057-F.
423Account temporarily locked at sign-in Five failed password attempts locked the account for 15 minutes. Wait it out, then sign in with the correct password from the credentials table.
When reporting an issue, include the correlation ID from the app's top bar (also returned on every response as X-Correlation-ID). It links your action to every audit row and log line it produced.

Glossary#

Prior Authorization (PA)
A payer's advance approval that a service is medically necessary and covered before it is delivered. The unit of work in the PA module.
Utilization Management (UM)
The payer discipline of reviewing care requests against clinical criteria, the review queue, nurses and medical directors in this platform.
Adverse determination
A denial (or partial approval) of requested care. Here it requires a physician credential and a specific reason, never automation.
SLA / TAT
Service-level agreement / turnaround time, the decision deadline on a PA. Stamped at submission: 72 hours expedited, 7 calendar days standard, per CMS-0057-F.
CMS-0057-F
The CMS Interoperability and Prior Authorization final rule. Its decision timeframes and specific-denial-reason requirements have been in force since January 1, 2026; its API requirements (Prior Authorization, Patient Access, Provider Access, Payer-to-Payer) take effect January 1, 2027.
Documentation readiness
The pre-submission check that matches a plan's criteria against the member's own record and reports each one as evidenced, present in the chart but not attached, or not evidenced. Deterministic: it cites evidence and never asserts a clinical fact.
Unattached evidence
A document that exists on the member but is not bound to the request being built. The most common avoidable cause of a pended authorization, and the case the readiness check exists to find.
Care gap
A measurable difference between recommended and delivered care for one member, tied to a versioned quality measure and closable only by clinical evidence.
PMPM
Per member per month. Allowed dollars divided by member-months, not by member count, which is what makes it comparable to a payer benchmark.
Member months
The sum of months each attributed member was covered in a period. A member attributed for four months of a twelve-month period contributes four.
Attribution
The record of which members belong to an organisation for a performance period, and by what method. The denominator under every quality and financial number.
Benchmark / shared savings / withhold
Contract terms. The benchmark is the target PMPM; savings below it are shared at the contracted rate, gated on a minimum quality score, then reduced by the quality withhold.
Risk tier
HIGH, RISING, MEDIUM or LOW, produced by a named, versioned rule engine from the member's own clinical record. Every contributing factor carries its weight and source.
Denominator / numerator / exclusion
A measure's eligible population, the compliant subset of it, and members removed from consideration entirely. An excluded member is never counted as compliant.
Next best action
A ranked, advisory recommendation of what to do for which member and why. It creates nothing and never suggests an action the workflow would refuse.
Transitions of care
The post-discharge follow-up window. Both the 48-hour contact clock and the 7-day visit clock run from the discharge date, not from when the record arrived.
Master patient index (MPI)
Reconciliation of the same person appearing under different identifiers from different sources. Matches are proposed by score and confirmed by a person.
SDOH
Social drivers of health — housing, food, transport, isolation — recorded as Z-coded observations alongside clinical ones, because they are observations about a member like any other.
HEDIS
A widely used set of healthcare quality measures. The demo's measure keys (e.g. CDC-HBA1C, EED-RETINAL) follow this style of gap logic with explicit measure versions.
FHIR
Fast Healthcare Interoperability Resources, the modern HL7 standard for healthcare data exchange. The platform's integration surface is designed around FHIR R4 patterns.
CRD / DTR / PAS
The Da Vinci implementation guides for electronic PA: Coverage Requirements Discovery (is PA needed?), Documentation Templates & Rules (collect the evidence), Prior Authorization Support (submit and track). The requirement-check → launch → review flow mirrors this pattern, which the HTI-4 rule is building into certified EHRs.
X12 278
The legacy EDI transaction for PA requests/responses. Channel provenance on each PA records whether it arrived via FHIR, X12 278 or portal.
NCD / LCD
National / Local Coverage Determinations — Medicare's published coverage policies; the kind of source content a production policy library encodes as rule packages.
Rule package
A versioned, effective-dated bundle of coverage criteria keyed by payer, line of business and service codes. PAs snapshot the version they were judged under.
Gold carding
State-law programs exempting consistently-approved providers from PA for certain services. One reason PA applicability must be configuration, not code.
Idempotency key
A client-supplied token on PA creation guaranteeing that retries return the original request instead of creating duplicates.
Decision trace
The ordered record of every review action on a PA, kind (machine / human / AI advisory), criteria version, 5-state outcomes, credential, model version, sufficient to reproduce the decision later.
Correlation ID
A per-request identifier stamped on responses, logs and audit rows, tying one user action to everything it caused.
ACO
Accountable Care Organization, a provider group accountable for the total cost and quality of a population. The demo tenant is an ACO.
Medicare Advantage (MA)
Medicare benefits administered by private plans, the line of business on the demo members' coverage, and a primary target of CMS-0057-F.
TCOC / PMPM
Total cost of care / per-member-per-month, the financial lenses of value-based contracts that population dashboards ultimately roll up to.
Risk stratification
Ranking members by predicted need (HIGH / RISING / MEDIUM / LOW here), with each factor carrying provenance and the scoring model versioned.