Skip to content

Choose a medication

Find a medication, then read its fill, quantities, compounding reasons, states and shipping options.

Updated View as Markdown

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:

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

ValueMedications for
weight_lossWeight loss
hormonesHormones
sexual_healthSexual health
hairHair
skinSkin
wellnessWellness
peptidesPeptides
painPain
otherOther
suppliesSupplies

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:

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. Catalog values can change. Use the values from your current catalog response.

{
  "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.

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.

Navigation

Send feedback

Don't include patient information.

Type to search…

↑↓ navigate↵ selectEsc close