Important Notice
Please send an email to api@drchrono.com. Aside from our API scopes and User Permissions, a specialist will need to enable the Lab Vendor permission for your application to be able to POST to our lab APIs. Provide the name of your DrChrono API app and the name of the lab you are connecting to.
The DrChrono Lab API does NOT electronically send orders to a laboratory or receive results from one. The purpose of these endpoints is to allow a third-party lab system to push data into DrChrono.
DrChrono Lab API
Complete API Sequence Summary
| API Endpoint | Action | Purpose | |
| 1 | /api/sublabs | POST | One-time: Register your lab (save the id) |
| 2 | /api/lab_orders | POST | Create order record |
| 3 | /api/lab_documents | POST | [Optional] Upload requisition PDF (type=REQ) |
| 4 | /api/lab_tests | POST | Submit test panels |
| 5 | /api/lab_documents | POST | Upload result PDF (type=RES) |
| 6 | /api/lab_results | POST | Submit structured result values |
| 7 | /api/lab_orders/{id} | PATCH | Update order status to "R" (Results Received) |
Pre-Requisite:
- Email api@drchrono.com to request Lab Vendor permission for your app (provide your DrChrono API app name)
- Required OAuth scopes: labs:read labs:write settings:read settings:write users:read users:write
- Required user permission: "Share Patients" (From Account > Staff Permissions)
Sublab API
This is a one-time setup. The sublab ID is required when creating lab orders. The sublab is an identifier for your laboratory. For instance, I am looking to connect to a Lab called "Custom DRC Labs". I will first need to create a sublab for my lab and store it inside the DrChrono system.
Here is a POST call to accomplish a new sublab creation.
POST https://app.drchrono.com/api/sublabs{"facility_code": "00999CL","name": "Custom DRC Labs"}
Response:
{"id": 1084,"name": "Custom DRC Labs","facility_code": "00999CL","vendor_name": "Your Lab Vendor Name"}
NOTE:
- vendor_name is set by the DrChrono API Specialist when granting Lab Vendor permission. If you want a specific name, specify it in your support ticket.
- id is the value you'll use as `sublab` in all subsequent lab_orders calls.
- This endpoint is read-only for standard API consumers; the Lab Vendor permission enables write access.
Lab Order
Create a lab order record in the patient's chart. This represents an order that has been placed with your lab.
JSON example for submitting an order via API.
POST https://app.drchrono.com/api/lab_orders{"doctor": 319108,"patient": 124818685,"sublab": 1084,"status": "S","notes": "Fasting required. Patient advised no food 12 hours prior.","accession_number": "ACN-2025-0714-001","icd10_codes": [{"code": "E11.65"},{"code": "E78.5"}],"priority": "N","requisition_id": "REQ-78432","external_requisition_id": "EXT-LAB-99201"}
If you are including a lab requisition form, please use the api/lab_documents endpoint and set "type" to REQ.
curl --location 'https://app.drchrono.com/api/lab_documents' \--header 'Authorization: Bearer 123456' \--form 'document=@"/Users/your.macbook/Downloads/LAB DOCUMENT A.pdf"' \--form 'lab_order="11104895"' \--form 'type="REQ"'
The patient's lab order should show in the patient chart > Lab Orders.

Lastly, to update a status make a PATCH call to the lab_orders API.
PATCH https://app.drchrono.com/api/lab_orders/11104895{"status": "R"}
Here is a complete list of lab order status.
| Value | Note |
| N | Not Sent |
| A | ABN Required (Advance Beneficiary Notice) |
| S | Sent |
| R | Results Received |
| E | Error |
| P | Preliminary Results |
| Q | Queued |
| C | Canceled |
Field Definitions for api/lab_orders
Field Type Required Description UI Effect
| doctor | integer | Yes | DrChrono doctor ID | Shows as ordering provider on the lab order. |
| patient | integer | Yes | DrChrono patient ID | Order appears in this patient's chart under Lab Orders |
| sublab | integer | Yes | The sublab ID | N/A |
| status | string (1 char) | No (default: "N") | Current status of the order | Displayed in the "Status" column of the lab orders table |
| notes | text | No | Free-text notes about the order | Visible when viewing order details |
| accession_number | string (max 70) | No | The lab's unique tracking number for this specimen/order | Displayed in order details. Used to correlate with external lab systems |
| icd10_codes | array of objects | No | Diagnosis codes associated with the order. Each object must have a `code` field with a valid ICD-10 code | Shows in the "Tests" column as the description text |
| priority | string (1 char) | No | `"N"` = Normal, `"S"` = STAT (urgent) | Indicates urgency of the order |
| requisition_id | string (max 100) | No | Your internal requisition identifier | Stored for reference/correlation |
| external_requisition_id | string (max 100) | No | External system requisition ID | Stored for cross-system tracking |
Lab Tests
Submit the individual test panels/components for an order. Each test represents a grouping of results (e.g., "Complete Blood Count", "Comprehensive Metabolic Panel"). You can submit multiple tests per order.
JSON example
POST https://app.drchrono.com/api/lab_tests[{"lab_order": 11104895,"code": "58410-2","name": "Complete Blood Count (CBC)","description": "CBC with Differential","collection_date": "2025-07-14T08:30:00","internal_notes": "Specimen collected at office. Tube type: EDTA lavender top.","report_notes": "Results reviewed and verified by lab director.","status": "F","specimen_source": "Blood","specimen_condition": "Satisfactory","specimen_total_volume": 5.0},{"lab_order": 11104895,"code": "24323-8","name": "Comprehensive Metabolic Panel (CMP)","description": "CMP-14","collection_date": "2025-07-14T08:30:00","internal_notes": "Fasting specimen confirmed.","report_notes": "All analytes within reference methodology limits.","status": "F","specimen_source": "Serum","specimen_condition": "Satisfactory","specimen_total_volume": 7.5}]
Field Definitions for api/lab_tests
Field Type Required Description UI Effect
| lab_order | integer | Yes | The lab order ID this test belongs to | Links test to the order in the patient chart |
| code | string (max 16) | No | LOINC code or your lab's internal panel code. Used to group results under this test. | Displayed as the panel identifier. Used for grouping results in the plotter |
| name | string (max 100) | No | Name of the test panel | Shown as the panel/test name in the results table header |
| description | string (max 200) | No | Description of what this test covers | Shows in the "Tests" column on the lab orders list |
| collection_date | datetime | No | When the specimen was collected. Format: `YYYY-MM-DDTHH:MM:SS` | Used as the timestamp for trending/plotting results over time. Critical for the plotter X-axis. |
| internal_notes | text | No | Internal notes visible to staff | Shown in test detail view |
| report_notes | text | No | Notes that appear on the report | Displayed with the test results |
| status | string (1 char) | No | Status of this test | Determines whether results are considered preliminary or final |
| specimen_source | string (max 100) | No | Source of the specimen (e.g., Blood, Urine, Serum, Saliva) | Displayed in test details |
| specimen_condition | string (max 100) | No | Condition of the specimen (e.g., Satisfactory, Hemolyzed, Lipemic) | Displayed in test details |
| specimen_total_volume | float | No | Volume of specimen in mL | Displayed in test details |
Lab Document
Upload PDF documents (requisition forms or result reports) and attach them to a lab order.
Important: The `id` from the RES document upload is required when submitting structured lab results.
curl --location 'https://app.drchrono.com/api/lab_documents' \--header 'Authorization: Bearer 123456' \--form 'document=@"/Users/your.macbook/Downloads/LAB DOCUMENT B.pdf"' \--form 'lab_order="11104895"' \--form 'type="RES"'
The DrChrono patient chart orders page should look like this.

The "type" field will determine the type of document upload. Here is a complete list of the "type" values.
| Value | Note |
| REQ | Requisition Form |
| RES | Lab Results |
| R-A | Requisition Form and ABN |
| ABN | ABN (Advance Beneficiary Notice) |
Lab Results
Submit the individual structured result values (observations) for each test. This is what populates the results table AND the graphical plotter in the patient chart.
POST https://app.drchrono.com/api/lab_results[{"lab_test": 156196635,"document": 17836725,"status": "F","observation_code": "6690-2","observation_description": "White Blood Cell Count","test_performed": "2025-07-14T14:30:00","value": "7.2","value_is_numeric": true,"unit": "10*3/uL","normal_range": "4.5 11.0","abnormal_status": "N","is_abnormal": false,"comments": "Within normal limits."},{"lab_test": 156196635,"document": 17836725,"status": "F","observation_code": "789-8","observation_description": "Red Blood Cell Count","test_performed": "2025-07-14T14:30:00","value": "5.1","value_is_numeric": true,"unit": "10*6/uL","normal_range": "4.7 6.1","abnormal_status": "N","is_abnormal": false,"comments": ""},{"lab_test": 156196635,"document": 17836725,"status": "F","observation_code": "718-7","observation_description": "Hemoglobin","test_performed": "2025-07-14T14:30:00","value": "11.8","value_is_numeric": true,"unit": "g/dL","normal_range": "12.0 17.5","abnormal_status": "L","is_abnormal": true,"comments": "Slightly below reference range. Consider iron studies."},{"lab_test": 156196636,"document": 17836725,"status": "F","observation_code": "2345-7","observation_description": "Glucose","test_performed": "2025-07-14T14:30:00","value": "105","value_is_numeric": true,"unit": "mg/dL","normal_range": "70.0 99.0","abnormal_status": "H","is_abnormal": true,"comments": "Elevated. Fasting confirmed. Recommend follow-up A1C."}]
Field Definitions for api/lab_results
Field Type Required Description UI Effect Plotter Impact
| lab_test | integer | Yes | The lab test ID this result belongs to | Groups results under the correct test panel in the results table | Determines panel grouping in chart |
| document | integer | Yes | The lab document ID (from step 4, type=RES) | Links the result to the PDF report. Clicking the document link opens this PDF | None directly |
| status | string (1 char) | Yes | Result status. Same values as test status (F, P, C, I, X) | Shown in result detail. "F" indicates verified final result | Only `F` and `C` results are considered definitive |
| observation_code | string (max 16) | No | LOINC code for this specific observation (e.g., "6690-2" for WBC) | Displayed as identifier | Critical for trending. Results with the same `observation_code` across multiple orders are plotted together on the same chart over time |
| observation_description | string (max 200) | No | Name (e.g., "White Blood Cell Count") | Shown as the row label in the results table and as the chart title | Chart title |
| test_performed | datetime | Yes | When the test/analysis was performed. Format: `YYYY-MM-DDTHH:MM:SS` | Shown in result details | Used as the X-axis data point on the plotter chart |
| value | string (max 100) | Yes | The result value (e.g., "7.2", "Positive", "Non-reactive") | Displayed in the "Value" column | The Y-axis data point when numeric |
| value_is_numeric | boolean | Yes | Whether the value should be treated as a number | Determines display formatting | Controls whether the plotter renders a chart. If `false`, no chart is generated for this observation. Only numeric results get plotted |
| unit | string (max 16) | No | Unit of measurement (e.g., "mg/dL", "10*3/uL", "g/dL") | Shown next to the value | Displayed on the Y-axis label |
| normal_range | string | No | Reference range. When `value_is_numeric` is `true`, format as `"<lower> <upper>"` (e.g., `"70.0 99.0"`). When not numeric, provide as descriptive text (e.g., `"Negative"`) | Displayed in "Reference Range" column | Defines the shaded normal band on the chart. The plotter draws a gray band from `lower` to `upper`. Values outside the band are visually abnormal |
| abnormal_status | string | No | Coded abnormal flag. See table below | Displayed with color coding (red for abnormal) | Affects the abnormal indicator on data points |
| is_abnormal | boolean | No | Whether this result is abnormal | Row is highlighted/flagged when `true`. Panel header shows abnormal indicator | Data point may be colored differently on chart |
| comments | text | No | Comments/notes about this specific result | Shown in result details and as tooltip on chart hover | Appears in chart tooltip |
| group_code | string | No | Alternative grouping code (maps to internal `result_code`) | Used for panel-level grouping if present | Can affect which panel a result is displayed under |
| specimen_received | datetime | No | When the lab received the specimen | Stored for reference | Not directly used in plotter |
Abnormal Status Values
| Value | Meaning | Visual Indicator |---------------------------------------| `N` | Normal | No flag || `L` | Low | Below range flag || `LL` | Alert Low | Critical low flag || `H` | High | Above range flag || `HH` | Alert High | Critical high flag || `<` | Panic Low | Critical alert || `>` | Panic High | Critical alert || `A` | Abnormal | General abnormal flag || `AA` | Very Abnormal | Critical abnormal flag || `S` | Susceptible | Microbiology || `R` | Resistant | Microbiology || `I` | Intermediate | Microbiology || `NEG` | Negative | Negative finding || `POS` | Positive | Positive finding || (empty) | No Comment | No indicator |
How normal_range works with the Plotter.
When `value_is_numeric` is `true`:
- Format: `"<lower_bound> <upper_bound>"` (space-separated floats)
- Example: `"70.0 99.0"` means normal range is 70.0 to 99.0
- The plotter draws a **shaded band** between these values representing the normal zone
- The Y-axis auto-scales to show the range plus 5% padding above/below
- Values falling **outside** the shaded band are visually abnormal
When `value_is_numeric` is `false`:
- Provide as descriptive text (e.g., `"Negative"`, `"Non-Reactive"`)
- **No chart is rendered** for non-numeric results
- The range text is displayed as-is in the reference column
How the Plotter Trends Results Over Time.
The plotter groups results by `observation_code`. When the same patient has multiple lab orders over time with results sharing the same `observation_code`:
- All values are plotted on a single spline chart
- X-axis = `collection_date` (from the parent lab_test) or `test_performed`
- Y-axis = `value` (numeric)
- The normal range band persists across all data points
- This allows providers to see trends (e.g., glucose trending upward over 6 months)
Lab Webhook
The lab order API has a webhook for when the order was created, modified, and deleted. You can subscribe to those events from the API page (Account > API).
Webhook Events:
| Event | Fires When |----------------------| `LAB_ORDER_CREATE` | A lab order is created (via UI or API) || `LAB_ORDER_MODIFY` | A lab order is modified (status change, etc.) || `LAB_ORDER_DELETE` | A lab order is deleted |

Reference
https://app.drchrono.com/api-docs/#tag/Clinical/operation/sublabs_create
https://app.drchrono.com/api-docs/#tag/Clinical/operation/lab_orders_create
https://app.drchrono.com/api-docs/#tag/Clinical/operation/lab_documents_create
https://app.drchrono.com/api-docs/#tag/Clinical/operation/lab_tests_create
https://app.drchrono.com/api-docs/#tag/Clinical/operation/lab_results_create