> 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/vantage-api-docs/documentation/test-collection-methods.md).

# Test Collection Methods

## Overview

Depending on the supplier and the product, a test can support multiple collection methods - ways for the end user to provide the sample. A variant advertises what it supports in `available_collection_types`; every order picks one via `collection_type`.

| `collection_type` | Meaning                                                                                                 |
| ----------------- | ------------------------------------------------------------------------------------------------------- |
| `AT_HOME`         | Kits are sent to the end user's home. They follow the kit instructions to self-collect.                 |
| `GO_TO_LAB`       | The end user visits a lab draw site (Patient Service Center), where a professional collects the sample. |

The collection type determines which address field the order requires:

* `AT_HOME` → `shipping_address` (where to ship the kit)
* `GO_TO_LAB` → `requested_lab_address` (used to route the order to the closest available lab)

## Where a test can be ordered

Every variant advertises the countries it can be ordered in as `supported_ship_to_countries` (ISO-3166 alpha-2 codes) — for `AT_HOME` this is the kit's shipping destination; for `GO_TO_LAB`, the country of the requested lab:

```json
{
  "id": 100011,
  "variant_name": "Standard Kit",
  "available_collection_types": ["AT_HOME"],
  "supported_ship_to_countries": ["GB"]
}
```

Gate your address form (or country picker) on this list. Orders outside it are rejected with a `400` you can map straight onto the form — the `invalid_fields` entry carries the tag `unsupported_ship_to_country` and the field that failed (`shipping_address.country_code` or `requested_lab_address.country_code`), and the problem detail includes the allowed codes:

```json
{
  "detail": "This test isn't available in the provided country. Supported country codes: GB.",
  "status": 400,
  "invalid_fields": [
    {
      "field": "shipping_address.country_code",
      "message": "must be one of: GB",
      "tag": "unsupported_ship_to_country",
      "value": "US"
    }
  ],
  "supported_ship_to_countries": ["GB"]
}
```

### AT\_HOME orders

{% tabs %}
{% tab title="Request" %}

```json
{
  "client_order_reference_id": "TEST-ORDER-001",
  "collection_type": "AT_HOME",
  "recipient": {
    "first_name": "John",
    "last_name": "Tan",
    "email": "john.tan@example.com",
    "phone_number": "+447436503302",
    "date_of_birth": "1995-10-10",
    "gender_at_birth": "male"
  },
  "shipping_address": {
    "address_line_1": "123 High Street",
    "city": "London",
    "administrative_area": "England",
    "country_code": "GB",
    "postal_code": "SW1A 1AA"
  },
  "items": [
    {
      "variant_id": "100011",
      "quantity": 1
    }
  ]
}
```

{% endtab %}

{% tab title="Response (201)" %}

```json
{
  "order_id": "256488482397134848",
  "recipient_id": "256488482397134849",
  "order_items": [
    {
      "order_id": "256488482397134848",
      "order_item_id": "256488482397134851",
      "variant_id": "100011",
      "product_type_id": "1",
      "price_per_item_cents": 3999,
      "quantity": 1,
      "currency": 826,
      "results_status": "results.awaiting_sample"
    }
  ],
  "order_status": "order.payment_processing"
}
```

{% endtab %}
{% endtabs %}

### GO\_TO\_LAB orders

For `GO_TO_LAB`, send the address the end user would like to be near as `requested_lab_address`. Terra uses it as a proxy to route the order to the closest available lab. To let the user pick a specific draw site up front, list nearby locations first (see [Finding nearby lab draw sites](#finding-nearby-lab-draw-sites)):

{% tabs %}
{% tab title="Request" %}

```json
{
  "client_order_reference_id": "TEST-ORDER-002",
  "collection_type": "GO_TO_LAB",
  "recipient": {
    "first_name": "Jane",
    "last_name": "Doe",
    "email": "jane.doe@example.com",
    "phone_number": "+12125550100",
    "date_of_birth": "1990-05-15",
    "gender_at_birth": "female"
  },
  "requested_lab_address": {
    "address_line_1": "350 5th Avenue",
    "city": "New York",
    "administrative_area": "NY",
    "country_code": "US",
    "postal_code": "10118"
  },
  "items": [
    {
      "variant_id": "100011",
      "quantity": 1
    }
  ]
}
```

{% endtab %}

{% tab title="Response (201)" %}

```json
{
  "order_id": "256488482397134852",
  "recipient_id": "256488482397134853",
  "order_items": [
    {
      "order_id": "256488482397134852",
      "order_item_id": "256488482397134855",
      "variant_id": "100011",
      "product_type_id": "1",
      "price_per_item_cents": 3999,
      "quantity": 1,
      "currency": 840,
      "results_status": "results.awaiting_sample"
    }
  ],
  "order_status": "order.payment_processing"
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
Order responses include a `confirmed_lab_address` field: the nearest draw site to the requested lab address, resolved at order time. It is best-effort - `null` when resolution is unavailable, so don't build a flow that requires it. The requisition is typically accepted at any of the network's sites (see the labs listing below).
{% endhint %}

## Finding nearby lab draw sites

To let your end user choose a convenient location before placing a `GO_TO_LAB` order, list nearby Patient Service Centers for a US zip code:

```bash
curl 'https://vantage-sandbox.tryterra.co/api/v1/labs?zip_code=10001' \
  -u 'YOUR_DEV_ID:YOUR_API_KEY'
```

```json
{
  "labs": [
    {
      "code": "PSC12345",
      "name": "Quest Diagnostics - Midtown",
      "address": {
        "address_line_1": "245 W 35th St",
        "city": "New York",
        "administrative_area": "NY",
        "country_code": "US",
        "postal_code": "10001"
      },
      "phone": "+1-212-555-0100",
      "hours": { "monday": "08:00-17:00" },
      "latitude": 40.7549,
      "longitude": -73.984,
      "scheduling": true,
      "distance": 0.4
    }
  ]
}
```

`distance` is in miles from the requested zip code; `scheduling` indicates whether online scheduling is open at that site.

## Letting the user pick a draw site

To bind a `GO_TO_LAB` order to the site your user chose (instead of the automatic nearest-site resolution), pass the chosen row's `code` and `address.postal_code` as `requested_lab` when creating the order:

```json
{
  "collection_type": "GO_TO_LAB",
  "requested_lab_address": { "...": "the user's search area" },
  "requested_lab": { "code": "PSC12345", "postal_code": "10001-6975" }
}
```

Both values come verbatim from the `GET /labs` row (ZIP+4 is fine - it is normalized server-side). The outcomes:

* **Bound** - the order response (and any later `GET /orders/{id}`) carries `confirmed_lab` (the full site: code, name, address, phone, hours) and `confirmed_lab_address`. Render it as "your draw site".
* **Unknown code** - `400` with an `invalid_fields` entry on `requested_lab.code` tagged `unknown_lab_code`. The site list may have changed: re-fetch `GET /labs` and let the user re-select. Nothing was created, so retrying is safe.
* **Lookup temporarily unavailable** - the order is **accepted unbound** (`confirmed_lab` is `null`). The requisition is typically valid at any of the network's sites, so a brief outage never fails an order. `GET /orders/{id}` echoes your `requested_lab` so you can tell this case apart from "no selection was made".

Without `requested_lab`, Terra falls back to resolving the nearest site to `requested_lab_address` (best-effort).
