Use resource methods such as get, list, create, and update.
Read a resource
Pass path identifiers before request options.
const order = await affinity.forPractice(practiceId).orders.get("ord_...");List resources
Pass query parameters in one object.
const practices = await affinity.practices.list({ limit: 25 });
for (const practice of practices.data) {
console.log(practice.id, practice.name);
}List available pharmacies
Use a key with catalog:read to list the pharmacies available to your platform in the key’s Test or Live mode.
const pharmacies = await affinity.pharmacies.list({ limit: 25 });
const offers = await affinity.forPractice(practiceId).catalog.items.list({
pharmacyId: selectedPharmacyId,
availability: "orderable",
hideUnpriced: true,
limit: 25,
});Use a returned pharmacy ID as selectedPharmacyId. Pharmacy access does not mean every catalog item is orderable; use the catalog’s availability filters.
Discover medications and offers
Request one representative priced prescription offer per medication group:
const medications = await affinity.forPractice(practiceId).catalog.items.list({
view: "medications",
query: "tadalafil",
availability: "orderable",
hideUnpriced: true,
limit: 25,
});Grouped results include medicationGroup.offerCount, pharmacyCount, and strengths.
Use a returned item’s ID to retrieve individual offers for the same medication and route:
const offers = await affinity.forPractice(practiceId).catalog.items.list({
view: "offers",
relatedToCatalogItemId: medicationId,
availability: "orderable",
hideUnpriced: true,
limit: 25,
});Omitting view preserves the individual-offer response. Keep the same filters when paginating;
when hasMore is true, pass the last returned item ID as startingAfter.
Select and review an individual offer before creating a prescription.
Create a patient
Use synthetic patient data in Test mode.
const patient = await affinity.forPractice(practiceId).patients.create({
name: { first: "Synthetic", last: "Patient" },
dateOfBirth: "1980-01-10",
externalId: "patient-456",
address: {
line1: "100 Test Street",
city: "Austin",
state: "TX",
postalCode: "78701",
country: "US",
},
phone: "+15125550100",
});Request options are optional. The SDK generates keys for routine patient writes. Consequential actions require a persisted key.
Supply your own stable idempotencyKey when retrying an operation across separate calls or processes.
Use actorId and actorType in request options when attributing an action to a person. Order signing accepts a prescriber selector or inherits the draft’s prescriber without requiring actor options.
Legacy requests with userId still require the registered clinician as a user actor.
externalId is the patient ID in your integration. Affinity scopes it to the authenticated
platform or practice, so you do not need to provide a source. Creating a patient with a matching
externalId returns the existing patient without overwriting demographics.
Use externalIdentities for aliases owned by another system, such as a legacy EHR:
externalIdentities: [{ source: "legacy-ehr", value: "12345" }];Find your patient with patients.list({ externalId: "patient-456" }, { practiceId }). To find an
explicit alias, provide externalIdentitySource and externalIdentityValue together. Updating
externalId changes only your integration’s identifier. Updating externalIdentities replaces
the explicit aliases.
Manage practice Live access
Use a Live API key from an approved platform with practices:write.
const practice = await affinity.practices.create({
...practiceDetails,
liveEnabled: true,
});
await affinity.practices.update(practice.id, { liveEnabled: false });
await affinity.practices.update(practice.id, { liveEnabled: true });practiceDetails contains the required practice name, address, and attestations.
The response uses liveEnabled: boolean; disabled access is false, not a pending approval.
Your platform can change only its owned practices. Affinity Admin decisions take precedence.
See Practice Live access for restrictions.
Use domain types
import type {
Practice,
Patient,
Order,
CreatedOrder,
CatalogItem,
PracticeLocation,
} from "@affinity-health/sdk";
const practice: Practice = await affinity.practices.get(practiceId);
const id: string = practice.id;Resource IDs are non-null strings. Fields that can be empty, such as legalName, remain nullable.
CreatedOrder describes the creation response; Order describes the full retrieved order.
When upgrading from older releases, replace practice productionAccess comparisons with liveEnabled checks.
Use typed compounding reasons
import { CompoundingReason } from "@affinity-health/sdk";
const category: CompoundingReason = CompoundingReason.ConcentrationAdjustment;Use catalog.prescribingOptions.get to get the categories accepted for a medication.
Send the selected value as clinical.compoundingReason.category on the prescription. Add context when required.
See Compounding reasons for the complete workflow.
Iterate through a collection
The iterator loads pages as you consume them and preserves practice context and filters.
for await (const patient of affinity.forPractice(practiceId).patients.iterate({ limit: 20 })) {
await syncPatient(patient);
}Use the API reference for direct HTTP access to endpoints outside the SDK.