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

Core concepts

The Vantage API data model: catalog structure, orders and order items, recipients and test takers, status lifecycles, and conventions used across all endpoints.

The catalog: product types → products → variants

The catalog is three levels deep:

Level
What it is
Example

Product type

The broadest category

Blood Test, DNA Test

Product

An offering within a type

An at-home blood test kit from a given supplier

Variant

The exact configuration an end user receives - the thing you order

The "Inflammation" panel (hs-CRP + Vitamin D), 3-5 day turnaround

You browse with GET /api/v1/products (types) → GET /api/v1/products/{product_type_id} (products) → GET /api/v1/products/{product_id}/variants (variants), and you order a variant_id. A variant advertises which collection methods it supports in available_collection_types (an array of strings: "AT_HOME", "GO_TO_LAB").

Your catalog is scoped to your contract: browsing returns only the panels and fulfilment options your account is entitled to, and orders for anything outside it are rejected. To add panels to your contract, contact the Terra team. Within your entitlements, you can additionally curate which products your catalog reads return - see Managing orders.

Orders and order items

An order is one purchase: it has a recipient, a collection type, an address, and one or more order items (one per variant_id + quantity). Everything result-related happens per order item: kit activation, result statuses, result downloads, and acknowledgment are all keyed by order_item_id, not order_id.

  • client_order_reference_id - your unique identifier for the order, supplied when you create it. Use it to reconcile webhooks and REST reads with your own system. For retry-safe creation, send an Idempotency-Key header - the reference id alone does not deduplicate.

  • order_id, order_item_id, recipient_id, test_taker_id - Terra-generated identifiers.

Recipient vs test taker

  • The recipient is the person the order is placed for - name, date of birth, gender at birth, email, phone. You provide it at order time.

  • The test taker is the person who actually takes the test. For suppliers with kit activation, the test taker registers themselves during activation (and may differ from the recipient, supplier-permitting). Terra assigns a test_taker_id at that point and includes it in every result webhook.

You need the test_taker_id to fetch and acknowledge results - capture it from the result webhooks (or from GET /api/v1/orders/{orderID}).

Collection types

Every order has a collection_type that determines how the sample is collected and which address field the order requires:

collection_type

Meaning

Address field

AT_HOME

Kit shipped to the recipient, who self-collects

shipping_address

GO_TO_LAB

Sample drawn at a lab draw site (Patient Service Center)

requested_lab_address

See Test Collection Methods.

Status lifecycles

An order carries a fulfilment status; each order item carries a results status.

Order (fulfilment) statuses, as returned by the REST API:

New orders start at order.payment_processing.

Order item (results) statuses:

Escalation levels

Results carrying clinical escalation include an escalation_level, one of (in ascending severity):

not_escalated, very_low, low, medium, high, very_high

Escalated results also carry an acknowledgment_due_by timestamp - see Acknowledging Results.

Conventions

  • Money is integer cents (price_cents, total_cents); currency is an ISO 4217 numeric code (840 = USD, 978 = EUR, 826 = GBP).

  • Phone numbers are a single E.164 string everywhere — the industry-standard format used by Stripe, Twilio and FHIR. Send phone_number as a +-prefixed E.164 string ("+14155551234"); reads and webhook test_taker payloads return the same string. There is no separate recipient country_code field.

  • Timestamps in webhook payloads (timestamp) are Unix seconds; REST timestamps are RFC 3339 strings.

  • Errors follow RFC 7807 problem-detail format - see Errors.

  • List endpoints (GET /api/v1/orders, GET /api/v1/results, GET /api/v1/webhook-deliveries) are keyset-paginated: pass the returned next_cursor as ?cursor= for the next page; a page without next_cursor is the last one.

Last updated

Was this helpful?