Python SDK
healthcare-dev: typed sync and asyncio clients with retries, pagination and batch helpers.
The Python SDK has the same surface as the TypeScript SDK, with a sync and an asyncio client. Python 3.9 or later.
Not on PyPI yet. It will be published as healthcare-dev (import healthcare_dev); until
then, install it from the repository's packages/sdk-py.
from healthcare_dev import HealthcareDev, NotFoundError
hdev = HealthcareDev() # reads HDEV_API_KEY
r = hdev.codes.get("icd10cm", "E11.9")
print(r["data"]["display"], r["data"]["billable"], r["meta"]["data_version"])
# One page, or every result
page = hdev.codes.search("icd10cm", q="type 2 diabetes kidney", billable=True)
for code in hdev.codes.iterate("hcpcs", q="wheelchair"):
print(code["code"])
# Hierarchy, batch (any length, split into requests of 100) and drugs
tree = hdev.codes.hierarchy("icd10cm", "E11.22")
many = hdev.codes.batch("icd10cm", ["E11.9", "I10", "NOPE"])
product = hdev.drugs.ndc("0002-0152-01") # includes linked RxNorm concepts
# Medicare enrollment, opt-out and OIG exclusions for an NPI; each answer has a `note`
enrolled = hdev.providers.enrollment("1881018208")
excl = hdev.providers.exclusions("1922348218") # matched by NPI as listed by OIG
by_name = hdev.exclusions.search(q="dunn medical", state="MS")
try:
hdev.codes.get("icd10cm", "XYZ")
except NotFoundError as err:
print(err.detail)import asyncio
from healthcare_dev import AsyncHealthcareDev
async def main() -> None:
async with AsyncHealthcareDev() as hdev:
r = await hdev.drugs.full("0006-3026-02", view="compact")
print(r["data"]["flags"])
async for change in hdev.changes.iterate(dataset="icd10cm", order="desc"):
print(change["kind"], change["key"])
asyncio.run(main())Method names are the TypeScript ones in snake case (care_categories.iterate_codes,
drugs.search_asp), and parameters are keyword arguments: billable=True,
fields=["code", "display"], and from_="2026-01-01" for from. Child keys are
hdev.keys.create, list, get, update and revoke; a route outside a key's scopes raises
PermissionDeniedError with required_scope.
Webhooks
Pro plan and up. Subscribe once and store the secret (shown only in the create response), then
verify every delivery against the raw body with verify_webhook. It checks the signature in
constant time and the timestamp within five minutes, and raises WebhookVerificationError
otherwise. See Webhooks.
from healthcare_dev import HealthcareDev, verify_webhook
created = HealthcareDev().webhooks.create(
{
"url": "https://example.com/hooks/healthcare-dev",
"events": ["dataset.released", "record.changed"],
"subjects": ["E11.9", "J1817"],
}
)
# save created["data"]["secret"]
# In your handler (Flask shown): the raw body, not re-serialized JSON
event = verify_webhook(SECRET, request.headers, request.get_data())Behavior
- Retries: 429
rate-limited, 5xx and network errors are retried twice with exponential backoff and jitter, honoringRetry-After.QuotaExceededErroris never retried. Writes (POST and DELETE: reporting an issue, creating, replaying or deleting a webhook) are sent once; batch lookups are reads and are retried. - Timeout: a deadline for each attempt, request and body together (in the sync client, one
stalled network read can add up to one more
timeout). - Errors: every failure is a
HealthcareDevError; API problems areApiErrorsubclasses withstatus, the stable problemcode,detailandrequest_id. Network failures and timeouts arehealthcare_dev.ConnectionError, which also subclasses the built-in one. - Responses: dicts typed as
Response[T],{"data", "meta", "links"}, as in Responses. - Options:
api_key,base_url,max_retries(2),timeout(30 seconds),user_agent,http_client(your ownhttpxclient). is_valid_npi,to_ndc11,ndc_prefixandndc_product_keywork offline, with the same rules as the API.
Types are generated from the same OpenAPI spec as this reference, so they never drift from the API.