{"openapi":"3.1.0","info":{"title":"SeqBench API","version":"1.1.0","summary":"REST API for DNA, RNA and protein sequence analysis, molecular cloning, primer design and CRISPR guide design.","description":"The SeqBench REST API exposes every SeqBench tool as a stateless JSON endpoint: primer design and melting-temperature (Tm) calculation, in-silico PCR, cloning simulation (Gibson Assembly, Golden Gate Assembly, restriction digest), CRISPR guide RNA (gRNA) design, ORF finding, restriction-site mapping, codon optimization, sequence alignment and more.\n\nEvery tool is callable at `POST /{tool}` with a JSON body matching that tool's input schema. `GET /` lists all tools and their schemas. `POST /batch` runs one tool over a whole multi-FASTA file, and `POST /workflow` chains several tools into a pipeline over every record.\n\nResponses share a common envelope: `{ ok, tool, result, gate, provenance }`. The optional `gate` reports typed pass/fail QC checks plus an honest `notChecked` list of what it does not verify.\n\nNo authentication or API key is required. CORS is open. The same tools are also available over the Model Context Protocol (MCP) at `https://seqbench.com/api/mcp` for AI agents.","contact":{"name":"SeqBench","url":"https://seqbench.com","email":"seqbench.bio@gmail.com"},"license":{"name":"Free to use","url":"https://seqbench.com/terms"}},"externalDocs":{"description":"SeqBench API & MCP documentation","url":"https://seqbench.com/mcp"},"servers":[{"url":"https://seqbench.com/api/v1","description":"Production"}],"security":[{}],"tags":[{"name":"Index","description":"Discovery — list tools and their schemas."},{"name":"Batch & workflow","description":"Run one tool over many records, or chain tools into a pipeline."},{"name":"Sequence","description":"Reverse complement, GC content, formatting and core sequence utilities."},{"name":"Translation & ORFs","description":"Translate DNA/RNA, find open reading frames, reverse-translate."},{"name":"Primers & oligos","description":"Primer and oligo design, melting temperature, in-silico PCR, dimers."},{"name":"Enzymes & cloning","description":"Restriction sites and digests, Gibson / Golden Gate / restriction cloning, virtual gel."},{"name":"Analysis","description":"Sequence search, reporting and higher-level analysis."},{"name":"Alignment & variants","description":"Pairwise and multiple sequence alignment, variant comparison."},{"name":"Files & formats","description":"Parse and convert FASTA, GenBank, Sanger traces and sequence files."},{"name":"Proteins & peptides","description":"Protein properties, hydrophobicity, protease digestion, annotation."},{"name":"Codon usage","description":"Codon optimization and codon adaptation index (CAI)."},{"name":"CRISPR","description":"Guide RNA (gRNA) design, off-target checks, HDR donor design."}],"paths":{"/":{"get":{"tags":["Index"],"operationId":"listTools","summary":"List all tools and their input schemas","description":"Returns the API version, documentation links, and every tool with its endpoint, category, and JSON-Schema input.","responses":{"200":{"description":"The API index.","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/reverse_complement":{"post":{"tags":["Sequence"],"operationId":"reverse_complement","summary":"Reverse Complement","description":"Reverse, complement and reverse complement of a DNA or RNA sequence.\n\nBatchable via `POST /batch`.\n\nChainable in workflows (passes its `reverseComplement` field to the next step).","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"sequence":{"type":"string","residues":"nt","description":"Nucleotide sequence (raw or FASTA; IUPAC accepted)."},"type":{"type":"string","enum":["dna","rna"],"default":"dna"}},"required":["sequence"],"additionalProperties":false},"example":{"sequence":"ATGGCCTGA","type":"dna"}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gc_content":{"post":{"tags":["Sequence"],"operationId":"gc_content","summary":"GC Content","description":"GC content, AT content and per-base composition of a sequence.\n\nBatchable via `POST /batch`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"sequence":{"type":"string","residues":"nt","description":"Nucleotide sequence (raw or FASTA; IUPAC accepted)."}},"required":["sequence"],"additionalProperties":false},"example":{"sequence":"ATGGCGCGCTAA"}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/translate":{"post":{"tags":["Translation & ORFs"],"operationId":"translate","summary":"Translate","description":"Translate a nucleotide sequence to protein (single frame or all six frames; standard code).\n\nBatchable via `POST /batch`.\n\nChainable in workflows (passes its `protein` field to the next step).","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"sequence":{"type":"string","residues":"nt","description":"Nucleotide sequence (raw or FASTA; IUPAC accepted)."},"frame":{"type":"integer","enum":[1,2,3],"default":1},"toStop":{"type":"boolean","default":false,"description":"Stop at the first stop codon."}},"required":["sequence"],"additionalProperties":false},"example":{"sequence":"ATGGCCTGA","frame":1}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/find_orfs":{"post":{"tags":["Translation & ORFs"],"operationId":"find_orfs","summary":"ORF Finder","description":"Find open reading frames (ATG…stop) across all six frames.\n\nBatchable via `POST /batch`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"sequence":{"type":"string","residues":"nt","description":"Nucleotide sequence (raw or FASTA; IUPAC accepted)."},"minAaLength":{"type":"integer","default":30,"description":"Minimum protein length (aa) to report."},"requireStop":{"type":"boolean","default":false,"description":"Only report ORFs terminated by a stop codon."},"limit":{"type":"integer","default":100,"minimum":1,"maximum":5000,"description":"How many ORFs to return, longest first. `count` always reports every ORF found and `truncated` says whether the list was cut."}},"required":["sequence"],"additionalProperties":false},"example":{"sequence":"ATGGCCAAGTTGACCAGTGCCGTTCCGGTGCTCACCGCGTAA"}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/format_sequence":{"post":{"tags":["Sequence"],"operationId":"format_sequence","summary":"Format Sequence","description":"Clean, case-fold, DNA↔RNA convert, reverse and line-wrap a sequence.\n\nBatchable via `POST /batch`.\n\nChainable in workflows (passes its `sequence` field to the next step).","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"sequence":{"type":"string","residues":"nt","description":"Nucleotide sequence (raw or FASTA; IUPAC accepted)."},"stripNonLetters":{"type":"boolean","default":true,"description":"Remove digits, spaces and gaps (keep letters only)."},"caseMode":{"type":"string","enum":["keep","upper","lower"],"default":"keep"},"convert":{"type":"string","enum":["none","toRna","toDna"],"default":"none","description":"DNA→RNA (T→U) or RNA→DNA (U→T)."},"reverse":{"type":"boolean","default":false,"description":"Reverse the sequence (no complement)."},"width":{"type":"integer","default":60,"description":"Line-wrap width; 0 = single line."}},"required":["sequence"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/motif_finder":{"post":{"tags":["Sequence"],"operationId":"motif_finder","summary":"Motif Finder","description":"Find (overlapping) occurrences of an IUPAC motif on either strand, allowing mismatches.\n\nBatchable via `POST /batch`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"sequence":{"type":"string","residues":"nt","description":"Nucleotide sequence (raw or FASTA; IUPAC accepted)."},"motif":{"type":"string","residues":"nt","description":"Query motif; IUPAC ambiguity codes (R Y S W K M B D H V N) allowed."},"searchReverseStrand":{"type":"boolean","default":true,"description":"Also search the reverse strand."},"maxMismatches":{"type":"integer","default":0,"description":"Maximum allowed mismatches per match."},"limit":{"type":"integer","default":500,"minimum":1,"maximum":20000,"description":"How many matches to return. `count` always reports every hit found and `truncated` says whether the list was cut."}},"required":["sequence","motif"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/reverse_translate":{"post":{"tags":["Translation & ORFs"],"operationId":"reverse_translate","summary":"Reverse Translate","description":"Back-translate a protein to DNA (most-frequent codon per organism, or degenerate IUPAC consensus).\n\nBatchable via `POST /batch`.\n\nChainable in workflows (passes its `dna` field to the next step).","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"protein":{"type":"string","residues":"aa","description":"Protein sequence (one-letter codes; * for stop)."},"mode":{"type":"string","enum":["frequent","degenerate"],"default":"frequent"},"organism":{"type":"string","enum":["ecoli","human","yeast","cho","pichia","insect","arabidopsis","zebrafish"],"default":"ecoli","description":"Codon-usage host (ignored in degenerate mode)."}},"required":["protein"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/random_sequence":{"post":{"tags":["Sequence"],"operationId":"random_sequence","summary":"Random Sequence","description":"Generate a random DNA, RNA or protein sequence, optionally with a target GC content.\n\nNot a workflow step (it does not take a single sequence argument), but its `sequence` field is the sequence to carry into the next call yourself.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"kind":{"type":"string","enum":["dna","rna","protein"],"default":"dna"},"length":{"type":"integer","default":100,"description":"Number of residues to generate."},"gcContent":{"type":"number","description":"Target GC percentage 0..100 (dna/rna only); omit for uniform."}},"required":["length"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/melting_temperature":{"post":{"tags":["Primers & oligos"],"operationId":"melting_temperature","summary":"Primer Tm calculator","description":"Primer/oligo melting temperature: nearest-neighbor (SantaLucia 1998) at the supplied reaction conditions, recommended from 14 nt up, with the Wallace rule for shorter oligos, a fixed-100 mM-Na+ Schildkraut-Lifson reference estimate, and molecular weights.\n\nBatchable via `POST /batch`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"sequence":{"type":"string","residues":"nt","description":"Nucleotide sequence (raw or FASTA; IUPAC accepted)."},"oligoNM":{"type":"number","default":250,"description":"Total strand concentration (nM)."},"naMM":{"type":"number","default":50,"description":"Monovalent cation [Na+]/[K+] (mM)."},"mgMM":{"type":"number","default":1.5,"description":"Divalent cation [Mg2+] (mM)."},"dntpMM":{"type":"number","default":0.2,"description":"Total [dNTP] (mM), chelates Mg2+."},"targetTm":{"type":"number","description":"Optional target Tm (°C). When given, the response includes a pass/fail gate."},"tmTolerance":{"type":"number","default":2,"description":"Allowed +/- window (°C) around targetTm for the gate."}},"required":["sequence"],"additionalProperties":false},"example":{"sequence":"ACGGTCAGGTCAGTTACGGT","targetTm":60}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/oligo_analysis":{"post":{"tags":["Primers & oligos"],"operationId":"oligo_analysis","summary":"Oligo analyzer","description":"Full oligo analysis: nearest-neighbor Tm/ΔG/ΔH/ΔS plus hairpin and self-dimer screening with base-pair diagrams and warnings.\n\nBatchable via `POST /batch`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"sequence":{"type":"string","residues":"nt","description":"Nucleotide sequence (raw or FASTA; IUPAC accepted)."},"oligoNM":{"type":"number","default":250,"description":"Total strand concentration (nM)."},"naMM":{"type":"number","default":50,"description":"Monovalent cation [Na+]/[K+] (mM)."},"mgMM":{"type":"number","default":1.5,"description":"Divalent cation [Mg2+] (mM)."},"dntpMM":{"type":"number","default":0.2,"description":"Total [dNTP] (mM), chelates Mg2+."}},"required":["sequence"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/in_silico_pcr":{"post":{"tags":["Primers & oligos"],"operationId":"in_silico_pcr","summary":"In-silico PCR","description":"Predict PCR products for a template and a pair of primers (IUPAC-aware, allows mismatches, handles circular templates). Primers may carry a non-templated 5' tail — a restriction site, a Gibson arm, a Kozak, a tag: a primer primes on its 3' end, and the tail is carried into the product rather than required to match. start/end are the TEMPLATE-derived span, `length` is the whole product including tails, and `features` marks which product bases came from the oligos (present only when there is a tail). Each end reports annealedLength and tailLength.\n\nBatchable via `POST /batch`.\n\nChainable in workflows (passes its `amplicon` field to the next step).","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"template":{"type":"string","residues":"nt","description":"Nucleotide sequence (raw or FASTA; IUPAC accepted)."},"forwardPrimer":{"type":"string","residues":"nt","description":"Primer 1, 5'→3'."},"reversePrimer":{"type":"string","residues":"nt","description":"Primer 2, 5'→3' (order does not matter). Optional: one primer alone is accepted and reports the products it makes on its own — none, unless the template carries inverted sites it can prime from both ends."},"maxMismatches":{"type":"integer","default":0,"minimum":0,"maximum":10,"description":"Mismatches tolerated per primer (0–10)."},"maxProductLength":{"type":"integer","default":50000,"minimum":1,"maximum":500000,"description":"Ignore predicted products longer than this (bp). A SEARCH WINDOW, not a claim about what amplifies: whole-plasmid inverse PCR — the reaction a q5-style site_directed_mutagenesis design is run as — makes one product the size of the plasmid, so raise this for a construct over 50 kb. `suppressedByLength` in the response counts what the window discarded."},"circular":{"type":"boolean","default":false,"description":"Treat the template as circular (plasmid)."}},"required":["template"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/primer_design":{"post":{"tags":["Primers & oligos"],"operationId":"primer_design","summary":"Primer designer","description":"De-novo PCR primer design (Primer3-style penalty picker): enumerate and score candidate primer pairs against length/Tm/GC/3'-clamp/structure constraints.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"template":{"type":"string","residues":"nt","description":"Nucleotide sequence (raw or FASTA; IUPAC accepted)."},"lenMin":{"type":"integer","default":18},"lenOpt":{"type":"integer","default":20},"lenMax":{"type":"integer","default":25,"minimum":1,"maximum":100},"tmMin":{"type":"number","default":57},"tmOpt":{"type":"number","default":60},"tmMax":{"type":"number","default":63},"tmMaxDiff":{"type":"number","default":3,"description":"Max Tm difference within a pair (°C)."},"gcMin":{"type":"number","default":40},"gcMax":{"type":"number","default":60},"ampliconMin":{"type":"integer","default":100},"ampliconMax":{"type":"integer","default":1000},"targetStart":{"type":"integer","description":"1-based inclusive start of a region the product must span (optional)."},"targetEnd":{"type":"integer","description":"1-based inclusive end of the target region (optional)."},"maxReturn":{"type":"integer","default":5,"description":"Number of best pairs to return."},"maxPolyX":{"type":"integer","description":"Longest run of one base a primer may contain (Primer3's PRIMER_MAX_POLY_X). Omitted or 0 means no limit."},"gcClamp":{"type":"integer","description":"Consecutive G/C required at the very 3' end (Primer3's PRIMER_GC_CLAMP). Omitted or 0 means no requirement."},"minThreePrimeDG":{"type":"number","description":"Floor on the NN ΔG37 (kcal/mol) of the five 3'-most bases; a more stable end than this is rejected. Deliberately not Primer3's max_end_stability, which is a different scale this model has not been calibrated against."},"excludedRegions":{"type":"array","description":"Regions no primer may overlap, 1-based inclusive, as {start,end}. start > end is a region crossing the origin of a circular template.","items":{"type":"object","properties":{"start":{"type":"integer"},"end":{"type":"integer"}},"required":["start","end"]}},"oligoNM":{"type":"number","default":250,"description":"Total strand concentration (nM)."},"naMM":{"type":"number","default":50,"description":"Monovalent cation [Na+]/[K+] (mM)."},"mgMM":{"type":"number","default":1.5,"description":"Divalent cation [Mg2+] (mM)."},"dntpMM":{"type":"number","default":0.2,"description":"Total [dNTP] (mM), chelates Mg2+."}},"required":["template"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/dna_molarity":{"post":{"tags":["Primers & oligos"],"operationId":"dna_molarity","summary":"DNA molarity calculator","description":"Nucleic-acid quantity conversions: molar mass, amount (pmol/nmol), molar and mass concentration, and copy number, from mass ± volume and either a length or a sequence.\n\nBatchable via `POST /batch`.","requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string","enum":["dsDNA","ssDNA","ssRNA"],"default":"dsDNA","description":"Molecule type."},"length":{"type":"integer","default":1000,"description":"Length in bp (dsDNA) or nt (ssDNA/ssRNA). Ignored when a sequence is given."},"massNg":{"type":"number","default":100,"description":"Mass in nanograms."},"volumeUl":{"type":"number","default":0,"description":"Volume in microlitres (0 = unknown; needed for concentration)."},"sequence":{"type":"string","residues":"nt","description":"Optional sequence — overrides length and gives an exact molar mass from base composition."},"targetConcentration":{"type":"number","description":"Optional: the concentration you need. Supplying it (with volumeUl, so there is a stock concentration to dilute FROM) returns a `dilution` plan — µL of stock and µL of diluent — instead of leaving C1V1 = C2V2 to be done by hand. The stock and the target may be quoted in different units; the molar mass converts between them."},"targetUnit":{"type":"string","enum":["nM","uM","ngPerUl"],"default":"nM","description":"Unit for targetConcentration."},"targetVolumeUl":{"type":"number","default":20,"description":"Final volume of the diluted sample, in µL."}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/site_directed_mutagenesis":{"post":{"tags":["Primers & oligos"],"operationId":"site_directed_mutagenesis","summary":"Site-directed mutagenesis designer","description":"Design site-directed mutagenesis primers (QuikChange overlapping or Q5 back-to-back) for a base substitution, an amino-acid codon swap, or an insertion/deletion/delins. The edit can be given as fields or, more simply, by NAME in `mutation`: \"E52K\", \"p.Glu52Lys\", \"c.155A>G\", \"c.76_78del\", \"c.76_77insGGA\", \"c.76_78dup\". A named mutation is checked against the template — if the reference allele it states is not what is actually at that position, the call is refused and the real base or residue is quoted back, because a coordinate belonging to a different transcript or the other strand yields perfectly well-formed primers for the wrong base. `interpretedAs` in the response says which reading was designed.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"template":{"type":"string","residues":"nt","description":"Nucleotide sequence (raw or FASTA; IUPAC accepted)."},"mutation":{"type":"string","description":"The edit by name — \"E52K\", \"p.Glu52Lys\", \"Q100*\", \"c.155A>G\", \"A155G\", \"c.76_78del\", \"c.76_77insGGA\", \"c.76_78dup\", \"c.76delinsAA\". Replaces the field-by-field forms below. An unprefixed \"A123G\" is a legal reading at BOTH levels; it is resolved by which one matches the template, and refused if both do."},"editKind":{"type":"string","enum":["nt","aa","delins"],"description":"Edit level. Normally omitted — it is inferred from the fields you send (newBase means nt, targetAa means aa, insert/deleteLength means delins)."},"style":{"type":"string","enum":["quikchange","q5"],"default":"quikchange","description":"Mutagenic primer style."},"armTmTarget":{"type":"number","default":60,"description":"Target Tm (°C) for each template-binding arm."},"position":{"type":"integer","description":"1-based position to substitute (nt), or the first base of the span to replace (delins). Required for those forms — it is never assumed. For a pure insertion (deleteLength 0) it is the base the insert goes in FRONT of."},"newBase":{"type":"string","enum":["A","C","G","T"],"description":"Replacement base (nt edit)."},"deleteLength":{"type":"integer","description":"Template bases to remove, starting at `position` (delins edit). 0 with `insert` set is a pure insertion, placed immediately before `position`."},"insert":{"type":"string","residues":"nt","description":"Bases to put in place of the deleted span (delins edit). Omit for a pure deletion. NOTE the convention when deleteLength is 0: the insert lands immediately BEFORE `position`, so position 101 + insert \"GGA\" is the same edit as mutation: \"c.100_101insGGA\" — HGVS names the two flanking bases, this names the base the insert sits in front of. `interpretedAs` states which bases the insert ended up between."},"frameStart":{"type":"integer","default":1,"description":"1-based position of the first base of codon 1. Needed whenever the coding sequence does not start at base 1 of the template — a residue number means nothing without it."},"residue":{"type":"integer","description":"1-based residue number to change (aa edit)."},"targetAa":{"type":"string","description":"Target amino acid, one-letter code incl '*' (aa edit)."},"organism":{"type":"string","enum":["ecoli","human","yeast","cho","pichia","insect","arabidopsis","zebrafish"],"default":"ecoli","description":"Codon-usage table for choosing the new codon (aa edit). Latin names and common strain/cell-line names are accepted."},"oligoNM":{"type":"number","default":250,"description":"Total strand concentration (nM)."},"naMM":{"type":"number","default":50,"description":"Monovalent cation [Na+]/[K+] (mM)."},"mgMM":{"type":"number","default":1.5,"description":"Divalent cation [Mg2+] (mM)."},"dntpMM":{"type":"number","default":0.2,"description":"Total [dNTP] (mM), chelates Mg2+."}},"required":["template"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/oligo_pool_screen":{"post":{"tags":["Primers & oligos"],"operationId":"oligo_pool_screen","summary":"Oligo pool cross-dimer screen","description":"Screen a whole set of oligos you already have — every pair for cross-dimers, every oligo for its own hairpin and self-dimer, and the set for duplicates and Tm spread — and get back the conflicts ranked rather than a table of every combination. This is the pool-level answer cross_dimer gives one pair at a time: 51 primers is 1,275 pairs, which is 1,275 separate calls done by hand and one call done here. Not to be confused with multiplex_panel_design, which DESIGNS primers from templates; this takes the primers you have already ordered. A pairing that involves an oligo's 3' END is judged at a weaker ΔG than one that only pairs internally, because that end is where extension starts — the same two-bar rule the multiplex panel designer uses. Every number is a nearest-neighbor calculation over the sequences supplied, not a prediction of what the reaction will do.","requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"oligos":{"type":"array","description":"The pool, as objects with a name and a sequence. Up to 384. Use this or `fasta`, not both.","items":{"type":"object","properties":{"name":{"type":"string","description":"Label used throughout the result. Defaults to oligo_1, oligo_2, …"},"sequence":{"type":"string","description":"The oligo, 5'→3'."}},"required":["sequence"]}},"fasta":{"type":"string","residues":"nt","description":"The pool as a FASTA paste (headers become the names), or as one sequence per line — which is what comes out of a spreadsheet column. An alternative to `oligos`."},"threePrimeThresholdDG":{"type":"number","default":-6,"description":"ΔG (kcal/mol) at or below which a pairing that involves a 3' END counts as a conflict."},"internalThresholdDG":{"type":"number","default":-9,"description":"The looser bar for a pairing that only sequesters primer internally, away from either 3' end."},"maxConflicts":{"type":"integer","default":200,"description":"Conflict rows returned, most stable first. The COUNTS are always complete."},"oligoNM":{"type":"number","default":250,"description":"Total strand concentration (nM)."},"naMM":{"type":"number","default":50,"description":"Monovalent cation [Na+]/[K+] (mM)."},"mgMM":{"type":"number","default":1.5,"description":"Divalent cation [Mg2+] (mM)."},"dntpMM":{"type":"number","default":0.2,"description":"Total [dNTP] (mM), chelates Mg2+."}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/cross_dimer":{"post":{"tags":["Primers & oligos"],"operationId":"cross_dimer","summary":"Cross-Dimer","description":"Screen two oligos for the most stable heterodimer (cross-dimer) between them.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"sequenceA":{"type":"string","residues":"nt","description":"First oligo (5'→3')."},"sequenceB":{"type":"string","residues":"nt","description":"Second oligo (5'→3')."}},"required":["sequenceA","sequenceB"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/primer_specificity":{"post":{"tags":["Primers & oligos"],"operationId":"primer_specificity","summary":"Primer specificity screen","description":"Self-hosted e-PCR-style screen for off-target amplicons predicted by a primer pair against a small set of curated reference genomes (currently: E. coli K-12 MG1655, B. subtilis 168, human mitochondrion rCRS, Mycoplasma hyorhinis SK76 — see genomesChecked in the response for the exact list, and note that the nuclear human and mouse genomes are NOT covered). Amplicons are 1-based inclusive on the plus strand; a product across a circular genome's origin reports an end lower than its start and sets wraps: true. This checks background/host-genome specificity, NOT whether the primers hit your intended target — pair it with in_silico_pcr against your own template for that. Each off-target end reports its 3' ANCHOR — the primer's unbroken run of matched bases at the extending end — with that anchor's nearest-neighbor ΔG and a margin against the intended, fully matched reaction, so a site can be told apart by WHERE its mismatches fall rather than only how many there are: one mismatch at the 5' end leaves a site nearly as strong, and one at the 3' base leaves it unable to prime at all. Batchable over candidate REVERSE primers against one fixed forward primer (screen many candidates against a shared partner) — not independent primer-pair batching, which this tool doesn't support. A primer may carry a non-templated 5' tail (a restriction site, a Gibson arm, a tag): the screen looks for a 3'-anchored annealing region as well as a full-length match, so a tailed cloning primer is screened rather than silently matching nothing. Each end's `anchor` is the annealed run, which is the length that matters for extension, and `start`/`end` are measured on the ANNEALED footprints — the bases each primer actually pairs with on the genome — so `length` (the product, tails included) equals end - start + 1 only for untailed primers. Screening a TAILED primer without `intendedTemplate` inflates every margin by the tail's own free energy, because nothing about an oligo says where its non-templated part ends; `intended.basis` reports which footprint the margins rest on.\n\nBatchable via `POST /batch`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"forwardPrimer":{"type":"string","residues":"nt","description":"Forward primer, 5'→3'."},"reversePrimer":{"type":"string","residues":"nt","description":"Reverse primer, 5'→3'."},"maxMismatches":{"type":"integer","default":1,"minimum":0,"maximum":4,"description":"Mismatches tolerated per primer against a reference genome. Capped at 4 — past that a primer would not extend anyway. No primer length is refused for raising this: the pigeonhole seed just gets shorter and less selective, so more candidate sites are verified and the call takes longer (an 18-mer over the bundled genomes runs in ~0.1 s at 0 and ~1.5 s at 4). A short primer at a high setting can still exceed the binding-site pairing limit and come back \"unsupported\" — a 13-mer at 4 binds too many places to pair up, where an 18-mer screens fine — and either primer under 13 nt is not screened at all (ambiguousSeed: true, no amplicons)."},"maxProductLength":{"type":"integer","default":5000,"minimum":1,"description":"Ignore candidate off-target products longer than this (bp) — a search-window cap, not a biological claim."},"intendedTemplate":{"type":"string","residues":"nt","description":"The template these primers are meant to amplify. Only their annealing footprints are read from it, so an amplicon, a plasmid or a cassette is always enough (at most 1,000,000 bp). Passing it is what makes closestCompetitorMargin true for a primer carrying a 5' tail: a tail is non-templated by definition, so nothing about the oligo says where it ends, and without a template the screen has to assume the whole oligo anneals — which credits the intended reaction with a duplex the tail cannot form ANYWHERE and inflates every margin by that tail's own free energy. Searched on both strands as given; a primer that cannot be found on it is an error rather than a silent fall back to the whole oligo."}},"required":["forwardPrimer","reversePrimer"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/oligo_cofold":{"post":{"tags":["Primers & oligos"],"operationId":"oligo_cofold","summary":"Oligo cofold (ΔG)","description":"Minimum-free-energy structure and ΔG for one oligo (hairpin) or two oligos together (homo/heterodimer), using ViennaRNA's published loop model at a temperature you choose — DNA parameters (Mathews 2004) by default, RNA (Turner 2004) on request. Reports each strand alone, the duplex, and the interaction ΔG the two gain by pairing with each other rather than folding alone, which is the number a primer-dimer screen wants. Unlike oligo_analysis's fast stack-sum screen this is a full loop model with bulge, internal-loop and dangling-end terms; the two are on different parameter sets and must not be compared.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"a":{"type":"string","maxLength":800,"description":"First oligo, 5'→3'. Max 200 nt."},"b":{"type":"string","maxLength":800,"description":"Second oligo. Omit to analyze hairpin structure in 'a' alone; pass the same sequence as 'a' for a homodimer."},"alphabet":{"type":"string","enum":["dna","rna"],"default":"dna","description":"Which measured parameter set to use. This is not cosmetic — the same 20-mer can differ by several kcal/mol between them."},"temperature":{"type":"number","default":37,"minimum":-20,"maximum":120,"description":"°C. Primer dimers matter at the annealing temperature, not at 37 °C."},"partition":{"type":"boolean","default":false,"description":"Also compute the ensemble free energy over all structures, not just the MFE one. Costs a second pass."}},"required":["a"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/barcode_design":{"post":{"tags":["Primers & oligos"],"operationId":"barcode_design","summary":"Design a set of sequencing barcodes","description":"Build a set of DNA barcodes that are pairwise at least a chosen edit distance apart, so a read error cannot turn one barcode in the pool into another. Honours a GC window, a homopolymer cap and excluded motifs (the restriction sites you clone with) during the search rather than filtering afterwards, and can extend a set you already have rather than replacing it. Reports the distance ACHIEVED — re-derived over the finished pool, not assumed from the search — plus how many read errors that distance lets you correct and detect. Deterministic given a seed. Returns fewer barcodes than asked, with a reason, when the constraints leave no room.","requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"count":{"type":"integer","default":96,"minimum":1,"maximum":1000,"description":"How many barcodes to design (max 1000). A plate is 96 or 384."},"length":{"type":"integer","default":12,"minimum":4,"maximum":40,"description":"Barcode length in bases (default 12). Longer barcodes make a given distance far easier to reach."},"minDistance":{"type":"integer","default":3,"minimum":1,"description":"Minimum edit distance between any two barcodes (default 3). Distance 3 corrects one read error and detects two; distance 5 corrects two. Distance 1 only means 'not identical' and corrects nothing."},"metric":{"type":"string","enum":["levenshtein","hamming"],"default":"levenshtein","description":"'levenshtein' counts substitutions, insertions and deletions — the right choice for nanopore or PacBio, and the safe default. 'hamming' counts substitutions only, which is faster and adequate when the platform's errors are substitutions (Illumina), but gives NO protection against an indel shifting one barcode into another."},"gcMin":{"type":"number","default":25,"minimum":0,"maximum":100,"description":"Lowest GC% a barcode may have."},"gcMax":{"type":"number","default":75,"minimum":0,"maximum":100,"description":"Highest GC% a barcode may have."},"maxHomopolymer":{"type":"integer","default":3,"minimum":1,"description":"Longest run of one base allowed (default 3). Homopolymers miscall on every platform and are the one composition rule worth keeping tight."},"exclude":{"type":"array","items":{"type":"string"},"description":"Motifs no barcode may contain, checked on both strands — the restriction sites you clone with. Literal ACGT only."},"existing":{"type":"array","items":{"type":"string"},"description":"Barcodes you already use. They are held fixed and the new ones are kept distant from them, so a second plate does not collide with the first."},"seed":{"type":"integer","default":1,"description":"Seeds the search. Change it for a different set from the same constraints; keep it to reproduce one."}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/barcode_audit":{"post":{"tags":["Primers & oligos"],"operationId":"barcode_audit","summary":"Measure a set of barcodes you already have","description":"Take a set of barcodes and report the minimum edit distance in it, which pairs sit at that distance, any duplicates, the GC range and the longest homopolymer. The pairs are the point: 'minimum distance 2' is a number, and 'these two barcodes are one substitution apart' is something to fix. Use before committing a pool you inherited or assembled by hand — a single close pair makes two constructs indistinguishable in the data and nothing downstream can detect it.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"barcodes":{"type":"string","description":"The barcodes, as FASTA, one per line, or comma-separated. Max 1,000, because every pair is compared."},"metric":{"type":"string","enum":["levenshtein","hamming"],"default":"levenshtein","description":"'levenshtein' counts substitutions, insertions and deletions — the right choice for nanopore or PacBio, and the safe default. 'hamming' counts substitutions only, which is faster and adequate when the platform's errors are substitutions (Illumina), but gives NO protection against an indel shifting one barcode into another."}},"required":["barcodes"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/restriction_sites":{"post":{"tags":["Enzymes & cloning"],"operationId":"restriction_sites","summary":"Restriction sites","description":"Find restriction enzyme recognition sites in a DNA sequence.\n\nBatchable via `POST /batch`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"sequence":{"type":"string","residues":"nt","description":"Nucleotide sequence (raw or FASTA; IUPAC accepted)."},"enzymes":{"type":"array","items":{"type":"string"},"description":"Enzyme names to scan; omit to scan the curated common-enzyme set. A name is resolved against the curated set, the Type IIS cutters and the generated REBASE table, case-, punctuation- and HF/v2-variant-insensitively, so \"ecori\", \"EcoRI-HF\", \"BsaI\" and \"BsmFI\" all resolve. A name that resolves to nothing is REJECTED rather than dropped — an unscanned enzyme reported as having no sites is indistinguishable from one that genuinely does not cut."},"circular":{"type":"boolean","default":false,"description":"Treat the sequence as circular (plasmid) so sites spanning the origin are found."}},"required":["sequence"],"additionalProperties":false},"example":{"sequence":"GAATTCGGATCCAAGCTT"}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/double_digest":{"post":{"tags":["Enzymes & cloning"],"operationId":"double_digest","summary":"Double digest buffer","description":"Recommend a single NEB buffer (and flag caveats) for digesting with two enzymes in one tube.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"enzymeA":{"type":"string","description":"First enzyme name (e.g. EcoRI)."},"enzymeB":{"type":"string","description":"Second enzyme name (e.g. BamHI)."}},"required":["enzymeA","enzymeB"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/cloning_simulate":{"post":{"tags":["Enzymes & cloning"],"operationId":"cloning_simulate","summary":"Cloning simulator","description":"Assemble fragments by Gibson/overlap, Golden Gate (Type IIS), restriction–ligation (sticky or blunt), TOPO/TA, LIC or SLIC (T4-polymerase chew-back) or In-Fusion/CPEC, returning the product, the junctions and — for the primer-design methods — the junction primers. Each method is modeled as its own chemistry rather than as one product model with different labels: LIC's chew-back stops at the first occurrence of the single dNTP supplied, so a tail carrying that base stops it early and a tail without one lets it run past the junction, and both are refused with the offending base and position named.\n\nNot a workflow step (it does not take a single sequence argument), but its `product` field is the sequence to carry into the next call yourself.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"method":{"type":"string","enum":["gibson","goldengate","restriction","topo","lic","slic","infusion"],"default":"gibson","description":"Assembly method. gibson/goldengate design the junction primers for bare fragments; restriction and topo build a product from a vector and an insert; lic and slic model T4-polymerase chew-back (sequence-defined and time-stopped respectively); infusion is In-Fusion/CPEC, 15 bp terminal homology with no exonuclease, and works out the fragment ORDER for itself."},"fragments":{"type":"array","items":{"type":"string"},"maxItems":24,"description":"Fragments (5′→3′). Used by gibson/goldengate/slic/infusion. gibson and goldengate assemble them head-to-tail in the order given and add the junctions by primer; slic needs the homology already ON the fragments and keeps the order given; infusion needs it on the fragments too but derives the order from the homologies, so the order listed here is ignored. slic and infusion take at most 24."},"names":{"type":"array","items":{"type":"string"},"description":"Optional labels for each fragment."},"circular":{"type":"boolean","default":true,"description":"Produce a circular product."},"overlapLen":{"type":"integer","default":20,"description":"Gibson homology-arm length (bp)."},"mergePreAddedArms":{"type":"boolean","default":true,"description":"Gibson only. When two fragments already share terminal sequence, count that share ONCE (the default — it is a homology arm the fragments already carry) or set false to concatenate it twice. The second reading is the right one when the shared block is a genuine tandem repeat, e.g. a 2x tag or enhancer split between its copies: nothing in the two fragments can tell the two apart, so the choice belongs to the caller. Either way the share is reported in preAddedArms and both readings are returned in `readings`."},"armTmTarget":{"type":"number","default":60,"description":"Target annealing Tm (°C) for primer arms."},"enzyme":{"type":"string","default":"BsaI","description":"Type IIS enzyme for Golden Gate — one of BsaI, BbsI, Esp3I (BsmBI); \"BsmBI\" also resolves to Esp3I. Any other name is rejected rather than substituted."},"vector":{"type":"string","residues":"nt","description":"Vector sequence (restriction, topo and lic methods; for lic, the LINEARIZED vector)."},"insert":{"type":"string","residues":"nt","description":"Insert sequence (restriction, topo and lic methods)."},"enzyme5":{"type":"string","default":"EcoRI","description":"Insert 5′ enzyme (restriction method)."},"enzyme3":{"type":"string","default":"BamHI","description":"Insert 3′ enzyme (restriction method)."},"vectorEnzyme5":{"type":"string","description":"Vector 5′ enzyme (restriction method); defaults to enzyme5. Set a different, compatible enzyme (e.g. BglII for a BamHI insert) to model heterologous-overhang cloning."},"vectorEnzyme3":{"type":"string","description":"Vector 3′ enzyme (restriction method); defaults to enzyme3."},"dephosphorylateVector":{"type":"boolean","default":false,"description":"CIP/rSAP-dephosphorylate the vector to suppress self-ligation background (restriction method)."},"topoMode":{"type":"string","enum":["ta","blunt","directional"],"default":"ta","description":"TOPO chemistry (topo method): TA (Taq 3′-A), blunt, or directional (pENTR/D-TOPO, needs 5′-CACC on the insert)."},"vectorNucleotide":{"type":"string","enum":["A","C","G","T"],"description":"lic method: the single dNTP the VECTOR's chew-back was run with (T for dTTP…). Required — T4 pol's exonuclease stops at the first occurrence of this base reading inward from each 3′ end, so there is no answer without it."},"insertNucleotide":{"type":"string","enum":["A","C","G","T"],"description":"lic method: the single dNTP the INSERT's chew-back was run with. Normally the COMPLEMENT of vectorNucleotide (the classic pair is dTTP on the vector, dATP on the insert) — with the same base for both, each junction's shared block would have to avoid that base and its complement at once."},"chewBackLen":{"type":"integer","default":0,"minimum":0,"description":"slic method: nucleotides removed from each 3′ end. A SLIC chew-back has no dNTP to arrest it and is stopped by time, so this is an input rather than a property of the sequence. 0 (default) models the intended reaction — chewed to the full homology and no further; any positive value is checked against each junction's own homology, and both overrunning it and falling short of meeting the chew-back coming the other way are reported."},"homologyLen":{"type":"integer","default":15,"minimum":15,"description":"infusion method: terminal homology required at every junction, in bp. At least 15 — the junction is annealed and extended by a polymerase with no exonuclease to widen it and no ligase to seal it, so a shorter overlap is a different chemistry rather than a weaker version of this one."}},"required":["method"],"additionalProperties":false},"example":{"method":"gibson","fragments":["ATGGCCAAGCTGACCGAACTGAAAGCCGCCGTGGAAACCCTG","GAAACCCTGGATAAAGCCTTCAAAGATGCCCTGAAAGCCTAA"],"circular":true,"overlapLen":20}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/plasmid_annotate":{"post":{"tags":["Enzymes & cloning"],"operationId":"plasmid_annotate","summary":"Plasmid annotator","description":"Auto-detect common cloning features (promoters, tags, origins, resistance markers, MCS, primers) on both strands. Signatures under 20 bp must match exactly; longer ones tolerate up to ~10% mismatches so point mutants still annotate — each feature reports its own `mismatches` count and an `exact` flag.\n\nBatchable via `POST /batch`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"sequence":{"type":"string","residues":"nt","description":"Nucleotide sequence (raw or FASTA; IUPAC accepted)."}},"required":["sequence"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/construct_qc":{"post":{"tags":["Enzymes & cloning"],"operationId":"construct_qc","summary":"Construct QC linter","description":"Lint a coding DNA sequence for premature stops, internal RBS/polyA motifs, unwanted restriction sites, GC extremes and repeats.\n\nBatchable via `POST /batch`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"sequence":{"type":"string","residues":"nt","description":"Nucleotide sequence (raw or FASTA; IUPAC accepted)."},"frameStart":{"type":"integer","default":1,"description":"1-based nucleotide where the reading frame begins."},"avoidEnzymes":{"type":"array","items":{"type":"string"},"description":"Enzyme names whose internal sites should be flagged as errors. Matched against the curated common-enzyme set plus the Golden Gate Type IIS enzymes (BsaI, BbsI, Esp3I/BsmBI); an unrecognized name is rejected, never skipped."},"gcWindow":{"type":"integer","default":50,"description":"Sliding-window size (nt) for GC-extreme scanning."},"gcLow":{"type":"number","default":30,"description":"GC% below this flags an AT-rich window."},"gcHigh":{"type":"number","default":70,"description":"GC% above this flags a GC-rich window."},"homopolymerMin":{"type":"integer","default":8,"description":"Minimum run length to flag a homopolymer."},"crypticOrfMinAa":{"type":"integer","default":20,"description":"Minimum peptide length (aa) for a hidden alternate-frame ORF to be flagged."}},"required":["sequence"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/construct_autofix":{"post":{"tags":["Enzymes & cloning"],"operationId":"construct_autofix","summary":"Construct auto-fix (domestication)","description":"Iteratively substitutes synonymous codons to resolve unwanted restriction sites (domestication for Golden Gate), homopolymers, tandem repeats, predicted secondary structure, cryptic RBS/polyA motifs and hidden alternate-frame ORFs that construct_qc flags — without changing the encoded protein (verified). Does NOT touch premature stops or GC extremes; re-run construct_qc afterward to confirm. A native TypeScript alternative to a constraint-solver sidecar.\n\nBatchable via `POST /batch`.\n\nChainable in workflows (passes its `sequence` field to the next step).","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"sequence":{"type":"string","residues":"nt","description":"Nucleotide sequence (raw or FASTA; IUPAC accepted)."},"organism":{"type":"string","enum":["ecoli","human","yeast","cho","pichia","insect","arabidopsis","zebrafish"],"default":"ecoli","description":"Codon-usage table to prefer among synonymous options."},"frameStart":{"type":"integer","default":1,"description":"1-based nucleotide where the reading frame begins."},"avoidEnzymes":{"type":"array","items":{"type":"string"},"description":"Enzyme names whose internal sites should be removed (e.g. [\"BsaI\",\"BsmBI\"] for Golden Gate domestication)."},"gcWindow":{"type":"integer","default":50},"gcLow":{"type":"number","default":30},"gcHigh":{"type":"number","default":70},"homopolymerMin":{"type":"integer","default":8},"crypticOrfMinAa":{"type":"integer","default":20,"description":"Minimum peptide length (aa) for a hidden alternate-frame ORF to be flagged."},"maxPasses":{"type":"integer","default":3,"minimum":1,"maximum":10,"description":"Repeat full passes until clean or no further progress."}},"required":["sequence"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/virtual_gel":{"post":{"tags":["Enzymes & cloning"],"operationId":"virtual_gel","summary":"Virtual gel","description":"Predict restriction-digest fragment sizes and their gel migration positions against a chosen DNA ladder.\n\nBatchable via `POST /batch`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"sequence":{"type":"string","residues":"nt","description":"Nucleotide sequence (raw or FASTA; IUPAC accepted)."},"enzymes":{"type":"array","items":{"type":"string"},"description":"Enzyme names to digest with, from the curated common-enzyme set (see restriction_sites for the full list). An unrecognized name is rejected rather than skipped, so an empty band pattern always means \"no sites\"."},"circular":{"type":"boolean","default":false,"description":"Treat the sequence as circular (plasmid)."},"ladder":{"type":"string","enum":["1 kb","1 kb Plus","100 bp"],"default":"1 kb","description":"DNA ladder to plot alongside the sample lane."}},"required":["sequence"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/ligation_setup":{"post":{"tags":["Enzymes & cloning"],"operationId":"ligation_setup","summary":"Ligation / assembly reaction setup","description":"Work out how many microlitres of vector and insert to pipette to hit a target molar ratio, from each part's length and stock concentration. Handles one insert or several with independent equivalents (Gibson, Golden Gate, MoClo), reports pmol and ng per part alongside the volumes, and flags the two things that actually go wrong on a bench: a volume below what a pipette measures reliably, and a plan whose DNA does not leave room for buffer and enzyme. A molar ratio is about moles, so a shorter insert at 3 molar equivalents goes in at LESS mass than the vector — that conversion is the point.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"vectorLengthBp":{"type":"integer","description":"Backbone length in bp."},"vectorNgPerUl":{"type":"number","description":"Backbone stock concentration, ng/µL."},"vectorNg":{"type":"number","default":50,"description":"How much backbone to put in the reaction, ng. This is the quantity you fix; every insert mass follows from the ratio."},"insertLengthBp":{"type":"integer","description":"Insert length in bp. Use `inserts` instead for a multi-fragment assembly."},"insertNgPerUl":{"type":"number","description":"Insert stock concentration, ng/µL."},"molarRatio":{"type":"number","default":3,"description":"Molar equivalents of insert per vector. 3 is the usual starting point for a sticky-end ligation; 1-2 is common for Gibson and Golden Gate."},"inserts":{"type":"array","description":"Multi-fragment assembly: one entry per insert, each with its own length, stock and molar equivalents. Overrides insertLengthBp/insertNgPerUl/molarRatio when present.","items":{"type":"object","properties":{"label":{"type":"string"},"lengthBp":{"type":"integer"},"ngPerUl":{"type":"number"},"equivalents":{"type":"number","default":1}},"required":["lengthBp","ngPerUl"]}},"reactionVolumeUl":{"type":"number","default":20,"description":"Total reaction volume, µL."},"vectorSequence":{"type":"string","residues":"nt","description":"Optional backbone sequence — gives an exact molar mass from base composition instead of the 650 g/mol/bp average."}},"required":["vectorLengthBp","vectorNgPerUl"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/golden_gate_from_parts":{"post":{"tags":["Enzymes & cloning"],"operationId":"golden_gate_from_parts","summary":"Golden Gate from part plasmids","description":"Golden Gate as the reaction runs: digest pre-domesticated part plasmids with a Type IIS enzyme and assemble them in the order their OVERHANGS dictate. The fragment released from each part is the one carrying no recognition site (the site goes out with the backbone, which is why a mis-ordered assembly is not re-cut), and the assembly order is an OUTPUT — a set whose overhangs do not close into a single cycle has no product, and the reason is the answer. Distinct from cloning_simulate's `goldengate` method, which does the other job: designing the primers that ADD the sites to BARE parts, assembled in the order you list them.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"parts":{"type":"array","items":{"type":"object"},"minItems":2,"maxItems":24,"description":"The part plasmids: [{ name, sequence, circular }]. Each needs two Type IIS sites facing INWARDS at the part. `circular` defaults to true, which is what a level-0 part plasmid is. 2-24 parts, each at most 30,000 bp and 200,000 bp in total."},"enzyme":{"type":"string","enum":["BsaI","BsmBI","BbsI","SapI"],"default":"BsaI","description":"Type IIS enzyme (BsaI, BsmBI, BbsI, SapI). NEB's variant names (BsaI-HFv2, BbsI-HF, BsmBI) fold to the parent enzyme; any other name is rejected rather than substituted, since site, spacer and overhang length are all enzyme-specific."}},"required":["parts"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/assembly_outcomes":{"post":{"tags":["Enzymes & cloning"],"operationId":"assembly_outcomes","summary":"Assembly outcomes (what else you might have built)","description":"Enumerate the specific wrong plasmids a multi-part Golden Gate or Gibson assembly can produce — a part dropped, inverted, duplicated, two parts swapped, the backbone self-circularized — as full sequences, ranked by how few independent mis-ligations each needs. Golden Gate outcomes are annotated with the MEASURED overhang cross-talk they would have to exploit (Potapov/Pryor ligation data). Feed the result to diagnostic_digest to pick a screening enzyme. Reports no probability per outcome: the ligation data does not measure transformation or vector background.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"fragments":{"type":"array","items":{"type":"string"},"description":"The parts in assembly order, raw or FASTA — the same list cloning_simulate takes. 2-8 parts."},"names":{"type":"array","items":{"type":"string"},"description":"Optional labels for the parts, in the same order (\"backbone\", \"promoter\", \"CDS\"). Used in every outcome label."},"method":{"type":"string","enum":["goldengate","gibson"],"default":"goldengate","description":"How the parts are joined. Golden Gate junctions are the Type IIS fusion overhangs; Gibson junctions are the homology arms."},"enzyme":{"type":"string","default":"BsaI","description":"Golden Gate only — the Type IIS enzyme, which fixes the overhang length (BsaI, BbsI, Esp3I (BsmBI))."},"overlapLen":{"type":"number","default":20,"description":"Gibson only — homology arm length, which must match what the assembly was designed with."},"dataset":{"type":"string","enum":["generic-t4-37c-1h","bsai-hfv2"],"default":"generic-t4-37c-1h","description":"Which ligation dataset to read overhang cross-talk from (Golden Gate only)."},"circular":{"type":"boolean","default":true,"description":"Circular product. Only circular assemblies are covered — a linear product's leading end is a free terminus, not a junction."},"maxAlternatives":{"type":"number","default":12,"description":"Cap on returned alternatives, most accessible first. The pre-cap count is always reported as alternativesEnumerated."}},"required":["fragments"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/diagnostic_digest":{"post":{"tags":["Enzymes & cloning"],"operationId":"diagnostic_digest","summary":"Diagnostic digest planner","description":"Pick the restriction digest that tells your intended construct apart from the wrong ones on a screening gel. Digests every candidate, works out which bands would actually resolve at the chosen agarose percentage (size ratio, the gel's resolving window, and whether a band is too faint to score), and ranks single enzymes — then buffer-checked pairs if no single one works. The criterion is separating the INTENDED construct from every alternative; telling the alternatives apart from each other is reported as a bonus. Get the alternatives from assembly_outcomes.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"intended":{"type":"string","residues":"nt","description":"The construct you designed, raw or FASTA."},"alternatives":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string","description":"What this wrong construct is (\"empty vector\", \"insert reversed\")."},"sequence":{"type":"string","description":"Its full sequence, raw or FASTA."}},"required":["sequence"]},"description":"The wrong constructs to screen against, 1-12. assembly_outcomes emits these ready-made as `forDiagnosticDigest`."},"circular":{"type":"boolean","default":true,"description":"Treat every candidate as a circular plasmid."},"agarosePercent":{"type":"number","default":1,"description":"Agarose percentage of the screening gel. Snapped to the nearest tabulated value (0.5, 0.7, 1, 1.2, 1.5, 2) and the one used is reported back, since the resolving window is what decides which bands separate."},"enzymes":{"type":"array","items":{"type":"string"},"description":"Restrict the search to these enzymes (e.g. the ones on your bench). Default is the whole curated set of 49. An unrecognized name is rejected rather than skipped, so \"does not discriminate\" always means it was actually tried."},"includePairs":{"type":"string","enum":["auto","always","never"],"default":"auto","description":"Whether to search double digests. \"auto\" adds them only when no single enzyme separates everything."},"maxSuggestions":{"type":"number","default":5,"description":"How many ranked options to return."}},"required":["intended","alternatives"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/repeat_instability":{"post":{"tags":["Enzymes & cloning"],"operationId":"repeat_instability","summary":"Repeat instability (what the construct can delete)","description":"Find the exact direct repeats in a construct that make it deletable, and build the molecule each pair would collapse to. Two copies of the same terminator or promoter in a multi-gene assembly let the DNA between them recombine out — silently, so the clone grows and the map looks right until it is sequenced. Returns each repeat pair's coordinates plus the resulting sequence(s), ordered by repeat length and spacer, the two factors that govern how readily a pair recombines. Reports no deletion RATE: none is derivable from sequence alone. Feed a deletion product to diagnostic_digest to screen for it.\n\nBatchable via `POST /batch`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"sequence":{"type":"string","residues":"nt","description":"The construct, raw or FASTA. Max 500,000 bp."},"circular":{"type":"boolean","default":true,"description":"Treat as a plasmid. A circular construct is searched across its own arbitrary start, so a repeat straddling position 1 is not missed, and each pair reports BOTH circles the recombination makes."},"minRepeatLength":{"type":"number","default":20,"description":"Shortest repeat to report, in bp (default 20). Below about 20 bp homologous recombination has little to work with and chance matches multiply."},"maxPairs":{"type":"number","default":60,"description":"Cap on reported pairs, most recombinogenic first. The pre-cap count is always reported as pairsFound."},"includeSequences":{"type":"boolean","default":true,"description":"Return the full product sequences. Turn off for a coordinates-only summary over a large construct."}},"required":["sequence"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/nonrepetitive_parts_find":{"post":{"tags":["Enzymes & cloning"],"operationId":"nonrepetitive_parts_find","summary":"Find a non-repetitive subset of existing parts","description":"Given a toolbox of genetic parts, return the largest subset in which no two parts share more than a chosen length of sequence — on either strand. Parts that share a long stretch recombine into each other in a multi-part assembly and are the single largest cause of DNA synthesis failure, and neither shows up when the parts are checked one at a time. Reports every conflicting pair and why each dropped part was dropped. Deterministic: no model, no rate, no score. Use nonrepetitive_parts_design to build new parts instead of selecting from existing ones.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"parts":{"type":"string","description":"The toolbox as (multi-)FASTA — each record's header becomes the part's name. Max 4,000 parts, 5,000 bp each."},"lmax":{"type":"integer","default":15,"minimum":8,"maximum":40,"description":"Longest stretch two parts may share, in bp (default 15). Two parts conflict when they share MORE than this. Below 8 bp every pair of sequences matches by chance."},"bothStrands":{"type":"boolean","default":true,"description":"Count a shared stretch even when one part carries it reverse-complemented. Recombination and synthesis both see both strands, so leaving this on is almost always right."},"strategy":{"type":"string","enum":["2apx","greedy"],"default":"2apx","description":"Which approximation picks the subset. Maximum independent set is NP-hard, so neither is guaranteed largest: '2apx' is the standard 2-approximation, 'greedy' repeatedly drops the most-conflicting part. Try both — they disagree on real toolboxes."}},"required":["parts"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/nonrepetitive_parts_design":{"post":{"tags":["Enzymes & cloning"],"operationId":"nonrepetitive_parts_design","summary":"Design new non-repetitive parts","description":"Build a set of new genetic parts that match a degenerate (IUPAC) template and share more than a chosen length with nothing — not each other, not themselves, not a background sequence you supply. This is how a toolbox of promoters, RBSs, terminators or sgRNA handles is made large without making an assembly unstable. Honours a GC range and excluded motifs (restriction sites) during the search rather than filtering afterwards. Deterministic given a seed: the same inputs give the same toolbox. Returns fewer parts than asked, with a reason, when the constraints leave no room — it never invents a repetitive one to hit the count.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"constraint":{"type":"string","description":"The IUPAC template every part must match, e.g. \"NNNNNNTTGACANNNNNNNNNNNNNNNNNTATAATNNNNNN\" for a sigma-70 promoter library. N is any base; fixed letters are held. Max 1,000 nt."},"count":{"type":"integer","default":20,"minimum":1,"maximum":500,"description":"How many parts to build (max 500)."},"lmax":{"type":"integer","default":15,"minimum":8,"maximum":40,"description":"Longest stretch any two parts may share, in bp (default 15)."},"bothStrands":{"type":"boolean","default":true,"description":"Treat a stretch and its reverse complement as the same stretch."},"gcMin":{"type":"number","default":0,"minimum":0,"maximum":100,"description":"Lowest GC% a part may have."},"gcMax":{"type":"number","default":100,"minimum":0,"maximum":100,"description":"Highest GC% a part may have."},"background":{"type":"array","items":{"type":"string"},"description":"Sequences the new parts must also avoid sharing with — the host genome region, the vector, or a toolbox you already own."},"exclude":{"type":"array","items":{"type":"string"},"description":"Motifs no part may contain, checked on both strands: restriction sites you clone with, a terminator you do not want. Literal ACGT only — an IUPAC code is refused rather than silently half-matched."},"seed":{"type":"integer","default":1,"description":"Seeds the search. Change it for a different toolbox from the same constraints; keep it to reproduce one."}},"required":["constraint"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/operon_scan":{"post":{"tags":["Enzymes & cloning"],"operationId":"operon_scan","summary":"Find unwanted regulatory elements in a construct","description":"Scan a multi-gene construct, on both strands, for the sequence that quietly breaks operons: promoter-like -35/-10 pairs (including ones pointing backwards, which make antisense RNA), Shine-Dalgarno sequences positioned in front of an internal start codon, terminator-shaped hairpins with a U-tract, out-of-frame start codons inside a declared CDS, and exact direct repeats. Reports what MATCHED and how far it sits from consensus — it does not score a match or claim it transcribes. For an estimated promoter strength use promoter_predict; for a translation rate use rbs_predict.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"sequence":{"type":"string","residues":"nt","description":"The construct, raw, FASTA or GenBank. Max 100,000 bp."},"maxPromoterMismatches":{"type":"integer","default":1,"minimum":0,"maximum":4,"description":"Total mismatches allowed across both consensus boxes (default 1). 0 finds only perfect consensus, which real promoters rarely are; above 2 the hit rate on random DNA climbs fast."},"cdsStart":{"type":"integer","description":"1-based start of a coding sequence. Given with cdsEnd, out-of-frame start codons inside it are reported — without them that check is skipped, because 'out of frame' has no meaning until a frame is declared."},"cdsEnd":{"type":"integer","description":"1-based end of that coding sequence."}},"required":["sequence"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/operon_design":{"post":{"tags":["Enzymes & cloning"],"operationId":"operon_design","summary":"Assemble a multi-gene operon and check it","description":"Build a polycistronic operon from a promoter, a list of CDSs with their RBSs, spacers and a terminator — optionally recoding every CDS for a host — then scan the ASSEMBLED molecule for internal promoters, Shine-Dalgarno sequences, terminators, out-of-frame start codons and repeats. Scanning the product rather than the parts is the point: these elements are very often created BY THE JOIN between two parts, so checking each part alone finds nothing. Returns the sequence, an annotated GenBank file, and every element found. Assigns no translation rate — use rbs_library_design to choose RBSs, then rbs_predict to rank the result.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"genes":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","description":"Label for the CDS feature."},"cds":{"type":"string","description":"The coding sequence, as DNA."},"rbs":{"type":"string","description":"Ribosome binding site placed in front of this gene. Omit for a consensus default, or pass \"\" for none."}},"required":["cds"]},"description":"The genes, in order (max 12)."},"promoter":{"type":"string","description":"Promoter placed at the 5' end."},"terminator":{"type":"string","description":"Terminator placed at the 3' end."},"spacer":{"type":"string","description":"Sequence inserted between one CDS and the next gene's RBS."},"optimiseFor":{"type":"string","enum":["ecoli","human","yeast","cho","pichia","insect","arabidopsis","zebrafish"],"description":"Recode every CDS with this host's most-frequent codons. The rewrite is checked to translate back to the same protein, and skipped for that gene if it does not. This is a determinate recoding, NOT a yield prediction — published codon-optimisation algorithms are close to a coin flip on whether they raise or lower real expression."},"name":{"type":"string","description":"LOCUS name for the GenBank output."},"includeGenbank":{"type":"boolean","default":true,"description":"Return the annotated GenBank file."}},"required":["genes"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/synthesis_complexity":{"post":{"tags":["Analysis"],"operationId":"synthesis_complexity","summary":"Measure what makes a fragment hard to synthesise","description":"Measure the sequence features gene-synthesis vendors screen on — repeats (the single largest cause of synthesis failure), GC extremes, GC swings between adjacent windows, homopolymer runs and hairpin-forming inverted repeats — and report each against the threshold vendors publish. Returns measurements and named flags, never a success probability: refitted on the 303 REAL orders its authors publish (scripts/ssc-eval), the published classifier scores F1 0.866 against 0.878 for assuming every order succeeds, and transfers between ordering labs at AUC 0.423 — below chance. Pair with nonrepetitive_parts_design to fix the repeats it finds.\n\nBatchable via `POST /batch`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"sequence":{"type":"string","residues":"nt","description":"The fragment as it would be ordered, raw, FASTA or GenBank. Max 100,000 bp."},"window":{"type":"integer","default":50,"minimum":20,"maximum":500,"description":"Window for the GC profile, in bp (default 50). Vendors screen local GC, not just the average, so this is what the flags are computed over."},"repeatMin":{"type":"integer","default":20,"minimum":8,"description":"Shortest repeated stretch to report, in bp (default 20, which is where vendor repeat filters sit)."},"includeProfile":{"type":"boolean","default":false,"description":"Return the full per-window GC profile. Off by default — it is one row per window and most callers want the flags."}},"required":["sequence"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/band_traceback":{"post":{"tags":["Primers & oligos"],"operationId":"band_traceback","summary":"Band traceback (where the extra band came from)","description":"Explain a band you measured on a gel. Given the template, both primers and the observed size, it enumerates every pair of priming sites — including a single primer priming both strands — that would give a product that size, and ranks them by how much of each primer's 3' end matches without interruption, which is what decides whether a mispriming event can extend at all. Reports no yield and assigns no share of the band: the band is the input, not the output. Says plainly when nothing on this template explains the size, and what that points to instead.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"template":{"type":"string","residues":"nt","description":"The template you amplified, raw or FASTA. Max 200,000 bp."},"forwardPrimer":{"type":"string","residues":"nt","description":"Forward primer, 5'→3'."},"reversePrimer":{"type":"string","residues":"nt","description":"Reverse primer, 5'→3'."},"observedSize":{"type":"number","description":"The band size you measured off the gel, in bp."},"tolerancePercent":{"type":"number","default":10,"description":"How far off the size read may be, as a percentage. A percentage rather than a fixed number of bases because ±10% of 200 bp is not the same reading precision as ±10% of 5 kb."},"toleranceBp":{"type":"number","description":"Override the tolerance with a fixed window in bp."},"circular":{"type":"boolean","default":false,"description":"Template is circular (a plasmid)."},"maxMismatches":{"type":"number","default":3,"description":"Mismatches tolerated per primer while looking for sites (max 6). Higher finds more explanations and more coincidences."},"maxCandidates":{"type":"number","default":40,"description":"Cap on returned candidates, best-anchored first."}},"required":["template","forwardPrimer","reversePrimer","observedSize"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/sanger_indel_spectrum":{"post":{"tags":["Alignment & variants"],"operationId":"sanger_indel_spectrum","summary":"Sanger indel spectrum (editing efficiency without NGS)","description":"Quantify CRISPR editing from a pair of Sanger traces — an unedited control and the edited pool — by decomposing the edited trace onto shifted copies of the control. Returns the indel spectrum (how much of the pool carries each insertion or deletion size), the unedited fraction, and the R² of the decomposition, which is the number that says whether the model fits your traces at all. Non-negative least squares, so no allele is ever assigned a negative share. Does not work for base editing, which makes a mixed base rather than a shift.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"controlBases":{"type":"string","residues":"nt","description":"Base calls of the UNEDITED control read."},"controlChannels":{"type":"array","items":{"type":"array","items":{"type":"number"}},"description":"Per-base [A, C, G, T] intensities of the control read, one row per called base, read at that base's peak location (trace arrays are indexed by scan, not by base)."},"editedBases":{"type":"string","residues":"nt","description":"Base calls of the edited pool's read."},"editedChannels":{"type":"array","items":{"type":"array","items":{"type":"number"}},"description":"Per-base [A, C, G, T] intensities of the edited read, same convention."},"cutPosition":{"type":"number","description":"1-based position of the expected cut, in CONTROL read coordinates."},"maxIndel":{"type":"number","default":10,"description":"Largest indel to include in the basis, in bp (max 20). Every shift from −maxIndel to +maxIndel is fitted."},"windowLength":{"type":"number","default":70,"description":"Bases downstream of the cut used for the decomposition (20-300). Longer is better conditioned but needs more clean read."},"guard":{"type":"number","default":3,"description":"Bases skipped immediately after the cut, where the trace is least reliable."},"offset":{"type":"number","description":"Override the alignment offset between the reads. By default it is found from the base calls upstream of the cut, which is reported back along with the identity achieved."}},"required":["controlBases","controlChannels","editedBases","editedChannels","cutPosition"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/outcome_deconvolve":{"post":{"tags":["Alignment & variants"],"operationId":"outcome_deconvolve","summary":"Which product is in this tube (mixture from one Sanger read)","description":"Decompose one Sanger trace into fractions over a set of candidate molecules — the intended construct, the empty backbone, a double insert, a flipped part — instead of onto a generic indel ladder. Non-negative least squares against the candidates' own sequences, so no molecule is ever assigned a negative share. Reports the R² of the fit, which is what says whether the tube holds anything outside the candidate set, and GROUPS candidates the read cannot tell apart rather than splitting their share between them. Feed it the alternatives from assembly_outcomes.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"readBases":{"type":"string","residues":"nt","description":"Base calls of the read, e.g. from parse_sanger_trace."},"readChannels":{"type":"array","items":{"type":"array","items":{"type":"number"}},"description":"Per-base [A, C, G, T] intensities, one row per called base, read at that base's peak location."},"candidates":{"type":"array","items":{"type":"object"},"description":"The molecules this reaction could have produced, as { id, label, sequence, circular? }. Between 2 and 24; assembly_outcomes' intended plus alternatives is the intended source."}},"required":["readBases","readChannels","candidates"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/trace_secondary_peaks":{"post":{"tags":["Alignment & variants"],"operationId":"trace_secondary_peaks","summary":"Mixed bases and the uncalled tail of a Sanger trace","description":"Read a chromatogram for what the basecaller did not report: positions where a second dye is present under the called base (a heterozygote, or a contaminating template), and bases still visible in the scan past where base calling stopped. Both are arithmetic on the channel intensities already in the file — a ratio, and a peak position extrapolated from the median spacing — not a model. Returns the called sequence rewritten with IUPAC ambiguity codes, the extra bases, and every threshold that produced the answer. Takes the SCAN arrays, because the tail lies past the last peak location.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"baseCalls":{"type":"string","description":"Base calls, e.g. from parse_sanger_trace."},"peakLocations":{"type":"array","items":{"type":"number"},"description":"Scan index of each called base's peak — one per base call."},"channelA":{"type":"array","items":{"type":"number"},"description":"Full A channel, indexed by SCAN (not by base)."},"channelC":{"type":"array","items":{"type":"number"},"description":"Full C channel, indexed by scan."},"channelG":{"type":"array","items":{"type":"number"},"description":"Full G channel, indexed by scan."},"channelT":{"type":"array","items":{"type":"number"},"description":"Full T channel, indexed by scan."},"quality":{"type":"array","items":{"type":"number"},"description":"Optional per-base Phred scores; echoed beside each mixed position."},"mixedRatio":{"type":"number","default":0.25,"description":"Secondary/primary intensity ratio at which a position is reported as mixed (0-1 exclusive). A convention, not a measurement."},"skipLeading":{"type":"number","default":40,"description":"Bases at the read's start excluded from the mixed scan (0-1000). The dye blob lives here and lifts every channel; without this every read reports a wall of false heterozygotes at its start."},"tailSignalToNoise":{"type":"number","default":3,"description":"How far above the measured noise floor a channel must sit before the tail extension calls it (1-100)."},"maxExtension":{"type":"number","default":400,"description":"Most extra bases to call past the last called base (0-400). The cap is part of the method: peak positions are extrapolated and the extrapolation drifts."}},"required":["baseCalls","peakLocations","channelA","channelC","channelG","channelT"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/trace_diagnose":{"post":{"tags":["Files & formats"],"operationId":"trace_diagnose","summary":"Why is this Sanger read bad?","description":"Diagnose a failing Sanger chromatogram: the longest usable window (Mott trimming), whether there is signal above the noise at all, whether more than one molecule is in the tube and from which base, whether quality collapsed at a homopolymer or tandem repeat the polymerase stuttered through, and whether a dye blob or the instrument's own separation is the problem rather than the DNA. Each finding carries the measurement it is based on, what that pattern is usually caused by, and what to do next. Reads .ab1, .abi and .scf.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"fileBase64":{"type":"string","description":"The binary trace file (.ab1 / .abi / .scf), base64-encoded."},"fileName":{"type":"string","description":"Optional original file name (echoed back, and used to explain a refusal)."},"qualityCutoff":{"type":"number","minimum":5,"maximum":60,"default":20,"description":"Phred score the usable window is measured at. 20 is the conventional 1-in-100 line."},"mixedRatio":{"type":"number","minimum":0.1,"maximum":0.9,"default":0.35,"description":"A second peak at or above this fraction of the called peak counts as a mixed position. Lower it to catch a minor species, raise it if ordinary crosstalk on your instrument is firing it."}},"required":["fileBase64"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/primer_site_accessibility":{"post":{"tags":["Primers & oligos"],"operationId":"primer_site_accessibility","summary":"Is the template folded over my primer site?","description":"Fold the template around each place a primer binds, at the annealing temperature and under DNA parameters, and report how much of the primer's own footprint sits inside a helix. Primer design tools score the oligo — its Tm, its hairpin, its dimers — and leave the template unexamined, while a binding site buried in a stable stem is an ordinary reason a well-designed primer does not amplify. Returns the folded window, its free energy, the paired fraction of the footprint, and how many of the 3'-terminal five bases are paired.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"template":{"type":"string","description":"The template the primer has to bind — the region of interest, a plasmid, or an amplicon."},"primer":{"type":"string","description":"The primer, 5'->3'."},"annealingTemp":{"type":"number","minimum":20,"maximum":95,"default":60,"description":"The annealing temperature in Celsius. This is the whole reason the tool exists — structure at 37 C is not structure at 60 C, and the number changes the answer."},"windowNt":{"type":"number","minimum":40,"maximum":200,"default":120,"description":"Template to fold around each site, centred on the footprint. 40-200 nt."},"circular":{"type":"boolean","default":false,"description":"Wrap the window across the origin instead of clipping it."},"maxMismatches":{"type":"number","minimum":0,"maximum":10,"description":"Mismatches allowed when locating the primer. Defaults to the binding scanner's own rate."}},"required":["template","primer"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/promoter_predict":{"post":{"tags":["Analysis"],"operationId":"promoter_predict","summary":"Sigma-70 promoter strength","description":"Scan DNA for E. coli sigma-70 promoters and estimate each one's transcription initiation rate, with the free-energy terms it is built from: the -35 and -10 boxes, the spacer, the discriminator, the extended -10 and the initial transcribed region. Pairs with rbs_predict — together they separate 'nothing is transcribed' from 'it is transcribed and not translated', which no single measurement on the sequence does. Both strands by default, because a promoter reading into your insert from the other strand is still a promoter.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"sequence":{"type":"string","description":"DNA to scan, 80-10000 nt. A promoter region, a 5' UTR with its upstream context, or a whole cassette."},"bothStrands":{"type":"boolean","default":true,"description":"Scan the reverse strand too. Leave on unless you know the orientation — cryptic antisense promoters are a common and easily missed cause of trouble."},"limit":{"type":"number","default":10,"minimum":1,"maximum":100,"description":"How many of the strongest promoters to return."}},"required":["sequence"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/promoter_library_design":{"post":{"tags":["Analysis"],"operationId":"promoter_library_design","summary":"Design a non-repetitive promoter library spanning a strength range","description":"Build a set of sigma-70 promoters that (a) share no more than a chosen length of sequence with each other, so the library does not recombine with itself once integrated, and (b) span a range of predicted transcription rates, picked as an evenly log-spaced ladder. Variants are constructed deterministically from an IUPAC template holding the -35 and -10 consensus; their strengths are then estimated by the Promoter Calculator model. Rungs with no variant near them are reported as gaps rather than filled with the nearest thing. PREDICTED, NOT MEASURED: strengths carry R^2 = 0.45-0.60 against independent in vivo data, so treat the ladder as a ranked set to screen, not as calibrated numbers.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"librarySize":{"type":"integer","minimum":2,"maximum":24,"description":"How many promoters the ladder should have (2 to 24). Required: every other argument has a defensible default, so this is the one statement of intent, and without it an empty call would build and score a library nobody asked for."},"targetMin":{"type":"number","description":"Weakest rung, in the model's arbitrary transcription-rate units. OMIT THIS and the range is taken from what the built variants actually score, which is usually right: the units have no absolute meaning, so a default would describe nothing. Set it only to match a promoter you measured yourself."},"targetMax":{"type":"number","description":"Strongest rung, same units. Omit with targetMin to use the variants' own range."},"lmax":{"type":"integer","default":12,"minimum":8,"maximum":40,"description":"Longest stretch any two promoters in the library may share, in bp (default 12). This is the property that stops the library recombining with itself."},"template":{"type":"string","description":"IUPAC template every variant must match. Defaults to a sigma-70 layout holding TTGACA and TATAAT with a 17 nt spacer and randomised flanks. Change it to target a different architecture — but a template that randomises the boxes will produce members that are not promoters."},"candidatePool":{"type":"integer","default":24,"minimum":4,"maximum":48,"description":"How many variants to build and score before selecting the ladder. A larger pool fills more rungs and costs one longer scan, not more round trips."},"gcMin":{"type":"number","default":0,"minimum":0,"maximum":100,"description":"Lowest GC% a variant may have."},"gcMax":{"type":"number","default":100,"minimum":0,"maximum":100,"description":"Highest GC% a variant may have."},"exclude":{"type":"array","items":{"type":"string"},"description":"Motifs no variant may contain, both strands — the restriction sites you clone with. Literal ACGT only."},"seed":{"type":"integer","default":1,"description":"Seeds variant construction; same seed, same variants."}},"required":["librarySize"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/cloning_next_observation":{"post":{"tags":["Enzymes & cloning"],"operationId":"cloning_next_observation","summary":"Which experiment to run next, and how many are left","description":"Rank every observation you have not yet made by how many open causes it settles WHICHEVER WAY IT COMES OUT, then return the smallest set of observations that settles all of them. Takes the same arguments as cloning_diagnose. The ranking is computed by re-running the diagnosis at each possible outcome of each observation and intersecting, so every count is a worst case rather than an average — and causes that no observation can settle are named, because those need a different experiment rather than more observing. No probabilities anywhere.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"symptom":{"type":"string","enum":["no_colonies","wrong_clones","no_pcr_band"],"description":"The complaint. \"no_colonies\" = the plate is blank; \"wrong_clones\" = colonies grew but the clones are empty vector / rearranged / the original template; \"no_pcr_band\" = the gel lane is empty or the band is the wrong size."},"method":{"type":"string","enum":["goldengate","gibson","restriction_ligation","pcr"],"description":"How the construct was made. Decides which cause set applies and which design checks can run."},"parts":{"type":"array","items":{"type":"string"},"maxItems":8,"description":"Parts in assembly order (Golden Gate / Gibson), or [vector, insert] for a restriction ligation. Raw or FASTA. Up to 8; 300,000 bp total across parts and template."},"partNames":{"type":"array","items":{"type":"string"},"description":"Labels for the parts, in the same order (\"backbone\", \"promoter\", \"CDS\"). Used in every fact that names a part."},"enzymes":{"type":"array","items":{"type":"string"},"maxItems":4,"description":"The Type IIS enzyme for Golden Gate (BsaI, BbsI, Esp3I (BsmBI)), or the one or two restriction enzymes the insert and vector were cut with. An unrecognized name is rejected rather than skipped: every methylation and site-geometry verdict here reads \"no site found\" when the enzyme is missing, so a typo would come back as a clean bill of health."},"overlapLen":{"type":"number","default":20,"description":"Gibson only — the homology arm length the assembly was designed with."},"template":{"type":"string","residues":"nt","description":"PCR template, raw or FASTA."},"templateCircular":{"type":"boolean","default":false,"description":"Treat the template as a plasmid, so a product across the origin is found."},"primerForward":{"type":"string","residues":"nt","description":"Forward primer, up to 200 nt."},"primerReverse":{"type":"string","residues":"nt","description":"Reverse primer, up to 200 nt."},"annealingTempC":{"type":"number","description":"Annealing temperature actually used, °C. Compared against each primer's own nearest-neighbor Tm."},"agarosePercent":{"type":"number","default":1,"description":"Agarose percentage of the gel. Snapped to the nearest tabulated value; decides the resolving window a band is placed against."},"hostMethylation":{"type":"string","enum":["dam_dcm_plus","dam_dcm_minus","unknown"],"default":"unknown","description":"Dam/Dcm state of the DNA that was CUT — a property of the strain the plasmid was prepared from, not the one it was transformed into. Standard cloning strains are dam+/dcm+. \"dam_dcm_minus\" eliminates every methylation-blocking cause; \"unknown\" leaves the sequence overlap stated as a fact and the methylation as an open question."},"phosphataseTreated":{"type":"boolean","description":"Was the cut vector dephosphorylated (rSAP/CIP) before ligation?"},"insertSource":{"type":"string","enum":["plasmid_pcr","genomic_pcr","synthesis","digest","unknown"],"description":"Where the insert came from. Only \"plasmid_pcr\" changes a verdict: a plasmid template replicates and selects on its own, so it can give colonies with no ligation at all."},"vectorMarker":{"type":"string","enum":["amp","ampicillin","bla","cam","carb","carbenicillin","chlor","chloramphenicol","gent","gentamicin","hyg","hygromycin","kan","kanamycin","neo","spec","spectinomycin","strep","tet","tetracycline","zeo","zeocin"],"description":"Selection marker on the vector. Compared against the plate's antibiotic by identity, not by guessing at free text."},"plateAntibiotic":{"type":"string","enum":["amp","ampicillin","bla","cam","carb","carbenicillin","chlor","chloramphenicol","gent","gentamicin","hyg","hygromycin","kan","kanamycin","neo","spec","spectinomycin","strep","tet","tetracycline","zeo","zeocin"],"description":"Antibiotic on the plate. amp and carbenicillin count as the same selection (both select bla)."},"colonies":{"type":"number","description":"Colonies on the experimental plate. Omitting this is different from giving 0."},"noDnaControlColonies":{"type":"number","description":"Colonies from the same cells and plate with NO DNA added. Non-zero means the plate is not selecting."},"positiveControlColonies":{"type":"number","description":"Colonies from an intact, uncut plasmid into the same cell aliquot. Non-zero eliminates \"the cells never took up DNA\"."},"positiveControlSameMarker":{"type":"boolean","description":"Did that control plasmid carry the SAME selection marker? If not, it eliminates the cells but says nothing about the plate — the tool reports the difference."},"noInsertControlColonies":{"type":"number","description":"Colonies from the identical reaction with the insert (or one part) left out."},"uncutVectorControlColonies":{"type":"number","description":"Colonies from the digested but UNLIGATED vector. Measures intact vector that survived the digest, with no help from the ligase."},"transformationEfficiencyCfuPerUg":{"type":"number","description":"cfu/µg from a control transformation, where it was measured."},"screened":{"type":"object","properties":{"total":{"type":"number","description":"Clones screened."},"correct":{"type":"number","description":"Clones that were the intended construct."},"emptyVector":{"type":"number","description":"Clones carrying no insert."},"rearranged":{"type":"number","description":"Clones that were a real plasmid but not the intended arrangement of parts."},"originalTemplate":{"type":"number","description":"Clones that turned out to be the plasmid the insert was amplified from."}},"required":["total","correct"],"description":"Screening tally, up to 100,000 clones. The buckets must not add up to more than total — an inconsistent tally is rejected rather than reasoned over, because every verdict drawn from the screen compares a count against that total."},"gelBandsObservedBp":{"type":"array","items":{"type":"number"},"maxItems":30,"description":"Band sizes read off the lane, bp. An empty array (\"I looked and there was nothing\") is not the same as omitting the field."},"ladderRan":{"type":"boolean","description":"Was the ladder itself visible in the same gel? A true here eliminates the whole stain-and-imaging branch in one observation."}},"required":["symptom","method"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/read_placement_plan":{"post":{"tags":["Primers & oligos"],"operationId":"read_placement_plan","summary":"Which sequencing reads actually tell your candidates apart","description":"Given the molecules a cloning reaction could have produced and the sequencing primers you could use, work out which primers separate which pairs of candidates — and return the smallest set that separates every pair any of them can. Scores a read by discrimination, not coverage: a read of 700 bases every candidate shares is worth nothing, and a short read across a junction is worth everything. Names the pairs no primer here separates, so you find out before paying for the reads rather than after. Pair it with outcome_deconvolve once the traces come back.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"candidates":{"type":"array","items":{"type":"object"},"description":"The molecules this reaction could produce, as { id, label, sequence, circular? }. Between 2 and 24; assembly_outcomes' intended plus alternatives is the intended source."},"primers":{"type":"array","items":{"type":"object"},"description":"Sequencing primers to choose between, as { id, label, sequence }. Up to 32."},"usableFrom":{"type":"number","default":30,"description":"Bases after the primer's 3' end before the trace becomes readable (0-500). A difference inside this dead zone is not counted as a separation, because the trace cannot show it."},"usableLength":{"type":"number","default":700,"description":"Readable bases per reaction, counted from usableFrom (50-5000)."},"maxMismatches":{"type":"number","description":"Mismatch budget passed to the priming scan. Defaults to primer-binding's own (~10% of the primer's length)."}},"required":["candidates","primers"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/base_edit_quant":{"post":{"tags":["Alignment & variants"],"operationId":"base_edit_quant","summary":"Base editing quantification from Sanger traces (EditR equivalent)","description":"Quantify CBE/ABE base editing from a pair of Sanger traces — an unedited control and the edited pool — without NGS. At each editable position in the activity window the edited trace is treated as a mixture of the unedited and converted peaks, and the control's OWN alt-channel signal at that same position is subtracted as background, because dye crosstalk is position- and context-dependent and a global constant would be wrong per position. Significance comes from a null built from the same sample (every control position outside the window carrying the same base), so the threshold adapts to the run's chemistry instead of being hardcoded. Returns per-position percentages with z-scores, the target and its bystanders, the background distribution (including a robust estimate of its spread and a count of its outliers), and the noise floor — the percentage the background alone reaches, or null when the run's own null has no spread to derive one from. A window position whose control already carries the converted base is reported but not quantified, because the (1 − b) rescale amplifies error by 1/(1 − b) and turns a 0.1-point wobble into half the pool. Locate the window with an editor id plus the protospacer, or give it explicitly. Blind to indels, which shift the trace rather than mixing a base.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"controlBases":{"type":"string","residues":"nt","description":"Base calls of the UNEDITED control read."},"controlChannels":{"type":"array","items":{"type":"array","items":{"type":"number"}},"description":"Per-base [A, C, G, T] intensities of the control read, one row per called base, read at that base's peak location (trace arrays are indexed by scan, not by base)."},"editedBases":{"type":"string","residues":"nt","description":"Base calls of the edited pool's read."},"editedChannels":{"type":"array","items":{"type":"array","items":{"type":"number"}},"description":"Per-base [A, C, G, T] intensities of the edited read, same convention."},"editor":{"type":"string","enum":["be3","be4max","abe7.10","abe8e"],"description":"Base editor id (be3, be4max, abe7.10, abe8e) — fixes the converted bases and the activity window in protospacer coordinates. Requires \"protospacer\". Mutually exclusive with the explicit window arguments."},"protospacer":{"type":"string","residues":"nt","description":"The 20-nt spacer, located in the CONTROL read. Found on either strand; a reverse-complement match numbers the protospacer right-to-left along the read and complements the converted bases (a CBE's C→T reads as G→A), which is handled. Must match exactly once."},"windowStart":{"type":"number","description":"Explicit window start, 1-based in CONTROL read coordinates. Requires windowEnd, from and to."},"windowEnd":{"type":"number","description":"Explicit window end, 1-based inclusive, in CONTROL coordinates. Window length is capped at 40."},"from":{"type":"string","residues":"nt","description":"Explicit-window mode: the base the editor converts, as READ on the control strand (C for a CBE read forward, G for one read reverse)."},"to":{"type":"string","residues":"nt","description":"Explicit-window mode: the base it converts to, as READ on the control strand."},"targetPosition":{"type":"number","description":"1-based CONTROL position of the intended edit. Give it when you know it: without it the most-edited significant position is labeled the target and the rest become bystanders, which relabels a bystander-dominant result as a clean one."},"targetProtospacerPosition":{"type":"number","description":"1-based protospacer position of the intended edit (PAM-distal = 1). Editor mode only."},"zThreshold":{"type":"number","default":3,"minimum":1,"maximum":10,"description":"Significance threshold in standard deviations of the sample's own background. Must be between 1 and 10 — a value outside that range is REJECTED, not clamped, because a run silently retested at a threshold the caller did not choose looks exactly like one that was. Raising it raises the reported noise floor with it."},"offset":{"type":"number","description":"Override the alignment offset between the reads (edited position p matches control position p + offset). Whole numbers only. By default it is found from the base calls outside the window; either way the identity reported back is the identity AT THE OFFSET USED, so overriding it does not hide a bad alignment behind the best-scoring one."}},"required":["controlBases","controlChannels","editedBases","editedChannels"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/sanger_knockin_quant":{"post":{"tags":["Alignment & variants"],"operationId":"sanger_knockin_quant","summary":"Knock-in / prime-edit rate from Sanger traces","description":"Measure the rate of a SPECIFIC intended edit from a pair of Sanger traces — an unedited control and the edited pool — by decomposing the edited trace onto three things at once: the wild-type allele, the intended edited allele, and the unintended indels. Serves both readouts that need this: HDR knock-in rate (what fraction of the pool carries the donor's edit, including an insert of novel sequence), and prime editing (the pegRNA's intended substitution, insertion, deletion or replacement as the intended column, and the indel byproducts at the nick as the shift columns). This is what sanger_indel_spectrum cannot do: that tool's basis is indexed by indel LENGTH, so an intended 6 bp knock-in and an accidental 6 bp NHEJ deletion are one column there. Returns knock-in / wild-type / unintended-indel percentages, the byproduct spectrum by shift, and the R² that says whether the model fits your traces at all. Non-negative least squares, so no allele is ever assigned a negative share. For a substitution or replacement the reference allele you name is checked against the control read before anything is fitted; an insertion and a deletion name no reference bases, so there only the position can be range-checked.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"controlBases":{"type":"string","residues":"nt","description":"Base calls of the UNEDITED control read."},"controlChannels":{"type":"array","items":{"type":"array","items":{"type":"number"}},"description":"Per-base [A, C, G, T] intensities of the control read, one row per called base, read at that base's peak location (trace arrays are indexed by scan, not by base)."},"editedBases":{"type":"string","residues":"nt","description":"Base calls of the edited pool's read."},"editedChannels":{"type":"array","items":{"type":"array","items":{"type":"number"}},"description":"Per-base [A, C, G, T] intensities of the edited read, same convention."},"editKind":{"type":"string","enum":["substitution","insertion","deletion","replacement"],"description":"Shape of the intended edit, spelled as prime_editing_design spells it. \"substitution\" replaces bases one for one; \"insertion\" adds novel bases and replaces none; \"deletion\" removes bases and adds none; \"replacement\" is the general case where the two lengths differ."},"editPosition":{"type":"number","description":"1-based position of the edit in CONTROL read coordinates: the first base the edit replaces. An insertion replaces nothing, so there it is the base the insert lands immediately BEFORE — one MORE than the VCF/HGVS anchor, which names the base before an insertion. The rule is uniform across all four kinds on purpose; a spec transcribed from VCF needs +1 on an insertion."},"refAllele":{"type":"string","residues":"nt","description":"The control bases the edit replaces (substitution and replacement). Checked against the control read: a mismatch is rejected, because building the intended-edit column at the wrong position yields a confident, meaningless number."},"altAllele":{"type":"string","residues":"nt","description":"The bases the edit installs in their place (substitution and replacement)."},"insertedSeq":{"type":"string","residues":"nt","description":"The novel bases inserted (insertion only)."},"deletedLength":{"type":"number","description":"How many bases are deleted (deletion only)."},"cutPosition":{"type":"number","description":"1-based CONTROL position where UNINTENDED indels start — the nuclease cut or the PE nick. Defaults to the edit start. Separate from editPosition because a byproduct allele is wild-type up to the cut and shifted after it, so a wrong cut position makes those columns wrong over the first part of the window."},"maxIndel":{"type":"number","default":10,"description":"Largest unintended indel to fit, in bp (1-20; out of range is rejected, not clamped). Every shift from −maxIndel to +maxIndel is included except 0, which is wild-type. The intended edit's OWN net shift is included too whenever its column is measurably different from the intended-edit column — it is dropped only when the two are the same vector, which happens for a pure deletion whose cut is at the edit. See sameShiftByproduct in the result for which of the two happened."},"windowLength":{"type":"number","default":70,"description":"Bases from the edit site downstream used for the decomposition (20-300; out of range is rejected, not clamped). Unlike sanger_indel_spectrum there is no guard region: the edited positions themselves are the only signal separating a substitution from wild-type."},"offset":{"type":"number","description":"Override the alignment offset between the reads (whole number, −40 to 40). By default it is found from the base calls upstream of the edit. upstreamIdentity is always measured AT the offset used, so an override that is wrong shows up as a failed same-amplicon check rather than borrowing the auto-detected offset's score."}},"required":["controlBases","controlChannels","editedBases","editedChannels","editKind","editPosition"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/editing_plate_quantify":{"post":{"tags":["Alignment & variants"],"operationId":"editing_plate_quantify","summary":"Editing quantification across a plate (one control, many wells)","description":"Quantify a whole plate of edited samples against ONE untreated control trace and return a single sortable table — the plate-scale form of sanger_indel_spectrum, base_edit_quant and sanger_knockin_quant, chosen with `mode`. Each sample gives one row keyed by its id, carrying the headline number for that mode (edited fraction / editing at the target base / intended knock-in percentage), the fit-quality numbers behind it (R², or the background n and noise floor for base mode), and fitAdequate — the single-sample tool's own gate verdict on that row, so the plate cannot drift from the per-well answer. Failure is isolated per well: a sample whose read is short, mismatched or unfittable becomes a failed ROW with its error message and the other 95 still come back, while an error about the control trace, the mode or the work ceilings throws, because it is wrong for every row. Duplicate sample ids are suffixed (against the whole plate, so the suffix never lands on another well's name) rather than merged. Arguments are strict: an argument belonging to another mode, an unknown argument, an out-of-range limit, and an `offset` override (which is a property of one pair of reads, not of a plate) are all rejected rather than ignored or clamped, because at plate scale a substituted setting rewrites every row identically and nothing in the table looks odd. Returns the rows in input order, a tally, and a CSV. Comparing two wells' percentages is only meaningful when both rows are fitAdequate, which is why the plate summary is computed over those rows alone.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"mode":{"type":"string","enum":["indel","base","knockin"],"description":"Which quantifier to run on every well. \"indel\" = sanger_indel_spectrum (NHEJ efficiency and the indel spectrum; needs cutPosition; blind to substitutions). \"base\" = base_edit_quant (CBE/ABE conversion; needs an editor id + protospacer, or an explicit window with from/to; blind to indels). \"knockin\" = sanger_knockin_quant (a specific intended edit against its byproducts; needs editKind + editPosition). Arguments belonging to another mode are rejected, not ignored."},"controlBases":{"type":"string","residues":"nt","description":"Base calls of the ONE untreated control read (raw or FASTA)."},"controlChannels":{"type":"array","items":{"type":"array","items":{"type":"number","minimum":0}},"description":"Per-base [A, C, G, T] intensities of the control read, one row per called base, read at that base's peak location (trace arrays are indexed by scan, not by base). Raw peak heights: every intensity must be >= 0, because negatives are clamped to zero during normalization and a baseline-subtracted trace would silently lose its minor peaks and read as unedited.","maxItems":3000},"samples":{"type":"array","maxItems":384,"description":"The plate's edited wells, in the order you want them tabulated. Up to 384 samples (96 is the natural plate) and 400,000 trace positions across the whole call, control included — that is already an 8-10 MB request body, so split a plate of untrimmed reads rather than sending one call.","items":{"type":"object","properties":{"id":{"type":"string","description":"Well or sample name — this keys the row. A number is tolerated and read as its digits. Duplicates are suffixed (\"A01#2\", stepping past any name already in use), never merged; an empty or absent id becomes sample_<n>."},"bases":{"type":"string","description":"Base calls of this well's read (raw or FASTA)."},"channels":{"type":"array","items":{"type":"array","items":{"type":"number","minimum":0}},"description":"Per-base [A, C, G, T] intensities for this well, same convention as the control, and non-negative for the same reason."}},"required":["bases","channels"],"additionalProperties":false}},"cutPosition":{"type":"number","description":"indel mode (required): 1-based position of the expected cut, in CONTROL read coordinates. knockin mode (optional): 1-based CONTROL position where UNINTENDED indels start — the nuclease cut or the PE nick; defaults to the edit start."},"maxIndel":{"type":"number","default":10,"description":"indel and knockin modes: largest indel to fit, in bp — a whole number, 1-20. Out of range is rejected, not clamped."},"windowLength":{"type":"number","default":70,"description":"indel and knockin modes: bases downstream used for the decomposition — a whole number, 20-300. Out of range is rejected, not clamped."},"guard":{"type":"number","default":3,"description":"indel mode: bases skipped immediately after the cut, where the trace is least reliable. A whole number >= 0; a negative value is rejected, not clamped to 0."},"editor":{"type":"string","enum":["be3","be4max","abe7.10","abe8e"],"description":"base mode: base editor id (be3, be4max, abe7.10, abe8e) — fixes the converted bases and the activity window in protospacer coordinates. Requires \"protospacer\". Mutually exclusive with windowStart/windowEnd/from/to."},"protospacer":{"type":"string","residues":"nt","description":"base mode: the 20-nt spacer, located in the CONTROL read (either strand; must match exactly once)."},"windowStart":{"type":"number","description":"base mode: explicit window start, 1-based in CONTROL coordinates. Requires windowEnd, from and to."},"windowEnd":{"type":"number","description":"base mode: explicit window end, 1-based inclusive. Window length is capped at 40."},"from":{"type":"string","residues":"nt","description":"base mode: the base the editor converts, as READ on the control strand."},"to":{"type":"string","residues":"nt","description":"base mode: the base it converts to, as READ on the control strand."},"targetPosition":{"type":"number","description":"base mode: 1-based CONTROL position of the intended edit. Give it for a plate. Without it each well's headline is its OWN most-edited significant position, so two rows can be reporting two different bases and the column is not one measurement."},"targetProtospacerPosition":{"type":"number","description":"base mode: 1-based protospacer position of the intended edit (PAM-distal = 1). Editor mode only."},"zThreshold":{"type":"number","default":3,"description":"base mode: significance threshold in standard deviations of each well's own background (1-10; out of range is rejected, not clamped). Raising it raises the reported noise floor with it."},"editKind":{"type":"string","enum":["substitution","insertion","deletion","replacement"],"description":"knockin mode (required): shape of the intended edit. \"substitution\" replaces bases one for one; \"insertion\" adds novel bases and replaces none; \"deletion\" removes bases and adds none; \"replacement\" is the general case where the lengths differ."},"editPosition":{"type":"number","description":"knockin mode (required): 1-based CONTROL position of the first base the edit replaces. An insertion replaces nothing, so there it is the base the insert lands immediately BEFORE — one MORE than the VCF/HGVS anchor."},"refAllele":{"type":"string","residues":"nt","description":"knockin mode: the control bases the edit replaces (substitution and replacement). Checked against the control read once, before any well is fitted."},"altAllele":{"type":"string","residues":"nt","description":"knockin mode: the bases installed in their place."},"insertedSeq":{"type":"string","residues":"nt","description":"knockin mode: the novel bases inserted (insertion only)."},"deletedLength":{"type":"number","description":"knockin mode: how many bases are deleted (deletion only)."}},"required":["mode","controlBases","controlChannels","samples"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/multiplex_panel_design":{"post":{"tags":["Primers & oligos"],"operationId":"multiplex_panel_design","summary":"Multiplex PCR panel design","description":"Choose one primer pair per target so the whole panel works in one tube: no cross-dimer between any two of the primers, every amplicon resolvable from every other on the gel you will run, and one annealing temperature that serves all of them. Searches combinations rather than picking each target's best pair in isolation, which is what makes panels fail — and when no compatible panel exists it names the target pairs that cannot be multiplexed at all, so you know which one to redesign.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"targets":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string","description":"Name for this target, used throughout the result."},"template":{"type":"string","description":"Template sequence, raw or FASTA."},"targetStart":{"type":"number","description":"1-based start of the region the product must span."},"targetEnd":{"type":"number","description":"1-based inclusive end of that region."},"ampliconMin":{"type":"number","description":"Smallest product for THIS target. Giving each target its own size band is how a panel is made readable — leaving them all on one range makes comigration the dominant conflict."},"ampliconMax":{"type":"number","description":"Largest product for this target."}},"required":["template"]},"description":"2-8 targets to amplify in one reaction."},"agarosePercent":{"type":"number","description":"Gel the panel will be read on. Omit and the percentage whose resolving window contains the amplicons is chosen and reported — a panel of small products judged on a 1% gel reads as all-comigrating, which is about the gel rather than the primers."},"dimerThresholdDG":{"type":"number","default":-6,"description":"ΔG (kcal/mol) at or below which a cross-dimer involving a primer's 3' END is a conflict. That end is where extension starts, so it matters at a weaker ΔG than an internal pairing."},"internalDimerThresholdDG":{"type":"number","default":-9,"description":"The looser bar for a cross-dimer that pairs internally and only sequesters primer."},"maxTmSpread":{"type":"number","default":3,"description":"Widest Tm difference tolerated across every primer in the panel, in °C — one annealing temperature has to serve all of them."},"candidatesPerTarget":{"type":"number","default":4,"description":"Candidate pairs considered per target (max 6). More finds a panel where fewer cannot, at the cost of a larger search."},"ampliconMin":{"type":"number","description":"Panel-wide default product size floor, for targets that set none."},"ampliconMax":{"type":"number","description":"Panel-wide default product size ceiling."}},"required":["targets"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/cloning_diagnose":{"post":{"tags":["Enzymes & cloning"],"operationId":"cloning_diagnose","summary":"Cloning failure diagnosis (ranked causes from design + observation)","description":"Work out why a cloning experiment failed: no colonies, every clone empty vector, or no PCR band. Takes your design (method, parts, enzymes, primers, host methylation state) plus what you actually observed (colony counts on the plate and on each control, screening tally, band sizes, whether the ladder ran) and returns causes ranked by evidence — each with the deterministic fact from the design or the observation that implicates it, the cheapest observation that would separate it from the next candidate, and the next experiment. Causes the observations eliminate are reported as eliminated, naming the observation that did it; causes the design makes impossible are not listed. No probability is computed anywhere — the ordering is of evidence, not of likelihood, and `ranking.evidenceBased` says so when the inputs separate nothing.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"symptom":{"type":"string","enum":["no_colonies","wrong_clones","no_pcr_band"],"description":"The complaint. \"no_colonies\" = the plate is blank; \"wrong_clones\" = colonies grew but the clones are empty vector / rearranged / the original template; \"no_pcr_band\" = the gel lane is empty or the band is the wrong size."},"method":{"type":"string","enum":["goldengate","gibson","restriction_ligation","pcr"],"description":"How the construct was made. Decides which cause set applies and which design checks can run."},"parts":{"type":"array","items":{"type":"string"},"maxItems":8,"description":"Parts in assembly order (Golden Gate / Gibson), or [vector, insert] for a restriction ligation. Raw or FASTA. Up to 8; 300,000 bp total across parts and template."},"partNames":{"type":"array","items":{"type":"string"},"description":"Labels for the parts, in the same order (\"backbone\", \"promoter\", \"CDS\"). Used in every fact that names a part."},"enzymes":{"type":"array","items":{"type":"string"},"maxItems":4,"description":"The Type IIS enzyme for Golden Gate (BsaI, BbsI, Esp3I (BsmBI)), or the one or two restriction enzymes the insert and vector were cut with. An unrecognized name is rejected rather than skipped: every methylation and site-geometry verdict here reads \"no site found\" when the enzyme is missing, so a typo would come back as a clean bill of health."},"overlapLen":{"type":"number","default":20,"description":"Gibson only — the homology arm length the assembly was designed with."},"template":{"type":"string","residues":"nt","description":"PCR template, raw or FASTA."},"templateCircular":{"type":"boolean","default":false,"description":"Treat the template as a plasmid, so a product across the origin is found."},"primerForward":{"type":"string","residues":"nt","description":"Forward primer, up to 200 nt."},"primerReverse":{"type":"string","residues":"nt","description":"Reverse primer, up to 200 nt."},"annealingTempC":{"type":"number","description":"Annealing temperature actually used, °C. Compared against each primer's own nearest-neighbor Tm."},"agarosePercent":{"type":"number","default":1,"description":"Agarose percentage of the gel. Snapped to the nearest tabulated value; decides the resolving window a band is placed against."},"hostMethylation":{"type":"string","enum":["dam_dcm_plus","dam_dcm_minus","unknown"],"default":"unknown","description":"Dam/Dcm state of the DNA that was CUT — a property of the strain the plasmid was prepared from, not the one it was transformed into. Standard cloning strains are dam+/dcm+. \"dam_dcm_minus\" eliminates every methylation-blocking cause; \"unknown\" leaves the sequence overlap stated as a fact and the methylation as an open question."},"phosphataseTreated":{"type":"boolean","description":"Was the cut vector dephosphorylated (rSAP/CIP) before ligation?"},"insertSource":{"type":"string","enum":["plasmid_pcr","genomic_pcr","synthesis","digest","unknown"],"description":"Where the insert came from. Only \"plasmid_pcr\" changes a verdict: a plasmid template replicates and selects on its own, so it can give colonies with no ligation at all."},"vectorMarker":{"type":"string","enum":["amp","ampicillin","bla","cam","carb","carbenicillin","chlor","chloramphenicol","gent","gentamicin","hyg","hygromycin","kan","kanamycin","neo","spec","spectinomycin","strep","tet","tetracycline","zeo","zeocin"],"description":"Selection marker on the vector. Compared against the plate's antibiotic by identity, not by guessing at free text."},"plateAntibiotic":{"type":"string","enum":["amp","ampicillin","bla","cam","carb","carbenicillin","chlor","chloramphenicol","gent","gentamicin","hyg","hygromycin","kan","kanamycin","neo","spec","spectinomycin","strep","tet","tetracycline","zeo","zeocin"],"description":"Antibiotic on the plate. amp and carbenicillin count as the same selection (both select bla)."},"colonies":{"type":"number","description":"Colonies on the experimental plate. Omitting this is different from giving 0."},"noDnaControlColonies":{"type":"number","description":"Colonies from the same cells and plate with NO DNA added. Non-zero means the plate is not selecting."},"positiveControlColonies":{"type":"number","description":"Colonies from an intact, uncut plasmid into the same cell aliquot. Non-zero eliminates \"the cells never took up DNA\"."},"positiveControlSameMarker":{"type":"boolean","description":"Did that control plasmid carry the SAME selection marker? If not, it eliminates the cells but says nothing about the plate — the tool reports the difference."},"noInsertControlColonies":{"type":"number","description":"Colonies from the identical reaction with the insert (or one part) left out."},"uncutVectorControlColonies":{"type":"number","description":"Colonies from the digested but UNLIGATED vector. Measures intact vector that survived the digest, with no help from the ligase."},"transformationEfficiencyCfuPerUg":{"type":"number","description":"cfu/µg from a control transformation, where it was measured."},"screened":{"type":"object","properties":{"total":{"type":"number","description":"Clones screened."},"correct":{"type":"number","description":"Clones that were the intended construct."},"emptyVector":{"type":"number","description":"Clones carrying no insert."},"rearranged":{"type":"number","description":"Clones that were a real plasmid but not the intended arrangement of parts."},"originalTemplate":{"type":"number","description":"Clones that turned out to be the plasmid the insert was amplified from."}},"required":["total","correct"],"description":"Screening tally, up to 100,000 clones. The buckets must not add up to more than total — an inconsistent tally is rejected rather than reasoned over, because every verdict drawn from the screen compares a count against that total."},"gelBandsObservedBp":{"type":"array","items":{"type":"number"},"maxItems":30,"description":"Band sizes read off the lane, bp. An empty array (\"I looked and there was nothing\") is not the same as omitting the field."},"ladderRan":{"type":"boolean","description":"Was the ladder itself visible in the same gel? A true here eliminates the whole stain-and-imaging branch in one observation."}},"required":["symptom","method"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/protein_properties":{"post":{"tags":["Proteins & peptides"],"operationId":"protein_properties","summary":"Protein Properties","description":"Protein properties: molecular weight, isoelectric point, GRAVY, extinction coefficient and composition.\n\nBatchable via `POST /batch`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"sequence":{"type":"string","residues":"aa","description":"Protein sequence (one-letter amino-acid codes; non-AA characters ignored)."},"chargeStep":{"type":"number","default":0.25,"minimum":0.001,"maximum":14,"description":"pH step along the net-charge titration curve, which always spans pH 0-14. Between 0.001 and 14."}},"required":["sequence"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/protein_hydrophobicity":{"post":{"tags":["Proteins & peptides"],"operationId":"protein_hydrophobicity","summary":"Hydrophobicity Profile","description":"Sliding-window hydropathy/hydrophobicity profile (ProtScale-style) over a published amino-acid scale.\n\nBatchable via `POST /batch`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"sequence":{"type":"string","residues":"aa","description":"Protein sequence (one-letter amino-acid codes; non-AA characters ignored)."},"scale":{"type":"string","enum":["Kyte-Doolittle","Hopp-Woods","Eisenberg"],"default":"Kyte-Doolittle","description":"Amino-acid scale. Kyte-Doolittle and Eisenberg are hydrophobicity; Hopp-Woods is hydrophilicity."},"window":{"type":"integer","default":9,"description":"Sliding-window size (clamped to an odd number ≥ 1)."}},"required":["sequence"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/protease_digestion":{"post":{"tags":["Proteins & peptides"],"operationId":"protease_digestion","summary":"Protease Digestion","description":"In-silico protease/chemical digestion: cleave a protein and report each peptide's position, length and neutral mass. CNBr masses assume terminal Met becomes homoserine lactone; the sequence retains M and the response labels the modification.\n\nBatchable via `POST /batch`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"sequence":{"type":"string","residues":"aa","description":"Protein sequence (one-letter amino-acid codes; non-AA characters ignored)."},"protease":{"type":"string","enum":["trypsin","lysc","argc","chymotrypsin","gluc","aspn","cnbr"],"default":"trypsin","description":"Protease or chemical cleavage agent."},"missedCleavages":{"type":"integer","enum":[0,1,2],"default":0,"description":"Allowed missed internal cleavages (0–2)."},"minMass":{"type":"number","description":"Optional lower bound on neutral monoisotopic mass (Da)."},"maxMass":{"type":"number","description":"Optional upper bound on neutral monoisotopic mass (Da)."},"maxPeptides":{"type":"integer","default":2000,"description":"Cap on the number of returned peptides."}},"required":["sequence"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/codon_optimize":{"post":{"tags":["Codon usage"],"operationId":"codon_optimize","summary":"Codon optimizer","description":"Codon-optimize a protein (or coding DNA) for an expression host by picking the most-frequent codon per residue.\n\nBatchable via `POST /batch`.\n\nChainable in workflows (passes its `dna` field to the next step).","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"protein":{"type":"string","residues":"any","description":"Protein sequence (one-letter codes). Coding DNA/RNA is accepted and translated in frame +1 up to the first stop codon (residues after an in-frame stop are NOT optimized)."},"organism":{"type":"string","enum":["ecoli","human","yeast","cho","pichia","insect","arabidopsis","zebrafish"],"default":"ecoli"},"inputType":{"type":"string","enum":["auto","protein","dna"],"default":"auto","description":"How to read `protein`. 'auto' guesses from the alphabet (>90% ACGTUN reads as DNA), which mis-files genuine Ala/Cys/Gly/Thr/Asn-only peptides — set 'protein' or 'dna' to force it."}},"required":["protein"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/codon_adaptation_index":{"post":{"tags":["Codon usage"],"operationId":"codon_adaptation_index","summary":"CAI analyzer","description":"Codon Adaptation Index (CAI) and per-codon relative adaptiveness of a CDS against an expression host, with rare-codon and GC3 analysis.\n\nBatchable via `POST /batch`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"sequence":{"type":"string","residues":"nt","description":"Coding sequence (DNA/RNA; should start in-frame at ATG)."},"organism":{"type":"string","enum":["ecoli","human","yeast","cho","pichia","insect","arabidopsis","zebrafish"],"default":"ecoli"},"frameStart":{"type":"integer","default":1,"description":"1-based position to start reading codons."},"rareThreshold":{"type":"number","default":0.1,"description":"Relative adaptiveness (w) below this flags a codon as rare."}},"required":["sequence"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/pairwise_alignment":{"post":{"tags":["Alignment & variants"],"operationId":"pairwise_alignment","summary":"Pairwise Alignment","description":"Global (Needleman-Wunsch), local (Smith-Waterman) or semi-global/fitting pairwise alignment of two sequences, with match/mismatch scoring and affine gap costs (Gotoh).","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"seqA":{"type":"string","residues":"any","description":"First sequence (raw or FASTA; nucleotide or protein)."},"seqB":{"type":"string","residues":"any","description":"Second sequence (raw or FASTA; nucleotide or protein)."},"mode":{"type":"string","enum":["global","local","semiglobal"],"default":"global","description":"\"global\" penalizes end gaps in both sequences; \"local\" returns the best-scoring subalignment; \"semiglobal\" is a fitting alignment — seqB is consumed end to end while seqA's terminal overhangs are free and are not emitted, so a partial read placed on a longer reference is not smeared across it."},"match":{"type":"number","default":1,"description":"Match score."},"mismatch":{"type":"number","default":-1,"description":"Mismatch penalty."},"gap":{"type":"number","default":-2,"description":"Affine gap EXTEND penalty, charged per gap position (including the first)."},"gapOpen":{"type":"number","description":"Extra one-off penalty charged on top of gap for a gap's first position. Defaults to 1.5 * gap, so a k-base gap costs gap * (k + 1.5) and one contiguous k-base indel is cheaper than k scattered 1-base gaps. Pass 0 for a purely linear penalty."}},"required":["seqA","seqB"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/multiple_sequence_alignment":{"post":{"tags":["Alignment & variants"],"operationId":"multiple_sequence_alignment","summary":"Multiple Sequence Alignment","description":"Center-star multiple sequence alignment of a multi-FASTA input — nucleotide or protein, detected from the records and reported as `type` — with consensus and per-column conservation.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"input":{"type":"string","residues":"any","description":"Two or more sequences in multi-FASTA format (>name / sequence), nucleotide or protein. Up to 25 are aligned."}},"required":["input"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/variant_comparator":{"post":{"tags":["Alignment & variants"],"operationId":"variant_comparator","summary":"Variant Comparator","description":"Align a query to a reference and call variants (substitutions, insertions, deletions) in HGVS g. notation, with optional coding effects.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"reference":{"type":"string","residues":"nt","description":"Reference / wild-type sequence (raw or FASTA)."},"query":{"type":"string","residues":"nt","description":"Query / variant sequence (raw or FASTA)."},"coding":{"type":"boolean","default":false,"description":"Treat as a coding sequence and report amino-acid effects."},"frameStart":{"type":"integer","default":1,"description":"1-based reading-frame start (used when coding is true)."}},"required":["reference","query"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/sanger_plate_verify":{"post":{"tags":["Alignment & variants"],"operationId":"sanger_plate_verify","summary":"Sanger plate clone verdicts","description":"Judge a whole plate of Sanger reads against one construct and return one row per clone: PASS, POINT_MUTATION, INDEL, VECTOR_ONLY (the insert is absent), WRONG_INSERT (the backbone matches and the insert does not), LOW_COVERAGE, or AMBIGUOUS. Reads are grouped into clones from their FASTA/FASTQ record names (facility conventions like PlateA_A01_pXY-1_M13F, pXY-1_T7-F, 2026-08-01_pXY_clone3_R), and every read's assignment is reported with a confidence so a grouping can be corrected rather than trusted. Each clone's reads are piled up in reference coordinates, so a difference one read reports where other covering reads read the reference is reported as the sequencing error it is, not as a mutation — and a position no read covered is never PASS. Every verdict cites the positions it rests on. Give insertStart/insertEnd to have clones judged over the insert alone, which is also what VECTOR_ONLY and WRONG_INSERT need.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"reference":{"type":"string","residues":"nt","description":"The intended construct (raw or FASTA). Up to 20,000 bp."},"reads":{"type":"string","description":"All the plate's reads as FASTA or FASTQ (auto-detected). The record name is what the clone grouping is read from. Up to 384 reads / 400,000 total bases, and (reference length x total read bases) must stay under 200,000,000 — split a 96-clone plate across calls.","maxLength":2000000},"circular":{"type":"boolean","default":false,"description":"Treat the construct as a plasmid, so a read crossing its arbitrary linear start is aligned through the join instead of having its tail discarded."},"insertStart":{"type":"integer","minimum":1,"description":"1-based first base of the stretch that has to be right (the insert). With insertEnd, every clone is judged over this span alone — the only honest framing when one 900 bp read cannot cover a 6 kb plasmid — and VECTOR_ONLY/WRONG_INSERT become reachable. May be greater than insertEnd on a circular construct, meaning the span crosses the origin."},"insertEnd":{"type":"integer","minimum":1,"description":"1-based last base of that stretch."},"insertLabel":{"type":"string","description":"What to call it in the verdicts. Default \"the insert\"."},"grouping":{"type":"string","enum":["auto","one-clone","per-read"],"default":"auto","description":"How reads become clones. \"auto\" parses the record names; \"one-clone\" treats every read as being of one clone (use when the names carry nothing); \"per-read\" judges each read on its own."},"trimThreshold":{"type":"integer","default":20,"minimum":0,"maximum":60,"description":"Phred threshold for trimming both ends of a read (BWA's rule). Only applies to FASTQ input, which is the only input that carries quality."},"qualityOffset":{"type":"integer","enum":[33,64],"default":33,"description":"ASCII offset of the FASTQ quality string. 33 for anything modern, 64 for pre-1.8 Illumina."}},"required":["reference","reads"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/crispr_grna_design":{"post":{"tags":["CRISPR"],"operationId":"crispr_grna_design","summary":"CRISPR gRNA designer","description":"Find and score candidate guide RNAs (protospacer + PAM) in a target DNA for common nucleases (SpCas9, SpCas9-NG, SaCas9, Cas12a).\n\nBatchable via `POST /batch`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"sequence":{"type":"string","residues":"nt","description":"Nucleotide sequence (raw or FASTA; IUPAC accepted)."},"nuclease":{"type":"string","enum":["spcas9","spcas9ng","sacas9","cas12a"],"default":"spcas9","description":"Nuclease id. Omit to just list the available nucleases (no scan is performed)."},"searchReverseStrand":{"type":"boolean","default":true,"description":"Also scan the reverse strand for guides."},"minScore":{"type":"number","default":0,"description":"Only return guides with a heuristic score at least this high (0–100)."}},"required":["sequence"],"additionalProperties":false},"example":{"sequence":"ATGGCCAAGCTGACCGAACTGAAAGCCGCCGTGGAAACCCTGGATAAAGCCTTCAAAGATGCCCTGAAAGCC"}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/crispr_offtarget_check":{"post":{"tags":["CRISPR"],"operationId":"crispr_offtarget_check","summary":"CRISPR guide off-target check","description":"Screen a guide's protospacer for off-target sites (protospacer match + valid PAM, both strands) against a small curated set of common lab reference genomes (see genomesChecked) — NOT a whole human/mouse genome search. For SpCas9 with a 20 nt spacer each site also gets a Doench 2016 CFD score, so sites are ranked by predicted cut likelihood rather than by mismatch count alone, and the guide gets an aggregate specificity. Use this the same way primer_specificity is used: a useful sanity check within the covered organisms, not a clearance guarantee for a mammalian expression host.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"protospacer":{"type":"string","residues":"nt","maxLength":32,"description":"The guide's protospacer sequence, 5'→3' (no PAM). Max 32 nt — every supported nuclease uses a 20–23 nt guide."},"nuclease":{"type":"string","enum":["spcas9","spcas9ng","sacas9","cas12a"],"default":"spcas9","description":"Nuclease id — determines the PAM pattern/side required at each candidate site."},"maxMismatches":{"type":"integer","default":2,"minimum":0,"maximum":4,"description":"Mismatches tolerated between the protospacer and a candidate genomic site. Max 4 — a complete search seeds on maxMismatches+1 non-overlapping blocks, and past that the blocks are too short to be selective against a multi-Mb genome (a site that mismatched more would not be cut anyway)."}},"required":["protospacer"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/crispr_hdr_donor":{"post":{"tags":["CRISPR"],"operationId":"crispr_hdr_donor","summary":"HDR donor designer","description":"Build an HDR donor (homology arms flanking an edit) from a target sequence and either an explicit edit window (editStart/editEnd) or a guide's cut site (guideStart/guideEnd/guideStrand/nuclease — SpCas9-family only; Cas12a's staggered cut needs an explicit editStart/editEnd). Also designs genotyping primers spanning the edit site on the original sequence (a real size-shift or sequencing target to confirm the edit), reusing the same primer-design engine as primer_design.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"targetSequence":{"type":"string","residues":"nt","description":"Nucleotide sequence (raw or FASTA; IUPAC accepted)."},"editStart":{"type":"integer","description":"1-based start of the region being replaced. Omit to derive from guideStart/guideEnd/guideStrand instead."},"editEnd":{"type":"integer","description":"1-based inclusive end of the region being replaced; editEnd = editStart-1 denotes a pure insertion with nothing removed. Omit to derive from the guide's cut site."},"guideStart":{"type":"integer","description":"1-based forward-strand start of the guide's protospacer (alternative to editStart/editEnd, for an insertion exactly at the cut site)."},"guideEnd":{"type":"integer","description":"1-based forward-strand end of the guide's protospacer."},"guideStrand":{"type":"string","enum":["+","-"],"description":"Strand the guide's protospacer is on."},"nuclease":{"type":"string","enum":["spcas9","spcas9ng","sacas9","cas12a"],"default":"spcas9","description":"Needed only when deriving the cut site from guideStart/guideEnd/guideStrand."},"replacement":{"type":"string","default":"","description":"Sequence to insert/substitute (\"\" for a pure deletion)."},"armLength":{"type":"integer","default":500,"description":"Homology arm length (bp) on each side. Use ~30–60 for an ssODN donor, ~500–1000 for a dsDNA donor plasmid."},"designGenotypingPrimers":{"type":"boolean","default":true,"description":"Also design a primer pair (on the original targetSequence) whose product spans the edit site."},"blockPam":{"type":"boolean","default":true,"description":"When a SpCas9-family guide is supplied and the edit does not already disrupt its PAM, fold a PAM-blocking mutation (silent when a CDS frame is given) into the donor so the edited allele can't be re-cut."},"frameStart":{"type":"integer","description":"Optional 1-based CDS reading-frame start; makes the PAM-blocking mutation synonymous where possible."}},"required":["targetSequence","replacement"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/crispr_ontarget":{"post":{"tags":["CRISPR"],"operationId":"crispr_ontarget","summary":"CRISPR on-target activity (Rule Set 3)","description":"Score SpCas9 guides for on-target activity with Rule Set 3 (DeWeirdt et al., Nat Commun 2022) — the current successor to the Doench 2014 and CRISPRscan scores crispr_grna_design reports. Give a target sequence to find and score every NGG guide in it, or give 30-mer contexts directly. The tracrRNA MATTERS and is not cosmetic: Rule Set 3 models it as a feature, and the paper measures its accuracy dropping when the wrong one is specified. Returns a z-scored activity, which ranks guides against each other; it is not a percentage and not a probability of editing.","requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"sequence":{"type":"string","residues":"nt","description":"Target DNA to find NGG guides in. Give this OR `contexts`."},"contexts":{"type":"array","items":{"type":"string"},"description":"30-mer contexts to score directly: 4 nt upstream + 20 nt spacer + PAM + 3 nt downstream. Give this OR `sequence`."},"tracr":{"type":"string","enum":["Hsu2013","Chen2013"],"default":"Hsu2013","description":"Which tracrRNA the guides will be paired with. Hsu2013 is the one in lentiCRISPRv2 and most published libraries; Chen2013 is the sgRNA(F+E) scaffold used by the Sanger/Yusa libraries. If you use the DeWeirdt (2020) tracrRNA, the paper reports Chen2013 as the better proxy — there is no DeWeirdt option in the model itself."}},"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/elsa_capacity":{"post":{"tags":["CRISPR"],"operationId":"elsa_capacity","summary":"How many sgRNAs fit in one non-repetitive array","description":"Report how many promoters, sgRNA handles and neutral spacers are available at each maximum-shared-length threshold, and therefore the longest extra-long sgRNA array that can be built without reusing a part. Ask this before designing: the answer is a property of the measured parts collection, not of your guides, and it is the constraint that decides the design. Deterministic — it is a selection over a fixed table.","requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"lmax":{"type":"integer","minimum":8,"maximum":40,"description":"Report a single threshold. Omit to get the whole curve from 8 to 24."}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/elsa_design":{"post":{"tags":["CRISPR"],"operationId":"elsa_design","summary":"Design an extra-long sgRNA array","description":"Build a multiplexed CRISPR array that expresses many sgRNAs from one cassette and shares no long stretch with itself. Twenty sgRNAs built the obvious way carry twenty copies of the same Cas9 scaffold, promoter and terminator — a construct that recombines in the cell and that synthesis vendors refuse — so this draws each transcription unit's parts from the measured non-repetitive collection of Reis et al. (2019), selecting ACROSS promoters, handles and spacers at once rather than within each type, then re-measures the assembled molecule for repeats the junctions created. Returns the sequence, an annotated GenBank file and the pool usage. Takes guides; it does not choose or score them — use crispr_grna_design and crispr_offtarget_check for that.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"guides":{"type":"array","items":{"type":"string"},"description":"The 20 nt protospacers, in array order, WITHOUT their PAM. Strings, or {name, sequence} objects to label each unit. Max 27 — the size of the handle collection."},"lmax":{"type":"integer","default":12,"minimum":8,"maximum":40,"description":"Longest stretch any two parts in the array may share, in bp (default 12). Lower is more stable and leaves fewer parts to choose from: the handle pool offers 12 at lmax 12, 18 at 15 and 24 at 20. Run elsa_capacity first."},"insulate":{"type":"boolean","default":true,"description":"Place a neutral spacer between transcription units. Turning it off frees the spacer pool from the selection, which can let a longer array fit at a low lmax."},"name":{"type":"string","description":"LOCUS name for the GenBank output."},"includeGenbank":{"type":"boolean","default":true,"description":"Return the annotated GenBank file."}},"required":["guides"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/parse_genbank":{"post":{"tags":["Files & formats"],"operationId":"parse_genbank","summary":"GenBank Parser","description":"Parse a GenBank flat file into its locus, definition, features and sequence.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"text":{"type":"string","description":"A GenBank flat file (LOCUS … FEATURES … ORIGIN … //)."}},"required":["text"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/sequence_format_convert":{"post":{"tags":["Files & formats"],"operationId":"sequence_format_convert","summary":"Sequence Format Converter","description":"Convert between FASTA and GenBank (whole sequence, CDS or protein), or export to TSV.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"input":{"type":"string","description":"A FASTA or GenBank record to convert."},"from":{"type":"string","enum":["auto","fasta","genbank"],"default":"auto","description":"Input format; 'auto' sniffs it from the first meaningful line."},"to":{"type":"string","enum":["fasta","fasta-cds","fasta-protein","genbank","tsv","snapgene"],"default":"fasta","description":"Output format. fasta-cds / fasta-protein extract CDS features (GenBank input only). GenBank in and 'genbank' out rewrites the record with its features, qualifiers and topology intact — it is a rewrite, not a re-annotation. 'snapgene' writes a binary SnapGene .dna file, returned base64 in `fileBase64` rather than in `output`; it takes ONE record, because a .dna holds one molecule."}},"required":["input"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/seqfile_stats":{"post":{"tags":["Files & formats"],"operationId":"seqfile_stats","summary":"FASTA/FASTQ Stats","description":"Statistics for a FASTA or FASTQ file: count, length distribution, N50, GC content and (FASTQ) mean quality.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"input":{"type":"string","description":"FASTA or FASTQ text (raw sequence is treated as single-record FASTA)."},"qualityOffset":{"type":"integer","enum":[33,64],"default":33,"description":"ASCII offset of the FASTQ quality string. 33 for anything modern, 64 for pre-1.8 Illumina."}},"required":["input"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/parse_sanger_trace":{"post":{"tags":["Files & formats"],"operationId":"parse_sanger_trace","summary":"Sanger Trace Parser","description":"Decode a Sanger ABIF (.ab1 / .abi) chromatogram: base calls, per-base quality, the four dye-channel traces, peak locations, and the run's own labels (sample name, well, plate, instrument, run start).","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"fileBase64":{"type":"string","description":"The binary ABIF (.ab1 / .abi) trace file, base64-encoded."},"fileName":{"type":"string","description":"Optional original file name (echoed back)."},"includeTraces":{"type":"boolean","default":false,"description":"Include the four raw dye-channel arrays and peakLocations. They are 93% of the response — a 900-base read is 122 kB with them and 8 kB without (measured) — and they are only useful for DRAWING the chromatogram. Everything you would reason about (base calls, quality, the run's labels) is returned either way, so leave this off unless you are rendering."}},"required":["fileBase64"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/sanger_vs_reference":{"post":{"tags":["Files & formats"],"operationId":"sanger_vs_reference","summary":"Sanger vs Reference","description":"Align a Sanger ABIF read to a reference and report identity plus every mismatch, insertion and deletion.\n\nBatchable via `POST /batch`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"fileBase64":{"type":"string","description":"The binary ABIF (.ab1 / .abi) trace file, base64-encoded."},"read":{"type":"string","residues":"nt","description":"Sanger read as FASTA or raw text (alternative to uploading an ABIF trace). Also the per-record field for plate-batch runs via /api/v1/batch."},"reference":{"type":"string","residues":"nt","description":"Expected reference sequence (FASTA or raw)."},"fileName":{"type":"string","description":"Optional original file name (echoed back)."},"minCoverage":{"type":"number","default":0.9,"description":"Fraction of the reference the read must span before a PASS is meaningful; below this the verdict is 'ambiguous_low_coverage' regardless of identity. Lower it when the reference is intentionally just the region/junction being checked."}},"required":["reference"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/parse_snapgene":{"post":{"tags":["Files & formats"],"operationId":"parse_snapgene","summary":"SnapGene .dna Parser","description":"Read a SnapGene .dna file: sequence, topology, every feature with its span, strand, display color and qualifiers (spliced and origin-spanning features kept as such), and the saved primer list.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"fileBase64":{"type":"string","maxLength":43000000,"description":"The binary SnapGene .dna file, base64-encoded. A `data:...;base64,` prefix is accepted."},"fileName":{"type":"string","description":"Optional original file name (echoed back)."},"includeSequence":{"type":"boolean","default":true,"description":"Include the full sequence. Turn it off to ask what is IN a construct without moving the bases: a 250 kb BAC is 244 kB of the response and length/topology/features answer most questions without it."},"featureLimit":{"type":"integer","minimum":1,"maximum":2000,"default":2000,"description":"Cap on features returned (max 2000). featureCount always reports the true total and `truncated` says whether the list was cut."}},"required":["fileBase64"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/sanger_assemble":{"post":{"tags":["Files & formats"],"operationId":"sanger_assemble","summary":"Sanger de novo assembly","description":"Assemble two or more Sanger reads into a contig WITHOUT a reference sequence — the forward/reverse pair of one insert, or a set of tiling reads. Orientation is worked out from the overlaps, ends are quality-trimmed, and the consensus is quality-weighted. Reports depth and agreement per position, every position where the reads disagree (including a base only one read has), and any read that overlapped nothing. Use sanger_vs_reference instead when you already know what the sequence should be.","requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"reads":{"type":"array","items":{"type":"object"},"description":"The reads, as [{name, sequence, quality?}]. `quality` is a per-base Phred array the same length as `sequence`; without it the read still assembles but its ends are NOT trimmed, which the result says."},"fasta":{"type":"string","residues":"nt","description":"Alternative to `reads`: a multi-record FASTA of the reads. No quality, so no end trimming."},"minOverlap":{"type":"integer","default":30,"description":"Shortest overlap that may join two reads."},"minIdentity":{"type":"number","default":85,"description":"Lowest percent identity an overlap may have."},"trimThreshold":{"type":"number","description":"Phred threshold for end-trimming. Ignored for reads with no quality array."},"noTrim":{"type":"boolean","default":false,"description":"Assemble the reads exactly as given, with no quality trimming."}},"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/characterize_sequence":{"post":{"tags":["Analysis"],"operationId":"characterize_sequence","summary":"Characterize sequence","description":"One-paste 'tell me everything': auto-detects DNA/RNA/protein, then reports composition, ORFs, single-cutter enzymes, end primers or protein properties, plus a BLAST link.\n\nBatchable via `POST /batch`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"sequence":{"type":"string","residues":"any","description":"Nucleotide or protein sequence (raw or FASTA; IUPAC accepted). The alphabet is detected."},"minOrfAa":{"type":"integer","default":40,"description":"Minimum ORF length in amino acids (nucleotide input only)."},"maxOrfs":{"type":"integer","default":8,"description":"Maximum number of ORFs to return, longest first."},"endPrimerLength":{"type":"integer","default":20,"description":"Length of the naive end primers taken from each end."}},"required":["sequence"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/sequence_report":{"post":{"tags":["Analysis"],"operationId":"sequence_report","summary":"Sequence report","description":"One-click DNA analysis: composition, ORFs, restriction-enzyme scan (single cutters) and end-primer Tm composed into a single report with a copyable text block.\n\nBatchable via `POST /batch`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"sequence":{"type":"string","residues":"nt","description":"Nucleotide sequence (raw or FASTA; IUPAC accepted)."},"minOrfAa":{"type":"integer","default":50,"description":"Minimum ORF length in amino acids."},"maxOrfs":{"type":"integer","default":10,"description":"Maximum number of ORFs to return, longest first."},"endPrimerLength":{"type":"integer","default":20,"description":"Length of the naive end primers taken from each end."}},"required":["sequence"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/session_create":{"post":{"tags":["Analysis"],"operationId":"session_create","summary":"Create a design session","description":"Start a scratch session that holds several named sequences/values (e.g. vector, insert, forward/reverse primer) for use across multiple tool calls via session_run, instead of re-pasting them into every call. Sessions expire after 24 hours.","requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"entries":{"type":"object","additionalProperties":{"type":"string"},"description":"Initial named entries, e.g. {\"vector\": \"...\", \"insert\": \"...\"}. Optional — you can also add entries later with session_set."}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/session_get":{"post":{"tags":["Analysis"],"operationId":"session_get","summary":"Read a design session","description":"Fetch named entries from a session. Prefer session_run for actually USING the values — it keeps raw sequences out of your context. Use this mainly to inspect or debug what a session currently holds.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"sessionId":{"type":"string"},"names":{"type":"array","items":{"type":"string"},"description":"Only return these entries; omit to return all of them."}},"required":["sessionId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/session_set":{"post":{"tags":["Analysis"],"operationId":"session_set","summary":"Write to a design session","description":"Add or overwrite named entries in an existing session.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"sessionId":{"type":"string"},"entries":{"type":"object","additionalProperties":{"type":"string"},"description":"Named entries to add/overwrite, e.g. {\"insert\": \"...\"}."}},"required":["sessionId","entries"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/session_run":{"post":{"tags":["Analysis"],"operationId":"session_run","summary":"Run a tool using session entries","description":"Run any SeqBench tool, resolving selected arguments from a session's named entries instead of pasting them inline, and optionally store selected result fields back into the session by name. This is the main way to chain a multi-part design (vector + insert + primers) across calls without shuttling raw sequences through your own context.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"sessionId":{"type":"string"},"tool":{"type":"string","description":"Name of any non-meta SeqBench tool (not batch, workflow, or another session_* tool)."},"fromSession":{"type":"object","additionalProperties":{"type":"string"},"description":"Map of { toolArgName: sessionEntryName } — resolves each named tool argument from the session before running."},"args":{"type":"object","additionalProperties":true,"description":"Additional literal arguments, merged with the ones resolved from the session."},"writeBack":{"type":"object","additionalProperties":{"type":"string"},"description":"Map of { resultFieldName: sessionEntryName } — stores selected fields of the result back into the session under these names."}},"required":["sessionId","tool"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/sequence_fetch":{"post":{"tags":["Files & formats"],"operationId":"sequence_fetch","summary":"Fetch sequence by accession","description":"Fetch a public DNA/protein record by accession from NCBI Nucleotide, NCBI Protein, UniProt, or Ensembl (e.g. NM_000546, NP_000537, P04637, ENSG00000141510). Only the accession is sent upstream. Use sequence_search first if you only know a gene/organism name, not an accession. For an Ensembl transcript ID this returns spliced cDNA; for a gene ID it returns the full genomic locus (introns included) — Ensembl's own default for each ID type.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"accession":{"type":"string","description":"GenBank/RefSeq accession (e.g. NM_000546), UniProtKB accession (e.g. P04637), or Ensembl stable ID (e.g. ENSG00000141510, ENST00000335137)."},"db":{"type":"string","enum":["auto","nucleotide","protein","uniprot","ensembl"],"default":"auto","description":"Database to query; auto-detects from the accession format."},"format":{"type":"string","enum":["fasta","genbank"],"default":"fasta","description":"Output format (GenBank is only available for NCBI accessions — UniProt and Ensembl are FASTA-only)."}},"required":["accession"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/sequence_search":{"post":{"tags":["Files & formats"],"operationId":"sequence_search","summary":"Search sequence databases by name","description":"Resolve a gene/organism name — or a raw NCBI search term — to candidate accessions, instead of guessing one. Returns up to maxResults hits (accession, title, organism); pass the accession you want to sequence_fetch.","requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"gene":{"type":"string","description":"Gene symbol/name, e.g. \"BRCA1\". Combined with organism (if given) into a search term."},"organism":{"type":"string","description":"Organism name, e.g. \"Homo sapiens\". Optional; narrows the gene search."},"term":{"type":"string","description":"Raw NCBI search term (advanced) — overrides gene/organism when given, e.g. \"BRCA1[gene] AND Homo sapiens[orgn]\"."},"db":{"type":"string","enum":["nucleotide","protein"],"default":"nucleotide"},"maxResults":{"type":"integer","minimum":1,"maximum":20,"default":5,"description":"Up to 20."}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/protein_annotate_submit":{"post":{"tags":["Proteins & peptides"],"operationId":"protein_annotate_submit","summary":"Submit a protein for domain/GO annotation","description":"Submit a protein sequence to EBI InterProScan for domain architecture, family and GO-term annotation. Returns a jobId immediately — the job itself takes minutes; poll it with protein_annotate_poll.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"sequence":{"type":"string","description":"Protein sequence, one-letter code (FASTA header, if any, is stripped)."},"appl":{"type":"string","description":"Restrict to one member database (e.g. \"PfamA\"); omit to run EBI's defaults across all of them."},"goterms":{"type":"boolean","default":true,"description":"Include GO-term cross-references."}},"required":["sequence"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/protein_annotate_poll":{"post":{"tags":["Proteins & peptides"],"operationId":"protein_annotate_poll","summary":"Poll a protein annotation job","description":"Check an InterProScan job submitted via protein_annotate_submit. Returns {status, ready:false} while still running; once FINISHED, also returns the parsed domain architecture, per-match details and deduplicated GO terms.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"jobId":{"type":"string"}},"required":["jobId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/plasmid_identify":{"post":{"tags":["Enzymes & cloning"],"operationId":"plasmid_identify","summary":"Identify an unknown plasmid","description":"Screen a query plasmid against a small curated set of common backbones (cloning vectors, expression vectors, BACs — see referencesChecked for the exact list) to identify which one(s) it resembles, separate an unmatched region (normal — your own insert) from a POSSIBLE CHIMERA (a region matching a different known backbone than its neighbor), and report per-match %identity/%coverage. NOT a search against Addgene's ~100k-plasmid catalog or PlasmidScope's 850k+ — a curated-set screen only.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"sequence":{"type":"string","residues":"nt","description":"Nucleotide sequence (raw or FASTA; IUPAC accepted)."},"circular":{"type":"boolean","default":true,"description":"Treat the query as a circular molecule (most plasmids are)."},"topN":{"type":"integer","default":5,"description":"How many top-ranked backbone candidates to report."}},"required":["sequence"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/plasmid_full_report":{"post":{"tags":["Enzymes & cloning"],"operationId":"plasmid_full_report","summary":"Plasmid full report (identity + features + unexplained regions)","description":"One combined view of 'what is this plasmid': recognized common features (from plasmid_annotate), backbone identity / possible chimera (from plasmid_identify), and — the two crossed together — any region that neither a curated backbone nor a recognized common feature explains. That last list is a triage signal (an unusual insert, an unannotated part, or worth a closer look), not a defect finding: a real gene-of-interest legitimately has no curated-feature match.\n\nBatchable via `POST /batch`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"sequence":{"type":"string","residues":"nt","description":"Nucleotide sequence (raw or FASTA; IUPAC accepted)."},"circular":{"type":"boolean","default":true,"description":"Treat the query as a circular molecule (most plasmids are)."},"topN":{"type":"integer","default":5,"description":"How many top-ranked backbone candidates to report."}},"required":["sequence"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/plasmid_deep_annotate":{"post":{"tags":["Enzymes & cloning"],"operationId":"plasmid_deep_annotate","summary":"Deep plasmid annotation (pLannotate)","description":"Annotate a plasmid against pLannotate's open-source feature library — a much larger signature set (GenoLIB parts + Swiss-Prot + FPbase + Rfam, cross-referenced against ~195k Addgene-deposited plasmids) than plasmid_annotate's built-in curated list, and it reports partial and low-identity hits as graded alignments rather than the pass/fail signature match plasmid_annotate does (that one is not exact-only either — signatures of 20 bp or more tolerate up to ~10% mismatches — but it reports a hit or nothing, with a `mismatches` count and an `exact` flag). Each feature here carries its percent identity, reference coverage and a fragment flag so you can judge a weak hit. Runs a multi-second search on a shared service and is therefore rate limited (see 429/503); use plasmid_annotate for an instant, unmetered first pass.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"sequence":{"type":"string","description":"Nucleotide sequence (raw or FASTA). A, C, G, T, N only — other IUPAC codes are rejected rather than silently dropped, because pLannotate's search engines discard them and every coordinate after would shift. Max 150,000 bp."},"circular":{"type":"boolean","default":true,"description":"Treat the sequence as a circular plasmid (vs. linear)."}},"required":["sequence"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/verify_construct":{"post":{"tags":["Enzymes & cloning"],"operationId":"verify_construct","summary":"Verify a claimed construct","description":"Re-derive a construct's insert from the PCR (template + primers) claimed to have produced it, then check — independently of that claim — whether the expected insert actually appears (either orientation) in the claimed final construct, at what identity, and with exact mismatch positions if not. Optionally also checks for a premature stop in a declared reading frame. Primers may carry a non-templated 5' tail (a restriction site, a Gibson arm, a tag): a construct missing ONLY tail bases still passes, since that is exactly what digesting a tailed amplicon removes before ligation — see match.templateCoveragePct and match.unalignedIsTailOnly, and note the pass does not establish that the right enzyme made the cut. This re-derives from the claim's own stated inputs; it does not review the claim's prose.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"claimedConstruct":{"type":"string","residues":"nt","description":"The final sequence claimed to have been built."},"insertTemplate":{"type":"string","residues":"nt","description":"PCR template the insert was amplified from."},"insertForwardPrimer":{"type":"string","residues":"nt","description":"Forward primer used to amplify the insert, 5'→3'."},"insertReversePrimer":{"type":"string","residues":"nt","description":"Reverse primer used to amplify the insert, 5'→3'."},"templateCircular":{"type":"boolean","default":false,"description":"Treat insertTemplate as circular (e.g. amplifying from a plasmid)."},"constructCircular":{"type":"boolean","default":false,"description":"Treat claimedConstruct as a circular plasmid, so an insert that spans its arbitrary numbering origin is found whole. Without it the insert is looked for linearly and a wrapped one covers only its longer half."},"maxPrimerMismatches":{"type":"integer","default":0,"minimum":0,"maximum":10,"description":"Mismatches tolerated per primer during PCR prediction (0–10)."},"expectedFrameStart":{"type":"integer","description":"1-based position in claimedConstruct where the intended reading frame begins. If given, flags a premature stop before the end of the aligned insert region."}},"required":["claimedConstruct","insertTemplate","insertForwardPrimer","insertReversePrimer"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/verify_assembly":{"post":{"tags":["Enzymes & cloning"],"operationId":"verify_assembly","summary":"Verify a full assembly recipe","description":"Deterministic self-check: given the same method/parts cloning_simulate would use (restriction-ligation, Gibson, Golden Gate, LIC, SLIC or In-Fusion/CPEC — optionally deriving a part by in-silico PCR first), re-derive the expected WHOLE product and diff it against a claimed final sequence. Returns pass/fail plus the exact position and nature of any discrepancy — not an opinion, the same deterministic simulation SeqBench already runs, run a second time as a check. A recipe that can give more than one molecule is checked against ALL of them and `matchedCandidate` names the one the claim matched: a non-directional ligation really does put the insert in both ways round (half the plate carries each), a vector cut more than twice offers more than one backbone, and a Gibson junction whose fragments already share terminal sequence has two honest readings (one homology arm, or a tandem repeat present twice). See verify_construct for a narrower, insert-only check that doesn't require declaring the vector/enzymes/method.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"method":{"type":"string","enum":["restriction","gibson","goldengate","lic","slic","infusion"],"description":"Assembly method used. restriction/gibson/goldengate are the primer-and-enzyme methods; lic and slic re-run the T4-polymerase chew-back (sequence-defined and time-stopped respectively) and infusion is In-Fusion/CPEC. Anything else is refused rather than substituted — see the note on \"topo\"."},"claimedConstruct":{"type":"string","residues":"nt","description":"The sequence you claim you ended up with."},"circular":{"type":"boolean","default":true,"description":"Treat the product/claimed construct as circular (most plasmids are)."},"coding":{"type":"boolean","default":false,"description":"Report amino-acid effects of any mismatch, assuming claimedConstruct is (or contains) a coding sequence."},"frameStart":{"type":"integer","default":1,"description":"1-based reading-frame start on claimedConstruct, used when coding is true."},"vector":{"type":"string","residues":"nt","description":"Vector sequence (restriction and lic methods; for lic, the LINEARIZED vector). Omit if vectorPcr is given."},"vectorPcr":{"type":"object","description":"Derive the vector by PCR instead: {template, forwardPrimer, reversePrimer, maxMismatches? (0-10), circular?}."},"insert":{"type":"string","residues":"nt","description":"Insert sequence (restriction and lic methods). Omit if insertPcr is given."},"insertPcr":{"type":"object","description":"Derive the insert by PCR instead: {template, forwardPrimer, reversePrimer, maxMismatches? (0-10), circular?}."},"enzyme5":{"type":"string","default":"EcoRI","description":"Insert 5′ enzyme (restriction method)."},"enzyme3":{"type":"string","default":"BamHI","description":"Insert 3′ enzyme (restriction method)."},"vectorEnzyme5":{"type":"string","description":"Vector 5′ enzyme (restriction method); defaults to enzyme5. Set a different, compatible enzyme (e.g. BglII for a BamHI insert) to verify heterologous-overhang cloning."},"vectorEnzyme3":{"type":"string","description":"Vector 3′ enzyme (restriction method); defaults to enzyme3."},"dephosphorylateVector":{"type":"boolean","default":false,"description":"The linearized vector was CIP/rSAP-dephosphorylated (restriction method). Affects the self-ligation background warnings, not the product."},"fragments":{"type":"array","items":{"type":"string"},"maxItems":24,"description":"Fragments (5′→3′), assembled head-to-tail (gibson/goldengate/slic/infusion). BARE parts only — for gibson do NOT include the homology arms, which are added by the assembly primers and merged (so the product is fragment1+…+fragmentN). The convention is the OPPOSITE for slic and infusion: there the homology must already BE on the fragments (it arrived on the PCR primer tails), and infusion derives the ORDER from those homologies, so the order listed here is ignored. Use \"\" as a placeholder for any fragment supplied instead via the matching fragmentPcrs[i]."},"fragmentPcrs":{"type":"array","items":{"type":"object"},"description":"Parallel to fragments, same length: null (or omit) to use fragments[i] directly, or a PCR spec {template, forwardPrimer, reversePrimer, maxMismatches? (0-10), circular?} to derive that fragment instead."},"names":{"type":"array","items":{"type":"string"},"description":"Optional labels for each fragment."},"overlapLen":{"type":"integer","default":20,"description":"Gibson homology-arm length (bp) that the assembly PRIMERS add at each junction. Since the fragments themselves must not carry their arms, this describes the junction/primer design only — it does not change the predicted product length or the verdict."},"mergePreAddedArms":{"type":"boolean","default":true,"description":"Gibson only. When two fragments already share terminal sequence, count that share ONCE (the default — the fragments already carry their arm) or set false to concatenate it twice, which is the right reading when the shared block is a genuine tandem repeat. You should rarely need this: the check tries BOTH readings and reports which one matched in `matchedCandidate`. Setting it restricts the check to one."},"armTmTarget":{"type":"number","default":60,"description":"Target annealing Tm (°C) for primer arms."},"enzyme":{"type":"string","default":"BsaI","description":"Type IIS enzyme for Golden Gate — one of BsaI, BbsI, Esp3I (BsmBI); \"BsmBI\" also resolves to Esp3I, and NEB's variant names (BsaI-HFv2, BbsI-HF, BsmBI-v2) fold to the parent enzyme. Any other name fails the verification outright rather than being substituted."},"vectorNucleotide":{"type":"string","enum":["A","C","G","T"],"description":"lic method: the single dNTP the VECTOR's chew-back was run with (T for dTTP…). Required — T4 pol's exonuclease stops at the first occurrence of this base reading inward from each 3′ end, so there is no product to check against without it."},"insertNucleotide":{"type":"string","enum":["A","C","G","T"],"description":"lic method: the single dNTP the INSERT's chew-back was run with. Normally the COMPLEMENT of vectorNucleotide (the classic pair is dTTP on the vector, dATP on the insert)."},"chewBackLen":{"type":"integer","default":0,"minimum":0,"description":"slic method: nucleotides removed from each 3′ end. A SLIC chew-back has no dNTP to arrest it and is stopped by time, so this is an input rather than a property of the sequence. 0 (default) models the intended reaction — chewed to the full homology and no further."},"homologyLen":{"type":"integer","default":15,"minimum":15,"description":"infusion method: terminal homology required at every junction, in bp. At least 15 — the junction is annealed and extended by a polymerase with no exonuclease to widen it and no ligase to seal it, so a shorter overlap is a different chemistry rather than a weaker version of this one."}},"required":["method","claimedConstruct"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/golden_gate_fidelity":{"post":{"tags":["Enzymes & cloning"],"operationId":"golden_gate_fidelity","summary":"Golden Gate overhang fidelity","description":"Score a candidate set of 4-base Golden Gate/MoClo junction overhangs against real published T4-ligase ligation-count data: per-overhang specificity, the weakest link in the set, and any risky cross-reacting pairs. Optionally compare against a named published overhang set. This is SeqBench's own transparent scoring methodology — it does not reproduce NEB's/Potapov's own published aggregate fidelity percentages for named sets (their exact formula isn't disclosed anywhere accessible).","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"overhangs":{"type":"array","items":{"type":"string"},"description":"The candidate 4-base overhangs for one assembly (e.g. [\"GGAG\",\"TACT\",\"AATG\"]). At least 2, no duplicates."},"dataset":{"type":"string","enum":["generic-t4-37c-1h","bsai-hfv2"],"default":"generic-t4-37c-1h","description":"Which real ligation dataset to score against — generic T4 ligase, or an enzyme-specific one-pot dataset if that matches your actual digestion enzyme."},"riskThreshold":{"type":"number","default":0.05,"description":"Flag a pair as risky when the cross-reaction is at least this fraction of that pair's own total signal."},"compareToNamedSet":{"type":"string","enum":["pryor-2020-plant-11","pryor-2020-20set","cidar-moclo"],"description":"Also score this published reference set (see namedSetsAvailable in the output) alongside your candidate set, for comparison."}},"required":["overhangs"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/golden_gate_design":{"post":{"tags":["Enzymes & cloning"],"operationId":"golden_gate_design","summary":"Golden Gate overhang set designer","description":"CHOOSE a set of 4-base Golden Gate/MoClo junction overhangs, rather than scoring one you already have. Maximizes the fidelity of the set's WEAKEST junction against the same published T4-ligase ligation data golden_gate_fidelity scores with, subject to every member actually ligating well — an overhang can score a perfect ratio simply because nothing was ever measured cross-reacting with it, and 94% of the ligation matrix is zeros. Pin the overhangs your vector already commits you to with `fixed`, forbid others with `forbidden`, and give `junctions` when the junctions sit at real positions in real sequence and may only slide a few bases. Reports whether the search was exhaustive (provably the best available) or budget-limited (the best found).","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"count":{"type":"integer","minimum":2,"maximum":40,"description":"How many junctions the assembly has, INCLUDING any given in `fixed`."},"fixed":{"type":"array","items":{"type":"string"},"description":"Overhangs that must appear — typically the ones the destination vector already commits you to. Scored like any other member; simply not swappable."},"forbidden":{"type":"array","items":{"type":"string"},"description":"Overhangs the design may not use, whatever they score."},"junctions":{"type":"array","items":{"type":"object"},"description":"One entry per junction still to be chosen, as {sequence, position, slide}: the construct sequence, the 1-based first base of the preferred overhang, and how many bases either side the junction may move. Use this instead of a free design when the junctions are real places in real DNA — the candidates then come from bases that actually exist. Length must equal count minus fixed."},"dataset":{"type":"string","enum":["generic-t4-37c-1h","bsai-hfv2"],"default":"generic-t4-37c-1h","description":"Which real ligation dataset to optimize against."},"minCorrectSignal":{"type":"number","description":"Reject any overhang whose own correct-join signal is below this. Defaults to the chosen dataset's MEDIAN diagonal (2,694 for generic T4, 520 for BsaI-HFv2 — they differ five-fold, which is why this is derived rather than fixed). Set 0 to allow every overhang."}},"required":["count"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/save_permalink":{"post":{"tags":["Analysis"],"operationId":"save_permalink","summary":"Save a permanent shareable link","description":"Run a registered tool and save its (arguments, result) pair under a short permanent code that anyone with the link can view read-only (/permalink/{code}). Use this to cite or share a specific result (e.g. a verify_construct or verify_assembly check) rather than re-pasting it.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"tool":{"type":"string","description":"Name of the registered tool to run and save (e.g. \"verify_construct\")."},"args":{"type":"object","description":"Arguments for that tool, exactly as you would pass to it directly."}},"required":["tool","args"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/sequencing_readback_verify":{"post":{"tags":["Files & formats"],"operationId":"sequencing_readback_verify","summary":"Sequencing read-back verification","description":"Align raw Sanger or NGS reads (FASTA or FASTQ) back onto a claimed reference sequence using minimap2, and report per-read mapping identity plus exact variant positions (substitutions/insertions/deletions), with a consensus view across reads and a corrected consensus sequence (the reference with every consensus-supported edit applied). Each alignment also reports how much of the READ was used (queryCoveragePct/clippedBases), since identity is measured over the aligned portion only and a partially-used read would otherwise score perfectly. Set circular: true for a plasmid so reads crossing the reference's arbitrary linear start are aligned through the join rather than cut short at it. Also calls STRUCTURAL variants from split alignments — a large deletion, tandem duplication, inversion or backbone rearrangement never appears as a run of mismatches, only as one read aligning at several distant reference positions, so per-base calling reports a perfect clone — and returns a coverage depth profile with the regions no read reached at all, since \"never read\" is not \"correct\". On a circular reference one junction cannot always tell an event of length d from one of length referenceLength − d the other way round; where the read's own blocks and the coverage profile settle it they do, and where they do not the call carries an alternateInterpretation with the other reading rather than presenting one as a finding. Set platform (nanopore/pacbio/illumina/sanger) to pick minimap2's preset; the preset used is reported back. Complements verify_construct/verify_assembly: those re-derive what a design SHOULD produce from its own stated inputs; this checks what a real sequencer actually read back.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"reference":{"type":"string","residues":"nt","description":"The claimed/expected reference — bare bases, FASTA, or a whole GenBank record. Pass the GenBank record (your own map) to get consequences: every consensus edit is then placed against the features, so the answer reads \"silent in AmpR\" or \"premature STOP at codon 41 of your CDS\" instead of only a position and a base. Bare bases still work and simply return no consequences."},"reads":{"type":"string","description":"Raw reads in FASTA or FASTQ format (auto-detected). Up to 2000 reads / 5,000,000 total bp per call."},"minSupportingReads":{"type":"integer","default":2,"description":"Minimum number of reads agreeing on a variant position for it to count as a consensus (candidate real) variant rather than single-read noise."},"circular":{"type":"boolean","default":false,"description":"Treat the reference as a circular molecule (plasmid). Reads that straddle its arbitrary linear start are then aligned right through the join instead of being cut short there, so variants in the part that would otherwise be clipped away are actually called. Turn this on for whole-plasmid data — the reads begin wherever the molecule was cut, so most of them cross the join. Reads longer than the reference still get clipped. It also governs structural-variant calling: on a circle an origin-crossing read is contiguous, and only this flag lets it be told apart from a whole-reference duplication."},"platform":{"type":"string","enum":["auto","nanopore","pacbio","illumina","sanger"],"default":"auto","description":"Read type, which selects minimap2's alignment preset. \"auto\" (the default) passes no preset and uses minimap2's own defaults — whose parameters happen to be map-ont's, so nanopore data is already handled; setting \"nanopore\" makes that explicit and pins it. \"pacbio\" uses map-hifi and \"illumina\" uses sr, both of which materially change the result: under the ONT defaults gaps are cheap, so on accurate reads a cluster of mismatches can be reported as a spurious indel. \"sanger\" uses map-hifi with the minimum alignment score returned to 80, because map-hifi's own floor of 200 was chosen for 10-25 kb reads and would leave a short or partly-failed Sanger read unmapped. The preset actually used is reported back as minimap2Preset/alignerArgs so a run can be reproduced. Names are matched ignoring case and punctuation, and the obvious aliases resolve (\"ONT\" and \"map-ont\" to nanopore, \"HiFi\" to pacbio, \"sr\" to illumina); anything unrecognized is rejected rather than silently treated as \"auto\"."},"minSvSupport":{"type":"integer","default":3,"description":"Distinct reads that must agree on the same breakpoint before a structural variant (large deletion, duplication, inversion, insertion) is reported. Default 3 — stricter than minSupportingReads on purpose: a single split read is a library-prep chimera or a mapping artifact far more often than it is biology, and chimeras are common enough that two agreeing by chance is likelier than two matching base errors."},"minSvLength":{"type":"integer","default":50,"description":"Smallest structural variant to report, in bp (default 50). Below this the per-base variant caller already reports the event from inside a single alignment, and on nanopore data the range is mostly the error profile."},"breakpointTolerance":{"type":"integer","default":50,"description":"How far apart two reads' breakpoints may sit and still count as the same event, in bp (default 50). Long-read breakpoints are fuzzy, and microhomology at a real junction moves the split legitimately."}},"required":["reference","reads"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/web_search":{"post":{"tags":["Analysis"],"operationId":"web_search","summary":"Search the web","description":"Search the live web (via Tavily) for information not covered by SeqBench's own tools — recent literature, protocols, vendor/reagent info, general facts. Returns a short synthesized answer (if available) plus ranked source snippets with URLs. This does not run any bioinformatics calculation itself; use the dedicated tools for that.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"query":{"type":"string","description":"The search query."},"max_results":{"type":"number","description":"Maximum number of results to return (default 5, max 10)."}},"required":["query"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/id_map_submit":{"post":{"tags":["Analysis"],"operationId":"id_map_submit","summary":"Submit a batch gene/protein ID mapping job","description":"Submit up to 100,000 ids to UniProt's ID mapping service for a single confirmed-safe hop (e.g. Gene_Name -> UniProtKB-Swiss-Prot, or UniProtKB_AC-ID -> Ensembl/GeneID/RefSeq_Protein/Gene_Name). Returns a jobId immediately — poll it with id_map_poll.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"ids":{"type":"array","items":{"type":"string"},"description":"The ids to map, up to 100000 (e.g. gene symbols, UniProt accessions, Ensembl gene IDs, Entrez GeneIDs, or RefSeq protein accessions, depending on \"from\")."},"from":{"type":"string","description":"Source id type: \"Gene_Name\", \"Ensembl\", \"GeneID\", \"RefSeq_Protein\", or \"UniProtKB_AC-ID\". UniProt's mapping graph is hub-and-spoke — see the \"to\" note."},"to":{"type":"string","description":"Target id type. Supported single hops: Gene_Name/Ensembl/GeneID/RefSeq_Protein -> \"UniProtKB-Swiss-Prot\" (the only direct target for these), or \"UniProtKB_AC-ID\" -> Ensembl/GeneID/RefSeq_Protein/Gene_Name. Any other pair is rejected — chain two of these hops instead."},"taxId":{"type":"string","description":"NCBI taxonomy id to disambiguate a gene symbol (only used when from=\"Gene_Name\"). Defaults to human (9606) if omitted."}},"required":["ids","from","to"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/id_map_poll":{"post":{"tags":["Analysis"],"operationId":"id_map_poll","summary":"Poll a batch ID mapping job","description":"Check a UniProt id-mapping job submitted via id_map_submit. Returns {status, ready:false} while still running; once FINISHED, also returns the mapped ids (normalized regardless of which target database was requested) and any ids that failed to map.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"jobId":{"type":"string"}},"required":["jobId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/ortholog_map":{"post":{"tags":["Analysis"],"operationId":"ortholog_map","summary":"Find orthologs/paralogs for gene symbols across species","description":"Look up the orthologous (or paralogous) gene for up to 50 gene symbols in a target species, via Ensembl's homology-by-symbol REST endpoint. Symbols with no homology record are reported in `unmapped`, never silently dropped.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"symbols":{"type":"array","items":{"type":"string"},"description":"Gene symbols to look up, up to 50 (e.g. [\"TP53\", \"BRCA1\"])."},"sourceSpecies":{"type":"string","default":"human","description":"Ensembl species slug the symbols belong to (e.g. \"human\", \"mouse\"). Defaults to \"human\"."},"targetSpecies":{"type":"string","description":"Ensembl species slug to find homologs in (e.g. \"mouse\", \"rat\", \"zebrafish\", \"fruit_fly\")."},"type":{"type":"string","enum":["orthologues","paralogues","all"],"default":"orthologues","description":"Homology type to return. Defaults to orthologues."}},"required":["symbols","targetSpecies"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/volcano_plot_data":{"post":{"tags":["Analysis"],"operationId":"volcano_plot_data","summary":"Volcano plot data","description":"Validate a differential-expression table (gene, log2 fold-change, p-value/FDR) and compute -log10(p) plus up/down/non-significant counts at conventional default thresholds (|log2FC|>=1, p<=0.05), for the Volcano Plot visualization. Invalid rows (non-finite log2FC, or p-value outside (0,1]) are dropped and reported rather than failing the whole batch.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"rows":{"type":"array","description":"Differential expression rows, one per gene.","items":{"type":"object","properties":{"gene":{"type":"string","description":"Gene name/id."},"log2fc":{"type":"number","description":"log2 fold-change."},"pvalue":{"type":"number","description":"p-value, or an adjusted/FDR value — whichever column you want thresholded on. Must be in (0, 1]."}},"required":["gene","log2fc","pvalue"]}}},"required":["rows"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/expression_heatmap_cluster":{"post":{"tags":["Analysis"],"operationId":"expression_heatmap_cluster","summary":"Expression heatmap clustering","description":"Hierarchically cluster a genes x samples expression matrix (UPGMA/average, complete, or single linkage; Euclidean or correlation distance) and return the row/column leaf order, dendrogram merge trees, and row-z-scored values for the Clustered Expression Heatmap visualization.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"genes":{"type":"array","items":{"type":"string"},"description":"Row (gene) labels."},"samples":{"type":"array","items":{"type":"string"},"description":"Column (sample) labels."},"values":{"type":"array","items":{"type":"array","items":{"type":"number"}},"description":"genes x samples numeric matrix — one row per gene, in the same order as `genes`."},"clusterRows":{"type":"boolean","default":true,"description":"Cluster (reorder) genes."},"clusterCols":{"type":"boolean","default":true,"description":"Cluster (reorder) samples."},"distanceMetric":{"type":"string","enum":["euclidean","correlation"],"default":"correlation","description":"correlation = 1 - Pearson r (the standard expression-heatmap default); euclidean = straight-line distance."},"linkage":{"type":"string","enum":["average","complete","single"],"default":"average","description":"average = UPGMA (standard default), complete = farthest-neighbor, single = nearest-neighbor."},"zScoreRows":{"type":"boolean","default":true,"description":"Row-wise z-score each gene's values before clustering and returning (the conventional 'relative expression' heatmap normalization — the dendrograms are computed on the same scaled matrix the heatmap shows, as in seaborn's clustermap(z_score=0) / pheatmap's scale=\"row\")."}},"required":["genes","samples","values"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/functional_enrichment":{"post":{"tags":["Analysis"],"operationId":"functional_enrichment","summary":"Functional enrichment (GO + Reactome)","description":"Over-representation analysis: test which GO terms (biological process / molecular function / cellular component) and Reactome pathways are statistically enriched in a query gene list versus a background, using the hypergeometric test with Benjamini-Hochberg FDR correction across all tested terms. Uses bundled GO Consortium + Reactome reference data (human only). KEGG is not included (its license does not permit bundling gene sets).","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"genes":{"type":"array","items":{"type":"string"},"description":"Query gene symbols (human, e.g. \"TP53\"). Case-insensitive. Capped at 5000."},"background":{"type":"array","items":{"type":"string"},"description":"Custom background/universe gene symbols. If omitted, defaults to every gene present in the bundled GO+Reactome dataset (the 'only annotated genes' convention, as used by g:Profiler) rather than the whole genome."},"collections":{"type":"array","items":{"type":"string","enum":["GO:BP","GO:MF","GO:CC","Reactome"]},"default":["GO:BP","GO:MF","GO:CC","Reactome"],"description":"Which term collections to test. Defaults to all four."},"minTermSize":{"type":"integer","default":3,"description":"Skip terms/pathways with fewer than this many background genes."},"maxTermSize":{"type":"integer","default":500,"description":"Skip terms/pathways with more than this many background genes (matches clusterProfiler's default)."}},"required":["genes"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/hgvs_convert":{"post":{"tags":["Alignment & variants"],"operationId":"hgvs_convert","summary":"HGVS Variant Converter (c. <-> g. <-> p.)","description":"Parse an HGVS \"c.\" variant description (by gene symbol, RefSeq NM_, or Ensembl ENST accession), convert it to genomic (g.) coordinates via a real, live-fetched Ensembl exon/CDS map (transcripts resolved through the bundled MANE RefSeq<->Ensembl crosswalk), apply 3'-rule normalization to any del/dup/ins, and predict the protein (p.) effect where that is safely computable. Refuses cleanly — rather than guessing — for circular/mitochondrial genomes, RNA-level or protein-level input, uncertain/mosaic syntax, splice-junction-adjacent or inversion protein effects, and non-MANE/non-Ensembl transcripts.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"variant":{"type":"string","description":"A full HGVS \"c.\" variant description: \"<accession or gene symbol>:c.<edit>\", e.g. \"NM_000546.6:c.215C>G\" or \"TP53:c.215C>G\". Substitution (\">\"), deletion (\"del\"), duplication (\"dup\"), insertion (\"ins\"), delins, and inversion (\"inv\") are supported."}},"required":["variant"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/fastq_qc_report":{"post":{"tags":["Files & formats"],"operationId":"fastq_qc_report","summary":"FASTQ Deep QC Report","description":"FastQC-style deep quality-control report for a FASTQ file: per-base quality and content, GC and length distributions, sequence duplication levels, overrepresented sequences, and adapter content — each with a warn/fail verdict against FastQC's own published thresholds.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"input":{"type":"string","description":"FASTQ text: records of an '@id' header, sequence, '+' separator and quality line (four lines each)."},"qualityOffset":{"type":"integer","enum":[33,64],"default":33,"description":"ASCII offset of the FASTQ quality string. 33 for anything modern, 64 for pre-1.8 Illumina."}},"required":["input"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/fastq_trim":{"post":{"tags":["Files & formats"],"operationId":"fastq_trim","summary":"FASTQ Adapter & Quality Trimmer","description":"Trim FASTQ reads: an ungapped sliding-suffix adapter match (against the same named Illumina adapters as the QC report) followed by a BWA-style 3' quality trim (the same algorithm Cutadapt's own -q option reuses), then drops reads below a minimum length. Returns the trimmed FASTQ plus before/after read-count, mean-length and mean-quality stats.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"input":{"type":"string","description":"FASTQ text: records of an '@id' header, sequence, '+' separator and quality line (four lines each)."},"qualityOffset":{"type":"integer","enum":[33,64],"default":33,"description":"ASCII offset of the FASTQ quality string. 33 for anything modern, 64 for pre-1.8 Illumina."},"qualityThreshold":{"type":"integer","default":20,"description":"3' quality-trim threshold (Phred score)."},"minLength":{"type":"integer","default":20,"description":"Reads shorter than this after trimming are dropped."}},"required":["input"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/alphafold_lookup":{"post":{"tags":["Proteins & peptides"],"operationId":"alphafold_lookup","summary":"Look up an AlphaFold structure prediction","description":"Look up a UniProt accession in the AlphaFold Protein Structure Database (CC-BY 4.0). Returns confidence, model version and structure file URLs, or {found:false} when no prediction exists for that accession.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"accession":{"type":"string","description":"UniProt accession, e.g. \"P04637\"."}},"required":["accession"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/export_plate_layout":{"post":{"tags":["Files & formats"],"operationId":"export_plate_layout","summary":"PCR plate layout","description":"Assign a set of PCR reactions (name + forward/reverse primer + optional template label) to wells on a 96-well plate, row-major (A1, A2, … A12, then B1, B2, … up to H12). Returns the well-assignment data for rendering a plate diagram; export_opentrons_protocol and export_echo_picklist build their downloadable files from this exact same layout, so all three always agree.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"reactions":{"type":"array","description":"One entry per PCR reaction, up to 96 (a single 96-well plate).","items":{"type":"object","properties":{"name":{"type":"string","description":"Reaction/construct name."},"forward":{"type":"string","description":"Forward primer sequence, 5'->3' (IUPAC accepted)."},"reverse":{"type":"string","description":"Reverse primer sequence, 5'->3' (IUPAC accepted)."},"template":{"type":"string","description":"Optional template name/id — a short label (e.g. a plasmid or sample name), not a sequence."}},"required":["forward","reverse"]}}},"required":["reactions"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/export_opentrons_protocol":{"post":{"tags":["Files & formats"],"operationId":"export_opentrons_protocol","summary":"Opentrons protocol export","description":"Generate a downloadable Opentrons Python Protocol API (v2, OT-2) script that sets up the given PCR reactions on a 96-well PCR plate, at the same well positions export_plate_layout assigns. Uses real Opentrons labware/pipette API names confirmed against docs.opentrons.com and the Opentrons shared-data labware-definitions repository (opentrons_96_wellplate_200ul_pcr_full_skirt, opentrons_96_tiprack_20ul, opentrons_24_tuberack_nest_1.5ml_snapcap, nest_12_reservoir_15ml, p20_single_gen2) and the confirmed load_labware/load_instrument/transfer method signatures. Master-mix/primer/template/water volumes are clearly-labeled placeholder constants at the top of the script — this is a starting point to review and adapt for your own enzyme and instrument, not a certified ready-to-run protocol.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"reactions":{"type":"array","description":"One entry per PCR reaction, up to 96 (a single 96-well plate).","items":{"type":"object","properties":{"name":{"type":"string","description":"Reaction/construct name."},"forward":{"type":"string","description":"Forward primer sequence, 5'->3' (IUPAC accepted)."},"reverse":{"type":"string","description":"Reverse primer sequence, 5'->3' (IUPAC accepted)."},"template":{"type":"string","description":"Optional template name/id — a short label (e.g. a plasmid or sample name), not a sequence."}},"required":["forward","reverse"]}},"protocolName":{"type":"string","description":"Optional protocol name (used in the script's metadata)."}},"required":["reactions"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/export_echo_picklist":{"post":{"tags":["Files & formats"],"operationId":"export_echo_picklist","summary":"Echo picklist export","description":"Generate a downloadable Beckman/Labcyte Echo acoustic-liquid-handler picklist CSV (columns: Source Plate Name, Source Plate Type, Source Well, Destination Plate Name, Destination Well, Transfer Volume, Name — the header row reproduced from PyEcho, a real open-source Echo-picklist generator) for the given PCR reactions, at the same well positions export_plate_layout assigns. Assumes a 5 uL Echo-scale PCR reaction (master mix 2500 nL, each primer 250 nL, template 250 nL, water 1750 nL) — a commonly used acoustic-dispensing miniaturization scale, not a universal standard; rescale the volumes for your own protocol. Source/Destination Plate Type uses a placeholder Echo plate-type code (384PP_AQ_BP) — replace with the exact type from your own Echo Plate Type Library. Each distinct template label gets its own well on the TemplateSource plate, row-major (A1, A2, … A24, then B1, …) across that 384-well source plate.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"reactions":{"type":"array","description":"One entry per PCR reaction, up to 96 (a single 96-well plate).","items":{"type":"object","properties":{"name":{"type":"string","description":"Reaction/construct name."},"forward":{"type":"string","description":"Forward primer sequence, 5'->3' (IUPAC accepted)."},"reverse":{"type":"string","description":"Reverse primer sequence, 5'->3' (IUPAC accepted)."},"template":{"type":"string","description":"Optional template name/id — a short label (e.g. a plasmid or sample name), not a sequence."}},"required":["forward","reverse"]}}},"required":["reactions"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/variant_annotate":{"post":{"tags":["Alignment & variants"],"operationId":"variant_annotate","summary":"Variant Annotator","description":"One-box variant lookup against MyVariant.info: accepts an rsID, chrom:pos:ref:alt (colon- or hyphen-separated), genomic HGVS (\"chr17:g.7676154G>C\"), or transcript HGVS c. (\"NM_000546.6:c.215C>G\" / \"TP53:c.215C>G\", bridged via the hgvs_convert tool). Returns a ClinVar significance summary, gnomAD exome/genome allele frequencies, and CADD/SIFT/PolyPhen2/REVEL pathogenicity predictor scores — each section explicitly null when that source has no data, never silently omitted. See the result's own \"caveats\" for real data-freshness limits (frozen gnomAD/CADD snapshots, periodic ClinVar snapshot).\n\nBatchable via `POST /batch`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"variant":{"type":"string","description":"An rsID (\"rs1042522\"), chrom:pos:ref:alt with either separator (\"17:7676154:G:C\" or \"17-7676154-G-C\", single-base substitutions only), genomic HGVS (\"chr17:g.7676154G>C\" or \"17:g.7676154G>C\"), or transcript HGVS c. (\"NM_000546.6:c.215C>G\" or \"TP53:c.215C>G\")."},"assembly":{"type":"string","enum":["hg19","hg38"],"default":"hg19","description":"Genome build for rsID/chrom-pos-ref-alt/genomic-HGVS lookups (MyVariant.info's native default is hg19). Ignored for transcript \"c.\" input, which is always bridged via GRCh38/hg38 (hgvs_convert's own coordinate space)."}},"required":["variant"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/variant_to_construct":{"post":{"tags":["Alignment & variants"],"operationId":"variant_to_construct","summary":"Variant to construct to genotyping bridge","description":"Turn one variant into one buildable plan: verify the reference allele actually sits where the coordinate says, apply the edit, design site-directed mutagenesis primers to install it, design KASP/ARMS allele-specific primers to genotype it afterwards, and consolidate everything into a single oligo order table. Takes either a construct sequence with a 1-based position and ref/alt alleles (offline, deterministic), or an HGVS \"c.\" description resolved through the MANE crosswalk and a live Ensembl exon map. A mismatched reference allele is refused with the bases that were actually found there, because a coordinate that is right for another isoform yields a perfectly valid primer set for the wrong base. Bases shared by both alleles are trimmed first, so a VCF-anchored pair is designed as the substitution or indel it actually is. Mutagenesis covers every class (a substitution, an insertion, a deletion and a multi-base replacement are all one interval replacement); KASP needs a single-base substitution's 3'-terminal base, so for an indel the genotyping half comes back as a named omission with the reason and the readout that does work, never as an empty list.\n\nNot a workflow step (it does not take a single sequence argument), but its `editedSequence` field is the sequence to carry into the next call yourself.","requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"sequence":{"type":"string","residues":"nt","description":"OFFLINE MODE. The reference/construct sequence the variant is described against (raw or FASTA). Mutually exclusive with \"variant\"."},"position":{"type":"integer","minimum":1,"description":"OFFLINE MODE. 1-based position of the first base of refAllele on `sequence`. For a pure insertion (empty refAllele) the alternate bases are inserted immediately BEFORE this position."},"refAllele":{"type":"string","description":"OFFLINE MODE. Bases replaced, as they appear on `sequence` — checked against it and refused if they differ. Use \"-\" or \"\" for a pure insertion. A VCF-style anchored pair (both alleles carrying a shared flanking base, e.g. refAllele \"T\" / altAllele \"TGGATCC\", or \"TG\" / \"AG\") is accepted and trimmed to its minimal form before anything is designed; the trimmed coordinates are reported as `minimal`."},"altAllele":{"type":"string","description":"OFFLINE MODE. Bases installed. Use \"-\" or \"\" for a pure deletion."},"variant":{"type":"string","description":"NETWORK MODE. A full HGVS \"c.\" description, e.g. \"NM_000546.6:c.215C>G\" or \"TP53:c.215C>G\". Resolved through the bundled MANE crosswalk and a live Ensembl exon map, then a genomic window is fetched around it. Mutually exclusive with \"sequence\"."},"flank":{"type":"integer","default":300,"description":"NETWORK MODE. Bases of genomic context fetched either side of the variant (60-1000). Needs to cover the allele-specific core upstream and the genotyping amplicon downstream."},"label":{"type":"string","description":"Name stem for the ordered oligos. Defaults to the HGVS string (network mode) or a positional label like \"A100G\" (offline)."},"style":{"type":"string","enum":["quikchange","q5"],"default":"quikchange","description":"Mutagenic primer style: overlapping (QuikChange) or back-to-back (Q5/KLD)."},"armTmTarget":{"type":"number","default":60,"minimum":45,"maximum":80,"description":"Target Tm (°C) for each mutagenic primer's template-binding arm (45-80; the arm is grown between 10 and 30 nt, so a target outside that range is refused rather than clamped to the shortest or longest arm)."},"targetCoreTm":{"type":"number","default":56,"minimum":45,"maximum":80,"description":"Target Tm (°C) for the allele-specific genotyping core, before the universal tail (45-80; the core is chosen between 18 and 27 nt, so a target outside that range is refused rather than clamped)."},"minAmplicon":{"type":"integer","default":60,"minimum":1,"maximum":10000,"description":"Minimum genotyping amplicon length, measured from the allele-specific primer's 5' end (which sits one core-length upstream of the variant) to the reverse primer's 5' end. Must not exceed maxAmplicon."},"maxAmplicon":{"type":"integer","default":150,"minimum":36,"maximum":10000,"description":"Maximum genotyping amplicon length. Refused below 36 bp, the shortest KASP product that can exist (an 18 nt core plus an 18 nt reverse primer), and refused below minAmplicon — both are unsatisfiable for every reference, and left unchecked they came back as \"no common reverse primer could be placed; provide more 3' flanking sequence\"."},"addSecondaryMismatch":{"type":"boolean","default":true,"description":"Engineer the ARMS destabilizing mismatch 3 nt from the allele-specific primer's 3' end."}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gene_model":{"post":{"tags":["Analysis"],"operationId":"gene_model","summary":"Gene Model (Exon/CDS Structure)","description":"The real exon/UTR/CDS structure of a human gene's canonical transcript, fetched live from Ensembl (the same exon/CDS map the HGVS Converter tool uses) — for rendering an exon diagram.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"gene":{"type":"string","description":"A human gene symbol (\"TP53\") or Ensembl gene ID (\"ENSG00000141510\")."}},"required":["gene"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gene_dossier":{"post":{"tags":["Analysis"],"operationId":"gene_dossier","summary":"Gene/Target Dossier","description":"A gene/drug-target dossier fanned out to five independent sources in one call: Open Targets (function, tractability, top associated diseases), an NCBI/UniProt plain-English function summary, ChEMBL (known drugs and their mechanism/clinical phase, cross-referenced with indications), ClinicalTrials.gov (trials by gene/condition term), and Europe PMC (top cited papers). Each source fails independently — a down source returns null/empty for its own section rather than failing the whole call, and every failure is listed in \"sourceErrors\" rather than silently omitted.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"gene":{"type":"string","description":"A human gene symbol (\"TP53\") or Ensembl gene ID (\"ENSG00000141510\")."}},"required":["gene"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gene_expression":{"post":{"tags":["Analysis"],"operationId":"gene_expression","summary":"Gene Expression Fingerprint","description":"A gene's tissue-expression fingerprint: per-tissue median TPM from GTEx (v8) and subcellular localization / RNA tissue-specificity / protein class from the Human Protein Atlas, in one call.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"gene":{"type":"string","description":"A human gene symbol (\"TP53\") or Ensembl gene ID (\"ENSG00000141510\")."}},"required":["gene"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/prime_editing_design":{"post":{"tags":["CRISPR"],"operationId":"prime_editing_design","summary":"Prime Editing Studio (pegRNA)","description":"Design SpCas9 prime-editing pegRNAs for a substitution, insertion, deletion, or small replacement: for each usable NGG PAM it builds the spacer, a primer-binding-site (PBS) length sweep targeting a ~30 C melting temperature, the reverse-transcriptase template (RTT) that encodes the edit, and the full 3' extension, plus PE3 nicking-sgRNA suggestions 40-90 bp away on the opposite strand. Designs where the edit destroys the pegRNA's own PAM (preventing re-nicking of the edited allele) are ranked first. Coordinates: every pegRNA coordinate (protospacer span, nick position, editStart/editEnd) is 1-based inclusive in the submitted PRE-EDIT target's frame — the protospacer+PAM search runs on the unedited sequence, because Cas9 has to bind the allele you actually have. The one exception is edit-dependent PE3b nicking guides, which exist only once the edit is installed; each nickingGuides entry therefore carries a `coordinateFrame` field of \"target\" or \"editedSequence\" naming the frame its own start/end/nickToNickDistance are measured in, and for a length-changing edit the two frames differ downstream of the edit. Off-target activity is not evaluated (no in-browser reference genome).","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"target":{"type":"string","residues":"nt","description":"Forward-strand target DNA (raw or FASTA), with flanking sequence around the intended edit."},"editStart":{"type":"integer","description":"1-based inclusive start of the region being changed."},"editEnd":{"type":"integer","description":"1-based inclusive end of the region being changed. For a pure insertion, set editEnd = editStart - 1."},"insertedSeq":{"type":"string","residues":"nt","default":"","description":"Replacement bases (forward strand). Empty string means a deletion."},"rttHomology":{"type":"integer","default":13,"description":"Homology length (nt) 3' of the edit that the RTT should include (typically 10-16)."},"pbsLength":{"type":"integer","description":"Optional preferred PBS length to highlight; a full 8-17 nt sweep is always returned."},"frameStart":{"type":"integer","description":"Optional 1-based CDS reading-frame start, used only to annotate whether a PAM-blocking mutation would be silent."}},"required":["target","editStart","editEnd"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/prime_editing_twin_design":{"post":{"tags":["CRISPR"],"operationId":"prime_editing_twin_design","summary":"twinPE Studio (dual pegRNA)","description":"Design a twinPE pegRNA pair (Anzalone et al. 2022) for a replacement too large for a single pegRNA's RTT: a left pegRNA nicks the + strand at/before the replacement window and a right pegRNA nicks the - strand at/after it, each synthesizing a new 3' flap; both flaps are truncated at a shared overlap in the middle of the new sequence so they anneal and resolve the edit without an HDR donor. Coordinates: both pegRNAs' protospacerStart/protospacerEnd/nickPosition are 1-based inclusive in the submitted PRE-EDIT target's frame (the PAM search runs on the unedited sequence, on both sides), while replaceSpan is the span of the new content in the returned editedSequence. Off-target activity is not evaluated (no in-browser reference genome).","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"target":{"type":"string","residues":"nt","description":"Forward-strand target DNA (raw or FASTA), with flanking sequence on both sides of the replacement window."},"replaceStart":{"type":"integer","description":"1-based inclusive start of the region being replaced/deleted."},"replaceEnd":{"type":"integer","description":"1-based inclusive end of the region being replaced/deleted. For a pure insertion, set replaceEnd = replaceStart - 1."},"newSequence":{"type":"string","residues":"nt","description":"New sequence (forward strand) to install in place of [replaceStart, replaceEnd]. Needs >= 2 bp."},"overlapLength":{"type":"integer","default":15,"description":"Length (bp) of the shared overlap built into both pegRNAs' 3' flaps where they meet and anneal."},"pbsLength":{"type":"integer","description":"Optional preferred PBS length to highlight; a full 8-17 nt sweep is always returned."}},"required":["target","replaceStart","replaceEnd","newSequence"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/prime_editing_efficiency":{"post":{"tags":["CRISPR"],"operationId":"prime_editing_efficiency","summary":"Prime-editing efficiency (PRIDICT2.0)","description":"Predict per-pegRNA prime-editing efficiency for one edit with PRIDICT2.0, and return the top-scoring pegRNA designs ranked by it. Takes the target as context, the edit in brackets, then context — ACGT...(A/G)...ACGT, with roughly 100+ bp each side — and enumerates PBS/RTT length combinations, scoring every one in HEK293 and K562. Each candidate comes back with both scores, its percentile against the training library, its rank, the spacer, PBS and RTT lengths, the full pegRNA, and Golden Gate cloning oligos. Use it to CHOOSE between designs; the number is not a promised editing percentage.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"sequence":{"type":"string","description":"Target with the edit in brackets: context, then (original/edited), then context. Roughly 100+ bp each side — the model reads that context. Keep unchanged flanking bases OUTSIDE the brackets: T(a/g)C, not (TAC/TGC). Insertions and deletions leave one side empty, e.g. (/AGG) or (AGG/)."},"cellType":{"type":"string","enum":["HEK","K562"],"default":"HEK","description":"Which trained context to RANK by. Both scores are always returned; this decides the ordering. There is no generic-mammalian option because the model has no such training data."},"topN":{"type":"integer","default":10,"minimum":1,"maximum":50,"description":"How many top-ranked pegRNAs to return, out of the hundreds enumerated. Max 50."},"use5Folds":{"type":"boolean","default":false,"description":"Average all five trained folds instead of the first. Modestly steadier scores for five times the compute, and it is charged five times as much."}},"required":["sequence"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/base_editing_design":{"post":{"tags":["CRISPR"],"operationId":"base_editing_design","summary":"Base Editing Designer","description":"Design cytosine (CBE, C→T) or adenine (ABE, A→G) base-editing gRNAs for an SpCas9 target: for each NGG gRNA it reports every editable base inside the editor's activity window, flags bystander edits (more than one editable base in the window), and — with a CDS reading frame — classifies each edit's amino-acid consequence (silent / missense / nonsense / stop-loss). Bystander-free guides are ranked first. Handles both strands (a C→T on the protospacer of a reverse-strand guide is reported as the forward-strand G→A).","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"target":{"type":"string","residues":"nt","description":"Nucleotide sequence (raw or FASTA; IUPAC accepted)."},"editor":{"type":"string","enum":["be3","be4max","abe7.10","abe8e"],"default":"be4max","description":"Base editor: be3/be4max (CBE, C→T) or abe7.10/abe8e (ABE, A→G)."},"frameStart":{"type":"integer","description":"Optional 1-based CDS reading-frame start, to classify each edit's amino-acid consequence."},"targetPosition":{"type":"integer","description":"Optional 1-based forward-strand position of the base you intend to edit; only guides whose window covers it are returned."}},"required":["target"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/sirna_design":{"post":{"tags":["Primers & oligos"],"operationId":"sirna_design","summary":"siRNA / shRNA Designer","description":"Design siRNA duplexes against an mRNA target using the established Reynolds (2004) 8-criteria score and the Ui-Tei (2004) rules, plus the siDirect seed-duplex Tm off-target flag (≥21.5 °C, computed on siDirect's own RNA/RNA scale: Freier 1986 nearest-neighbor parameters, helix initiation A = −10.8, CT = 100 µM, 100 mM Na⁺). Returns ranked candidates with sense/guide oligos (with UU 3' overhangs) and, per candidate, a ready shRNA cassette (sense–loop–antisense–Pol III terminator). Heuristic sequence rules only — no RNA-folding accessibility model and no transcriptome-wide off-target search.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"target":{"type":"string","residues":"nt","description":"Nucleotide sequence (raw or FASTA; IUPAC accepted)."},"minReynolds":{"type":"integer","default":6,"description":"Minimum Reynolds score (0–8) to keep; falls back to best-ranked if none qualify."},"shRnaLoop":{"type":"string","residues":"nt","default":"TTCAAGAGA","description":"Loop sequence used when assembling the shRNA cassette."}},"required":["target"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/aso_design":{"post":{"tags":["Primers & oligos"],"operationId":"aso_design","summary":"ASO Gapmer Designer","description":"Design antisense-oligonucleotide (ASO) gapmers against an mRNA target: scans candidate sites, builds the antisense oligo in the standard 5-10-5 architecture (chemically-modified wings, central DNA gap for RNase H1, phosphorothioate backbone), and screens each for known liabilities (G-quadruplex motifs, CpG immunostimulation, self-complementarity, GC extremes). No transcriptome-wide off-target search.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"target":{"type":"string","residues":"nt","description":"Nucleotide sequence (raw or FASTA; IUPAC accepted)."},"length":{"type":"integer","default":20,"minimum":8,"maximum":50,"description":"Total gapmer length (nt). A real RNase H1 gapmer is 12-25."},"wing":{"type":"integer","default":5,"minimum":0,"description":"Modified-wing length on each side (nt); the central gap = length − 2×wing, so 2×wing must be less than length."}},"required":["target"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/kasp_primer_design":{"post":{"tags":["Primers & oligos"],"operationId":"kasp_primer_design","summary":"KASP / ARMS Allele-Specific Primers","description":"Design KASP/ARMS allele-specific genotyping primers for a SNP: two allele-specific forward primers differing only at the 3' terminal base (one per allele), each with the standard KASP universal tail (FAM for allele A, HEX for allele B), a deliberate internal ARMS secondary mismatch near the 3' end whose strength complements that primer's own natural allele mismatch (strong↔weak), and one common downstream reverse primer sized to a chosen amplicon range. Because a forward primer reads the antisense strand, each primer's 3' base sits opposite the complement of the other allele, so the two primers get different mismatch classes and are reported separately (graded from the measured PCR yields in Kwok et al. 1990). Reuses the site's nearest-neighbor Tm engine.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"target":{"type":"string","residues":"nt","description":"Nucleotide sequence (raw or FASTA; IUPAC accepted)."},"snpPosition":{"type":"integer","minimum":18,"description":"1-based position of the SNP on the forward strand. Must be 18 or greater: the allele-specific primers end on the SNP, so they need at least 17 bp of upstream template to build a core from."},"alleleA":{"type":"string","residues":"nt","description":"First allele (single base) — gets the FAM tail."},"alleleB":{"type":"string","residues":"nt","description":"Second allele (single base) — gets the HEX tail."},"targetCoreTm":{"type":"number","default":56,"description":"Target Tm (°C) for the allele-specific primer core (before the universal tail)."},"minAmplicon":{"type":"integer","default":60,"description":"Minimum amplicon length for the common reverse primer."},"maxAmplicon":{"type":"integer","default":150,"description":"Maximum amplicon length for the common reverse primer."},"addSecondaryMismatch":{"type":"boolean","default":true,"description":"Engineer the internal ARMS destabilizing mismatch near the 3' end."}},"required":["target","snpPosition","alleleA","alleleB"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/rna_fold":{"post":{"tags":["Analysis"],"operationId":"rna_fold","summary":"RNA Secondary Structure (MFE)","description":"Predict an RNA secondary structure by minimum free energy (MFE) using a Zuker dynamic program with Turner 1999 nearest-neighbor stacking energies (no pseudoknots). Returns the dot-bracket structure, the estimated MFE (kcal/mol), and the list of base pairs. A from-scratch, in-browser implementation (there is no usable browser ViennaRNA); the simplified loop energy model makes the MFE a good comparative estimate, not a lab-grade absolute.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"sequence":{"type":"string","residues":"nt","description":"Nucleotide sequence (raw or FASTA; IUPAC accepted)."}},"required":["sequence"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/rbs_predict":{"post":{"tags":["Analysis"],"operationId":"rbs_predict","summary":"Predict translation initiation rate (OSTIR)","description":"Predict the translation initiation rate at each start codon in a bacterial mRNA using OSTIR, the open-source continuation of the Salis lab RBS Calculator, with ViennaRNA free energies. Returns the predicted rate plus the full thermodynamic breakdown (16S rRNA:mRNA hybridization, mRNA unfolding, spacing, standby site, start-codon binding) for every start codon found. Rates are on an arbitrary scale — compare them as ratios, not as absolute expression levels. Runs ViennaRNA on a shared service and is therefore rate limited (see 429/503).","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"sequence":{"type":"string","description":"mRNA sequence, raw or FASTA — the 5' UTR plus at least the start of the CDS. DNA (T) and RNA (U) are both accepted and scored identically. A, C, G, T/U only. Max 10,000 nt."},"start":{"type":"number","description":"Optional 1-based position; only consider start codons beginning at or after it."},"end":{"type":"number","description":"Optional 1-based position; only consider start codons beginning at or before it."},"antiShineDalgarno":{"type":"string","description":"Optional anti-Shine-Dalgarno sequence (the 16S rRNA 3' end) to model a non-E. coli host. Omit to use OSTIR's own E. coli default."}},"required":["sequence"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/rbs_design":{"post":{"tags":["Analysis"],"operationId":"rbs_design","summary":"Design a ribosome binding site (OSTIR)","description":"Design a 5' UTR / ribosome binding site for a given CDS. Generates a spread of Shine-Dalgarno cores and SD-to-start spacings, scores every one with OSTIR in the context of your own CDS (which matters — the rate depends on how the RBS interacts with that CDS's 5' folding), and returns them ranked. Supply targetExpression to rank by closeness to a target rate instead of by maximum strength, and supply your existing 5' UTR to get a measured baseline and fold-change for each candidate. Runs ViennaRNA on a shared service and is therefore rate limited (see 429/503).","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"cds":{"type":"string","description":"Coding sequence, raw or FASTA, starting at its start codon. Only the 5' end affects the prediction, so the first ~90 nt is enough. A, C, G, T/U only. Max 10,000 nt."},"currentUtr":{"type":"string","description":"Optional: your existing 5' UTR (everything upstream of the start codon). Scored as a baseline so each candidate gets a fold-change against it."},"leader":{"type":"string","description":"Optional 5' context upstream of the designed RBS — the transcribed leader from your promoter. Affects the standby-site term. Defaults to a 20 nt unstructured poly-A leader."},"targetExpression":{"type":"number","description":"Optional target rate on OSTIR's arbitrary scale. Candidates are then ranked by closeness to it (log-ratio) rather than by maximum strength. Only meaningful against a number produced by this same tool."},"antiShineDalgarno":{"type":"string","description":"Optional anti-Shine-Dalgarno sequence (the 16S rRNA 3' end) to model a non-E. coli host. Omit to use OSTIR's own E. coli default."},"limit":{"type":"number","default":10,"description":"How many ranked candidates to return. 1-60."}},"required":["cds"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/rbs_library_design":{"post":{"tags":["Analysis"],"operationId":"rbs_library_design","summary":"Design an RBS library spanning a range of translation rates","description":"Build a ladder of ribosome binding sites whose predicted translation initiation rates are evenly spread, in log space, across a range you choose — the standard way to titrate one enzyme's level in a pathway without guessing. Scores every SD-core/spacing/spacer-composition combination with OSTIR in your own CDS context, then picks one variant per rung. Rungs it cannot fill are reported as GAPS rather than filled with the nearest available variant, so a library that does not really span the range says so. PREDICTED, NOT MEASURED: the ordering comes from a model with ρ ≈ 0.39 against measured expression, which is what makes it usable for ranking a library you will screen and unusable for hitting an absolute number.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"cds":{"type":"string","residues":"nt","description":"The coding sequence, raw or FASTA, starting at its start codon. Only the 5' end affects the prediction, so the first ~90 nt is enough. Max 10,000 nt."},"leader":{"type":"string","description":"Sequence upstream of the RBS (the 5' end of the transcript). OSTIR needs some 5' context for its standby-site term; a 20 nt A-rich leader is assumed when none is given, which is an assumption and not a measurement."},"targetMin":{"type":"number","description":"Weakest rung, in OSTIR's arbitrary units. OMIT THIS and the range is taken from what the candidates actually reach in your CDS context, which is usually what you want: the units have no absolute meaning, so a number carried over from a paper or a default describes nothing. Set it only when you are matching a value you measured yourself in the same context."},"targetMax":{"type":"number","description":"Strongest rung, in the same arbitrary units. Omit with targetMin to use the candidates' own range."},"librarySize":{"type":"integer","default":8,"minimum":2,"maximum":24,"description":"How many variants the ladder should have (default 8)."},"antiShineDalgarno":{"type":"string","description":"Override the host's anti-Shine-Dalgarno sequence. Defaults to the E. coli one OSTIR is parameterised on."}},"required":["cds"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/rbs_occlusion":{"post":{"tags":["Analysis"],"operationId":"rbs_occlusion","summary":"What can base-pair over the ribosome binding site","description":"Find every stretch of a transcript that is reverse-complementary to the ribosome's footprint (-20 to +13 around the start codon), with the length and nearest-neighbour Tm of each duplex, and flag the ones that cover the Shine-Dalgarno core or the start codon. This is the mechanism every translational switch runs on — riboswitch, toehold switch, RNA thermometer, antisense repressor — and the first thing to look at when a switch does not switch or a construct is unexpectedly silent. Also reports where a sensor domain can be inserted without touching the site. Deterministic base-pairing, not a folding prediction: use rna_fold to ask whether a given stem actually wins at 37 °C. Reports no switching ratio — see this tool's notes for why.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"sequence":{"type":"string","residues":"nt","description":"The transcript: the 5' UTR plus at least the start of the CDS. DNA or RNA. Max 20,000 nt."},"startCodonAt":{"type":"integer","description":"1-based position of the start codon to anchor the footprint on. Omit to use the first ATG/GTG/TTG — pass it when the transcript has several, which is the usual case for a real 5' UTR."},"minStem":{"type":"integer","default":6,"minimum":4,"maximum":40,"description":"Shortest duplex to report, in bp (default 6). Below 4 bp every sequence pairs with everything; a stem that actually holds a site shut is usually 8 bp or more."},"maxLoop":{"type":"integer","default":100,"minimum":3,"description":"Largest number of unpaired bases allowed between an arm and its target (default 100)."}},"required":["sequence"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/riboswitch_states":{"post":{"tags":["Analysis"],"operationId":"riboswitch_states","summary":"Fold a riboswitch with and without its ligand","description":"Fold a transcript twice — once freely, once with the aptamer held out of the secondary structure as a bound ligand would hold it — and report what changes at the ribosome binding site. Returns both structures, both free energies, the cost of occupying the aptamer, and whether the site becomes more or less accessible. This is the question a riboswitch design can be checked on before the bench: is the site sequestered in one state and free in the other. Returns NO activation ratio and no fold-change — see this tool's validation note for why that number is not offered. Pair with rbs_occlusion, which finds what can pair over the site in the first place.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"sequence":{"type":"string","residues":"nt","description":"The transcript: aptamer, expression platform, and at least the start of the CDS. DNA or RNA. Max 1,000 nt, because it is folded twice."},"aptamerStart":{"type":"integer","description":"1-based start of the aptamer — the region the ligand occupies. Omit both ends to fold freely and only report the site's accessibility."},"aptamerEnd":{"type":"integer","description":"1-based end of the aptamer."},"siteStart":{"type":"integer","description":"1-based start of the region whose accessibility is the answer. Omit both ends and the ribosome footprint is located automatically from the first start codon and its Shine-Dalgarno."},"siteEnd":{"type":"integer","description":"1-based end of that region."},"temperature":{"type":"number","default":37,"minimum":-20,"maximum":120,"description":"Folding temperature in °C. A switch characterised at 37 °C is not a switch at 30 °C."}},"required":["sequence"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/vector_library_search":{"post":{"tags":["Enzymes & cloning"],"operationId":"vector_library_search","summary":"Search the vector library","description":"Browse a curated library of publicly deposited, feature-annotated cloning and expression vectors — by name, category (E. coli cloning/expression, yeast, mammalian, plant binary, BAC/fosmid, recombineering, phage/M13), length window, or annotated feature (e.g. 'T7 promoter', 'ori', 'AmpR'). Each hit reports the vector's accession, length, topology and feature count; vector_library_get returns the sequence and the full feature table. A curated public-record set, NOT a vendor catalog — see the gate's notChecked.","requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"query":{"type":"string","description":"Substring of the vector name or its GenBank definition (case- and punctuation-insensitive, min 2 characters)."},"category":{"type":"string","description":"Restrict to one category. An unknown category is an error, not an empty result."},"feature":{"type":"string","description":"Substring of an annotated feature's label, type or note (min 2 characters), e.g. \"T7 promoter\", \"kanR\", \"rep_origin\"."},"minLength":{"type":"integer","minimum":0,"description":"Smallest vector length in bp."},"maxLength":{"type":"integer","minimum":0,"description":"Largest vector length in bp."},"limit":{"type":"integer","minimum":1,"maximum":100,"default":25,"description":"Maximum hits to return. Capped at 100; asking for more is an error, not a silent truncation."}},"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/vector_library_get":{"post":{"tags":["Enzymes & cloning"],"operationId":"vector_library_get","summary":"Get a vector with its annotation","description":"Return one vector from the library: its GenBank accession and version, length, topology, organism/definition, complete sequence, and the full annotated feature table (type, label, 1-based inclusive start/end, strand, spliced length, and the location descriptor as the record wrote it). Accepts the library id, the vector name, or the accession. An unrecognized id is an error carrying the closest names — never an empty result.\n\nBatchable via `POST /batch`.\n\nChainable in workflows (passes its `sequence` field to the next step).","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"Library id (e.g. \"pbr322\"), vector name (\"pBR322\"), or accession (\"J01749\" / \"J01749.1\")."},"includeSequence":{"type":"boolean","default":true,"description":"Set false for the annotation only — useful for a large BAC where the bases are not the point."}},"required":["id"],"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/parts_library_search":{"post":{"tags":["Enzymes & cloning"],"operationId":"parts_library_search","summary":"Search the parts library","description":"Search a parts list harvested from the annotated features of the vector library — promoters, terminators, RBSs, polyA signals, origins, selection markers, affinity tags, reporters, linkers/MCSs — by name, kind or length. Nothing here is transcribed: every part is the exact sequence a GenBank record annotated, and each hit carries the accession and 1-based span it was cut from, plus every other library vector the same part was found in. Parts whose location is spliced or approximate are excluded, because their sequence is not fully determined.","requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"query":{"type":"string","description":"Substring of the part name (min 2 characters), e.g. \"T7\", \"AmpR\", \"SV40 polyA\"."},"kinds":{"type":"array","items":{"type":"string"},"description":"Restrict to these part kinds (promoter, terminator, origin, RBS, polyA, selection marker, affinity tag, reporter, linker/MCS, …). An unknown kind is an error."},"minLength":{"type":"integer","minimum":0,"description":"Smallest part length in bp."},"maxLength":{"type":"integer","minimum":0,"description":"Largest part length in bp."},"includeSequence":{"type":"boolean","default":true,"description":"Include each part's bases (5'→3' on the part's own strand)."},"limit":{"type":"integer","minimum":1,"maximum":100,"default":25,"description":"Maximum hits to return. Capped at 100; asking for more is an error, not a silent truncation."}},"additionalProperties":false}}}},"responses":{"200":{"description":"Tool ran successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Invalid argument or the tool could not run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/batch":{"get":{"tags":["Batch & workflow"],"operationId":"batchInfo","summary":"List batchable tools and batch limits","responses":{"200":{"description":"Batchable tool list and limits.","content":{"application/json":{"schema":{"type":"object"}}}}}},"post":{"tags":["Batch & workflow"],"operationId":"runBatch","summary":"Run one tool over many records","description":"Runs a single batchable tool over every record in `input` (a multi-FASTA file or one sequence per line). The per-record sequence is injected into the tool argument named by that tool's `seqArg`; `args` are shared across all records.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchRequest"},"example":{"tool":"gc_content","input":">seq1\nATGGCGCGCTAA\n>seq2\nTTTTAAAACCCC"}}}},"responses":{"200":{"description":"Batch completed (individual rows may carry per-record errors).","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"result":{"$ref":"#/components/schemas/BatchResult"}},"required":["ok","result"]}}}},"400":{"description":"Invalid request (bad JSON, missing tool/input, or tool not batchable).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SimpleError"}}}}}}},"/workflow":{"get":{"tags":["Batch & workflow"],"operationId":"workflowInfo","summary":"List pipeline-capable tools and workflow limits","responses":{"200":{"description":"Pipeline-capable tool list and limits.","content":{"application/json":{"schema":{"type":"object"}}}}}},"post":{"tags":["Batch & workflow"],"operationId":"runWorkflow","summary":"Run a multi-tool pipeline over many records","description":"Runs an ordered pipeline of tools over every record in `input`. Each step's chained output sequence feeds the next step by default; a step may instead draw from an earlier step (`from`: 0-based index) or the original record (`from`: \"initial\"). A step that draws from an earlier step requires that step to declare a chain output.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkflowRequest"},"example":{"input":">seq1\nATGGCCTGA","steps":[{"tool":"reverse_complement"},{"tool":"translate","args":{"frame":1}}]}}}},"responses":{"200":{"description":"Workflow completed (individual steps may carry per-record errors).","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"result":{"$ref":"#/components/schemas/WorkflowResult"}},"required":["ok","result"]}}}},"400":{"description":"Invalid request (bad JSON, missing steps/input, or a step is invalid).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SimpleError"}}}}}}}},"components":{"schemas":{"SuccessResponse":{"type":"object","description":"Standard success envelope returned by every single-tool call.","properties":{"ok":{"const":true},"tool":{"type":"string","description":"The tool slug that ran."},"result":{"type":"object","additionalProperties":true,"description":"Tool-specific output object. Its shape depends on the tool — call `GET /{tool}` or see the docs for each tool's fields."},"gate":{"oneOf":[{"$ref":"#/components/schemas/GateResult"},{"type":"null"}],"description":"Typed QC verdict, or null when the tool defines no gate or the call lacked gating inputs (e.g. no targetTm)."},"provenance":{"$ref":"#/components/schemas/Provenance"}},"required":["ok","tool","result","provenance"]},"ErrorResponse":{"type":"object","description":"Standard error envelope for single-tool calls.","properties":{"ok":{"const":false},"tool":{"type":"string"},"error":{"type":"string","description":"Human-readable error message."},"code":{"type":"string","enum":["invalid_argument","unsupported","upstream_unavailable","upstream_timeout","rate_limited","internal_error"]},"retryable":{"type":"boolean"},"suggestedAction":{"type":"string"}},"required":["ok","error"]},"SimpleError":{"type":"object","description":"Error shape returned by the batch and workflow endpoints.","properties":{"ok":{"const":false},"error":{"type":"string"}},"required":["ok","error"]},"GateResult":{"type":"object","properties":{"pass":{"type":"boolean","description":"True if and only if every hard check passed."},"checks":{"type":"array","items":{"$ref":"#/components/schemas/GateCheck"}},"notChecked":{"type":"array","items":{"type":"string"},"description":"Honest list of what this gate does NOT verify."}},"required":["pass","checks","notChecked"]},"GateCheck":{"type":"object","properties":{"id":{"type":"string"},"label":{"type":"string"},"severity":{"type":"string","enum":["hard","soft"]},"pass":{"type":"boolean"},"message":{"type":"string"},"value":{"type":"number"},"threshold":{"type":"string"}},"required":["id","label","severity","pass","message"]},"Provenance":{"type":"object","properties":{"apiVersion":{"type":"string","example":"1.1.0"},"tool":{"oneOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Tool slug, or an array of slugs (one per step) for a workflow."},"generatedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp of when the result was generated."}},"required":["apiVersion","tool","generatedAt"]},"BatchRequest":{"type":"object","properties":{"tool":{"type":"string","description":"A batchable tool slug (see `GET /batch`)."},"input":{"type":"string","description":"Multi-FASTA text or one sequence per line (max ~2,000,000 chars)."},"args":{"type":"object","additionalProperties":true,"description":"Shared tool arguments applied to every record."}},"required":["tool","input"]},"BatchResult":{"type":"object","properties":{"tool":{"type":"string"},"count":{"type":"integer"},"capped":{"type":"boolean","description":"True if input exceeded the record limit."},"limit":{"type":"integer","description":"Maximum records per call (500)."},"columns":{"type":"array","items":{"type":"string"}},"rows":{"type":"array","items":{"$ref":"#/components/schemas/BatchRow"}},"errors":{"type":"integer"},"provenance":{"$ref":"#/components/schemas/Provenance"}},"required":["tool","count","capped","limit","columns","rows","errors","provenance"]},"BatchRow":{"type":"object","properties":{"name":{"type":"string"},"cells":{"type":"object","additionalProperties":{"type":["string","number"]}},"error":{"type":"string"},"errorCode":{"type":"string"},"retryable":{"type":"boolean"}},"required":["name","cells"]},"WorkflowRequest":{"type":"object","properties":{"steps":{"type":"array","minItems":1,"maxItems":8,"items":{"$ref":"#/components/schemas/WorkflowStep"}},"input":{"type":"string","description":"Multi-FASTA text or one sequence per line."}},"required":["steps","input"]},"WorkflowStep":{"type":"object","properties":{"tool":{"type":"string","description":"A pipeline-capable tool slug."},"args":{"type":"object","additionalProperties":true},"from":{"oneOf":[{"type":"integer","description":"0-based index of an earlier step."},{"const":"initial","description":"The original input record."}],"description":"Source of this step's input. Defaults to the previous step."}},"required":["tool"]},"WorkflowResult":{"type":"object","properties":{"steps":{"type":"array","items":{"type":"object","properties":{"tool":{"type":"string"},"title":{"type":"string"}}}},"count":{"type":"integer"},"capped":{"type":"boolean"},"limit":{"type":"integer","description":"Maximum records per call (200)."},"columns":{"type":"array","items":{"type":"string"},"description":"Flattened \"<step>·<tool>·<key>\" column headers."},"rows":{"type":"array","items":{"type":"object"}},"errors":{"type":"integer"},"provenance":{"$ref":"#/components/schemas/Provenance"}},"required":["steps","count","capped","limit","columns","rows","errors","provenance"]}}}}