curl -X POST "https://api.omophub.com/v1/concepts/recommended" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"concept_ids": [201826, 4329847],
"standard_only": true,
"page": 1,
"page_size": 20
}'
import requests
payload = {
"concept_ids": [201826, 4329847], # Type 2 diabetes, Myocardial infarction
"relationship_types": ["Has finding", "Associated finding"],
"vocabulary_ids": ["SNOMED"],
"standard_only": True,
"page": 1,
"page_size": 20
}
response = requests.post(
"https://api.omophub.com/v1/concepts/recommended",
headers={"Authorization": "Bearer YOUR_API_KEY"},
json=payload
)
data = response.json()
for source_id, recommendations in data['data'].items():
print(f"\nRecommendations for concept {source_id}:")
for rec in recommendations[:5]:
print(f" - {rec['concept_name']} ({rec['vocabulary_id']}) via {rec['relationship_id']}")
import { OMOPHub } from '@omophub/omophub-node';
const client = new OMOPHub();
const { data, meta } = await client.concepts.recommended({
conceptIds: [201826, 4329847],
relationshipTypes: ['Has finding', 'Associated finding'],
vocabularyIds: ['SNOMED'],
standardOnly: true,
page: 1,
pageSize: 20,
});
console.log(
`Page ${meta?.pagination?.page} of ${meta?.pagination?.total_pages}`
);
console.log(`Total items: ${meta?.pagination?.total_items}`);
curl -X POST "https://api.omophub.com/v1/concepts/recommended" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"concept_ids": [201826],
"vocabulary_ids": ["SNOMED", "ICD10CM"],
"domain_ids": ["Condition", "Measurement"],
"relationship_types": ["Has finding"],
"standard_only": true,
"include_invalid": false,
"page": 1,
"page_size": 50
}'
import requests
# Get comprehensive recommendations for Type 2 diabetes
payload = {
"concept_ids": [201826], # Type 2 diabetes mellitus (SNOMED)
"vocabulary_ids": ["SNOMED", "LOINC"],
"domain_ids": ["Condition", "Measurement", "Procedure"],
"standard_only": True,
"page": 1,
"page_size": 50
}
response = requests.post(
"https://api.omophub.com/v1/concepts/recommended",
headers={"Authorization": "Bearer YOUR_API_KEY"},
json=payload
)
data = response.json()
# Analyze recommendations by domain
from collections import Counter
domains = Counter(rec['domain_id'] for recs in data['data'].values() for rec in recs)
print(f"Recommendations by domain: {dict(domains)}")
# Show top recommendations
for source_id, recommendations in data['data'].items():
print(f"\nTop 10 recommendations for concept {source_id}:")
for i, rec in enumerate(recommendations[:10], 1):
print(f" {i}. {rec['concept_name']}")
print(f" [{rec['vocabulary_id']}] via '{rec['relationship_id']}'")
print(f" Domain: {rec['domain_id']}, Code: {rec['concept_code']}")
{
"success": true,
"data": {
"201826": [
{
"concept_id": 4193704,
"concept_name": "Hyperglycemia",
"vocabulary_id": "SNOMED",
"concept_code": "80394007",
"domain_id": "Condition",
"concept_class_id": "Clinical Finding",
"standard_concept": "S",
"invalid_reason": null,
"valid_start_date": "1970-01-01",
"valid_end_date": "2099-12-31",
"relationship_id": "Has finding"
},
{
"concept_id": 4058243,
"concept_name": "Diabetic retinopathy",
"vocabulary_id": "SNOMED",
"concept_code": "4855003",
"domain_id": "Condition",
"concept_class_id": "Clinical Finding",
"standard_concept": "S",
"invalid_reason": null,
"valid_start_date": "1970-01-01",
"valid_end_date": "2099-12-31",
"relationship_id": "Associated finding"
},
{
"concept_id": 3004410,
"concept_name": "Hemoglobin A1c measurement",
"vocabulary_id": "LOINC",
"concept_code": "4548-4",
"domain_id": "Measurement",
"concept_class_id": "Lab Test",
"standard_concept": "S",
"invalid_reason": null,
"valid_start_date": "1970-01-01",
"valid_end_date": "2099-12-31",
"relationship_id": "Has finding"
}
],
"4329847": [
{
"concept_id": 437894,
"concept_name": "Coronary arteriosclerosis",
"vocabulary_id": "SNOMED",
"concept_code": "53741008",
"domain_id": "Condition",
"concept_class_id": "Clinical Finding",
"standard_concept": "S",
"invalid_reason": null,
"valid_start_date": "1970-01-01",
"valid_end_date": "2099-12-31",
"relationship_id": "Associated finding"
},
{
"concept_id": 4213540,
"concept_name": "Troponin measurement",
"vocabulary_id": "LOINC",
"concept_code": "6598-7",
"domain_id": "Measurement",
"concept_class_id": "Lab Test",
"standard_concept": "S",
"invalid_reason": null,
"valid_start_date": "1970-01-01",
"valid_end_date": "2099-12-31",
"relationship_id": "Has finding"
}
]
},
"meta": {
"request_id": "rec_1234567890_abc",
"vocab_release": "2025.2",
"pagination": {
"page": 1,
"page_size": 100,
"total_items": 296,
"total_pages": 3,
"has_next": true,
"has_previous": false
}
}
}
Recommended Concepts
curl -X POST "https://api.omophub.com/v1/concepts/recommended" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"concept_ids": [201826, 4329847],
"standard_only": true,
"page": 1,
"page_size": 20
}'
import requests
payload = {
"concept_ids": [201826, 4329847], # Type 2 diabetes, Myocardial infarction
"relationship_types": ["Has finding", "Associated finding"],
"vocabulary_ids": ["SNOMED"],
"standard_only": True,
"page": 1,
"page_size": 20
}
response = requests.post(
"https://api.omophub.com/v1/concepts/recommended",
headers={"Authorization": "Bearer YOUR_API_KEY"},
json=payload
)
data = response.json()
for source_id, recommendations in data['data'].items():
print(f"\nRecommendations for concept {source_id}:")
for rec in recommendations[:5]:
print(f" - {rec['concept_name']} ({rec['vocabulary_id']}) via {rec['relationship_id']}")
import { OMOPHub } from '@omophub/omophub-node';
const client = new OMOPHub();
const { data, meta } = await client.concepts.recommended({
conceptIds: [201826, 4329847],
relationshipTypes: ['Has finding', 'Associated finding'],
vocabularyIds: ['SNOMED'],
standardOnly: true,
page: 1,
pageSize: 20,
});
console.log(
`Page ${meta?.pagination?.page} of ${meta?.pagination?.total_pages}`
);
console.log(`Total items: ${meta?.pagination?.total_items}`);
curl -X POST "https://api.omophub.com/v1/concepts/recommended" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"concept_ids": [201826],
"vocabulary_ids": ["SNOMED", "ICD10CM"],
"domain_ids": ["Condition", "Measurement"],
"relationship_types": ["Has finding"],
"standard_only": true,
"include_invalid": false,
"page": 1,
"page_size": 50
}'
import requests
# Get comprehensive recommendations for Type 2 diabetes
payload = {
"concept_ids": [201826], # Type 2 diabetes mellitus (SNOMED)
"vocabulary_ids": ["SNOMED", "LOINC"],
"domain_ids": ["Condition", "Measurement", "Procedure"],
"standard_only": True,
"page": 1,
"page_size": 50
}
response = requests.post(
"https://api.omophub.com/v1/concepts/recommended",
headers={"Authorization": "Bearer YOUR_API_KEY"},
json=payload
)
data = response.json()
# Analyze recommendations by domain
from collections import Counter
domains = Counter(rec['domain_id'] for recs in data['data'].values() for rec in recs)
print(f"Recommendations by domain: {dict(domains)}")
# Show top recommendations
for source_id, recommendations in data['data'].items():
print(f"\nTop 10 recommendations for concept {source_id}:")
for i, rec in enumerate(recommendations[:10], 1):
print(f" {i}. {rec['concept_name']}")
print(f" [{rec['vocabulary_id']}] via '{rec['relationship_id']}'")
print(f" Domain: {rec['domain_id']}, Code: {rec['concept_code']}")
{
"success": true,
"data": {
"201826": [
{
"concept_id": 4193704,
"concept_name": "Hyperglycemia",
"vocabulary_id": "SNOMED",
"concept_code": "80394007",
"domain_id": "Condition",
"concept_class_id": "Clinical Finding",
"standard_concept": "S",
"invalid_reason": null,
"valid_start_date": "1970-01-01",
"valid_end_date": "2099-12-31",
"relationship_id": "Has finding"
},
{
"concept_id": 4058243,
"concept_name": "Diabetic retinopathy",
"vocabulary_id": "SNOMED",
"concept_code": "4855003",
"domain_id": "Condition",
"concept_class_id": "Clinical Finding",
"standard_concept": "S",
"invalid_reason": null,
"valid_start_date": "1970-01-01",
"valid_end_date": "2099-12-31",
"relationship_id": "Associated finding"
},
{
"concept_id": 3004410,
"concept_name": "Hemoglobin A1c measurement",
"vocabulary_id": "LOINC",
"concept_code": "4548-4",
"domain_id": "Measurement",
"concept_class_id": "Lab Test",
"standard_concept": "S",
"invalid_reason": null,
"valid_start_date": "1970-01-01",
"valid_end_date": "2099-12-31",
"relationship_id": "Has finding"
}
],
"4329847": [
{
"concept_id": 437894,
"concept_name": "Coronary arteriosclerosis",
"vocabulary_id": "SNOMED",
"concept_code": "53741008",
"domain_id": "Condition",
"concept_class_id": "Clinical Finding",
"standard_concept": "S",
"invalid_reason": null,
"valid_start_date": "1970-01-01",
"valid_end_date": "2099-12-31",
"relationship_id": "Associated finding"
},
{
"concept_id": 4213540,
"concept_name": "Troponin measurement",
"vocabulary_id": "LOINC",
"concept_code": "6598-7",
"domain_id": "Measurement",
"concept_class_id": "Lab Test",
"standard_concept": "S",
"invalid_reason": null,
"valid_start_date": "1970-01-01",
"valid_end_date": "2099-12-31",
"relationship_id": "Has finding"
}
]
},
"meta": {
"request_id": "rec_1234567890_abc",
"vocab_release": "2025.2",
"pagination": {
"page": 1,
"page_size": 100,
"total_items": 296,
"total_pages": 3,
"has_next": true,
"has_previous": false
}
}
}
Overview
The Recommended Concepts endpoint implements the OHDSI Phoebe algorithm to provide curated concept recommendations. This feature helps researchers discover related concepts during cohort building and phenotype development. Key Features:- Curated recommendations from OHDSI community data
- Relationship-based concept discovery
- Support for multiple source concepts
- Filtering by vocabulary, domain, and relationship type
- Cohort building assistance
- Phenotype expansion
- Related concept discovery
- Clinical terminology exploration
Request Body
integer[]
required
Array of source concept IDs to get recommendations for (min: 1, max: 100)
string[]
Filter recommendations by relationship types (max: 20). Examples: “Has
finding”, “Associated finding”, “Has clinical course”
string[]
Filter recommended concepts to specific vocabularies (max: 50). Examples:
[“SNOMED”, “ICD10CM”, “LOINC”]
string[]
Filter recommended concepts to specific domains (max: 50). Examples:
[“Condition”, “Procedure”, “Drug”]
boolean
default:"false"
Only return standard concepts (S flag in OMOP CDM)
boolean
default:"false"
Include invalid/deprecated concepts in results
integer
default:"1"
Page number for pagination (min: 1)
integer
default:"100"
Number of recommendations to return per page (min: 1, max: 1000)
curl -X POST "https://api.omophub.com/v1/concepts/recommended" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"concept_ids": [201826, 4329847],
"standard_only": true,
"page": 1,
"page_size": 20
}'
import requests
payload = {
"concept_ids": [201826, 4329847], # Type 2 diabetes, Myocardial infarction
"relationship_types": ["Has finding", "Associated finding"],
"vocabulary_ids": ["SNOMED"],
"standard_only": True,
"page": 1,
"page_size": 20
}
response = requests.post(
"https://api.omophub.com/v1/concepts/recommended",
headers={"Authorization": "Bearer YOUR_API_KEY"},
json=payload
)
data = response.json()
for source_id, recommendations in data['data'].items():
print(f"\nRecommendations for concept {source_id}:")
for rec in recommendations[:5]:
print(f" - {rec['concept_name']} ({rec['vocabulary_id']}) via {rec['relationship_id']}")
import { OMOPHub } from '@omophub/omophub-node';
const client = new OMOPHub();
const { data, meta } = await client.concepts.recommended({
conceptIds: [201826, 4329847],
relationshipTypes: ['Has finding', 'Associated finding'],
vocabularyIds: ['SNOMED'],
standardOnly: true,
page: 1,
pageSize: 20,
});
console.log(
`Page ${meta?.pagination?.page} of ${meta?.pagination?.total_pages}`
);
console.log(`Total items: ${meta?.pagination?.total_items}`);
curl -X POST "https://api.omophub.com/v1/concepts/recommended" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"concept_ids": [201826],
"vocabulary_ids": ["SNOMED", "ICD10CM"],
"domain_ids": ["Condition", "Measurement"],
"relationship_types": ["Has finding"],
"standard_only": true,
"include_invalid": false,
"page": 1,
"page_size": 50
}'
import requests
# Get comprehensive recommendations for Type 2 diabetes
payload = {
"concept_ids": [201826], # Type 2 diabetes mellitus (SNOMED)
"vocabulary_ids": ["SNOMED", "LOINC"],
"domain_ids": ["Condition", "Measurement", "Procedure"],
"standard_only": True,
"page": 1,
"page_size": 50
}
response = requests.post(
"https://api.omophub.com/v1/concepts/recommended",
headers={"Authorization": "Bearer YOUR_API_KEY"},
json=payload
)
data = response.json()
# Analyze recommendations by domain
from collections import Counter
domains = Counter(rec['domain_id'] for recs in data['data'].values() for rec in recs)
print(f"Recommendations by domain: {dict(domains)}")
# Show top recommendations
for source_id, recommendations in data['data'].items():
print(f"\nTop 10 recommendations for concept {source_id}:")
for i, rec in enumerate(recommendations[:10], 1):
print(f" {i}. {rec['concept_name']}")
print(f" [{rec['vocabulary_id']}] via '{rec['relationship_id']}'")
print(f" Domain: {rec['domain_id']}, Code: {rec['concept_code']}")
Response Fields
boolean
Whether recommendation lookup succeeded.
object
Map keyed by each requested source
concept_id.array
Recommendations for one source concept.
integer
Recommended concept identifier.
string
Recommended concept name.
string
Vocabulary identifier.
string
Vocabulary code.
string
OMOP domain.
string
Concept class.
string | null
S, C, or null.string | null
Invalidity marker, or null.
string
Validity start date.
string
Validity end date.
string
Relationship supporting the recommendation.
object
Request, release, and pagination metadata.
string
Request correlation ID.
string
Vocabulary release used.
object
Page, page size, totals, and navigation flags.
{
"success": true,
"data": {
"201826": [
{
"concept_id": 4193704,
"concept_name": "Hyperglycemia",
"vocabulary_id": "SNOMED",
"concept_code": "80394007",
"domain_id": "Condition",
"concept_class_id": "Clinical Finding",
"standard_concept": "S",
"invalid_reason": null,
"valid_start_date": "1970-01-01",
"valid_end_date": "2099-12-31",
"relationship_id": "Has finding"
},
{
"concept_id": 4058243,
"concept_name": "Diabetic retinopathy",
"vocabulary_id": "SNOMED",
"concept_code": "4855003",
"domain_id": "Condition",
"concept_class_id": "Clinical Finding",
"standard_concept": "S",
"invalid_reason": null,
"valid_start_date": "1970-01-01",
"valid_end_date": "2099-12-31",
"relationship_id": "Associated finding"
},
{
"concept_id": 3004410,
"concept_name": "Hemoglobin A1c measurement",
"vocabulary_id": "LOINC",
"concept_code": "4548-4",
"domain_id": "Measurement",
"concept_class_id": "Lab Test",
"standard_concept": "S",
"invalid_reason": null,
"valid_start_date": "1970-01-01",
"valid_end_date": "2099-12-31",
"relationship_id": "Has finding"
}
],
"4329847": [
{
"concept_id": 437894,
"concept_name": "Coronary arteriosclerosis",
"vocabulary_id": "SNOMED",
"concept_code": "53741008",
"domain_id": "Condition",
"concept_class_id": "Clinical Finding",
"standard_concept": "S",
"invalid_reason": null,
"valid_start_date": "1970-01-01",
"valid_end_date": "2099-12-31",
"relationship_id": "Associated finding"
},
{
"concept_id": 4213540,
"concept_name": "Troponin measurement",
"vocabulary_id": "LOINC",
"concept_code": "6598-7",
"domain_id": "Measurement",
"concept_class_id": "Lab Test",
"standard_concept": "S",
"invalid_reason": null,
"valid_start_date": "1970-01-01",
"valid_end_date": "2099-12-31",
"relationship_id": "Has finding"
}
]
},
"meta": {
"request_id": "rec_1234567890_abc",
"vocab_release": "2025.2",
"pagination": {
"page": 1,
"page_size": 100,
"total_items": 296,
"total_pages": 3,
"has_next": true,
"has_previous": false
}
}
}
Implementation Notes
Data Source
- Data is curated by the OHDSI community using the Phoebe algorithm
- Version-independent: recommendations persist across vocabulary releases
Response Structure
- Results are grouped by source concept ID
- Each source concept ID maps to an array of recommended concepts
- Recommendations include full concept details and relationship information
Filtering
- Apply multiple filters simultaneously (vocabulary, domain, relationship type)
standard_only=false(default) includes all concepts; set totrueto filter to standard concepts onlyinclude_invalid=false(default) excludes deprecated concepts
Related Endpoints
- Search Concepts - Full-text concept search
- Get Concept Relationships - Direct relationships
- Get Concept Hierarchy - Hierarchical relationships
- Batch Concepts - Retrieve multiple concepts
Was this page helpful?