Skip to main content

Production-ready Python client for the NLM UMLS REST APIs.

Project description

UMLS Python Client

Production-ready Python SDK for the National Library of Medicine UMLS Terminology Services APIs.

umls-python-client keeps the original UMLSClient interface for existing users and adds typed sync, async, export, release, and workflow helpers for new applications. It is designed for developers and researchers who need a practical one-stop Python client for UMLS search, concepts, source vocabularies, semantic types, crosswalks, metadata, and UTS release downloads.

Why This Client

  • Current NLM REST coverage, including the May 4, 2026 search filters semanticTypes and semanticGroups.
  • Typed sync and async clients built on httpx.
  • Backward-compatible legacy client with the original camelCase namespaces.
  • Structured exceptions for modern clients and legacy error payloads for older code.
  • JSON, JSONL, CSV, and RDF/Turtle exports.
  • Practical helpers for bulk search, bulk crosswalk, concept profiles, source lookup, UMLS URL following, API-key validation, and release downloads.
  • CI across Python 3.9 through 3.14.

Installation

pip install umls-python-client

For local development:

pip install ".[dev,docs]"

Authentication

Most UMLS requests require an API key from your UTS profile: https://documentation.uts.nlm.nih.gov/rest/authentication.html

import os

api_key = os.environ["UMLS_API_KEY"]

The metadata sources endpoint is public and does not require authentication, but the client still uses one consistent client configuration.

Typed Sync Quickstart

from umls_python_client import TypedUMLSClient

with TypedUMLSClient(api_key="YOUR_UMLS_API_KEY") as client:
    response = client.search_api.search(
        "diabetes",
        semantic_groups="Disorders",
        page_size=25,
    )

    for result in response.result:
        print(result.ui, result.name)

Typed methods return UMLSResponse[T]. Use response.result for parsed models, response.raw or response.to_dict() for the original UMLS envelope, and response.to_rdf() for Turtle RDF.

Async Quickstart

from umls_python_client import AsyncUMLSClient


async def main() -> None:
    async with AsyncUMLSClient(api_key="YOUR_UMLS_API_KEY") as client:
        response = await client.crosswalk_api.get_crosswalk(
            source="HPO",
            id="HP:0001947",
            target_source="SNOMEDCT_US",
        )
        print(response.result)

Legacy Compatible Usage

UMLSClient keeps existing imports, JSON string defaults, and camelCase namespaces:

from umls_python_client import UMLSClient

client = UMLSClient(api_key="YOUR_UMLS_API_KEY")

pretty_json = client.searchAPI.search("diabetes")
raw_dict = client.search_api.search("diabetes", return_indented=False)
rdf = client.cui_api.get_cui_info("C0011849", format="rdf")

Existing namespaces are preserved:

  • client.searchAPI
  • client.sourceAPI
  • client.cuiAPI
  • client.semanticNetworkAPI
  • client.crosswalkAPI
  • client.metadataAPI
  • client.atomAPI
  • client.authAPI
  • client.releaseAPI

Modern namespaces are also available:

  • search_api
  • source_api
  • cui_api
  • semantic_network_api
  • crosswalk_api
  • metadata_api
  • atom_api
  • auth_api
  • release_api

Common Recipes

Semantic Search

response = client.search_api.search(
    "depression",
    semantic_types="T047|T046",
    semantic_groups="Disorders",
)

semantic_types supports semantic type TUIs, semantic type names, and semantic tree number prefixes. Use pipes for multiple values, matching NLM's search documentation.

Source Code To CUI

response = client.search_api.search(
    "9468002",
    input_type="sourceUi",
    search_type="exact",
    sabs="SNOMEDCT_US",
)

HPO To SNOMED CT Crosswalk

response = client.crosswalk_api.get_crosswalk(
    source="HPO",
    id="HP:0001947",
    target_source="SNOMEDCT_US",
)

UMLS CUI crosswalks are useful starting points for mapping work. Review results before using them in clinical or research pipelines.

Concept Profile

profile = client.cui_api.get_concept_profile(
    "C0011849",
    include_atoms=False,
).result

print(profile.concept.name)
print([definition.value for definition in profile.definitions])

Metadata Lookup

sources = client.metadata_api.find_source(abbreviation="SNOMEDCT_US").result

Bulk Workflows

searches = client.search_api.bulk_search(["diabetes", "asthma"])
crosswalks = client.crosswalk_api.bulk_crosswalk(
    ["HP:0001947", "HP:0001250"],
    source="HPO",
    target_source="SNOMEDCT_US",
)

Follow UMLS URLs

Many UMLS payload fields contain URLs to related resources. Follow those URLs with the same authenticated client:

concept = client.cui_api.get_cui_info("C0011849").result
atoms = client.follow_url(concept.raw["atoms"])

Release Downloads

releases = client.release_api.list_releases(
    release_type="umls-full-release",
    current=True,
)

client.release_api.download_file(
    url=releases.result[0].url,
    path="downloads",
)

Call list_releases() without a release_type to inspect NLM's release catalog, or pass a release type such as umls-full-release to discover current download URLs.

Exports

Typed responses can save themselves:

response = client.search_api.search("fracture", page_size=25)

response.save("exports/search", format="jsonl")
response.save("exports/search.csv", format="csv")
response.save("exports/search.ttl", format="rdf")

Clients can export any response or raw payload:

client.export(response, "exports/search.json", format="json", overwrite=True)

Supported formats:

Format Output
json Full UMLS response envelope
jsonl One result record per line
csv Flattened scalar result fields
rdf Turtle RDF

If the path has a file suffix, the client writes exactly there. If the path is a directory or suffixless path, parent directories are created and a safe filename is generated.

Legacy save_to_file=True still works and now delegates to the same export implementation.

Endpoint Coverage

Namespace Coverage Pagination behavior
search_api /search/{version} with semantic filters Sends pageSize; no obsolete pageNumber
metadata_api /metadata/{version}/sources No auth required
cui_api CUI detail, atoms, preferred atom, definitions, relations Pagination where NLM documents it
atom_api AUI detail, parents, children, ancestors, descendants Sends pageSize; no pageNumber
source_api Source detail, atoms, preferred atom, hierarchy, attributes, relations Pagination where NLM documents it
crosswalk_api Source identifier crosswalk Supports documented pagination
semantic_network_api Semantic type lookup Single resource
auth_api UMLS license/API-key validation UTS validation endpoint
release_api Release listing and authenticated downloads UTS release/download endpoints

Error Handling

Typed clients raise structured exceptions:

  • UMLSRequestError
  • UMLSHTTPError
  • UMLSDecodeError

Legacy UMLSClient methods keep returning error payload dictionaries instead of raising for UMLS request failures.

Configure timeouts and retries at client construction:

client = TypedUMLSClient(
    api_key="YOUR_UMLS_API_KEY",
    timeout=20.0,
    retries=3,
)

Testing

ruff check .
ruff format --check .
mypy src
pytest
mkdocs build --strict
python -m build

Live integration tests are optional and require UMLS_API_KEY. Tests that would validate user keys or download release files remain opt-in and do not run in default CI.

Migration Notes

From 1.0.x and 1.1.0:

  • Existing imports and UMLSClient behavior remain supported.
  • Prefer TypedUMLSClient for new sync code.
  • Prefer AsyncUMLSClient for async applications.
  • Prefer response.save(...) or client.export(...) over new uses of save_to_file=True.
  • Use snake_case namespaces in new code. CamelCase namespaces remain available for compatibility.

Documentation

Releases

This repository uses Release Please and PyPI trusted publishing. Merged commits should use Conventional Commit prefixes:

  • fix: for patch releases
  • feat: for minor releases
  • feat!: or fix!: for major releases

Release Please opens a release PR. Merging that release PR creates the GitHub Release, builds distributions, attaches artifacts, and publishes to PyPI.

GitHub Actions must be allowed to create release PRs, or the repository must provide a RELEASE_PLEASE_TOKEN secret with PR permissions.

License

Apache-2.0. See LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

umls_python_client-1.2.0.tar.gz (39.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

umls_python_client-1.2.0-py3-none-any.whl (37.8 kB view details)

Uploaded Python 3

File details

Details for the file umls_python_client-1.2.0.tar.gz.

File metadata

  • Download URL: umls_python_client-1.2.0.tar.gz
  • Upload date:
  • Size: 39.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for umls_python_client-1.2.0.tar.gz
Algorithm Hash digest
SHA256 ba86fbb2ba3f70931cfc62295805839a2b2d3771c3c0941c1f38183856587daf
MD5 055eee355526b74bcc39d0808846deb7
BLAKE2b-256 48fca024ee2932322a72664b676ec5557edf1fbf3506db6b4908c06dc16c88ce

See more details on using hashes here.

Provenance

The following attestation bundles were made for umls_python_client-1.2.0.tar.gz:

Publisher: release-please.yml on palasht75/umls-python-client

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file umls_python_client-1.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for umls_python_client-1.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 c782eff4311d7b96c4df51977eff17fa65da81a3bb331c521d50679cacf7dca7
MD5 f85d7c4eb9726c9b1852bbe8022c5e19
BLAKE2b-256 f6fd003bebfb60a9b2166e2bc14b316eb6337425bef42ea71105888aa7c1b06e

See more details on using hashes here.

Provenance

The following attestation bundles were made for umls_python_client-1.2.0-py3-none-any.whl:

Publisher: release-please.yml on palasht75/umls-python-client

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page