> ## 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.

# Pricing

> How Aniva prices biomarkers, positions and panels

Aniva prices one thing: the **position**. A position is a commercial offer — a curated set of biomarkers that bills once, at a flat price, and is always delivered whole. A biomarker you can buy on its own is simply a position of one.

Everything you see in `pricing` follows from that. Read this page once and the four states below stop looking like special cases.

## What the numbers mean

Every `price_cents` is what **you** pay, at the rate card on your API key. Beside it, `retail_cents` is the same item at the recommended retail card, so you can show a saving without a second request. Both are integer cents.

<Note>
  `retail_cents` is always present. When your key is already on the retail card it simply equals
  `price_cents`.
</Note>

Pricing is gated behind the `prices_view` scope. Without it, `pricing` is `null` on every response — that is the only reason the whole object is ever `null`.

## The four states

`price_cents`, plus which optional block sits beside it, is the state. There is no separate type field.

| `price_cents` | Also present | What it means                                                     |
| ------------- | ------------ | ----------------------------------------------------------------- |
| positive      | `positions?` | Orderable on its own at that price.                               |
| `0`           | `requires`   | A **ratio**. It costs nothing itself; you pay for its components. |
| `0`           | `positions`  | **Position-gated**. Sold only inside one of the listed positions. |
| `null`        | —            | **Uncurated**. Aniva has not priced it, and it cannot be ordered. |

### Positive — orderable alone

The marker has a price of its own. It may still appear in positions, and `positions` then lists them cheapest first — buying the position is often cheaper than buying its members one by one.

```json theme={null}
{
  "id": 71,
  "pricing": {
    "price_cents": 350,
    "retail_cents": 403,
    "tier": "routine",
    "positions": [
      {
        "id": "b7d4c2e1-9a3f-4c8b-91d2-5e6f7a8b9c0d",
        "name": "Aniva Blood Count",
        "price_cents": 452,
        "retail_cents": 520,
        "biomarker_ids": [71, 72, 73],
        "includes": [72, 73]
      }
    ]
  }
}
```

`biomarker_ids` is the position's full member set; `includes` is that set minus the marker you queried — what rides along.

### Zero with `requires` — a ratio

A ratio is computed from measured markers, so it has no price of its own. Order it and Aniva puts its components in the cart at their own prices. A component is paid **once per cart** however many ratios lean on it.

```json theme={null}
{
  "id": 279,
  "pricing": {
    "price_cents": 0,
    "retail_cents": 0,
    "requires": [
      { "id": 42, "name": "HDL Cholesterol", "price_cents": 233, "retail_cents": 268 },
      { "id": 84, "name": "hs-CRP", "price_cents": 1166, "retail_cents": 1341 }
    ]
  }
}
```

A ratio composes with positions rather than competing with one. If its components are members of a position you are already buying, the position pays for them and the ratio rides along for free.

<Warning>
  A ratio whose components are not all priced is **absent from the catalog** — it does not appear
  with `price_cents: null`. It comes back once Aniva prices the missing component.
</Warning>

### Zero with `positions` — sold only inside a position

The marker has no price of its own, but it is a member of one or more positions. Buy one of those positions and you get it.

```json theme={null}
{
  "id": 77,
  "pricing": {
    "price_cents": 0,
    "retail_cents": 0,
    "positions": [
      {
        "id": "3f1a8c22-64bd-4e57-8a90-1c2d3e4f5a6b",
        "name": "Blood Count (extended)",
        "price_cents": 460,
        "retail_cents": 529,
        "biomarker_ids": [71, 72, 73, 77],
        "includes": [71, 72, 73]
      }
    ]
  }
}
```

Adding one of these to an appointment on its own is refused — see [Add Individual Biomarkers](/api/appointments/add-individual-biomarkers). Add every biomarker of one of the listed positions instead.

### Null — uncurated

Aniva has not decided what this marker costs, so it is not for sale. `null` is not zero and not "ask us": treat it as unavailable.

```json theme={null}
{ "id": 555, "pricing": { "price_cents": null, "retail_cents": null } }
```

## Finding the cheapest way to buy a set

Because every position a marker belongs to travels with the marker, you can solve this locally, without extra requests:

1. Collect the markers you want from [List Biomarkers](/api/biomarkers/list-biomarkers).
2. For each one, compare its own `price_cents` against the `price_cents` of the positions in its `positions` block.
3. A position bills **once** and delivers its whole `biomarker_ids` set, so a position covering several of your markers is charged a single time. Extra markers you did not ask for come along at no additional cost.

Nothing overlaps twice: two positions that share a member each deliver their set, the member is listed once, and they never discount each other.

## The bill

[Preview Containers](/api/appointments/preview-containers) returns the whole-cart bill for an appointment — the exact counterpart of the catalog states above:

* `positions[]` — every position that fired, billed once at its flat price.
* `panels[]` — every attached panel.
* `biomarkers[]` — one row per **delivered** marker. A row a position pays for costs `0` and names it in `via_position`. A component pulled in by a ratio carries `required_by`; the ratio itself carries `requires`.
* `total_cents` — the priced positions plus the priced panels plus the priced biomarker rows, with `retail_total_cents` beside it.

A row Aniva cannot price carries `price_cents: null` and adds nothing to the total, so a cart carrying one totals less than it will cost. Every other row keeps its price.

<Note>
  Some positions are internal. One that fired but is not partner-facing still bills, and appears in
  `positions[]` with `id` and `name` set to `null`; the markers it pays for then carry no
  `via_position`.
</Note>
