---
title: "Choose a medication"
description: "Find a medication, then read its fill, quantities, compounding reasons, states and shipping options."
---

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

# Choose a medication

Each prescription in an order names one medication by its `med_` ID. The medication tells you what
its pharmacy accepts. Read it before you send an order.

## Find a medication

List medications for the mode of your key:

```sh
curl "https://api.affinityrx.com/v1/medications?limit=10" \
  -H "Authorization: Bearer $AFFINITY_API_KEY" \
  -H "Affinity-Version: 2026-10-28"
```

Test offers each pharmacy's Live medications with the same medication IDs, names and prices.
Medication and shipping option IDs are shared across Test and Live. Old Test shipping IDs remain valid in Test.
The list contains all the medications that you can order in the mode of your key, A to Z by name.
It has no search and no filters. To get the next page, send `nextCursor` as `startingAfter`. Stop
when `hasMore` is `false`. This list goes forward only. `limit` sets the number of results on one
page: 1 to 100. The default is 25. `practiceId` quotes prices for one practice; see
[Prices for your practice](#prices-for-your-practice). The list accepts only `practiceId`, `limit`
and `startingAfter`. Any other query parameter returns `400` `invalid_request`.

To find a medication, read all the pages. Then select it by `name`, `strength`, `form` and
`pharmacy`. Do not select the first result of a page.

Each medication has a `category`, one of these values:

| Value | Medications for |
| --- | --- |
| `weight_loss` | Weight loss |
| `hormones` | Hormones |
| `sexual_health` | Sexual health |
| `hair` | Hair |
| `skin` | Skin |
| `wellness` | Wellness |
| `peptides` | Peptides |
| `pain` | Pain |
| `other` | Other |
| `supplies` | Supplies |

Every strength, form and pharmacy of one medication has the same `category`.

To read one medication, send `GET /v1/medications/{medicationId}`.

## Read the other strengths of a medication

A medication ID names one strength, one form and one pharmacy. To read the other strengths, forms
and pharmacies of the same medication in one request, add `expand=variants`:

```sh
curl "https://api.affinityrx.com/v1/medications/$MEDICATION_ID?expand=variants" \
  -H "Authorization: Bearer $AFFINITY_API_KEY" \
  -H "Affinity-Version: 2026-10-28"
```

The response is the medication with a `variants` array. Each entry has the same fields as the
medication and does not repeat the medication itself. `variants` lists only what you can order in
the mode of your key, and it has prices for the same organization. Without `expand`, the response
has no `variants` field. Any other `expand` value returns `400`.

## Read the medication

This Test medication supplies the IDs in [Send an order](/guides/send-an-order/).
Catalog values can change. Use the values from your current catalog response.

```json
{
  "category": "weight_loss",
  "coldChainRequired": true,
  "compoundingReasons": [
    "alcohol_free",
    "alternate_route",
    "commercial_product_discontinued",
    "concentration_adjustment",
    "dosage_form_unavailable",
    "drug_shortage",
    "flavor_adjustment",
    "inactive_ingredient_sensitivity",
    "inactive_ingredient_toxicity",
    "modified_release",
    "no_rationale_required",
    "patient_cannot_use_commercial_product",
    "tablet_burden"
  ],
  "defaultDirections": null,
  "fill": {
    "amount": 1,
    "container": "vial",
    "ingredients": [
      { "amount": 60, "name": "Tirzepatide", "unit": "mg" },
      { "amount": 1, "name": "B12", "unit": "mg" }
    ],
    "unit": "vial",
    "volume": { "amount": 2, "unit": "mL" }
  },
  "form": "Vial",
  "fullName": "Tirzepatide / B12",
  "id": "med_3v9r73nmfs8bmbjb960yd2pggg",
  "name": "Tirzepatide / B12",
  "pharmacy": {
    "id": "pharm_314xqfy8g09snbzq56416t1zb1",
    "name": "PerfectRx Pharmacy"
  },
  "price": 11725,
  "quantities": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
  "quantityUnit": "vial",
  "requirements": [],
  "restrictedStates": ["AS", "GU", "MP", "PR", "VI", "AA", "AE", "AP"],
  "shippingOptions": [
    {
      "id": "shp_7yna882w139zfbmwzeyb16y24e",
      "name": "Ground Cold Chain",
      "price": 2706
    }
  ],
  "shippingSuppliesPrice": 206,
  "strength": "30 mg/0.5 mg/mL"
}
```

All prices are integers in cents. There are no fractional prices.

## Fill, quantity and strength

`fill` is what the pharmacy dispenses for one `price`. For a vial product, `quantityUnit` is `vial`,
one fill is one vial, and `quantity` counts vials. `fill.volume` is what one vial holds, here 2 mL:

| `quantity` | Vials | Prescription price |
| ---------- | ----- | ------------------ |
| `1`        | 1     | 11725              |
| `6`        | 6     | 70350              |

`quantities` lists the accepted values: 1 to 10 vials. To order 6 vials, send one prescription with
`quantity: 6`. Do not send 6 prescriptions. A quantity that is not in `quantities`, for example `12`,
returns `422` `invalid_order`.

For other products, `quantity` counts `quantityUnit`, not fills. Tablets, capsules and creams keep
their unit. `fill.amount` is the number of units in one fill. The number of fills is
`quantity / fill.amount`, and the prescription price is `price × quantity / fill.amount`. Send a
quantity from `quantities`; each value is a whole number of fills in units. Example: PerfectRx
Anastrozole 1 mg tablets have `quantityUnit: "tablet"`, `fill.amount: 30`, `price: 2520` and
`quantities: [30, 60, …, 300]`:

| `quantity` | Fills | Tablets | Prescription price |
| ---------- | ----- | ------- | ------------------ |
| `30`       | 1     | 30      | 2520               |
| `60`       | 2     | 60      | 5040               |

To order two fills of 30 tablets, send `quantity: 60`. Do not send `quantity: 2`: it is not in
`quantities` and returns `422` `invalid_order`. A vial is the same rule with `fill.amount: 1`, so
`quantity` counts vials.

`strength` is the pharmacy's text. For a liquid, it is an amount per mL: `30 mg/0.5 mg/mL` is
30 mg of tirzepatide and 0.5 mg of B12 in each mL. Do not read it as the amount in a vial.
`fill.ingredients` gives the total of each active ingredient in one fill: 60 mg of tirzepatide and
1 mg of B12 in one 2 mL vial. Use these totals to check a dose. Do not calculate them from `strength`.

`fill` is `null` when the pharmacy has not given the fill and the amount of each ingredient.
Then the prescription price is `price` for any accepted quantity.

| Field                   | Use it to                                                                                                                                              |
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `fullName`              | Show the name with its salt, for example `Enclomiphene Citrate`. It equals `name` when there is no salt.                                               |
| `category`              | Group medications. It is one of the `category` values above.                                                                                           |
| `requirements`          | Know which optional prescription fields this pharmacy requires, for example `compoundingReason`.                                                       |
| `compoundingReasons`    | Choose a compounding reason. When the list is not empty, send one of its values exactly.                                                               |
| `fill`                  | Show what one fill holds, for example a 2 mL vial with 60 mg of tirzepatide. `price` is for one fill.                                                  |
| `quantities`            | Choose a quantity. When the list is not empty, send one of its values. Each value counts `quantityUnit`; with a `fill`, it is a whole number of fills. |
| `quantityUnit`          | Show what a quantity counts. For a vial, quantity `1` is one vial; `fill.volume` gives its volume.                                                     |
| `restrictedStates`      | Know where the medication cannot ship, including pharmacy coverage and medication restrictions. These are two-letter postal region codes.              |
| `defaultDirections`     | Prefill the directions. The prescriber can change them.                                                                                                |
| `shippingOptions`       | Choose a shipping option. Send its `id` as `shipping.optionId` in the order. The same shipping option ID works in Test and Live.                       |
| `coldChainRequired`     | Know whether the medication needs refrigerated shipping.                                                                                               |
| `shippingSuppliesPrice` | Read the supplies amount already included in each shipping option price.                                                                               |

## Prices for your practice

Catalog reads return prices for the current organization. Without a `practiceId` query parameter, the API uses the key's organization.
A platform key therefore returns platform prices. An independent practice key returns that practice's prices.

For each medication and shipping option, a practice pays the first available price:

1. Its own price.
2. Its platform's price, when the practice has a platform.
3. The default price.

A platform pays its own price when available, then the default price.

With a platform key, send `practiceId` in the query to quote an order for one of that platform's child practices.
Both medication list and detail routes accept it, including `expand=variants`.
A foreign or archived practice returns `404`. A practice key may select only itself.
API keys always act as their own organization and mode. `Affinity-Organization` does not override them.

```sh
curl "https://api.affinityrx.com/v1/medications?limit=10&practiceId=prac_01j9z3k4m5n6p7q8r9s0t1v2w3" \
  -H "Authorization: Bearer $AFFINITY_API_KEY" \
  -H "Affinity-Version: 2026-10-28"
```

Order creation uses the target practice's prices. The order keeps those prices when catalog prices change.

Each option price includes `shippingSuppliesPrice`; a mixed order pays the highest supplies price once. Example: $25.00 cold chain + $2.06 supplies = $27.06.
Do not add `shippingSuppliesPrice` again.
Use `coldChainRequired` to select refrigerated shipping.

## Rules for an order

- All prescriptions in one order go to one pharmacy. Choose medications of the same pharmacy.
- When a field is in `requirements`, send it. Otherwise the order returns `422` with the path of
  the missing field, for example `prescriptions[0].compoundingReason`.
- PerfectRx ships to all 50 states and DC. It does not ship to territories or military addresses.
- PerfectRx also refuses a patient whose own address is in a territory other than PR, or is a
  military address, wherever the order ships. The order returns `422` with the path
  `patient.address.state`.
- The order checks `restrictedStates` against the state of the shipping destination:
  - The patient's address, the default: the path is `patient.address.state`.
  - The practice's address (`shipping.destination.type: "practice"`): the path is
    `practice.address.state`.
  - Another address (`shipping.destination.type: "address"`): the path is
    `shipping.destination.address.state`.

  When that state is in `restrictedStates`, the order returns `422` with that path.

- A refrigerated medication (`coldChainRequired: true`) lists refrigerated shipping options only.
  An order with a refrigerated medication needs refrigerated shipping.
  Choose an option from that medication's `shippingOptions`.

The `requirements` list can get new values when Affinity adds a pharmacy. A new value applies only
to that pharmacy's medications. Read `requirements` for each medication and do not hard-code it.

Next: [Send an order](/guides/send-an-order/).

Source: https://docs.affinityrx.com/guides/choose-a-medication/index.mdx

If a response or a page is wrong or unclear, send `POST /v1/feedback` with an `Idempotency-Key`, a short message and the `requestId` from the response. Do not include patient information.
