This article is the complete reference for the Data Webhook payload that Lab Data sends for each processed document (data_structure: "lab_result_event").
Use it to build and test the handler that receives Lab Data results. For how to submit documents, see the Lab Data documentation.
Example data only Every identifier, laboratory name, and value in this article is fictional. Your payloads contain your own client_uuid, user_id, and document_id. |
Example request
Submit the document from your backend as multipart/form-data, with the file and timezone fields. This example uses the Sandbox base URL (https://api.lab.rook-connect.review). In Production, use https://api.lab.rook-connect.com.
curl -X POST \
"api.lab.rook- connect.review/client_uuid/$ROOK_CLIENT_UUID/user_id/$USER_ID" \
-u "$ROOK_CLIENT_UUID:$ROOK_SECRET_KEY" \
-F "file=@/path/to/laboratory_result.pdf" \
-F "timezone=-05:00"
The example reads your client_uuid and secret_key from the ROOK_CLIENT_UUID and ROOK_SECRET_KEY environment variables, so the credentials stay out of your source code and shell history.
The -u option builds the Authorization: Basic header from your client_uuid and secret_key. Never submit documents from a web browser or a mobile application, where the credentials would be exposed to end users.
If the request is valid, the endpoint returns 200 OK:
{
"document_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"status": "received"
}
Store the document_id. The same value arrives in the Data Webhook as laboratory_data.metadata.document_id_string.
Receiving the result
Lab Data results arrive at your Data Webhook with the same HMAC validation and retries as the rest of your Data Webhooks. Validate the X-ROOK-HASH header, respond with a 2xx status as soon as you receive the payload, and then process it asynchronously.
The result arrives in one of two formats, depending on how Lab Data is activated for your organization:
| ROOK JSON (default) | FHIR R4 (requires Clinical Ready) |
Structure | ROOK normalized JSON | HL7 FHIR R4 Bundle of type collection |
laboratory_data contains | metadata, panels_array, rejected_biomarkers_array | metadata, clinical_ready |
Rejected biomarkers | rejected_biomarkers_array | Observation resources with status: "cancelled" |
*FHIR R4 output for Lab Data requires the Clinical Ready add-on. Activate it from your ROOK Portal or through the ROOK Support team or your account manager.
Both formats share the same top-level fields:
Field | Type | Description |
client_uuid | string | Your ROOK client identifier. |
user_id | string | The user_id you sent in the request path. |
version | integer | Version of the event envelope. Current value: 2. |
document_version | integer | Version of the lab_result_event structure. Current value: 1. |
data_structure | string | Always lab_result_event. Use it to route Lab Data results in your webhook handler. |
laboratory_data | object | The processed laboratory result. Its content depends on the format. |
ROOK JSON reference
`laboratory_data.metadata`
Field | Type | Description |
datetime_string | string | Sample collection date and time as printed on the document, in ISO 8601 format. Includes the UTC offset when it is available, following the time zone rules described in Integrate Lab Data. |
document_id_string | string | The document_id returned when the document was submitted. |
user_id_string | string | The user_id associated with the document. |
performing_lab_string | string or null | Name and location of the laboratory that performed the analysis, when it appears in the document. |
sources_of_data_array | array of strings | Laboratory providers identified in the document. |
is_fasting_bool | boolean or null | Whether the sample was taken while fasting, when the document states it. |
`panels_array`
One entry per supported panel identified in the document. A single document can contain several panels.
Field | Type | Description |
panel_name_string | string | Name of the panel, for example Complete Blood Count. |
panel_code_string | string | Short panel code: CBC, CMP, LIPID, THYROID, or HBA1C. |
panel_loinc_code_string | string | LOINC code of the panel. |
biomarkers_array | array | Biomarkers of this panel that passed every validation. |
`biomakers_array`
Field | Type | Description |
biomarker_name_string | string | Name of the biomarker. |
loinc_code_string | string | LOINC code of the biomarker. See Supported panels and biomarkers. |
value_float | number | Result value, expressed in the canonical unit. |
unit_string | string | Unit of value_float. Always equal to canonical_unit_string. |
canonical_unit_string | string | Canonical unit of the biomarker. |
reference_range_low_float | number or null | Lower limit of the reference range printed on the document, converted to the canonical unit. |
reference_range_high_float | number or null | Upper limit of the reference range printed on the document, converted to the canonical unit. |
reference_range_unit_string | string or null | Unit of the reference range. |
status_string | string | Interpretation of the result: normal, low, high, critical_low, or critical_high. |
confidence_float | number | Extraction confidence, from 0.0 to 1.0. Biomarkers below the minimum confidence required by ROOK are moved to rejected_biomarkers_array. |
plausibility_flag | boolean | true when the value is physiologically possible but unusual, or inconsistent with a related biomarker of the same document. ROOK recommends reviewing these values before using them in clinical decisions. |
value_corrected_bool | boolean | Present only when ROOK adjusted value_float during validation to resolve a unit conversion inconsistency. Always true when present. |
original_value_float | number | Present only together with value_corrected_bool. The value before the adjustment, kept for traceability. |
`rejected_biomarkers_array`
Biomarkers found in the document that did not pass validation. The array is always present, and it is empty when every biomarker passed.
Field | Type | Description |
biomarker_name_string | string | Name of the biomarker as it appears in the document. |
loinc_code_string | string or null | LOINC code, when it could be identified. |
extracted_value_string | string | Value as extracted from the document. |
extracted_unit_string | string | Unit as extracted from the document. |
reason_string | string | Reason for the rejection. See the following table. |
confidence_float | number | Extraction confidence at the time of the rejection. |
reason_string | Meaning |
low_confidence | The value could not be extracted with the minimum confidence required by ROOK, or its structure was not valid. |
unsupported_biomarker | The biomarker is not part of the supported biomarkers. |
unknown_unit | The unit printed on the document could not be converted to the canonical unit. |
implausible_value | The value falls outside physiological limits. |
not_mapped | The result could not be mapped to a LOINC code, for example qualitative results or non-standard markers. |
Example ROOK JSON payload
The following document contains two panels (CBC and CMP) with accepted biomarkers, and one biomarker in rejected_biomarkers_array.
{
"client_uuid": "c2f4ce3b-8e6d-4b5f-9a3e-1d2c3b4a5f6e",
"user_id": "user_1234",
"version": 2,
"document_version": 1,
"data_structure": "lab_result_event",
"laboratory_data": {
"metadata": {
"datetime_string": "2026-03-15T08:30:00-05:00",
"performing_lab_string": "Example Clinical Laboratory - North Branch",
"is_fasting_bool": true,
"user_id_string": "user_1234",
"document_id_string": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"sources_of_data_array": ["Example Clinical Laboratory - North Branch"]
},
"panels_array": [
{
"panel_name_string": "Complete Blood Count",
"panel_code_string": "CBC",
"panel_loinc_code_string": "58410-2",
"biomarkers_array": [
{
"biomarker_name_string": "Hemoglobin",
"loinc_code_string": "718-7",
"value_float": 14.5,
"unit_string": "g/dL",
"canonical_unit_string": "g/dL",
"reference_range_low_float": 12.0,
"reference_range_high_float": 17.5,
"reference_range_unit_string": "g/dL",
"status_string": "normal",
"confidence_float": 0.98,
"plausibility_flag": false
},
{
"biomarker_name_string": "White Blood Cell Count",
"loinc_code_string": "6690-2",
"value_float": 5.05,
"unit_string": "10^3/uL",
"canonical_unit_string": "10^3/uL",
"reference_range_low_float": 4.5,
"reference_range_high_float": 11.0,
"reference_range_unit_string": "10^3/uL",
"status_string": "normal",
"confidence_float": 0.97,
"plausibility_flag": false
}
]
},
{
"panel_name_string": "Comprehensive Metabolic Panel",
"panel_code_string": "CMP",
"panel_loinc_code_string": "24323-8",
"biomarkers_array": [
{
"biomarker_name_string": "Blood Urea Nitrogen",
"loinc_code_string": "3094-0",
"value_float": 15.7,
"unit_string": "mg/dL",
"canonical_unit_string": "mg/dL",
"reference_range_low_float": 7.0,
"reference_range_high_float": 20.0,
"reference_range_unit_string": "mg/dL",
"status_string": "normal",
"confidence_float": 0.95,
"plausibility_flag": false,
"value_corrected_bool": true,
"original_value_float": 43.98
}
]
}
],
"rejected_biomarkers_array": [
{
"biomarker_name_string": "Vitamin B12",
"loinc_code_string": "2132-9",
"extracted_value_string": "250.0",
"extracted_unit_string": "pg/mL",
"reason_string": "unsupported_biomarker",
"confidence_float": 0.93
}
]
}
}
What to notice in this example
metadata carries the sample collection date and time with its UTC offset, the performing laboratory, and the document_id_string returned by the request.
panels_array groups accepted biomarkers by panel. Each biomarker has its LOINC code and its value in the canonical unit.
Blood Urea Nitrogen shows value_corrected_bool: true: ROOK adjusted the value during validation to resolve a unit conversion inconsistency, and original_value_float keeps the value before the adjustment. These fields are present only when an adjustment happens.
Vitamin B12 appears in rejected_biomarkers_array with unsupported_biomarker, because it is not one of the supported biomarkers.
FHIR R4 reference
In FHIR R4 mode, laboratory_data keeps metadata and replaces panels_array and rejected_biomarkers_array with clinical_ready, an HL7 FHIR R4 Bundle of type collection.
Resource | Cardinality | Content |
Patient | 1 | The user_id as identifier, with system urn:rook:user-id. |
Practitioner | 1 | The ordering provider of the laboratory study. Referenced from each DiagnosticReport. |
Organization | 1 | The laboratory that performed the analysis, from performing_lab_string. |
Observation (status: "final") | One per accepted biomarker | LOINC code, value, unit, reference range, and interpretation. |
DiagnosticReport | One per panel | Panel LOINC code, sample collection date and time, and references to the panel's Observation resources. |
Observation (status: "cancelled") | One per rejected biomarker | Biomarker name, with the rejection reason and extracted value in note. |
Each accepted biomarker maps to an Observation as follows:
ROOK JSON field | FHIR R4 field |
loinc_code_string | code.coding[0].code (system http://loinc.org) |
biomarker_name_string | code.coding[0].display and code.text |
value_float | valueQuantity.value |
canonical_unit_string | valueQuantity.unit, and valueQuantity.code in UCUM notation (for example, 10^3/uL becomes 10*3/uL) |
reference_range_low_float / reference_range_high_float | referenceRange[0].low / referenceRange[0].high |
status_string | interpretation[0].coding[0]: N (normal), L (low), H (high), LL (critical low), HH (critical high) |
confidence_float, plausibility_flag, value_corrected_bool, and original_value_float are not included in the FHIR R4 output.
Example FHIR R4 payload
This example is an excerpt: it shows the shared resources, one accepted biomarker with its DiagnosticReport, and one rejected biomarker. A real bundle contains one Observation per accepted biomarker and one DiagnosticReport per panel.
{
"client_uuid": "c2f4ce3b-8e6d-4b5f-9a3e-1d2c3b4a5f6e",
"user_id": "user_1234",
"version": 2,
"document_version": 1,
"data_structure": "lab_result_event",
"laboratory_data": {
"metadata": {
"datetime_string": "2026-03-15T08:30:00-05:00",
"performing_lab_string": "Example Clinical Laboratory - North Branch",
"is_fasting_bool": true,
"user_id_string": "user_1234",
"document_id_string": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"sources_of_data_array": ["Example Clinical Laboratory - North Branch"]
},
"clinical_ready": {
"resourceType": "Bundle",
"id": "d720e9b8-e108-4f26-b784-30b1382e7be8",
"type": "collection",
"timestamp": "2026-03-15T14:02:11Z",
"entry": [
{
"fullUrl": "urn:uuid:2680a059-6f3c-4c1e-9d0a-5b7e1f3c9a11",
"resource": {
"resourceType": "Patient",
"id": "2680a059-6f3c-4c1e-9d0a-5b7e1f3c9a11",
"identifier": [
{ "system": "urn:rook:user-id", "value": "user_1234" }
]
}
},
{
"fullUrl": "urn:uuid:7b1d2c44-0a9e-4f7b-8c61-2e5d9f0a3b22",
"resource": {
"resourceType": "Practitioner",
"id": "7b1d2c44-0a9e-4f7b-8c61-2e5d9f0a3b22"
}
},
{
"fullUrl": "urn:uuid:c93e5a10-4d2b-4b8f-a7e6-9f1c0d2e4b33",
"resource": {
"resourceType": "Organization",
"id": "c93e5a10-4d2b-4b8f-a7e6-9f1c0d2e4b33",
"name": "Example Clinical Laboratory - North Branch"
}
},
{
"fullUrl": "urn:uuid:1bb895f4-8e2a-4d6c-b3f1-7a9e0c5d2f44",
"resource": {
"resourceType": "Observation",
"id": "1bb895f4-8e2a-4d6c-b3f1-7a9e0c5d2f44",
"status": "final",
"code": {
"coding": [
{ "system": "http://loinc.org", "code": "6690-2", "display": "White Blood Cell Count" }
],
"text": "White Blood Cell Count"
},
"subject": { "reference": "urn:uuid:2680a059-6f3c-4c1e-9d0a-5b7e1f3c9a11" },
"valueQuantity": {
"value": 5.05,
"unit": "10^3/uL",
"system": "http://unitsofmeasure.org",
"code": "10*3/uL"
},
"referenceRange": [
{
"low": { "value": 4.5, "unit": "10^3/uL", "system": "http://unitsofmeasure.org", "code": "10*3/uL" },
"high": { "value": 11.0, "unit": "10^3/uL", "system": "http://unitsofmeasure.org", "code": "10*3/uL" }
}
],
"interpretation": [
{
"coding": [
{
"system": "http://terminology.hl7.org/CodeSystem/v3-ObservationInterpretation",
"code": "N",
"display": "Normal"
}
]
}
]
}
},
{
"fullUrl": "urn:uuid:5e2f8a91-3c7d-4e0b-9a14-6d8b2c1f0e55",
"resource": {
"resourceType": "DiagnosticReport",
"id": "5e2f8a91-3c7d-4e0b-9a14-6d8b2c1f0e55",
"status": "final",
"code": {
"coding": [
{ "system": "http://loinc.org", "code": "58410-2", "display": "Complete Blood Count" },
{ "system": "urn:rook:panel-code", "code": "CBC", "display": "Complete Blood Count" }
],
"text": "Complete Blood Count"
},
"subject": { "reference": "urn:uuid:2680a059-6f3c-4c1e-9d0a-5b7e1f3c9a11" },
"effectiveDateTime": "2026-03-15T08:30:00-05:00",
"performer": [
{ "reference": "urn:uuid:7b1d2c44-0a9e-4f7b-8c61-2e5d9f0a3b22" },
{ "reference": "urn:uuid:c93e5a10-4d2b-4b8f-a7e6-9f1c0d2e4b33" }
],
"result": [
{ "reference": "urn:uuid:1bb895f4-8e2a-4d6c-b3f1-7a9e0c5d2f44" }
]
}
},
{
"fullUrl": "urn:uuid:35489c90-7b1e-4a2d-8f3c-0e9d6a5b4c66",
"resource": {
"resourceType": "Observation",
"id": "35489c90-7b1e-4a2d-8f3c-0e9d6a5b4c66",
"status": "cancelled",
"code": { "text": "Vitamin B12" },
"subject": { "reference": "urn:uuid:2680a059-6f3c-4c1e-9d0a-5b7e1f3c9a11" },
"note": [
{ "text": "Rejected — reason: unsupported_biomarker. Extracted value: 250.0" }
]
}
}
]
}
}
}
Two timestamps appear in the bundle: timestamp is the time ROOK generated the bundle, and DiagnosticReport.effectiveDateTime is the sample collection date and time.
Route by data_structure Lab Dat FHIR R4 results arrive with data_structure: "lab_result_event" and the bundle is at laboratory_data.clinical_ready. The Clinical Ready add-on uses a different structure (data_structure: "clinical_ready") for wearable summaries. Route both by data_structure.