Skip to main content

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 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.

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

ParameterTypeDefaultDescription
conceptId (positional)numberrequiredThe concept ID
format'flat' | 'graph''flat'Response format
vocabularyIdsstring[]-Filter to specific vocabularies
domainIdsstring[]-Filter to specific domains
maxLevelsnumber10Max hierarchy levels (server caps at 20)
maxResultsnumber-Max results per direction
relationshipTypesstring[]-Relationship types to follow
includeInvalidbooleantrueInclude 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

ParameterTypeDefaultDescription
conceptId (positional)numberrequiredOMOP concept ID - 0 is accepted as the “unmapped” sentinel
includeRelationshipsbooleanfalseInclude related concepts
includeSynonymsbooleanfalseInclude concept synonyms
includeHierarchybooleanfalseInclude hierarchy summary
vocabReleasestring-Pin to a specific vocabulary release (e.g. "2025.2")