Overview
OMOPHub exposes its vocabulary data through a standards-compliant FHIR Terminology Service at/fhir/{r4,r5,r6}/. Any FHIR-compatible client (HAPI FHIR, Firely, etc.) can query OMOP concepts using standard FHIR operations.
This is NOT a full FHIR server - it serves terminology resources only (CodeSystem, ConceptMap, ValueSet). For clinical resources, continue using your FHIR server and point it at OMOPHub for terminology resolution.
OMOPHub’s FHIR-to-OMOP mappings follow the HL7 FHIR-to-OMOP Implementation
Guide (Informative 1, v1.0.0),
including its administrative ConceptMaps (see Administrative
ConceptMaps below).
Endpoints
OMOPHub Extensions
These operations and properties are OMOPHub-specific and not part of the FHIR Terminology Service specification.FHIR Versions
All four FHIR versions are supported from the same endpoint:/fhir/r4/- FHIR R4 (4.0.1) - US Cures Act, EHDS mandate/fhir/r4b/- FHIR R4B (4.3.0)/fhir/r5/- FHIR R5 (5.0.0)/fhir/r6/- FHIR R6 (6.0.0)/fhir/- Defaults to R4
Authentication
OMOPHub supports two authentication methods for FHIR operations. Both use the same API key (oh_xxx) from your dashboard and share the same rate-limit and metering pool.
Bearer token (default)
Pass the API key directly in theAuthorization header:
OAuth2 client_credentials (for Spring-based clients)
FHIR clients built on Spring Security OAuth2 - HAPI FHIR JPA Starter, EHRbase, most Java/Kotlin Spring Boot stacks - expect to obtain a Bearer token from an OAuth2 token endpoint. OMOPHub exposes a minimal RFC 6749 client_credentials shim at https://fhir.omophub.com/oauth2/token:
access_token ({"access_token": "oh_...", "token_type": "Bearer", "expires_in": 31536000}). Both client_secret_basic (HTTP Basic auth header, Spring’s default) and client_secret_post (form body) authentication methods are accepted. client_secret is not validated - the client_id is the sole credential. Supply any non-empty placeholder for client_secret to satisfy Spring’s config schema.
For full walkthroughs, see the HAPI FHIR and EHRbase / openEHR integration guides.
Content Type
OMOPHub responds withContent-Type: application/fhir+json by default and serves FHIR XML on request. Content negotiation follows RFC 7231 §5.3.2 with two OMOPHub-specific rules:
- JSON wins on ties. When a client advertises both JSON and XML at the same q-value (HAPI FHIR’s default client sends
Accept: application/fhir+xml;q=1.0, application/fhir+json;q=1.0, ...), OMOPHub returns JSON. XML is served only when XML is strictly preferred - i.e. the client’s highest-scoring XML media type has a higher q-value than its highest-scoring JSON media type. - Wildcards are honored.
*/*andapplication/*count as matches at their advertised q-value, so a client sendingAccept: */*receives JSON (the default), and a client sendingAccept: application/*, application/fhir+xml;q=0.5also receives JSON (the wildcard matches JSON at q=1.0, which beats the explicit XML at q=0.5).
Requesting XML explicitly
SendAccept: application/fhir+xml (with no JSON at equal or higher q-value):
XML support matrix
OMOPHub’s XML serializer is clean for single-resource responses and best-effort for Bundle-shaped responses. Request JSON for the Bundle-shaped endpoints unless you have a specific reason to need XML.Pre-auth error responses come back as JSON even when XML was requested.
When a request fails authentication (401, missing or invalid API key) or
exhausts the monthly quota (429), the FHIR-scoped error middleware rewrites
the response into an
OperationOutcome resource but emits it as JSON
regardless of Accept. The response body is still valid FHIR OperationOutcome- HAPI, Firely, and most FHIR clients parse it correctly - it’s only the content-type header and wire format that don’t honor the XML preference. Handler-emitted errors (404 unknown code, 400 bad parameter, 403 restricted vocab, 500 internal) do respect the Accept header and return XML.
/fhir/* path - including auth failures, missing routes, and unsupported operations - are returned as FHIR OperationOutcome resources in whichever format the client negotiated (JSON by default, XML when requested). The generic REST JSON envelope ({"success": false, "error": {...}}) is never used on FHIR routes.
CodeSystem URLs
OMOPHub serves CodeSystem resources at two equivalent URL shapes:-
Canonical per-vocabulary URIs - e.g.
http://snomed.info/sct,http://loinc.org,http://www.nlm.nih.gov/research/umls/rxnorm. These resolve to per-vocabulary stubs (content: "not-present") and are what FHIR clients like HAPI and EHRbase use for discovery. Every URI in the Supported Vocabularies table is a valid CodeSystem URL. -
Unified OMOP omnibus URL -
https://fhir-terminology.ohdsi.org. A single CodeSystem covering all 130+ OMOP vocabularies byconcept_id. This is the OHDSI community canonical URL; use it when you want to address concepts by their OMOP internal ID rather than by vocabulary-specific code.
$lookup and $validate-code dispatch on the system / url parameter, so you can use whichever matches your client’s expectations. Codes resolved via OMOPHub are interchangeable with codes from any other FHIR server serving OMOP vocabularies.
Discover the full list of supported URLs with CodeSystem search or the metadata endpoint.
Supported Vocabularies
Query CodeSystem search without aurl parameter for the live list, or see the current registry below. Each row is a valid CodeSystem URL (usable in $lookup, $validate-code, $translate, etc.) with a corresponding stub id (usable in GET /CodeSystem/{id}).
Administrative ConceptMaps
Some FHIR resources carry administrative/structural codes that have no OMOP vocabulary-table representation — gender, encounter class, condition status, immunization route, and the like. OMOPHub resolves these via the HL7 FHIR-to-OMOP IG ConceptMaps. Both the FHIR Resolver (POST /v1/fhir/resolve) and ConceptMap/$translate accept these source systems:
The IG relationship is preserved: an
equivalent mapping is an exact match,
while source-is-broader-than-target / source-is-narrower-than-target are
approximate. The resolver surfaces this in relationship_id (and a
mapping_note advisory); $translate returns the corresponding FHIR
equivalence/relationship. A few codes (e.g. admit-source other) are
intentionally unmapped in the IG and resolve to concept_id 0.allergy-intolerance-category codes map under both AllergyType and
IntoleranceType — the resolver returns the allergy interpretation as the
primary match and the intolerance interpretation as an alternative.
Disambiguate using AllergyIntolerance.type.Three Access Patterns
1. By vocabulary-specific code (type-level, most common):$lookup, from an ETL pipeline, or from a $translate result) and want to look it up without maintaining a vocabulary-ID round-trip.
3. By CodeSystem instance ID (instance-level):
id from CodeSystem search - either a per-vocab stub id (loinc, snomed, …) or a release-specific unified id (omop-v20250827). This is what HAPI FHIR emits after its discovery phase, and what you get back from CodeSystem instance read.
Designations (Synonyms)
$lookup responses include designation entries for concept synonyms. Each
designation has a language code and a value string. These are the alternate
names from the OMOP concept_synonym table.
Property Naming
Standard OMOP properties use kebab-case names for interoperability. Relationship properties use their OMOP relationship names (e.g.,Maps to, Is a).
Standard OMOP properties
Relationship properties
Use the
property query parameter on $lookup to request specific properties
(e.g. property=concept-id&property=domain-id). When omitted, all standard
properties are returned.
Metering
FHIR operations count against the same API-call quota as REST API calls - there is no separate FHIR pool. Two exceptions to the “1 operation = 1 call” rule:- Batch Bundles are metered per entry. A 50-entry batch counts as 50 calls.
- Resolver batch (
POST /v1/fhir/resolve/batch) is also metered per coding, matching FHIR batch behavior.
X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset) are included on every response.
See Also
- FHIR Integration guide - comprehensive walkthrough of the FHIR Resolver and Terminology Service for new integrations
- FHIR Concept Resolver - OMOPHub-native JSON for ETL pipelines, with
target_table+ mapping-quality signals - EHRbase / openEHR Integration - use OMOPHub for openEHR template terminology validation
- HAPI FHIR Integration - config for HAPI JPA Starter (via reverse proxy) and custom Spring Boot HAPI builds
- EHR Integration - SMART on FHIR, CDS Hooks, and point-of-care patterns