Batch concept requests preserve JSON arrays for single concept IDs and vocabulary filters, including named input vectors. Vocabulary filters must contain non-missing strings; invalid filter types are rejected before sending.
Recommendations now preserve JSON arrays for single source concepts and single-item relationship, vocabulary, and domain filters. Named vectors also remain arrays. Filters reject missing strings before sending. Boolean flags and pagination values retain their scalar types.
get_by_code() percent-encodes vocabulary IDs and concept codes as individual
path segments, including literal percent sequences and slashes such as ICD-O
8032/3, with or without hierarchy, synonym, relationship, or vocabulary-release
query options.
HTTP failures now raise the documented OMOPHub condition classes instead of
only httr2's generic ones (#137): 400 → omophub_validation_error, 401 or
invalid_api_key / missing_api_key → omophub_auth_error, 403 →
omophub_forbidden_error (new; kept distinct from invalid credentials),
404 → omophub_not_found, 429 → omophub_rate_limit_error, 5xx →
omophub_server_error, other statuses → omophub_api_error. Network
failures raise omophub_connection_error. API conditions carry
status_code, error_code, details, request_id, endpoint, and (for
429) retry_after. The httr2 classes (httr2_http_404, httr2_http,
httr2_failure, ...) and e$resp are preserved, so existing handlers keep
working. Empty error-message arrays or objects fall back to the HTTP status
without masking the original failure.
/search/autocomplete endpoint and
returns its compact suggestion, type, and count fields. domain_ids,
page_size, and the warned compatibility aliases remain supported.source_concept and lower-bound totals.domain_ids and page_size, while retaining warned
compatibility aliases for domains and max_suggestions. Similarity search
now uses the API's semantic default algorithm.include_invalid = FALSE never reached the server on
client$mappings$map(). The method now sends its documented default
explicitly. Mapping documentation also describes unmapped_sources, which
reports every input that was not mapped and why.
Autocomplete documentation and tests used an incomplete response shape. They now document and exercise all seven fields returned for each suggestion.
jsonlite dependency and regenerated package manuals
so their signatures match the current source.Mapping pagination - client$mappings$get() accepts page and
page_size. GET /v1/concepts/{id}/mappings became paginated;
page_size defaults to 100,
matching the old cap, so an existing call returns exactly the page it
returned before. Pagination metadata is attached to the result as the
pagination attribute - read it with attr(result, "pagination").
client$mappings$get_all() - walks every page and returns one tibble of
all mappings for a concept. Prefer it over get() when assembling a code
list; a partial code list is wrong in a way nothing in the result reveals.
Takes max_pages and progress like the other *_all() methods.
relationship_ids on client$mappings$get() and get_all() - a
character vector of relationship types. The server defaults to "Maps to",
so a composite concept returns only half its decomposition unless
"Maps to value" is asked for too: "Allergy to penicillin G" maps to
"Allergy to drug" via Maps to and to "penicillin G" via Maps to value.
client$mappings$get() returned a different shape once the API added
pagination. perform_get() switches its return shape based on whether the
response carries meta.pagination.
include_invalid = FALSE never reached the server on
client$mappings$get() and get_all(). The parameter was only sent when
TRUE, and this endpoint defaults to including deprecated mappings, so
asking to exclude them did nothing. The default is now NULL (take the
server default); pass FALSE to exclude. Omitting it behaves exactly as
before, so only callers who explicitly passed FALSE - and were being
ignored - see a change.
client$search$semantic() and
client$search$semantic_all() now call GET /v1/search/semantic instead of
GET /v1/concepts/semantic-search. The legacy path remains a permanent
server-side alias (emits Deprecation: true + Link: …rel="successor-version"
headers), so older installations of this SDK continue to work - no breaking
change for callers.FHIR Value-as-Concept - the resolve_batch(as_tibble = TRUE) tibble now
includes value_as_concept_id and value_as_concept_name columns, populated
when the resolver decomposes a composite concept via the Maps to value
relationship (HL7 FHIR-to-OMOP IG Value-as-Concept pattern - e.g. "Allergy to
penicillin" yields a standard "Allergy to drug" plus a value "Penicillin G").
on_unmapped for FHIR resolution - resolve(), resolve_batch(), and
resolve_codeable_concept() gained an on_unmapped argument ("error"
default / "sentinel"). With "sentinel" the resolver returns a
concept_id 0 record instead of a 404 when nothing resolves, so ETL
pipelines always get a row (matches the Python SDK).
Maps to target now reports status = "unmapped"
(with standard_concept_id = 0) instead of "resolved", matching the OMOP /
FHIR-to-OMOP IG convention that an unmapped concept is concept_id 0. Code
that filters status == "resolved" will no longer treat these sentinels as
successful mappings.Tibble output for batch FHIR resolution
FhirResource$resolve_batch() (and the standalone fhir_resolve_batch())
gained an as_tibble parameter. When as_tibble = TRUE, the call returns
a flat tibble::tibble with one row per input coding and columns for the
source concept, standard concept, target CDM table, mapping type, and
resolution status - ready to pipe into dplyr / tidyr. The batch
summary (total / resolved / failed) is attached as
attr(result, "summary"). Default behavior is unchanged: as_tibble = FALSE
still returns the legacy list shape.
Standalone wrapper functions
Thin, pipe-friendly wrappers around the R6 FhirResource methods:
fhir_resolve(client, ...)fhir_resolve_batch(client, ...)fhir_resolve_codeable_concept(client, ...)Both the R6 form (client$fhir$resolve(...)) and the standalone form
work; pick whichever reads better in your pipeline.
FHIR client interop helper
New exported function omophub_fhir_url(version) returning the OMOPHub
FHIR Terminology Service base URL for a given FHIR version ("r4",
"r4b", "r5", "r6"). Use it with httr2, fhircrackr, or any
external FHIR client that wants to talk to OMOPHub's FHIR endpoint
directly.
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 FHIR Coding (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.
resolve_codeable_concept(): Resolve a FHIR CodeableConcept with
multiple codings. Automatically picks the best match per OHDSI vocabulary
preference (SNOMED > RxNorm > LOINC > CVX > ICD-10). Falls back to the
text field via semantic search when no coding resolves.
Bulk lexical search (bulk_basic()): Execute up to 50 keyword searches
in a single API call. Supports shared default filters for vocabulary, domain,
and other parameters. Each search is identified by a unique search_id for
result matching. Maps to POST /v1/search/bulk.
Bulk semantic 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. Query length validated at 1-500
characters. Maps to POST /v1/search/semantic-bulk.
Semantic search (semantic(), semantic_all()): 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_all() provides automatic pagination with progress bar.
Similarity 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.
Hierarchy get() method: New method to retrieve complete concept hierarchy (ancestors and descendants) in a single call with support for "flat" or "graph" visualization formats.
Vocabulary domain_stats() method: New method to get statistics for a specific domain within a vocabulary.
Vocabulary concept_classes() method: New method to list all available concept classes.
Added vocab_release parameter to concepts, mappings, relationships, and hierarchy methods for explicit vocabulary version pinning.
Added include_hierarchy parameter to concepts$get() and concepts$get_by_code().
API parameter naming: Updated to match OMOPHub API v1.3.0 specifications:
limit → page_size for paginationvocabulary, domain → vocabulary_ids, domain_ids for filteringmax_results → page_size for result limitsrelationship_type → relationship_ids for relationship filteringtarget_vocabularies → target_vocabulary (singular) in mappingsvocabulary_id → vocabulary_ids (plural) in hierarchy methodsAPI simplifications: Several methods now have fewer parameters to match the simplified backend API:
mappings$get(): Removed direction, include_indirect, standard_only, include_mapping_quality, include_synonyms, include_context, paginationdomains$list(): Simplified to single include_stats parametervocabularies$get(): Now takes only vocabulary_idvocabularies$domains(): Now takes no parametersBatch limits: concepts$batch() maximum reduced from 1000 to 100 concepts per request.
Default changes:
concepts$batch() standard_only default changed from FALSE to TRUErelationships$get() default page_size changed from 50 to 100include_synonyms and include_relationships parameters to get_by_code() for retrieving concept synonyms and relationships in a single request.OMOPHub-SDK-R/{version}.OMOPHubClient for accessing OMOPHub APIhttr2::req_throttle()basic_all()) returning tibblesOMOPHUB_API_KEY)vocab_version parameter