{"openapi":"3.1.0","info":{"title":"WheatOmics API for AI Agent - FastAPI","description":"<h2>Overview</h2>WheatOmics is a global wheat multi-omics data integration and analysis platform covering genome, transcriptome, protein-protein interaction and literature data. This API is the platform's backend service; it follows RESTful design principles and provides structured data access for front-end applications and third-party tools.<br><br>All endpoints are prefixed with <code>/api</code> and return JSON in a unified envelope: <pre>{\"success\": true, \"data\": { ... }}</pre><h2>Modules</h2><table><tr><td><b>Known Genes</b></td><td><code>/api/genes/known</code></td><td>Known-gene search and details</td></tr><tr><td><b>PfamSearch</b></td><td><code>/api/genes/functions/pfam</code></td><td>Gene structural-domain search (gene family)</td></tr><tr><td><b>IntervalTool</b></td><td><code>/api/genes/functions/interval</code></td><td>Genes within a chromosome interval</td></tr><tr><td><b>Coexpression</b></td><td><code>/api/coexpression</code></td><td>Co-expression network edge query and network-graph data</td></tr><tr><td><b>Search Wheat Protein-Protein Interactions</b></td><td><code>/api/ppi</code></td><td>Wheat protein-protein interactions (wheatPPI, CF-MS data)</td></tr><tr><td><b>Comparative</b></td><td><code>/api/comparative</code></td><td>Wheat-rice-Arabidopsis homolog mapping, synteny interval queries and cross-database gene ID conversion</td></tr><tr><td><b>Expression</b></td><td><code>/api/expression</code></td><td>Multi-species, multi-project gene expression profiles</td></tr><tr><td><b>GeneHub</b></td><td><code>/api/genes/detail/{gene_id}</code></td><td>GeneHub: normalized gene details (v1/v2/v3 ID mapping, protein properties, functional annotation)</td></tr><tr><td><b>Sequences</b></td><td><code>/api/sequence</code></td><td>Gene and interval sequence extraction, pre-computed BLAST hits</td></tr><tr><td><b>Triticeae Papers</b></td><td><code>/api/papers</code></td><td>Triticeae literature filtering by gene, trait, confidence and AI tags</td></tr><tr><td><b>BLAST</b></td><td><code>/api/blast</code></td><td>Sequence similarity search (blastn/blastp/blastx/tblastn/tblastx)</td></tr><tr><td><b>OrthoFinder</b></td><td><code>/api/orthofinder</code></td><td>OrthoFinder orthogroup browser: cluster-filtered gene tree, synteny, MSA download</td></tr><tr><td><b>PrimerServer (SNP)</b></td><td><code>/api/tasks</code></td><td>SNP primer design and specificity checks (PrimerServer replica)</td></tr><tr><td><b>PrimerServer2</b></td><td><code>/api/PrimerServer2</code></td><td>Batch PCR primer design and specificity checks (Primer design, version 2)</td></tr><tr><td><b>GO/KEGG Enrichment</b></td><td><code>/api/go</code> / <code>/api/kegg</code></td><td>GO/KEGG enrichment analysis: hypergeometric test with Benjamini-Hochberg FDR correction and bubble-plot visualization</td></tr><tr><td><b>VariantHub</b></td><td><code>/api/VariantHub/query</code></td><td>VCF variant queries across 26 population variation datasets grouped by genome (IWGSCv1.0 / IWGSCv2.1), with interval/variant-ID search and sample-subset filtering (bcftools)</td></tr><tr><td><b>JBrowse</b></td><td><code>/api/jbrowse</code></td><td>Genome browser dataset and track metadata (jbrowse_meta database; trackList.json is rebuilt by the API)</td></tr><tr><td><b>CAPS/dCAPS</b></td><td><code>/api/caps</code></td><td>CAPS/dCAPS primer design by SNP: enumeration of restriction enzymes and mismatch primers, with sequence/coordinate/VCF input modes</td></tr><tr><td><b>eQTL Atlas</b></td><td><code>/api/eqtl/search</code></td><td>Wheat eQTL atlas: eQTL records by gene and per-project FarmCPU Manhattan plots</td></tr></table><h2>AI Agent access (MCP)</h2>This service embeds an MCP (Model Context Protocol) server, so AI agents can call the data endpoints through a standardized protocol. SSE endpoint: <code>GET /api/mcp/sse</code>; message endpoint: <code>POST /api/mcp/messages</code>. See <a href='https://wheatomics.sdau.edu.cn/agent.html'>Agent &amp; API documentation</a> for details.<br>For issues and feedback, please email: <a href='mailto:shengweima@icloud.com'>shengweima@icloud.com</a>.","version":"2.0"},"paths":{"/api/expression/projects":{"get":{"tags":["Expression"],"summary":"Get Expression Projects","description":"Get the list of available gene expression projects.\n\nPurpose:\n    Return all expression profiling projects supported by the system, organized\n    by category (Tissue, Abiotic, Biotic, Development); each project contains\n    its name and the corresponding data table name.\n\nUsage:\n    GET /api/expression/projects\n    No parameters required.\n\nExample:\n    Request:\n      curl -X GET \"http://localhost:8000/api/expression/projects\"\n\n    Response:\n      {\n        \"success\": true,\n        \"data\": {\n          \"Tissue\": [\n            { \"name\": \"PRJEB5314 - Tissue Atlas\", \"table\": \"PRJEB5314_paired_tbl\" }\n          ],\n          \"Abiotic\": [\n            { \"name\": \"PRJEB25639 - Drought Stress\", \"table\": \"PRJEB25639_tbl\" }\n          ],\n          \"Biotic\": [...],\n          \"Development\": [...]\n        }\n      }","operationId":"get_expression_projects_api_expression_projects_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Get Expression Projects Api Expression Projects Get"}}}}}}},"/api/expression/query":{"get":{"tags":["Expression"],"summary":"Query Expression","description":"Query gene expression values in a given expression project.\n\nPurpose:\n    Query the expression values and standard deviations of one or more genes\n    in a given expression profiling project. Multiple genes can be queried at\n    once (comma-separated string or repeated parameters); returns each gene's\n    expression points under different experimental conditions (with error bars).\n    The response uses the platform's standard envelope\n    {success, message, timestamp, data}.\n\n⚠️  Gene ID version note:\n    Expression data is based on the Chinese Spring IWGSC v2.1 annotation\n    (gene IDs use the 02G format). If a v1 (01G) or v3 (03G) gene ID is\n    provided, the API converts it to v2 before querying. Conversion results\n    are recorded in the response's genes_converted field. If conversion fails,\n    the query uses the original ID and most likely returns gene not found.\n\nUsage:\n    GET /api/expression/query?gene_ids=<gene1,gene2>&project=<project table name>\n    - gene_ids: required, comma-separated gene ID list (or repeated gene_ids parameters)\n    - project: optional, expression project table name, default PRJEB5314_paired_tbl\n\nExample:\n    Request:\n      curl -X GET \"http://localhost:8000/api/expression/query?gene_ids=TraesCS5A02G391700&project=PRJEB5314_paired_tbl\"\n      curl -X GET \"http://localhost:8000/api/expression/query?gene_ids=TraesCS5A02G391700&gene_ids=TraesCS1A02G001000\"\n\n    Response:\n      {\n        \"success\": true, \"message\": \"ok\", \"timestamp\": \"...\",\n        \"data\": {\n          \"project\": \"PRJEB5314_paired_tbl\",\n          \"genes_found\": 2,\n          \"genes_not_found\": [],\n          \"results\": [ ... ]\n        }\n      }","operationId":"query_expression_api_expression_query_get","parameters":[{"name":"gene_ids","in":"query","required":true,"schema":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Gene IDs: comma-separated string (gene_ids=a,b) or repeated params (gene_ids=a&gene_ids=b). Expression data is based on Chinese Spring IWGSC v2.1 (02G); see the notes.","title":"Gene Ids"},"description":"Gene IDs: comma-separated string (gene_ids=a,b) or repeated params (gene_ids=a&gene_ids=b). Expression data is based on Chinese Spring IWGSC v2.1 (02G); see the notes."},{"name":"project","in":"query","required":false,"schema":{"type":"string","examples":["PRJEB5314_paired_tbl","PRJEB25639_tbl","ABA_JA_6BA_DMSO3h_mean_tbl"],"default":"PRJEB5314_paired_tbl","title":"Project"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Query Expression Api Expression Query Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/coexpression/databases":{"get":{"tags":["Coexpression"],"summary":"List Coexpression Databases","description":"List the available coexpression databases.\n\nPurpose:\n    Return all coexpression datasets supported by the system, each with a\n    unique ID and a description, for downstream queries.\n\nUsage:\n    GET /api/coexpression/databases\n    No parameters.\n\nExample:\n    Request:\n      curl -X GET \"http://localhost:8000/api/coexpression/databases\"\n\n    Response:\n      {\n        \"success\": true,\n        \"data\": [\n          { \"id\": \"CO_result2\", \"description\": \"Wheat grain coexpression\" },\n          { \"id\": \"CO_PRJEB25639\", \"description\": \"Wheat multiple tissues coexpression\" }\n        ]\n      }","operationId":"list_coexpression_databases_api_coexpression_databases_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response List Coexpression Databases Api Coexpression Databases Get"}}}}}}},"/api/coexpression/query":{"get":{"tags":["Coexpression"],"summary":"Query Coexpression","description":"Query coexpression relationships for genes.\n\nPurpose:\n    Given a list of gene IDs, query the coexpression partners of these\n    genes in the specified coexpression database. Two filter modes are\n    supported:\n    - Decimal mode (e.g. 0.8): filter by PCC (Pearson correlation\n      coefficient), returning records with |PCC| >= filter_value\n    - Integer mode (e.g. 5): filter by MR (Mutual Rank), returning\n      records with MR <= filter_value\n\nUsage:\n    GET /api/coexpression/query?gene_ids=<gene1,gene2>&database=<database>&filter_value=<threshold>\n    - gene_ids: required, comma-separated list of gene IDs\n    - database: optional, coexpression database ID (CO_result2 or CO_PRJEB25639), default CO_PRJEB25639\n    - filter_value: optional, filter threshold, default 300 (MR mode)\n\nExample:\n    Request (PCC mode):\n      curl -X GET \"http://localhost:8000/api/coexpression/query?gene_ids=TraesCS5A02G391700&database=CO_PRJEB25639&filter_value=0.9\"\n\n    Request (MR mode):\n      curl -X GET \"http://localhost:8000/api/coexpression/query?gene_ids=TraesCS5A02G391700&database=CO_PRJEB25639&filter_value=5\"\n\n    Response:\n      {\n        \"success\": true,\n        \"data\": {\n          \"database\": \"CO_PRJEB25639\",\n          \"pairs\": [\n            { \"gene1\": \"TraesCS5A02G391700\", \"gene2\": \"TraesCS5B02G391700\", \"pcc\": 0.95, \"mr\": 3 }\n          ]\n        }\n      }","operationId":"query_coexpression_api_coexpression_query_get","parameters":[{"name":"gene_ids","in":"query","required":true,"schema":{"type":"string","title":"Gene Ids"}},{"name":"database","in":"query","required":false,"schema":{"type":"string","default":"CO_PRJEB25639","title":"Database"}},{"name":"filter_value","in":"query","required":false,"schema":{"type":"number","default":300,"title":"Filter Value"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Query Coexpression Api Coexpression Query Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/coexpression/projects":{"get":{"tags":["Coexpression"],"summary":"List Bioprojects","description":"List bioproject metadata records.\n\nPurpose:\n    Return the bioproject metadata crawled into the\n    `coexpressiondb.bioproject_meta` table. Optionally filter by data\n    source (NCBI/ENA/CNGB), and optionally substring-search over\n    title / description / species.\n\nUsage:\n    GET /api/coexpression/projects\n    GET /api/coexpression/projects?source=NCBI\n    GET /api/coexpression/projects?q=wheat","operationId":"list_bioprojects_api_coexpression_projects_get","parameters":[{"name":"source","in":"query","required":false,"schema":{"anyOf":[{"type":"string","pattern":"^(NCBI|ENA|CNGB)$"},{"type":"null"}],"title":"Source"}},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Substring search over title/description/organism","title":"Q"},"description":"Substring search over title/description/organism"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Bioprojects Api Coexpression Projects Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/coexpression/projects/{accession}":{"get":{"tags":["Coexpression"],"summary":"Get Bioproject","description":"Return one bioproject's metadata, 404 if absent.\n\nUsage:\n    GET /api/coexpression/projects/PRJNA976214","operationId":"get_bioproject_api_coexpression_projects__accession__get","parameters":[{"name":"accession","in":"path","required":true,"schema":{"type":"string","title":"Accession"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Bioproject Api Coexpression Projects  Accession  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/ppi/query":{"get":{"tags":["Search Wheat Protein-Protein Interactions"],"summary":"Query Ppi","description":"Query protein-protein interaction (PPI) relationships.\n\n⚠️  Gene ID notes:\n    This module uses wheat protein interaction data (wheatPPI), based on\n    the Chinese Spring IWGSC v2.1 annotation. Input must be transcript IDs\n    (the gene ID with a \".1\" suffix appended), e.g.\n    \"TraesCS6D02G084800.1\". If a gene ID without \".1\" is supplied, the\n    query will not match any results.\n\nPurpose:\n    Given a list of gene IDs, query the protein pairs that interact with\n    those proteins in the protein interaction database. Returns the gene\n    IDs of both interacting partners, eggNOG IDs, functional annotations\n    and interaction scores (Score).\n\n    Score threshold notes (CF-MS score):\n    - 0.5: medium confidence (default)\n    - 0.2: low confidence\n    - 0: no filtering, return all records\n\nUsage:\n    GET /api/ppi/query?gene_ids=<gene1,gene2>&table=<table>&min_score=<minimum score>\n    - gene_ids: required, comma-separated list of gene IDs (transcript IDs with the \".1\" suffix)\n    - table: optional, PPI data table name, default PPI_result\n    - min_score: optional, CF-MS interaction score threshold, default 0.5. Common values: 0.5 (medium), 0.2 (low), 0 (all)\n\nExample:\n    Request:\n      curl -X GET \"http://localhost:8000/api/ppi/query?gene_ids=TraesCS6D02G084800.1&table=PPI_result&min_score=0.5\"\n\n    Response:\n      {\n        \"success\": true,\n        \"data\": {\n          \"interactions\": [\n            {\n              \"wheat_id1\": [\"TraesCS6D02G084800\"],\n              \"wheat_id2\": [\"TraesCS6D02G084800.1\"],\n              \"eggnog_id1\": \"ENOG410XNNN\",\n              \"eggnog_id2\": \"ENOG410XMMM\",\n              \"score\": 0.95,\n              \"annotation1\": \"MADS-box transcription factor\",\n              \"annotation2\": \"Flowering time protein\"\n            }\n          ]\n        }\n      }","operationId":"query_ppi_api_ppi_query_get","parameters":[{"name":"gene_ids","in":"query","required":true,"schema":{"type":"string","title":"Gene Ids"}},{"name":"table","in":"query","required":false,"schema":{"type":"string","default":"PPI_result","title":"Table"}},{"name":"min_score","in":"query","required":false,"schema":{"type":"number","default":0.5,"title":"Min Score"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Query Ppi Api Ppi Query Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/genes/known/search":{"get":{"tags":["Known Genes"],"summary":"Search Known Genes","description":"Search cloned genes with known functions (v2056: field-targeted search + pagination + multi-year fix).\n\nPurpose:\n    Fuzzy-search the curated cloned-gene library of known-function genes using a\n    user-supplied keyword. The default field=all covers the 9 legacy fields plus\n    the 6 fields added in v2056, and returns a summary list structurally identical\n    to /known/all (including dois / publication_years, etc.).\n    v2056 also fixes: the SQL now selects publication_year (this field used to be\n    always null).\n\nUsage:\n    GET /api/genes/known/search?searchid=<keyword>[&field=all][&limit=50&offset=0]\n    - searchid: required, search keyword (LIKE wildcards % / _ are escaped to literals)\n    - field: optional, default all; whitelist:\n      all | gene_id | gene_name | reference_genome_id | phenotype | species |\n      doi | protein_family | functional_category | chrom_pos | research_strategy\n      unknown values return 400\n    - limit: optional 1-5000; omit = all rows (legacy behavior)\n    - offset: optional >=0, default 0; only effective together with limit\n    total: without pagination = number of rows returned (legacy behavior); with pagination = total number of matches\n\nExample:\n    Request:\n      curl -X GET \"http://localhost:8000/api/genes/known/search?searchid=TaCRT\"\n\n    Response:\n      {\n        \"success\": true, \"message\": \"ok\", \"data\": {\n          \"query\": \"TaCRT\",\n          \"total\": 1,\n          \"records\": [{\n            \"clone_id\": 5, \"gene_id\": \"EF452301\", \"gene_name\": \"TaCRT-A/TaCRT3-A\",\n            \"chrom_pos\": \"Refv1.0 chr3A:646.127-646.132Mb\",\n            \"phenotype\": \"Drought tolerance; Powdery mildew resistance (Bgt)\",\n            \"species\": \"Triticum aestivum (bread wheat)\",\n            \"publication_year\": \"2008\",\n            \"dois\": [\"10.1093/jxb/erm369\", \"10.1094/phyto-08-23-0276-r\"],\n            \"reference_genome_id\": \"TraesCS3A03G0936700\",\n            \"species_primary\": \"Triticum aestivum\",\n            \"chromosome\": \"3A\", \"genome_ref\": \"Refv1.0\",\n            \"phenotype_brief\": \"Drought tolerance\",\n            \"functional_category\": \"Biotic Stress\",\n            \"research_strategy\": \"Reverse genetics\",\n            \"publication_years\": [\"2008\", \"2024\"]\n          }]\n        }\n      }\n\n    Error example:\n      ?searchid=x&field=bogus -> 400 Unsupported search field\n      ?searchid=%20%20        -> 400 searchid is required","operationId":"search_known_genes_api_genes_known_search_get","parameters":[{"name":"searchid","in":"query","required":true,"schema":{"type":"string","description":"Search keyword (required, partial match supported)","title":"Searchid"},"description":"Search keyword (required, partial match supported)"},{"name":"field","in":"query","required":false,"schema":{"type":"string","description":"Search field whitelist: all | gene_id | gene_name | reference_genome_id | phenotype | species | doi | protein_family | functional_category | chrom_pos | research_strategy; unknown values return 400","default":"all","title":"Field"},"description":"Search field whitelist: all | gene_id | gene_name | reference_genome_id | phenotype | species | doi | protein_family | functional_category | chrom_pos | research_strategy; unknown values return 400"},{"name":"limit","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":5000,"minimum":1},{"type":"null"}],"description":"Optional cap on returned rows (1-5000); omit = all rows (legacy behavior)","title":"Limit"},"description":"Optional cap on returned rows (1-5000); omit = all rows (legacy behavior)"},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"description":"Optional pagination offset; only effective together with limit","default":0,"title":"Offset"},"description":"Optional pagination offset; only effective together with limit"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Search Known Genes Api Genes Known Search Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/genes/known/all":{"get":{"tags":["Known Genes"],"summary":"List Known Genes","description":"List all cloned genes with known functions (v2056 summary fields).\n\nPurpose:\n    Query summary records for all known-function genes from cloned_gene_tbl.\n    The 6 legacy keys (clone_id / gene_id / gene_name / chrom_pos / phenotype /\n    species) are unchanged; v2056 adds reference_genome_id, species_primary,\n    chromosome, genome_ref, phenotype_brief, functional_category,\n    research_strategy, dois[] and publication_years[].\n    total semantics: when limit is omitted = number of rows returned (legacy\n    behavior); with limit = total row count of the table, records = current page.\n\nUsage:\n    GET /api/genes/known/all[?limit=50&offset=0]\n    - limit: optional 1-5000; omit = all rows (legacy behavior, about 1.1 MB, about 190 KB after gzip)\n    - offset: optional >=0, default 0; only effective together with limit\n\nExample:\n    curl \"http://localhost:8000/api/genes/known/all?limit=2\"\n\n    Response:\n    {\n      \"total\": 1420,\n      \"records\": [{\n        \"clone_id\": 528, \"gene_id\": \"EF452301\",\n        \"gene_name\": \"TaCRT-A/TaCRT3-A\",\n        \"chrom_pos\": \"Refv1.0 chr3A:646.127-646.132Mb\",\n        \"phenotype\": \"Drought tolerance; Powdery mildew resistance (Bgt)\",\n        \"species\": \"Triticum aestivum (bread wheat)\",\n        \"publication_year\": \"2008\",\n        \"dois\": [\"10.1093/jxb/erm369\", \"10.1094/phyto-08-23-0276-r\"],\n        \"reference_genome_id\": \"TraesCS3A03G0936700\",\n        \"species_primary\": \"Triticum aestivum\", \"chromosome\": \"3A\",\n        \"genome_ref\": \"Refv1.0\", \"phenotype_brief\": \"Drought tolerance\",\n        \"functional_category\": \"Biotic Stress\",\n        \"research_strategy\": \"Reverse genetics\",\n        \"publication_years\": [\"2008\", \"2024\"]\n      }]\n    }","operationId":"list_known_genes_api_genes_known_all_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":5000,"minimum":1},{"type":"null"}],"description":"Optional cap on returned rows (1-5000); omit = all rows (legacy behavior)","title":"Limit"},"description":"Optional cap on returned rows (1-5000); omit = all rows (legacy behavior)"},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"description":"Optional pagination offset; only effective together with limit","default":0,"title":"Offset"},"description":"Optional pagination offset; only effective together with limit"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Known Genes Api Genes Known All Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/genes/known/by-chromosome/{chromosome}":{"get":{"tags":["Known Genes"],"summary":"List Known Genes On Chromosome","description":"List all cloned genes with known functions on a given chromosome.\n\nPurpose:\n    Chromosome names are case-insensitive and tolerate a chr prefix\n    (5A / chr5A / 3h / 54 / chr54). v2056 first matches the normalized\n    chromosome column (the new chrom_pos is free-form\n    \"<reference genome> chr...\", so the old LIKE '5A%' matched 0 new rows);\n    rows not migrated / CGI-era submissions (chromosome is NULL) fall back to\n    a chrom_pos regex match. Illegal chromosome names return 400. Returned\n    records are structurally identical to /known/all.\n\nUsage:\n    GET /api/genes/known/by-chromosome/{chromosome}\n    - chromosome: chromosome label, e.g. 5A, chr5A, 3H, 1R, 54, chr54\n\nExample:\n    curl \"http://localhost:8000/api/genes/known/by-chromosome/chr7B\"\n\n    Response:\n    {\n      \"success\": true, \"data\": {\n        \"total\": 60,\n        \"chromosome\": \"7B\",\n        \"records\": [ ... same records as /known/all ... ]\n      }\n    }\n\n    Error example:\n      /api/genes/known/by-chromosome/XX -> 400 Invalid chromosome","operationId":"list_known_genes_on_chromosome_api_genes_known_by_chromosome__chromosome__get","parameters":[{"name":"chromosome","in":"path","required":true,"schema":{"type":"string","title":"Chromosome"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Known Genes On Chromosome Api Genes Known By Chromosome  Chromosome  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/genes/known/stats":{"get":{"tags":["Known Genes"],"summary":"Get Known Gene Stats","description":"Statistical aggregates for the known-function cloned-gene library (for the Stats tab, replacing client-side aggregation).\n\nPurpose:\n    Server-side aggregation of the v2056 dataset: total count, normalized\n    species distribution (with raw_forms and the NCBI common name),\n    chromosome distribution (38 entries, group=wheat|other), functional\n    categories, research strategies, top 100 phenotype tags, publication-year\n    distribution (multi-valued entries counted once per token), reference /\n    unique-DOI counts, and data-quality notes.\n    The response is about 8-12 KB, replacing the client-side fetch of the full\n    /known/all payload (about 1.1 MB) followed by aggregation.\n    Implemented as 7 small table scans (4 GROUP BYs on controlled dimensions\n    plus 1 light column query aggregated in Python); 1420 rows take < 50 ms per\n    call, so no cache is added.\n\nNotes:\n    This route must be registered before /known/{gene_id}; otherwise \"stats\"\n    is treated as a gene_id, hits the detail route and returns 404.\n\nUsage:\n    GET /api/genes/known/stats\n\nExample:\n    curl \"http://localhost:8000/api/genes/known/stats\"\n\n    Response (excerpt):\n    {\n      \"success\": true, \"data\": {\n        \"total\": 1420,\n        \"species\": [\n          {\"name\": \"Triticum aestivum\", \"count\": 1260,\n           \"raw_forms\": 229, \"common_name\": \"bread wheat\"},\n          {\"name\": \"Hordeum vulgare\", \"count\": 79,\n           \"raw_forms\": 4, \"common_name\": \"barley\"}\n        ],\n        \"species_raw_count\": 296,\n        \"chromosomes\": [\n          {\"label\": \"2B\", \"count\": 96, \"group\": \"wheat\"},\n          {\"label\": \"3H\", \"count\": 16, \"group\": \"other\"}\n        ],\n        \"functional_category\": [\n          {\"name\": \"Biotic Stress\", \"count\": 415}, {\"name\": \"Abiotic Stress\", \"count\": 361}\n        ],\n        \"research_strategy\": [\n          {\"name\": \"Reverse genetics\", \"count\": 1061}\n        ],\n        \"phenotype_tags\": [\n          {\"tag\": \"not determined\", \"count\": 65}\n        ],\n        \"phenotype_tag_distinct\": 583,\n        \"publication_year\": [{\"year\": 1998, \"count\": 2}],\n        \"references\": {\"entries\": 1570, \"unique_dois\": 883},\n        \"notes\": {\n          \"multi_year_rows\": 130,\n          \"multi_species_rows\": 263,\n          \"rows_without_tags\": 541,\n          \"wheat_chromosomes_covered\": 21\n        }\n      }\n    }","operationId":"get_known_gene_stats_api_genes_known_stats_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Get Known Gene Stats Api Genes Known Stats Get"}}}}}}},"/api/genes/known/{gene_id}":{"get":{"tags":["Known Genes"],"summary":"Get Known Gene","description":"Get detailed information for a given cloned gene (v2056 structured fields + positionally aligned references).\n\nPurpose:\n    Look up the full record of a cloned gene by gene ID. Numeric IDs still\n    query by clone_id (legacy semantics, detail page URL ?id=<clone_id>);\n    non-numeric values match gene_id / gene_name exactly (legacy semantics).\n    All legacy response keys are kept; v2056 adds reference_genome_id,\n    protein_family, validation_method, validation_methods[],\n    research_strategy, functional_category, species_primary, chromosome,\n    genome_ref, phenotype_brief, publication_years[].\n    references[] is built positionally from the paper_title / paper_doi /\n    publication_years columns aligned on `###`, each entry {doi, title, year};\n    missing positions are null (v2056 has one row with 4 titles / 3 DOIs, so\n    the 4th entry has a title only and doi may be null).\n    key_result keeps the legacy array semantics (`###` split; a single segment\n    in new data -> a 1-element array).\n    Normalization: new-data rows with a non-null reference_genome_id keep a\n    literal `#`; legacy rows keep the old # -> ' escape behavior.\n\nUsage:\n    GET /api/genes/known/{gene_id}\n    - gene_id: path parameter; a number = clone_id, e.g. 12; or a gene ID/name,\n      e.g. TraesCS3A03G0936700\n\nExample:\n    Request:\n      curl -X GET \"http://localhost:8000/api/genes/known/5\"\n\n    Response (excerpt):\n      {\n        \"success\": true, \"data\": {\n          \"clone_id\": 5, \"gene_id\": \"EF452301\",\n          \"gene_name\": \"TaCRT-A/TaCRT3-A\",\n          \"chrom_pos\": \"Refv1.0 chr3A:646.127-646.132Mb\",\n          \"phenotype\": \"Drought tolerance; Powdery mildew resistance (Bgt)\",\n          \"species\": \"Triticum aestivum (bread wheat)\",\n          \"paper_title\": [\"...\", \"...\"],\n          \"references\": [\n            {\"doi\": \"10.1093/jxb/erm369\", \"title\": \"...\", \"year\": 2008},\n            {\"doi\": \"10.1094/phyto-08-23-0276-r\", \"title\": \"...\", \"year\": 2024}\n          ],\n          \"key_result\": [\"...\"],\n          \"publication_year\": 2008,\n          \"function_description\": \"...\",\n          \"cloning_method\": \"Homology-based cloning; Functional cloning\",\n          \"cloning_method_description\": \"...\",\n          \"author\": \"WheatOmics curation\",\n          \"author_mail\": \"shengweima@icloud.com\",\n          \"submission_date\": \"2026-10-28\",\n          \"reference_genome_id\": \"TraesCS3A03G0936700\",\n          \"protein_family\": \"Calreticulin (CRT3) family; calcium-binding ER chaperone\",\n          \"validation_method\": \"Expression analysis; Overexpression; VIGS\",\n          \"validation_methods\": [\"Expression analysis\", \"Overexpression\", \"VIGS\"],\n          \"research_strategy\": \"Reverse genetics\",\n          \"functional_category\": \"Biotic Stress\",\n          \"species_primary\": \"Triticum aestivum\",\n          \"chromosome\": \"3A\", \"genome_ref\": \"Refv1.0\",\n          \"phenotype_brief\": \"Drought tolerance\",\n          \"publication_years\": [2008, 2024]\n        }\n      }","operationId":"get_known_gene_api_genes_known__gene_id__get","parameters":[{"name":"gene_id","in":"path","required":true,"schema":{"type":"string","title":"Gene Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Known Gene Api Genes Known  Gene Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/genes/detail/{gene_id}":{"get":{"tags":["GeneHub"],"summary":"Get Gene Detail","description":"Get normalized detailed information for a gene.\n\nPurpose:\n    Look up GenePageIWGSCv1_table by gene ID (IWGSC v1/v2/v3 versions all\n    supported) and return the gene description, chromosome location, protein\n    length, molecular weight, isoelectric point, functional annotations, etc.,\n    plus a JBrowse genome-browser link and an Ensembl external link.\n\nUsage:\n    GET /api/genes/detail/{gene_id}\n    - gene_id: path parameter, any of v1 (TraesCS5A02G391700), v2 (TraesCS5A02G391700.1), v3 (TraesCS5A03G1158600)\n\nExample:\n    Request:\n      curl -X GET \"http://localhost:8000/api/genes/detail/TraesCS5A02G391700\"\n\n    Response:\n      {\n        \"success\": true,\n        \"data\": {\n          \"query_gene\": \"TraesCS5A02G391700\",\n          \"gene_ids\": [\"TraesCS5A02G391700\", \"TraesCS5A01G391700\", \"TraesCS5A03G1158600\"],\n          \"description\": \"MADS-box transcription factor\",\n          \"genome\": \"A\",\n          \"chromosome\": \"chr5A\",\n          \"start\": 587123456,\n          \"end\": 587125000,\n          \"strand\": \"+\",\n          \"protein_length\": \"240\",\n          \"molecular_weight\": \"27.5\",\n          \"isoelectric_point\": \"6.2\",\n          \"functions\": [\"vernalization response\", \"flowering time regulation\"],\n          \"jbrowse_links\": { \"structure_center\": \"http://...\" },\n          \"external_links\": { \"ensembl\": \"https://ensembl.gramene.org/...\" }\n        }\n      }","operationId":"get_gene_detail_api_genes_detail__gene_id__get","parameters":[{"name":"gene_id","in":"path","required":true,"schema":{"type":"string","title":"Gene Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Gene Detail Api Genes Detail  Gene Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/genes/resolve":{"get":{"tags":["GeneHub"],"summary":"Resolve Gene Id","description":"Resolve a gene ID across the Genefunc tables and return its Chinese Spring 02G mappings.\n\nFallback for non-Chinese-Spring IDs in GeneHub: scans the Gene/Gene02G/Gene03G\ncolumns of all visible Genefunc tables and returns the matching records with\ntheir ChineseSpring02G mappings.","operationId":"resolve_gene_id_api_genes_resolve_get","parameters":[{"name":"ID","in":"query","required":true,"schema":{"type":"string","title":"Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Resolve Gene Id Api Genes Resolve Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/genes/functions/pfam":{"get":{"tags":["PfamSearch"],"summary":"Search Pfam","description":"PfamSearch: search genes by PFAM domain [gene family]\n\nPurpose:\n    Given a PFAM domain ID (starting with PF), return the list of all genes\n    containing that domain. The queried table can be specified (default\n    Genefunc_CS_IWGSC03G_table; see /api/genes/functions/tables for the full\n    list). Note the direction: this endpoint finds genes by PFAM; to look up\n    the domains of a single gene, use /api/genes/functions/interval (the\n    returned Domain column is the PFAM annotation).\n\nRelated site:\n    Corresponds to the PfamSearch tool: https://wheatomics.sdau.edu.cn/tools/proteinfamily.html\n\nUsage:\n    GET /api/genes/functions/pfam?ID=<PFAM domain ID>&table=<table name>\n    - ID: required, PFAM domain ID, e.g. PF00319\n    - table: optional, default Genefunc_CS_IWGSC03G_table (Chinese Spring IWGSC v2.1)\n\nExample:\n    Request:\n      curl -X GET \"http://localhost:8000/api/genes/functions/pfam?ID=PF00319\"\n\n    Response:\n      {\n        \"success\": true,\n        \"data\": {\n          \"table\": \"Genefunc_CS_IWGSC03G_table\",\n          \"domain\": \"PF00319\",\n          \"count\": 5,\n          \"records\": [\n            {\n              \"chromosome\": \"chr5A\",\n              \"start_mb\": 587.123456,\n              \"end_mb\": 587.125000,\n              \"gene_primary\": \"TraesCS5A02G391700\",\n              \"strand\": \"+\",\n              \"description\": \"MADS-box transcription factor\",\n              \"domain\": \"PF00319\"\n            }\n          ]\n        }\n      }","operationId":"search_pfam_api_genes_functions_pfam_get","parameters":[{"name":"ID","in":"query","required":true,"schema":{"type":"string","title":"Id"}},{"name":"table","in":"query","required":false,"schema":{"type":"string","default":"Genefunc_CS_IWGSC03G_table","title":"Table"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Search Pfam Api Genes Functions Pfam Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/genes/functions/tables":{"get":{"tags":["IntervalTool"],"summary":"List Gene Function Tables","description":"Query information about all tables in Genefuncdb.\n\nPurpose:\n    Connect directly to the Genefuncdb database, run SHOW TABLES to get all\n    table names, and query each table's row count and column list, returning\n    the structured information.\n\nUsage:\n    GET /api/genes/functions/tables\n    No parameters.\n\nExample:\n    Request:\n      curl -X GET \"http://localhost:8000/api/genes/functions/tables\"\n\n    Response:\n      {\n        \"success\": true,\n        \"data\": {\n          \"database\": \"Genefuncdb\",\n          \"total_tables\": 5,\n          \"tables\": [\n            { \"name\": \"Genefunc_CS_IWGSCv1.0_table\", \"rows\": 168900, \"columns\": [\"Chrom\", \"Start1\", ...] },\n            ...\n          ]\n        }\n      }","operationId":"list_gene_function_tables_api_genes_functions_tables_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response List Gene Function Tables Api Genes Functions Tables Get"}}}}}}},"/api/genes/functions/examples":{"get":{"tags":["IntervalTool"],"summary":"List Genome Examples","description":"Get example query data for all genomes.\n\nPurpose:\n    Return the example Region, Gene ID and Pfam ID for each genome, used by\n    the Interval Tool frontend to display example links.\n\nUsage:\n    GET /api/genes/functions/examples\n    No parameters.\n\nExample:\n    Request:\n      curl -X GET \"http://localhost:8000/api/genes/functions/examples\"\n\n    Response:\n      {\n        \"success\": true,\n        \"data\": {\n          \"examples\": [\n            { \"table_name\": \"Genefunc_CS_IWGSCv1.0_table\", \"display_name\": \"Chinese Spring genome v1.0\",\n              \"region\": \"chr1A:1-141522\", \"gene\": \"TraesCS1A01G000100LC\", \"pfam\": \"\" },\n            ...\n          ]\n        }\n      }","operationId":"list_genome_examples_api_genes_functions_examples_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response List Genome Examples Api Genes Functions Examples Get"}}}}}}},"/api/genes/functions/registry":{"get":{"tags":["IntervalTool"],"summary":"List Gene Function Registry","description":"Query the Genefuncdb.Genefunc_registry table.\n\nPurpose:\n    Return the metadata of all registered gene-function tables in the\n    Genefunc_registry table. Includes id, table_name, display_name, Subgenome,\n    Polyploidy, chromosome_level, Doi, title, Abstract, example_chr, example_id\n    and other fields.\n\nNotes:\n    Table names are case-sensitive (MySQL `lower_case_table_names=0` on Linux),\n    so `Genefunc_registry` must be written with a capital G; otherwise MySQL\n    raises 1146 table does not exist.\n\nUsage:\n    GET /api/genes/functions/registry\n    No parameters.\n\nExample:\n    Request:\n      curl -X GET \"http://localhost:8000/api/genes/functions/registry\"\n\n    Response:\n      {\n        \"success\": true,\n        \"data\": {\n          \"database\": \"genefunc_registry\",\n          \"count\": 2,\n          \"records\": [\n            {\n              \"id\": 1,\n              \"table_name\": \"Genefunc_Abo_table\",\n              \"display_name\": \"Abbondanza (Abo)\",\n              \"subgenome\": \"ABD\",\n              \"polyploidy\": \"Allohexaploid\",\n              \"chromosome_level\": \"AABBDD\",\n              \"doi\": \"10.1038/s41586-024-08277-0\",\n              \"title\": \"Unraveling Allelic Impacts...\",\n              \"abstract\": \"The TaVP1-B gene...\",\n              \"example_species_chr\": \"chr1A_Abo\",\n              \"example_cds\": \"Abo1A000100.1\",\n              \"example_protein\": \"Abo1A000100.1.p\"\n            }\n          ]\n        }\n      }","operationId":"list_gene_function_registry_api_genes_functions_registry_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response List Gene Function Registry Api Genes Functions Registry Get"}}}}}}},"/api/genes/functions/interval":{"get":{"tags":["IntervalTool"],"summary":"Search Gene Interval","description":"Search genes by chromosomal interval.\n\nPurpose:\n    Given a chromosomal interval (e.g. chr5A:587000000..587200000), return the\n    list of all genes within that interval. The queried table can be specified\n    (default Genefunc_CS_IWGSC03G_table; see /api/genes/functions/tables for\n    the full list).\n\nRelated site:\n    Corresponds to IntervalTool: https://wheatomics.sdau.edu.cn/tools/intervalTools.html\n\nUsage:\n    GET /api/genes/functions/interval?ID=<interval>&table=<table name>\n    - ID: required, chromosomal interval in the form chr5A:587000000..587200000\n    - table: optional, default Genefunc_CS_IWGSC03G_table (Chinese Spring IWGSC v2.1)\n\nExample:\n    Request:\n      curl -X GET \"http://localhost:8000/api/genes/functions/interval?ID=chr5A:587000000..587200000\"\n\n    Response:\n      {\n        \"success\": true,\n        \"data\": {\n          \"table\": \"Genefunc_CS_IWGSC03G_table\",\n          \"region\": \"chr5A:587000000..587200000\",\n          \"count\": 5,\n          \"records\": [\n            {\n              \"chromosome\": \"chr5A\",\n              \"start_mb\": 587.123456,\n              \"end_mb\": 587.125000,\n              \"gene_primary\": \"TraesCS5A02G391700\",\n              \"strand\": \"+\",\n              \"description\": \"MADS-box transcription factor\",\n              \"domain\": null\n            }\n          ]\n        }\n      }","operationId":"search_gene_interval_api_genes_functions_interval_get","parameters":[{"name":"ID","in":"query","required":true,"schema":{"type":"string","title":"Id"}},{"name":"table","in":"query","required":false,"schema":{"type":"string","default":"Genefunc_CS_IWGSC03G_table","title":"Table"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Search Gene Interval Api Genes Functions Interval Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/homologs/wheat-rice-arabidopsis":{"get":{"tags":["Comparative genomics"],"summary":"Wheat Rice Arabidopsis Homologs","description":"Query the homologs of a wheat gene in rice and Arabidopsis.\n\nPurpose:\n    Query the WheatRiceArabidopsis_tbl table by wheat gene ID and return the\n    gene's homologs in rice (Rice) and Arabidopsis, including alignment details\n    such as Qcovs, Identity, E-value and Score.\n    max_targets caps the number of homologs returned per species.\n\nUsage:\n    GET /api/homologs/wheat-rice-arabidopsis?gene_id=<gene ID>&max_targets=<count>\n    - gene_id: required, wheat gene ID (starting with Traes) or a gene ID from another species\n    - max_targets: optional, maximum homologs returned per species (default 3, 1-100)\n\nExample:\n    Request:\n      curl -X GET \"http://localhost:8000/api/homologs/wheat-rice-arabidopsis?gene_id=TraesCS5A02G391700&max_targets=3\"\n\n    Response:\n      {\n        \"success\": true,\n        \"data\": {\n          \"query_gene\": \"TraesCS5A02G391700\",\n          \"count\": 6,\n          \"hits\": [\n            {\n              \"query_gene\": \"TraesCS5A02G391700\",\n              \"target_gene\": \"Os01g0100100\",\n              \"description\": \"MADS-box transcription factor\",\n              \"species\": \"Rice\",\n              \"qcovs\": 95.0,\n              \"identity\": 85.2,\n              \"evalue\": 1e-120,\n              \"score\": 450.0\n            }\n          ]\n        }\n      }","operationId":"wheat_rice_arabidopsis_homologs_api_homologs_wheat_rice_arabidopsis_get","parameters":[{"name":"gene_id","in":"query","required":true,"schema":{"type":"string","title":"Gene Id"}},{"name":"max_targets","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":3,"title":"Max Targets"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Wheat Rice Arabidopsis Homologs Api Homologs Wheat Rice Arabidopsis Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/synteny/search":{"get":{"tags":["Comparative genomics"],"summary":"Search Synteny","description":"Search synteny information between wheat and other Triticeae species.\n\nPurpose:\n    Supports two query modes:\n    1. Genomic interval query - format chr5A:100000-200000; returns the synteny records of genes in that region\n    2. Gene ID query - looks up the synteny relationships of a single gene\n    Results are the syntenic counterparts of each gene in Chinese Spring, Durum wheat, Wild emmer,\n    Triticum urartu and Aegilops tauschii.\n\nUsage:\n    GET /api/synteny/search?ID=<query>&table=<table name>\n    - ID: required, gene ID or chromosome interval\n    - table: optional, synteny table name, default CSsymaptbl\n\nExample:\n    Request:\n      curl -X GET \"http://localhost:8000/api/synteny/search?ID=TraesCS5A02G391700\"\n\n    Response:\n      {\n        \"success\": true,\n        \"data\": {\n          \"count\": 1,\n          \"records\": [\n            {\n              \"chromosome\": \"chr5A\",\n              \"start_mb\": 587.123456,\n              \"end_mb\": 587.125000,\n              \"strand\": \"+\",\n              \"gene\": \"TraesCS5A02G391700\",\n              \"chinese_spring\": \"...\",\n              \"durum_wheat\": \"...\",\n              \"wild_emmer\": \"...\",\n              \"triticum_urartu\": \"...\",\n              \"aegilops_tauschii\": \"...\"\n            }\n          ]\n        }\n      }","operationId":"search_synteny_api_synteny_search_get","parameters":[{"name":"ID","in":"query","required":true,"schema":{"type":"string","title":"Id"}},{"name":"table","in":"query","required":false,"schema":{"type":"string","default":"CSsymaptbl","title":"Table"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Search Synteny Api Synteny Search Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/id-conversion":{"get":{"tags":["Comparative genomics"],"summary":"Convert Gene Ids","description":"Convert gene IDs between different gene annotation versions (all mapped to IWGSC v1.1 / 02G).\n\n⚠️  Version note:\n    Gene IDs from the following three source versions can be converted to IWGSC v1.1 (02G):\n    - MIPS_result:  MIPS v2.2 format, e.g. \"Traes_1AS_E6058767A.1\"\n    - TGACv1_result: TGACv1 format, e.g. \"TRIAE_CS42_6BL_TGACv1_501926_AA1621570.1\"\n    - IWGSCv1_result: IWGSC v1.0 format, e.g. \"TraesCS6B01G342500.1\"\n    Please provide transcript IDs (with the \".1\" suffix); the output reference_gene is in 02G format (e.g. \"TraesCS6B02G084800\").\n\nPurpose:\n    Take multiple source gene IDs (%0D%0A-separated), look them up in the\n    specified version table and convert them to IWGSC v1.1 (02G). Returns\n    each gene's mapping result (reference_gene, code, length). Genes that\n    are not found are listed in not_found.\n\nUsage:\n    GET /api/id-conversion?ID=<gene1 gene2>&gene_version=<source version table>\n    - ID: required, gene ID list; separate multiple genes with %0D%0A (URL-encoded newline) (transcript IDs with the \".1\" suffix are required)\n    - gene_version: required, database table name of the source version:\n      \"MIPS_result\" / \"TGACv1_result\" / \"IWGSCv1_result\"\n\nExample:\n    Request (MIPS v2.2 → IWGSC v1.1):\n      curl -X GET \"http://localhost:8000/api/id-conversion?ID=Traes_1AS_E6058767A.1&gene_version=MIPS_result\"\n\n    Request (IWGSC v1.0 → IWGSC v1.1):\n      curl -X GET \"http://localhost:8000/api/id-conversion?ID=TraesCS6B01G342500.1%0D%0ATraesCS6B01G123400.1&gene_version=IWGSCv1_result\"\n\n    Response:\n      {\n        \"success\": true,\n        \"data\": {\n          \"version\": \"IWGSCv1_result\",\n          \"mappings\": [\n            {\n              \"query_gene\": \"TraesCS6B01G342500.1\",\n              \"reference_gene\": \"TraesCS6B02G342500\",\n              \"code\": \"-\",\n              \"length\": \"1500\"\n            }\n          ],\n          \"not_found\": []\n        }\n      }","operationId":"convert_gene_ids_api_id_conversion_get","parameters":[{"name":"ID","in":"query","required":true,"schema":{"type":"string","title":"Id"}},{"name":"gene_version","in":"query","required":true,"schema":{"type":"string","title":"Gene Version"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Convert Gene Ids Api Id Conversion Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/papers":{"get":{"tags":["Triticeae Papers"],"summary":"Search Papers","description":"Search Triticeae paper metadata.\n\nQueries only the `papers` table (includes paper-level annotations such as\nfunctional_gene_flag / ai_tags / keywords_source); it no longer LEFT JOINs\nfunctional_gene_annotations. For fine-grained LLM annotations (gene_name /\ntrait_label / confidence, etc.) call /papers/{pmid}/annotation.\n\nEvery parameter also accepts a <param>_exclude variant for NOT semantics.\n\n`since_days` is anchored to `papers.created_at` (when the row was\ninserted), not `fga.created_at`. Use it for \"what new papers did\nwe add this week\".\n\nDefault order: paper_created_at DESC (most recently added first).","operationId":"search_papers_api_papers_get","parameters":[{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Full-text keyword search (title / abstract / journal / authors / pubmed_keywords / ai_tags / function_gene_tags)","title":"Q"},"description":"Full-text keyword search (title / abstract / journal / authors / pubmed_keywords / ai_tags / function_gene_tags)"},{"name":"q_exclude","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Excluded keywords (NOT semantics); same search scope as q","title":"Q Exclude"},"description":"Excluded keywords (NOT semantics); same search scope as q"},{"name":"title","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Fuzzy title match","title":"Title"},"description":"Fuzzy title match"},{"name":"title_exclude","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Title exclusion","title":"Title Exclude"},"description":"Title exclusion"},{"name":"abstract","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Fuzzy abstract match","title":"Abstract"},"description":"Fuzzy abstract match"},{"name":"abstract_exclude","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Abstract exclusion","title":"Abstract Exclude"},"description":"Abstract exclusion"},{"name":"journal","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Fuzzy journal match","title":"Journal"},"description":"Fuzzy journal match"},{"name":"journal_exclude","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Journal exclusion","title":"Journal Exclude"},"description":"Journal exclusion"},{"name":"authors","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Fuzzy author match (LIKE %...%, across whole words)","title":"Authors"},"description":"Fuzzy author match (LIKE %...%, across whole words)"},{"name":"authors_exclude","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Author exclusion","title":"Authors Exclude"},"description":"Author exclusion"},{"name":"pubmed_keywords","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Fuzzy PubMed keyword match","title":"Pubmed Keywords"},"description":"Fuzzy PubMed keyword match"},{"name":"pubmed_keywords_exclude","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"PubMed keyword exclusion","title":"Pubmed Keywords Exclude"},"description":"PubMed keyword exclusion"},{"name":"ai_tags","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Fuzzy AI tag match (papers.ai_tags)","title":"Ai Tags"},"description":"Fuzzy AI tag match (papers.ai_tags)"},{"name":"ai_tags_exclude","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"AI tag exclusion","title":"Ai Tags Exclude"},"description":"AI tag exclusion"},{"name":"function_gene_tags","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Fuzzy functional gene tag match (papers.function_gene_tags)","title":"Function Gene Tags"},"description":"Fuzzy functional gene tag match (papers.function_gene_tags)"},{"name":"function_gene_tags_exclude","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Functional gene tag exclusion","title":"Function Gene Tags Exclude"},"description":"Functional gene tag exclusion"},{"name":"gene_name","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Fuzzy gene name match (papers.function_gene_tags + functional_gene_tags)","title":"Gene Name"},"description":"Fuzzy gene name match (papers.function_gene_tags + functional_gene_tags)"},{"name":"gene_name_exclude","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Gene name exclusion","title":"Gene Name Exclude"},"description":"Gene name exclusion"},{"name":"source_method","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by LLM annotation source (functional_gene_annotations.source_method, EXISTS subquery), e.g. llm_error / rule+llm / seed_title_match","title":"Source Method"},"description":"Filter by LLM annotation source (functional_gene_annotations.source_method, EXISTS subquery), e.g. llm_error / rule+llm / seed_title_match"},{"name":"source_method_exclude","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Exclude an annotation source (NOT EXISTS)","title":"Source Method Exclude"},"description":"Exclude an annotation source (NOT EXISTS)"},{"name":"review_status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by annotation review status (EXISTS subquery), e.g. negative / auto_pass / need_review","title":"Review Status"},"description":"Filter by annotation review status (EXISTS subquery), e.g. negative / auto_pass / need_review"},{"name":"review_status_exclude","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Exclude a review status (NOT EXISTS)","title":"Review Status Exclude"},"description":"Exclude a review status (NOT EXISTS)"},{"name":"pmid","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Exact PubMed ID match (whitespace is stripped automatically)","title":"Pmid"},"description":"Exact PubMed ID match (whitespace is stripped automatically)"},{"name":"pmid_exclude","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Exact PubMed ID exclusion","title":"Pmid Exclude"},"description":"Exact PubMed ID exclusion"},{"name":"functional_gene_flag","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Paper-level functional gene flag","title":"Functional Gene Flag"},"description":"Paper-level functional gene flag"},{"name":"functional_gene_source","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Paper-level functional gene source","title":"Functional Gene Source"},"description":"Paper-level functional gene source"},{"name":"function_gene_flag","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Second-set functional gene flag","title":"Function Gene Flag"},"description":"Second-set functional gene flag"},{"name":"pub_date_start","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Publication year start","title":"Pub Date Start"},"description":"Publication year start"},{"name":"pub_date_end","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Publication year end","title":"Pub Date End"},"description":"Publication year end"},{"name":"since_days","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":3650,"minimum":1},{"type":"null"}],"description":"Filter by papers-table insertion time (p.created_at) within the last N days","title":"Since Days"},"description":"Filter by papers-table insertion time (p.created_at) within the last N days"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"description":"Maximum number of results","default":20,"title":"Limit"},"description":"Maximum number of results"},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"description":"Pagination offset","default":0,"title":"Offset"},"description":"Pagination offset"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Search Papers Api Papers Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/papers/dois":{"get":{"tags":["Triticeae Papers"],"summary":"Paper Dois","operationId":"paper_dois_api_papers_dois_get","parameters":[{"name":"pmids","in":"query","required":true,"schema":{"type":"string","description":"Comma-separated PubMed IDs","title":"Pmids"},"description":"Comma-separated PubMed IDs"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/papers/{pmid}/annotation":{"get":{"tags":["Triticeae Papers"],"summary":"Get Paper Annotation","description":"Get the LLM annotation of a single paper by PMID (functional_gene_annotations table).\n\nReturns all annotation-layer fields: fga_id, is_functional_gene, confidence,\ngene_name, gene_type, trait_label, function_summary, evidence_type,\nnew_tags, llm_reason, source_method, review_status, created_at,\nupdated_at.\n\nIf the paper has no annotation record (the AI judged it is not a\nfunctional gene study), returns has_annotation: false + annotation: null.","operationId":"get_paper_annotation_api_papers__pmid__annotation_get","parameters":[{"name":"pmid","in":"path","required":true,"schema":{"type":"string","title":"Pmid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Paper Annotation Api Papers  Pmid  Annotation Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/papers/stats":{"get":{"tags":["Triticeae Papers"],"summary":"Stats","description":"Dataset aggregate statistics: year distribution, top-20 journals, top-30 AI tags, functional gene ratio, review status distribution.\n\nAll aggregations use SQL GROUP BY; 22K rows return in under 100ms. The papers\ntable is counted with PMID de-duplication; functional_gene_annotations is\ncounted per annotation record (one PMID may map to several annotations).","operationId":"stats_api_papers_stats_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Stats Api Papers Stats Get"}}}}}}},"/api/papers/{pubmedid}":{"get":{"tags":["Triticeae Papers"],"summary":"Get Paper","description":"Get the metadata of a single paper by PubMed ID (papers table only).\n\nReturns the papers.* fields; all fga_* fields are empty.\nFor LLM annotations call /papers/{pmid}/annotation.\n\nNote the route order: this route must be declared **after**\n/papers/{pmid}/annotation, otherwise Starlette matches this single-segment\nroute first and splits the request 42105133/annotation into\npubmedid=\"42105133\" plus an unknown \"annotation\" query parameter.","operationId":"get_paper_api_papers__pubmedid__get","parameters":[{"name":"pubmedid","in":"path","required":true,"schema":{"type":"string","title":"Pubmedid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Paper Api Papers  Pubmedid  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/sequence/chromosomes":{"get":{"tags":["Sequences"],"summary":"List Chromosomes","description":"List every sequence (chromosome) name stored in a BLAST database.\n\nUsage:\n    GET /api/sequence/chromosomes?database=all_genomes\n\nCase:\n    Names come back exactly as stored in the DB headers (e.g.\n    \"Chr1A_Abo\", \"chr1D_Aegilops_tauschii_TA1675\"), so callers can build\n    guaranteed-valid chr:start-end regions without guessing naming\n    conventions.","operationId":"list_chromosomes_api_sequence_chromosomes_get","parameters":[{"name":"database","in":"query","required":false,"schema":{"type":"string","description":"BLAST database under BLAST_DB_PATH","default":"all_genomes","title":"Database"},"description":"BLAST database under BLAST_DB_PATH"},{"name":"pattern","in":"query","required":false,"schema":{"type":"string","maxLength":100,"description":"Optional case-insensitive regex on seqid, e.g. ^chr","default":"","title":"Pattern"},"description":"Optional case-insensitive regex on seqid, e.g. ^chr"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Chromosomes Api Sequence Chromosomes Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/sequence/by-gene":{"get":{"tags":["Sequences"],"summary":"Sequence By Gene","description":"Fetch gene and protein sequences (FASTA format) by gene ID.\n\n    Purpose:\n        Use the blastdbcmd tool to extract the corresponding gene sequence\n        (CDS) and protein sequence from the local BLAST databases, based on\n        the gene ID. If the gene ID does not end with .1, the .1 suffix is\n        appended automatically before lookup.\n\n    Usage:\n        GET /api/sequence/by-gene?gene_id=<gene ID>&gene_db=<gene DB>&protein_db=<protein DB>\n        - gene_id: required, e.g. TraesCS5A02G391700\n        - when both db parameters are omitted the defaults are used\n          (gene_db=all_gene, protein_db=all_protein)\n        - passing only one of them queries that side only (e.g. passing only\n          protein_db=all_protein → protein sequence only)\n\n    Example:\n        Request:\n          curl -X GET \"http://localhost:8000/api/sequence/by-gene?gene_id=TraesCS5A02G391700\"\n          curl -X GET \"http://localhost:8000/api/sequence/by-gene?gene_id=TraesCS5A02G391700&protein_db=all_protein\"\n\n        Response:\n          {\n            \"gene_id\": \"TraesCS5A02G391700\",\n            \"gene_sequence\": \">TraesCS5A02G391700.1\nATGGCG...\",\n            \"protein_sequence\": \">TraesCS5A02G391700.1\nMAGD...\"\n          }","operationId":"sequence_by_gene_api_sequence_by_gene_get","parameters":[{"name":"gene_id","in":"query","required":true,"schema":{"type":"string","title":"Gene Id"}},{"name":"gene_db","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"CDS / genomic BLAST DB. Provide only one of gene_db / protein_db to fetch that side alone. Omit both to use the defaults (all_gene + all_protein).","title":"Gene Db"},"description":"CDS / genomic BLAST DB. Provide only one of gene_db / protein_db to fetch that side alone. Omit both to use the defaults (all_gene + all_protein)."},{"name":"protein_db","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Protein BLAST DB. Provide only one of gene_db / protein_db to fetch that side alone. Omit both to use the defaults (all_gene + all_protein).","title":"Protein Db"},"description":"Protein BLAST DB. Provide only one of gene_db / protein_db to fetch that side alone. Omit both to use the defaults (all_gene + all_protein)."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SequenceBundle"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/sequence/by-interval":{"get":{"tags":["Sequences"],"summary":"Sequence By Interval","description":"Get genomic FASTA sequence by chromosome interval.\n\nChromosome naming follows genome-specific conventions.\nSee the full reference at:\nhttps://wheatomics.sdau.edu.cn/doc/getsequence_search.txt\n\nExamples:\n  - Hexaploid wheat (Abbondanza):     Chr1A_Abo:200-500\n  - Hexaploid wheat (Chinese Spring): chr1A:200-500\n  - Barley v3:                         chr1H_Barley3:200-500\n  - Aegilops tauschii TA1675:          chr1D_Aegilops_tauschii_TA1675:200-500\n  - Wild emmer:                        chr1A_Wild_emmer:200-500","operationId":"sequence_by_interval_api_sequence_by_interval_get","parameters":[{"name":"region","in":"query","required":true,"schema":{"type":"string","description":"Genomic interval, e.g. Chr1A_Abo:200-500. See https://wheatomics.sdau.edu.cn/doc/getsequence_search.txt for the full list of genome-specific chromosome naming conventions.","title":"Region"},"description":"Genomic interval, e.g. Chr1A_Abo:200-500. See https://wheatomics.sdau.edu.cn/doc/getsequence_search.txt for the full list of genome-specific chromosome naming conventions."},{"name":"database","in":"query","required":true,"schema":{"type":"string","description":"BLAST database name. For genome-wide queries use the aggregated databases:\n  - all_genomes   (genomic sequences, recommended for interval queries)\n  - all_gene      (gene CDS)\n  - all_protein   (protein)\nSee GET /api/blast/databases?program=blastn for the full list.","title":"Database"},"description":"BLAST database name. For genome-wide queries use the aggregated databases:\n  - all_genomes   (genomic sequences, recommended for interval queries)\n  - all_gene      (gene CDS)\n  - all_protein   (protein)\nSee GET /api/blast/databases?program=blastn for the full list."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Sequence By Interval Api Sequence By Interval Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/sequence/batch":{"get":{"tags":["Sequences"],"summary":"Batch Sequence","description":"Batch-fetch FASTA sequences for multiple genes/intervals.\n\n    Purpose:\n        Query multiple gene IDs or genomic intervals in one request. IDs are\n        space-separated (use %20 or + to encode spaces in the URL). Gene IDs\n        get the transcript version suffix .1 appended automatically.\n        Interval format: chr:start-end (e.g. Chr1A_Chinese_Spring1.0:200-500).\n\n    Usage:\n        GET /api/sequence/batch?ID=<id1 id2>&database=<database name>\n\n    Example:\n        curl -X GET \"http://localhost:8000/api/sequence/batch?ID=TraesCS5A02G391700%20TraesCS5A02G391701&database=all_gene\"\n        curl -X GET \"http://localhost:8000/api/sequence/batch?ID=Chr1A:200-500%20Chr5B:1000-2000&database=all_genomes\"\n\n    Response:\n        {\n          \"success\": true,\n          \"data\": {\n            \"database\": \"...\",\n            \"records\": [\n              {\"sequence_id\": \"Chr1A:200-500\", \"fasta\": \">Chr1A:200-500\n...\"},\n              ...\n            ]\n          }\n        }","operationId":"batch_sequence_api_sequence_batch_get","parameters":[{"name":"database","in":"query","required":true,"schema":{"type":"string","title":"Database"}},{"name":"ID","in":"query","required":true,"schema":{"type":"string","title":"Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Batch Sequence Api Sequence Batch Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/blastp":{"get":{"tags":["Comparative genomics"],"summary":"Search Blastp","description":"Triticeae protein pre-blastp results.\n\nPurpose:\n    Can be used to search for the target genes of a query gene across the\n    Triticeae, and for homolog searches or gene ID conversion between\n    different genome versions / different materials.\n    Searches the all_protein_blastp table by gene ID, matching both\n    query_id and subject_id. Handles several gene ID formats (with .1,\n    transcript: prefix, .cds suffix, etc.).\n    Results are ordered by bit_score descending, then evalue ascending.\n\nUsage:\n    GET /api/blastp?gene=<gene ID>&limit=5000&offset=0\n    - gene: required, gene ID\n    - limit: optional, maximum number of records to return, default 5000\n    - offset: optional, offset, default 0\n\nExample:\n    Request:\n      curl -X GET \"http://localhost:8000/api/blastp?gene=TraesCS5A02G391700\"\n\n    Response:\n      {\n        \"success\": true,\n        \"data\": {\n          \"gene\": \"TraesCS5A02G391700\",\n          \"total\": 42,\n          \"limit\": 5000,\n          \"offset\": 0,\n          \"results\": [\n            {\n              \"query_id\": \"TraesCS5A02G391700.1\",\n              \"subject_id\": \"TraesCS5B02G391700.1\",\n              \"identity_val\": 85.32,\n              \"align_length\": 245,\n              \"mismatch\": 12,\n              \"gap_open\": 0,\n              \"q_start\": 1,\n              \"q_end\": 245,\n              \"s_start\": 1,\n              \"s_end\": 245,\n              \"evalue\": 0.0,\n              \"bit_score\": 456.7,\n              \"query_length\": 300,\n              \"subject_length\": 290\n            }\n          ]\n        }\n      }","operationId":"search_blastp_api_blastp_get","parameters":[{"name":"gene","in":"query","required":true,"schema":{"type":"string","title":"Gene"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":50000,"minimum":1,"default":5000,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Search Blastp Api Blastp Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/blast/search":{"post":{"tags":["BLAST"],"summary":"Blast Search","description":"Run a BLAST search; results are saved to files and download links are returned.\n\nAll jobs are executed by the standalone blast daemon (wheatomics-blastd.service),\nunaffected by API worker recycling/restarts. wait=true (default): enqueue and\npoll to completion, returning download_url (no changes needed for existing\nagents/scripts); wait=false: return job_id immediately and poll\nGET /api/blast/status/{job_id}.\n\nExample call:\n  curl -X POST \"https://wheatomics.sdau.edu.cn/api/blast/search\" \\n        -d \"program=blastp\" \\n        -d \"database=Fielder_protein\" \\n        --data-urlencode \"query=>test\\nMSSSTG...\"","operationId":"blast_search_api_blast_search_post","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/Body_blast_search_api_blast_search_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/blast/status/{job_id}":{"get":{"tags":["BLAST"],"summary":"Blast Job Status","description":"Poll a BLAST job's status (jobs submitted with wait=false).\n\nReturns {\"success\", \"job_id\", \"status\": pending|running|done|error|stale,\n\"message\", \"download_urls\"}. download_urls is populated when done; for\nerror/stale check message. job_id must be in uuid4 format, otherwise 404.","operationId":"blast_job_status_api_blast_status__job_id__get","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/blast/databases":{"get":{"tags":["BLAST"],"summary":"List Databases","description":"List the available BLAST databases (grouped by protein/nucleotide).\n\nThe huge sequence-retrieval-only aggregate databases (SEQUENCE_ONLY_DBS:\nall_genomes / all_other_genomes / all_Allohexaploid) are not included in\nthis list; they remain available through /api/sequence/*.","operationId":"list_databases_api_blast_databases_get","parameters":[{"name":"program","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"blastp/blastn/blastx/tblastn/tblastx/empty=all","title":"Program"},"description":"blastp/blastn/blastx/tblastn/tblastx/empty=all"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/blast/database-example":{"get":{"tags":["BLAST"],"summary":"Database Example","description":"Return the first sequence name of a BLAST database (from its .fai index) as a front-end example.","operationId":"database_example_api_blast_database_example_get","parameters":[{"name":"db","in":"query","required":true,"schema":{"type":"string","title":"Db"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/blast/job/{job_id}":{"delete":{"tags":["BLAST"],"summary":"Delete Blast Job","description":"Delete a finished BLAST job and its result files.\n\nThe job UUID acts as the capability (result URLs are public and there are no\nuser accounts); running/queued jobs cannot be deleted.","operationId":"delete_blast_job_api_blast_job__job_id__delete","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/blast/job/{job_id}/delete":{"post":{"tags":["BLAST"],"summary":"Delete Blast Job","description":"Delete a finished BLAST job and its result files.\n\nThe job UUID acts as the capability (result URLs are public and there are no\nuser accounts); running/queued jobs cannot be deleted.","operationId":"delete_blast_job_api_blast_job__job_id__delete_post","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/blast/status":{"get":{"tags":["BLAST"],"summary":"Blast Status","description":"Check the BLAST environment.","operationId":"blast_status_api_blast_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/orthofinder/search":{"get":{"tags":["OrthoFinder"],"summary":"Search by protein ID / orthogroup ID / species catalog / members","operationId":"search_orthogroup_api_orthofinder_search_get","parameters":[{"name":"q","in":"query","required":false,"schema":{"type":"string","description":"Protein/gene ID or orthogroup ID. Used when action=search.","default":"","title":"Q"},"description":"Protein/gene ID or orthogroup ID. Used when action=search."},{"name":"action","in":"query","required":false,"schema":{"type":"string","description":"Action: 'search' (default) | 'species_catalog' | 'members'","default":"search","title":"Action"},"description":"Action: 'search' (default) | 'species_catalog' | 'members'"},{"name":"og","in":"query","required":false,"schema":{"type":"string","description":"Orthogroup ID, required for action=members","default":"","title":"Og"},"description":"Orthogroup ID, required for action=members"},{"name":"sub","in":"query","required":false,"schema":{"type":"string","description":"Subgenome filter (A/B/D), used with action=members","default":"","title":"Sub"},"description":"Subgenome filter (A/B/D), used with action=members"},{"name":"species","in":"query","required":false,"schema":{"type":"string","description":"Species filter for gene search (optional)","default":"","title":"Species"},"description":"Species filter for gene search (optional)"},{"name":"_","in":"query","required":false,"schema":{"type":"integer","description":"Cache-buster (optional)","default":0,"title":" "},"description":"Cache-buster (optional)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/orthofinder/download":{"get":{"tags":["OrthoFinder"],"summary":"Download gene tree (Newick) or multiple sequence alignment (FASTA)","operationId":"download_file_api_orthofinder_download_get","parameters":[{"name":"og","in":"query","required":true,"schema":{"type":"string","description":"Orthogroup ID, e.g. OG0001897","title":"Og"},"description":"Orthogroup ID, e.g. OG0001897"},{"name":"type","in":"query","required":false,"schema":{"type":"string","description":"File type: 'tree' or 'alignment'","default":"tree","title":"Type"},"description":"File type: 'tree' or 'alignment'"},{"name":"cluster","in":"query","required":false,"schema":{"type":"integer","description":"Cluster number (1-7). 0 = full OG.","default":0,"title":"Cluster"},"description":"Cluster number (1-7). 0 = full OG."},{"name":"type_tree","in":"query","required":false,"schema":{"type":"string","description":"Type tree filter: 'type1' or 'type2'. Only for cluster downloads.","default":"","title":"Type Tree"},"description":"Type tree filter: 'type1' or 'type2'. Only for cluster downloads."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/orthofinder/neighborhood":{"get":{"tags":["OrthoFinder"],"summary":"Get chromosomal neighbors of a gene with homoeologous cluster info","description":"Return the query gene + 5 upstream/downstream neighbors (11 genes total)\nacross all genomes in the OrthoFinder analysis, with cluster assignments.\n\nBackend:\n  1. Look up gene in BED index → (chrom, pos, genome, subgenome)\n  2. Get per-chromosome sorted gene list\n  3. Extract ±5 neighbors\n  4. _resolve_cluster for each","operationId":"neighborhood_api_orthofinder_neighborhood_get","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string","description":"Gene ID, e.g. TraesCS1A02G219700.1","title":"Q"},"description":"Gene ID, e.g. TraesCS1A02G219700.1"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/track/visit":{"post":{"tags":["Track"],"summary":"Record Visit","description":"Record one page view and bump today's UV if this is a new visitor.\n\nIdempotent within the same day per (ip, user-agent) pair.","operationId":"record_visit_api_track_visit_post","parameters":[{"name":"X-Forwarded-For","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Forwarded-For"}},{"name":"User-Agent","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User-Agent"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrackPayload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Record Visit Api Track Visit Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/track/stats":{"get":{"tags":["Track"],"summary":"Get Stats","description":"Public stats: today's PV/UV, total PV/UV, and currently-online count.","operationId":"get_stats_api_track_stats_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Get Stats Api Track Stats Get"}}}}}}},"/api/go":{"post":{"tags":["GO/KEGG Enrichment"],"summary":"GO Enrichment Analysis","description":"Run **GO (Gene Ontology) enrichment analysis** on the gene list submitted by the user.\n\n**Statistical method**: hypergeometric test + Benjamini-Hochberg FDR multiple-testing correction.\n\n**Background gene set**: all genes with GO annotations in wheat_function.gene_go.\n\n**Input**: list of gene IDs (IWGSC RefSeq v1.1, e.g. `TraesCS1A02G045300.1`).\n\n**Output**: list of significantly enriched GO terms.","operationId":"go_enrichment_api_go_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichmentRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichmentResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/kegg":{"post":{"tags":["GO/KEGG Enrichment"],"summary":"KEGG Pathway Enrichment Analysis","description":"Run **KEGG pathway enrichment analysis** on the gene list submitted by the user.\n\n**Statistical method**: hypergeometric test + Benjamini-Hochberg FDR correction.\n\n**Background gene set**: all genes with KEGG annotations in wheat_function.gene_kegg.\n\n**Mapping chain**: gene_id → KO → pathway (linked through the ko_pathway and kegg_pathway tables).\n\n**Input/Output**: same format as GO enrichment.","operationId":"kegg_enrichment_api_kegg_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichmentRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichmentResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/go/genes":{"get":{"tags":["GO/KEGG Enrichment"],"summary":"Go Genes","description":"Return which genes from the query list match a GO term.","operationId":"go_genes_api_go_genes_get","parameters":[{"name":"go_id","in":"query","required":true,"schema":{"type":"string","title":"Go Id"}},{"name":"genes","in":"query","required":false,"schema":{"type":"string","default":"","title":"Genes"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/kegg/genes":{"get":{"tags":["GO/KEGG Enrichment"],"summary":"Kegg Genes","description":"Return which genes from the query list match a KEGG pathway.","operationId":"kegg_genes_api_kegg_genes_get","parameters":[{"name":"pathway","in":"query","required":true,"schema":{"type":"string","title":"Pathway"}},{"name":"genes","in":"query","required":false,"schema":{"type":"string","default":"","title":"Genes"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/VariantHub/datasets":{"get":{"tags":["VariantHub"],"summary":"Varianthub Datasets","description":"List all VCF datasets, grouped by reference genome.","operationId":"varianthub_datasets_api_VariantHub_datasets_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Varianthub Datasets Api Varianthub Datasets Get"}}}}}}},"/api/VariantHub/dataset_info":{"get":{"tags":["VariantHub"],"summary":"Varianthub Dataset Info","description":"Return a dataset's VCF header: ## meta lines and sample IDs.","operationId":"varianthub_dataset_info_api_VariantHub_dataset_info_get","parameters":[{"name":"dataset","in":"query","required":true,"schema":{"type":"string","description":"Dataset key from /api/VariantHub/datasets","title":"Dataset"},"description":"Dataset key from /api/VariantHub/datasets"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Varianthub Dataset Info Api Varianthub Dataset Info Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/VariantHub/samples":{"get":{"tags":["VariantHub"],"summary":"Varianthub Samples","description":"List sample metadata for a dataset, optionally filtered.\n\nAny extra query parameter is treated as a metadata filter on the\ndataset's own fields (exact, case-insensitive), e.g.\n&country=Turkey&status=Landrace or &group=LR.","operationId":"varianthub_samples_api_VariantHub_samples_get","parameters":[{"name":"dataset","in":"query","required":true,"schema":{"type":"string","description":"Dataset key from /api/VariantHub/datasets","title":"Dataset"},"description":"Dataset key from /api/VariantHub/datasets"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Varianthub Samples Api Varianthub Samples Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/VariantHub/query":{"get":{"tags":["VariantHub"],"summary":"Varianthub Query","description":"Query variants by genomic region or by variant ID.\n\nExactly one of `region` / `variant_id` is required. Region queries use the\ntabix index (`bcftools view -r`); ID queries filter on the ID column\n(`bcftools view -i 'ID=\"...\"'`, a full-file scan that can be slow on the\nlarge population VCFs).\n\nSamples default to all; narrow them either explicitly with `samples` or\nvia sample-metadata filters — any extra query parameter matching one of\nthe dataset's metadata fields (e.g. &country=Turkey, &group=LR) — the\ntwo are mutually exclusive.","operationId":"varianthub_query_api_VariantHub_query_get","parameters":[{"name":"dataset","in":"query","required":true,"schema":{"type":"string","description":"Dataset key from /api/VariantHub/datasets","title":"Dataset"},"description":"Dataset key from /api/VariantHub/datasets"},{"name":"region","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Genomic interval, e.g. chr1A:1000-50000","title":"Region"},"description":"Genomic interval, e.g. chr1A:1000-50000"},{"name":"variant_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Variant ID (exact match on the ID column)","title":"Variant Id"},"description":"Variant ID (exact match on the ID column)"},{"name":"samples","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated sample IDs; omit for all samples","title":"Samples"},"description":"Comma-separated sample IDs; omit for all samples"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":5000,"minimum":1,"default":200,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Varianthub Query Api Varianthub Query Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/syntenyview/genomes":{"get":{"tags":["SynTeny Viewer"],"summary":"Api Genomes","operationId":"api_genomes_api_syntenyview_genomes_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/syntenyview/gene-search":{"get":{"tags":["SynTeny Viewer"],"summary":"Api Gene Search","operationId":"api_gene_search_api_syntenyview_gene_search_get","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string","minLength":1,"title":"Q"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":50,"minimum":1,"default":20,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/syntenyview/status":{"get":{"tags":["SynTeny Viewer"],"summary":"Api Status","operationId":"api_status_api_syntenyview_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/syntenyview/triticeae":{"get":{"tags":["SynTeny Viewer"],"summary":"Api Triticeae","operationId":"api_triticeae_api_syntenyview_triticeae_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/syntenyview/neighborhood":{"get":{"tags":["SynTeny Viewer"],"summary":"Api Synteny","operationId":"api_synteny_api_syntenyview_neighborhood_get","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string","description":"Gene ID","title":"Q"},"description":"Gene ID"},{"name":"upstream","in":"query","required":false,"schema":{"type":"integer","maximum":50,"minimum":0,"default":5,"title":"Upstream"}},{"name":"downstream","in":"query","required":false,"schema":{"type":"integer","maximum":50,"minimum":0,"default":5,"title":"Downstream"}},{"name":"targets","in":"query","required":false,"schema":{"type":"string","description":"Comma-separated target genome labels","default":"","title":"Targets"},"description":"Comma-separated target genome labels"},{"name":"window","in":"query","required":false,"schema":{"type":"integer","maximum":50,"minimum":0,"default":5,"title":"Window"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/jbrowse/datasets":{"get":{"tags":["JBrowse"],"summary":"List Jbrowse Datasets","description":"List all JBrowse datasets and their track counts.\n\nUsage:\n    GET /api/jbrowse/datasets\n\nData comes from jbrowse_meta.jbrowse_datasets (imported by\nscripts/import_jbrowse_meta.py from the trackList.json files in the\nJBrowse data directory).","operationId":"list_jbrowse_datasets_api_jbrowse_datasets_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response List Jbrowse Datasets Api Jbrowse Datasets Get"}}}}}}},"/api/jbrowse/datasets/{dataset}/trackList":{"get":{"tags":["JBrowse"],"summary":"Get Jbrowse Tracklist","description":"Return the JBrowse trackList.json config of a dataset.\n\nUsage:\n    GET /api/jbrowse/datasets/Chinese_Spring1.0/trackList\n\nThe response is the bare JBrowse config object (not the unified ok()\nenvelope), equivalent to the static trackList.json on disk:\n{formatVersion, dataset_id?, names?, tracks[]}.\nTracks are rebuilt in their original order (ord) and each track object is\npreserved field by field.","operationId":"get_jbrowse_tracklist_api_jbrowse_datasets__dataset__trackList_get","parameters":[{"name":"dataset","in":"path","required":true,"schema":{"type":"string","title":"Dataset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/caps/enzymes":{"get":{"tags":["CAPS/dCAPS"],"summary":"List Enzymes","description":"List the built-in restriction enzyme library (name, recognition sequence, cut positions, whether common).","operationId":"list_enzymes_api_caps_enzymes_get","parameters":[{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by enzyme name","title":"Q"},"description":"Filter by enzyme name"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Enzymes Api Caps Enzymes Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/caps/design":{"post":{"tags":["CAPS/dCAPS"],"summary":"Design Caps Primers","description":"Design CAPS/dCAPS primer pairs (three input modes, see CapsDesignRequest).\n\nUsage:\n    POST /api/caps/design\n    {\n      \"seq1\": \"...\", \"seq2\": \"...\",          // mode 1: pasted sequences\n      \"mismatch_max\": 1\n    }","operationId":"design_caps_primers_api_caps_design_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CapsDesignRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Design Caps Primers Api Caps Design Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/eqtl/image/{project}/{gene}":{"get":{"tags":["eQTL Atlas"],"summary":"Manhattan Image","description":"Serve the FarmCPU Manhattan plot for a gene in a project.","operationId":"manhattan_image_api_eqtl_image__project___gene__get","parameters":[{"name":"project","in":"path","required":true,"schema":{"type":"string","title":"Project"}},{"name":"gene","in":"path","required":true,"schema":{"type":"string","title":"Gene"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/eqtl/search":{"get":{"tags":["eQTL Atlas"],"summary":"Search Eqtl","description":"Query eQTL records by gene ID plus each project's FarmCPU Manhattan plot.\n\nPurpose:\n    Fuzzy-match ``Geneid`` in the ``eqtl`` database's ``wheat`` table,\n    return all matching records (column names discovered dynamically, see\n    the module docstring) plus the Manhattan plot info of the 5 projects.\n\nUsage:\n    GET /api/eqtl/search?gene=TraesCS5A02G391700\n\nResponse:\n    {\n      \"success\": true,\n      \"data\": {\n        \"gene\": \"TraesCS5A02G391700\",\n        \"columns\": [\"Geneid\", \"Project\", ...],\n        \"rows\": [ {\"Geneid\": ..., \"Project\": ..., ...} ],\n        \"projects\": [\n          {\"project\": \"PRJNA670223\", \"desc\": \"...\", \"url\": \"...\", \"image\": \"/api/eqtl/image/PRJNA670223/TraesCS5A02G391700\" | null}\n        ]\n      }\n    }","operationId":"search_eqtl_api_eqtl_search_get","parameters":[{"name":"gene","in":"query","required":true,"schema":{"type":"string","minLength":1,"description":"Gene ID (Traes...) to search","title":"Gene"},"description":"Gene ID (Traes...) to search"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Search Eqtl Api Eqtl Search Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/scrna/genomes":{"get":{"tags":["scRNA"],"summary":"Api Genomes","description":"List the available scRNA genomes and their datasets.","operationId":"api_genomes_api_scrna_genomes_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/scrna/annotation":{"get":{"tags":["scRNA"],"summary":"Api Annotation","description":"Marker-gene preview table (all annotation CSV/TSV files under the genome merged, paginated).","operationId":"api_annotation_api_scrna_annotation_get","parameters":[{"name":"genome","in":"query","required":true,"schema":{"type":"string","description":"Genome key, e.g. Chinese_Spring","title":"Genome"},"description":"Genome key, e.g. Chinese_Spring"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","default":10,"title":"Per Page"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/scrna/dotplot":{"get":{"tags":["scRNA"],"summary":"Api Dotplot","description":"Query dotplot data for each dataset by gene.","operationId":"api_dotplot_api_scrna_dotplot_get","parameters":[{"name":"genome","in":"query","required":true,"schema":{"type":"string","description":"Genome key, e.g. Chinese_Spring","title":"Genome"},"description":"Genome key, e.g. Chinese_Spring"},{"name":"genes","in":"query","required":true,"schema":{"type":"string","description":"Comma/space/newline separated gene IDs","title":"Genes"},"description":"Comma/space/newline separated gene IDs"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/scrna/dotplot/download":{"get":{"tags":["scRNA"],"summary":"Api Dotplot Download","description":"Download the gene-filtered dotplot TSV.","operationId":"api_dotplot_download_api_scrna_dotplot_download_get","parameters":[{"name":"genome","in":"query","required":true,"schema":{"type":"string","title":"Genome"}},{"name":"folder","in":"query","required":true,"schema":{"type":"string","title":"Folder"}},{"name":"genes","in":"query","required":true,"schema":{"type":"string","title":"Genes"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/wheatpsp/stats":{"get":{"tags":["wheatPSP"],"summary":"Api Stats","description":"Database statistics: total proteins, predicted PSPs, PrD proteins (with percentages) + key score distributions.","operationId":"api_stats_api_wheatpsp_stats_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/wheatpsp/search":{"get":{"tags":["wheatPSP"],"summary":"Api Search","description":"Search proteins by seq_id / gene_id, paginated.","operationId":"api_search_api_wheatpsp_search_get","parameters":[{"name":"q","in":"query","required":false,"schema":{"type":"string","description":"seq_id / gene_id fuzzy search","default":"","title":"Q"},"description":"seq_id / gene_id fuzzy search"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","default":20,"title":"Per Page"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/wheatpsp/psp":{"get":{"tags":["wheatPSP"],"summary":"Api Psp","description":"List of predicted phase-separation-associated proteins (is_psp=1), paginated.","operationId":"api_psp_api_wheatpsp_psp_get","parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","default":20,"title":"Per Page"}},{"name":"q","in":"query","required":false,"schema":{"type":"string","description":"seq_id / gene_id fuzzy filter","default":"","title":"Q"},"description":"seq_id / gene_id fuzzy filter"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/wheatpsp/prd":{"get":{"tags":["wheatPSP"],"summary":"Api Prd","description":"List of predicted PrD (prion-like domain) proteins (has_prd=1), paginated.","operationId":"api_prd_api_wheatpsp_prd_get","parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","default":20,"title":"Per Page"}},{"name":"q","in":"query","required":false,"schema":{"type":"string","description":"seq_id / gene_id fuzzy filter","default":"","title":"Q"},"description":"seq_id / gene_id fuzzy filter"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/wheatpsp/gene/{cs_gene_id}":{"get":{"tags":["wheatPSP"],"summary":"Api Gene","description":"All transcripts of one gene (CS 02G id), with phase-separation predictions side by side.","operationId":"api_gene_api_wheatpsp_gene__cs_gene_id__get","parameters":[{"name":"cs_gene_id","in":"path","required":true,"schema":{"type":"string","title":"Cs Gene Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/wheatpsp/protein/{seq_id}":{"get":{"tags":["wheatPSP"],"summary":"Api Protein","description":"Complete prediction result for a single protein + sequence + physicochemical properties (from fangenome.csv).","operationId":"api_protein_api_wheatpsp_protein__seq_id__get","parameters":[{"name":"seq_id","in":"path","required":true,"schema":{"type":"string","title":"Seq Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/wheatpsp/download/{table}":{"get":{"tags":["wheatPSP"],"summary":"Api Download","description":"Download split tables: allProteins / PredPSPs / PrD_Pro (TSV inside a ZIP, DEFLATE-compressed).","operationId":"api_download_api_wheatpsp_download__table__get","parameters":[{"name":"table","in":"path","required":true,"schema":{"type":"string","title":"Table"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/genomes/stats":{"get":{"tags":["Genome Registry"],"summary":"Genome Registry Stats","description":"Genome registry statistics (by ploidy / annotation status / module coverage).","operationId":"genome_registry_stats_api_genomes_stats_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Genome Registry Stats Api Genomes Stats Get"}}}}}}},"/api/genomes":{"get":{"tags":["Genome Registry"],"summary":"List Genomes","description":"List genome registry records (filterable by ploidy / annotation status / keyword).","operationId":"list_genomes_api_genomes_get","parameters":[{"name":"ploidy","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by ploidy, e.g. AABBDD / AABBRR","title":"Ploidy"},"description":"Filter by ploidy, e.g. AABBDD / AABBRR"},{"name":"annotation_status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Annotation status: none / pending / available","title":"Annotation Status"},"description":"Annotation status: none / pending / available"},{"name":"has_annotation","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"True = annotated only; False = unannotated / pending","title":"Has Annotation"},"description":"True = annotated only; False = unannotated / pending"},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Fuzzy search over dataset_id / display_name / species / cultivar","title":"Q"},"description":"Fuzzy search over dataset_id / display_name / species / cultivar"},{"name":"include_hidden","in":"query","required":false,"schema":{"type":"boolean","description":"Whether to include records with visible=0","default":false,"title":"Include Hidden"},"description":"Whether to include records with visible=0"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"default":100,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Genomes Api Genomes Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/genomes/{dataset_id}":{"get":{"tags":["Genome Registry"],"summary":"Get Genome","description":"Single genome record (with full provenance in aliases_json / usage_json).","operationId":"get_genome_api_genomes__dataset_id__get","parameters":[{"name":"dataset_id","in":"path","required":true,"schema":{"type":"string","title":"Dataset Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Genome Api Genomes  Dataset Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/ptm/search":{"get":{"tags":["wheatPTM"],"summary":"Search Ptm","description":"Search all PTM sites of a protein by protein ID (across 9 PTM types).\n\nUsage:\n    GET /api/ptm/search?protein=TraesCS1A02G000100LC.1\n    GET /api/ptm/search?protein=TraesCS1A02G000100LC.1&scope=ptm\n\n``sites``/``stats``/``confidence_counts`` always describe the requested\n``scope``; ``known`` says whether the protein exists in the dataset at all.","operationId":"search_ptm_api_ptm_search_get","parameters":[{"name":"protein","in":"query","required":true,"schema":{"type":"string","minLength":1,"description":"Protein ID, e.g. TraesCS1A02G000100LC.1","title":"Protein"},"description":"Protein ID, e.g. TraesCS1A02G000100LC.1"},{"name":"scope","in":"query","required":false,"schema":{"type":"string","description":"all | ptm | high","default":"all","title":"Scope"},"description":"all | ptm | high"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Search Ptm Api Ptm Search Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/ptm/download":{"get":{"tags":["wheatPTM"],"summary":"Download Ptm","description":"Download all PTM sites of a protein as CSV (``scope`` matches the search endpoint).","operationId":"download_ptm_api_ptm_download_get","parameters":[{"name":"protein","in":"query","required":true,"schema":{"type":"string","minLength":1,"description":"Protein ID","title":"Protein"},"description":"Protein ID"},{"name":"scope","in":"query","required":false,"schema":{"type":"string","description":"all | ptm | high","default":"all","title":"Scope"},"description":"all | ptm | high"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/genes/known/write":{"post":{"tags":["Known Genes (write)"],"summary":"Create Known Gene","description":"Create one KnownGene record (requires write scope; dry_run supported).\n\nPurpose:\n    Validate and write one known-function gene record, automatically deriving\n    ``species_primary`` (296 source-text mappings + scientific-name aliases,\n    with a warning when falling back), ``chromosome`` (chr regex over chrom_pos)\n    and ``publication_year`` (minimum of the multi-valued years); multi-valued\n    ``paper_title`` / ``paper_doi`` / ``publication_years`` accept a list or a\n    ``\"; \"``-separated string, are aligned positionally and stored with ``###``.\n    A duplicate (gene_id, gene_name) -> 409. The main-table write and the audit\n    record (``known_gene_change_log``, action=create, after_json=full row) share\n    one transaction.\n\nParameters:\n    - ``dry_run``: when true, only validate/deduplicate and return the \"record that would be written\"; nothing is persisted;\n    - ``gene``: gene field object (the fields may also be placed at the top level).\n    Required: gene_id / gene_name / reference_genome_id / gene_species / chrom_pos /\n    gene_phenotype / functional_category / research_strategy / key_result;\n    and at least one of paper_doi and paper_title.\n    Optional: protein_family / validation_method / cloning_method /\n    cloning_method_description / function_description / author / author_mail /\n    submission_date / publication_year / publication_years / paper_title /\n    paper_doi; the derived columns species_primary / chromosome may be explicitly\n    overridden (they are validated).\n    Defaults: author='WheatOmics API', author_mail='shengweima@icloud.com',\n    submission_date=today.\n\nUsage:\n    POST /api/genes/known/write\n    Header: Authorization: Bearer kgw_xxx (or X-API-Key: kgw_xxx)\n    Body: {\"dry_run\": false, \"gene\": {...}}\n\nExample:\n    Request:\n      curl -X POST \"http://localhost:8000/api/genes/known/write\" \\\n        -H \"Authorization: Bearer $KNOWN_GENE_API_KEY\" \\\n        -H \"Content-Type: application/json\" \\\n        -d '{\"dry_run\": true, \"gene\": {\n              \"gene_id\": \"TraesCS7B03G0166400\", \"gene_name\": \"TaERF1-B\",\n              \"reference_genome_id\": \"TraesCS7B03G0166400\",\n              \"gene_species\": \"Triticum aestivum (bread wheat)\",\n              \"chrom_pos\": \"Refv1.0 chr7B:112.264-112.266Mb\",\n              \"gene_phenotype\": \"Drought tolerance\",\n              \"functional_category\": \"Biotic Stress\",\n              \"research_strategy\": \"Reverse genetics\",\n              \"key_result\": \"Overexpression improves drought tolerance.\",\n              \"paper_doi\": \"10.1007/s11103-007-9237-9\"}}'\n\n    Response:\n      {\"success\": true, \"message\": \"dry-run: validation passed, nothing written\",\n       \"timestamp\": \"...\", \"data\": {\"dry_run\": true,\n         \"record\": {\"gene_id\": \"...\", \"species_primary\": \"Triticum aestivum\",\n                    \"chromosome\": \"7B\", \"publication_year\": 2007, ...},\n         \"warnings\": []}}\n\n    Persisted response data: {\"dry_run\": false, \"clone_id\": 1626, \"audit_id\": 1,\n                    \"record\": {<detail shape, same as /api/genes/known/{clone_id}>},\n                    \"warnings\": []}","operationId":"create_known_gene_api_genes_known_write_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Bearer <kgw_xxx>","title":"Authorization"},"description":"Bearer <kgw_xxx>"},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Compatibility header; equivalent to Bearer","title":"X-Api-Key"},"description":"Compatibility header; equivalent to Bearer"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Create Known Gene Api Genes Known Write Post"}}}},"400":{"description":"Request body is not valid JSON / malformed parameters"},"401":{"description":"Missing or invalid API Key (not found / disabled / expired all return 401)"},"403":{"description":"API Key scope insufficient, or the source IP is not allowlisted"},"404":{"description":"clone_id does not exist"},"409":{"description":"(gene_id, gene_name) already exists"},"413":{"description":"Request body exceeds 2MB"},"422":{"description":"Business field validation failed (detail.errors lists each field error)"},"429":{"description":"Write requests per Key per minute exceeded"},"503":{"description":"Auth table not initialized / database unavailable"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"Recommended form {\"dry_run\": false, \"gene\": {...}}; the gene fields may also be placed at the top level (bare object).","properties":{"dry_run":{"type":"boolean","default":false},"gene":{"type":"object","additionalProperties":true,"description":"Gene fields; see the field table in the docs on the GET /api/genes/known/write/whoami page"}},"additionalProperties":true},"example":{"dry_run":true,"gene":{"gene_id":"TraesCS7B03G0166400","gene_name":"TaERF1-B","reference_genome_id":"TraesCS7B03G0166400","gene_species":"Triticum aestivum (bread wheat)","chrom_pos":"Refv1.0 chr7B:112.264-112.266Mb","gene_phenotype":"Drought tolerance; Salt tolerance","functional_category":"Biotic Stress","research_strategy":"Reverse genetics","key_result":"Overexpression of TaERF1 improves drought tolerance.","paper_title":"Isolation and molecular characterization of TaERF1","paper_doi":"10.1007/s11103-007-9237-9","publication_year":2007}}}}}}},"/api/genes/known/write/update/{clone_id}":{"post":{"tags":["Known Genes (write)"],"summary":"Update Known Gene","description":"Update a KnownGene by clone_id (requires write scope; only supplied fields change; dry_run supported).\n\nPurpose:\n    Update only the fields present in the body (same whitelist as create,\n    excluding clone_id); when a source field changes, recompute the derived\n    columns (gene_species->species_primary, chrom_pos->chromosome,\n    publication_years->publication_year). Rows are locked with\n    ``SELECT ... FOR UPDATE`` before update; a missing clone_id -> 404. The audit\n    record stores the full before/after rows plus the columns that actually\n    changed (``changed_fields``), in the same transaction as the UPDATE.\n    If the supplied values are identical to the stored row, no UPDATE is run and\n    no audit is written (changed_fields=[]).\n\nParameters:\n    - ``clone_id``: path parameter, the internal auto-increment primary key (the id in the detail-page URL);\n    - ``dry_run``: when true, return the merged record and changed_fields without persisting;\n    - ``fields``: object of fields to update (the fields may also be placed at the top level).\n\nUsage:\n    PATCH /api/genes/known/write/{clone_id}\n\nExample:\n    Request:\n      curl -X PATCH \"http://localhost:8000/api/genes/known/write/1626\" \\\n        -H \"Authorization: Bearer $KNOWN_GENE_API_KEY\" \\\n        -H \"Content-Type: application/json\" \\\n        -d '{\"fields\": {\"gene_phenotype\": \"Drought tolerance; Salt tolerance\",\n                        \"publication_years\": \"2007; 2024\"}}'\n\n    Response:\n      {\"success\": true, \"message\": \"updated successfully\", \"data\": {\n        \"dry_run\": false, \"clone_id\": 1626, \"audit_id\": 2,\n        \"changed_fields\": [\"gene_phenotype\", \"publication_year\", \"publication_years\"],\n        \"record\": {<detail shape>}, \"warnings\": []}}","operationId":"update_known_gene_api_genes_known_write_update__clone_id__post","parameters":[{"name":"clone_id","in":"path","required":true,"schema":{"type":"integer","title":"Clone Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Bearer <kgw_xxx>","title":"Authorization"},"description":"Bearer <kgw_xxx>"},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Compatibility header; equivalent to Bearer","title":"X-Api-Key"},"description":"Compatibility header; equivalent to Bearer"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Update Known Gene Api Genes Known Write Update  Clone Id  Post"}}}},"400":{"description":"Request body is not valid JSON / malformed parameters"},"401":{"description":"Missing or invalid API Key (not found / disabled / expired all return 401)"},"403":{"description":"API Key scope insufficient, or the source IP is not allowlisted"},"404":{"description":"clone_id does not exist"},"409":{"description":"(gene_id, gene_name) already exists"},"413":{"description":"Request body exceeds 2MB"},"422":{"description":"Business field validation failed (detail.errors lists each field error)"},"429":{"description":"Write requests per Key per minute exceeded"},"503":{"description":"Auth table not initialized / database unavailable"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"Recommended form {\"dry_run\": false, \"fields\": {...}}; the fields to change may also be placed at the top level (bare object).","properties":{"dry_run":{"type":"boolean","default":false},"fields":{"type":"object","additionalProperties":true,"description":"Fields to update (same whitelist as create, excluding clone_id)"}},"additionalProperties":true},"example":{"dry_run":true,"fields":{"gene_phenotype":"Drought tolerance; Salt tolerance; Heat tolerance","publication_years":"2007; 2024"}}}}}}},"/api/genes/known/write/{clone_id}":{"patch":{"tags":["Known Genes (write)"],"summary":"Update Known Gene","description":"Update a KnownGene by clone_id (requires write scope; only supplied fields change; dry_run supported).\n\nPurpose:\n    Update only the fields present in the body (same whitelist as create,\n    excluding clone_id); when a source field changes, recompute the derived\n    columns (gene_species->species_primary, chrom_pos->chromosome,\n    publication_years->publication_year). Rows are locked with\n    ``SELECT ... FOR UPDATE`` before update; a missing clone_id -> 404. The audit\n    record stores the full before/after rows plus the columns that actually\n    changed (``changed_fields``), in the same transaction as the UPDATE.\n    If the supplied values are identical to the stored row, no UPDATE is run and\n    no audit is written (changed_fields=[]).\n\nParameters:\n    - ``clone_id``: path parameter, the internal auto-increment primary key (the id in the detail-page URL);\n    - ``dry_run``: when true, return the merged record and changed_fields without persisting;\n    - ``fields``: object of fields to update (the fields may also be placed at the top level).\n\nUsage:\n    PATCH /api/genes/known/write/{clone_id}\n\nExample:\n    Request:\n      curl -X PATCH \"http://localhost:8000/api/genes/known/write/1626\" \\\n        -H \"Authorization: Bearer $KNOWN_GENE_API_KEY\" \\\n        -H \"Content-Type: application/json\" \\\n        -d '{\"fields\": {\"gene_phenotype\": \"Drought tolerance; Salt tolerance\",\n                        \"publication_years\": \"2007; 2024\"}}'\n\n    Response:\n      {\"success\": true, \"message\": \"updated successfully\", \"data\": {\n        \"dry_run\": false, \"clone_id\": 1626, \"audit_id\": 2,\n        \"changed_fields\": [\"gene_phenotype\", \"publication_year\", \"publication_years\"],\n        \"record\": {<detail shape>}, \"warnings\": []}}","operationId":"update_known_gene_api_genes_known_write__clone_id__patch","parameters":[{"name":"clone_id","in":"path","required":true,"schema":{"type":"integer","title":"Clone Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Bearer <kgw_xxx>","title":"Authorization"},"description":"Bearer <kgw_xxx>"},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Compatibility header; equivalent to Bearer","title":"X-Api-Key"},"description":"Compatibility header; equivalent to Bearer"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Update Known Gene Api Genes Known Write  Clone Id  Patch"}}}},"400":{"description":"Request body is not valid JSON / malformed parameters"},"401":{"description":"Missing or invalid API Key (not found / disabled / expired all return 401)"},"403":{"description":"API Key scope insufficient, or the source IP is not allowlisted"},"404":{"description":"clone_id does not exist"},"409":{"description":"(gene_id, gene_name) already exists"},"413":{"description":"Request body exceeds 2MB"},"422":{"description":"Business field validation failed (detail.errors lists each field error)"},"429":{"description":"Write requests per Key per minute exceeded"},"503":{"description":"Auth table not initialized / database unavailable"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"Recommended form {\"dry_run\": false, \"fields\": {...}}; the fields to change may also be placed at the top level (bare object).","properties":{"dry_run":{"type":"boolean","default":false},"fields":{"type":"object","additionalProperties":true,"description":"Fields to update (same whitelist as create, excluding clone_id)"}},"additionalProperties":true},"example":{"dry_run":true,"fields":{"gene_phenotype":"Drought tolerance; Salt tolerance; Heat tolerance","publication_years":"2007; 2024"}}}}}}},"/api/genes/known/write/bulk":{"post":{"tags":["Known Genes (write)"],"summary":"Bulk Upsert Known Genes","description":"Bulk create/update KnownGene (<=500 rows per call, requires write scope; dry_run by default).\n\nPurpose:\n    Validate each row as a \"complete create record\"; with ``mode=insert_only``\n    the whole batch is rejected if any (gene_id, gene_name) already exists;\n    with ``mode=upsert`` existing rows are updated (audit action=bulk_update),\n    otherwise inserted (action=bulk_create).\n    When not a dry run it is **all or nothing**: any row failing validation ->\n    422 + per-row errors, nothing is written; after all rows pass, every row is\n    written in one transaction with an audit record per row.\n    dry_run (the default) returns ``would_create`` / ``would_update`` / ``error``\n    for each row.\n\nParameters:\n    - ``rows``: array of gene objects (the per-row field spec is the same as POST / and must be complete);\n    - ``mode``: ``insert_only`` | ``upsert`` (default upsert);\n    - ``dry_run``: defaults to true; pass false to persist after confirming the dry-run result.\n\nUsage:\n    POST /api/genes/known/write/bulk\n\nExample:\n    Request:\n      curl -X POST \"http://localhost:8000/api/genes/known/write/bulk\" \\\n        -H \"Authorization: Bearer $KNOWN_GENE_API_KEY\" \\\n        -H \"Content-Type: application/json\" \\\n        -d '{\"mode\": \"upsert\", \"dry_run\": true, \"rows\": [{...}, {...}]}'\n\n    Response (dry-run):\n      {\"success\": true, \"data\": {\"created\": 1, \"updated\": 0, \"errors\": 0,\n        \"dry_run\": true, \"total\": 1,\n        \"results\": [{\"row\": 1, \"status\": \"would_create\", \"clone_id\": null}],\n        \"audit_ids\": []}}\n\n    Persisted response data: {\"created\": 0, \"updated\": 1, \"errors\": 0, \"dry_run\": false,\n        \"total\": 1, \"results\": [{\"row\": 1, \"status\": \"updated\", \"clone_id\": 1626,\n        \"audit_id\": 3, \"changed_fields\": [\"gene_phenotype\"]}], \"audit_ids\": [3]}","operationId":"bulk_upsert_known_genes_api_genes_known_write_bulk_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Bearer <kgw_xxx>","title":"Authorization"},"description":"Bearer <kgw_xxx>"},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Compatibility header; equivalent to Bearer","title":"X-Api-Key"},"description":"Compatibility header; equivalent to Bearer"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Bulk Upsert Known Genes Api Genes Known Write Bulk Post"}}}},"400":{"description":"Request body is not valid JSON / malformed parameters"},"401":{"description":"Missing or invalid API Key (not found / disabled / expired all return 401)"},"403":{"description":"API Key scope insufficient, or the source IP is not allowlisted"},"404":{"description":"clone_id does not exist"},"409":{"description":"(gene_id, gene_name) already exists"},"413":{"description":"Request body exceeds 2MB"},"422":{"description":"Business field validation failed (detail.errors lists each field error)"},"429":{"description":"Write requests per Key per minute exceeded"},"503":{"description":"Auth table not initialized / database unavailable"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["rows"],"properties":{"rows":{"type":"array","maxItems":500,"items":{"type":"object","additionalProperties":true}},"mode":{"type":"string","enum":["insert_only","upsert"],"default":"upsert","description":"insert_only: reject the whole batch if any (gene_id,gene_name) already exists; upsert: update it if it exists"},"dry_run":{"type":"boolean","default":true,"description":"Defaults to true (dry-run first); pass false explicitly to persist after confirming"}},"additionalProperties":false},"example":{"mode":"upsert","dry_run":true,"rows":[{"gene_id":"TraesCS7B03G0166400","gene_name":"TaERF1-B","reference_genome_id":"TraesCS7B03G0166400","gene_species":"Triticum aestivum (bread wheat)","chrom_pos":"Refv1.0 chr7B:112.264-112.266Mb","gene_phenotype":"Drought tolerance","functional_category":"Biotic Stress","research_strategy":"Reverse genetics","key_result":"Overexpression of TaERF1 improves drought tolerance.","paper_doi":"10.1007/s11103-007-9237-9"}]}}}}}},"/api/genes/known/write/changes":{"get":{"tags":["Known Genes (write)"],"summary":"List Known Gene Changes","description":"Query the KnownGene write audit log (requires admin scope).\n\nPurpose:\n    Return ``known_gene_change_log`` records (newest id first), including the\n    action, clone_id, gene_id/gene_name, changed_fields, actor key label,\n    client_ip, timestamp and reason. The before/after snapshots are not returned\n    by default (they can be large); with ``include_snapshot=true`` the parsed\n    full row dicts are returned.\n\nUsage:\n    GET /api/genes/known/write/changes?limit=20&action=update\n    Header: Authorization: Bearer kgw_xxx (requires admin scope)\n\nExample:\n    Request:\n      curl \"http://localhost:8000/api/genes/known/write/changes?clone_id=1626&limit=10\" \\\n        -H \"Authorization: Bearer $KNOWN_GENE_ADMIN_KEY\"\n\n    Response:\n      {\"success\": true, \"data\": {\"total\": 2, \"limit\": 10, \"offset\": 0,\n        \"records\": [{\"id\": 2, \"action\": \"update\", \"clone_id\": 1626,\n          \"gene_id\": \"...\", \"gene_name\": \"...\",\n          \"changed_fields\": [\"gene_phenotype\", \"publication_year\"],\n          \"actor_key_id\": 1, \"actor_label\": \"maintainer-key\",\n          \"client_ip\": \"127.0.0.1\", \"reason\": null,\n          \"created_at\": \"2026-10-28T19:20:00\"}]}}","operationId":"list_known_gene_changes_api_genes_known_write_changes_get","parameters":[{"name":"clone_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Only show the change history of a given clone_id","title":"Clone Id"},"description":"Only show the change history of a given clone_id"},{"name":"action","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by action: create / update / delete / bulk_create / bulk_update","title":"Action"},"description":"Filter by action: create / update / delete / bulk_create / bulk_update"},{"name":"since","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Start time (YYYY-MM-DD or ISO 8601)","title":"Since"},"description":"Start time (YYYY-MM-DD or ISO 8601)"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"description":"Number of rows to return (default 50, max 500)","default":50,"title":"Limit"},"description":"Number of rows to return (default 50, max 500)"},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"description":"Pagination offset","default":0,"title":"Offset"},"description":"Pagination offset"},{"name":"include_snapshot","in":"query","required":false,"schema":{"type":"boolean","description":"Whether to return the full before/after row snapshots (includes long text; not returned by default)","default":false,"title":"Include Snapshot"},"description":"Whether to return the full before/after row snapshots (includes long text; not returned by default)"},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Bearer <kgw_xxx>","title":"Authorization"},"description":"Bearer <kgw_xxx>"},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Compatibility header; equivalent to Bearer","title":"X-Api-Key"},"description":"Compatibility header; equivalent to Bearer"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Known Gene Changes Api Genes Known Write Changes Get"}}}},"400":{"description":"Request body is not valid JSON / malformed parameters"},"401":{"description":"Missing or invalid API Key (not found / disabled / expired all return 401)"},"403":{"description":"API Key scope insufficient, or the source IP is not allowlisted"},"404":{"description":"clone_id does not exist"},"409":{"description":"(gene_id, gene_name) already exists"},"413":{"description":"Request body exceeds 2MB"},"422":{"description":"Business field validation failed (detail.errors lists each field error)"},"429":{"description":"Write requests per Key per minute exceeded"},"503":{"description":"Auth table not initialized / database unavailable"}}}},"/api/genes/known/write/whoami":{"get":{"tags":["Known Genes (write)"],"summary":"Known Gene Write Whoami","description":"Return the identity info of the current API Key (any valid key may call it).\n\nPurpose:\n    For maintainer self-checks: key_id, label, scopes, expires_at,\n    last_used_at (auth refreshes last_used_at on a best-effort basis). The\n    response does **not** include the key itself or its hash.\n\nUsage:\n    GET /api/genes/known/write/whoami\n    Header: Authorization: Bearer kgw_xxx\n\nExample:\n    Request:\n      curl \"http://localhost:8000/api/genes/known/write/whoami\" \\\n        -H \"Authorization: Bearer $KNOWN_GENE_API_KEY\"\n\n    Response:\n      {\"success\": true, \"data\": {\"key_id\": 1, \"label\": \"maintainer-key\",\n        \"scopes\": [\"write\"], \"expires_at\": \"2027-10-28T00:00:00\",\n        \"last_used_at\": \"2026-10-28T19:21:03\"}}","operationId":"known_gene_write_whoami_api_genes_known_write_whoami_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Bearer <kgw_xxx>","title":"Authorization"},"description":"Bearer <kgw_xxx>"},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Compatibility header; equivalent to Bearer","title":"X-Api-Key"},"description":"Compatibility header; equivalent to Bearer"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Known Gene Write Whoami Api Genes Known Write Whoami Get"}}}},"400":{"description":"Request body is not valid JSON / malformed parameters"},"401":{"description":"Missing or invalid API Key (not found / disabled / expired all return 401)"},"403":{"description":"API Key scope insufficient, or the source IP is not allowlisted"},"404":{"description":"clone_id does not exist"},"409":{"description":"(gene_id, gene_name) already exists"},"413":{"description":"Request body exceeds 2MB"},"422":{"description":"Business field validation failed (detail.errors lists each field error)"},"429":{"description":"Write requests per Key per minute exceeded"},"503":{"description":"Auth table not initialized / database unavailable"}}}},"/api/regulatory/health":{"get":{"tags":["Wheat Regulatory Hub"],"summary":"Health","operationId":"health_api_regulatory_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/regulatory/gene/{gene_id}":{"get":{"tags":["Wheat Regulatory Hub"],"summary":"Gene Profile","operationId":"gene_profile_api_regulatory_gene__gene_id__get","parameters":[{"name":"gene_id","in":"path","required":true,"schema":{"type":"string","title":"Gene Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/regulatory/gene/{gene_id}/hits":{"get":{"tags":["Wheat Regulatory Hub"],"summary":"Gene Hits","operationId":"gene_hits_api_regulatory_gene__gene_id__hits_get","parameters":[{"name":"gene_id","in":"path","required":true,"schema":{"type":"string","title":"Gene Id"}},{"name":"motif","in":"query","required":false,"schema":{"type":"string","maxLength":100,"default":"","title":"Motif"}},{"name":"strand","in":"query","required":false,"schema":{"type":"string","pattern":"^$|^[+-]$","default":"","title":"Strand"}},{"name":"max_pvalue","in":"query","required":false,"schema":{"type":"number","maximum":1,"exclusiveMinimum":0,"default":0.0001,"title":"Max Pvalue"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Page Size"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/regulatory/gene/{gene_id}/track":{"get":{"tags":["Wheat Regulatory Hub"],"summary":"Gene Track","operationId":"gene_track_api_regulatory_gene__gene_id__track_get","parameters":[{"name":"gene_id","in":"path","required":true,"schema":{"type":"string","title":"Gene Id"}},{"name":"max_pvalue","in":"query","required":false,"schema":{"type":"number","maximum":1,"exclusiveMinimum":0,"default":1e-06,"title":"Max Pvalue"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":250,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/regulatory/motifs":{"get":{"tags":["Wheat Regulatory Hub"],"summary":"Search Motifs","operationId":"search_motifs_api_regulatory_motifs_get","parameters":[{"name":"q","in":"query","required":false,"schema":{"type":"string","maxLength":100,"default":"","title":"Q"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":30,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/regulatory/gene/{gene_id}/export":{"get":{"tags":["Wheat Regulatory Hub"],"summary":"Export Gene Hits","operationId":"export_gene_hits_api_regulatory_gene__gene_id__export_get","parameters":[{"name":"gene_id","in":"path","required":true,"schema":{"type":"string","title":"Gene Id"}},{"name":"motif","in":"query","required":false,"schema":{"type":"string","maxLength":100,"default":"","title":"Motif"}},{"name":"strand","in":"query","required":false,"schema":{"type":"string","pattern":"^$|^[+-]$","default":"","title":"Strand"}},{"name":"max_pvalue","in":"query","required":false,"schema":{"type":"number","maximum":1,"exclusiveMinimum":0,"default":0.0001,"title":"Max Pvalue"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/regulatory/gene/{gene_id}/candidate-tfs":{"get":{"tags":["Wheat Regulatory Integration"],"summary":"Candidate Tfs","operationId":"candidate_tfs_api_regulatory_gene__gene_id__candidate_tfs_get","parameters":[{"name":"gene_id","in":"path","required":true,"schema":{"type":"string","title":"Gene Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100000,"minimum":1,"default":10000,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/regulatory/variant-datasets":{"get":{"tags":["Wheat Regulatory Integration"],"summary":"Variant Datasets","operationId":"variant_datasets_api_regulatory_variant_datasets_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/regulatory/variants/overlap":{"get":{"tags":["Wheat Regulatory Integration"],"summary":"Variants Overlap","operationId":"variants_overlap_api_regulatory_variants_overlap_get","parameters":[{"name":"dataset_id","in":"query","required":true,"schema":{"type":"string","title":"Dataset Id"}},{"name":"assembly","in":"query","required":true,"schema":{"type":"string","title":"Assembly"}},{"name":"chrom","in":"query","required":true,"schema":{"type":"string","title":"Chrom"}},{"name":"start0","in":"query","required":true,"schema":{"type":"integer","minimum":0,"title":"Start0"}},{"name":"end0","in":"query","required":true,"schema":{"type":"integer","exclusiveMinimum":0,"title":"End0"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":100,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/regulatory/tf/search":{"get":{"tags":["Wheat Regulatory Integration"],"summary":"Search Wheat Tf","description":"Search curated wheat TF atlas; no automatic motif-name-as-TF substitution.","operationId":"search_wheat_tf_api_regulatory_tf_search_get","parameters":[{"name":"q","in":"query","required":false,"schema":{"type":"string","maxLength":100,"default":"","title":"Q"}},{"name":"family","in":"query","required":false,"schema":{"type":"string","maxLength":80,"default":"","title":"Family"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/regulatory/atlas/search":{"get":{"tags":["Regulatory TF Atlas"],"summary":"Search","operationId":"search_api_regulatory_atlas_search_get","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string","minLength":2,"maxLength":100,"title":"Q"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/regulatory/atlas/gene/{gene_id}":{"get":{"tags":["Regulatory TF Atlas"],"summary":"Profile","operationId":"profile_api_regulatory_atlas_gene__gene_id__get","parameters":[{"name":"gene_id","in":"path","required":true,"schema":{"type":"string","title":"Gene Id"}},{"name":"region","in":"query","required":false,"schema":{"type":"string","default":"upstream","title":"Region"}},{"name":"motif_limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"default":100,"title":"Motif Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/regulatory/atlas/gene/{gene_id}/motif-variants":{"get":{"tags":["Regulatory TF Atlas"],"summary":"Motif Variants","description":"Precise motif-variant genomic interval intersection; NO PWM scoring.\nOne VCF fetch per regulatory region (upstream in the main database,\ndownstream in the per-chromosome shard), then in-memory interval checks.","operationId":"motif_variants_api_regulatory_atlas_gene__gene_id__motif_variants_get","parameters":[{"name":"gene_id","in":"path","required":true,"schema":{"type":"string","title":"Gene Id"}},{"name":"dataset_id","in":"query","required":true,"schema":{"type":"string","title":"Dataset Id"}},{"name":"region","in":"query","required":false,"schema":{"type":"string","default":"upstream","title":"Region"}},{"name":"motif_limit","in":"query","required":false,"schema":{"type":"integer","maximum":100000,"minimum":1,"default":20000,"title":"Motif Limit"}},{"name":"variant_limit","in":"query","required":false,"schema":{"type":"integer","maximum":50000,"minimum":1,"default":10000,"title":"Variant Limit"}},{"name":"result_limit","in":"query","required":false,"schema":{"type":"integer","maximum":2000,"minimum":1,"default":500,"title":"Result Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/PrimerServer2/config":{"get":{"tags":["PrimerServer2"],"summary":"Get public server configuration","description":"Returns input limits and system flags (CPU count, cleanup policy, etc.).","operationId":"get_config_endpoint_api_PrimerServer2_config_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfigResponse"}}}}}}},"/api/PrimerServer2/databases":{"get":{"tags":["PrimerServer2"],"summary":"List available specificity-check databases","description":"Returns database groups (genome / gene) built from the shared BLAST library at settings.BLAST_DB_PATH, and the all_* aggregated databases are excluded because hits in multi-genome aggregates are not useful for genome-specific primer specificity checking. For each database, sequence IDs are read from the corresponding .fai file and returned through the examples field. Use the file names in the selected-databases field when submitting jobs.","operationId":"get_databases_api_PrimerServer2_databases_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DatabasesResponse"}}}}}}},"/api/PrimerServer2/databases/{db_name}/sequences":{"get":{"tags":["PrimerServer2"],"summary":"List every acceptable template ID in one database","description":"Streams the full `sequence_id<TAB>length` list read from <BLAST_DB_PATH>/<db_name>.fai — the IDs that are acceptable as the TargetID in a design job. A genome database has ~21 rows; a gene database can exceed 100k rows and several MB, so the body is streamed as text/plain rather than wrapped in JSON. This is the same list the legacy PrimerServer offered through script/modal_help_list_ID.php.\n\ndb_name must be one of the names from GET /databases.","operationId":"get_database_sequences_api_PrimerServer2_databases__db_name__sequences_get","parameters":[{"name":"db_name","in":"path","required":true,"schema":{"type":"string","title":"Db Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"404":{"description":"Not a picker database, or no .fai beside it"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/PrimerServer2/server-info":{"get":{"tags":["PrimerServer2"],"summary":"Get server runtime information","description":"Returns current time and versions of external tools (samtools, blastn, primer3). CPU and memory details are only included when showInfo is enabled in config.","operationId":"get_server_info_api_PrimerServer2_server_info_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServerInfoResponse"}}}}}}},"/api/PrimerServer2/health":{"get":{"tags":["PrimerServer2"],"summary":"Check that the external tools and directories are in place","description":"Returns status=healthy only when every check passes, plus the individual booleans. Useful straight after a deploy — a missing primer3 or blastn, or a database dir that does not exist, is otherwise only visible as a failed job. Tool paths come from the PRIMERSERVER2_* settings.","operationId":"get_health_api_PrimerServer2_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/PrimerServer2/jobs":{"post":{"tags":["PrimerServer2"],"summary":"Submit a primer design & check job","description":"Designs PCR primers with Primer3 and checks specificity against selected databases. Returns a jobId; poll GET /jobs/{job_id}/progress and GET /jobs/{job_id}/result.","operationId":"create_job_api_PrimerServer2_jobs_post","parameters":[{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DesignJobRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/PrimerServer2/jobs/check":{"post":{"tags":["PrimerServer2"],"summary":"Submit a specificity-check-only job","description":"Checks the specificity of user-provided primer sequences against selected databases. Returns a jobId; poll GET /jobs/{job_id}/progress and GET /jobs/{job_id}/result.","operationId":"create_check_job_api_PrimerServer2_jobs_check_post","parameters":[{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckJobRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/PrimerServer2/jobs/{job_id}":{"get":{"tags":["PrimerServer2"],"summary":"Get job status","description":"Returns the current status and metadata of a submitted job.","operationId":"get_job_api_PrimerServer2_jobs__job_id__get","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}},{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["PrimerServer2"],"summary":"Stop and delete a job","description":"Terminates the running process and removes the job working directory.","operationId":"delete_job_api_PrimerServer2_jobs__job_id__delete","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}},{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/PrimerServer2/jobs/{job_id}/progress":{"get":{"tags":["PrimerServer2"],"summary":"Get job progress","description":"Returns the completion percentage and current pipeline stage.","operationId":"get_progress_api_PrimerServer2_jobs__job_id__progress_get","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}},{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProgressResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/PrimerServer2/jobs/{job_id}/result":{"get":{"tags":["PrimerServer2"],"summary":"Get job result","description":"Returns the final result of a design or check job. Use job_type='design' or 'check'.","operationId":"get_result_api_PrimerServer2_jobs__job_id__result_get","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}},{"name":"job_type","in":"query","required":false,"schema":{"type":"string","default":"design","title":"Job Type"}},{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobResultResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/PrimerServer2/jobs/cleanup":{"post":{"tags":["PrimerServer2"],"summary":"Clean up old job directories","description":"Manually trigger cleanup of expired job directories according to retention policy.","operationId":"cleanup_jobs_api_PrimerServer2_jobs_cleanup_post","parameters":[{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/PrimerServer2/jobs/{job_id}/result-html":{"get":{"tags":["PrimerServer2"],"summary":"Get legacy HTML result","description":"Returns the raw legacy HTML result page if it was generated by the pipeline.","operationId":"get_result_html_api_PrimerServer2_jobs__job_id__result_html_get","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}},{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/PrimerServer2/jobs/{job_id}/specificity/{filename}":{"get":{"tags":["PrimerServer2"],"summary":"Download a specificity result file","description":"Downloads a file from the job's specificity-check result directory (e.g. alignment images).","operationId":"get_specificity_result_api_PrimerServer2_jobs__job_id__specificity__filename__get","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}},{"name":"filename","in":"path","required":true,"schema":{"type":"string","title":"Filename"}},{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/about":{"get":{"summary":"Root","description":"Return basic application information.\n\nPurpose:\n    Return the WheatOmics API name, version, interactive documentation URL and API prefix.\n\nUsage:\n    GET /api/about\n    No parameters; returns the application metadata JSON directly.\n\nExample:\n    Request:\n      curl -X GET \"http://localhost:8000/api/about\"\n\n    Response:\n      {\n        \"name\": \"WheatOmics\",\n        \"version\": \"1.0.0\",\n        \"docs\": \"/api/docs\",\n        \"api_prefix\": \"/api\",\n        \"server_time\": \"2025-06-18T10:30:00+00:00\",\n        \"client_ip\": \"192.168.1.1\"\n      }","operationId":"root_api_about_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Root Api About Get"}}}}}}},"/api/health":{"get":{"summary":"Health","description":"Service health check.\n\nPurpose:\n    Return the service status for liveness probes and monitoring.\n\nUsage:\n    GET /api/health\n    No parameters; returns the status information directly.\n\nExample:\n    Request:\n      curl -X GET \"http://localhost:8000/api/health\"\n\n    Response:\n      { \"status\": \"Wheatomics API running, ...\" }","operationId":"health_api_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Health Api Health Get"}}}}}}},"/api/webhook/gitee":{"post":{"summary":"Gitee Webhook","description":"Handle a Gitee webhook push.\n\nAfter validating the X-Gitee-Token header, run git pull as a background\ntask and return immediately so the Gitee request does not time out.","operationId":"gitee_webhook_api_webhook_gitee_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}}},"components":{"schemas":{"AmpliconDetail":{"properties":{"chrom":{"type":"string","title":"Chrom","description":"Target sequence the amplicon sits on."},"start":{"type":"integer","title":"Start","description":"Amplicon start (1-based, on chrom)."},"end":{"type":"integer","title":"End","description":"Amplicon end (1-based, on chrom)."},"size":{"type":"integer","title":"Size","description":"Amplicon length in bp."}},"type":"object","required":["chrom","start","end","size"],"title":"AmpliconDetail","description":"One candidate amplicon: where it sits on the target and how long it is."},"Body_blast_search_api_blast_search_post":{"properties":{"program":{"type":"string","title":"Program","description":"blastp (protein→protein DB) / blastn (nucleotide→nucleotide DB) / blastx (translated nucleotide→protein DB) / tblastn (protein→translated nucleotide DB) / tblastx (translated nucleotide→translated nucleotide DB)","default":"blastp"},"database":{"type":"string","title":"Database","description":"Database name(s), comma-separated, e.g. Fielder_protein,AK58_protein.fasta"},"query":{"type":"string","title":"Query","description":"Query sequence in FASTA format"},"evalue":{"type":"number","maximum":1000.0,"minimum":0.0,"title":"Evalue","description":"E-value threshold (0-1000)","default":10.0},"max_target_seqs":{"type":"integer","maximum":50000.0,"minimum":1.0,"title":"Max Target Seqs","description":"Maximum number of hits to return (1-50000)","default":1000},"word_size":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Word Size"},"matrix":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Matrix"},"outfmt":{"type":"string","title":"Outfmt","description":"Result format: tabular (default, outfmt 6, includes ppos/btop columns) / traditional (outfmt 0 pairwise alignments) / both (generate both)","default":"tabular"},"wait":{"type":"boolean","title":"Wait","description":"true=wait for completion (default, backward-compatible for existing callers); false=return job_id immediately and poll /api/blast/status/{job_id}","default":true}},"type":"object","required":["database","query"],"title":"Body_blast_search_api_blast_search_post"},"CapsDesignRequest":{"properties":{"seq1":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Seq1"},"seq2":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Seq2"},"db":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Db"},"region":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Region"},"pos":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Pos"},"allele1":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Allele1"},"allele2":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Allele2"},"vcf_dataset":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Vcf Dataset"},"chrom":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Chrom"},"enzymes":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Enzymes","description":"Subset of enzyme names; null = all built-in enzymes"},"custom_enzymes":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Custom Enzymes","description":"Custom enzymes [{'name','recognition','cut':[l,r]}]"},"mismatch_max":{"type":"integer","maximum":3.0,"minimum":0.0,"title":"Mismatch Max","default":1},"primer_len":{"prefixItems":[{"type":"integer"},{"type":"integer"}],"type":"array","maxItems":2,"minItems":2,"title":"Primer Len","default":[20,27]},"tm_range":{"prefixItems":[{"type":"number"},{"type":"number"}],"type":"array","maxItems":2,"minItems":2,"title":"Tm Range","default":[55.0,65.0]},"product_size":{"prefixItems":[{"type":"integer"},{"type":"integer"}],"type":"array","maxItems":2,"minItems":2,"title":"Product Size","default":[100,1000]},"flank":{"type":"integer","maximum":2000.0,"minimum":60.0,"title":"Flank","description":"How many bp to take on each side of the SNP in coordinate/VCF mode","default":250},"top_n":{"type":"integer","maximum":100.0,"minimum":1.0,"title":"Top N","default":20}},"type":"object","title":"CapsDesignRequest"},"CheckJobRequest":{"properties":{"size_start":{"type":"integer","maximum":100000.0,"minimum":1.0,"title":"Size Start","description":"Minimum allowed amplicon size (bp) during specificity checking.","default":50},"size_stop":{"type":"integer","maximum":1000000.0,"minimum":1.0,"title":"Size Stop","description":"Maximum allowed amplicon size (bp) during specificity checking.","default":2000},"min_Tm_diff":{"type":"integer","maximum":100.0,"minimum":0.0,"title":"Min Tm Diff","description":"Minimum Tm difference (°C) required to keep a non-specific amplicon.","default":10},"retain":{"type":"integer","maximum":1000.0,"minimum":1.0,"title":"Retain","description":"Maximum number of primer pairs to return per site.","default":10},"end3_mismatch_threshold":{"type":"integer","maximum":5.0,"minimum":0.0,"title":"End3 Mismatch Threshold","description":"Maximum mismatches allowed in the last 5 bp of the 3' end. 5 is the window size, so passing 5 turns the check off.","default":3},"max_report_amplicon":{"type":"integer","maximum":10000.0,"minimum":1.0,"title":"Max Report Amplicon","description":"Maximum number of amplicons reported per primer pair in specificity check.","default":50},"blast_e_value":{"type":"integer","minimum":1.0,"title":"Blast E Value","description":"BLAST e-value threshold for primer-to-database alignment.","default":30000},"blast_word_size":{"type":"integer","maximum":11.0,"minimum":4.0,"title":"Blast Word Size","description":"BLAST word size for short primer sequences.","default":7},"blast_identity":{"type":"integer","maximum":100.0,"minimum":0.0,"title":"Blast Identity","description":"Minimum BLAST identity (%) for a primer hit to be considered.","default":60},"blast_max_hsps":{"type":"integer","minimum":1.0,"title":"Blast Max Hsps","description":"Maximum BLAST HSPs retained per primer query.","default":500},"conc_primer":{"type":"number","minimum":0.0,"title":"Conc Primer","description":"Primer concentration (nM).","default":100.0},"conc_dNTPs":{"type":"number","minimum":0.0,"title":"Conc Dntps","description":"dNTP concentration (mM).","default":0.2},"conc_Na":{"type":"number","minimum":0.0,"title":"Conc Na","description":"Sodium ion concentration (mM).","default":0.0},"conc_K":{"type":"number","minimum":0.0,"title":"Conc K","description":"Potassium ion concentration (mM).","default":50.0},"conc_Tris":{"type":"number","minimum":0.0,"title":"Conc Tris","description":"Tris buffer concentration (mM).","default":10.0},"conc_Mg":{"type":"number","minimum":0.0,"title":"Conc Mg","description":"Magnesium ion concentration (mM).","default":1.5},"selected-databases":{"items":{"type":"string"},"type":"array","title":"Selected-Databases","description":"List of database file names to check specificity against. Use 'custom' together with customDbSequences for a custom FASTA database. Default: ['AABBDD_Chinese_Spring2.1.genome'] (Chinese Spring v2.1 reference genome).","default":["AABBDD_Chinese_Spring2.1.genome"]},"custom-db-sequences":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Custom-Db-Sequences","description":"Custom database sequences in FASTA format. Only used when 'custom' is in selectedDatabases."},"app-type":{"$ref":"#/components/schemas/JobType","description":"Must be 'check'."},"check-primers":{"type":"string","title":"Check-Primers","description":"One primer group per line: PrimerID LeftSeq RightSeq [AdditionalSeq ...]. A numeric rank may follow PrimerID — the 'Site_ID Rank Seq1 Seq2' shape the design stage emits — in which case the rank is used instead of 0."}},"type":"object","required":["app-type","check-primers"],"title":"CheckJobRequest","description":"Request body for submitting a primer specificity-check-only job.","example":{"app-type":"check","blast_e_value":30000,"blast_identity":60,"blast_word_size":7,"check-primers":"Primer1 TTCGATGCTGAGGAAGGCTG AGGAGAGAACGGAGACGAAG\nPrimer2 AGGAGAGAACGGAGACGAAG TTCGATGCTGAGGAAGGCTG","end3_mismatch_threshold":3,"min_Tm_diff":10,"retain":10,"selected-databases":["AABBDD_Chinese_Spring2.1.genome"],"size_start":50,"size_stop":2000}},"CheckResult":{"properties":{"siteId":{"type":"string","title":"Siteid","description":"Primer group identifier."},"rank":{"type":"integer","title":"Rank","description":"Primer pair rank (1-based)."},"database":{"type":"string","title":"Database","description":"Database name used for the check."},"ampliconNumber":{"type":"integer","title":"Ampliconnumber","description":"Total number of amplicons found."},"ampliconsCapped":{"type":"boolean","title":"Ampliconscapped","description":"True when ampliconNumber stopped at max_report_amplicon and more amplicons exist — display it as 'N+' rather than N.","default":false},"primerSeqs":{"items":{"type":"string"},"type":"array","title":"Primerseqs","description":"Input primer sequences."},"sizes":{"items":{"type":"integer"},"type":"array","title":"Sizes","description":"Amplicon sizes in bp, in the order the amplicons were found. Capped at max_report_amplicon."},"amplicons":{"items":{"$ref":"#/components/schemas/AmpliconDetail"},"type":"array","title":"Amplicons","description":"Where each amplicon sits. Empty when a job predates the amplicon file being kept, so treat it as best-effort."}},"type":"object","required":["siteId","rank","database","ampliconNumber","primerSeqs"],"title":"CheckResult","description":"Specificity-check result for one primer group against one database."},"ConfigResponse":{"properties":{"limitSite":{"type":"integer","title":"Limitsite"},"limitPrimer":{"type":"integer","title":"Limitprimer"},"limitDatabase":{"type":"integer","title":"Limitdatabase"},"useCPU":{"type":"integer","title":"Usecpu"},"showInfo":{"type":"boolean","title":"Showinfo"},"removeTmp":{"type":"boolean","title":"Removetmp"}},"type":"object","required":["limitSite","limitPrimer","limitDatabase","useCPU","showInfo","removeTmp"],"title":"ConfigResponse"},"DatabaseGroup":{"properties":{"name":{"type":"string","title":"Name"},"databases":{"additionalProperties":{"type":"string"},"type":"object","title":"Databases"},"examples":{"additionalProperties":{"items":{"type":"string"},"type":"array"},"type":"object","title":"Examples","default":{}}},"type":"object","required":["name","databases"],"title":"DatabaseGroup"},"DatabasesResponse":{"properties":{"groups":{"items":{"$ref":"#/components/schemas/DatabaseGroup"},"type":"array","title":"Groups"}},"type":"object","required":["groups"],"title":"DatabasesResponse"},"DesignJobRequest":{"properties":{"size_start":{"type":"integer","maximum":100000.0,"minimum":1.0,"title":"Size Start","description":"Minimum allowed amplicon size (bp) during specificity checking.","default":50},"size_stop":{"type":"integer","maximum":1000000.0,"minimum":1.0,"title":"Size Stop","description":"Maximum allowed amplicon size (bp) during specificity checking.","default":2000},"min_Tm_diff":{"type":"integer","maximum":100.0,"minimum":0.0,"title":"Min Tm Diff","description":"Minimum Tm difference (°C) required to keep a non-specific amplicon.","default":10},"retain":{"type":"integer","maximum":1000.0,"minimum":1.0,"title":"Retain","description":"Maximum number of primer pairs to return per site.","default":10},"end3_mismatch_threshold":{"type":"integer","maximum":5.0,"minimum":0.0,"title":"End3 Mismatch Threshold","description":"Maximum mismatches allowed in the last 5 bp of the 3' end. 5 is the window size, so passing 5 turns the check off.","default":3},"max_report_amplicon":{"type":"integer","maximum":10000.0,"minimum":1.0,"title":"Max Report Amplicon","description":"Maximum number of amplicons reported per primer pair in specificity check.","default":50},"blast_e_value":{"type":"integer","minimum":1.0,"title":"Blast E Value","description":"BLAST e-value threshold for primer-to-database alignment.","default":30000},"blast_word_size":{"type":"integer","maximum":11.0,"minimum":4.0,"title":"Blast Word Size","description":"BLAST word size for short primer sequences.","default":7},"blast_identity":{"type":"integer","maximum":100.0,"minimum":0.0,"title":"Blast Identity","description":"Minimum BLAST identity (%) for a primer hit to be considered.","default":60},"blast_max_hsps":{"type":"integer","minimum":1.0,"title":"Blast Max Hsps","description":"Maximum BLAST HSPs retained per primer query.","default":500},"conc_primer":{"type":"number","minimum":0.0,"title":"Conc Primer","description":"Primer concentration (nM).","default":100.0},"conc_dNTPs":{"type":"number","minimum":0.0,"title":"Conc Dntps","description":"dNTP concentration (mM).","default":0.2},"conc_Na":{"type":"number","minimum":0.0,"title":"Conc Na","description":"Sodium ion concentration (mM).","default":0.0},"conc_K":{"type":"number","minimum":0.0,"title":"Conc K","description":"Potassium ion concentration (mM).","default":50.0},"conc_Tris":{"type":"number","minimum":0.0,"title":"Conc Tris","description":"Tris buffer concentration (mM).","default":10.0},"conc_Mg":{"type":"number","minimum":0.0,"title":"Conc Mg","description":"Magnesium ion concentration (mM).","default":1.5},"selected-databases":{"items":{"type":"string"},"type":"array","title":"Selected-Databases","description":"List of database file names to check specificity against. Use 'custom' together with customDbSequences for a custom FASTA database. Default: ['AABBDD_Chinese_Spring2.1.genome'] (Chinese Spring v2.1 reference genome).","default":["AABBDD_Chinese_Spring2.1.genome"]},"custom-db-sequences":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Custom-Db-Sequences","description":"Custom database sequences in FASTA format. Only used when 'custom' is in selectedDatabases."},"app-type":{"$ref":"#/components/schemas/JobType","description":"Must be 'design'."},"selectTemplate":{"type":"string","title":"Selecttemplate","description":"Template database name (e.g. 'AABBDD_Chinese_Spring2.1.genome') or 'custom'. Backend validates the database exists; returns 422 + available list if not. For custom templates, keep FASTA IDs simple (letters, digits, underscore only, avoid ':', '-', spaces)."},"template-regions":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Template-Regions","description":"One region per line: TemplateID TargetPos TargetLength [ProductSizeMin] [ProductSizeMax]. Required unless selectTemplate is 'custom'."},"custom-template-sequences":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Custom-Template-Sequences","description":"Template sequences in FASTA format. Required when selectTemplate is 'custom'."},"region_type":{"$ref":"#/components/schemas/RegionType","description":"How to interpret the target region.","default":"SEQUENCE_TARGET"},"product_size_min":{"type":"integer","maximum":50000.0,"minimum":30.0,"title":"Product Size Min","description":"Minimum desired product size (bp).","default":100},"product_size_max":{"type":"integer","maximum":50000.0,"minimum":30.0,"title":"Product Size Max","description":"Maximum desired product size (bp).","default":1000},"PRIMER_MIN_SIZE":{"type":"integer","maximum":35.0,"minimum":1.0,"title":"Primer Min Size","description":"Minimum primer length (bp).","default":18},"PRIMER_OPT_SIZE":{"type":"integer","maximum":35.0,"minimum":1.0,"title":"Primer Opt Size","description":"Optimal primer length (bp).","default":20},"PRIMER_MAX_SIZE":{"type":"integer","maximum":35.0,"minimum":1.0,"title":"Primer Max Size","description":"Maximum primer length (bp).","default":23},"PRIMER_MIN_GC":{"type":"number","maximum":100.0,"minimum":0.0,"title":"Primer Min Gc","description":"Minimum GC content (%).","default":35.0},"PRIMER_OPT_GC_PERCENT":{"type":"number","maximum":100.0,"minimum":0.0,"title":"Primer Opt Gc Percent","description":"Optimal GC content (%).","default":50.0},"PRIMER_MAX_GC":{"type":"number","maximum":100.0,"minimum":0.0,"title":"Primer Max Gc","description":"Maximum GC content (%).","default":65.0},"PRIMER_MIN_TM":{"type":"number","maximum":100.0,"minimum":0.0,"title":"Primer Min Tm","description":"Minimum melting temperature (°C).","default":57.0},"PRIMER_OPT_TM":{"type":"number","maximum":100.0,"minimum":0.0,"title":"Primer Opt Tm","description":"Optimal melting temperature (°C).","default":60.0},"PRIMER_MAX_TM":{"type":"number","maximum":100.0,"minimum":0.0,"title":"Primer Max Tm","description":"Maximum melting temperature (°C).","default":63.0},"PRIMER_PAIR_MAX_DIFF_TM":{"type":"number","minimum":0.0,"title":"Primer Pair Max Diff Tm","description":"Maximum Tm difference between left and right primers (°C).","default":3.0},"PRIMER_NUM_RETURN":{"type":"integer","maximum":1000.0,"minimum":1.0,"title":"Primer Num Return","description":"Number of candidate primer pairs designed by Primer3 per site.","default":30},"PRIMER_MIN_LEFT_THREE_PRIME_DISTANCE":{"type":"integer","maximum":10.0,"minimum":-1.0,"title":"Primer Min Left Three Prime Distance","description":"Primer3 LEFT_THREE_PRIME_DISTANCE.","default":3},"PRIMER_MIN_RIGHT_THREE_PRIME_DISTANCE":{"type":"integer","maximum":10.0,"minimum":-1.0,"title":"Primer Min Right Three Prime Distance","description":"Primer3 RIGHT_THREE_PRIME_DISTANCE.","default":3},"PRIMER_MAX_END_STABILITY":{"type":"number","minimum":0.0,"title":"Primer Max End Stability","description":"Maximum 3' end stability.","default":9.0},"PRIMER_LOWERCASE_MASKING":{"type":"integer","maximum":1.0,"minimum":0.0,"title":"Primer Lowercase Masking","description":"Treat lowercase sequence as masked (0=no, 1=yes).","default":0},"PRIMER_MAX_SELF_ANY_TH":{"type":"number","minimum":0.0,"title":"Primer Max Self Any Th","description":"Maximum self-complementarity (any).","default":45.0},"PRIMER_PAIR_MAX_COMPL_ANY_TH":{"type":"number","minimum":0.0,"title":"Primer Pair Max Compl Any Th","description":"Maximum pair complementarity (any).","default":45.0},"PRIMER_MAX_SELF_END_TH":{"type":"number","minimum":0.0,"title":"Primer Max Self End Th","description":"Maximum self-complementarity at 3' end.","default":35.0},"PRIMER_PAIR_MAX_COMPL_END_TH":{"type":"number","minimum":0.0,"title":"Primer Pair Max Compl End Th","description":"Maximum pair complementarity at 3' end.","default":35.0},"PRIMER_MAX_HAIRPIN_TH":{"type":"number","minimum":0.0,"title":"Primer Max Hairpin Th","description":"Maximum hairpin stability.","default":24.0}},"type":"object","required":["app-type","selectTemplate"],"title":"DesignJobRequest","description":"Request body for submitting a primer design & specificity-check job.","example":{"PRIMER_MAX_SIZE":23,"PRIMER_MAX_TM":63,"PRIMER_MIN_SIZE":18,"PRIMER_MIN_TM":57,"PRIMER_NUM_RETURN":30,"PRIMER_OPT_SIZE":20,"PRIMER_OPT_TM":60,"app-type":"design","blast_e_value":30000,"blast_identity":60,"blast_word_size":7,"end3_mismatch_threshold":3,"min_Tm_diff":10,"product_size_max":800,"product_size_min":150,"region_type":"SEQUENCE_TARGET","retain":10,"selectTemplate":"AABBDD_Chinese_Spring2.1.genome","selected-databases":["AABBDD_Chinese_Spring2.1.genome"],"size_start":50,"size_stop":2000,"template-regions":"chr1A 100000 200\nchr1B 200000 300 150 800"}},"EnrichmentRequest":{"properties":{"genes":{"items":{"type":"string"},"type":"array","title":"Genes"},"padj_threshold":{"type":"number","title":"Padj Threshold","default":0.05}},"type":"object","required":["genes"],"title":"EnrichmentRequest","example":{"genes":["TraesCS1A02G045300.1","TraesCS1A02G104700.1","TraesCS1A02G118400.1"],"padj_threshold":0.05}},"EnrichmentResponse":{"properties":{"N":{"type":"integer","title":"N"},"n":{"type":"integer","title":"N"},"results":{"items":{"$ref":"#/components/schemas/EnrichmentResult"},"type":"array","title":"Results"},"gene_count":{"type":"integer","title":"Gene Count"}},"type":"object","required":["N","n","results","gene_count"],"title":"EnrichmentResponse","example":{"N":73626,"gene_count":3,"n":3,"results":[{"K":4,"id":"GO:0043425","k":1,"ontology":"molecular_function","padj":0.009779,"pvalue":0.000162,"ratio":6135.5,"term":"bHLH transcription factor binding"}]}},"EnrichmentResult":{"properties":{"id":{"type":"string","title":"Id"},"term":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Term","default":""},"ontology":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ontology","default":""},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name","default":""},"k":{"type":"integer","title":"K"},"K":{"type":"integer","title":"K"},"ratio":{"type":"number","title":"Ratio"},"pvalue":{"type":"number","title":"Pvalue"},"padj":{"type":"number","title":"Padj"}},"type":"object","required":["id","k","K","ratio","pvalue","padj"],"title":"EnrichmentResult"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"JobResponse":{"properties":{"jobId":{"type":"string","title":"Jobid","description":"Unique job identifier (UUID)."},"status":{"$ref":"#/components/schemas/JobStatus","description":"Current job status."},"createdAt":{"type":"string","title":"Createdat","description":"ISO 8601 timestamp when the job was created."},"message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Message","description":"Human-readable status message."}},"type":"object","required":["jobId","status","createdAt"],"title":"JobResponse","description":"Response returned when a job is created or queried by ID."},"JobResultResponse":{"properties":{"jobId":{"type":"string","title":"Jobid","description":"Unique job identifier."},"jobType":{"type":"string","title":"Jobtype","description":"'design' or 'check'."},"status":{"$ref":"#/components/schemas/JobStatus","description":"Final job status."},"html":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Html","description":"URL/path to legacy HTML result when available."},"designPrimers":{"anyOf":[{"items":{"$ref":"#/components/schemas/PrimerResult"},"type":"array"},{"type":"null"}],"title":"Designprimers","description":"Designed primer pairs (design jobs)."},"checkResults":{"anyOf":[{"items":{"$ref":"#/components/schemas/CheckResult"},"type":"array"},{"type":"null"}],"title":"Checkresults","description":"Specificity check summaries (check jobs)."},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error","description":"Error message if the job failed."}},"type":"object","required":["jobId","jobType","status"],"title":"JobResultResponse","description":"Final result of a primer design or specificity-check job."},"JobStatus":{"type":"string","enum":["pending","running","done","error","stopped"],"title":"JobStatus"},"JobType":{"type":"string","enum":["design","check"],"title":"JobType"},"PrimerResult":{"properties":{"siteId":{"type":"string","title":"Siteid","description":"Input site / primer group identifier."},"rank":{"type":"integer","title":"Rank","description":"Final rank after specificity filtering (1-based)."},"leftSeq":{"type":"string","title":"Leftseq","description":"Left primer sequence (5' -> 3')."},"rightSeq":{"type":"string","title":"Rightseq","description":"Right primer sequence (5' -> 3')."},"productSize":{"type":"integer","title":"Productsize","description":"Expected PCR product size (bp)."},"penalty":{"type":"number","title":"Penalty","description":"Primer3 penalty score (lower is better)."},"leftTm":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Lefttm","description":"Left primer melting temperature (°C)."},"rightTm":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Righttm","description":"Right primer melting temperature (°C)."},"leftGc":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Leftgc","description":"Left primer GC content (%)."},"rightGc":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Rightgc","description":"Right primer GC content (%)."},"leftPos":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Leftpos","description":"Left primer alignment position, e.g. 'chr1A:100025-100042 (+)'."},"rightPos":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rightpos","description":"Right primer alignment position, e.g. 'chr1A:100824-100841 (-)'."},"leftLen":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Leftlen","description":"Left primer length (bp)."},"rightLen":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Rightlen","description":"Right primer length (bp)."},"leftSelfAny":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Leftselfany","description":"Left primer self-complementarity (any)."},"rightSelfAny":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Rightselfany","description":"Right primer self-complementarity (any)."},"leftSelfEnd":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Leftselfend","description":"Left primer self-complementarity at 3' end."},"rightSelfEnd":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Rightselfend","description":"Right primer self-complementarity at 3' end."},"leftHairpin":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Lefthairpin","description":"Left primer hairpin stability."},"rightHairpin":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Righthairpin","description":"Right primer hairpin stability."},"leftEndStability":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Leftendstability","description":"Left primer 3' end stability."},"rightEndStability":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Rightendstability","description":"Right primer 3' end stability."},"pairComplAny":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Paircomplany","description":"Pair complementarity (any)."},"pairComplEnd":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Paircomplend","description":"Pair complementarity at 3' end."},"primer3Rank":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Primer3Rank","description":"Original Primer3 rank before specificity filtering."},"databases":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Databases","description":"Specificity-check results per database (amplicons, alignments, etc.)."}},"type":"object","required":["siteId","rank","leftSeq","rightSeq","productSize","penalty","databases"],"title":"PrimerResult","description":"A single designed primer pair with thermodynamic and specificity details."},"ProgressResponse":{"properties":{"total":{"type":"integer","title":"Total","description":"Total number of work units."},"finished":{"type":"integer","title":"Finished","description":"Number of completed work units."},"percent":{"type":"integer","title":"Percent","description":"Completion percentage (0-100)."},"stage":{"type":"string","title":"Stage","description":"Current pipeline stage description."}},"type":"object","required":["total","finished","percent","stage"],"title":"ProgressResponse","description":"Progress information for a running or finished job."},"RegionType":{"type":"string","enum":["SEQUENCE_TARGET","SEQUENCE_INCLUDED_REGION","FORCE_END"],"title":"RegionType"},"SequenceBundle":{"properties":{"gene_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Gene Id"},"genome_sequence":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Genome Sequence"},"gene_sequence":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Gene Sequence"},"protein_sequence":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Protein Sequence"},"additional_sequences":{"items":{"$ref":"#/components/schemas/SequenceRecord"},"type":"array","title":"Additional Sequences"}},"type":"object","title":"SequenceBundle","description":"Bundled sequences for a gene or interval."},"SequenceRecord":{"properties":{"sequence_id":{"type":"string","title":"Sequence Id"},"fasta":{"type":"string","title":"Fasta"}},"type":"object","required":["sequence_id","fasta"],"title":"SequenceRecord","description":"Named sequence payload."},"ServerInfoResponse":{"properties":{"currentTime":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Currenttime"},"cpuInfo":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cpuinfo"},"memTotal":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Memtotal"},"memFree":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Memfree"},"samtoolsVersion":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Samtoolsversion"},"blastnVersion":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Blastnversion"},"primer3Version":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Primer3Version"}},"type":"object","title":"ServerInfoResponse"},"TrackPayload":{"properties":{"page":{"type":"string","title":"Page","default":"unknown"}},"type":"object","title":"TrackPayload"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}},"tags":[{"name":"PrimerServer2","description":"Primer design, version 2"},{"name":"OrthoFinder","description":"OrthoFinder orthogroup browser and search"}]}