Claude Skill

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

LLM Mart · 0 points · 0 views 0 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download alterlab-ieu-alterlab-academic-skills-skills_databases_alterlab-clinpgx-e4836c0.zip · 23 KB
Part of alterlab-ieu/alterlab-academic-skills — 94 skills

Install

skills CLI npx skills add https://github.com/AlterLab-IEU/AlterLab-Academic-Skills/tree/main/skills/databases/alterlab-clinpgx
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install alterlab-ieu-alterlab-academic-skills@llmmart
Git 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 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.namerelatedChemicals.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 resourcegene, 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

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.

No comments yet.

Reviews (0)

No reviews yet.

Related