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#
Signing in#
- 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.
- 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.
- Sessions use short-lived JWT access tokens (15 minutes) with a refresh token behind them.
If a request returns
401after a long idle period, sign in again.
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.
| Role | Password | What this role demonstrates | |
|---|---|---|---|
| Care Manager Jane Smith | jane@demo.aco | CareManager!2026x |
My Work queue, interventions, engagement, launching PAs |
| VBC Manager Alex Rivera | alex@demo.aco | VbcManager!2026xx |
Dashboard aggregates, population views |
| UM Nurse (RN) Sam Nurse | nurse@demo.payer | UmNurse!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.payer | MedDirector!2026 |
Adverse determinations with credential + specific reason |
| Medical Director 2 Dr. B. Rivera — MD, Ophthalmology | md2@demo.payer | MedDirector2!26x |
Independent appeal reviews (the original denier cannot decide an appeal) |
| Auditor Avery Auditor | audit@demo.aco | Auditor!2026xxxx |
Read-only decision traces |
| Platform Admin (backend) Pat Admin | admin@demo.aco | PlatformAdmin!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:
| State | Meaning |
|---|---|
CANDIDATE | Measure engine has flagged the member; not yet confirmed into the work stream |
OPEN | Confirmed gap, no active work, this is where Start Intervention appears |
IN_PROGRESS | An intervention is actively working the gap |
SCHEDULED | The closing service has an appointment on the books |
AWAITING_AUTH | Blocked on a pending prior authorization, the cross-module wait state |
SATISFIED | Measure numerator met per the engine; pending confirmation into CLOSED |
CLOSED | Closed on qualifying clinical evidence, the only way a gap closes |
EXCLUDED | Member meets a measure exclusion; gap leaves the denominator |
NOT_APPLICABLE | Measure does not apply to this member |
REOPENED | Evidence lapsed or was invalidated; the gap is live again |
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.
SCHEDULED → OUTREACH (no-show reopens outreach) ·
AWAITING_AUTH → OUTREACH (e.g. after a denial, re-engage on an alternative) ·
SCHEDULED → IN_PROGRESS → COMPLETED · COMPLETED → REOPENED.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.
WITHDRAWN is reachable from DRAFT, SUBMITTED and
PENDED. PARTIALLY_APPROVED follows the same appeal/closure paths as DENIED.
On approval the platform issues an auth number (AUTH-…) valid for 180 days.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.read | vbc.write | vbc.admin |
task.read | analytics.read |
pa.create | pa.read | pa.review |
pa.pend | pa.decide |
policy.read | policy.write |
audit.read | admin.all |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| care_manager | Yes | Yes | — | Yes | — | Yes | Yes | — | — | — | — | — | — | — |
| vbc_manager | Yes | Yes | Yes | Yes | Yes | — | Yes | — | — | — | — | — | — | — |
| executive | Yes | — | — | — | Yes | — | — | — | — | — | — | — | — | — |
| provider | Yes | Yes | — | — | — | Yes | Yes | — | — | — | — | — | — | — |
| pa_coordinator | Yes | — | — | — | — | Yes | Yes | — | — | — | — | — | — | — |
| um_nurse | — | — | — | — | — | — | Yes | Yes | Yes | — | — | — | — | — |
| medical_director | — | — | — | — | — | — | Yes | Yes | Yes | Yes | — | — | — | — |
| policy_admin | — | — | — | — | — | — | — | — | — | — | Yes | Yes | — | — |
| platform_admin | — | — | — | — | — | — | — | — | — | — | Yes | — | — | Yes |
| auditor | Yes | — | — | — | — | — | Yes | — | — | — | — | — | Yes | — |
= 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#
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
- 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
- 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
- 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. - 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)
- On an
OPENgap, click Start Intervention. - 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.
- The intervention appears in the Interventions panel in state
IDENTIFIED, its first timeline event reading "created, context inherited from care gap". The gap moves toIN_PROGRESS. - 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
- On the
IDENTIFIEDintervention, click Begin outreach → state becomesOUTREACH. - Click Patient responded →
ENGAGED. Every click appends a timestamped event to the timeline. - Click Schedule →
SCHEDULED— unless a linked PA is still pending. If you launched a PA that has not been decided, the server refuses with409 Scheduling gated: PA-2026-xxxxx is IN_REVIEW.What you should seeWhile the PA is pending the intervention sits inAWAITING_AUTHwith a stopwatch chip ("awaiting payer decision") and no schedule button at all. The moment the PA is approved, the intervention flips toAUTH_APPROVEDautomatically and the button returns as Schedule (auth on file).
Recording completion evidence & auto-closure
- On a
SCHEDULEDintervention, click Record completion evidence. This simulates the EHR/claims completion feed a production deployment receives automatically. - Choose the evidence type —
lab,encounterorprocedure, and enter the CPT observed (e.g.83036for the HbA1c gap,92250for the retinal exam), then Send event. - 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
COMPLETEDtoGAP_CLOSEDand the gap becomesCLOSED. On a mismatch: "Evidence insufficient, gap stays IN_PROGRESS (logged)" and an audit event records exactly what was offered and rejected. - 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
- 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
- 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. - 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_AUTHand the gap showsAWAITING_AUTHtoo. - The policy package and version in force are snapshotted onto the request, and the submission passes intake
validation into
IN_REVIEWwith 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
- Click Review on an
IN_REVIEWPA, 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". - 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
- In the review dialog, record the criterion outcomes. Outcomes are 5-state —
MET,NOT_MET,UNKNOWN,NOT_APPLICABLE,NEEDS_HUMAN_REVIEW, never collapsed to yes/no. - 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.
- 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. - 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 answers422 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 →DENIEDwith the reason stored on the request, yourMD:Ophthalmologycredential 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:
| State | What it means | What 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 |
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 about | Example | Needs |
|---|---|---|
| A request's status | What is the status of PA-2026-0001? | pa.read |
| What is blocking a request | What is blocking my authorizations? | pa.read |
| Deadlines | Which requests are close to their SLA? | pa.read |
| Why authorization is needed | Why does Sarah Martinez need a prior auth for 92250? | pa.read |
| Open care gaps | Which care gaps are open for John Doe? | patient.read |
| Your queue | What should I work on next? | patient.read |
| Risk scoring | What is driving John Doe's risk score? | patient.read |
| Recommendations | What do you recommend I do next? | patient.read |
| Discharges | Who was discharged recently? | patient.read |
| Population | How many members are attributed? | patient.read |
| Quality rates | What are our measure rates? | analytics.read |
| Cost | What is our PMPM? | analytics.read |
| Contract position | How are we tracking against the benchmark? | analytics.read |
| Outcomes | Which 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#
| Control | Behaviour |
|---|---|
| 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.
| # | Actor | Action | System response |
|---|---|---|---|
| 1 | Care Manager (jane) | Patients → open Sarah Martinez's 360 | HIGH risk with evidence (HbA1c 10.1% · lab); gap Diabetic Retinal Exam is OPEN |
| 2 | Care Manager | Start 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 |
| 3 | Care Manager | Launch 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 |
| 4 | Care Manager | Attempt to schedule anyway | 409 Scheduling gated: PA-2026-xxxxx is IN_REVIEW, the appointment cannot outrun the authorization |
| 5 | UM Nurse (nurse) | Open Review Queue → Review the PA | SLA clock, policy snapshot v3 and criteria context displayed |
| 6 | UM Nurse | Run AI criteria analysis | Advisory row recorded (apex-um v1.8) — no state change |
| 7 | UM Nurse | Press Deny | 403 Adverse determinations require a medical director, refusal is itself audited |
| 8 | Medical 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 |
| 9 | Care Manager | Schedule (auth on file) | Gate passes, intervention → SCHEDULED. Note: the gap is still open. Approval ≠ care delivered |
| 10 | Care Manager | Record completion evidence: procedure / CPT 92250 |
Deterministic match → intervention COMPLETED → GAP_CLOSED; gap → CLOSED; toast
"Care gap closed automatically; evidence recorded" |
| 11 | Auditor (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 |
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.
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.
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.
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.
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.
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.
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.
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.
| Method | Path | Permission | Purpose |
|---|---|---|---|
| POST | /auth/login | public | Sign in; returns access + refresh tokens, role and name. Throttled; lockout after 5 failures (423) |
| POST | /auth/refresh | valid refresh token | Exchange a refresh token for a fresh token pair |
| GET | /auth/me | any authenticated | Current identity: user ID, tenant, role, credential |
| GET | /population/patients/{id}/clinical | patient.read |
Longitudinal record: labs, problem list, SDOH, medications, procedures, encounters |
| GET | /population/patients/{id}/risk | patient.read |
Current score, contributing factors with weights, and scoring history |
| POST | /population/risk/recompute | vbc.write |
Rescore the tenant; writes a new history row per member |
| GET | /population/measures | patient.read |
Active measure definitions with version and steward |
| GET | /population/quality | analytics.read |
Measure rates with denominator, numerator, exclusions and open gaps |
| POST | /population/quality/evaluate | vbc.write |
Re-run evaluation and reconcile care gaps. Idempotent |
| GET | /population/next-best-actions | patient.read |
Ranked recommendations with reasoning. Advisory only; creates nothing |
| GET | /population/attribution | patient.read |
Attributed members for the open period, each with its method and rationale |
| POST | /population/attribution/run | vbc.admin |
Attribute the population to the open period. Idempotent |
| GET | /population/cohorts | patient.read |
Saved cohort definitions with live member counts |
| POST | /population/cohorts | vbc.write |
Save a cohort. Unknown filter keys are refused (422), never ignored |
| GET | /population/patients/{id}/enrollments | patient.read |
Programme enrollment history with status, dates and consent |
| POST | /population/patients/{id}/enrollments | vbc.write |
Record an enrollment transition. Updates the existing row rather than stacking duplicates |
| GET | /finance/cost | analytics.read |
Allowed, paid, member liability, PMPM over member-months, utilization per 1,000/year |
| GET | /finance/claims | analytics.read |
Claim headers with service lines |
| GET | /finance/contracts | analytics.read |
Benchmark vs actual PMPM, quality gate, estimated settlement. Always labelled an estimate |
| GET | /finance/outcomes | analytics.read |
Outcome metrics with method and trend; unmeasurable claims returned as NOT MEASURED |
| POST | /finance/outcomes/snapshot | vbc.admin |
Freeze today's measured outcomes so they can be trended |
| GET | /mpi/candidates | patient.read |
Probable duplicate records with match score and the basis for it |
| POST | /mpi/scan | vbc.admin |
Scan the tenant for duplicates, writing candidates |
| POST | /mpi/candidates/{id}/merge | vbc.admin |
Confirm a match. Consolidates identity only, and stays reversible |
| GET | /transitions | patient.read |
Recent discharges with contact and visit clocks measured from the discharge date |
| POST | /transitions/sweep | vbc.write |
Raise follow-up tasks for open windows. Idempotent |
| GET | /engagement/templates | patient.read |
Approved outreach templates by channel and locale |
| POST | /engagement/send | vbc.write |
Send an approved template. Refused on opt-out or quiet hours (409). Cannot deliver externally in a synthetic deployment |
| POST | /engagement/inbound | vbc.write |
Record a member reply. Opt-out keywords honoured first; a confirmation advances the intervention |
| GET | /vbc/patients | patient.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/interventions | vbc.write |
Create an intervention from a care gap; blocks duplicates (409); gap → IN_PROGRESS |
| POST | /vbc/interventions/{id}/transition | vbc.write |
Move an intervention through its state machine; illegal moves and PA-gated scheduling → 409 |
| POST | /vbc/events/completion | vbc.write |
Completion-evidence feed (simulates EHR/claims); deterministic gap auto-closure on match |
| GET | /vbc/tasks | task.read |
My Work queue. Each task carries priority, reason (why) and action (what) |
| GET | /vbc/summary | patient.read |
Dashboard aggregates computed live from rows, so KPIs always reconcile to drill-downs |
| POST | /pa/requirement-check | pa.read |
CRD-style discovery: is PA required for this member + CPT? Returns yes / no / unknown + policy + docs |
| POST | /pa | pa.create |
Create + submit a PA (idempotency key honored); snapshots policy version; stamps the SLA deadline |
| GET | /pa | pa.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/readiness | pa.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}/readiness | pa.read |
The same check against an existing request. Both sides of the desk see the same picture |
| POST | /pa/{ref}/attach-document | pa.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/ask | any 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/suggestions | any authenticated | Opening questions appropriate to the caller's role, and whether phrasing is enabled |
| GET | /audit | audit.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/actions | audit.read |
The action vocabulary actually present, with counts |
| GET | /audit/verify | audit.read |
Recompute the hash chain; returns ok, how many were checked, and the first break |
| POST | /pa/{ref}/ai-advisory | pa.review |
Record an AI advisory row (model + version logged) — cannot change PA state |
| POST | /pa/{ref}/decision | pa.review (deny: + pa.decide + MD credential) |
Human decision: approve / pend / deny. Deny additionally requires a specific reason code + text |
| GET | /branding | public | Brand config (name, tagline, company), the SPA reads this at boot |
| GET | /health | public | 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.
| Status | You will see it when… | What it means & what to do |
|---|---|---|
| 401 | Any 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. |
| 403 | An 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. |
| 404 | Opening 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. |
| 422 | Denying 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. |
| 423 | Account 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. |
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.