List and retrieve coding evaluations
When Brellium runs coding evaluations for your organization, GET /v2/coding_evaluations lists them and GET /v2/coding_evaluations/{coding_eval_id} returns one, so you can bring the results into your own system. The results are the recommended evaluation and management (E/M) codes, the evaluated International Classification of Diseases (ICD) codes and the flags raised. Coding evaluations are read-only; the question responses are on the linked audit.
Prerequisites
- An access token in
$BRELLIUM_ACCESS_TOKEN, cached and reused (Authenticate with OAuth2 client credentials). - Optionally a
document_idoraudit_idto filter on. This page uses the sample audita1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d, its document0f8e7d6c-5b4a-4938-8271-605f4e3d2c1band the sample coding evaluation6f1c2b3a-4d5e-4f60-8a71-92b3c4d5e6f7. - With a live key the response contains protected health information (PHI); a sandbox key returns the sample coding evaluation.
Steps
List coding evaluations with a filter
Without filters, GET /v2/coding_evaluations returns every coding evaluation in your organization, newest first, 20 per page. A coding evaluation must match every filter you send.
| Parameter | Matches |
|---|---|
document_id |
One UUID. The parameter is not repeatable, unlike documents on audits. The page is empty when no coding evaluation covers the document. |
audit_id |
One UUID. The page holds only the coding evaluations that belong to this audit. |
status |
The value must match exactly. An unknown value returns an empty page with status 200. |
updated_after, updated_before, created_after, created_before |
The bounds are inclusive. Send them as RFC 3339 timestamps in UTC ending in Z; an offset such as +02:00 or a date alone returns 400 VALIDATION_ERROR. |
coding_eval_id (repeated or comma-separated), limit, starting_after, ending_before and include_total work as in Page through and filter lists.
The call below lists the complete coding evaluations that cover the sample document, up to 100 per page.
curl --get "https://api.brellium.com/v2/coding_evaluations" \
--data-urlencode "document_id=0f8e7d6c-5b4a-4938-8271-605f4e3d2c1b" \
--data-urlencode "status=complete" \
--data-urlencode "limit=100" \
--header "Authorization: Bearer $BRELLIUM_ACCESS_TOKEN" \
--write-out "HTTP %{http_code}\n"
const params = new URLSearchParams({
document_id: "0f8e7d6c-5b4a-4938-8271-605f4e3d2c1b",
status: "complete",
limit: "100",
});
const res = await fetch(
`https://api.brellium.com/v2/coding_evaluations?${params}`,
{
headers: { Authorization: `Bearer ${process.env.BRELLIUM_ACCESS_TOKEN}` },
},
);
if (!res.ok) {
const { error } = await res.json();
throw new Error(`${res.status} ${error.code}: ${error.message}`);
}
console.log(await res.json(), `HTTP ${res.status}`);
import BrelliumClient from "@brellium/api-client";
const client = new BrelliumClient({ oAuth2: process.env.BRELLIUM_ACCESS_TOKEN });
const codingEvaluations = await client.codingEvaluations.list({
document_id: "0f8e7d6c-5b4a-4938-8271-605f4e3d2c1b",
status: "complete",
limit: 100,
});
console.log(codingEvaluations);
import os
from brellium_api_client import BrelliumClient
client = BrelliumClient(o_auth2=os.environ["BRELLIUM_ACCESS_TOKEN"])
coding_evaluations = client.coding_evaluations.list(
document_id="0f8e7d6c-5b4a-4938-8271-605f4e3d2c1b",
status="complete",
limit=100,
)
print(coding_evaluations.to_json())
The full programs below page through every match and print each coding evaluation's coding_eval_id, status and recommended E/M base code.
// Keep credentials on the server; never in a browser or mobile app.
const token = process.env.BRELLIUM_ACCESS_TOKEN;
if (!token) throw new Error("BRELLIUM_ACCESS_TOKEN is not set");
const BASE_URL = "https://api.brellium.com";
// Only the fields this sample reads; the full shape is in the Response below
// and in the reference (/tag/coding-evaluations/get/v2/coding_evaluations).
type CodingEvaluation = {
coding_eval_id: string;
status: string;
em_evaluation: { recommended_base_code: string | null } | null;
};
type ListPage = {
object: "list";
data: CodingEvaluation[];
has_more: boolean;
};
type ApiError = {
error: { type: string; code: string; message: string; request_id?: string };
};
async function getPage(params: Record<string, string>): Promise<ListPage> {
const url = new URL("/v2/coding_evaluations", BASE_URL);
for (const [key, value] of Object.entries(params))
url.searchParams.set(key, value);
const res = await fetch(url, { headers: { Authorization: `Bearer ${token}` } });
if (!res.ok) {
const body = (await res.json()) as ApiError;
throw new Error(
`${res.status} ${body.error.code}: ${body.error.message} (request_id ` +
`${body.error.request_id})`,
);
}
return (await res.json()) as ListPage;
}
// Every evaluation matching the filters, across pages, newest first.
async function* listCodingEvaluations(
filters: Record<string, string>,
): AsyncGenerator<CodingEvaluation> {
let startingAfter: string | undefined;
for (;;) {
const page = await getPage({
...filters,
limit: "100",
...(startingAfter ? { starting_after: startingAfter } : {}),
});
yield* page.data;
if (!page.has_more || page.data.length === 0) return;
startingAfter = page.data[page.data.length - 1].coding_eval_id;
}
}
async function main() {
const filters = {
document_id: "0f8e7d6c-5b4a-4938-8271-605f4e3d2c1b",
status: "complete",
};
for await (const ce of listCodingEvaluations(filters)) {
const em = ce.em_evaluation;
console.log(
ce.coding_eval_id,
ce.status,
em ? em.recommended_base_code : "no E/M finding",
);
}
}
main();
# Keep credentials on the server; never in a browser or mobile app.
import os
from collections.abc import Iterator
import requests
TOKEN = os.environ["BRELLIUM_ACCESS_TOKEN"]
BASE_URL = "https://api.brellium.com"
HEADERS = {"Authorization": f"Bearer {TOKEN}"}
def raise_for_envelope(res: requests.Response) -> None:
if res.ok:
return
err = res.json()["error"]
raise RuntimeError(
f"{res.status_code} {err['code']}: {err['message']} "
f"(request_id {err.get('request_id')})"
)
def list_coding_evaluations(**filters: str) -> Iterator[dict]:
"""Every evaluation matching the filters, across pages, newest first."""
params: dict[str, str | int] = {**filters, "limit": 100}
while True:
res = requests.get(
f"{BASE_URL}/v2/coding_evaluations",
headers=HEADERS,
params=params,
timeout=30,
)
raise_for_envelope(res)
page = res.json()
yield from page["data"]
if not page["has_more"] or not page["data"]:
return
params["starting_after"] = page["data"][-1]["coding_eval_id"]
for ce in list_coding_evaluations(
document_id="0f8e7d6c-5b4a-4938-8271-605f4e3d2c1b",
status="complete",
):
em = ce["em_evaluation"]
print(
ce["coding_eval_id"],
ce["status"],
em["recommended_base_code"] if em else "no E/M finding",
)
The response is 200 with a list envelope (List coding evaluations). If Brellium runs no coding evaluations for your organization, you get { "object": "list", "data": [], "has_more": false }. The ids and values below are examples; the field names are exact.
{
"object": "list",
"data": [
{
// the id to copy (example)
"coding_eval_id": "6f1c2b3a-4d5e-4f60-8a71-92b3c4d5e6f7",
"object": "coding_evaluation",
// the linked audit: GET /v2/audits/{audit_id} for its responses
"audit_id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
// read this first
"status": "complete",
"reviewed_by": null,
"em_evaluation": {
// null unless status is "complete"
"em_eval_id": "0a1b2c3d-4e5f-4a6b-8c7d-8e9f0a1b2c3d",
"object": "em_evaluation",
"coding_status": "codable",
"uncodable_reason": null,
"score": 0.5,
"flags": ["Upcoded"],
"base_code_aligned": false,
"add_on_codes_aligned": true,
"problems_level": "moderate",
"data_level": "low",
"risk_level": "moderate",
"mdm_level": "moderate",
"time_based": false,
"encounter_time_minutes": null,
"upcoded": true,
"downcoded": false,
"submitted_base_code": "99215",
"submitted_add_on_codes": [],
"recommended_base_code": "99214",
"recommended_add_on_codes": [],
"problems": [
{
"problem_id": "1b2c3d4e-5f60-4a7b-8c9d-0e1f2a3b4c5d",
"category": "Stable, Chronic Illnesses",
"description": "Generalized anxiety disorder, stable"
}
],
"data": [],
"risk": [
{
"risk_id": "2c3d4e5f-6071-4b8c-9d0e-1f2a3b4c5d6e",
"category": "Prescription Drug Management",
"description": "Sertraline dose continued"
}
]
},
"icd_evaluation": {
// null unless status is "complete"
"icd_eval_id": "3d4e5f60-7182-4c9d-8e1f-2a3b4c5d6e7f",
"object": "icd_evaluation",
"score": 1,
"flags": [],
"hcc_model_name": null,
"icd_codes": [
{
"icd_code": "F41.1",
"hcc_code": null,
"criteria": [
{
"icd_criteria_id": "4e5f6071-8293-4da0-9f2a-3b4c5d6e7f80",
"criteria_name": "Assess",
"criteria_context": "Assessment lists generalized anxiety disorder.",
"is_criteria_met": true
}
]
}
]
},
// document_id values
"documents": ["0f8e7d6c-5b4a-4938-8271-605f4e3d2c1b"],
"display_info": [
{
"key": "date_of_service",
"title": "Date of service",
"value": "2026-09-24T02:34:54.489Z",
"format": "date"
}
],
"people": [
{
"person_id": "2a1b0c9d-8e7f-4a6b-9c5d-4e3f2a1b0c9d",
"role": "provider",
"role_title": "Provider",
"name": "Jordan Rivera"
}
],
"created_at": "2026-09-24T02:34:54.489Z",
"updated_at": "2026-09-24T02:37:12.105Z"
}
],
"has_more": false
}
To pull only what changed since your last run, use the overlapping updated_after window from Keep audits in sync with updated_after, with coding_eval_id as the upsert key.
Retrieve a coding evaluation by id
GET /v2/coding_evaluations/{coding_eval_id} returns the coding evaluation on its own, without a list envelope (Retrieve a coding evaluation). The call below fetches the sample coding evaluation.
curl \
"https://api.brellium.com/v2/coding_evaluations/6f1c2b3a-4d5e-4f60-8a71-92b3c4d5e6f7" \
--header "Authorization: Bearer $BRELLIUM_ACCESS_TOKEN" \
--write-out "HTTP %{http_code}\n"
const res = await fetch(
"https://api.brellium.com/v2/coding_evaluations/6f1c2b3a-4d5e-4f60-8a71-92b3c4d5e6f7",
{
headers: { Authorization: `Bearer ${process.env.BRELLIUM_ACCESS_TOKEN}` },
},
);
if (!res.ok) {
const { error } = await res.json();
throw new Error(`${res.status} ${error.code}: ${error.message}`);
}
console.log(await res.json(), `HTTP ${res.status}`);
import BrelliumClient from "@brellium/api-client";
const client = new BrelliumClient({ oAuth2: process.env.BRELLIUM_ACCESS_TOKEN });
const codingEvaluation = await client.codingEvaluations.retrieve(
"6f1c2b3a-4d5e-4f60-8a71-92b3c4d5e6f7",
);
console.log(codingEvaluation);
import os
from brellium_api_client import BrelliumClient
client = BrelliumClient(o_auth2=os.environ["BRELLIUM_ACCESS_TOKEN"])
coding_evaluation = client.coding_evaluations.retrieve(
"6f1c2b3a-4d5e-4f60-8a71-92b3c4d5e6f7"
)
print(coding_evaluation.to_json())
The full programs below return no coding evaluation on a 404 and raise any other error with its code, message and request_id. When status is complete, they print the E/M result and the ICD codes.
// Keep credentials on the server; never in a browser or mobile app.
const token = process.env.BRELLIUM_ACCESS_TOKEN;
if (!token) throw new Error("BRELLIUM_ACCESS_TOKEN is not set");
// Only the fields this sample reads; the full shape is in step 1.
type CodingEvaluation = {
coding_eval_id: string;
audit_id: string | null;
status: string;
em_evaluation: {
coding_status: "codable" | "uncodable";
uncodable_reason: string | null;
flags: string[];
submitted_base_code: string | null;
recommended_base_code: string | null;
} | null;
icd_evaluation: {
icd_codes: { icd_code: string; hcc_code: string | null }[];
} | null;
updated_at: string;
};
type ApiError = {
error: { type: string; code: string; message: string; request_id?: string };
};
// Returns null for a 404: no coding evaluation with this id that your token can
// read.
async function getCodingEvaluation(
codingEvalId: string,
): Promise<CodingEvaluation | null> {
const res = await fetch(
`https://api.brellium.com/v2/coding_evaluations/${codingEvalId}`,
{
headers: { Authorization: `Bearer ${token}` },
},
);
if (res.status === 404) return null;
if (!res.ok) {
const body = (await res.json()) as ApiError;
throw new Error(
`${res.status} ${body.error.code}: ${body.error.message} (request_id ` +
`${body.error.request_id})`,
);
}
return (await res.json()) as CodingEvaluation;
}
async function main() {
const ce = await getCodingEvaluation("6f1c2b3a-4d5e-4f60-8a71-92b3c4d5e6f7");
if (!ce) {
console.log("No coding evaluation with that id in this organization");
return;
}
if (ce.status !== "complete") {
console.log(
`Evaluation is ${ce.status}; em_evaluation and icd_evaluation are null ` +
`until complete`,
);
return;
}
const em = ce.em_evaluation;
if (!em) {
console.log("No E/M finding on this evaluation");
} else if (em.coding_status === "uncodable") {
console.log(`Uncodable: ${em.uncodable_reason}; flags ${em.flags.join(", ")}`);
} else {
console.log(
`E/M submitted ${em.submitted_base_code}, recommended ` +
`${em.recommended_base_code}`,
);
}
if (ce.icd_evaluation) {
console.log(
`ICD ${ce.icd_evaluation.icd_codes.map((c) => c.icd_code).join(", ")}`,
);
}
}
main();
# Keep credentials on the server; never in a browser or mobile app.
import os
import requests
TOKEN = os.environ["BRELLIUM_ACCESS_TOKEN"]
BASE_URL = "https://api.brellium.com"
def get_coding_evaluation(coding_eval_id: str) -> dict | None:
"""Returns None for a 404: no coding evaluation with this id that your token can
read.
"""
res = requests.get(
f"{BASE_URL}/v2/coding_evaluations/{coding_eval_id}",
headers={"Authorization": f"Bearer {TOKEN}"},
timeout=30,
)
if res.status_code == 404:
return None
if not res.ok:
err = res.json()["error"]
raise RuntimeError(
f"{res.status_code} {err['code']}: {err['message']} "
f"(request_id {err.get('request_id')})"
)
return res.json()
ce = get_coding_evaluation("6f1c2b3a-4d5e-4f60-8a71-92b3c4d5e6f7")
if ce is None:
print("No coding evaluation with that id in this organization")
elif ce["status"] != "complete":
print(
f"Evaluation is {ce['status']}; em_evaluation and icd_evaluation are "
f"null until complete"
)
else:
em = ce["em_evaluation"]
if em is None:
print("No E/M finding on this evaluation")
elif em["coding_status"] == "uncodable":
print(
f"Uncodable: {em['uncodable_reason']}; flags {', '.join(em['flags'])}"
)
else:
print(
f"E/M submitted {em['submitted_base_code']}, recommended "
f"{em['recommended_base_code']}"
)
icd = ce["icd_evaluation"]
if icd is not None:
print("ICD", ", ".join(c["icd_code"] for c in icd["icd_codes"]))
The response for the sample coding evaluation is the data[0] item from step 1. Before status is complete, the same 12 fields are present, and em_evaluation and icd_evaluation are null:
{
"coding_eval_id": "6f1c2b3a-4d5e-4f60-8a71-92b3c4d5e6f7",
"object": "coding_evaluation",
"status": "awaiting_audit", // not complete yet
"em_evaluation": null, // null until status is "complete"
"icd_evaluation": null, // null until status is "complete"
"updated_at": "2026-09-24T02:35:40.012Z"
// ... audit_id, reviewed_by, documents, display_info, people and created_at as in
// step 1
}
The API returns 404 NOT_FOUND (Coding evaluation not found) when your organization has no coding evaluation with this id; another organization's id returns 404 too. An id that is not a UUID returns 400 VALIDATION_ERROR with path: ["coding_eval_id"]. A new or changed coding evaluation can take a few seconds to appear at GET /v2/coding_evaluations/{coding_eval_id}. If a coding evaluation you expect returns 404, retry once after a short wait.
Read status before the results
em_evaluation and icd_evaluation can have values only when status is complete. The call below fetches the sample coding evaluation and prints its status, the E/M coding_status, the ICD codes and updated_at.
curl \
"https://api.brellium.com/v2/coding_evaluations/6f1c2b3a-4d5e-4f60-8a71-92b3c4d5e6f7" \
--header "Authorization: Bearer $BRELLIUM_ACCESS_TOKEN" \
| jq '{
status,
em: .em_evaluation.coding_status,
icd_codes: [.icd_evaluation.icd_codes[]?.icd_code],
updated_at
}'
const res = await fetch(
"https://api.brellium.com/v2/coding_evaluations/6f1c2b3a-4d5e-4f60-8a71-92b3c4d5e6f7",
{
headers: { Authorization: `Bearer ${process.env.BRELLIUM_ACCESS_TOKEN}` },
},
);
if (!res.ok) {
const { error } = await res.json();
throw new Error(`${res.status} ${error.code}: ${error.message}`);
}
const evaluation = await res.json();
console.log({
status: evaluation.status,
em: evaluation.em_evaluation?.coding_status ?? null,
icd_codes: (evaluation.icd_evaluation?.icd_codes ?? []).map(
(c: { icd_code: string }) => c.icd_code,
),
updated_at: evaluation.updated_at,
});
import BrelliumClient from "@brellium/api-client";
const client = new BrelliumClient({ oAuth2: process.env.BRELLIUM_ACCESS_TOKEN });
const evaluation = await client.codingEvaluations.retrieve(
"6f1c2b3a-4d5e-4f60-8a71-92b3c4d5e6f7",
);
console.log({
status: evaluation.status,
em: evaluation.em_evaluation?.coding_status ?? null,
icd_codes: (evaluation.icd_evaluation?.icd_codes ?? []).map((c) => c.icd_code),
updated_at: evaluation.updated_at,
});
import json
import os
from brellium_api_client import BrelliumClient
client = BrelliumClient(o_auth2=os.environ["BRELLIUM_ACCESS_TOKEN"])
evaluation = client.coding_evaluations.retrieve(
"6f1c2b3a-4d5e-4f60-8a71-92b3c4d5e6f7"
)
em = evaluation.em_evaluation
icd = evaluation.icd_evaluation
print(
json.dumps(
{
"status": evaluation.status,
"em": em.coding_status if em else None,
"icd_codes": [c.icd_code for c in icd.icd_codes] if icd else [],
"updated_at": evaluation.updated_at,
},
indent=2,
default=str,
)
)
{
"status": "complete",
"em": "codable",
"icd_codes": ["F41.1"],
"updated_at": "2026-09-24T02:37:12.105Z"
}
status can be any string. Today's values are todo, in_progress, awaiting_audit (waiting for its audit), complete and error. New values can appear, so branch on complete and treat every other value as unfinished. error isn't final either: Brellium can run the coding evaluation again, and it can then reach complete.
When status is complete, read the results as follows:
- When
coding_statusiscodable, comparesubmitted_base_codewithrecommended_base_codeand the*_add_on_codesarrays. Then readupcoded,downcoded, the four*_levelstrings,time_based, and theproblems,dataandriskelements behind their levels.flagsholds the display names of the raised flags in alphabetical order. - When
coding_statusisuncodable, onlyuncodable_reason,flagsandencounter_time_minuteshave values.uncodable_reasoncan take new values (todayno_problem_identified,visit_type_indeterminateorinsufficient_documentation), so store it as given. - A
completecoding evaluation can still haveem_evaluation: nulloricd_evaluation: nullwhen there is no E/M or ICD result to show. Handle each result on its own.
{
"em_eval_id": "0a1b2c3d-4e5f-4a6b-8c7d-8e9f0a1b2c3d",
"object": "em_evaluation",
"coding_status": "uncodable",
"uncodable_reason": "insufficient_documentation",
// example; flag names are your organization's
"flags": ["Insufficient Documentation"],
"encounter_time_minutes": 45
// ... every other field is null, or [] for the arrays
}
Fetch the linked audit for its responses
A coding evaluation has no responses; they belong to the audit named by audit_id (null when there is no audit). The call below fetches that audit and prints its status, score, flags and each response's question and answer.
curl "https://api.brellium.com/v2/audits/a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d" \
--header "Authorization: Bearer $BRELLIUM_ACCESS_TOKEN" \
| jq '{status, score, flags, responses: [.responses[] | {question, answer}]}'
const res = await fetch(
"https://api.brellium.com/v2/audits/a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
{
headers: { Authorization: `Bearer ${process.env.BRELLIUM_ACCESS_TOKEN}` },
},
);
if (!res.ok) {
const { error } = await res.json();
throw new Error(`${res.status} ${error.code}: ${error.message}`);
}
const audit = await res.json();
console.log({
status: audit.status,
score: audit.score,
flags: audit.flags,
responses: audit.responses.map((r: { question: string; answer: string }) => ({
question: r.question,
answer: r.answer,
})),
});
import BrelliumClient from "@brellium/api-client";
const client = new BrelliumClient({ oAuth2: process.env.BRELLIUM_ACCESS_TOKEN });
const audit = await client.audits.retrieve("a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d");
console.log({
status: audit.status,
score: audit.score,
flags: audit.flags,
responses: audit.responses.map((r) => ({
question: r.question,
answer: r.answer,
})),
});
import json
import os
from brellium_api_client import BrelliumClient
client = BrelliumClient(o_auth2=os.environ["BRELLIUM_ACCESS_TOKEN"])
audit = client.audits.retrieve("a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d")
print(
json.dumps(
{
"status": audit.status,
"score": audit.score,
"flags": audit.flags,
"responses": [
{"question": r.question, "answer": r.answer}
for r in audit.responses
],
},
indent=2,
)
)
{
"status": "complete",
"score": 0.6666666666666666,
"flags": ["Failed", "Missing Signature"],
"responses": [
{
"question": "Is the session note signed by the rendering provider?",
"answer": "No"
},
{
"question": "Does the note document the service start and end times?",
"answer": "Yes"
},
{ "question": "Which program does this note belong to?", "answer": "N/A" }
]
}
Check that the audit's own status is complete before reading score, flags or responses (Retrieve an audit by id). documents[] holds document_id values; fetch each document with Retrieve a document. people[].person_id is the id shared by the email recipient and user for that person, or null when the name isn't linked to a person (Link an audit's people to recipients and users).
Expected response
Every field of a coding evaluation is always present, and an array with no items is []. Lists can take a few seconds to include a new or changed coding evaluation. The list and retrieve endpoints can also return the previous version for a few seconds after a change, so compare updated_at with the value you stored.
Common mistakes
| Mistake | What you see | Fix |
|---|---|---|
Repeating document_id like documents on audits |
400 VALIDATION_ERROR, path: ["document_id"], message Invalid input: expected string, received array |
Send one document_id per request. With coding_eval_id values in hand, fetch several at once with a batch get (?coding_eval_id=<id>&coding_eval_id=<id>). |
Next
Retrieve an audit by id
Retrieve one audit, check status before trusting score and flags, handle 404 and 400.
Keep audits in sync with updated_after
Backfill once, then poll updated_after windows that overlap and upsert by id.
Migrate from v1
Move an integration from the v1 API to v2, one resource at a time.