> ## Documentation Index
> Fetch the complete documentation index at: https://docs.anivahealth.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Preview Containers

> Preview required specimen-collection containers for an appointment

Preview the specimen-collection containers required for an appointment based on its currently attached panels and biomarkers. This runs the logistics pipeline in preview mode — no orders are placed.

Use this endpoint after adding panels or individual biomarkers to see what physical containers (blood tubes, and where applicable a dried-blood-spot card or urine cup) the practitioner needs to prepare for the sample collection.

<Note>
  `pricing` is the appointment's whole-cart pricing — billing groups (each billed once) plus a
  total, at both the retail card and your API key's own card. `routing` is intentionally always
  `null`.
</Note>

## Request

### Path parameters

<ParamField path="id" type="string" required>
  Unique identifier (UUID) of the appointment to preview container requirements for.
</ParamField>

## Response

On success, the API returns `200 OK` with the container requirements and reserved fields for future use.

<ResponseField name="containers" type="object[]" required>
  Array of required specimen-collection containers. Empty when no panels or biomarkers have been added to the appointment.

  <Expandable title="container">
    <ResponseField name="type" type="string">
      Container type identifier. One of `serum`, `serum_capillary`, `edta`, `edta_capillary`, `citrate`, `lihep`, `glucoexact`, `naf`, `homocysteine`, `urine`, `dried_blood_spot`, `swab`, `stool`, `saliva`, `hair`, or `trace_metal`.
    </ResponseField>

    <ResponseField name="name" type="string">
      Human-readable container name (e.g., "Serum", "EDTA", "Li-Heparin").
    </ResponseField>

    <ResponseField name="kind" type="string">
      Physical form of the container. One of `monovette`, `dbs_card`, or `urine_cup`.
    </ResponseField>

    <ResponseField name="cap_color" type="string">
      Hex color code of the container cap for display (e.g., `"#A0784B"`).
    </ResponseField>

    <ResponseField name="volume" type="string">
      Volume capacity of the container (e.g., `"7.5 ml"`).
    </ResponseField>

    <ResponseField name="article_number" type="string">
      Sarstedt catalog number (REF), when known (e.g., `"01.1602.001"`). Omitted for containers without a mapped article number.
    </ResponseField>

    <ResponseField name="count" type="integer">
      Number of containers of this type required.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="routing" type="null">
  Lab routing details — intentionally not exposed, always `null`.
</ResponseField>

<ResponseField name="pricing" type="object | null">
  Whole-cart pricing for the appointment, or `null` when it has no location or no attached tests, or
  when your key lacks the `prices_view` scope. Carries `retail` and `yours`, each a [price
  breakdown](/api/biomarkers/list-biomarkers#price-objects) (`total_cents` + billing `groups`, each
  billed once across the whole appointment, with the `biomarker_ids` each group delivers).
</ResponseField>

## Error responses

| Status | Description                                                      |
| ------ | ---------------------------------------------------------------- |
| `400`  | Invalid ID format — the provided value is not a valid UUID.      |
| `403`  | Forbidden — your API key does not have access to this operation. |
| `404`  | Appointment not found.                                           |
| `500`  | Internal server error.                                           |

<RequestExample>
  ```bash cURL theme={null}
  curl --request GET \
    --url https://anivahealth.com/api/v1/appointments/c9f3e2a1-7d6b-4c5e-b3a2-1f0e9d8c7b6a/preview \
    --header 'x-api-key: YOUR_API_KEY'
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "containers": [
      {
        "type": "serum",
        "name": "Serum",
        "kind": "monovette",
        "cap_color": "#A0784B",
        "volume": "7.5 ml",
        "article_number": "01.1602.001",
        "count": 3
      },
      {
        "type": "edta",
        "name": "EDTA",
        "kind": "monovette",
        "cap_color": "#D13438",
        "volume": "3.4 ml",
        "article_number": "04.1914.001",
        "count": 2
      },
      {
        "type": "glucoexact",
        "name": "GlucoEXACT",
        "kind": "monovette",
        "cap_color": "#9E9E9E",
        "volume": "3.1 ml",
        "article_number": "05.1074.001",
        "count": 1
      }
    ],
    "routing": null,
    "pricing": {
      "retail": {
        "total_cents": 18852,
        "groups": [
          { "price_cents": 14900, "biomarker_ids": [43, 44, 51, 52] },
          {
            "price_cents": 3952,
            "biomarker_ids": [42],
            "goa_lines": [
              {
                "goa_code": "5812",
                "goa_base_cents": 982,
                "quantity": 3.5,
                "factor": 1.15,
                "amount_cents": 3952
              }
            ]
          }
        ]
      },
      "yours": {
        "total_cents": 14821,
        "groups": [
          { "price_cents": 11900, "biomarker_ids": [43, 44, 51, 52] },
          {
            "price_cents": 2921,
            "biomarker_ids": [42],
            "goa_lines": [
              {
                "goa_code": "5812",
                "goa_base_cents": 982,
                "quantity": 3.5,
                "factor": 0.85,
                "amount_cents": 2921
              }
            ]
          }
        ]
      }
    }
  }
  ```

  ```json 200 (no panels) theme={null}
  {
    "containers": [],
    "routing": null,
    "pricing": null
  }
  ```

  ```json 404 theme={null}
  {
    "error": "Appointment not found"
  }
  ```
</ResponseExample>
