All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
1.6.0 - 2026-04-10
- FHIR-to-OMOP Concept Resolver (
client.fhir): Translate FHIR coded values into OMOP standard concepts, CDM target tables, and optional Phoebe recommendations in a single API call.resolve(): Resolve a single FHIRCoding(system URI + code) or text-only input via semantic search fallback. Returns the standard concept, target CDM table, domain alignment check, and optional mapping quality signal.resolve_batch(): Batch-resolve up to 100 FHIR codings per request with inline per-item error reporting. Failed items do not fail the batch.resolve_codeable_concept(): Resolve a FHIRCodeableConceptwith multiple codings. Automatically picks the best match per OHDSI vocabulary preference (SNOMED > RxNorm > LOINC > CVX > ICD-10). Falls back to thetextfield via semantic search when no coding resolves.
- New TypedDict types for FHIR resolver:
FhirResolveResult,FhirResolution,FhirBatchResult,FhirBatchSummary,FhirCodeableConceptResult,ResolvedConcept,RecommendedConceptOutput. - Both sync (
OMOPHub) and async (AsyncOMOPHub) clients support FHIR resolver methods viaclient.fhir.*.
- Extracted shared response parsing (
_request.py): The duplicated JSON decode / error-handling / rate-limit-retry logic acrossRequest._parse_response,Request._parse_response_raw,AsyncRequest._parse_response, andAsyncRequest._parse_response_raw(4 copies of ~50 lines each) is now a single_parse_and_raise()module-level function. All four methods delegate to it, eliminating the risk of divergence bugs. - Fixed
paginate_asyncsignature (_pagination.py): The type hint now correctly declaresCallable[[int, int], Awaitable[tuple[...]]]instead ofCallable[[int, int], tuple[...]], and the runtimehasattr(__await__)duck-typing hack has been replaced with a cleanawait. AsyncSearch.semantic_iternow delegates topaginate_asyncinstead of manually reimplementing the pagination loop, matching the syncsemantic_iterwhich already usespaginate_sync.
- Python prerequisite in CONTRIBUTING.md corrected from
3.9+to3.10+(matchingpyproject.toml). __all__intypes/__init__.pysorted per RUF022.
1.5.1 - 2026-04-08
- Rate-limit handling: HTTP client now respects the
Retry-Afterheader on429 Too Many Requestsresponses and applies exponential backoff with jitter on retries. Previous versions retried only on502/503/504with a fixed2^attempt * 0.5sschedule and did not back off on429at all, so a client that hit the server's rate limit at high volume could burn through thousands of failed requests in a tight loop. The client now honorsRetry-After, uses exponential backoff with jitter, respects the configuredmax_retries, and caps backoff at 30 seconds. - Updated
examples/search_concepts.pyto reflect current API.
1.5.0 - 2026-03-26
- Bulk lexical search (
search.bulk_basic()): Execute up to 50 keyword searches in a single API call. Supports shared defaults for vocabulary, domain, and other filters. Each search is identified by a uniquesearch_idfor result matching. Maps toPOST /v1/search/bulk. - Bulk semantic search (
search.bulk_semantic()): Execute up to 25 natural-language searches using neural embeddings in a single call. Supports per-search similarity thresholds and shared defaults. Includes query enhancement data (abbreviation expansion, misspelling correction). Maps toPOST /v1/search/semantic-bulk. - New TypedDict types for bulk search:
BulkSearchInput,BulkSearchDefaults,BulkSearchResponse,BulkSearchResultItem,BulkSemanticSearchInput,BulkSemanticSearchDefaults,BulkSemanticSearchResponse,BulkSemanticSearchResultItem,QueryEnhancement. - Both sync (
OMOPHub) and async (AsyncOMOPHub) clients support bulk search methods.
- Updated
__all__exports to alphabetical order (ruff RUF022 compliance). BulkSearchInputandBulkSemanticSearchInputnow useRequired[str]forsearch_idandqueryfields for proper type checking.
1.4.1 - 2026-02-28
- User-Agent header now reports actual SDK version (e.g.,
OMOPHub-SDK-Python/1.4.1) instead of hardcoded0.1.0. Version is resolved at runtime viaimportlib.metadata.
1.4.0 - 2026-02-23
- Semantic search (
search.semantic(),search.semantic_iter()): Natural language concept search using neural embeddings. Search for clinical intent like "high blood sugar levels" to find diabetes-related concepts. Supports filtering by vocabulary, domain, standard concept, concept class, and minimum similarity threshold.semantic_iter()provides automatic pagination. - Similarity search (
search.similar()): Find concepts similar to a reference concept ID, concept name, or natural language query. Three algorithm options:'semantic'(neural embeddings),'lexical'(string matching), and'hybrid'(combined). Configurable similarity threshold with optional detailed scores and explanations.
1.3.1 - 2026-01-24
- Fixed
search.basic_iter()pagination bug that caused only the first page of results to be returned. The iterator now correctly fetches all pages when iterating through search results.
- Added
get_raw()method to internal request classes for retrieving full API responses with pagination metadata. - Expanded
search.basic_iter()method signature to explicitly list all filter parameters instead of using**kwargs.
1.3.0 - 2026-01-06
Parameter Renames (for API consistency):
search.autocomplete():max_suggestions→page_sizeconcepts.suggest():vocabulary→vocabulary_ids,domain→domain_ids,limit→page_sizeconcepts.related():relatedness_types→relationship_typesconcepts.relationships():relationship_type→relationship_idsrelationships.get():relationship_type→relationship_ids,target_vocabulary→vocabulary_idshierarchy.ancestors():vocabulary_id→vocabulary_ids,include_deprecated→include_invalidhierarchy.descendants():vocabulary_id→vocabulary_ids,include_deprecated→include_invalid
Simplified APIs (removed parameters):
vocabularies.get(): Removedinclude_stats,include_domains(usestats()method instead)vocabularies.domains(): Removed pagination parameters, now returns all domainsdomains.list(): Simplified to singleinclude_statsparameterdomains.concepts(): Removedconcept_class_ids, addedinclude_invalidmappings.get(): Simplified totarget_vocabulary,include_invalid,vocab_releaserelationships.types(): Removed all filtering parameters
Default Changes:
vocabularies.list(): Defaultpage_sizechanged from 100 to 20concepts.batch(): Defaultstandard_onlychanged fromFalsetoTrue
vocabularies.domain_stats(vocabulary_id, domain_id)- Get statistics for a specific domain within a vocabularyvocabularies.concept_classes()- Get all concept classeshierarchy.get(concept_id)- Get complete hierarchy (ancestors and descendants) in one callvocab_releaseparameter toconcepts.get(),concepts.get_by_code(),mappings.get(),mappings.map()include_hierarchyparameter toconcepts.get()andconcepts.get_by_code()- Pagination support to
concepts.suggest() domain_ids,standard_only,include_reverseparameters torelationships.get()
1.2.0 - 2025-12-09
include_synonymsandinclude_relationshipsparameters toconcepts.get_by_code()method for retrieving concept synonyms and relationships in a single request.
- User-Agent header updated to
OMOPHub-SDK-Python/{version}.
0.1.0 - 2025-12-01
- Initial release of the OMOPHub Python SDK
- Synchronous client (
OMOPHub) and asynchronous client (AsyncOMOPHub) - Full support for all OMOPHub API endpoints:
- Concepts: get, get_by_code, batch, suggest, related, relationships
- Search: basic, advanced, autocomplete
- Hierarchy: ancestors, descendants, paths
- Relationships: get, types
- Mappings: get, map, bulk
- Vocabularies: list, get, stats, domains, concepts
- Domains: list, get, concepts
- TypedDict type definitions for all API responses
- Automatic retry with exponential backoff
- Rate limit handling with Retry-After support
- Comprehensive exception hierarchy
- Auto-pagination iterators for search results
- Full type hints and PEP 561 compliance
- HTTP/2 support via httpx