alterlab-clinpgx
Access ClinPGx pharmacogenomics data (the successor to PharmGKB) to query gene-drug interactions, CPIC/DPWG dosing guidelines, drug labels, and pharmacogene records. Use when interpreting pharmacogenes (CYP2D6, CYP2C19, TPMT, DPYD, SLCO1B1), looking up genotype-guided drug dosing
Install
npx skills add https://github.com/AlterLab-IEU/AlterLab-Academic-Skills/tree/main/skills/databases/alterlab-clinpgx
claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install alterlab-ieu-alterlab-academic-skills@llmmart
git clone https://github.com/AlterLab-IEU/AlterLab-Academic-Skills.git
The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole alterlab-ieu/alterlab-academic-skills collection as a plugin from our marketplace. Git is the plain clone.
Skill manifest
ClinPGx Database
Overview
ClinPGx (Clinical Pharmacogenomics Database) is a comprehensive resource for clinical pharmacogenomics, the successor to PharmGKB. It consolidates data from PharmGKB, CPIC, and PharmCAT, providing curated information on how genetic variation affects medication response. Access gene-drug pairs, clinical guidelines, allele functions, and drug labels for precision medicine.
When to Use This Skill
Use this skill for:
- Gene-drug interactions — how variants affect drug metabolism, efficacy, or toxicity
- CPIC guidelines — evidence-based clinical practice guidelines for pharmacogenetics
- Allele information — allele function, frequency, and phenotype data
- Drug labels — FDA and other regulatory pharmacogenomic labeling
- Pharmacogenomic annotations — curated literature on gene-drug-disease relationships
- Clinical decision support — PharmDOG for phenoconversion and custom genotype interpretation
- Precision medicine / personalized dosing — genotype-guided dosing recommendations
- Drug metabolism — CYP450 and other pharmacogene functions
- Adverse drug reactions — genetic risk factors for drug toxicity
Does NOT Trigger
| Scenario | Use Instead |
|---|---|
| Germline/somatic variant pathogenicity or ClinVar review status | alterlab-clinvar |
| Population allele frequencies for a variant (gnomAD v4) | alterlab-gnomad |
| Drug–drug interactions or general pharmacology with no genetic component | alterlab-drugbank |
| FDA adverse-event reports, recalls, or full-text label search | alterlab-fda |
Setup and Access Essentials
Only requests is needed. Run the helper script (or any snippet) with an
ephemeral dependency — no venv to manage:
uv run --with requests python scripts/query_clinpgx.py
# or, inside an existing project venv: uv pip install requests
Base URL: https://api.clinpgx.org/v1/data/ — the legacy api.pharmgkb.org host was
turned off on 2026-07-20, so older PharmGKB scripts must switch hostnames (paths are
unchanged).
- Resource addressing: ClinPGx resources are addressed by ClinPGx accession
IDs in the path (e.g. gene CYP2D6 =
PA128, CYP2C9 =PA126), not by gene symbols or rsIDs. To resolve a symbol or rsID, query the collection endpoint with parameters (e.g.GET /v1/data/gene?symbol=CYP2D6,GET /v1/data/variant?symbol=rs4244285) and read the accession ID from the response. - Response envelope (verified): every response is a JSON object
{"status": "success"|"fail", "data": [...]}— the payload is never a bare list. Read results fromresponse.json()["data"]; onstatus == "fail",datais{"errors": [...]}(e.g. "No results matching criteria"). - Query-param convention (verified): genes filter on
relatedGenes.symbol(the.nameform fails), while chemicals/drugs filter onrelatedChemicals.name—relatedChemicals.symbolsilently returnsstatus: "fail"with zero results. Thegenecollection takes?symbol=, thechemicalcollection takes?name=, andvariantaccepts?symbol=/?name=. - Rate limits: 2 requests per second maximum; excessive requests return HTTP 429. Implement a ~500ms delay between requests.
- Authentication: Not required for basic access.
- Data license: Creative Commons Attribution-ShareAlike 4.0 International.
- For substantial API use, notify the ClinPGx team at api@clinpgx.org.
Core Workflow
- Resolve identifiers — Convert gene symbols / rsIDs to ClinPGx accession
IDs via collection endpoints with
symbol=parameters. - Query the relevant resource —
gene,chemical,guidelineAnnotation,summaryAnnotation,variantAnnotation,variant,label, orpathway. There is no/alleleresource — use PharmVar (https://www.pharmvar.org/) for star-allele definitions and population frequencies. - Derive gene-drug relationships — From guideline annotations
(
relatedGenes.symbolfor genes,relatedChemicals.namefor drugs), or the/report/pair/{firstObjId}/{secondObjId}/{resultType}endpoint. - Filter by evidence level — Prefer levels 1A/1B/2A for clinical use; confirm field names against the live OpenAPI spec.
- Respect rate limits — Throttle, retry on 429 with backoff, and cache.
For ready-made functions with rate limiting and error handling, see
scripts/query_clinpgx.py.
Routing Guidance
- Need the exact code for a resource (gene, chemical, gene-drug pair, CPIC
guideline, allele/PharmVar, variant, clinical annotation, label, pathway)?
Read
references/endpoints-and-capabilities.md. - Doing an end-to-end task (clinical decision support, gene-panel analysis,
drug-safety assessment, population pharmacogenomics, literature review) or a
common use case? Read
references/query-workflows.md. - Need robust API plumbing (rate limiting, retries, caching)? Read
references/rate-limiting-and-error-handling.md. - Need full endpoint/parameter/schema details? Read
references/api_reference.md.
References
references/api_reference.md— Complete endpoint listing, request/response formats, filter operators, data schemas, rate-limit details, and troubleshooting.references/endpoints-and-capabilities.md— Worked code for all nine capability areas (gene, drug/chemical, gene-drug pair, CPIC guidelines, allele/PharmVar, variant, clinical annotations, drug labels, pathways), including key pharmacogenes and evidence-level definitions.references/query-workflows.md— Five end-to-end workflows (decision support, gene panel, drug safety, population pharmacogenomics, literature review) plus common use cases (pre-emptive testing, medication therapy management, trial eligibility).references/rate-limiting-and-error-handling.md— Reusable helpers for rate limiting, retries with exponential backoff, and result caching.
PharmDOG Tool
PharmDOG (formerly DDRx) is ClinPGx's clinical decision support tool for interpreting pharmacogenomic test results. Features: phenoconversion calculator (adjusts phenotype for drug-drug interactions affecting CYP2D6), custom genotype input, QR-code report sharing, selectable guidance sources (CPIC, DPWG, FDA), and multi-drug analysis. Access: https://www.clinpgx.org/pharmacogenomic-decision-support
Important Notes
Data sources — ClinPGx consolidates PharmGKB (now part of ClinPGx), CPIC, PharmCAT, DPWG, and FDA/EMA labels. As of July 2025, all PharmGKB URLs redirect to corresponding ClinPGx pages.
Clinical considerations — Always check evidence strength before clinical application; allele frequencies vary significantly across populations; account for phenoconversion (drug-drug interactions) and multi-gene effects; non-genetic factors (age, organ function) also affect response; not all clinically relevant alleles are detected by all assays.
Data updates / API stability — ClinPGx updates continuously; check publication dates and the ClinPGx Blog (https://blog.clinpgx.org/). API endpoints are relatively stable but may change during development — pin versions and test in development before production.
Additional Resources
- ClinPGx website: https://www.clinpgx.org/
- ClinPGx Blog: https://blog.clinpgx.org/
- API documentation: https://api.clinpgx.org/
- CPIC website: https://cpicpgx.org/
- PharmCAT: https://pharmcat.clinpgx.org/
- PharmVar (star alleles): https://www.pharmvar.org/
- ClinGen: https://clinicalgenome.org/
- Contact: api@clinpgx.org (for substantial API use)
Files (alterlab-academic-skills)
-
evals
-
evals.json 3.9 KB
{ "skill": "alterlab-clinpgx", "evals": [ { "id": "cpic-clopidogrel-dosing", "prompt": "My patient is CYP2C19 *1/*2 (intermediate metabolizer) and we're considering clopidogrel. What does the CPIC guideline say about dosing or alternative therapy?", "expected_output": "Invokes alterlab-clinpgx. Queries the ClinPGx guidelineAnnotation endpoint for clopidogrel (relatedChemicals.name), surfaces the CPIC recommendation (alternative antiplatelet therapy for intermediate/poor metabolizers), and notes evidence level. May reference checking the drug label endpoint too.", "assertions": [ { "type": "should_trigger", "value": true }, { "type": "output_contains", "value": "CPIC" } ] }, { "id": "pharmacogene-resolve", "prompt": "Pull the ClinPGx record for CYP2D6 and tell me which drugs have actionable pharmacogenomic guidelines tied to it.", "expected_output": "Invokes alterlab-clinpgx. Resolves the CYP2D6 gene symbol via the /data/gene collection endpoint (accession PA128), then derives gene-drug relationships from guidelineAnnotation queries filtered by relatedGenes.symbol. Respects the 2 req/sec rate limit.", "assertions": [ { "type": "should_trigger", "value": true }, { "type": "behavior", "value": "Resolves CYP2D6 to a ClinPGx accession and lists drugs with guideline annotations." } ] }, { "id": "hla-abacavir-safety", "prompt": "Before starting a patient on abacavir, what pharmacogenomic screening does ClinPGx flag, and what's the recommendation if they test positive?", "expected_output": "Invokes alterlab-clinpgx. Queries guideline annotations and/or labels for abacavir, surfacing the HLA-B*57:01 association: avoid abacavir if HLA-B*57:01 positive. Frames it as a drug-safety / adverse-reaction risk assessment.", "assertions": [ { "type": "should_trigger", "value": true }, { "type": "output_contains", "value": "abacavir" } ] }, { "id": "gene-panel-review", "prompt": "I have a preemptive PGx panel covering CYP2C19, CYP2D6, CYP2C9, TPMT, DPYD, and SLCO1B1. For each gene, give me the clinically actionable gene-drug pairs and dosing implications.", "expected_output": "Invokes alterlab-clinpgx. Iterates the panel genes, querying guidelineAnnotation by relatedGenes.symbol for each, and compiles actionable gene-drug pairs (e.g., TPMT-azathioprine, DPYD-fluoropyrimidines) with phenotype-based dosing recommendations and evidence levels.", "assertions": [ { "type": "should_trigger", "value": true } ] }, { "id": "near-miss-alterlab-clinvar", "prompt": "Is the variant rs121913529 in KRAS classified as pathogenic? I want the ClinVar clinical significance, review status, and submitter assertions for this disease-causing variant.", "expected_output": "Does NOT invoke this skill; defers to alterlab-clinvar. The user wants germline/somatic variant pathogenicity classification and review status for disease causation, which is ClinVar's domain, not ClinPGx's pharmacogenomic gene-drug response data.", "assertions": [ { "type": "should_not_trigger", "value": true }, { "type": "output_contains", "value": "alterlab-clinvar" } ] }, { "id": "near-miss-alterlab-pubmed", "prompt": "Find me the original CPIC clopidogrel guideline publication and a few recent review papers on CYP2C19 and antiplatelet therapy, with full citations and abstracts.", "expected_output": "Does NOT invoke this skill; defers to alterlab-pubmed. The user wants a literature search with citations and abstracts, which is PubMed's territory. ClinPGx surfaces PMIDs within annotations but the actual reference retrieval and literature search belongs to alterlab-pubmed.", "assertions": [ { "type": "should_not_trigger", "value": true }, { "type": "output_contains", "value": "alterlab-pubmed" } ] } ] }
-
-
references
-
api_reference.md 18.9 KB
# ClinPGx API Reference Complete reference documentation for the ClinPGx REST API. ## Base URL ``` https://api.clinpgx.org/v1/data/ ``` **Resource addressing**: ClinPGx objects are addressed by ClinPGx accession IDs in the path (e.g. gene CYP2D6 = `PA128`, CYP2C9 = `PA126`), not by gene symbols or rsIDs. Resolve a symbol or rsID by querying the collection endpoint with parameters (e.g. `GET /v1/data/gene?symbol=CYP2D6`, `GET /v1/data/variant?symbol=rs4244285`) and reading the accession ID from the response. ## Response Envelope (verified) Every response is a JSON object, never a bare array: ```json { "status": "success", "data": [ /* ...records... */ ] } ``` Read results from `response.json()["data"]`. On failure the envelope is `{"status": "fail", "data": {"errors": [{"message": "No results matching criteria."}]}}`. A single-object GET (e.g. `/gene/PA128`) returns the object inside `data` as well. ## Filter-Parameter Convention (verified) - **Genes** filter on `relatedGenes.symbol` (e.g. `CYP2C19`). The `relatedGenes.name` form fails. - **Chemicals/drugs** filter on `relatedChemicals.name` (e.g. `clopidogrel`). The `relatedChemicals.symbol` form returns `status: "fail"` ("No results matching criteria") — do **not** use it. - Collection lookups: `gene?symbol=`, `chemical?name=`, `variant?symbol=` or `variant?name=`. The illustrative `Example Response` blocks below predate this verification and are schematic — trust the envelope/param rules above and the live OpenAPI spec (`https://api.clinpgx.org/`) over the exact field names shown. ## Rate Limiting - **Maximum rate**: 2 requests per second - **Enforcement**: Requests exceeding the limit will receive HTTP 429 (Too Many Requests) - **Best practice**: Implement 500ms delay between requests (0.5 seconds) - **Recommendation**: For substantial API use, contact api@clinpgx.org ## Authentication No authentication is required for basic API access. All endpoints are publicly accessible. ## Data License All data accessed through the API is subject to: - Creative Commons Attribution-ShareAlike 4.0 International License - ClinPGx Data Usage Policy ## Response Format All successful responses return JSON with appropriate HTTP status codes: - `200 OK`: Successful request - `404 Not Found`: Resource does not exist - `429 Too Many Requests`: Rate limit exceeded - `500 Internal Server Error`: Server error ## Core Endpoints ### 1. Gene Endpoint Retrieve pharmacogene information including function, variants, and clinical significance. #### Get Gene by Accession ID ```http GET /v1/data/gene/{gene_id} ``` **Parameters:** - `gene_id` (path, required): ClinPGx gene accession ID (e.g., PA128 for CYP2D6, PA126 for CYP2C9) **Example Request:** ```bash curl "https://api.clinpgx.org/v1/data/gene/PA128" ``` **Example Response:** ```json { "id": "PA128", "symbol": "CYP2D6", "name": "cytochrome P450 family 2 subfamily D member 6", "chromosome": "22", "chromosomeLocation": "22q13.2", "function": "Drug metabolism", "description": "Highly polymorphic gene encoding enzyme...", "clinicalAnnotations": [...], "relatedDrugs": [...] } ``` #### Resolve / Search Genes by Symbol ```http GET /v1/data/gene?symbol={gene_symbol} ``` **Parameters:** - `symbol` (query): Gene symbol to resolve to its accession ID (e.g., CYP2D6) **Example:** ```bash curl "https://api.clinpgx.org/v1/data/gene?symbol=CYP2D6" ``` ### 2. Chemical/Drug Endpoint Access drug and chemical compound information including pharmacogenomic annotations. #### Get Drug by ID ```http GET /v1/data/chemical/{drug_id} ``` **Parameters:** - `drug_id` (path, required): ClinPGx drug accession ID (e.g., PA451906 for warfarin) **Example Request:** ```bash curl "https://api.clinpgx.org/v1/data/chemical/PA451906" ``` #### Search Drugs by Name ```http GET /v1/data/chemical?name={drug_name} ``` **Parameters:** - `name` (query, optional): Drug name or synonym **Example:** ```bash curl "https://api.clinpgx.org/v1/data/chemical?name=warfarin" ``` **Example Response:** ```json [ { "id": "PA451906", "name": "warfarin", "genericNames": ["warfarin sodium"], "tradeNames": ["Coumadin", "Jantoven"], "drugClasses": ["Anticoagulants"], "indication": "Prevention of thrombosis", "relatedGenes": ["CYP2C9", "VKORC1", "CYP4F2"] } ] ``` ### 3. Gene-Drug Relationships (no single pair endpoint) The public ClinPGx API does **not** provide a `geneDrugPair` endpoint. Gene-drug relationships are derived from guideline annotations, or fetched via the pair report endpoint when both object accession IDs are known. #### Derive from Guideline Annotations ```http GET /v1/data/guidelineAnnotation?relatedGenes.symbol={gene} GET /v1/data/guidelineAnnotation?relatedChemicals.name={drug} ``` **Example Requests:** ```bash # Guideline annotations related to a gene curl "https://api.clinpgx.org/v1/data/guidelineAnnotation?relatedGenes.symbol=CYP2D6" # Guideline annotations related to a drug curl "https://api.clinpgx.org/v1/data/guidelineAnnotation?relatedChemicals.name=codeine" ``` #### Pair Report Endpoint ```http GET /report/pair/{firstObjId}/{secondObjId}/{resultType} ``` **Parameters:** - `firstObjId` (path): Accession ID of the first object (e.g., gene PA128) - `secondObjId` (path): Accession ID of the second object (e.g., chemical PA449088) - `resultType` (path): Report type (e.g., `guidelineAnnotation`) **Example:** ```bash curl "https://api.clinpgx.org/v1/report/pair/PA128/PA449088/guidelineAnnotation" ``` ### 4. Guideline Annotation Endpoint Access clinical practice guideline annotations from CPIC, DPWG, and other sources. #### Get Guideline Annotations ```http GET /v1/data/guidelineAnnotation?source={source}&relatedGenes.symbol={gene}&relatedChemicals.name={drug} ``` **Parameters:** - `source` (query, optional): Guideline source (CPIC, DPWG, FDA) - `relatedGenes.symbol` (query, optional): Gene symbol - `relatedChemicals.name` (query, optional): Drug name/symbol **Example Requests:** ```bash # Get all CPIC guideline annotations curl "https://api.clinpgx.org/v1/data/guidelineAnnotation?source=CPIC" # Get guideline annotations for a specific gene curl "https://api.clinpgx.org/v1/data/guidelineAnnotation?relatedGenes.symbol=CYP2C19" ``` #### Get Guideline Annotation by ID ```http GET /v1/data/guidelineAnnotation/{guideline_id} ``` **Example:** ```bash curl "https://api.clinpgx.org/v1/data/guidelineAnnotation/PA166104939" ``` **Example Response:** ```json { "id": "PA166104939", "name": "CPIC Guideline for CYP2C19 and Clopidogrel", "source": "CPIC", "genes": ["CYP2C19"], "drugs": ["clopidogrel"], "recommendationLevel": "A", "lastUpdated": "2023-08-01", "summary": "Alternative antiplatelet therapy recommended for...", "recommendations": [...], "pdfUrl": "https://www.clinpgx.org/...", "pmid": "23400754" } ``` ### 5. Alleles (no /allele resource in the public API) The public ClinPGx API does **not** expose an `/allele` resource. Canonical star-allele definitions, functional status, activity scores, and population frequencies are maintained by **PharmVar** (https://www.pharmvar.org/), which provides its own gene pages, downloads, and API. Allele-level clinical implications are surfaced through ClinPGx guideline annotations. **For star-allele data**, use PharmVar: ```bash # e.g. CYP2D6 star-allele definitions and frequencies # https://www.pharmvar.org/gene/CYP2D6 ``` **For allele-related clinical guidance**, use the guideline annotation endpoint: ```bash curl "https://api.clinpgx.org/v1/data/guidelineAnnotation?relatedGenes.symbol=CYP2D6" ``` ### 6. Variant Endpoint Search for genetic variants and their pharmacogenomic annotations. #### Resolve Variant by rsID The path form `/variant/{id}` expects a ClinPGx accession ID, so resolve an rsID via the collection endpoint and read the accession ID from the response. ```http GET /v1/data/variant?symbol={rsid} ``` **Parameters:** - `symbol` (query): dbSNP reference SNP ID (e.g., rs4244285) **Example Request:** ```bash curl "https://api.clinpgx.org/v1/data/variant?symbol=rs4244285" ``` #### Get Variant by Accession ID ```http GET /v1/data/variant/{variant_id} ``` **Parameters:** - `variant_id` (path, required): ClinPGx variant accession ID **Example:** ```bash curl "https://api.clinpgx.org/v1/data/variant/{variant_id}" ``` ### 7. Annotation Endpoints Access curated literature annotations for gene-drug-phenotype relationships. ClinPGx serves these through the `summaryAnnotation`, `variantAnnotation`, and `dataAnnotation` collections depending on annotation type. Query parameter names (including any level-of-evidence filter) should be confirmed against the live OpenAPI spec. #### Get Summary Annotations ```http GET /v1/data/summaryAnnotation?relatedGenes.symbol={gene}&relatedChemicals.name={drug} ``` **Parameters:** - `relatedGenes.symbol` (query, optional): Gene symbol - `relatedChemicals.name` (query, optional): Drug name/symbol **Example Requests:** ```bash # Summary annotations related to a gene curl "https://api.clinpgx.org/v1/data/summaryAnnotation?relatedGenes.symbol=CYP2D6" # Variant-level annotations related to a gene curl "https://api.clinpgx.org/v1/data/variantAnnotation?relatedGenes.symbol=TPMT" ``` **Example Response:** ```json [ { "id": "PA166153683", "gene": "CYP2D6", "drug": "codeine", "phenotype": "Reduced analgesic effect", "evidenceLevel": "1A", "annotation": "Poor metabolizers have reduced conversion...", "pmid": "24618998", "studyType": "Clinical trial", "population": "European", "sources": ["CPIC"] } ] ``` **Evidence Levels:** - **1A**: High-quality evidence from guidelines (CPIC, FDA, DPWG) - **1B**: High-quality evidence not yet guideline - **2A**: Moderate evidence from well-designed studies - **2B**: Moderate evidence with some limitations - **3**: Limited or conflicting evidence - **4**: Case reports or weak evidence ### 8. Label Endpoint Retrieve regulatory drug label information with pharmacogenomic content. #### Get Labels ```http GET /v1/data/label?relatedChemicals.name={drug_name}&source={source} ``` **Parameters:** - `relatedChemicals.name` (query): Drug name/symbol - `source` (query, optional): Regulatory source (FDA, EMA, PMDA, Health Canada) **Example Requests:** ```bash # Get all labels for warfarin curl "https://api.clinpgx.org/v1/data/label?relatedChemicals.name=warfarin" # Get only FDA labels curl "https://api.clinpgx.org/v1/data/label?relatedChemicals.name=warfarin&source=FDA" ``` **Example Response:** ```json [ { "id": "DL001234", "drug": "warfarin", "source": "FDA", "sections": { "testing": "Consider CYP2C9 and VKORC1 genotyping...", "dosing": "Dose adjustment based on genotype...", "warnings": "Risk of bleeding in certain genotypes" }, "biomarkers": ["CYP2C9", "VKORC1"], "testingRecommended": true, "labelUrl": "https://dailymed.nlm.nih.gov/...", "lastUpdated": "2024-01-15" } ] ``` ### 9. Pathway Endpoint Access pharmacokinetic and pharmacodynamic pathway diagrams and information. #### Get Pathway by ID ```http GET /v1/data/pathway/{pathway_id} ``` **Parameters:** - `pathway_id` (path, required): ClinPGx pathway accession ID **Example:** ```bash curl "https://api.clinpgx.org/v1/data/pathway/PA146123006" ``` #### Search Pathways ```http GET /v1/data/pathway?relatedChemicals.name={drug_name}&relatedGenes.symbol={gene} ``` **Parameters:** - `relatedChemicals.name` (query, optional): Drug name/symbol - `relatedGenes.symbol` (query, optional): Gene symbol **Example:** ```bash curl "https://api.clinpgx.org/v1/data/pathway?relatedChemicals.name=warfarin" ``` **Example Response:** ```json { "id": "PA146123006", "name": "Warfarin Pharmacokinetics and Pharmacodynamics", "drugs": ["warfarin"], "genes": ["CYP2C9", "VKORC1", "CYP4F2", "GGCX"], "description": "Warfarin is metabolized primarily by CYP2C9...", "diagramUrl": "https://www.clinpgx.org/pathway/...", "steps": [ { "step": 1, "process": "Absorption", "genes": [] }, { "step": 2, "process": "Metabolism", "genes": ["CYP2C9", "CYP2C19"] }, { "step": 3, "process": "Target interaction", "genes": ["VKORC1"] } ] } ``` ## Query Patterns and Examples ### Common Query Patterns #### 1. Patient Medication Review Find guideline annotations for a patient's medications: ```python import requests patient_meds = ["clopidogrel", "simvastatin", "codeine"] patient_genes = {"CYP2C19": "*1/*2", "CYP2D6": "*1/*1", "SLCO1B1": "*1/*5"} for med in patient_meds: response = requests.get( "https://api.clinpgx.org/v1/data/guidelineAnnotation", params={"relatedChemicals.name": med} ) guideline_annotations = response.json() # Cross-reference returned annotations against patient_genes ``` #### 2. Actionable Gene Panel Find genes with CPIC guideline annotations: ```python response = requests.get( "https://api.clinpgx.org/v1/data/guidelineAnnotation", params={"source": "CPIC"} ) guideline_annotations = response.json() # Enumerate genes from each annotation's relatedGenes genes = set() for ann in guideline_annotations: for g in ann.get("relatedGenes", []): genes.add(g.get("symbol")) print(f"Panel should include: {sorted(genes)}") ``` #### 3. Population Frequency Analysis Compare allele frequencies across populations. The ClinPGx API has no `/allele` resource; obtain star-allele definitions and frequencies from **PharmVar** (https://www.pharmvar.org/): ```python # Populate from PharmVar gene data, e.g. https://www.pharmvar.org/gene/CYP2D6 alleles = [] # list of allele records from PharmVar # Calculate phenotype frequencies pm_freq = {} # Poor metabolizer frequencies for allele in alleles: if allele['function'] == 'No function': for pop, freq in allele['frequencies'].items(): pm_freq[pop] = pm_freq.get(pop, 0) + freq ``` #### 4. Drug Safety Screen Check for high-risk gene-drug associations via guideline annotations: ```python # Screen for HLA-B*57:01 guidance before abacavir response = requests.get( "https://api.clinpgx.org/v1/data/guidelineAnnotation", params={"relatedChemicals.name": "abacavir"} ) guideline_annotations = response.json() # CPIC: Do not use if HLA-B*57:01 positive ``` ## Error Handling ### Common Error Responses #### 404 Not Found ```json { "error": "Resource not found", "message": "Gene 'INVALID' does not exist" } ``` #### 429 Too Many Requests ```json { "error": "Rate limit exceeded", "message": "Maximum 2 requests per second allowed" } ``` ### Recommended Error Handling Pattern ```python import requests import time def safe_query(url, params=None, max_retries=3): for attempt in range(max_retries): try: response = requests.get(url, params=params, timeout=10) if response.status_code == 200: time.sleep(0.5) # Rate limiting return response.json() elif response.status_code == 429: wait = 2 ** attempt print(f"Rate limited. Waiting {wait}s...") time.sleep(wait) elif response.status_code == 404: print("Resource not found") return None else: response.raise_for_status() except requests.RequestException as e: print(f"Attempt {attempt + 1} failed: {e}") if attempt == max_retries - 1: raise return None ``` ## Best Practices ### Rate Limiting - Implement 500ms delay between requests (2 requests/second maximum) - Use exponential backoff for rate limit errors - Consider caching results for frequently accessed data - For bulk operations, contact api@clinpgx.org ### Caching Strategy ```python import json from pathlib import Path def cached_query(cache_file, query_func, *args, **kwargs): cache_path = Path(cache_file) if cache_path.exists(): with open(cache_path) as f: return json.load(f) result = query_func(*args, **kwargs) if result: with open(cache_path, 'w') as f: json.dump(result, f) return result ``` ### Batch Processing ```python import time def batch_gene_query(genes, delay=0.5): results = {} for gene in genes: # Resolve each symbol via the collection endpoint (path takes an accession ID) response = requests.get( "https://api.clinpgx.org/v1/data/gene", params={"symbol": gene} ) if response.status_code == 200: results[gene] = response.json() time.sleep(delay) return results ``` ## Data Schema Definitions ### Gene Object ```typescript { id: string; // ClinPGx gene ID symbol: string; // HGNC gene symbol name: string; // Full gene name chromosome: string; // Chromosome location function: string; // Pharmacogenomic function clinicalAnnotations: number; // Count of annotations relatedDrugs: string[]; // Associated drugs } ``` ### Drug Object ```typescript { id: string; // ClinPGx drug ID name: string; // Generic name tradeNames: string[]; // Brand names drugClasses: string[]; // Therapeutic classes indication: string; // Primary indication relatedGenes: string[]; // Pharmacogenes } ``` ### Gene-Drug Relationship (derived, not a single endpoint object) There is no `geneDrugPair` resource. Relationships are derived from guideline annotations; inspect each annotation's `relatedGenes` and `relatedChemicals` fields together with its source and level-of-evidence fields (confirm exact field names against the live OpenAPI spec). ### Allele Object (PharmVar, not the ClinPGx API) Star-allele records are served by PharmVar (https://www.pharmvar.org/), not by the ClinPGx API. Refer to the PharmVar schema for the authoritative shape of allele name, function, activity score, population frequencies, and defining variants. ## API Stability and Versioning ### Current Status - API version: v1 - Stability: Beta - endpoints stable, parameters may change - Monitor: https://blog.clinpgx.org/ for updates ### Migration from PharmGKB As of July 2025, PharmGKB web URLs redirect to ClinPGx. The legacy API host `https://api.pharmgkb.org/` was **turned off on 2026-07-20** (it no longer answers), so update any old code: - Old: `https://api.pharmgkb.org/` (retired) - New: `https://api.clinpgx.org/` (same `/v1/data/...` paths) ### Future Changes - Watch for API v2 announcements - Breaking changes will be announced on ClinPGx Blog - Consider version pinning for production applications ## Support and Contact - **API Issues**: api@clinpgx.org - **Documentation**: https://api.clinpgx.org/ - **General Questions**: https://www.clinpgx.org/page/faqs - **Blog**: https://blog.clinpgx.org/ - **CPIC Guidelines**: https://cpicpgx.org/ ## Related Resources - **PharmCAT**: Pharmacogenomic variant calling and annotation tool - **PharmVar**: Pharmacogene allele nomenclature database - **CPIC**: Clinical Pharmacogenetics Implementation Consortium - **DPWG**: Dutch Pharmacogenetics Working Group - **ClinGen**: Clinical Genome Resource -
endpoints-and-capabilities.md 8.9 KB
# ClinPGx Endpoints and Core Capabilities Worked code for each of the nine ClinPGx capability areas. See `api_reference.md` for the complete endpoint/parameter listing. **Resource addressing reminder**: ClinPGx resources are addressed by ClinPGx accession IDs in the path (e.g. gene CYP2D6 = `PA128`, CYP2C9 = `PA126`), not by gene symbols or rsIDs. To resolve a symbol or rsID, query the collection endpoint with parameters (e.g. `GET /v1/data/gene?symbol=CYP2D6`, `GET /v1/data/variant?symbol=rs4244285`) and read the accession ID from the response. **Response/param reminder** (verified): every response is wrapped as `{"status": "success"|"fail", "data": [...]}`, so read records from `response.json()["data"]` — it is never a bare list. Filter genes with `relatedGenes.symbol` but drugs with `relatedChemicals.name` (`relatedChemicals.symbol` returns `status: "fail"`). The snippets below call `response.json()` for brevity; unwrap `["data"]` in real use (the helpers in `scripts/query_clinpgx.py` do this for you). Base URL: `https://api.clinpgx.org/v1/data/` ## 1. Gene Queries Retrieve gene function, clinical annotations, and pharmacogenomic significance: ```python import requests # Resolve a gene symbol to its ClinPGx record (accession ID is in the response) response = requests.get("https://api.clinpgx.org/v1/data/gene", params={"symbol": "CYP2D6"}) genes = response.json() # Get gene details directly by accession ID (CYP2D6 = PA128) response = requests.get("https://api.clinpgx.org/v1/data/gene/PA128") gene_data = response.json() ``` **Key pharmacogenes:** - **CYP450 enzymes**: CYP2D6, CYP2C19, CYP2C9, CYP3A4, CYP3A5 - **Transporters**: SLCO1B1, ABCB1, ABCG2 - **Other metabolizers**: TPMT, DPYD, NUDT15, UGT1A1 - **Receptors**: OPRM1, HTR2A, ADRB1 - **HLA genes**: HLA-B, HLA-A ## 2. Drug and Chemical Queries Retrieve drug information including pharmacogenomic annotations and mechanisms: ```python # Get drug details by ClinPGx accession ID (response is {"status","data"}) response = requests.get("https://api.clinpgx.org/v1/data/chemical/PA451906") # Warfarin drug_data = response.json()["data"] # Search drugs by name (filter chemicals by .name, not .symbol) response = requests.get("https://api.clinpgx.org/v1/data/chemical", params={"name": "warfarin"}) drugs = response.json()["data"] ``` **Drug categories with pharmacogenomic significance:** - Anticoagulants (warfarin, clopidogrel) - Antidepressants (SSRIs, TCAs) - Immunosuppressants (tacrolimus, azathioprine) - Oncology drugs (5-fluorouracil, irinotecan, tamoxifen) - Cardiovascular drugs (statins, beta-blockers) - Pain medications (codeine, tramadol) - Antivirals (abacavir) ## 3. Gene-Drug Pair Queries There is no single gene-drug-pair endpoint in the public API; derive pairs from guideline annotations, or use the pair report endpoint when you have both object accession IDs: ```python # Derive gene-drug relationships from guideline annotations response = requests.get("https://api.clinpgx.org/v1/data/guidelineAnnotation", params={"relatedChemicals.name": "codeine"}) guideline_annotations = response.json() # Pair report endpoint (requires accession IDs for both objects) # /report/pair/{firstObjId}/{secondObjId}/{resultType} response = requests.get( "https://api.clinpgx.org/v1/report/pair/PA128/PA449088/guidelineAnnotation" ) pair_report = response.json() ``` **Clinical annotation sources:** - CPIC (Clinical Pharmacogenetics Implementation Consortium) - DPWG (Dutch Pharmacogenetics Working Group) - FDA (Food and Drug Administration) labels - Peer-reviewed literature summary annotations ## 4. CPIC Guidelines Access evidence-based clinical practice guidelines: ```python # Get a guideline annotation by accession ID response = requests.get("https://api.clinpgx.org/v1/data/guidelineAnnotation/PA166104939") guideline = response.json() # List guideline annotations from a given source response = requests.get("https://api.clinpgx.org/v1/data/guidelineAnnotation", params={"source": "CPIC"}) guidelines = response.json() ``` **CPIC guideline components:** gene-drug pairs covered, clinical recommendations by phenotype, evidence levels and strength ratings, supporting literature, downloadable PDFs and supplementary materials, and implementation considerations. **Example guidelines:** - CYP2D6-codeine (avoid in ultra-rapid metabolizers) - CYP2C19-clopidogrel (alternative therapy for poor metabolizers) - TPMT-azathioprine (dose reduction for intermediate/poor metabolizers) - DPYD-fluoropyrimidines (dose adjustment based on activity) - HLA-B*57:01-abacavir (avoid if positive) ## 5. Allele and Variant Information The public ClinPGx API does **not** expose a dedicated `/allele` resource. Star-allele definitions, functional status, and population frequencies are maintained by **PharmVar** (https://www.pharmvar.org/); allele-level clinical implications are surfaced through guideline annotations: ```python # Allele function / phenotype implications come through guideline annotations response = requests.get("https://api.clinpgx.org/v1/data/guidelineAnnotation", params={"relatedGenes.symbol": "CYP2D6"}) guideline_annotations = response.json() # For canonical star-allele definitions and frequencies, use PharmVar: # https://www.pharmvar.org/gene/CYP2D6 ``` **Allele information (via PharmVar / guideline annotations) includes:** functional status (normal, decreased, no function, increased, uncertain), population frequencies across ethnic groups, defining variants (SNPs, indels, CNVs), phenotype assignment, and references to PharmVar and other nomenclature systems. **Phenotype categories:** - **Ultra-rapid metabolizer** (UM): Increased enzyme activity - **Normal metabolizer** (NM): Normal enzyme activity - **Intermediate metabolizer** (IM): Reduced enzyme activity - **Poor metabolizer** (PM): Little to no enzyme activity ## 6. Variant Annotations Access clinical annotations for specific genetic variants: ```python # Resolve an rsID to its ClinPGx variant record (accession ID is in the response) response = requests.get("https://api.clinpgx.org/v1/data/variant", params={"symbol": "rs4244285"}) variants = response.json() # Then fetch the full record directly by its accession ID, e.g.: # requests.get(f"https://api.clinpgx.org/v1/data/variant/{variants[0]['id']}") ``` **Variant data includes:** rsID and genomic coordinates, gene and functional consequence, allele associations, clinical significance, population frequencies, and literature references. ## 7. Clinical Annotations Curated literature annotations (formerly PharmGKB clinical annotations) are served by the annotation collections `summaryAnnotation`, `variantAnnotation`, and `dataAnnotation` depending on annotation type: ```python # Get summary (clinical) annotations related to a gene response = requests.get("https://api.clinpgx.org/v1/data/summaryAnnotation", params={"relatedGenes.symbol": "CYP2D6"}) annotations = response.json() # Variant-level annotations response = requests.get("https://api.clinpgx.org/v1/data/variantAnnotation", params={"relatedGenes.symbol": "CYP2D6"}) variant_annotations = response.json() ``` Confirm the exact query parameter names and any evidence-level filters against the live OpenAPI spec before relying on them in production. **Evidence levels** (highest to lowest): - **Level 1A**: High-quality evidence, CPIC/FDA/DPWG guidelines - **Level 1B**: High-quality evidence, not yet guideline - **Level 2A**: Moderate evidence from well-designed studies - **Level 2B**: Moderate evidence with some limitations - **Level 3**: Limited or conflicting evidence - **Level 4**: Case reports or weak evidence ## 8. Drug Labels Access pharmacogenomic information from drug labels: ```python # Get drug labels with PGx information response = requests.get("https://api.clinpgx.org/v1/data/label", params={"relatedChemicals.name": "warfarin"}) labels = response.json() # Filter by regulatory source response = requests.get("https://api.clinpgx.org/v1/data/label", params={"source": "FDA"}) fda_labels = response.json() ``` **Label information includes:** testing recommendations, dosing guidance by genotype, warnings and precautions, biomarker information, and regulatory source (FDA, EMA, PMDA, etc.). ## 9. Pathways Explore pharmacokinetic and pharmacodynamic pathways: ```python # Get pathway information by accession ID response = requests.get("https://api.clinpgx.org/v1/data/pathway/PA146123006") # Warfarin pathway pathway_data = response.json() # Search pathways related to a drug response = requests.get("https://api.clinpgx.org/v1/data/pathway", params={"relatedChemicals.name": "warfarin"}) pathways = response.json() ``` **Pathway diagrams** show: drug metabolism steps, enzymes and transporters involved, gene variants affecting each step, downstream effects on efficacy/toxicity, and interactions with other pathways. -
query-workflows.md 6.5 KB
# ClinPGx Query Workflows End-to-end workflows and common use cases for ClinPGx. All queries respect the 2 req/sec rate limit — see `rate-limiting-and-error-handling.md`. **Verified API conventions used throughout**: responses are wrapped as `{"status", "data"}` (read results from `response.json()["data"]`, never a bare list); filter genes with `relatedGenes.symbol` and drugs with `relatedChemicals.name` (`relatedChemicals.symbol` returns `status: "fail"`). The snippets below show `response.json()` for brevity — unwrap `["data"]` in real use, or call the helpers in `scripts/query_clinpgx.py`, which unwrap it for you. ## Workflow 1: Clinical Decision Support for Drug Prescription 1. **Identify patient genotype** for relevant pharmacogenes: ```python # Example: Patient is CYP2C19 *1/*2 (intermediate metabolizer) # Star-allele function/definitions come from PharmVar (no /allele resource in the API): # https://www.pharmvar.org/gene/CYP2C19 ``` 2. **Find guideline annotations** for the medication of interest: ```python response = requests.get("https://api.clinpgx.org/v1/data/guidelineAnnotation", params={"relatedChemicals.name": "clopidogrel"}) guideline_annotations = response.json() # Recommendation: Alternative antiplatelet therapy for IM/PM ``` 3. **Check drug label** for regulatory guidance: ```python response = requests.get("https://api.clinpgx.org/v1/data/label", params={"relatedChemicals.name": "clopidogrel"}) label = response.json() ``` ## Workflow 2: Gene Panel Analysis 1. **Get list of pharmacogenes** in clinical panel: ```python pgx_panel = ["CYP2C19", "CYP2D6", "CYP2C9", "TPMT", "DPYD", "SLCO1B1"] ``` 2. **For each gene, retrieve its guideline annotations**: ```python all_interactions = {} for gene in pgx_panel: response = requests.get("https://api.clinpgx.org/v1/data/guidelineAnnotation", params={"relatedGenes.symbol": gene}) all_interactions[gene] = response.json() ``` 3. **Review the guideline annotations** returned for each gene: ```python for gene, annotations in all_interactions.items(): for ann in annotations: print(f"{gene}: {ann.get('name')}") ``` 4. **Generate patient report** with actionable pharmacogenomic findings. ## Workflow 3: Drug Safety Assessment 1. **Query drug for PGx associations**: ```python response = requests.get("https://api.clinpgx.org/v1/data/chemical", params={"name": "abacavir"}) drug_id = response.json()["data"][0]['id'] ``` 2. **Get summary annotations**: ```python response = requests.get("https://api.clinpgx.org/v1/data/summaryAnnotation", params={"relatedChemicals.name": "abacavir"}) annotations = response.json() ``` 3. **Check for HLA associations** and toxicity risk: ```python for annotation in annotations: if 'HLA' in annotation.get('genes', []): print(f"Toxicity risk: {annotation.get('phenotype')}") ``` 4. **Retrieve screening recommendations** from guidelines and labels. ## Workflow 4: Research Analysis — Population Pharmacogenomics 1. **Get allele frequencies** for population comparison. The ClinPGx API has no `/allele` resource; allele definitions and population frequencies are obtained from **PharmVar** (https://www.pharmvar.org/), which offers its own download/API: ```python # e.g. PharmVar gene page / downloads for CYP2D6 star-allele frequencies # https://www.pharmvar.org/gene/CYP2D6 alleles = [] # populate from PharmVar data ``` 2. **Extract population-specific frequencies** from the PharmVar records: ```python populations = ['European', 'African', 'East Asian', 'Latino'] frequency_data = {} for allele in alleles: allele_name = allele['name'] frequency_data[allele_name] = { pop: allele.get(f'{pop}_frequency', 'N/A') for pop in populations } ``` 3. **Calculate phenotype distributions** by population: ```python # Combine allele frequencies with function to predict phenotypes phenotype_dist = calculate_phenotype_frequencies(frequency_data) ``` 4. **Analyze implications** for drug dosing in diverse populations. ## Workflow 5: Literature Evidence Review 1. **Find guideline annotations for the gene-drug relationship**: ```python response = requests.get("https://api.clinpgx.org/v1/data/guidelineAnnotation", params={"relatedGenes.symbol": "TPMT"}) guideline_annotations = response.json() ``` 2. **Retrieve all summary annotations**: ```python response = requests.get("https://api.clinpgx.org/v1/data/summaryAnnotation", params={"relatedGenes.symbol": "TPMT"}) annotations = response.json() ``` 3. **Filter by the annotation's level-of-evidence field** (confirm field name against the OpenAPI spec): ```python high_quality = [a for a in annotations if a.get('levelOfEvidence') in ['1A', '1B', '2A']] ``` 4. **Extract PMIDs** and retrieve full references: ```python pmids = [a['pmid'] for a in high_quality if 'pmid' in a] # Use PubMed skill to retrieve full citations ``` ## Common Use Cases ### Pre-emptive Pharmacogenomic Testing Query all clinically actionable gene-drug pairs to guide panel selection: ```python # List CPIC guideline annotations and derive the actionable gene-drug pairs from them response = requests.get("https://api.clinpgx.org/v1/data/guidelineAnnotation", params={"source": "CPIC"}) guideline_annotations = response.json() ``` ### Medication Therapy Management Review patient medications against known genotypes: ```python patient_genes = {"CYP2C19": "*1/*2", "CYP2D6": "*1/*1", "SLCO1B1": "*1/*5"} medications = ["clopidogrel", "simvastatin", "escitalopram"] for med in medications: response = requests.get("https://api.clinpgx.org/v1/data/guidelineAnnotation", params={"relatedChemicals.name": med}) guideline_annotations = response.json() # Cross-reference returned annotations against patient_genes for dosing guidance ``` ### Clinical Trial Eligibility Screen for pharmacogenomic contraindications: ```python # Check for HLA-B*57:01 guidance before abacavir trial response = requests.get("https://api.clinpgx.org/v1/data/guidelineAnnotation", params={"relatedChemicals.name": "abacavir"}) guideline_annotations = response.json() # CPIC: Do not use if HLA-B*57:01 positive ``` -
rate-limiting-and-error-handling.md 2.8 KB
# ClinPGx Rate Limiting, Error Handling, and Caching Reusable helpers for compliant, robust ClinPGx API access. The API allows a maximum of **2 requests per second**; exceeding it returns HTTP 429. For substantial API use, notify the ClinPGx team at api@clinpgx.org. **Note**: `safe_api_call` below returns the raw `{"status", "data"}` envelope. Unwrap the records with `result["data"]` (and treat `status == "fail"` — e.g. "No results matching criteria" — as an empty result). `scripts/query_clinpgx.py` provides an `unwrap()` helper and query functions that do this for you. ## Rate Limit Compliance ```python import requests import time def rate_limited_request(url, params=None, delay=0.5): """Make API request with rate limiting (2 req/sec max)""" response = requests.get(url, params=params) time.sleep(delay) # Wait 0.5 seconds between requests return response # Use in loops (resolve each gene symbol via the collection endpoint) genes = ["CYP2D6", "CYP2C19", "CYP2C9"] for gene in genes: response = rate_limited_request( "https://api.clinpgx.org/v1/data/gene", params={"symbol": gene} ) data = response.json() ``` ## Error Handling ```python def safe_api_call(url, params=None, max_retries=3): """API call with error handling and retries""" for attempt in range(max_retries): try: response = requests.get(url, params=params, timeout=10) if response.status_code == 200: return response.json() elif response.status_code == 429: # Rate limit exceeded wait_time = 2 ** attempt # Exponential backoff print(f"Rate limit hit. Waiting {wait_time}s...") time.sleep(wait_time) else: response.raise_for_status() except requests.exceptions.RequestException as e: print(f"Attempt {attempt + 1} failed: {e}") if attempt == max_retries - 1: raise time.sleep(1) ``` ## Caching Results ```python import json from pathlib import Path def cached_query(cache_file, api_func, *args, **kwargs): """Cache API results to avoid repeated queries""" cache_path = Path(cache_file) if cache_path.exists(): with open(cache_path) as f: return json.load(f) result = api_func(*args, **kwargs) # must return JSON-serializable data if result is not None: with open(cache_path, 'w') as f: json.dump(result, f, indent=2) return result # Usage (CYP2D6 = accession PA128). Pass a func that returns parsed JSON # (e.g. safe_api_call), NOT rate_limited_request, which returns a Response. envelope = cached_query( 'cyp2d6_cache.json', safe_api_call, "https://api.clinpgx.org/v1/data/gene/PA128" ) gene_data = envelope["data"] if envelope else None ```
-
-
scripts
-
query_clinpgx.py 17.5 KB
#!/usr/bin/env python3 """ ClinPGx API Query Helper Script Provides ready-to-use functions for querying the ClinPGx database API. Includes rate limiting, error handling, and caching functionality. ClinPGx API: https://api.clinpgx.org/ Rate limit: 2 requests per second License: Creative Commons Attribution-ShareAlike 4.0 International """ import requests import time import json from pathlib import Path from typing import Dict, List, Optional, Any # API Configuration # ClinPGx resources are addressed by ClinPGx accession IDs in the path # (e.g. gene CYP2D6 = PA128, CYP2C9 = PA126), not by symbols/rsIDs. Resolve a # symbol or rsID via the collection endpoints with params (e.g. ?symbol=CYP2D6). # # Query-param convention (verified against the live API): # - genes are matched by `relatedGenes.symbol` (the `.name` form fails) # - chemicals/drugs are matched by `relatedChemicals.name` (the `.symbol` # form returns status:"fail" / "No results matching criteria") # # Response envelope: every response is a JSON object of the form # {"status": "success"|"fail", "data": [...] | {"errors": [...]}} # so the payload is NEVER a bare list — read it via `payload["data"]`. The # helpers below unwrap this for you (see `unwrap`). BASE_URL = "https://api.clinpgx.org/v1/data/" RATE_LIMIT_DELAY = 0.5 # 500ms delay = 2 requests/second def unwrap(payload: Optional[Dict]) -> Optional[Any]: """ Unwrap the ClinPGx {"status", "data"} response envelope. Returns the inner `data` on success, or None when the request failed, returned no results, or the payload was empty/malformed. """ if not isinstance(payload, dict): return None if payload.get("status") == "fail": return None return payload.get("data") def rate_limited_request(url: str, params: Optional[Dict] = None, delay: float = RATE_LIMIT_DELAY) -> requests.Response: """ Make API request with rate limiting compliance. Args: url: API endpoint URL params: Query parameters delay: Delay in seconds between requests (default 0.5s for 2 req/sec) Returns: Response object """ response = requests.get(url, params=params) time.sleep(delay) return response def safe_api_call(url: str, params: Optional[Dict] = None, max_retries: int = 3) -> Optional[Dict]: """ Make API call with error handling and exponential backoff retry. Args: url: API endpoint URL params: Query parameters max_retries: Maximum number of retry attempts Returns: JSON response data or None on failure """ for attempt in range(max_retries): try: response = requests.get(url, params=params, timeout=10) if response.status_code == 200: time.sleep(RATE_LIMIT_DELAY) return response.json() elif response.status_code == 429: # Rate limit exceeded wait_time = 2 ** attempt # Exponential backoff: 1s, 2s, 4s print(f"Rate limit exceeded. Waiting {wait_time}s before retry...") time.sleep(wait_time) elif response.status_code == 404: print(f"Resource not found: {url}") return None else: response.raise_for_status() except requests.exceptions.RequestException as e: print(f"Attempt {attempt + 1}/{max_retries} failed: {e}") if attempt == max_retries - 1: print(f"Failed after {max_retries} attempts") return None time.sleep(1) return None def cached_query(cache_file: str, query_func, *args, **kwargs) -> Any: """ Cache API results to avoid repeated queries. Args: cache_file: Path to cache file query_func: Function to call if cache miss *args, **kwargs: Arguments to pass to query_func Returns: Cached or freshly queried data """ cache_path = Path(cache_file) if cache_path.exists(): print(f"Loading from cache: {cache_file}") with open(cache_path) as f: return json.load(f) print(f"Cache miss. Querying API...") result = query_func(*args, **kwargs) if result is not None: cache_path.parent.mkdir(parents=True, exist_ok=True) with open(cache_path, 'w') as f: json.dump(result, f, indent=2) print(f"Cached to: {cache_file}") return result # Core Query Functions def get_gene_info(gene_symbol: str) -> Optional[List[Dict]]: """ Resolve a pharmacogene symbol to its ClinPGx record(s). The path form /gene/{id} expects a ClinPGx accession ID (e.g. CYP2D6 = PA128), so to look up by symbol we query the collection endpoint with ?symbol=. Args: gene_symbol: Gene symbol (e.g., "CYP2D6", "TPMT") Returns: List of matching gene records (read the accession ID from result['id']) Example: >>> genes = get_gene_info("CYP2D6") >>> print(genes[0]['symbol'], genes[0]['id']) """ url = f"{BASE_URL}gene" return unwrap(safe_api_call(url, {"symbol": gene_symbol})) def get_gene_by_id(gene_id: str) -> Optional[Dict]: """ Retrieve a gene record directly by its ClinPGx accession ID. Args: gene_id: ClinPGx gene accession ID (e.g., "PA128" for CYP2D6) Returns: Gene information dictionary """ url = f"{BASE_URL}gene/{gene_id}" return unwrap(safe_api_call(url)) def get_drug_info(drug_name: str) -> Optional[List[Dict]]: """ Search for drug/chemical information by name. Args: drug_name: Drug name (e.g., "warfarin", "codeine") Returns: List of matching drugs Example: >>> drugs = get_drug_info("warfarin") >>> for drug in drugs: >>> print(drug['name'], drug['id']) """ url = f"{BASE_URL}chemical" params = {"name": drug_name} return unwrap(safe_api_call(url, params)) def get_gene_drug_pairs(gene: Optional[str] = None, drug: Optional[str] = None) -> Optional[List[Dict]]: """ Derive gene-drug relationships from guideline annotations. The public ClinPGx API has no single gene-drug-pair endpoint; pairs are derived from guideline annotations (or the /report/pair report endpoint when both object accession IDs are known). Args: gene: Gene symbol (optional) drug: Drug name / symbol (optional) Returns: List of guideline annotations matching the gene and/or drug Example: >>> # Guideline annotations related to CYP2D6 >>> anns = get_gene_drug_pairs(gene="CYP2D6") >>> >>> # Guideline annotations related to codeine >>> anns = get_gene_drug_pairs(drug="codeine") """ url = f"{BASE_URL}guidelineAnnotation" params = {} if gene: params["relatedGenes.symbol"] = gene if drug: params["relatedChemicals.name"] = drug return unwrap(safe_api_call(url, params)) def get_pair_report(first_obj_id: str, second_obj_id: str, result_type: str = "guidelineAnnotation") -> Optional[Any]: """ Fetch a pair report for two ClinPGx objects via the report endpoint. Endpoint: /report/pair/{firstObjId}/{secondObjId}/{resultType} Args: first_obj_id: Accession ID of the first object (e.g. gene "PA128") second_obj_id: Accession ID of the second object (e.g. chemical "PA449088") result_type: Report result type (e.g. "guidelineAnnotation") Returns: Pair report data """ url = f"https://api.clinpgx.org/v1/report/pair/{first_obj_id}/{second_obj_id}/{result_type}" return unwrap(safe_api_call(url)) def get_cpic_guidelines(gene: Optional[str] = None, drug: Optional[str] = None) -> Optional[List[Dict]]: """ Retrieve CPIC clinical practice guidelines. Args: gene: Gene symbol (optional) drug: Drug name (optional) Returns: List of CPIC guidelines Example: >>> # Get all CPIC guidelines >>> guidelines = get_cpic_guidelines() >>> >>> # Get guideline for specific gene-drug >>> guideline = get_cpic_guidelines(gene="CYP2C19", drug="clopidogrel") """ url = f"{BASE_URL}guidelineAnnotation" params = {"source": "CPIC"} if gene: params["relatedGenes.symbol"] = gene if drug: params["relatedChemicals.name"] = drug return unwrap(safe_api_call(url, params)) def get_alleles(gene: str) -> Optional[List[Dict]]: """ Star-allele definitions, functions, and population frequencies. NOTE: The public ClinPGx API does NOT expose an /allele resource. Canonical star-allele definitions and frequencies are maintained by PharmVar (https://www.pharmvar.org/). Allele-level clinical implications are surfaced through guideline annotations; this helper returns the guideline annotations related to the gene so callers do not rely on a non-existent endpoint. Args: gene: Gene symbol (e.g., "CYP2D6") Returns: List of guideline annotations related to the gene Example: >>> # For canonical allele data use PharmVar: https://www.pharmvar.org/gene/CYP2D6 >>> anns = get_alleles("CYP2D6") """ url = f"{BASE_URL}guidelineAnnotation" params = {"relatedGenes.symbol": gene} return unwrap(safe_api_call(url, params)) def get_clinical_annotations( gene: Optional[str] = None, drug: Optional[str] = None, evidence_level: Optional[str] = None ) -> Optional[List[Dict]]: """ Retrieve curated literature annotations for gene-drug interactions. Served by the summaryAnnotation collection (use variantAnnotation / dataAnnotation for variant- or data-level annotations). The level-of-evidence filter field is unverified against the OpenAPI spec; confirm before relying on it. Args: gene: Gene symbol (optional) drug: Drug name / symbol (optional) evidence_level: Filter by level of evidence (1A, 1B, 2A, 2B, 3, 4) Returns: List of summary annotations Example: >>> # Get summary annotations related to CYP2D6 >>> annotations = get_clinical_annotations(gene="CYP2D6") """ url = f"{BASE_URL}summaryAnnotation" params = {} if gene: params["relatedGenes.symbol"] = gene if drug: params["relatedChemicals.name"] = drug if evidence_level: params["levelOfEvidence"] = evidence_level return unwrap(safe_api_call(url, params)) def get_drug_labels(drug: str, source: Optional[str] = None) -> Optional[List[Dict]]: """ Retrieve pharmacogenomic drug label information. Args: drug: Drug name source: Regulatory source (e.g., "FDA", "EMA") Returns: List of drug labels with PGx information Example: >>> # Get all labels for warfarin >>> labels = get_drug_labels("warfarin") >>> >>> # Get only FDA labels >>> fda_labels = get_drug_labels("warfarin", source="FDA") """ url = f"{BASE_URL}label" params = {"relatedChemicals.name": drug} if source: params["source"] = source return unwrap(safe_api_call(url, params)) def search_variants(rsid: Optional[str] = None) -> Optional[List[Dict]]: """ Resolve a genetic variant by rsID. The path form /variant/{id} expects a ClinPGx accession ID, so to look up by rsID we query the collection endpoint with ?symbol=. Read the accession ID from result['id'] to fetch the full record directly. Args: rsid: dbSNP rsID (e.g., "rs4244285") Returns: List of matching variant records Example: >>> variants = search_variants(rsid="rs4244285") >>> # full record: get_variant_by_id(variants[0]['id']) """ url = f"{BASE_URL}variant" return unwrap(safe_api_call(url, {"symbol": rsid})) def get_variant_by_id(variant_id: str) -> Optional[Dict]: """ Retrieve a variant record directly by its ClinPGx accession ID. Args: variant_id: ClinPGx variant accession ID Returns: Variant information dictionary """ url = f"{BASE_URL}variant/{variant_id}" return unwrap(safe_api_call(url)) def get_pathway_info(pathway_id: Optional[str] = None, drug: Optional[str] = None) -> Optional[Any]: """ Retrieve pharmacokinetic/pharmacodynamic pathway information. Args: pathway_id: ClinPGx pathway ID (optional) drug: Drug name (optional) Returns: Pathway information or list of pathways Example: >>> # Get specific pathway >>> pathway = get_pathway_info(pathway_id="PA146123006") >>> >>> # Get all pathways for a drug >>> pathways = get_pathway_info(drug="warfarin") """ if pathway_id: url = f"{BASE_URL}pathway/{pathway_id}" return unwrap(safe_api_call(url)) url = f"{BASE_URL}pathway" params = {} if drug: params["relatedChemicals.name"] = drug return unwrap(safe_api_call(url, params)) # Utility Functions def export_to_dataframe(data: List[Dict], output_file: Optional[str] = None): """ Convert API results to pandas DataFrame for analysis. Args: data: List of dictionaries from API output_file: Optional CSV output file path Returns: pandas DataFrame Example: >>> pairs = get_gene_drug_pairs(gene="CYP2D6") >>> df = export_to_dataframe(pairs, "cyp2d6_pairs.csv") >>> print(df.head()) """ try: import pandas as pd except ImportError: print("pandas not installed. Install with: pip install pandas") return None df = pd.DataFrame(data) if output_file: df.to_csv(output_file, index=False) print(f"Data exported to: {output_file}") return df def batch_gene_query(gene_list: List[str], delay: float = 0.5) -> Dict[str, List[Dict]]: """ Resolve multiple gene symbols in batch with rate limiting. Args: gene_list: List of gene symbols delay: Delay between requests (default 0.5s) Returns: Dictionary mapping each gene symbol to its list of matching records Example: >>> genes = ["CYP2D6", "CYP2C19", "CYP2C9", "TPMT"] >>> results = batch_gene_query(genes) >>> for gene, recs in results.items(): >>> print(f"{gene}: {recs[0]['id'] if recs else 'not found'}") """ results = {} print(f"Querying {len(gene_list)} genes with {delay}s delay between requests...") for gene in gene_list: print(f"Fetching: {gene}") data = get_gene_info(gene) if data: results[gene] = data time.sleep(delay) print(f"Completed: {len(results)}/{len(gene_list)} successful") return results def find_actionable_gene_drug_pairs(source: str = "CPIC") -> Optional[List[Dict]]: """ Find clinically actionable gene-drug relationships via guideline annotations. There is no geneDrugPair endpoint (and no cpicLevel parameter) in the public API. Actionable pairs are derived from guideline annotations; inspect each returned annotation's relatedGenes / relatedChemicals to enumerate pairs. Args: source: Guideline source to filter on (e.g. "CPIC", "DPWG") Returns: List of guideline annotations from the requested source Example: >>> actionable = find_actionable_gene_drug_pairs(source="CPIC") >>> for ann in actionable: >>> print(ann.get("name")) """ url = f"{BASE_URL}guidelineAnnotation" params = {"source": source} return unwrap(safe_api_call(url, params)) # Example Usage if __name__ == "__main__": print("ClinPGx API Query Examples\n") # Example 1: Get gene information print("=" * 60) print("Example 1: Get CYP2D6 gene information") print("=" * 60) cyp2d6 = get_gene_info("CYP2D6") if cyp2d6: rec = cyp2d6[0] print(f"Gene: {rec.get('symbol')}") print(f"ID: {rec.get('id')}") print(f"Name: {rec.get('name')}") print() # Example 2: Search for a drug print("=" * 60) print("Example 2: Search for warfarin") print("=" * 60) warfarin = get_drug_info("warfarin") if warfarin: for drug in warfarin[:1]: # Show first result print(f"Drug: {drug.get('name')}") print(f"ID: {drug.get('id')}") print() # Example 3: Derive gene-drug relationship from guideline annotations print("=" * 60) print("Example 3: Guideline annotations for CYP2C19 + clopidogrel") print("=" * 60) pair = get_gene_drug_pairs(gene="CYP2C19", drug="clopidogrel") if pair: print(f"Found {len(pair)} guideline annotation(s)") if len(pair) > 0: print(f"First: {pair[0].get('name')}") print() # Example 4: Get CPIC guidelines print("=" * 60) print("Example 4: Get CPIC guidelines for CYP2C19") print("=" * 60) guidelines = get_cpic_guidelines(gene="CYP2C19") if guidelines: print(f"Found {len(guidelines)} guideline(s)") for g in guidelines[:2]: # Show first 2 print(f" - {g.get('name')}") print() # Example 5: Allele-related guideline annotations for a gene # (canonical allele definitions/frequencies: https://www.pharmvar.org/gene/CYP2D6) print("=" * 60) print("Example 5: CYP2D6 allele-related guideline annotations") print("=" * 60) alleles = get_alleles("CYP2D6") if alleles: print(f"Found {len(alleles)} guideline annotation(s)") for ann in alleles[:3]: # Show first 3 print(f" - {ann.get('name')}") print() print("=" * 60) print("Examples completed!") print("=" * 60)
-
-
SKILL.md 8.4 KB
--- name: alterlab-clinpgx description: Access ClinPGx pharmacogenomics data (the successor to PharmGKB) to query gene-drug interactions, CPIC/DPWG dosing guidelines, drug labels, and pharmacogene records. Use when interpreting pharmacogenes (CYP2D6, CYP2C19, TPMT, DPYD, SLCO1B1), looking up genotype-guided drug dosing, checking PGx drug-safety associations (e.g. HLA-B*57:01 and abacavir), or supporting precision medicine and clinical pharmacogenomics decisions. For star-allele definitions/frequencies see PharmVar; for germline/somatic variant pathogenicity see alterlab-clinvar. Part of the AlterLab Academic Skills suite. license: MIT allowed-tools: Read WebFetch Bash(curl:*) Bash(python:*) compatibility: Keyless ClinPGx (PharmGKB) API for basic access (no authentication required) metadata: skill-author: AlterLab version: "1.0.1" last_updated: "2026-09-23" --- # ClinPGx Database ## Overview ClinPGx (Clinical Pharmacogenomics Database) is a comprehensive resource for clinical pharmacogenomics, the successor to PharmGKB. It consolidates data from PharmGKB, CPIC, and PharmCAT, providing curated information on how genetic variation affects medication response. Access gene-drug pairs, clinical guidelines, allele functions, and drug labels for precision medicine. ## When to Use This Skill Use this skill for: - **Gene-drug interactions** — how variants affect drug metabolism, efficacy, or toxicity - **CPIC guidelines** — evidence-based clinical practice guidelines for pharmacogenetics - **Allele information** — allele function, frequency, and phenotype data - **Drug labels** — FDA and other regulatory pharmacogenomic labeling - **Pharmacogenomic annotations** — curated literature on gene-drug-disease relationships - **Clinical decision support** — PharmDOG for phenoconversion and custom genotype interpretation - **Precision medicine / personalized dosing** — genotype-guided dosing recommendations - **Drug metabolism** — CYP450 and other pharmacogene functions - **Adverse drug reactions** — genetic risk factors for drug toxicity ### Does NOT Trigger | Scenario | Use Instead | |----------|-------------| | Germline/somatic variant pathogenicity or ClinVar review status | `alterlab-clinvar` | | Population allele frequencies for a variant (gnomAD v4) | `alterlab-gnomad` | | Drug–drug interactions or general pharmacology with no genetic component | `alterlab-drugbank` | | FDA adverse-event reports, recalls, or full-text label search | `alterlab-fda` | ## Setup and Access Essentials Only `requests` is needed. Run the helper script (or any snippet) with an ephemeral dependency — no venv to manage: ```bash uv run --with requests python scripts/query_clinpgx.py # or, inside an existing project venv: uv pip install requests ``` Base URL: `https://api.clinpgx.org/v1/data/` — the legacy `api.pharmgkb.org` host was turned off on 2026-07-20, so older PharmGKB scripts must switch hostnames (paths are unchanged). - **Resource addressing**: ClinPGx resources are addressed by ClinPGx accession IDs in the path (e.g. gene CYP2D6 = `PA128`, CYP2C9 = `PA126`), **not** by gene symbols or rsIDs. To resolve a symbol or rsID, query the collection endpoint with parameters (e.g. `GET /v1/data/gene?symbol=CYP2D6`, `GET /v1/data/variant?symbol=rs4244285`) and read the accession ID from the response. - **Response envelope** (verified): every response is a JSON object `{"status": "success"|"fail", "data": [...]}` — the payload is **never** a bare list. Read results from `response.json()["data"]`; on `status == "fail"`, `data` is `{"errors": [...]}` (e.g. "No results matching criteria"). - **Query-param convention** (verified): genes filter on `relatedGenes.symbol` (the `.name` form fails), while chemicals/drugs filter on `relatedChemicals.name` — `relatedChemicals.symbol` silently returns `status: "fail"` with zero results. The `gene` collection takes `?symbol=`, the `chemical` collection takes `?name=`, and `variant` accepts `?symbol=`/`?name=`. - **Rate limits**: 2 requests per second maximum; excessive requests return HTTP 429. Implement a ~500ms delay between requests. - **Authentication**: Not required for basic access. - **Data license**: Creative Commons Attribution-ShareAlike 4.0 International. - For substantial API use, notify the ClinPGx team at **api@clinpgx.org**. ## Core Workflow 1. **Resolve identifiers** — Convert gene symbols / rsIDs to ClinPGx accession IDs via collection endpoints with `symbol=` parameters. 2. **Query the relevant resource** — `gene`, `chemical`, `guidelineAnnotation`, `summaryAnnotation`, `variantAnnotation`, `variant`, `label`, or `pathway`. There is no `/allele` resource — use **PharmVar** (https://www.pharmvar.org/) for star-allele definitions and population frequencies. 3. **Derive gene-drug relationships** — From guideline annotations (`relatedGenes.symbol` for genes, `relatedChemicals.name` for drugs), or the `/report/pair/{firstObjId}/{secondObjId}/{resultType}` endpoint. 4. **Filter by evidence level** — Prefer levels 1A/1B/2A for clinical use; confirm field names against the live OpenAPI spec. 5. **Respect rate limits** — Throttle, retry on 429 with backoff, and cache. For ready-made functions with rate limiting and error handling, see `scripts/query_clinpgx.py`. ## Routing Guidance - **Need the exact code for a resource (gene, chemical, gene-drug pair, CPIC guideline, allele/PharmVar, variant, clinical annotation, label, pathway)?** Read `references/endpoints-and-capabilities.md`. - **Doing an end-to-end task (clinical decision support, gene-panel analysis, drug-safety assessment, population pharmacogenomics, literature review) or a common use case?** Read `references/query-workflows.md`. - **Need robust API plumbing (rate limiting, retries, caching)?** Read `references/rate-limiting-and-error-handling.md`. - **Need full endpoint/parameter/schema details?** Read `references/api_reference.md`. ## References - `references/api_reference.md` — Complete endpoint listing, request/response formats, filter operators, data schemas, rate-limit details, and troubleshooting. - `references/endpoints-and-capabilities.md` — Worked code for all nine capability areas (gene, drug/chemical, gene-drug pair, CPIC guidelines, allele/PharmVar, variant, clinical annotations, drug labels, pathways), including key pharmacogenes and evidence-level definitions. - `references/query-workflows.md` — Five end-to-end workflows (decision support, gene panel, drug safety, population pharmacogenomics, literature review) plus common use cases (pre-emptive testing, medication therapy management, trial eligibility). - `references/rate-limiting-and-error-handling.md` — Reusable helpers for rate limiting, retries with exponential backoff, and result caching. ## PharmDOG Tool PharmDOG (formerly DDRx) is ClinPGx's clinical decision support tool for interpreting pharmacogenomic test results. Features: phenoconversion calculator (adjusts phenotype for drug-drug interactions affecting CYP2D6), custom genotype input, QR-code report sharing, selectable guidance sources (CPIC, DPWG, FDA), and multi-drug analysis. Access: https://www.clinpgx.org/pharmacogenomic-decision-support ## Important Notes **Data sources** — ClinPGx consolidates PharmGKB (now part of ClinPGx), CPIC, PharmCAT, DPWG, and FDA/EMA labels. As of July 2025, all PharmGKB URLs redirect to corresponding ClinPGx pages. **Clinical considerations** — Always check evidence strength before clinical application; allele frequencies vary significantly across populations; account for phenoconversion (drug-drug interactions) and multi-gene effects; non-genetic factors (age, organ function) also affect response; not all clinically relevant alleles are detected by all assays. **Data updates / API stability** — ClinPGx updates continuously; check publication dates and the ClinPGx Blog (https://blog.clinpgx.org/). API endpoints are relatively stable but may change during development — pin versions and test in development before production. ## Additional Resources - **ClinPGx website**: https://www.clinpgx.org/ - **ClinPGx Blog**: https://blog.clinpgx.org/ - **API documentation**: https://api.clinpgx.org/ - **CPIC website**: https://cpicpgx.org/ - **PharmCAT**: https://pharmcat.clinpgx.org/ - **PharmVar** (star alleles): https://www.pharmvar.org/ - **ClinGen**: https://clinicalgenome.org/ - **Contact**: api@clinpgx.org (for substantial API use)
Comments (0)
Sign in to join the conversation.
Reviews (0)
No reviews yet.
No comments yet.