How to retrieve Quest lab results programmatically

With LabLink, Quest results are pushed to you rather than pulled. When results are posted to an order, LabLink sends a signed order.results_final webhook to your endpoint. It carries Quest's own results message, HL7 v2 ORU^R01 parsed to JSON without interpretation, and the PDF report.

GET /orders/{id} tells you when an order has reached results_final, but the results themselves arrive in the event: no API endpoint returns them. This guide covers the event, how to read the HL7 JSON, corrected results, and handling results safely.

How results reach you

  1. You place the order with POST /orders. Its status is created.
  2. When Quest has the requisition, LabLink sends order.awaiting_collection. Download the requisition PDF the patient brings to the draw with GET /orders/{id}/requisition.
  3. The patient is drawn and Quest runs the tests.
  4. When results are posted, LabLink sends order.results_final with the results message and PDF report, and the order's status becomes results_final.

The order.results_final event

Field What it holds
idThe event id. The same order and event always have the same id: dedupe on it.
typeorder.results_final
environmentsandbox or production
testtrue for a test event sent from the console
data.orderIdThe order. Read it with GET /orders/{id}.
data.results.formatAlways hl7v2+json
data.results.messagesQuest's results message, every segment in order, every field under its HL7 position. Usually one; more when the lab network holds several for the order.
data.results.reportsThe PDF report: filename, contentType, base64, and source (hl7 when Quest embedded it in the message, lab_network otherwise)

A shortened sandbox test event, with the base64 cut short:

order.results_final · JSON
{
  "id": "evt_8a1d5c3e9b7f2a6d4c0e1b9f7a3d5c2e",
  "object": "event",
  "type": "order.results_final",
  "environment": "sandbox",
  "createdAt": "2026-10-21T15:06:12.000Z",
  "test": true,
  "data": {
    "orderId": "0",
    "status": "results_final",
    "results": {
      "format": "hl7v2+json",
      "messages": [
        {
          "encoding": { "field": "|", "component": "^", "repetition": "~", "escape": "\\", "subcomponent": "&" },
          "segments": [
            { "segment": "MSH", "fields": { "3": "LAB", "4": "QUEST DIAGNOSTICS", "9": ["ORU", "R01"], "12": "2.5.1" } },
            { "segment": "PID", "fields": { "1": "1", "5": ["SAMPLE", "TEST"], "7": "19000101", "8": "U" } },
            { "segment": "OBR", "fields": { "1": "1", "4": ["91986", "DONOR, CHAGAS SCREEN", "99QDI"], "25": "F" } },
            { "segment": "OBX", "fields": { "1": "1", "2": "ST", "3": ["86011607", "DONOR, CHAGAS SCREEN", "99QDI"], "5": "NONREACTIVE", "7": "NONREACTIVE", "8": "N", "11": "F" } },
            { "segment": "NTE", "fields": { "1": "1", "2": "L", "3": "This is a test event. No patient or order exists." } },
            { "segment": "OBX", "fields": { "1": "2", "2": "ED", "3": ["ClinicalPDFReport1", "Clinical PDF Report TEST000000-1", "99QDI"], "11": "F" } }
          ]
        }
      ],
      "reports": [
        { "filename": "ClinicalPDFReport1.pdf", "contentType": "application/pdf", "source": "hl7", "base64": "JVBERi0xLjQK" }
      ]
    }
  }
}

Reading the HL7 JSON

A starting point for turning the event into rows. It skips the embedded PDF (OBX type ED), which is also in reports:

Observations from order.results_final · JavaScript
function observations(event) {
  const rows = [];
  for (const message of event.data.results.messages) {
    let orderedTest = null;
    let last = null;
    for (const { segment, fields } of message.segments) {
      if (segment === 'OBR') orderedTest = fields['4'];
      if (segment === 'OBX' && fields['2'] !== 'ED') {
        last = {
          orderedTest,
          observation: fields['3'],
          value: fields['5'],
          units: fields['6'],
          referenceRange: fields['7'],
          abnormalFlags: fields['8'],
          status: fields['11'], // F final, C corrected
          comments: []
        };
        rows.push(last);
      }
      if (segment === 'NTE' && last) last.comments.push(fields['3']);
    }
  }
  return rows;
}

Delivery rules

Handling results safely

Questions

Can I poll for results instead of using webhooks?

You can poll GET /orders/{id} to see when an order reaches results_final, but the results themselves are delivered in the order.results_final webhook. Register a webhook endpoint to receive them.

What happens when Quest corrects a result?

A corrected result is a new message from Quest, so it arrives as a new order.results_final event with a new id. Its OBX-11 result status is C. The same message delivered twice keeps the same id.

Can I fetch results again later through the API?

Not today. No API endpoint returns results: they are delivered in the order.results_final event, so store them when it arrives, as you would any patient record.

Can I test results handling in sandbox?

Yes. Register a sandbox webhook endpoint and send a test event from the LabLink console. Test events have test set to true and an orderId of 0.

Next step

Read the webhook reference, then register a sandbox endpoint and send yourself a test results event.

Related: How to order Quest labs through an API