---
title: "Base editing quantification from Sanger traces (EditR equivalent)"
method: POST
path: "/base_edit_quant"
tags: ["Alignment & variants"]
---

# Base editing quantification from Sanger traces (EditR equivalent)

`POST /base_edit_quant`

## Request

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

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.

## Request body

- object
  - `controlBases` string, required: Base calls of the UNEDITED control read.
  - `controlChannels` array[], required: 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).
    - number[]
  - `editedBases` string, required: Base calls of the edited pool's read.
  - `editedChannels` array[], required: Per-base [A, C, G, T] intensities of the edited read, same convention.
    - number[]
  - `editor` 'be3' | 'be4max' | 'abe7.10' | 'abe8e': 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` string: 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` number: Explicit window start, 1-based in CONTROL read coordinates. Requires windowEnd, from and to.
  - `windowEnd` number: Explicit window end, 1-based inclusive, in CONTROL coordinates. Window length is capped at 40.
  - `from` string: 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` string: Explicit-window mode: the base it converts to, as READ on the control strand.
  - `targetPosition` number: 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` number: 1-based protospacer position of the intended edit (PAM-distal = 1). Editor mode only.
  - `zThreshold` number: 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` number: 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.

## 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)
