> For the complete documentation index, see [llms.txt](https://docs.tryterra.co/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.tryterra.co/lab-reports/quickstart.md).

# Quick Start

> ⚠️ **Pre-Release**
>
> This page is currently under active development and is provided in a pre-release state.
>
> Some content may evolve as we continue to iterate on the implementation based on your feedback, but the core concepts and functionality are expected to remain consistent.
>
> The page will be marked as general release in the near future

## Prerequisites

* A Terra developer account with a `dev-id` and `x-api-key` (get these from the [Terra Dashboard](https://dashboard.tryterra.co))
* A webhook destination configured in the dashboard (optional but recommended)
* A lab report file to upload (PDF, PNG, JPEG, GIF, or WebP)

## Step 1: Upload a Report

```bash
curl -X POST "https://access.tryterra.co/api/v2/lab-reports" \
  -H "dev-id: YOUR_DEV_ID" \
  -H "x-api-key: YOUR_API_KEY" \
  -F "file=@/path/to/blood-test.pdf"
```

You can optionally tag the upload with your own identifier:

```bash
curl -X POST "https://access.tryterra.co/api/v2/lab-reports?reference_id=patient_456" \
  -H "dev-id: YOUR_DEV_ID" \
  -H "x-api-key: YOUR_API_KEY" \
  -F "file=@/path/to/blood-test.pdf"
```

**Response (202 Accepted):**

```json
{
  "upload_id": "upl_4a2b8c1d",
  "current_status": "processing"
}
```

{% hint style="info" %}
The upload returns an `upload_id` — the durable handle for this upload. The `session_id`(s) are learned from the webhook events or via `GET /v2/lab-reports?upload_id=upl_4a2b8c1d`. Both IDs are strings; store snowflake `session_id`s as strings to avoid JavaScript integer precision issues.
{% endhint %}

## Step 2: Wait for Processing

The report moves through several statuses before results are ready:

```
processing -> processed -> standardizing -> standardized -> sending -> sent
```

**Option A: Webhook (recommended)** — Terra delivers a `lab_report.completed` event (with the report under `data`) to your configured webhook endpoint automatically when the session reaches `sent`. No polling needed.

{% hint style="info" %}
Lab reports can be delivered to any destination you've configured — not just webhooks, but also cloud storage, message queues, and databases. Delivery is opt-in per destination: add `"lab_report"` to a destination's `destination_event_types` to start receiving reports there. See [Delivery Destinations](/lab-reports/core-concepts.md#delivery-destinations).
{% endhint %}

**Option B: Poll the session** — Check status by retrieving the session:

```bash
curl "https://access.tryterra.co/api/v2/lab-reports/297405620317847552" \
  -H "dev-id: YOUR_DEV_ID" \
  -H "x-api-key: YOUR_API_KEY"
```

Processing typically takes 30 seconds to 2 minutes depending on report complexity.

## Step 3: Retrieve Results

Once the session status is `sent` (or `standardized` or later), the results are available:

```bash
curl "https://access.tryterra.co/api/v2/lab-reports/297405620317847552" \
  -H "dev-id: YOUR_DEV_ID" \
  -H "x-api-key: YOUR_API_KEY"
```

**Response (200 OK):**

```json
{
  "session_id": "297405620317847552",
  "upload_id": "upl_4a2b8c1d",
  "reference_id": "patient_456",
  "current_status": "sent",
  "report_type": "lab",
  "report_date": "2026-03-15",
  "uploaded_at": "2026-03-28T14:22:10Z",
  "updated_at": "2026-03-28T14:23:45Z",
  "report_locale": "en-US",
  "lab_name": "Quest Diagnostics",
  "patient_sex": "male",
  "patient_age_at_collection": 34,
  "results_count": 3,
  "file_count": 1,
  "status_history": [
    { "status": "processing",    "timestamp": "2026-03-28T14:22:10Z" },
    { "status": "processed",     "timestamp": "2026-03-28T14:22:38Z" },
    { "status": "standardizing", "timestamp": "2026-03-28T14:22:39Z" },
    { "status": "standardized",  "timestamp": "2026-03-28T14:23:02Z" },
    { "status": "sending",       "timestamp": "2026-03-28T14:23:44Z" },
    { "status": "sent",          "timestamp": "2026-03-28T14:23:45Z" }
  ],
  "report_notes": "Patient fasting for 12 hours prior to collection.",
  "panels": [
    { "id": 1, "name": "CBC", "key": "cbc" },
    { "id": 2, "name": "Hormones", "key": "hormones" }
  ],
  "results": [
    {
      "source": {
        "name": "Haemoglobin (Hb)",
        "panel": "CBC",
        "value": "14.2",
        "units": "g/dL",
        "flag": "H",
        "method": "Photometry",
        "reference_text": "13.0 - 17.0 (Male)"
      },
      "biomarker": {
        "key": "hemoglobin_blood",
        "display_name": "Hemoglobin",
        "loinc_code": "718-7",
        "panel_id": 1,
        "panel_key": "cbc",
        "specimen": "blood"
      },
      "measurement": {
        "type": "numeric",
        "numeric": 14.2,
        "units": "g/dL",
        "ucum_code": "g/dL"
      },
      "interpretation": {
        "flag": "high",
        "flag_raw": "H",
        "source": "report",
        "applied_range": { "lower": 13.0, "upper": 17.0 }
      },
      "reference_ranges": [
        {
          "lower": 13.0,
          "upper": 17.0,
          "type": "normal",
          "context": {
            "sex": "male",
            "age_lower": 18,
            "modifiers": ["fasting"]
          }
        }
      ]
    },
    {
      "source": {
        "name": "HIV 1/2 Antigen/Antibody",
        "value": "Non-Reactive",
        "method": "ECLIA"
      },
      "biomarker": {
        "key": "hiv_12_ag_per_ab_combo",
        "display_name": "HIV 1/2 Antigen/Antibody",
        "specimen": "blood"
      },
      "measurement": {
        "type": "qualitative",
        "qualitative": { "text": "Non-Reactive" }
      },
      "interpretation": {
        "flag": null,
        "source": "none"
      },
      "reference_ranges": []
    },
    {
      "source": {
        "name": "Free Testosterone",
        "panel": "Hormones",
        "value": "8.1",
        "units": "pg/mL",
        "flag": "L",
        "method": "Equilibrium Dialysis",
        "notes": "Below optimal range for age group",
        "reference_text": "9.3 - 26.5 (Male)"
      },
      "biomarker": {
        "key": "testosterone_free",
        "display_name": "Free Testosterone",
        "loinc_code": "2991-8",
        "panel_id": 2,
        "panel_key": "hormones",
        "specimen": "blood"
      },
      "measurement": {
        "type": "numeric",
        "numeric": 8.1,
        "units": "pg/mL",
        "ucum_code": "pg/mL"
      },
      "interpretation": {
        "flag": "low",
        "flag_raw": "L",
        "source": "report",
        "applied_range": { "lower": 9.3, "upper": 26.5 }
      },
      "reference_ranges": [
        {
          "lower": 9.3,
          "upper": 26.5,
          "type": "normal",
          "context": {
            "sex": "male",
            "age_lower": 20,
            "age_upper": 39
          }
        }
      ]
    }
  ]
}
```

## What's Next?

* [Core Concepts](/lab-reports/core-concepts.md) — Understand the full session lifecycle and data model
* [Webhook Payload](/lab-reports/webhook-payload.md) — Set up automatic delivery of results
* [Biomarker Reference](/lab-reports/biomarker-reference.md) — Browse the standardized biomarker catalog
