Documentation Index
Fetch the complete documentation index at: https://docs.omophub.com/llms.txt
Use this file to discover all available pages before exploring further.
Get a Concept
Retrieve a concept by its OMOP concept ID:
const { data, error } = await client.concepts.get(201826);
if (error) throw new Error(error.message);
console.log(data.concept_name); // "Type 2 diabetes mellitus"
console.log(data.vocabulary_id); // "SNOMED"
console.log(data.domain_id); // "Condition"
The SDK accepts conceptId === 0 - the OMOP “unmapped” sentinel - and forwards it to the server without client-side validation.
Get by Vocabulary Code
Look up a concept using a vocabulary-specific code:
// SNOMED concept by its code
const { data } = await client.concepts.getByCode('SNOMED', '44054006');
console.log(data?.concept_name); // "Type 2 diabetes mellitus"
// ICD-10-CM concept
const result = await client.concepts.getByCode('ICD10CM', 'E11');
// Include synonyms and relationships
const enriched = await client.concepts.getByCode('SNOMED', '44054006', {
includeSynonyms: true,
includeRelationships: true,
});
console.log(enriched.data?.synonyms);
console.log(enriched.data?.relationships);
// Specific vocabulary release
const pinned = await client.concepts.getByCode('SNOMED', '44054006', {
vocabRelease: '2025.2',
});
Batch Get Concepts
Retrieve up to 100 concepts in a single request:
const { data, error } = await client.concepts.batch({
conceptIds: [201826, 4329847, 1112807],
});
if (error) throw new Error(error.message);
for (const concept of data.concepts) {
console.log(`${concept.concept_id}: ${concept.concept_name}`);
}
console.log(`Retrieved: ${data.summary?.found}`);
console.log(`Failed: ${data.summary?.failed}`);
With optional flags:
const result = await client.concepts.batch({
conceptIds: [201826, 4329847, 1112807],
includeRelationships: true,
includeSynonyms: true,
includeMappings: true,
vocabularyFilter: ['SNOMED'],
standardOnly: false,
});
The SDK validates conceptIds.length is between 1 and 100 and returns a validation_error synthetically (no network call) if outside that range.
Autocomplete Suggestions
Get concept suggestions for autocomplete UI:
const { data, error, meta } = await client.concepts.suggest('diab', {
pageSize: 10,
});
if (error) throw new Error(error.message);
// Suggestions are an array - pagination on outer `meta`
for (const concept of Array.isArray(data) ? data : data?.data ?? []) {
console.log(concept.concept_name);
}
console.log(meta?.pagination?.total_items);
console.log(meta?.pagination?.has_next);
client.concepts.suggest() returns data as either ConceptSuggestion[] (bare array) or { data: ConceptSuggestion[] } (envelope), depending on the API version answering the request. Both shapes are valid per the SDK type (ConceptSuggestion[] | PaginatedData<ConceptSuggestion>); the Array.isArray(data) ? data : data?.data ?? [] pattern above handles both. Pagination always lives on the outer meta.pagination, never on the inner shape.
Filter by vocabulary and domain:
const filtered = await client.concepts.suggest('diab', {
vocabularyIds: ['SNOMED'],
domainIds: ['Condition'],
pageSize: 20,
});
Get Relationships
Get relationships for a concept. Both client.concepts.relationships(...) and client.relationships.get(...) hit the same wire endpoint - pick whichever reads more naturally at the call site:
const { data, error, meta } = await client.relationships.get(201826);
if (error) throw new Error(error.message);
for (const rel of data.relationships) {
console.log(`${rel.relationship_id}: ${rel.target_concept_name}`);
}
console.log(`Page ${meta?.pagination?.page} of ${meta?.pagination?.total_pages}`);
Filter by relationship type, vocabulary, and direction:
const filtered = await client.relationships.get(201826, {
relationshipIds: ['Is a', 'Subsumes'],
vocabularyIds: ['SNOMED'],
standardOnly: true,
page: 1,
pageSize: 50,
});
// Include reverse relationships
const bothDirections = await client.relationships.get(201826, {
includeReverse: true,
domainIds: ['Condition'],
});
Find concepts related to a given concept (Phoebe-style relatedness):
const { data, error } = await client.concepts.related(201826, {
pageSize: 10,
});
if (error) throw new Error(error.message);
for (const related of data.related_concepts) {
console.log(
`${related.concept_name} (${related.relatedness_type}): ${related.relatedness_score.toFixed(2)}`,
);
}
Filter by relationship type and minimum score:
const filtered = await client.concepts.related(201826, {
relationshipTypes: ['Is a', 'Maps to'],
minScore: 0.5,
pageSize: 20,
vocabRelease: '2025.1',
});
Get Recommended Concepts
Get curated concept recommendations using the OHDSI Phoebe algorithm:
const { data } = await client.concepts.recommended({
conceptIds: [201826, 4329847],
});
for (const group of data?.recommendations ?? []) {
console.log(`\nRecommendations for ${group.source_concept_id}:`);
for (const rec of group.recommendations.slice(0, 5)) {
console.log(` - ${rec.concept_name} (${rec.vocabulary_id})`);
}
}
With filters and pagination:
const filtered = await client.concepts.recommended({
conceptIds: [201826],
relationshipTypes: ['Has finding', 'Associated finding'],
vocabularyIds: ['SNOMED', 'LOINC'],
domainIds: ['Condition', 'Measurement'],
standardOnly: true,
page: 1,
pageSize: 50,
});
Server-side caps enforced client-side: conceptIds ≤ 100, relationshipTypes ≤ 20, vocabularyIds/domainIds ≤ 50. Violations return validation_error without hitting the network.
Navigate Hierarchy
Get Complete Hierarchy
Fetch ancestors and descendants in one request, in either flat or graph format:
// Flat format (default) - concepts + paths arrays
const flat = await client.hierarchy.get(201826, {
maxLevels: 3,
vocabularyIds: ['SNOMED'],
});
console.log(`Total ancestors: ${flat.data?.summary?.total_ancestors}`);
console.log(`Total descendants: ${flat.data?.summary?.total_descendants}`);
// Graph format for visualisation (D3.js, Cytoscape, …)
const graph = await client.hierarchy.get(201826, {
format: 'graph',
maxLevels: 3,
});
console.log(`Nodes: ${graph.data?.nodes?.length}`);
console.log(`Edges: ${graph.data?.edges?.length}`);
// Advanced filtering
await client.hierarchy.get(201826, {
domainIds: ['Condition'],
relationshipTypes: ['Is a'],
maxResults: 100,
includeInvalid: false,
});
Hierarchy Get Parameters
| Parameter | Type | Default | Description |
|---|
conceptId (positional) | number | required | The concept ID |
format | 'flat' | 'graph' | 'flat' | Response format |
vocabularyIds | string[] | - | Filter to specific vocabularies |
domainIds | string[] | - | Filter to specific domains |
maxLevels | number | 10 | Max hierarchy levels (server caps at 20) |
maxResults | number | - | Max results per direction |
relationshipTypes | string[] | - | Relationship types to follow |
includeInvalid | boolean | true | Include deprecated/invalid concepts |
Get Ancestors
Find parent concepts in the hierarchy:
const { data, meta } = await client.hierarchy.ancestors(201826, {
maxLevels: 3,
vocabularyIds: ['SNOMED'],
relationshipTypes: ['Is a'],
includeDistance: true,
includePaths: false,
includeInvalid: false,
page: 1,
pageSize: 100,
});
for (const ancestor of data?.ancestors ?? []) {
const level = ancestor.min_levels_of_separation ?? 0;
console.log(`${' '.repeat(level)}${ancestor.concept_name}`);
}
console.log(`Max depth: ${data?.summary?.max_hierarchy_depth}`);
console.log(`Page ${meta?.pagination?.page} of ${meta?.pagination?.total_pages}`);
Get Descendants
Find child concepts in the hierarchy:
const { data, meta } = await client.hierarchy.descendants(201826, {
maxLevels: 2,
vocabularyIds: ['SNOMED'],
relationshipTypes: ['Is a'],
includeDistance: true,
includePaths: false,
includeInvalid: false,
domainIds: ['Condition'],
page: 1,
pageSize: 100,
});
for (const descendant of data?.descendants ?? []) {
console.log(descendant.concept_name);
}
Get Relationship Types
Get the catalog of OMOP CDM relationship types:
const { data, meta } = await client.relationships.types({
page: 1,
pageSize: 100,
});
for (const relType of data?.relationship_types ?? []) {
console.log(`${relType.relationship_id}: ${relType.relationship_name}`);
}
console.log(`Total types: ${meta?.pagination?.total_items}`);
Concept Get Options
Include synonyms, relationships, hierarchy, and pin a vocabulary release:
// Concept with synonyms
const withSynonyms = await client.concepts.get(201826, {
includeSynonyms: true,
});
// Concept with synonyms and relationships
const enriched = await client.concepts.get(201826, {
includeSynonyms: true,
includeRelationships: true,
});
// Concept with hierarchy information
const withHierarchy = await client.concepts.get(201826, {
includeHierarchy: true,
});
// Pin to a specific vocabulary release
const pinned = await client.concepts.get(201826, {
vocabRelease: '2025.2',
});
Parameters
| Parameter | Type | Default | Description |
|---|
conceptId (positional) | number | required | OMOP concept ID - 0 is accepted as the “unmapped” sentinel |
includeRelationships | boolean | false | Include related concepts |
includeSynonyms | boolean | false | Include concept synonyms |
includeHierarchy | boolean | false | Include hierarchy summary |
vocabRelease | string | - | Pin to a specific vocabulary release (e.g. "2025.2") |