CDQ Care Data Quality

CDQ API

For engineers at client health systems who send patient data to CDQ.

Overview

CDQ checks patient event data against approved care pathways. For each patient and pathway it reports which steps were done on time, done late, done too early, or missed, and which are not due yet.

You send:

You get back:

CDQ does not store the patient data you send. Only counts (patients submitted and evaluated per pathway) are kept, for billing.

Two ways to send data

Both run the same evaluation on the same data. Pick the one that fits where you are.

FeatureFile uploadJSON API
Best forGetting started, one-off or monthly extractsAutomated pipelines
WhereWeb app, Analysis pagePOST /cdq/analysis/evaluate-batch
FormatCSV, TSV or JSON fileJSON request body
Sign-inYour CDQ user accountAPI key (X-API-Key) or bearer token
Choosing pathwaysCDQ shows which pathways the file's patients qualify for; you tick the ones to runYou list them in pathway_ids
Evaluation dateOptional date on the upload formOptional as_of_date
ResultsOn screen, plus CSV downloads (deviations, step statuses, recommendations)JSON response

The two are designed to be interchangeable:

A common path is to start with uploads, then move the same extract into a pipeline that calls the API.

Authentication

Every /cdq/* endpoint needs one of these headers:

HeaderWho uses itIdentity
X-API-Key: <key>PipelinesRole client_api, scoped to the key's client
Authorization: Bearer <token>Signed-in appsRole and client from the token's claims (RS256, checked against CDQ's identity provider)

If both are sent, X-API-Key is used.

There are no request-rate limits. Repeated failed sign-ins are logged and alerted on.

Evaluate a batch

POST /cdq/analysis/evaluate-batch
Content-Type: application/json
X-API-Key: <your key>

The request body may be up to 25 MB by default. Split larger extracts into several requests that share one submission_id (see below).

Request

This is the upload template with client_id and pathway_ids filled in:

{
  "client_id": "3f2c9a1e-5b7d-4c8e-9a10-2b3c4d5e6f70",
  "pathway_ids": [
    "8a1d2c3b-4e5f-4a6b-8c7d-9e0f1a2b3c4d",
    "1b2c3d4e-5f6a-4b7c-8d9e-0f1a2b3c4d5e"
  ],
  "as_of_date": null,
  "patients": [
    {
      "patient_id": "P001",
      "patient_context": {"date_of_birth": "1967-04-12", "patient_sex": "F", "plan_type": "commercial",
                          "active_diagnoses": ["E11.9", "73211009"]},
      "prior_assignments": [{"pathway_name": "Chronic Diabetes Management", "assignment_status": "active",
                             "assigned_since": "2025-09-02"}],
      "events": [
        {"event_id": "e1", "event_type": "diagnosis", "event_date": "2025-09-02", "event_code": "E11.9", "event_code_system": "ICD-10"},
        {"event_id": "e2", "event_type": "lab", "event_date": "2025-09-20", "event_code": "4548-4", "event_code_system": "LOINC", "result_value": "8.1",
         "communication_date": "2025-09-24"}
      ]
    },
    {
      "patient_id": "P002",
      "patient_context": {"date_of_birth": "1958-02-20", "patient_sex": "M", "plan_type": "medicare"},
      "events": [
        {"event_id": "e3", "event_type": "procedure", "event_date": "2025-10-03", "event_code": "27447",
         "event_code_system": "CPT", "scheduled_date": "2025-11-14"}
      ]
    }
  ]
}

With curl:

curl -sS https://<your CDQ host>/cdq/analysis/evaluate-batch \
  -H "X-API-Key: $CDQ_API_KEY" \
  -H "Content-Type: application/json" \
  --data @batch.json

Fields

Top level

FieldTypeRequiredMeaning
client_idUUID stringYesYour client. Must match your key or token.
pathway_idsarray of UUID stringsYes, at least onePathways to evaluate. Each must be approved for your client (see GET /cdq/pathways/available). Repeats are ignored.
patientsarrayYes, at least oneThe patients.
as_of_dateYYYY-MM-DD or nullNoThe evaluation date: steps due after it are not yet missed. Can't be after today (422). Default: the latest event dated on or before today in the request.
submission_idUUID stringNoGroups requests into one billing submission. Omitted: CDQ creates one and returns it.
mode"evaluate" or "enrollment_preview"No, default "evaluate"enrollment_preview only checks who qualifies for each pathway: qualifying patients are listed in patients_enrolled, the rest in patients_skipped. It is not billed, works while billing is paused, and returns no step statuses or deviations.
include_recommended_when_priorbooleanNo, default falseWhen a patient has prior assignments, CDQ normally evaluates only those pathways for them. true evaluates every listed pathway for every patient.
enforce_assigned_scopebooleanNo, default falsetrue requires every patient to have prior assignments with pathway_id, and evaluates only those. Cannot be combined with include_recommended_when_prior: true.

patients[]

FieldTypeRequiredMeaning
patient_idstringYesYour identifier for the patient. Returned as-is in every row. Use a pseudonymous ID, not an MRN, where you can.
eventsarrayYes (may be empty)The patient's events.
patient_contextobjectNoPatient-level facts. See below.
prior_assignmentsarrayNoPathways the patient is already on. See below.
prior_assignmentobjectNoA single prior assignment. Used only when prior_assignments is empty.

patients[].events[]

FieldTypeRequiredMeaning
event_idstringNoYour ID for the event, unique within the patient. Left out or empty: CDQ numbers the events.
event_typestringYesWhat kind of event, any case. See Event types and codes.
event_dateYYYY-MM-DDYesWhen it happened. For a booking, when it was booked. Events with a date CDQ can't read are ignored.
event_codestringNoThe clinical code: ICD-10-CM, SNOMED CT, LOINC, CPT/HCPCS or RxNorm. Case doesn't matter.
event_code_systemstringNoThe code's system, for example ICD-10, LOINC, CPT, RxNorm. Matching uses the code itself.
encounter_typestringNoVisit setting, for example ambulatory, inpatient, emergency, wellness, discharge.
result_valuestringNoA lab, vital sign or screening result, for example "8.1" or "positive".
scheduled_dateYYYY-MM-DDNoSet only for a procedure that is booked but not yet done: the booked date. An event whose scheduled date can't be read is ignored, as in an upload. See Scheduled procedures.
communication_dateYYYY-MM-DDNoWhen this event's result was given to the patient. Adds a communication event with the same code on that date. See Results and referrals.
referral_dateYYYY-MM-DDNoWhen a referral was made following this event. Adds a referral event with the same code on that date.
provider_typestringNoAccepted; not used in evaluation today.
departmentstringNoAccepted; not used in evaluation today.

patients[].patient_context (all keys optional)

KeyTypeMeaning
patient_ageintegerAge in whole years. Ages over 90 are treated as 90.
date_of_birthYYYY-MM-DDUsed to work out age on the evaluation date when patient_age is not sent.
patient_sexstringFor example F or M.
plan_typestringCoverage, for example commercial, medicare, medicaid. Some pathways apply to certain plan types only.
active_diagnosesarray of stringsThe problem list: ICD-10-CM or SNOMED CT codes.
open_sdoh_flagsarray of stringsOpen social needs: food_insecurity, housing_instability, transportation, social_isolation, financial_strain.
sdoh_food_insecurity, sdoh_housing_instability, sdoh_transportation, sdoh_social_isolation, sdoh_financial_straintrue, 1, "1", "true", "yes"The same flags one at a time. A set flag is added to open_sdoh_flags.
open_hcc_flagsarray of stringsOpen HCC flags.

Wrong types return 422 naming the key, for example patient_context.patient_age must be an integer.

patients[].prior_assignments[] (all keys optional)

KeyTypeMeaning
pathway_idUUID stringThe pathway the patient is on. Preferred.
pathway_namestringThe pathway's exact name. Used only when pathway_id is not given.
assignment_statusstringcompleted means the pathway is finished for this patient; it is skipped.
assigned_sinceYYYY-MM-DDWhen the patient started the pathway. The pathway's clock starts here instead of at the first triggering event.
last_completed_stepstringAccepted; not used in evaluation today.

Response

200 OK with a JSON object. Abridged example for the request above:

{
  "total_patients": 2,
  "total_pathways": 2,
  "as_of_date": "2025-10-03",
  "submission_id": "6d1f0b8e-2a4c-4e9b-9b7a-1c2d3e4f5a6b",
  "possible_deviations_count": 0,
  "deviations": [
    {
      "patient_id": "P001",
      "pathway_id": "8a1d2c3b-4e5f-4a6b-8c7d-9e0f1a2b3c4d",
      "pathway_name": "Chronic Diabetes Management",
      "step_name": "Diabetic eye exam",
      "deviation_type": "missing_step",
      "severity": "moderate",
      "expected_date": "2025-10-02",
      "actual_date": null,
      "days_variance": null,
      "confirmed": true,
      "missing_fields": null,
      "evaluation_source": "assigned",
      "visit_group": "ambulatory_visit"
    }
  ],
  "step_statuses": [
    {
      "patient_id": "P001",
      "pathway_id": "8a1d2c3b-4e5f-4a6b-8c7d-9e0f1a2b3c4d",
      "pathway_name": "Chronic Diabetes Management",
      "step_id": "c0ffee00-0000-4000-8000-000000000001",
      "step_name": "HbA1c test",
      "step_order": 1,
      "status": "COMPLETE",
      "actual_date": "2025-09-20",
      "expected_by_date": "2025-12-01",
      "window_open_date": "2025-09-02",
      "days_variance": -72,
      "evaluation_source": "assigned",
      "trigger_type": "icd10",
      "trigger_code": "E11",
      "trigger_date": "2025-09-02"
    },
    {
      "patient_id": "P002",
      "pathway_id": "1b2c3d4e-5f6a-4b7c-8d9e-0f1a2b3c4d5e",
      "pathway_name": "Total Knee Replacement",
      "step_id": "c0ffee00-0000-4000-8000-000000000002",
      "step_name": "Pre-operative assessment",
      "step_order": 1,
      "status": "DUE",
      "actual_date": null,
      "expected_by_date": "2025-11-07",
      "window_open_date": "2025-10-15",
      "days_variance": null,
      "evaluation_source": "recommended",
      "trigger_type": "procedure_scheduled",
      "trigger_code": "27447",
      "trigger_date": "2025-11-14"
    }
  ],
  "patients_skipped": [
    {
      "patient_id": "P001",
      "pathway_id": "1b2c3d4e-5f6a-4b7c-8d9e-0f1a2b3c4d5e",
      "pathway_name": "Total Knee Replacement",
      "reason": "pathway not in patient prior assignments"
    }
  ]
}

Pathway names, step names, codes and dates above are illustrative. The real ones come from your approved pathways.

Top level

FieldMeaning
total_patientsPatients in the request.
total_pathwaysDistinct pathways in the request.
as_of_dateThe evaluation date used.
submission_idThe submission this request was billed under. null in enrollment_preview mode.
deviationsMissed, late and premature steps, sorted by patient, then severity (critical first), then visit group.
step_statusesOne row per patient, pathway and evaluated step.
possible_deviations_countDeviations with confirmed: false.
patients_skippedPatient and pathway pairs not evaluated, with the reason.
patients_enrolledenrollment_preview only: each patient and pathway pair that qualifies, with trigger_date (when the pathway would start) and evaluation_source. Left out when empty.
recommendationsPresent only when at least one applies. Never counted as deviations.

deviations[]

FieldMeaning
deviation_typemissing_step (not done, due date passed), late_step (done after the due date), premature_step (done before the window opened), conditional_gap (a conditional step could not be checked because patient context is missing; confirmed: false).
severitycritical, high, moderate, low, informational, as set on the step.
expected_dateThe due date (missing, late), or the date the window opened (premature).
actual_dateWhen the step was done, if it was.
days_varianceLate: days after the due date (positive). Premature: days before the window opened (negative).
confirmedfalse only for conditional_gap.
missing_fieldsFor conditional_gap: the patient_context keys that would have let CDQ check the step.
evaluation_sourceassigned (clock started at a prior assignment's assigned_since) or recommended (CDQ found the patient qualifies from the data).
visit_groupWhere the gap would usually be closed: wellness_visit, ambulatory_visit, specialist_referral, ed_related.

step_statuses[]

FieldMeaning
statusCOMPLETE (a matching event was found, on time or not), DUE (not done, not yet past due), OVERDUE (not done, past due), NOT_APPLICABLE (the step depends on an earlier step that wasn't met), CANNOT_CHECK (the step lists no codes yet, so no event can show it was done; never a deviation).
actual_dateDate of the event that met the step.
window_open_date, expected_by_dateThe step's window.
days_varianceactual_date minus expected_by_date. Negative means early within the window.
trigger_type, trigger_code, trigger_dateWhat starts the pathway, and the date the clock started for this patient.

patients_skipped[].reason values:

ReasonMeaning
enrollment criteria not metThe patient doesn't qualify for the pathway from the data sent.
no trigger-matching event foundNo event starts the pathway for this patient.
pathway not in patient prior assignmentsThe patient has prior assignments and this pathway isn't one of them.
prior assignment status is 'completed'The patient has finished this pathway.
plan_type '…' not in pathway filter [...]The pathway is for other plan types.
missing enrollment criteria for canonical pathwayThe pathway is not set up correctly. Tell Preact.
evaluation error (see server logs)CDQ hit an error on this pair. The rest of the batch is unaffected. Tell Preact.

recommendations[]

FieldMeaning
recommendationWhat is recommended, in words.
action_typeThe kind of recommendation, for example pending_discharge.
step_nameThe step (or event) that prompted it.
valueThe value that prompted it: a result, days overdue, or for pending_discharge the admission date.
suggested_pathwayA pathway to consider, when the recommendation is to start one.
priorityFor example high.
conditional_refThe pathway rule that fired (empty for pending_discharge).

Submissions and billing

Upload ↔ API field mapping

The upload reads one row per event. Patient-level columns can repeat on every row of a patient, or appear on any one of them: the first non-blank value wins. Column names are matched without regard to case, and spaces, dots and dashes count as underscores (Event Date matches event_date). When several aliases are present, the first alias in the list wins.

Upload columnAlso acceptedAPI JSON pathMeaning
patient_idpatientid, patient, mrn, idpatients[].patient_idPatient identifier. Required in both.
event_typetype, record_type, event_categorypatients[].events[].event_typeKind of event. Upload: optional, defaults to encounter. API: required. Any case in both.
event_datedate, service_date, encounter_date, event_dt, date_of_servicepatients[].events[].event_dateWhen it happened. Required in both.
event_codecode, dx_code, procedure_code, icd_code, cpt_code, hcpcs_codepatients[].events[].event_codeClinical code.
event_code_systemcode_system, coding_system, code_typepatients[].events[].event_code_systemCode system name.
encounter_typevisit_type, setting, visit_settingpatients[].events[].encounter_typeVisit setting.
result_valuevalue, lab_value, result, test_resultpatients[].events[].result_valueResult.
scheduled_datescheduled_for, procedure_scheduled_date, surgery_date_scheduledpatients[].events[].scheduled_dateBooked date of a procedure not yet done. Blank otherwise.
communication_dateresult_communicated_date, results_communicated_date, date_communicatedpatients[].events[].communication_dateWhen the row's result was given to the patient. Blank otherwise.
referral_datedate_referred, referred_datepatients[].events[].referral_dateWhen a referral was made following the row's event. Blank otherwise.
provider_typeprovider, clinician_type, provider_rolepatients[].events[].provider_typeRecognized; not used in evaluation.
departmentdept, specialty, clinic, service_linepatients[].events[].departmentRecognized; not used in evaluation.
patient_ageagepatients[].patient_context.patient_ageAge in years. Upload drops decimals (45.5 → 45).
date_of_birthdob, birth_date, birthdatepatients[].patient_context.date_of_birthDate of birth.
patient_sexsex, genderpatients[].patient_context.patient_sexSex.
plan_typeinsurance_type, payer_typepatients[].patient_context.plan_typePlan type.
active_diagnosesproblem_list, active_problems, problemspatients[].patient_context.active_diagnosesProblem list. Upload: codes separated by ; or |. API: array of strings.
sdoh_food_insecurityfood_insecuritypatients[].patient_context.sdoh_food_insecurity (or open_sdoh_flags containing food_insecurity)Food insecurity flag.
sdoh_housing_instabilityhousing_instabilitypatients[].patient_context.sdoh_housing_instabilityHousing instability flag.
sdoh_transportationtransportationpatients[].patient_context.sdoh_transportationTransportation flag.
sdoh_social_isolationsocial_isolationpatients[].patient_context.sdoh_social_isolationSocial isolation flag.
sdoh_financial_strainfinancial_strainpatients[].patient_context.sdoh_financial_strainFinancial strain flag.
assigned_pathwaypathway, enrolled_pathway, pathway_namepatients[].prior_assignments[0].pathway_namePathway the patient is on, by name.
assignment_statuspathway_status, enrollment_status, statuspatients[].prior_assignments[0].assignment_statusAssignment status. Upload reads it from the patient's first row only.
assigned_sinceenrollment_date, pathway_start_date, trigger_datepatients[].prior_assignments[0].assigned_sinceStart date on the pathway.
last_completed_steplast_step, completed_steppatients[].prior_assignments[0].last_completed_stepRecognized; not used in evaluation.

SDOH flag values: both treat 1, true, TRUE, yes and YES as set (the API also takes JSON true and 1).

Upload only

Upload columnAlso acceptedMeaning
first_namefirstname, fname, given_nameShown as the patient's label in the web app. Never sent to the engine.
last_namelastname, lname, family_name, surnameAs above.
Evaluation date (form field, not a column)Same as the API's as_of_date. The upload refuses a date in the future.

API only

API fieldMeaning
client_idYour client. The upload uses the signed-in user's client.
pathway_idsPathways to run. The upload lets you pick them after showing who qualifies.
modeenrollment_preview is the API's version of the upload's "who qualifies" step.
submission_idThe upload makes a new submission each time you run it.
include_recommended_when_prior, enforce_assigned_scopeScope controls for prior assignments.
patients[].events[].event_idOptional in the API too; the upload always numbers events itself.
patients[].prior_assignments[] after the firstThe upload carries one assignment per patient. A JSON upload reads the first assignment's pathway_name, or its pathway_id when there's no name.
patients[].patient_context.open_hcc_flagsNo upload column.

Dates. The API takes YYYY-MM-DD only. Uploads also take YYYY/MM/DD, MM/DD/YYYY and M/D/YYYY (month first; day-first dates like 15/03/2026 are not read). Upload rows with a date CDQ can't read are left out and counted on the job page.

Missing values. In uploads, empty cells and NA, N/A and null count as missing. In the API, leave the key out or send null.

JSON uploads. Besides the API body shape, a JSON upload can be an array of flat event rows using the column names above, or a {"patients": [...]}, {"events": [...]}, {"data": [...]}, {"records": [...]} or {"rows": [...]} wrapper around one.

Event types and codes

A step is met by the first event, on or after the step's window opens, whose event_type is one the step accepts and whose event_code is one of the step's codes. A step with no codes can't be met by any event (CANNOT_CHECK).

Step typeEvent types that can meet it
encounter, enrollment, documentationencounter
referralencounter, referral
communicationcommunication, encounter
immunizationimmunization, medication, procedure, encounter
lablab
medicationmedication
diagnosisdiagnosis
sdoh_screeningsdoh_screening, screening
vital_signvital_sign, lab, encounter
imagingimaging, procedure, lab, encounter
procedureprocedure, encounter
screeningscreening, encounter, sdoh_screening, lab

Event types used to qualify patients for pathways (enrollment):

Event typeUsed for
diagnosisDiagnosis-based pathways (ICD-10-CM; a code also matches its child codes, so E11 matches E11.9). Also the principal diagnosis for a hospital stay.
medicationActive-medication criteria.
lab, vital_signResult thresholds (for example HbA1c, blood pressure, BMI). Put the number or text in result_value.
encounterVisits and utilization. With encounter_type inpatient it is an admission; with discharge it is a discharge.
admissionAn inpatient admission.
dischargeA hospital discharge.
procedure, claimProcedures done (CPT/HCPCS).
screening, sdoh_screeningScreening results (put the score or answer in result_value).

Event types and codes are read in any case, with spaces trimmed, by both the upload and the API.

Codes by kind of event

KindCode system to send
Diagnoses, problem listICD-10-CM (SNOMED CT also accepted on the problem list)
Labs, vital signsLOINC
Visits, proceduresCPT or HCPCS. Some visit steps also accept an encounter_type such as wellness.
MedicationsRxNorm (RXCUI) or NDC. See below.

Medications. Medication steps and criteria name drug classes (for example statins or SGLT2 inhibitors). Send the medication as an RxNorm code: an ingredient, clinical drug, branded drug or pack RXCUI all work. NDC codes are also accepted, current or discontinued: 11 digits, or hyphenated 4-4-2, 5-3-2 or 5-4-1. CDQ maps them to RxNorm. event_code_system is optional for medications (RxNorm or NDC); CDQ recognises the code either way.

How results are worked out

Evaluation date. Results are as of one date. Steps due after it are DUE, not missed. If you don't set as_of_date, CDQ uses the latest event dated on or before today in the request (bookings and future-dated events left out); a set date can't be after today. This judges an older extract as of when it was pulled, not as of now. The upload form's evaluation date works the same way.

When the clock starts. Each pathway has a trigger. For each patient, the clock starts at:

  1. the prior assignment's assigned_since, if you sent one for this pathway, else
  2. the qualifying event, for pathways that start at an event (a discharge, a booked procedure), else
  3. the first event that matches the trigger (for example the first diabetes diagnosis), else
  4. for pathways based on age or plan alone, the patient's latest visit for the first step within its repeat interval (a year by default), or the evaluation date if there is none.

Each step then has a window counted in days from that start, or from the previous step.

Scheduled procedures. For a procedure that is booked but not yet done, send the event with scheduled_date set to the booked date (event_date is when it was booked). CDQ treats it as a booking on the booked date. A procedure pathway then starts at the booked date, so pre-operative steps fall due before it. A booking never counts as the procedure itself being done. A procedure already done is sent as a normal procedure event without scheduled_date, and the pathway starts at its date.

Results and referrals. Some steps check that a result was given to the patient (for example "Results Communication" after a mammogram) or that a referral was made (for example a community resource referral after a positive social-needs screen). Put the date on the row of the result or screen: communication_date for when the result was given, referral_date for when the referral was made. CDQ adds a communication or referral event with that row's code on that date, and it meets the step that follows the result or screen. You can also send such events directly, as rows with event_type communication or referral and the code of the result or screen. A visit with the step's own codes (an office visit to discuss results) also counts. Results are due within 7 days of the result for screening pathways.

Vaccines. Immunization steps accept a vaccine given at a visit (the CPT vaccine code or the Medicare administration code, as a procedure, encounter or immunization event) or as a prescription. CVX codes count only when event_code_system is CVX, since CVX and RxNorm share small numbers.

Transitions of care. Discharge pathways (for example heart failure or pneumonia follow-up) start at the discharge. Send the discharge as an event (event_type discharge, or an encounter with encounter_type discharge), plus the principal diagnosis as a diagnosis event during the stay. A patient admitted in the last 30 days with a qualifying diagnosis but no discharge yet is not evaluated (nothing is due until discharge). Instead the response carries a pending_discharge recommendation with the admission date, so the patient isn't missed.

Recommendations. Some pathways have rules that suggest a next action from a result or a delay, for example considering another pathway. These come back in recommendations. They are suggestions only: they never count as deviations and never change step statuses.

Early and late. An event before the step's window opens is a premature_step (counted as done, but flagged). For windows that open before the trigger, such as pre-operative steps, only events up to 60 days before the window count as premature; older ones are treated as unrelated history. An event after the due date is a late_step. No event by the due date is a missing_step.

Optional steps (for example "if abnormal" follow-ups) are shown in step_statuses but never reported as deviations.

Errors

Errors return JSON {"detail": "<message>"}.

StatusWhenExample body
401No X-API-Key or bearer token{"detail": "X-API-Key or Bearer token required"}
401Key unknown or revoked{"detail": "Invalid or revoked API key"}
401Bearer token expired, or invalid{"detail": "Token expired"}, {"detail": "Invalid token"}
402Your subscription is paused (evaluations only; enrollment_preview still works){"detail": "This account's subscription is paused, so evaluations are unavailable. Resume the subscription from the Billing page to continue."}
403Plain HTTP{"detail": "HTTPS required for all CDQ endpoints"}
403Your role can't call this endpoint{"detail": "Insufficient permissions"}
403client_id is not your client{"detail": "Access denied — you can only access your own data"}
404A pathway ID isn't one your client can run (your own, or a library pathway your plan includes){"detail": "Pathway 8a1d2c3b-… not found for this client"}
413Body larger than the limit (25 MB by default){"detail": "Request body too large: send fewer patients per request"}
422Body isn't valid JSON or a required field is missing or has the wrong type{"detail": "Invalid request body: missing field event_type at line 9 column 5"}
422pathway_ids or patients empty{"detail": "pathway_ids and patients need at least one item"}
422An ID isn't a UUID{"detail": "client_id: Input should be a valid UUID"}
422A pathway exists but isn't approved{"detail": "Pathway 8a1d2c3b-… is not approved (status: draft)"}
422Bad patient_context value{"detail": "patient_context.patient_age must be an integer"}
422Submission window closed{"detail": "submission_id 6d1f… was first used more than 24 hours ago; start a new submission with a new submission_id"}
422enforce_assigned_scope problems{"detail": "enforce_assigned_scope=true requires include_recommended_when_prior=false"}
400as_of_date not YYYY-MM-DD{"detail": "as_of_date must be ISO 8601 (YYYY-MM-DD), got: 10/03/2025"}
500Unexpected server error{"detail": "Internal Server Error"}

Every response carries an X-Request-Id header. Quote it when you contact Preact about a request.

An error evaluating one patient on one pathway does not fail the request: that pair appears in patients_skipped with reason evaluation error (see server logs).

Other endpoints

Pathways by plan. Every client runs its own approved pathways. Library pathways depend on the plan: Per Pathway Run, Explorer and a free trial run the whole library; HEDIS runs the pathways that report HEDIS measures; Custom Pathways runs up to 10 library pathways the client chooses; HEDIS + Custom runs both. Choose them on the Billing page or with the selection endpoints below. You can read the steps and references of every pathway you can run. Building your own pathways (creating or editing them) comes with Custom Pathways, HEDIS + Custom and Explorer once paid; during a free trial or on Per Pathway Run those requests get 403, and pathways you built before keep running.

All /cdq/* endpoints use the same authentication. Pass your own client_id.

Method and pathReturns
GET /cdq/pathways/available?client_id=<uuid>Approved, active pathways you can evaluate: your own and the library pathways your plan includes (see Pathways by plan). {"pathways": [{"pathway_id", "pathway_name", "tier", "trigger_type", "description"}]}. Optional tier filter. Use these IDs in pathway_ids.
GET /cdq/clients/{client_id}/pathway-selectionsThe library pathways a custom plan chose: {"plan_type", "selection_count", "max_selections", "selections": [...]}. Add ?with_catalog=true for the whole library as catalog: [{"pathway_id", "pathway_name", "hedis"}].
POST /cdq/clients/{client_id}/pathway-selectionsChoose a library pathway ({"pathway_id": "<uuid>"}; client admins, up to 10). The Billing page does the same.
DELETE /cdq/clients/{client_id}/pathway-selections/{pathway_id}Remove a chosen pathway.
GET /cdq/billing/plans/{client_id}The plans on offer and yours: {"plan_type", "stripe_sub_status", "current_period_end", "cancel_at_period_end", "trial_days", "can_change", "plans": [{"plan_type", "display_name", "monthly_price_cents", "per_run_price_cents", "max_custom_pathways", "includes_hedis", "includes_all_pathways", "available", "current"}]}. Client admins.
POST /cdq/billing/plan/{client_id}Choose a plan ({"plan_type": "hedis_custom"}; client admins). action says what happened: checkout (no subscription yet: add a card at url, Stripe Checkout; the plan starts once Stripe confirms, free for trial_days on a first subscription), changed (the subscription moves to the new price now, prorated), ending (per_pathway: the subscription ends with the paid period) or resumed (your current plan again, undoing ending). 409 when there's nothing to change or payment is past due. The Billing page does the same.
GET /cdq/pathways/definitions?client_id=<uuid>Full pathway definitions: {"definitions": [...]}. Optional filters: status (approved, draft, pending_review, retired), is_active, trigger_type, limit (1–1000, default 100), offset.
GET /cdq/pathways/definitions/{pathway_id}/steps?client_id=<uuid>A pathway's steps, with type, codes (expected_code, cpt_codes, loinc_codes, drug_classes), timing, severity and conditions: {"pathway_id", "steps": [...]}. Useful for checking your codes against what a step looks for.
GET /cdq/pathways/definitions/{pathway_id}/references?client_id=<uuid>The evidence references behind a pathway's steps.
GET /health{"status": "healthy", "service": "cdq-api"}. No authentication.
GET /readyz{"status": "ready"}, or 503 when the database is unavailable. No authentication.

Code systems and licences

CDQ uses ICD-10-CM, SNOMED CT, LOINC, CPT/HCPCS and RxNorm codes in its pathways and accepts them in your data.

This material contains content from LOINC® (http://loinc.org). LOINC is copyright © Regenstrief Institute, Inc. and the Logical Observation Identifiers Names and Codes (LOINC) Committee and is available at no cost under the license at http://loinc.org/license. LOINC® is a registered United States trademark of Regenstrief Institute, Inc.

CPT® is a registered trademark of the American Medical Association, and CPT codes are used under licence.

Medications can be sent as RxNorm codes, or as NDC codes, which CDQ maps to RxNorm. Drug classes are built from RxNorm. This product uses publicly available data courtesy of the U.S. National Library of Medicine (NLM), National Institutes of Health, Department of Health and Human Services; NLM is not responsible for the product and does not endorse or recommend this or any other product.