Skip to content

Batches

A batch is up to 100 notes analyzed in the background. You create it in one request, then check on it until every note has finished. There are no webhooks; your code polls.

How batches work

  1. You send the notes. The API checks your balance, holds one credit per note, queues every note, and answers 202 at once with the batch ID.
  2. The notes run in the background. Each note moves from queued to running, then to succeeded, failed, or out_of_scope.
  3. You poll the batch. When every note has finished, the batch's finished_at is set.
  4. You read each finished note with GET /v1/analyses/{id}, the same as a single analysis.

Only notes that succeed are charged. The held credit for a note that fails or is out of scope returns to your balance.

Limits:

  • A batch has 1 to 100 notes. Each note follows the same rules as a single analysis, including 20 to 100,000 characters.
  • The request body can be at most 12 MB.
  • An organization can have at most 5 unfinished batches at a time, including batches started in the web app.
  • Creating a batch counts as one call toward the per-minute rate limit, however many notes it has. For more information, see Rate limits.
  • Notes that end out of scope or fail count toward your organization's limit of 25 uncharged notes a day, like single analyses. For more information, see Uncharged notes.

Create a batch

POST/v1/batches

FieldTypeDescription
itemsarray of objectsRequired. 1 to 100 notes. Each item takes the same fields as the analysis request body, except test_data: document_text (required), cpts, icds, jurisdiction, visit_type, provider_type, patient_demographics, active_problems, and client_reference.
labelstringYour name for the batch, up to 120 characters.
test_databooleanRequired as true while your organization is in test mode. Default false.

You can send an Idempotency-Key header, as with a single analysis. For more information, see Idempotency.

curl -s https://api.medchartscan.io/v1/batches \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 0d6f3a52-1c7e-4b8a-a4f1-93e2c5b7d018" \
  -d '{
    "label": "Clinic day 2026-10-25",
    "items": [
      {"document_text": "Established patient seen for follow-up of type 2 diabetes and hypertension. Reports good adherence to metformin; no hypoglycemia. BP 138/86. A1c 7.4% reviewed. Assessment: diabetes, improving; hypertension, not at goal. Plan: increase lisinopril to 20 mg daily, recheck BMP in 2 weeks, follow up in 3 months.", "jurisdiction": "TX", "client_reference": "enc-0001"},
      {"document_text": "New patient with acute low back pain after lifting, no red flags. Exam: paraspinal tenderness, normal strength and reflexes. Plan: NSAIDs, activity as tolerated, return if worse.", "client_reference": "enc-0002"}
    ]
  }'
202 Accepted
{
  "id": "c29da7b5-0b37-4ea6-8db5-24f7d96f4c8e",
  "label": "Clinic day 2026-10-25",
  "source": "api",
  "is_test": false,
  "created_at": "2026-10-25T05:09:30.425542Z",
  "finished_at": null,
  "created_by": "Epic integration (prod)",
  "counts": {"queued": 2, "running": 0, "succeeded": 0, "failed": 0, "out_of_scope": 0},
  "items": [
    {"id": "088d3c79-485d-4131-bbd6-f54a9188bad8", "client_reference": "enc-0001", "created_at": "2026-10-25T05:09:30.425542Z", "status": "queued", "final_cpt_code": null, "retryable": false, "submitted_code": null, "coding_change": null, "missed_revenue_count": null, "denial_risk_count": null},
    {"id": "997aecf7-4ac2-4c79-a1bd-0e8f30047b88", "client_reference": "enc-0002", "created_at": "2026-10-25T05:09:30.425542Z", "status": "queued", "final_cpt_code": null, "retryable": false, "submitted_code": null, "coding_change": null, "missed_revenue_count": null, "denial_risk_count": null}
  ]
}

Items are in the order you sent them. Each item's id is an analysis ID, and its created_at is when that attempt was submitted: a retried note shows the time of its retry.

Errors

StatusCodeCause
400invalid_requestNo items, more than 100 items, or an invalid field (the message names it).
402insufficient_creditsThe balance doesn't cover every note. Nothing is stored or held.
403baa_resign_requiredThe organization is paused until an owner signs the updated BAA.
409idempotency_conflict, idempotency_in_progressSee Idempotency.
413note_too_longA note is longer than 100,000 characters.
413request_too_largeThe request body is larger than 12 MB.
422test_data_requiredThe organization is in test mode and the request didn't send "test_data": true.
429rate_limitedThe per-minute limit is reached. Wait for Retry-After seconds.
429too_many_batchesThe organization already has 5 unfinished batches. Wait for one to finish.
429too_many_uncharged_runs25 of your organization's notes ended out of scope or failed in the last 24 hours, or the batch would put more notes in progress than the uncharged limit allows. Wait for Retry-After seconds, or send a smaller batch. Retrying failed notes gets the same answer.

Check on a batch

GET/v1/batches/{id}

Returns the batch with its status counts and every note, in the order you sent them. Poll it every 5 to 10 seconds until finished_at isn't null. You can open each note as soon as its status is succeeded, without waiting for the whole batch.

curl -s https://api.medchartscan.io/v1/batches/$BATCH_ID \
  -H "Authorization: Bearer $ACCESS_TOKEN"

A finished batch where one note failed:

200 OK
{
  "id": "c29da7b5-0b37-4ea6-8db5-24f7d96f4c8e",
  "label": "Clinic day 2026-10-25",
  "source": "api",
  "is_test": false,
  "created_at": "2026-10-25T05:09:30.425542Z",
  "finished_at": "2026-10-25T05:09:30.483722Z",
  "created_by": "Epic integration (prod)",
  "counts": {"queued": 0, "running": 0, "succeeded": 1, "failed": 1, "out_of_scope": 0},
  "items": [
    {"id": "088d3c79-485d-4131-bbd6-f54a9188bad8", "client_reference": "enc-0001", "created_at": "2026-10-25T05:09:30.425542Z", "status": "failed", "final_cpt_code": null, "retryable": true, "submitted_code": null, "coding_change": null, "missed_revenue_count": null, "denial_risk_count": null},
    {"id": "997aecf7-4ac2-4c79-a1bd-0e8f30047b88", "client_reference": "enc-0002", "created_at": "2026-10-25T05:09:30.425542Z", "status": "succeeded", "final_cpt_code": "99214", "retryable": false, "submitted_code": "99213", "coding_change": "upgraded", "missed_revenue_count": 1, "denial_risk_count": 0}
  ]
}
FieldDescription
idThe batch ID.
labelYour name for the batch, or null.
sourceapi for batches created through the API.
is_testtrue for a batch created in test mode.
created_atWhen the batch was created.
finished_atWhen the last note finished; null while any note is queued or running.
created_byThe label of the API key that created the batch; null if the key no longer exists.
countsThe number of notes in each status.
itemsEvery note: its analysis id, your client_reference, status, final_cpt_code once it succeeded, retryable, and the review fields submitted_code, coding_change, missed_revenue_count, and denial_risk_count (null until the note succeeds; see Analyses).

To review a batch, start with the notes whose missed_revenue_count or denial_risk_count is above zero, and those whose coding_change is downgraded. To find them across batches, use Search results with "channel": "api_batch".

retryable is true for a failed note that you can still retry. If a note can't start within 6 hours, it fails, its held credit returns to your balance, and you can retry it.

A batch that doesn't exist, belongs to another organization, or was created in the web app returns 404 not_found.

List batches

GET/v1/batches

Lists the batches created through the API in your organization, newest first, with their counts but without their notes. It takes limit (1 to 100, default 50) and cursor.

curl -s "https://api.medchartscan.io/v1/batches?limit=10" \
  -H "Authorization: Bearer $ACCESS_TOKEN"
200 OK
{
  "items": [
    {"id": "c29da7b5-0b37-4ea6-8db5-24f7d96f4c8e", "label": "Clinic day 2026-10-25", "source": "api", "is_test": false, "created_at": "2026-10-25T05:09:30.425542Z", "finished_at": "2026-10-25T05:09:30.483722Z", "item_count": 2, "counts": {"queued": 0, "running": 0, "succeeded": 1, "failed": 1, "out_of_scope": 0}}
  ],
  "next_cursor": null
}

Retry failed notes

POST/v1/batches/{id}/retry

Queues failed notes again. A failed note keeps its text for 7 days so that you can retry it; after that, it can't be retried. Each retried note holds a new credit and gets a new analysis ID in the same position of items. Notes that were out of scope are never retried.

The body is optional:

  • No body, {}, or {"analysis_ids": null} retries every failed note that's still retryable.
  • {"analysis_ids": ["..."]} retries only those notes (1 to 100 IDs). Every listed note must be retryable.
curl -s -X POST https://api.medchartscan.io/v1/batches/$BATCH_ID/retry \
  -H "Authorization: Bearer $ACCESS_TOKEN"

The response is 200 with the batch. The retried note has a new ID and is queued again:

200 OK
{
  "id": "c29da7b5-0b37-4ea6-8db5-24f7d96f4c8e",
  "label": "Clinic day 2026-10-25",
  "source": "api",
  "is_test": false,
  "created_at": "2026-10-25T05:09:30.425542Z",
  "finished_at": null,
  "created_by": "Epic integration (prod)",
  "counts": {"queued": 1, "running": 0, "succeeded": 1, "failed": 0, "out_of_scope": 0},
  "items": [
    {"id": "4be72810-efa0-43ad-9dfc-61b4451cf385", "client_reference": "enc-0001", "created_at": "2026-10-25T05:14:02.118407Z", "status": "queued", "final_cpt_code": null, "retryable": false, "submitted_code": null, "coding_change": null, "missed_revenue_count": null, "denial_risk_count": null},
    {"id": "997aecf7-4ac2-4c79-a1bd-0e8f30047b88", "client_reference": "enc-0002", "created_at": "2026-10-25T05:09:30.425542Z", "status": "succeeded", "final_cpt_code": "99214", "retryable": false, "submitted_code": "99213", "coding_change": "upgraded", "missed_revenue_count": 1, "denial_risk_count": 0}
  ]
}

If nothing is retryable and you didn't list IDs, the response is 200 with the batch unchanged.

StatusCodeCause
400invalid_requestanalysis_ids is empty, lists more than 100 IDs, or has an ID that isn't valid.
402insufficient_creditsThe balance doesn't cover every note to retry. Nothing changes.
403baa_resign_requiredThe organization is paused until an owner signs the updated BAA.
404not_foundThe batch isn't visible to your keys, or a listed ID isn't in the batch.
409not_retryableA listed note didn't fail, or its 7-day window has passed. Nothing changes.
429too_many_batchesThe batch had finished, and retrying it would make a sixth unfinished batch.

Delete batch results

There's no endpoint that deletes a whole batch. Delete each note with DELETE /v1/analyses/{id}. Deleting a note that's still queued stops it from running and returns its held credit. A note that's running can't be deleted (409 analysis_running): delete it once it has finished.

Batches ยท MedChartScan E/M