For the complete documentation index, see llms.txt. This page is also available as Markdown.

API Reference

Complete reference for all Lab Reports API endpoints.

⚠️ 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

Base URL: https://access.tryterra.co/api

All endpoints require the following headers:

Header
Type
Required
Description

dev-id

string

Yes

Your Terra developer ID

x-api-key

string

Yes

Your Terra API key


Upload a Lab Report

POST /v2/lab-reports

Upload a single lab report file for processing. The file is sent as multipart form data. Accepted formats: PDF, PNG, JPEG, GIF, WebP.

Headers

Header
Value

dev-id

Your developer ID

x-api-key

Your API key

Content-Type

multipart/form-data

Query Parameters

Name
Type
Required
Description

reference_id

string

No

Your external identifier for this report/patient

Request Body (multipart)

Field
Type
Required
Description

file

file

Yes

File to upload (PDF, PNG, JPEG, GIF, WebP; max 20 MB)

Example

Response — 202 Accepted

The upload returns an upload_id, not a session_id. A single upload can produce more than one report (e.g. a multi-report PDF), so the session id(s) aren't known at upload time. Learn the session_id(s) from the webhook events, or list them with GET /v2/lab-reports?upload_id=upl_4a2b8c1d. Every resulting session and webhook event carries the same upload_id. session_id still exists — it's the per-report identifier you use for GET /v2/lab-reports/{session_id} — it's just no longer the handle returned at upload.

The list is eventually consistent: immediately after upload the sessions may not all exist yet, so a GET ?upload_id=… right after the 202 can return an empty or partial list. Webhook events are the reliable signal that a report finished.

Error Responses

Code
Description

400

Missing file or unsupported format

401

Invalid or missing dev-id / x-api-key

413

File exceeds 20 MB

429

Rate limit exceeded

500

Internal server error

Error responses use RFC 7807 Problem JSON format:


List Sessions

GET /v2/lab-reports

List lab report sessions for your account, with optional filters.

Query Parameters

Name
Type
Required
Description

reference_id

string

No

Filter by your external reference ID

upload_id

string

No

Filter by the upload handle — returns every report from that upload

report_date_from

string

No

Lab report date lower bound (ISO-8601 YYYY-MM-DD)

report_date_to

string

No

Lab report date upper bound (ISO-8601 YYYY-MM-DD)

uploaded_at_from

string

No

Upload date lower bound (ISO-8601 YYYY-MM-DD)

uploaded_at_to

string

No

Upload date upper bound (ISO-8601 YYYY-MM-DD)

All date filters are inclusive and can be combined. For example, you can query "reports from January uploaded this week" by setting both report_date_from/report_date_to and uploaded_at_from/uploaded_at_to.

Results are capped at 500 per request. Use date range filters to narrow results for accounts with many sessions.

Example

Response — 200 OK


Retrieve a Session

GET /v2/lab-reports/{session_id}

Retrieve the report: metadata, results, reference ranges, and status history. This response is immutable and cacheable — it does not include presigned file URLs (which expire) or per-destination delivery state (which changes). Fetch those from the sub-resources below.

Path Parameters

Name
Type
Required
Description

session_id

string

Yes

The session's snowflake ID

Example

Response — 200 OK

See the Quick Start page for a complete example response. The session object is returned directly at the top level. Key fields include:

  • session_id — Snowflake ID (string)

  • upload_id — The upload this report came from (string)

  • reference_id — Your external reference (omitted if not set)

  • current_status — Current status as a clean lowercase string (e.g. "sent", "processing")

  • report_type — Report type (e.g. "lab")

  • report_date — Date from the lab report (YYYY-MM-DD string, omitted if not extracted)

  • report_time — Time from the lab report (HH:MM 24-hour, omitted if not extracted)

  • collection_date — Specimen collection date (YYYY-MM-DD string, omitted if not extracted)

  • collection_time — Specimen collection time (HH:MM 24-hour, omitted if not extracted)

  • uploaded_at — Session creation timestamp (ISO-8601)

  • updated_at — Last update timestamp (ISO-8601)

  • report_locale — Locale of the report (e.g. "ja-JP", "pt-BR")

  • lab_name — Name of the laboratory

  • patient_sex — Clean lowercase string (e.g. "male", "female", omitted if unspecified)

  • patient_age_at_collection — Patient age in years (integer, omitted if unknown)

  • report_notes — Free-text notes extracted from the report

  • status_history[] — Array of { status, timestamp, note } entries

  • results_count — Number of biomarker results

  • file_count — Number of uploaded files

  • input_bytes — Size of uploaded file(s) in bytes

  • output_bytes — Size of output data in bytes

  • panels[] — Report-level panels that results reference by panel_id (omitted if the report has no panel grouping)

  • results[] — Array of biomarker results, each grouped into source / biomarker / measurement / interpretation layers (see Core Concepts for field specs)

client_id is intentionally omitted from the API response. The API authenticates by client identity, so echoing it back is redundant.

Error Responses

Code
Description

401

Invalid or missing authentication

404

Session not found

500

Internal server error


List Deliveries

GET /v2/lab-reports/{session_id}/deliveries

The per-destination delivery state for a report. A report is fanned out to every destination that has opted in to lab reports (see Delivery Destinations), and each is tracked independently — so a failure to one never hides that the report reached the others. This is also why a session can be partially_sent. Delivery state is mutable (pending → delivered/failed/retrying), so it lives here rather than on the cacheable session.

Response — 200 OK

Field
Type
Description

destination_id

string

The destination's ID

destination_type

string

The destination's type (e.g. webhook, s3)

status

string

pending, delivered, or failed

attempt_count

integer

Retry count — 0 on the first attempt, incremented per retry

last_error

string?

Most recent delivery error (omitted when delivered)


List Files

GET /v2/lab-reports/{session_id}/files

The uploaded input files and the report thumbnail, with freshly minted presigned download URLs. URLs are issued on demand because they expire — they are not embedded in the cacheable session or the webhook.

Response — 200 OK

expires_at applies to every URL in the response. Fetch the endpoint again to mint fresh URLs.


List Artifacts

GET /v2/lab-reports/{session_id}/artifacts

Intermediate processing artifacts, with freshly minted presigned URLs. Privileged keys only — standard keys receive a 404. Same response shape as /files (an artifacts[] array plus expires_at).


Reprocess a Session

POST /v2/lab-reports/{session_id}/reprocess

Re-run extraction and standardization on an existing session. Useful if a session failed or if you want to pick up improvements in the processing pipeline.

Path Parameters

Name
Type
Required
Description

session_id

string

Yes

The session's snowflake ID

Example

Response — 202 Accepted

Includes a Location header pointing to the session. The session re-enters the processing -> ... -> sent flow. A new webhook delivery will occur on completion.

Error Responses

Code
Description

401

Invalid or missing authentication

404

Session not found

500

Internal server error


Delete a Session

DELETE /v2/lab-reports/{session_id}

Soft-delete a session. The session is marked as deleted and a background process cleans up associated storage later.

Path Parameters

Name
Type
Required
Description

session_id

string

Yes

The session's snowflake ID

Example

Response — 204 No Content

No response body.

Error Responses

Code
Description

401

Invalid or missing authentication

404

Session not found

500

Internal server error

Last updated

Was this helpful?