Reference catalog (datasets)

The /v3/datasets bundle — inline-row shape, ULID identifiers, prescription_count sorting, and ?include= slicing.

Reference catalog (datasets)

GET /v3/datasets ships the reference catalog the SDK and your UI use to resolve free text to canonical conditions, medications, products, nicotine options, and spelling corrections.

Every row is self-contained: a condition row carries its medications inline as treated_with[], and a medication row carries its conditions inline as used_for[]. Each inline entry includes a prescription_count integer for sorting. No response-root joins, no client-side re-keying.

The SDK calls this for you. await isa.zyins.datasets.get() warms the bundle cache; every match() / autocomplete() after that reads from it.

Wire shape

{
  "object": "dataset_bundle",
  "request_id": "req_01HZK2N5GQR9T8X4B6FJW3Y1AS",
  "livemode": true,
  "data": {
    "version": "2026-05-29.r41",
    "datasets": {
      "conditions":  { "version": "2026-05-29", "item_count": 3812, "items": [ /* … */ ] },
      "medications": { "version": "2026-05-29", "item_count": 5174, "items": [ /* … */ ] },
      "products":    { "version": "2026-05-29", "item_count":  127, "items": [ /* … */ ] },
      "spelling_corrections": { "version": "2026-05-29", "item_count": 942, "items": [ /* … */ ] },
      "nicotine_options":     { "version": "2026-05-29", "item_count":   8, "items": [ /* … */ ] }
    }
  }
}

A conditions[] row:

{
  "id":   "cond_01KSR2WVAGC05ZGR6FA4QYEA8X",
  "name": "HIGH BLOOD PRESSURE",
  "treated_with": [
    { "id": "med_01KSR2WVAGC05ZGR6FA4QYEB12", "name": "LISINOPRIL",   "prescription_count": 4120 },
    { "id": "med_01KSR2WVAGC05ZGR6FA4QYEB7K", "name": "AMLODIPINE",   "prescription_count": 3088 },
    { "id": "med_01KSR2WVAGC05ZGR6FA4QYEC22", "name": "LOSARTAN",     "prescription_count": 2841 }
  ]
}

A medications[] row:

{
  "id":   "med_01KSR2WVAGC05ZGR6FA4QYEB12",
  "name": "LISINOPRIL",
  "used_for": [
    { "id": "cond_01KSR2WVAGC05ZGR6FA4QYEA8X", "name": "HIGH BLOOD PRESSURE", "prescription_count": 4120 },
    { "id": "cond_01KSR2WVAGC05ZGR6FA4QYEA9P", "name": "CONGESTIVE HEART FAILURE", "prescription_count":  617 }
  ]
}

Both inline arrays are pre-sorted by prescription_count descending, with ties broken alphabetically. Use the array directly for a "Most Common" picker—no re-sorting needed.

Identifiers

id is a kind-prefixed ULID:

PrefixKind
cond_Condition
med_Medication
prod_Product
nic_Nicotine option
corr_Spelling correction

Identifiers are stable for the lifetime of a dataset version (the bundle's top-level version token). When version changes, treat every cached id as potentially invalid and re-match() to get fresh identifiers.

Store name in your database, not id. The id is a cache key that changes across versions; name is the stable primary reference.

?include= — slice the bundle

The full bundle is large. Ask for only the categories you need:

curl -G https://zyins.isaapi.com/v3/datasets \
  -H "Authorization: Bearer $ISA_TOKEN" \
  --data-urlencode 'include=conditions,medications'

Omitted categories arrive as undefined on the typed bundle. The SDK treats them as empty arrays, so match() against an omitted category returns UnknownConcept instead of throwing an error.

?fields=meta — version-only probe

Polling for staleness? Ask for metadata only:

curl https://zyins.isaapi.com/v3/datasets?fields=meta \
  -H "Authorization: Bearer $ISA_TOKEN"

Each datasets[<category>] entry still carries version and item_count; items is omitted (the SDK normalizes the absence to an empty array). Compare per-category version to the one you cached. If anything moved, re-fetch the full bundle and warm the SDK's bundle cache:

import { Isa } from 'isa-sdk';

const isa = await Isa.withBearer();
await isa.zyins.datasets.get();

The next match(), autocomplete(), or autocorrector.correct() call sees the fresh bundle automatically. The SDK rebuilds the cached typo map and frequency map on first use after the bundle changes.

Conditional revalidation

The endpoint honors If-None-Match. Pass the previous response's ETag and on no-change the server returns 304 Not Modified with no body. The SDK handles this transparently; on a 304, get() resolves to a sentinel you can short-circuit on:

import { Isa } from 'isa-sdk';

const isa = await Isa.withBearer();

const result = await isa.zyins.datasets.get();
if ('notModified' in result) {
  // Use the previous bundle; the SDK cache is already current.
} else {
  // Fresh bundle; the SDK cache has been swapped under the same handle.
  console.log(result.version);
}

Code samples

TypeScript

import { Isa } from 'isa-sdk';

const isa = await Isa.withBearer();

await isa.zyins.datasets.get();           // warm the SDK cache

const hbp = isa.zyins.conditions.match('high blood pressure');
console.log(hbp.id, hbp.name, hbp.isKnown);
// cond_01KSR2WVAGC05ZGR6FA4QYEA8X  HIGH BLOOD PRESSURE  true

for (const med of hbp.medications(isa.zyins.reference.Sort.MostCommonFirst)) {
  console.log(med.name);
}
// LISINOPRIL
// AMLODIPINE
// LOSARTAN

Python

from isa_sdk import Isa
from isa_sdk.zyins.reference_v3 import Sort

isa = Isa.with_bearer()              # reads ISA_TOKEN; sync, no await

# The reference namespace fetches and caches the dataset bundle on first
# use, so match() / autocomplete() work straight after construction.
hbp = isa.zyins.conditions.match('high blood pressure')
print(hbp.id, hbp.name, hbp.is_known)

for med in hbp.medications(Sort.MOST_COMMON_FIRST):
    print(med.name)

Go

ctx := context.Background()
if _, err := isa.Zyins.Datasets.Get(ctx); err != nil {
    log.Fatal(err)
}

hbp := isa.Zyins.Conditions.Match("high blood pressure")
fmt.Println(hbp.ID, hbp.Name, hbp.IsKnown)

for _, med := range hbp.Medications(reference.SortMostCommonFirst) {
    fmt.Println(med.Name)
}

PHP

$isa->zyins->datasets->get();

$hbp = $isa->zyins->conditions->match('high blood pressure');
echo $hbp->id, ' ', $hbp->name, ' ', var_export($hbp->isKnown, true), PHP_EOL;

foreach ($hbp->medications(Sort::MostCommonFirst) as $med) {
    echo $med->name, PHP_EOL;
}

curl

curl https://zyins.isaapi.com/v3/datasets \
  -H "Authorization: Bearer $ISA_TOKEN" \
  -G --data-urlencode 'include=conditions,medications'

What changed from v2

v2 (/v2/reference-data)v3 (/v3/datasets)
medications_by_condition response-root mapInline treated_with[] on each condition row
frequency_graphs.use_map response-root mapInline prescription_count on each inline entry
Conditions nested inside medicationsFlat top-level conditions[] + medications[]
Raw display strings as keysULID id everywhere
Client-side make_key and reverse joinsServer-side authoritative shape

If you wrote any of lookupByCondition, frequencyOf, useMap, buildIndex, normalizeKey on the v2 surface, delete it. The row is the source of truth.

Why this matters for licensing

Every row is independently meaningful. A licensee who consumes only conditions[] does not need to also accept medications[] to render "Most Common medications for X" — the data is already on the condition row. See Licensing the datasets for the standalone-licensing posture.