---
title: "Primer specificity screen"
method: POST
path: "/primer_specificity"
tags: ["Primers & oligos"]
---

# Primer specificity screen

`POST /primer_specificity`

## Request

- Base URL: `https://seqbench.com/api/v1`
- URL: `https://seqbench.com/api/v1/primer_specificity`
- Auth: none required

Self-hosted e-PCR-style screen for off-target amplicons predicted by a primer pair against the background chosen with `background`: the bundled lab genomes (the default — E. coli K-12 MG1655, B. subtilis 168, human mitochondrion rCRS, Mycoplasma hyorhinis SK76), or the human or mouse TRANSCRIPTOME, one transcript per gene, where an off-target product means a different GENE. See genomesChecked in the response for what actually ran. No background covers the nuclear genome, so an off-target in an intron, a promoter, an intergenic region or genomic-DNA carry-over is out of scope in every mode. 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.

Batchable via `POST /batch`.

## Request body

- object
  - `forwardPrimer` string, required: Forward primer, 5'→3'.
  - `reversePrimer` string, required: Reverse primer, 5'→3'.
  - `maxMismatches` integer: 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` integer: Ignore candidate off-target products longer than this (bp) — a search-window cap, not a biological claim.
  - `background` 'lab-genomes' | 'human' | 'mouse': What to screen against. "lab-genomes" (the default) is the bundled set of common lab reference genomes. "human" is MANE Select and "mouse" is RefSeq Select — ONE TRANSCRIPT PER GENE, so an off-target product means a DIFFERENT GENE rather than another isoform of the one you meant (the full RefSeq set holds ~190,000 transcripts, most of them isoforms of each other, and screening against it buries the one real finding under fifteen copies of your own gene). These are TRANSCRIPTOMES, so they cover spliced mRNA only: an off-target in an intron, a promoter, an intergenic region or an unannotated locus is NOT in scope, and neither is genomic DNA contamination — read a clean result as "does not amplify another mRNA", never as "genome-wide specific". Each is a pinned annotation release, named in genomesChecked.
  - `intendedTemplate` string: 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.

## Response `200`

Tool ran successfully.

- SuccessResponse: Standard success envelope returned by every single-tool call.
  - `ok` unknown, required
  - `tool` string, required: The tool slug that ran.
  - `result` object, required: Tool-specific output object. Its shape depends on the tool — call `GET /{tool}` or see the docs for each tool's fields.
  - `gate` GateResult
    - `pass` boolean, required: True if and only if every hard check passed.
    - `checks` GateCheck[], required
      - `id` string, required
      - `label` string, required
      - `severity` 'hard' | 'soft', required
      - `pass` boolean, required
      - `message` string, required
      - `value` number
      - `threshold` string
    - `notChecked` string[], required: Honest list of what this gate does NOT verify.
  - `provenance` Provenance, required
    - `apiVersion` string, required
    - `tool` union, required: Tool slug, or an array of slugs (one per step) for a workflow.
      - string
      - string[]
    - `generatedAt` string, date-time, required: ISO 8601 timestamp of when the result was generated.

## Other responses

- `400`: Invalid argument or the tool could not run.
- `404`: Unknown tool.
- `429`: Rate limited (metered tools only). Body carries code `rate_limited` and retryable `true`; honor the Retry-After header.
- `503`: A metered tool is momentarily at capacity. The identical request should succeed after Retry-After; body carries code `upstream_unavailable`.

---

[API](https://skmtc.dev/seqbench/apis/seqbench-api.md) · [All operations](https://skmtc.dev/seqbench/apis/seqbench-api/llms.txt) · [OpenAPI document](https://skmtc.dev/seqbench/apis/seqbench-api/revisions/132575216865?raw)
