{"openapi":"3.1.0","info":{"title":"Genomic Intelligence API","description":"REST API for DNA sequence analysis with transformer language models. Six tasks — promoter, splice, enhancer, chromatin, annotation, expression — each with its own `POST /v1/tasks/{task}/predict` operation, plus one composite workflow under `/v1/workflows/`.\n\n**This document is the contract.** It is self-contained: request bounds, closed `options` objects, error codes, response headers and both async body shapes are all declared here, so a generated client needs nothing else.\n\n**Auth.** Every `/v1/*` route requires `Authorization: Bearer gi_…`, with two exceptions. `/health`, `/docs`, `/redoc` and `/v1/openapi.json` are public, and so is capability discovery: `GET /v1/tasks/{task}/models` needs no key, so you can read every model's `bio_spec` — organism, window geometry, output formats, `request_max_bp` — before you have one. It is rate-limited per source IP rather than per partner.\n\n**Envelopes.** Success is `{data, meta}`; `data` is a union discriminated on `task`. Errors are `{error: {code, message, request_id, details?}}`, with `error.code` drawn from a published enum.\n\n**Sequence length.** Each task's request schema publishes `minLength`/`maxLength` on `sequence`, measured after whitespace is stripped. One bound per task, applying to every model of that task: promoter 300 bp, splice 100 bp, enhancer 50 bp, chromatin 200 bp, annotation 1,000 bp, expression 9,198 bp (with the TSS at least 4,599 bp from each end) — all capped at 500,000 bp. Out-of-range requests are rejected with `422 validation_failed` before any model is loaded. These are the bounds this document previously advertised as 1-500,000 bp for all six.\n\nA floor is admission control, not a claim about regime. Where a model slides a window (promoter, splice, enhancer, chromatin), a request above the floor but shorter than that model's `bio_spec.context_window_bp` is accepted and scored against a padded window. Compare your length against that field to know whether the model saw real sequence or padding. Expression models read around the TSS instead: fetch each model's `bio_spec.recommended_flank_bp` on each side of it.\n\n**Body size.** Requests are also capped at 16 MiB of raw body, enforced before parsing; over that is `413 payload_too_large` regardless of sequence length.\n\n**Async.** Send `Prefer: respond-async` for a `202` with a `job_id`, then poll `GET /v1/tasks/jobs/{job_id}`. Two operations *require* it above a size threshold: the composite workflow above 50,000 bp and `POST /v1/tasks/annotation/predict` above 200,000 bp, both of which return `413 sync_too_large` to a synchronous JSON request over their threshold. Each threshold is published as `x-sync-limit-bp` on its own operation — read it from there rather than from this sentence, and take the absence of that extension on the other five predict operations as the statement that they have no sync cap. Async is JSON-only, so the cap governs JSON delivery: a BED/GFF3 response above the threshold is still served synchronously and can run long enough to hit a gateway timeout.\n\n**Rate limits.** Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset` and `RateLimit-Policy`; a `429` adds `Retry-After`. `RateLimit-Limit` is a *burst* capacity — one tenth of a minute's allowance (rpm / 6, published at the document root as `x-rate-limit-burst-divisor`), refilling continuously — so your sustained ceiling is 6 times it per minute. Pacing off the header alone budgets 6x low.","contact":{"name":"Genomic Intelligence Support","url":"https://docs.genomicintelligence.ai/","email":"contact@genomicintelligence.ai"},"version":"2026.10.03.2 (196f0fe4)"},"servers":[{"url":"https://api.genomicintelligence.ai","description":"Production"}],"paths":{"/health":{"get":{"tags":["Health"],"summary":"Health Check","description":"Liveness probe. Public; no auth required.","operationId":"health_check_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"}}}}},"security":[]}},"/v1/tasks/jobs/{job_id}":{"get":{"tags":["Tasks"],"summary":"Retrieve job progress or final result","description":"Unified progress + result endpoint.\n\nHTTP status reflects the underlying job state. Owner-scoped:\n\n- Unknown / not-owned → ``404 not_found``.\n- Expired → ``410 job_expired``.\n- Running / accepted → ``202`` with the canonical ``{data, meta}``\n  envelope; ``data`` carries ``status`` and ``progress``.\n- Completed → ``200`` with the same ``{data, meta}`` envelope sync\n  mode would have produced.\n- Failed → the natural ``4xx``/``5xx`` for the underlying error with\n  the unified ``{error: {...}}`` envelope.","operationId":"get_job_v1_tasks_jobs__job_id__get","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}}],"responses":{"200":{"description":"Job complete. Body is the same ``{data, meta}`` envelope the originating operation returns synchronously — one of three: a predict envelope for the six task endpoints (``data.task`` is ``promoter``, ``splice``, ``enhancer``, ``chromatin``, ``annotation`` or ``expression``), the composite envelope (``find_genes_and_predict_expression``), or the variant-workflow receipt (``genomic_variant_interpretation``). **Narrow on ``data.task``** — the literal is unique across all three and is the only discriminator. It is nested one level down, so this is an ``anyOf`` without an OpenAPI ``discriminator``, which names only top-level properties; a generated client must switch on ``data.task`` by hand rather than relying on first-match deserialization.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/PredictResponse"},{"$ref":"#/components/schemas/FindGenesAndPredictExpressionResponse"},{"$ref":"#/components/schemas/GenomicVariantInterpretationResponse"}],"title":"Response 200 Get Job V1 Tasks Jobs  Job Id  Get"}}},"headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}}},"400":{"description":"Bad request — e.g. `Prefer: respond-async` combined with a text format.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer key (`unauthorized`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}},"WWW-Authenticate":{"description":"Bearer challenge, e.g. ``Bearer realm=\"api.genomicintelligence.ai\", error=\"invalid_token\"``.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Key disabled or insufficient tier (`forbidden`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}},"WWW-Authenticate":{"description":"Bearer challenge, e.g. ``Bearer realm=\"api.genomicintelligence.ai\", error=\"invalid_token\"``.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown task, unknown job, or a job owned by another key (`not_found`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (`conflict`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"410":{"description":"Async job result expired out of the job store (`job_expired`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Either the 16 MiB request-body hard cap was exceeded (`payload_too_large`, enforced before parsing), or the body is over the endpoint's synchronous-delivery cap (`sync_too_large`; `error.details` carries `{sequence_length, threshold}` — retry the same request with `Prefer: respond-async`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"415":{"description":"The requested output format is not one this task can render (`unsupported_format`). The message lists the supported formats; the server never silently falls back to JSON.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation failed (`validation_failed`) — sequence length outside the task's bounds, a non-ACGTN character, an unknown key under `options` (every options object is closed), or a sequence below the *selected task's published `minLength`/`maxLength` bounds.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate or concurrency cap reached (`too_many_requests`). `Retry-After` and the `RateLimit-*` headers say when to retry.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always at least 1.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error (`internal_error`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Model still loading (`model_loading`), GPU memory exhausted (`insufficient_memory`), or service unavailable. `insufficient_memory` means the card OOM-ed on this request and its cache has been released — it is transient GPU pressure, not a server bug, so `Retry-After` is honest and a bounded retry is the right response.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always at least 1.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"202":{"description":"Job still running. Same ``{data, meta}`` envelope; ``data.progress.current_percent`` and ``data.progress.message`` carry live progress. Keep polling until 200.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobProgressResponse"}}}}}}},"/v1/tasks/jobs":{"get":{"tags":["Tasks"],"summary":"List the caller's recent jobs","description":"Return a short list of the caller's recently submitted jobs.","operationId":"list_jobs_v1_tasks_jobs_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"default":50,"title":"Limit"}}],"responses":{"200":{"description":"Recent jobs submitted with this key, newest first. Owner-scoped — never returns another key's jobs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobListResponse"}}},"headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}}},"400":{"description":"Bad request — e.g. `Prefer: respond-async` combined with a text format.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer key (`unauthorized`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}},"WWW-Authenticate":{"description":"Bearer challenge, e.g. ``Bearer realm=\"api.genomicintelligence.ai\", error=\"invalid_token\"``.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Key disabled or insufficient tier (`forbidden`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}},"WWW-Authenticate":{"description":"Bearer challenge, e.g. ``Bearer realm=\"api.genomicintelligence.ai\", error=\"invalid_token\"``.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown task, unknown job, or a job owned by another key (`not_found`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (`conflict`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"410":{"description":"Async job result expired out of the job store (`job_expired`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Either the 16 MiB request-body hard cap was exceeded (`payload_too_large`, enforced before parsing), or the body is over the endpoint's synchronous-delivery cap (`sync_too_large`; `error.details` carries `{sequence_length, threshold}` — retry the same request with `Prefer: respond-async`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"415":{"description":"The requested output format is not one this task can render (`unsupported_format`). The message lists the supported formats; the server never silently falls back to JSON.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation failed (`validation_failed`) — sequence length outside the task's bounds, a non-ACGTN character, an unknown key under `options` (every options object is closed), or a sequence below the *selected task's published `minLength`/`maxLength` bounds.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate or concurrency cap reached (`too_many_requests`). `Retry-After` and the `RateLimit-*` headers say when to retry.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always at least 1.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error (`internal_error`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Model still loading (`model_loading`), GPU memory exhausted (`insufficient_memory`), or service unavailable. `insufficient_memory` means the card OOM-ed on this request and its cache has been released — it is transient GPU pressure, not a server bug, so `Retry-After` is honest and a bounded retry is the right response.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always at least 1.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/tasks/promoter/predict":{"post":{"tags":["Tasks"],"summary":"Scan a sequence for promoter regions","description":"Slide the selected promoter classifier across the sequence and return the windows and merged regions scoring above ``options.threshold``.\n\nMinimum input is 300 bp — the smallest ``context_window_bp`` among the promoter models, so it is the shortest sequence that fills some model's window with no padding at all.\n\nThat floor is admission control, not a quality guarantee. The default ``g0-promoter-2000bp`` has a 2000 bp window, so a 300 bp request to it is scored against a heavily padded window — accepted and meaningful, but not the same regime as a full-window call. Read ``bio_spec.context_window_bp`` from ``GET /v1/tasks/promoter/models`` and compare it against your sequence length; pick ``g0-promoter-large-300bp`` or ``g0-promoter-base-300bp`` if your input really is ~300 bp. Longer input is never a problem — the scanner steps one prediction window at a time and pads only the final partial window.","operationId":"predict_promoter_v1_tasks_promoter_predict_post","parameters":[{"name":"format","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Output format: ``json`` (default) or one of ``bed``, ``bedgraph``. Text formats are synchronous-only — combining one with ``Prefer: respond-async`` is a ``400``. An unsupported value is a ``415 unsupported_format``, never a silent fallback to JSON.","title":"Format"},"description":"Output format: ``json`` (default) or one of ``bed``, ``bedgraph``. Text formats are synchronous-only — combining one with ``Prefer: respond-async`` is a ``400``. An unsupported value is a ``415 unsupported_format``, never a silent fallback to JSON."},{"name":"accept","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Accept"}},{"name":"Prefer","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Set to ``respond-async`` to dispatch asynchronously: the server returns ``202`` with ``{data: {job_id, status, links}, meta}`` immediately and the result is polled from ``GET /v1/tasks/jobs/{job_id}``. Anything else (or omitting the header) delivers the result synchronously with ``200``. Async is JSON-only — combining it with a text ``format`` is a ``400``. Some endpoints *require* it above a size threshold and reject sync delivery with ``413 sync_too_large``.","title":"Prefer"},"description":"Set to ``respond-async`` to dispatch asynchronously: the server returns ``202`` with ``{data: {job_id, status, links}, meta}`` immediately and the result is polled from ``GET /v1/tasks/jobs/{job_id}``. Anything else (or omitting the header) delivers the result synchronously with ``200``. Async is JSON-only — combining it with a text ``format`` is a ``400``. Some endpoints *require* it above a size threshold and reject sync delivery with ``413 sync_too_large``."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PromoterPredictRequest"}}}},"responses":{"200":{"description":"Successful inference. ``data`` is a discriminated union keyed on ``task`` — narrow on ``data.task`` (or ``meta.task``) to reach task-specific fields; here it is always ``\"promoter\"``. ``meta.task_specific_counts`` is the matching counts variant.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PredictResponse"}}},"headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}}},"400":{"description":"Bad request — e.g. `Prefer: respond-async` combined with a text format.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer key (`unauthorized`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}},"WWW-Authenticate":{"description":"Bearer challenge, e.g. ``Bearer realm=\"api.genomicintelligence.ai\", error=\"invalid_token\"``.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Key disabled or insufficient tier (`forbidden`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}},"WWW-Authenticate":{"description":"Bearer challenge, e.g. ``Bearer realm=\"api.genomicintelligence.ai\", error=\"invalid_token\"``.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown task, unknown job, or a job owned by another key (`not_found`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (`conflict`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"410":{"description":"Async job result expired out of the job store (`job_expired`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Either the 16 MiB request-body hard cap was exceeded (`payload_too_large`, enforced before parsing), or the body is over the endpoint's synchronous-delivery cap (`sync_too_large`; `error.details` carries `{sequence_length, threshold}` — retry the same request with `Prefer: respond-async`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"415":{"description":"The requested output format is not one this task can render (`unsupported_format`). The message lists the supported formats; the server never silently falls back to JSON.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation failed (`validation_failed`) — sequence length outside the task's bounds, a non-ACGTN character, an unknown key under `options` (every options object is closed), or a sequence below the *selected task's published `minLength`/`maxLength` bounds.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate or concurrency cap reached (`too_many_requests`). `Retry-After` and the `RateLimit-*` headers say when to retry.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always at least 1.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error (`internal_error`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Model still loading (`model_loading`), GPU memory exhausted (`insufficient_memory`), or service unavailable. `insufficient_memory` means the card OOM-ed on this request and its cache has been released — it is transient GPU pressure, not a server bug, so `Retry-After` is honest and a bounded retry is the right response.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always at least 1.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"202":{"description":"Async submission accepted — returned only when ``Prefer: respond-async`` was sent. Poll ``GET /v1/tasks/jobs/{job_id}``; ``Content-Location`` carries the same path.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}},"Content-Location":{"description":"Path to poll for the async result, ``/v1/tasks/jobs/{job_id}``.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AsyncAcceptedResponse"}}}}},"x-models":{"model":{"default":"g0-promoter-2000bp","ids":["g0-promoter-2000bp","g0-promoter-large-300bp","g0-promoter-base-300bp","dnabert-promoter-2000bp","g0-promoter-drosophila","g0-promoter-yeast","g0-promoter-arabidopsis"]}}}},"/v1/tasks/splice/predict":{"post":{"tags":["Tasks"],"summary":"Annotate donor and acceptor splice sites","description":"Token-level classification of splice sites over a 15 kb sliding context.\n\n**The model is strand-specific, and the wrong strand fails silently *and* plausibly.** It scores the sequence as given: a minus-strand gene submitted in plus orientation returns sites at different positions, often still at high confidence, so neither the site count nor the scores are a usable tell. (Measured: reverse-complemented BRCA1 exon 11 returns 2 sites at 0.91/0.99.) The response carries no ``strand`` field, so orientation has to be tracked caller-side — submit transcript orientation.\n\n``options.threshold`` trades response size for recall — a threshold of 0 emits every position and can produce a response in the megabytes.","operationId":"predict_splice_v1_tasks_splice_predict_post","parameters":[{"name":"format","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Output format: ``json`` (default) or one of ``bed``, ``gff3``. Text formats are synchronous-only — combining one with ``Prefer: respond-async`` is a ``400``. An unsupported value is a ``415 unsupported_format``, never a silent fallback to JSON.","title":"Format"},"description":"Output format: ``json`` (default) or one of ``bed``, ``gff3``. Text formats are synchronous-only — combining one with ``Prefer: respond-async`` is a ``400``. An unsupported value is a ``415 unsupported_format``, never a silent fallback to JSON."},{"name":"accept","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Accept"}},{"name":"Prefer","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Set to ``respond-async`` to dispatch asynchronously: the server returns ``202`` with ``{data: {job_id, status, links}, meta}`` immediately and the result is polled from ``GET /v1/tasks/jobs/{job_id}``. Anything else (or omitting the header) delivers the result synchronously with ``200``. Async is JSON-only — combining it with a text ``format`` is a ``400``. Some endpoints *require* it above a size threshold and reject sync delivery with ``413 sync_too_large``.","title":"Prefer"},"description":"Set to ``respond-async`` to dispatch asynchronously: the server returns ``202`` with ``{data: {job_id, status, links}, meta}`` immediately and the result is polled from ``GET /v1/tasks/jobs/{job_id}``. Anything else (or omitting the header) delivers the result synchronously with ``200``. Async is JSON-only — combining it with a text ``format`` is a ``400``. Some endpoints *require* it above a size threshold and reject sync delivery with ``413 sync_too_large``."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SplicePredictRequest"}}}},"responses":{"200":{"description":"Successful inference. ``data`` is a discriminated union keyed on ``task`` — narrow on ``data.task`` (or ``meta.task``) to reach task-specific fields; here it is always ``\"splice\"``. ``meta.task_specific_counts`` is the matching counts variant.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PredictResponse"}}},"headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}}},"400":{"description":"Bad request — e.g. `Prefer: respond-async` combined with a text format.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer key (`unauthorized`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}},"WWW-Authenticate":{"description":"Bearer challenge, e.g. ``Bearer realm=\"api.genomicintelligence.ai\", error=\"invalid_token\"``.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Key disabled or insufficient tier (`forbidden`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}},"WWW-Authenticate":{"description":"Bearer challenge, e.g. ``Bearer realm=\"api.genomicintelligence.ai\", error=\"invalid_token\"``.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown task, unknown job, or a job owned by another key (`not_found`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (`conflict`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"410":{"description":"Async job result expired out of the job store (`job_expired`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Either the 16 MiB request-body hard cap was exceeded (`payload_too_large`, enforced before parsing), or the body is over the endpoint's synchronous-delivery cap (`sync_too_large`; `error.details` carries `{sequence_length, threshold}` — retry the same request with `Prefer: respond-async`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"415":{"description":"The requested output format is not one this task can render (`unsupported_format`). The message lists the supported formats; the server never silently falls back to JSON.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation failed (`validation_failed`) — sequence length outside the task's bounds, a non-ACGTN character, an unknown key under `options` (every options object is closed), or a sequence below the *selected task's published `minLength`/`maxLength` bounds.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate or concurrency cap reached (`too_many_requests`). `Retry-After` and the `RateLimit-*` headers say when to retry.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always at least 1.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error (`internal_error`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Model still loading (`model_loading`), GPU memory exhausted (`insufficient_memory`), or service unavailable. `insufficient_memory` means the card OOM-ed on this request and its cache has been released — it is transient GPU pressure, not a server bug, so `Retry-After` is honest and a bounded retry is the right response.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always at least 1.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"202":{"description":"Async submission accepted — returned only when ``Prefer: respond-async`` was sent. Poll ``GET /v1/tasks/jobs/{job_id}``; ``Content-Location`` carries the same path.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}},"Content-Location":{"description":"Path to poll for the async result, ``/v1/tasks/jobs/{job_id}``.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AsyncAcceptedResponse"}}}}},"x-models":{"model":{"default":"g0-splice-bigbird","ids":["g0-splice-bigbird"]}}}},"/v1/tasks/enhancer/predict":{"post":{"tags":["Tasks"],"summary":"Score enhancer activity (developmental and housekeeping)","description":"DeepSTARR-style regression: two continuous activity scores per 249 bp window. Trained on Drosophila enhancers — see ``bio_spec.organism`` before applying it to another species. Takes no options. Minimum input is 50 bp, the floor for every enhancer model.","operationId":"predict_enhancer_v1_tasks_enhancer_predict_post","parameters":[{"name":"format","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Output format: ``json`` (default) or one of ``bedgraph``. Text formats are synchronous-only — combining one with ``Prefer: respond-async`` is a ``400``. An unsupported value is a ``415 unsupported_format``, never a silent fallback to JSON.","title":"Format"},"description":"Output format: ``json`` (default) or one of ``bedgraph``. Text formats are synchronous-only — combining one with ``Prefer: respond-async`` is a ``400``. An unsupported value is a ``415 unsupported_format``, never a silent fallback to JSON."},{"name":"accept","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Accept"}},{"name":"Prefer","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Set to ``respond-async`` to dispatch asynchronously: the server returns ``202`` with ``{data: {job_id, status, links}, meta}`` immediately and the result is polled from ``GET /v1/tasks/jobs/{job_id}``. Anything else (or omitting the header) delivers the result synchronously with ``200``. Async is JSON-only — combining it with a text ``format`` is a ``400``. Some endpoints *require* it above a size threshold and reject sync delivery with ``413 sync_too_large``.","title":"Prefer"},"description":"Set to ``respond-async`` to dispatch asynchronously: the server returns ``202`` with ``{data: {job_id, status, links}, meta}`` immediately and the result is polled from ``GET /v1/tasks/jobs/{job_id}``. Anything else (or omitting the header) delivers the result synchronously with ``200``. Async is JSON-only — combining it with a text ``format`` is a ``400``. Some endpoints *require* it above a size threshold and reject sync delivery with ``413 sync_too_large``."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnhancerPredictRequest"}}}},"responses":{"200":{"description":"Successful inference. ``data`` is a discriminated union keyed on ``task`` — narrow on ``data.task`` (or ``meta.task``) to reach task-specific fields; here it is always ``\"enhancer\"``. ``meta.task_specific_counts`` is the matching counts variant.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PredictResponse"}}},"headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}}},"400":{"description":"Bad request — e.g. `Prefer: respond-async` combined with a text format.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer key (`unauthorized`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}},"WWW-Authenticate":{"description":"Bearer challenge, e.g. ``Bearer realm=\"api.genomicintelligence.ai\", error=\"invalid_token\"``.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Key disabled or insufficient tier (`forbidden`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}},"WWW-Authenticate":{"description":"Bearer challenge, e.g. ``Bearer realm=\"api.genomicintelligence.ai\", error=\"invalid_token\"``.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown task, unknown job, or a job owned by another key (`not_found`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (`conflict`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"410":{"description":"Async job result expired out of the job store (`job_expired`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Either the 16 MiB request-body hard cap was exceeded (`payload_too_large`, enforced before parsing), or the body is over the endpoint's synchronous-delivery cap (`sync_too_large`; `error.details` carries `{sequence_length, threshold}` — retry the same request with `Prefer: respond-async`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"415":{"description":"The requested output format is not one this task can render (`unsupported_format`). The message lists the supported formats; the server never silently falls back to JSON.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation failed (`validation_failed`) — sequence length outside the task's bounds, a non-ACGTN character, an unknown key under `options` (every options object is closed), or a sequence below the *selected task's published `minLength`/`maxLength` bounds.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate or concurrency cap reached (`too_many_requests`). `Retry-After` and the `RateLimit-*` headers say when to retry.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always at least 1.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error (`internal_error`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Model still loading (`model_loading`), GPU memory exhausted (`insufficient_memory`), or service unavailable. `insufficient_memory` means the card OOM-ed on this request and its cache has been released — it is transient GPU pressure, not a server bug, so `Retry-After` is honest and a bounded retry is the right response.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always at least 1.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"202":{"description":"Async submission accepted — returned only when ``Prefer: respond-async`` was sent. Poll ``GET /v1/tasks/jobs/{job_id}``; ``Content-Location`` carries the same path.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}},"Content-Location":{"description":"Path to poll for the async result, ``/v1/tasks/jobs/{job_id}``.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AsyncAcceptedResponse"}}}}},"x-models":{"model":{"default":"g0-deepstarr","ids":["g0-deepstarr","dnabert-deepstarr"]}}}},"/v1/tasks/chromatin/predict":{"post":{"tags":["Tasks"],"summary":"Annotate chromatin features (DeepSEA-style, 919 labels)","description":"Multi-label classification over 919 ENCODE chromatin features, returned grouped into eight tracks (DNase, CTCF, Pol2, c-Myc, H3K27ac, H3K27me3, H3K4me1, Other). ``options.threshold`` gates which labels are reported.","operationId":"predict_chromatin_v1_tasks_chromatin_predict_post","parameters":[{"name":"format","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Output format: ``json`` (default) or one of ``bed``. Text formats are synchronous-only — combining one with ``Prefer: respond-async`` is a ``400``. An unsupported value is a ``415 unsupported_format``, never a silent fallback to JSON.","title":"Format"},"description":"Output format: ``json`` (default) or one of ``bed``. Text formats are synchronous-only — combining one with ``Prefer: respond-async`` is a ``400``. An unsupported value is a ``415 unsupported_format``, never a silent fallback to JSON."},{"name":"accept","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Accept"}},{"name":"Prefer","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Set to ``respond-async`` to dispatch asynchronously: the server returns ``202`` with ``{data: {job_id, status, links}, meta}`` immediately and the result is polled from ``GET /v1/tasks/jobs/{job_id}``. Anything else (or omitting the header) delivers the result synchronously with ``200``. Async is JSON-only — combining it with a text ``format`` is a ``400``. Some endpoints *require* it above a size threshold and reject sync delivery with ``413 sync_too_large``.","title":"Prefer"},"description":"Set to ``respond-async`` to dispatch asynchronously: the server returns ``202`` with ``{data: {job_id, status, links}, meta}`` immediately and the result is polled from ``GET /v1/tasks/jobs/{job_id}``. Anything else (or omitting the header) delivers the result synchronously with ``200``. Async is JSON-only — combining it with a text ``format`` is a ``400``. Some endpoints *require* it above a size threshold and reject sync delivery with ``413 sync_too_large``."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChromatinPredictRequest"}}}},"responses":{"200":{"description":"Successful inference. ``data`` is a discriminated union keyed on ``task`` — narrow on ``data.task`` (or ``meta.task``) to reach task-specific fields; here it is always ``\"chromatin\"``. ``meta.task_specific_counts`` is the matching counts variant.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PredictResponse"}}},"headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}}},"400":{"description":"Bad request — e.g. `Prefer: respond-async` combined with a text format.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer key (`unauthorized`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}},"WWW-Authenticate":{"description":"Bearer challenge, e.g. ``Bearer realm=\"api.genomicintelligence.ai\", error=\"invalid_token\"``.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Key disabled or insufficient tier (`forbidden`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}},"WWW-Authenticate":{"description":"Bearer challenge, e.g. ``Bearer realm=\"api.genomicintelligence.ai\", error=\"invalid_token\"``.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown task, unknown job, or a job owned by another key (`not_found`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (`conflict`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"410":{"description":"Async job result expired out of the job store (`job_expired`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Either the 16 MiB request-body hard cap was exceeded (`payload_too_large`, enforced before parsing), or the body is over the endpoint's synchronous-delivery cap (`sync_too_large`; `error.details` carries `{sequence_length, threshold}` — retry the same request with `Prefer: respond-async`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"415":{"description":"The requested output format is not one this task can render (`unsupported_format`). The message lists the supported formats; the server never silently falls back to JSON.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation failed (`validation_failed`) — sequence length outside the task's bounds, a non-ACGTN character, an unknown key under `options` (every options object is closed), or a sequence below the *selected task's published `minLength`/`maxLength` bounds.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate or concurrency cap reached (`too_many_requests`). `Retry-After` and the `RateLimit-*` headers say when to retry.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always at least 1.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error (`internal_error`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Model still loading (`model_loading`), GPU memory exhausted (`insufficient_memory`), or service unavailable. `insufficient_memory` means the card OOM-ed on this request and its cache has been released — it is transient GPU pressure, not a server bug, so `Retry-After` is honest and a bounded retry is the right response.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always at least 1.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"202":{"description":"Async submission accepted — returned only when ``Prefer: respond-async`` was sent. Poll ``GET /v1/tasks/jobs/{job_id}``; ``Content-Location`` carries the same path.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}},"Content-Location":{"description":"Path to poll for the async result, ``/v1/tasks/jobs/{job_id}``.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AsyncAcceptedResponse"}}}}},"x-models":{"model":{"default":"g0-deepsea","ids":["g0-deepsea","dnabert-deepsea"]}}}},"/v1/tasks/annotation/predict":{"post":{"tags":["Tasks"],"summary":"Find genes and their exon/intron/CDS structure","description":"Structure-aware gene finding: genes with transcript type and exon/intron/CDS structure, each with its own strand, renderable as GFF3 or BED.\n\n**Minimum input is 1000 bp** — the gene finder needs that much context to be meaningful. This is the bound the document used to advertise as 1 bp.\n\nDetection is strand-insensitive: the same genes are found whether the plus strand or its reverse complement is submitted, and the reported strand is relative to the input. ``options.reverse_complement`` (default true) averages each locus with its reverse complement, which improves minus-strand recall at roughly double the cost.\n\n**Above 200,000 bp this endpoint requires ``Prefer: respond-async``.** A synchronous JSON request over that size is rejected with ``413 sync_too_large`` (``error.details`` carries ``{sequence_length, threshold}``) because sync delivery would outlast the proxy timeout: a 500,000 bp annotation takes about 250 s against a 300 s idle timeout. The threshold is published as a number in ``x-sync-limit-bp`` on this operation — read it from there; this sentence is prose and a client cannot pin it.\n\n**The cap governs JSON delivery.** Async is JSON-only, so a BED or GFF3 request (``?format=`` or ``Accept: text/x-bed`` / ``text/x-gff3``) is *not* refused above the threshold: it is served synchronously at any admitted length. Near the 500,000 bp ceiling that is roughly 250 s of work and can exceed a gateway's 300 s idle timeout, so for long sequence prefer JSON with ``Prefer: respond-async`` and render the completed job yourself.","operationId":"predict_annotation_v1_tasks_annotation_predict_post","parameters":[{"name":"format","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Output format: ``json`` (default) or one of ``bed``, ``gff3``. Text formats are synchronous-only — combining one with ``Prefer: respond-async`` is a ``400``. An unsupported value is a ``415 unsupported_format``, never a silent fallback to JSON.","title":"Format"},"description":"Output format: ``json`` (default) or one of ``bed``, ``gff3``. Text formats are synchronous-only — combining one with ``Prefer: respond-async`` is a ``400``. An unsupported value is a ``415 unsupported_format``, never a silent fallback to JSON."},{"name":"accept","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Accept"}},{"name":"Prefer","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Set to ``respond-async`` to dispatch asynchronously: the server returns ``202`` with ``{data: {job_id, status, links}, meta}`` immediately and the result is polled from ``GET /v1/tasks/jobs/{job_id}``. Anything else (or omitting the header) delivers the result synchronously with ``200``. Async is JSON-only — combining it with a text ``format`` is a ``400``. Some endpoints *require* it above a size threshold and reject sync delivery with ``413 sync_too_large``.","title":"Prefer"},"description":"Set to ``respond-async`` to dispatch asynchronously: the server returns ``202`` with ``{data: {job_id, status, links}, meta}`` immediately and the result is polled from ``GET /v1/tasks/jobs/{job_id}``. Anything else (or omitting the header) delivers the result synchronously with ``200``. Async is JSON-only — combining it with a text ``format`` is a ``400``. Some endpoints *require* it above a size threshold and reject sync delivery with ``413 sync_too_large``."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnnotationPredictRequest"}}}},"responses":{"200":{"description":"Successful inference. ``data`` is a discriminated union keyed on ``task`` — narrow on ``data.task`` (or ``meta.task``) to reach task-specific fields; here it is always ``\"annotation\"``. ``meta.task_specific_counts`` is the matching counts variant.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PredictResponse"}}},"headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}}},"400":{"description":"Bad request — e.g. `Prefer: respond-async` combined with a text format.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer key (`unauthorized`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}},"WWW-Authenticate":{"description":"Bearer challenge, e.g. ``Bearer realm=\"api.genomicintelligence.ai\", error=\"invalid_token\"``.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Key disabled or insufficient tier (`forbidden`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}},"WWW-Authenticate":{"description":"Bearer challenge, e.g. ``Bearer realm=\"api.genomicintelligence.ai\", error=\"invalid_token\"``.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown task, unknown job, or a job owned by another key (`not_found`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (`conflict`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"410":{"description":"Async job result expired out of the job store (`job_expired`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Either the 16 MiB request-body hard cap was exceeded (`payload_too_large`, enforced before parsing), or the body is over the endpoint's synchronous-delivery cap (`sync_too_large`; `error.details` carries `{sequence_length, threshold}` — retry the same request with `Prefer: respond-async`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"415":{"description":"The requested output format is not one this task can render (`unsupported_format`). The message lists the supported formats; the server never silently falls back to JSON.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation failed (`validation_failed`) — sequence length outside the task's bounds, a non-ACGTN character, an unknown key under `options` (every options object is closed), or a sequence below the *selected task's published `minLength`/`maxLength` bounds.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate or concurrency cap reached (`too_many_requests`). `Retry-After` and the `RateLimit-*` headers say when to retry.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always at least 1.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error (`internal_error`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Model still loading (`model_loading`), GPU memory exhausted (`insufficient_memory`), or service unavailable. `insufficient_memory` means the card OOM-ed on this request and its cache has been released — it is transient GPU pressure, not a server bug, so `Retry-After` is honest and a bounded retry is the right response.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always at least 1.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"202":{"description":"Async submission accepted — returned only when ``Prefer: respond-async`` was sent. Poll ``GET /v1/tasks/jobs/{job_id}``; ``Content-Location`` carries the same path. **Required above this operation's ``x-sync-limit-bp``** (200,000 bp) — see the 413 response. That applies to JSON delivery only: async cannot carry a text format, so a BED/GFF3 request above the threshold is still served synchronously and may exceed the gateway timeout.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}},"Content-Location":{"description":"Path to poll for the async result, ``/v1/tasks/jobs/{job_id}``.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AsyncAcceptedResponse"}}}}},"x-models":{"model":{"default":"g0-annotation","ids":["g0-annotation"]}},"x-sync-limit-bp":200000}},"/v1/tasks/expression/predict":{"post":{"tags":["Tasks"],"summary":"Predict gene expression from the sequence around a TSS","description":"Predict expression for one gene from the sequence around its transcription start site (TSS), in ``log(TPM + 1)``.\n\nSubmit at least 9,198 bp with the TSS at least 4,599 bp from each end, and a ``tss_index`` (0-based, into the whitespace-stripped sequence) unless the submission is exactly 9,198 bp. Longer input is welcome. How far each model reads is its own: ``bio_spec.recommended_flank_bp`` (``GET /v1/tasks/expression/models``) is how many bp to fetch on each side of the TSS for that model. The response reports in ``meta.task_specific_counts.scored_window`` which part of the submission the model used (see that field). A TSS closer than 4,599 bp to either end is rejected with 422 rather than padded or truncated, and so is a window too N-rich, repeat-rich or low-complexity for the model to score.\n\n**Strand-sensitive.** This endpoint does **not** discover the TSS for you and does **not** reverse-complement: submit the gene's coding (sense) strand, 5'→3'. A minus-strand window is accepted and scored like any other, so the wrong strand returns a confident number rather than an error. If you have raw genomic input where the TSS is not known, use ``POST /v1/workflows/find-genes-and-predict-expression`` instead — it finds the genes and centres each window itself.\n\n``options.description`` is **required** — the model is conditioned on the experimental context (assay, biosample).","operationId":"predict_expression_v1_tasks_expression_predict_post","parameters":[{"name":"format","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Output format. ``expression`` renders JSON only; any other value is a ``415 unsupported_format`` (never a silent fallback).","title":"Format"},"description":"Output format. ``expression`` renders JSON only; any other value is a ``415 unsupported_format`` (never a silent fallback)."},{"name":"accept","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Accept"}},{"name":"Prefer","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Set to ``respond-async`` to dispatch asynchronously: the server returns ``202`` with ``{data: {job_id, status, links}, meta}`` immediately and the result is polled from ``GET /v1/tasks/jobs/{job_id}``. Anything else (or omitting the header) delivers the result synchronously with ``200``. Async is JSON-only — combining it with a text ``format`` is a ``400``. Some endpoints *require* it above a size threshold and reject sync delivery with ``413 sync_too_large``.","title":"Prefer"},"description":"Set to ``respond-async`` to dispatch asynchronously: the server returns ``202`` with ``{data: {job_id, status, links}, meta}`` immediately and the result is polled from ``GET /v1/tasks/jobs/{job_id}``. Anything else (or omitting the header) delivers the result synchronously with ``200``. Async is JSON-only — combining it with a text ``format`` is a ``400``. Some endpoints *require* it above a size threshold and reject sync delivery with ``413 sync_too_large``."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExpressionPredictRequest"}}}},"responses":{"200":{"description":"Successful inference. ``data`` is a discriminated union keyed on ``task`` — narrow on ``data.task`` (or ``meta.task``) to reach task-specific fields; here it is always ``\"expression\"``. ``meta.task_specific_counts`` is the matching counts variant.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PredictResponse"}}},"headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}}},"400":{"description":"Bad request — e.g. `Prefer: respond-async` combined with a text format.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer key (`unauthorized`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}},"WWW-Authenticate":{"description":"Bearer challenge, e.g. ``Bearer realm=\"api.genomicintelligence.ai\", error=\"invalid_token\"``.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Key disabled or insufficient tier (`forbidden`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}},"WWW-Authenticate":{"description":"Bearer challenge, e.g. ``Bearer realm=\"api.genomicintelligence.ai\", error=\"invalid_token\"``.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown task, unknown job, or a job owned by another key (`not_found`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (`conflict`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"410":{"description":"Async job result expired out of the job store (`job_expired`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Either the 16 MiB request-body hard cap was exceeded (`payload_too_large`, enforced before parsing), or the body is over the endpoint's synchronous-delivery cap (`sync_too_large`; `error.details` carries `{sequence_length, threshold}` — retry the same request with `Prefer: respond-async`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"415":{"description":"The requested output format is not one this task can render (`unsupported_format`). The message lists the supported formats; the server never silently falls back to JSON.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation failed (`validation_failed`) — sequence length outside the task's bounds, a non-ACGTN character, an unknown key under `options` (every options object is closed), or a sequence below the *selected task's published `minLength`/`maxLength` bounds.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate or concurrency cap reached (`too_many_requests`). `Retry-After` and the `RateLimit-*` headers say when to retry.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always at least 1.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error (`internal_error`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Model still loading (`model_loading`), GPU memory exhausted (`insufficient_memory`), or service unavailable. `insufficient_memory` means the card OOM-ed on this request and its cache has been released — it is transient GPU pressure, not a server bug, so `Retry-After` is honest and a bounded retry is the right response.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always at least 1.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"202":{"description":"Async submission accepted — returned only when ``Prefer: respond-async`` was sent. Poll ``GET /v1/tasks/jobs/{job_id}``; ``Content-Location`` carries the same path.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}},"Content-Location":{"description":"Path to poll for the async result, ``/v1/tasks/jobs/{job_id}``.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AsyncAcceptedResponse"}}}}},"x-models":{"model":{"default":"g0-expression-8192","ids":["g0-expression","g0-expression-8192"]}}}},"/v1/tasks/{task}/models":{"get":{"tags":["Tasks"],"summary":"List models available for a task","description":"List models registered for ``{task}``, plus which one is the default.\n\n``bio_spec.request_max_bp`` is the enforced ceiling — the field to\npre-check a sequence against. ``context_window_bp`` and\n``trained_window_bp`` describe what the model scores, not what the route\naccepts.","operationId":"list_task_models_v1_tasks__task__models_get","parameters":[{"name":"task","in":"path","required":true,"schema":{"type":"string","description":"Task identifier. The same value appears as ``meta.task`` on a prediction and as the ``data`` union discriminator. An unrecognised value is ``404 not_found``, not a 422.","enum":["promoter","splice","enhancer","chromatin","annotation","expression"],"title":"Task"},"description":"Task identifier. The same value appears as ``meta.task`` on a prediction and as the ``data`` union discriminator. An unrecognised value is ``404 not_found``, not a 422."}],"responses":{"200":{"description":"Every model registered for the task, with its ``bio_spec``: organism, capabilities, renderable output formats and the enforced ``request_max_bp`` ceiling. Use it to pick a ``model`` value; the length *minimum* is published once per task, as ``minLength`` on that task's request schema.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskModelsResponse"}}},"headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}}},"400":{"description":"Bad request — e.g. `Prefer: respond-async` combined with a text format.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown task, unknown job, or a job owned by another key (`not_found`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (`conflict`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"410":{"description":"Async job result expired out of the job store (`job_expired`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Either the 16 MiB request-body hard cap was exceeded (`payload_too_large`, enforced before parsing), or the body is over the endpoint's synchronous-delivery cap (`sync_too_large`; `error.details` carries `{sequence_length, threshold}` — retry the same request with `Prefer: respond-async`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"415":{"description":"The requested output format is not one this task can render (`unsupported_format`). The message lists the supported formats; the server never silently falls back to JSON.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation failed (`validation_failed`) — sequence length outside the task's bounds, a non-ACGTN character, an unknown key under `options` (every options object is closed), or a sequence below the *selected task's published `minLength`/`maxLength` bounds.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate or concurrency cap reached (`too_many_requests`). `Retry-After` and the `RateLimit-*` headers say when to retry.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always at least 1.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error (`internal_error`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Model still loading (`model_loading`), GPU memory exhausted (`insufficient_memory`), or service unavailable. `insufficient_memory` means the card OOM-ed on this request and its cache has been released — it is transient GPU pressure, not a server bug, so `Retry-After` is honest and a bounded retry is the right response.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always at least 1.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[]}},"/v1/workflows/find-genes-and-predict-expression":{"post":{"tags":["Workflows"],"summary":"Annotate a raw DNA sequence then predict per-gene expression","description":"Composite workflow: annotation → TSS centring → expression prediction.\n\nUse this instead of ``POST /v1/tasks/expression/predict`` when the input\nis raw genomic sequence and the TSS positions are unknown:\n\n1. Run gene finding to get transcript intervals with TSS positions.\n2. Cut a window around each gene's TSS, in the gene's own orientation.\n   The workflow takes as much flank on each side as the expression stage\n   can use, limited by what the submitted sequence holds, so longer\n   regions around genes give better expression predictions. Near an edge\n   the window is shorter on that side (padded with ``N`` where the\n   expression stage needs a fixed width) rather than dropping the gene;\n   the direct expression route, by contrast, refuses to pad at all.\n3. Score each window with the expression stage.\n\n``options.description`` is required and is applied to every gene.\n\n**Above 50,000 bp this endpoint requires ``Prefer: respond-async``.** A\nsynchronous request over that size is rejected with ``413\nsync_too_large`` (``error.details`` carries ``{sequence_length,\nthreshold}``) because sync delivery would outlast the proxy timeout.\nThe threshold is published as a number in ``x-sync-limit-bp`` on this\noperation — read it from there; this sentence is prose and a client\ncannot pin it.","operationId":"find_genes_and_predict_expression_v1_workflows_find_genes_and_predict_expression_post","parameters":[{"name":"Prefer","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Set to ``respond-async`` to dispatch asynchronously: the server returns ``202`` with ``{data: {job_id, status, links}, meta}`` immediately and the result is polled from ``GET /v1/tasks/jobs/{job_id}``. Anything else (or omitting the header) delivers the result synchronously with ``200``. Async is JSON-only — combining it with a text ``format`` is a ``400``. Some endpoints *require* it above a size threshold and reject sync delivery with ``413 sync_too_large``.","title":"Prefer"},"description":"Set to ``respond-async`` to dispatch asynchronously: the server returns ``202`` with ``{data: {job_id, status, links}, meta}`` immediately and the result is polled from ``GET /v1/tasks/jobs/{job_id}``. Anything else (or omitting the header) delivers the result synchronously with ``200``. Async is JSON-only — combining it with a text ``format`` is a ``400``. Some endpoints *require* it above a size threshold and reject sync delivery with ``413 sync_too_large``."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FindGenesAndPredictExpressionRequest"}}}},"responses":{"200":{"description":"Both stages completed. ``data.expression_predictions`` has one record per gene the annotation stage found; a gene whose TSS-centred window would run past the end of the submitted sequence comes back with ``skipped: true`` and a ``skip_reason`` rather than failing the whole request, so ``genes_predicted + genes_skipped == genes_found``.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FindGenesAndPredictExpressionResponse"}}},"headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}}},"400":{"description":"Bad request — e.g. `Prefer: respond-async` combined with a text format.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer key (`unauthorized`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}},"WWW-Authenticate":{"description":"Bearer challenge, e.g. ``Bearer realm=\"api.genomicintelligence.ai\", error=\"invalid_token\"``.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Key disabled or insufficient tier (`forbidden`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}},"WWW-Authenticate":{"description":"Bearer challenge, e.g. ``Bearer realm=\"api.genomicintelligence.ai\", error=\"invalid_token\"``.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown task, unknown job, or a job owned by another key (`not_found`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (`conflict`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"410":{"description":"Async job result expired out of the job store (`job_expired`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Either the 16 MiB request-body hard cap was exceeded (`payload_too_large`, enforced before parsing), or the body is over the endpoint's synchronous-delivery cap (`sync_too_large`; `error.details` carries `{sequence_length, threshold}` — retry the same request with `Prefer: respond-async`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"415":{"description":"The requested output format is not one this task can render (`unsupported_format`). The message lists the supported formats; the server never silently falls back to JSON.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation failed (`validation_failed`) — sequence length outside the task's bounds, a non-ACGTN character, an unknown key under `options` (every options object is closed), or a sequence below the *selected task's published `minLength`/`maxLength` bounds.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate or concurrency cap reached (`too_many_requests`). `Retry-After` and the `RateLimit-*` headers say when to retry.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always at least 1.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error (`internal_error`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Model still loading (`model_loading`), GPU memory exhausted (`insufficient_memory`), or service unavailable. `insufficient_memory` means the card OOM-ed on this request and its cache has been released — it is transient GPU pressure, not a server bug, so `Retry-After` is honest and a bounded retry is the right response.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always at least 1.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"202":{"description":"Async submission accepted (``Prefer: respond-async``). **Required above this operation's ``x-sync-limit-bp``** (50,000 bp) — see the 413 response. Poll ``GET /v1/tasks/jobs/{job_id}``.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}},"Content-Location":{"description":"``/v1/tasks/jobs/{job_id}``.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AsyncAcceptedResponse"}}}}},"x-sync-limit-bp":50000,"x-models":{"options.annotation_model":{"default":"g0-annotation","ids":["g0-annotation"]},"options.expression_model":{"default":"g0-expression-8192","ids":["g0-expression","g0-expression-8192"]}}}},"/v1/workflows/genomic-variant-interpretation":{"post":{"tags":["Workflows"],"summary":"Score the variants in a VCF and return an annotated copy","description":"Score every variant in a VCF and write back an annotated copy.\n\nGive it the ``s3://`` URI of a VCF. Each variant near a transcription\nstart site is scored in each requested tissue, and **every input record is\nwritten to the output** — those that could not be scored are flagged in\nplace rather than dropped, so the output is a superset of the input and\ncounts reconcile.\n\n**The annotated copy is written beside the input, named after it and\nafter the job** — ``sample.vcf.gz`` becomes\n``sample.annotated.<job>.vcf.gz`` in the same prefix, where ``<job>`` is\nthe first eight characters of the ``job_id``. Read the exact name from\n``data.output.uri`` rather than constructing it. This service needs\n``s3:GetObject`` on the object you name and ``s3:PutObject`` on its\nprefix, and nothing else. No listing is done, so a prefix holding a raw\nand a filtered VCF is fine: name either, and each gets its own output.\n\n**Submitting the same case twice gives you the same job.** The ``job_id``\nis derived from the request — caller, ``input.uri``, the input object's\nETag, ``client_ref`` and ``options`` — so a retry after an ambiguous\nfailure, or a restarted integration, resolves to the run already under way\n(or already finished, still inside the 24-hour window) rather than\nstarting a second multi-hour pass over the same object. There is no\n``Idempotency-Key`` to send. Two consequences: a **failed** job re-runs on\nresubmission, because de-duplicating a failure would strand the case for\nthe rest of the day; and to deliberately re-run a case that **succeeded**,\nchange ``client_ref``. Replacing the VCF under an unchanged path also\nyields a new job, because its ETag is part of the derivation.\n\n**This workflow is under development.** Your file is read, every record\nis matched against the GENCODE v50lift37 MANE Select start sites, every\nrecord is written back, and the counts are computed from it — but the\nper-tissue values in an annotated file are not final and are not yet to\nbe read as results. A run is model output when, and only when, the\nresponse carries ``meta.model`` and the annotated VCF carries a\n``##GEXModel`` header line; both are omitted rather than naming a model\nthat did not produce the values, so their presence is the signal.\n\nThe result of this operation is a receipt, not a payload: it names the\nobject that was written and reports how the run went. The predictions live\nin that object. A caller never has to parse a VCF to orchestrate the\nworkflow, and the annotation format inside it can change without breaking\nanything built against this envelope.\n\n**Async only.** A case takes hours, far past any proxy timeout, so there\nis no synchronous mode and no callback: submit, then poll. Results are\nretained for 24 hours; the annotated object is not on that clock.","operationId":"genomic_variant_interpretation_v1_workflows_genomic_variant_interpretation_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenomicVariantInterpretationRequest"}}}},"responses":{"200":{"description":"Never returned by this operation, which only ever accepts (202). Declared because ``GET /v1/tasks/jobs/{job_id}`` replays this envelope when the run completes, and a generated client needs the shape.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenomicVariantInterpretationResponse"}}},"headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}}},"400":{"headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"description":"Refused before any work started, always with ``error.code`` ``bad_request``. The cases, distinguishable today only by ``error.message``:\n\n* ``Prefer: respond-async`` was not sent (this operation has no synchronous mode).\n* ``input.uri`` is not an ``s3://`` URI naming a bucket and a key.\n* ``input.uri`` names a prefix rather than an object (it ends in ``/``), or its key does not end in ``.vcf``, ``.vcf.gz`` or ``.vcf.bgz``.\n* the object cannot be read — it does not exist, or this service has not been granted ``s3:GetObject`` on it.\n* the input VCF is empty, or larger than 2 GiB.\n* ``options.genes`` names an identifier that resolves to no MANE Select gene; the message names every unresolved one.\n* ``options.genome_build`` has no published start-site catalogue.\n\nThe input is validated **at submission**, so a typo costs a second rather than a poll cycle through a failed job.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer key (`unauthorized`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}},"WWW-Authenticate":{"description":"Bearer challenge, e.g. ``Bearer realm=\"api.genomicintelligence.ai\", error=\"invalid_token\"``.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Key disabled or insufficient tier (`forbidden`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}},"WWW-Authenticate":{"description":"Bearer challenge, e.g. ``Bearer realm=\"api.genomicintelligence.ai\", error=\"invalid_token\"``.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown task, unknown job, or a job owned by another key (`not_found`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (`conflict`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"410":{"description":"Async job result expired out of the job store (`job_expired`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Either the 16 MiB request-body hard cap was exceeded (`payload_too_large`, enforced before parsing), or the body is over the endpoint's synchronous-delivery cap (`sync_too_large`; `error.details` carries `{sequence_length, threshold}` — retry the same request with `Prefer: respond-async`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"415":{"description":"The requested output format is not one this task can render (`unsupported_format`). The message lists the supported formats; the server never silently falls back to JSON.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation failed (`validation_failed`) — sequence length outside the task's bounds, a non-ACGTN character, an unknown key under `options` (every options object is closed), or a sequence below the *selected task's published `minLength`/`maxLength` bounds.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate or concurrency cap reached (`too_many_requests`). `Retry-After` and the `RateLimit-*` headers say when to retry.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying. Always at least 1.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error (`internal_error`).","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}}},"description":"``service_unavailable``. On the POST it means the transcription-start-site catalogue for the requested build is missing or unreadable **on our side** — the request was correct, so retry rather than change it. On the poll it means the input object could not be downloaded, or the annotated copy could not be written, after the job was accepted. It is never ``model_loading`` or ``insufficient_memory``.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"202":{"description":"Submission accepted. **This operation is async-only** — a case runs for hours, so ``Prefer: respond-async`` is required and a request without it is refused with ``400``. Poll ``GET /v1/tasks/jobs/{job_id}``.","headers":{"X-Request-Id":{"description":"Request correlator, always a canonical UUID. Server-assigned unless the request carried a valid-UUID ``X-Request-Id``, which is echoed back; any other value is replaced. Mirrors ``error.request_id`` on error envelopes and ``meta.request_id`` on success; quote in support tickets.","schema":{"type":"string","format":"uuid"}},"X-Job-Id":{"description":"Server-generated UUIDv4 for the inference job. Same value appears in ``meta.job_id`` on success and is the lookup key for ``GET /v1/tasks/jobs/{job_id}``. Stable across the sync 200, async 202, and progress-poll 202 responses.","schema":{"type":"string","format":"uuid"}},"RateLimit-Limit":{"description":"Burst capacity: the size of the partner's token bucket, **not** the per-minute cap. The bucket holds one tenth of a minute's allowance (configured rpm / 6) and refills continuously at rpm / 60 per second, so the sustained ceiling is six times this number per minute — a key capped at 300 rpm advertises 50 here. Budget long-running work from the sustained rate; use this value only to size a burst.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Tokens left in the burst bucket after this request. Refills continuously at rpm / 60 per second up to `RateLimit-Limit`; it is not a countdown that resets on a window boundary.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until the burst bucket is full again. Because refill is continuous rather than windowed, this is usually far below 60 — one request into a full bucket typically reports 1.","schema":{"type":"integer"}},"RateLimit-Policy":{"description":"Policy in ``<burst capacity>;w=60`` form, e.g. ``50;w=60`` for a 300 rpm key. The capacity repeats `RateLimit-Limit` (rpm / 6) and `w=60` names the refill period the rate is expressed over, not a fixed window that resets.","schema":{"type":"string"}},"Content-Location":{"description":"``/v1/tasks/jobs/{job_id}``.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AsyncAcceptedResponse"}}}}},"parameters":[{"name":"Prefer","in":"header","required":true,"schema":{"type":"string","enum":["respond-async"]},"description":"**Required — this operation is async-only.** A case runs for hours, far past any proxy timeout, so a request without ``Prefer: respond-async`` is refused with ``400 bad_request`` rather than delivered synchronously."}]}}},"components":{"schemas":{"AnnotationCounts":{"properties":{"task":{"type":"string","const":"annotation","title":"Task"},"transcripts_found":{"type":"integer","title":"Transcripts Found"}},"additionalProperties":false,"type":"object","required":["task","transcripts_found"],"title":"AnnotationCounts"},"AnnotationData":{"properties":{"model":{"type":"string","title":"Model","description":"Model id that produced this result."},"input":{"$ref":"#/components/schemas/AnnotationInput","description":"The caller's label for the submitted sequence, echoed verbatim; nothing derived. The submitted length is ``meta.sequence_length``."},"summary":{"additionalProperties":true,"type":"object","title":"Summary","description":"Task-specific summary statistics. **Its keys are deliberately not part of this contract**: they are per-task statistics that may be added, renamed or removed without a contract revision, so consumers must not depend on them — branch on the typed fields (``meta`` and this payload's own declared keys) instead."},"formats":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Formats","description":"Optional per-format pre-rendered text payloads (BED/GFF3/…). In every GFF3 this service generates, column 2 (``source``) is the id of the model that produced the feature — the same value as ``model`` above — so a saved track records its own provenance. The one exception is a structure-aware model whose upstream pipeline emits its own canonical GFF3 (annotation's ``g0-annotation``): that document is passed through verbatim and keeps its producer's source value, which names a multi-stage pipeline rather than one model."},"task":{"type":"string","const":"annotation","title":"Task"},"transcripts":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Transcripts","description":"Detected transcripts. Every transcript carries gene boundaries (``start``/``end``/``strand``/``score``) plus ``tss_position`` and ``polya_position``. Structure-aware models (g0-annotation) additionally populate ``transcript_type`` (mRNA/lnc_RNA), ``transcript_type_score`` and 0-based half-open ``exons``/``introns``/``cds`` arrays. The ``formats`` object exposes ``bed`` and, for structure-aware models, a full ``gff3`` track (also available via ``Accept: text/x-gff3``)."}},"additionalProperties":true,"type":"object","required":["model","input","summary","task","transcripts"],"title":"AnnotationData","description":"``data`` shape for ``POST /v1/tasks/annotation/predict``."},"AnnotationInput":{"properties":{"sequence_name":{"type":"string","title":"Sequence Name","description":"The caller's label for the submitted sequence, echoed verbatim. Defaults to ``\"sequence\"`` when the request omitted it."}},"additionalProperties":false,"type":"object","required":["sequence_name"],"title":"AnnotationInput","description":"``data.input`` for ``POST /v1/tasks/annotation/predict``."},"AnnotationOptions":{"properties":{"shift_coordinates":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Shift Coordinates","description":"Set to \"UCSC\" to shift coordinates from a UCSC-style FASTA header (e.g. >chr8:1000-2000)."},"reverse_complement":{"type":"boolean","title":"Reverse Complement","description":"Structure-aware models (g0-annotation) only: average each locus with its reverse complement (improves minus-strand recall). Set false for a faster, single-pass smoke run. Ignored by boundary-only models.","default":true}},"additionalProperties":false,"type":"object","title":"AnnotationOptions"},"AnnotationPredictRequest":{"properties":{"sequence":{"type":"string","maxLength":500000,"minLength":1000,"pattern":"^\\s*(?:[ACGNTacgnt]\\s*)+$","title":"Sequence","description":"DNA sequence (A/C/G/T/N, case-insensitive). Whitespace (newlines, spaces, tabs) is stripped first, so a line-wrapped FASTA sequence body may be pasted verbatim; **length is measured against the whitespace-stripped string**, not the raw character count — so a line-wrapped body can satisfy the published ``minLength`` as a raw string and still be rejected once stripped. Count bases, not characters. 1,000–500,000 bp. The 1,000 bp floor applies to every annotation model — the gene finder needs that much context to be meaningful. This is the bound the document previously advertised as 1 bp. Requests outside the range are rejected with ``422 validation_failed`` before any model is loaded."},"sequence_name":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Sequence Name","description":"Display name for the sequence (e.g., 'chr1:1000-5000').","default":"sequence"},"model":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Model","description":"Model ID. If omitted, the task's default model is used. The valid ids and the default for this operation are published structurally as ``x-models`` on the operation itself — deliberately **not** as an ``enum`` here, so that adding a model cannot make a previously-generated client reject a valid id. ``GET /v1/tasks/{task}/models`` carries the same roster with full per-model specs."},"options":{"$ref":"#/components/schemas/AnnotationOptions"}},"additionalProperties":false,"type":"object","required":["sequence"],"title":"AnnotationPredictRequest","description":"Body for ``POST /v1/tasks/annotation/predict``.","example":{"options":{"threshold":0.5},"sequence":"ACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGT","sequence_name":"chr1:1000-3000"}},"AsyncAcceptedData":{"properties":{"job_id":{"type":"string","title":"Job Id"},"status":{"type":"string","const":"accepted","title":"Status"},"links":{"$ref":"#/components/schemas/JobLinks"}},"additionalProperties":true,"type":"object","required":["job_id","status","links"],"title":"AsyncAcceptedData","description":"``data`` of a ``202`` accept body."},"AsyncAcceptedResponse":{"properties":{"data":{"$ref":"#/components/schemas/AsyncAcceptedData"},"meta":{"$ref":"#/components/schemas/AsyncMeta"}},"additionalProperties":true,"type":"object","required":["data","meta"],"title":"AsyncAcceptedResponse","description":"``202`` returned by a predict/workflow POST carrying ``Prefer: respond-async``.\n\nSame ``{data, meta}`` envelope as the sync ``200`` so one client code\npath parses both. ``Content-Location`` and ``X-Job-Id`` headers carry\nthe same job id."},"AsyncMeta":{"properties":{"job_id":{"type":"string","title":"Job Id"},"request_id":{"type":"string","title":"Request Id","description":"Correlation id for the request that created or polled this job. Mirrored on the X-Request-Id response header. Note this is the *request's* id, not the job's — polling the same job twice yields two different request_ids and one job_id."},"task":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Task","description":"Task the job will run."},"mode":{"type":"string","const":"async","title":"Mode"}},"additionalProperties":true,"type":"object","required":["job_id","request_id","mode"],"title":"AsyncMeta","description":"``meta`` on both ``202`` shapes — a deliberately thin subset of\n:class:`Meta`, since no inference has happened yet."},"BioSpec":{"properties":{"sequence_type":{"type":"string","title":"Sequence Type","description":"Input alphabet family, e.g. \"DNA\"."},"tokenization":{"type":"string","title":"Tokenization","description":"\"BPE\" or \"k-mer\"."},"kmer_k":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Kmer K","description":"k for k-mer tokenizers; null for BPE."},"max_tokens":{"type":"integer","title":"Max Tokens","description":"Tokenizer output cap per window."},"request_max_bp":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Request Max Bp","description":"Longest ``sequence`` this model accepts, in bp — the admission cap, and the field to pre-check a request against. The matching minimum is published once per task, as ``minLength`` on that task's request schema, not here. Distinct from ``context_window_bp``/``trained_window_bp``, which describe what the model *scores* rather than what the route *accepts*."},"context_window_bp":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Context Window Bp","description":"The model's own input window, in bp. A request **shorter than this is accepted and scored, but against a window padded out to it** — the task's ``minLength`` is admission control, not a statement about regime. Compare your sequence length against this number to know whether the model saw real sequence or padding. Longer input is not a problem: the scanner steps a prediction window at a time and only the final partial window is padded. Null for models that do not slide a window (annotation, expression — see ``trained_window_bp`` for the latter)."},"trained_window_bp":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Trained Window Bp","description":"The fixed slice, in bp, the server cuts around ``tss_index`` for a model that has one (``g0-expression``: 9198; the model reads the central part of it, roughly 3 kb on each side of the TSS depending on sequence). Not a request bound — a longer submission is cut down to this server-side. Null for models that slide a window across the whole input, and for expression models that read a variable span around the TSS; see ``recommended_flank_bp``."},"recommended_flank_bp":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Recommended Flank Bp","description":"Expression only: how many bp of sequence to fetch on **each** side of the TSS for this model. Supply ``F`` bp of gene-sense (coding-strand) sequence before the TSS and ``F`` bp from the TSS onward, so the TSS is at offset ``F``, and send ``tss_index = F``. In genomic coordinates that is ``[tss - F, tss + F)`` on the plus strand and ``(tss - F, tss + F]``, then reverse-complemented, on the minus strand. Less is accepted down to the task's floor (4,599 bp each side, ``minLength`` 9198) and scored, but a model that reads further than the floor then sees less than it was trained on and its score drifts; the width of ``meta.task_specific_counts.scored_window`` shows how much was read. Equal to the floor for a model with a fixed window (``trained_window_bp``). Null for every other task."},"organism":{"type":"string","title":"Organism","description":"Organism the model was trained on."},"capabilities":{"items":{"type":"string"},"type":"array","title":"Capabilities","description":"Model capability tags."},"output_formats":{"items":{"type":"string"},"type":"array","title":"Output Formats","description":"Renderable output formats for this model."},"training_data":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Training Data","description":"Human-readable training-corpus summary."}},"additionalProperties":true,"type":"object","required":["sequence_type","tokenization","max_tokens","organism","capabilities","output_formats"],"title":"BioSpec","description":"Partner-facing model spec, echoed by ``GET /v1/tasks/{task}/models``.\n\nSourced from ``bio_spec`` in ``api/config/models.yaml``."},"ChromatinCounts":{"properties":{"task":{"type":"string","const":"chromatin","title":"Task"},"windows_processed":{"type":"integer","title":"Windows Processed"},"total_annotations":{"type":"integer","title":"Total Annotations","description":"Sum of per-track annotation counts across all windows."}},"additionalProperties":false,"type":"object","required":["task","windows_processed","total_annotations"],"title":"ChromatinCounts"},"ChromatinData":{"properties":{"model":{"type":"string","title":"Model","description":"Model id that produced this result."},"input":{"$ref":"#/components/schemas/ChromatinInput","description":"The caller's label for the submitted sequence, echoed verbatim; nothing derived. The submitted length is ``meta.sequence_length``."},"summary":{"additionalProperties":true,"type":"object","title":"Summary","description":"Task-specific summary statistics. **Its keys are deliberately not part of this contract**: they are per-task statistics that may be added, renamed or removed without a contract revision, so consumers must not depend on them — branch on the typed fields (``meta`` and this payload's own declared keys) instead."},"formats":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Formats","description":"Optional per-format pre-rendered text payloads (BED/GFF3/…). In every GFF3 this service generates, column 2 (``source``) is the id of the model that produced the feature — the same value as ``model`` above — so a saved track records its own provenance. The one exception is a structure-aware model whose upstream pipeline emits its own canonical GFF3 (annotation's ``g0-annotation``): that document is passed through verbatim and keeps its producer's source value, which names a multi-stage pipeline rather than one model."},"task":{"type":"string","const":"chromatin","title":"Task"},"windows":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Windows","description":"Per-window chromatin annotations."},"tracks":{"additionalProperties":true,"type":"object","title":"Tracks","description":"Per-position score tracks for visualization."}},"additionalProperties":true,"type":"object","required":["model","input","summary","task","windows","tracks"],"title":"ChromatinData","description":"``data`` shape for ``POST /v1/tasks/chromatin/predict``."},"ChromatinInput":{"properties":{"sequence_name":{"type":"string","title":"Sequence Name","description":"The caller's label for the submitted sequence, echoed verbatim. Defaults to ``\"sequence\"`` when the request omitted it."}},"additionalProperties":false,"type":"object","required":["sequence_name"],"title":"ChromatinInput","description":"``data.input`` for ``POST /v1/tasks/chromatin/predict``."},"ChromatinOptions":{"properties":{"threshold":{"type":"number","maximum":1.0,"minimum":0.0,"title":"Threshold","default":0.5}},"additionalProperties":false,"type":"object","title":"ChromatinOptions"},"ChromatinPredictRequest":{"properties":{"sequence":{"type":"string","maxLength":500000,"minLength":200,"pattern":"^\\s*(?:[ACGNTacgnt]\\s*)+$","title":"Sequence","description":"DNA sequence (A/C/G/T/N, case-insensitive). Whitespace (newlines, spaces, tabs) is stripped first, so a line-wrapped FASTA sequence body may be pasted verbatim; **length is measured against the whitespace-stripped string**, not the raw character count — so a line-wrapped body can satisfy the published ``minLength`` as a raw string and still be rejected once stripped. Count bases, not characters. 200–500,000 bp. The 200 bp floor applies to every chromatin model — both chromatin models use it. Requests outside the range are rejected with ``422 validation_failed`` before any model is loaded. Note that ``minLength`` is admission control, not a statement about regime: a sequence at least this long but shorter than the selected model's ``context_window_bp`` (published by ``GET /v1/tasks/{task}/models``) is accepted and scored, but against a window padded out to that size. Compare your length against that field to know whether the model saw real sequence or padding. Longer input is never a problem — the scanner steps one prediction window at a time and pads only the final partial window."},"sequence_name":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Sequence Name","description":"Display name for the sequence (e.g., 'chr1:1000-5000').","default":"sequence"},"model":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Model","description":"Model ID. If omitted, the task's default model is used. The valid ids and the default for this operation are published structurally as ``x-models`` on the operation itself — deliberately **not** as an ``enum`` here, so that adding a model cannot make a previously-generated client reject a valid id. ``GET /v1/tasks/{task}/models`` carries the same roster with full per-model specs."},"options":{"$ref":"#/components/schemas/ChromatinOptions"}},"additionalProperties":false,"type":"object","required":["sequence"],"title":"ChromatinPredictRequest","description":"Body for ``POST /v1/tasks/chromatin/predict``.","example":{"options":{"threshold":0.5},"sequence":"ACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGT","sequence_name":"chr1:1000-3000"}},"EnhancerCounts":{"properties":{"task":{"type":"string","const":"enhancer","title":"Task"},"windows_processed":{"type":"integer","title":"Windows Processed"}},"additionalProperties":false,"type":"object","required":["task","windows_processed"],"title":"EnhancerCounts"},"EnhancerData":{"properties":{"model":{"type":"string","title":"Model","description":"Model id that produced this result."},"input":{"$ref":"#/components/schemas/EnhancerInput","description":"The caller's label for the submitted sequence, echoed verbatim; nothing derived. The submitted length is ``meta.sequence_length``."},"summary":{"additionalProperties":true,"type":"object","title":"Summary","description":"Task-specific summary statistics. **Its keys are deliberately not part of this contract**: they are per-task statistics that may be added, renamed or removed without a contract revision, so consumers must not depend on them — branch on the typed fields (``meta`` and this payload's own declared keys) instead."},"formats":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Formats","description":"Optional per-format pre-rendered text payloads (BED/GFF3/…). In every GFF3 this service generates, column 2 (``source``) is the id of the model that produced the feature — the same value as ``model`` above — so a saved track records its own provenance. The one exception is a structure-aware model whose upstream pipeline emits its own canonical GFF3 (annotation's ``g0-annotation``): that document is passed through verbatim and keeps its producer's source value, which names a multi-stage pipeline rather than one model."},"task":{"type":"string","const":"enhancer","title":"Task"},"windows":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Windows","description":"Per-window enhancer scores."},"tracks":{"additionalProperties":true,"type":"object","title":"Tracks","description":"Per-position score tracks for visualization."}},"additionalProperties":true,"type":"object","required":["model","input","summary","task","windows","tracks"],"title":"EnhancerData","description":"``data`` shape for ``POST /v1/tasks/enhancer/predict``."},"EnhancerInput":{"properties":{"sequence_name":{"type":"string","title":"Sequence Name","description":"The caller's label for the submitted sequence, echoed verbatim. Defaults to ``\"sequence\"`` when the request omitted it."}},"additionalProperties":false,"type":"object","required":["sequence_name"],"title":"EnhancerInput","description":"``data.input`` for ``POST /v1/tasks/enhancer/predict``."},"EnhancerOptions":{"properties":{},"additionalProperties":false,"type":"object","title":"EnhancerOptions"},"EnhancerPredictRequest":{"properties":{"sequence":{"type":"string","maxLength":500000,"minLength":50,"pattern":"^\\s*(?:[ACGNTacgnt]\\s*)+$","title":"Sequence","description":"DNA sequence (A/C/G/T/N, case-insensitive). Whitespace (newlines, spaces, tabs) is stripped first, so a line-wrapped FASTA sequence body may be pasted verbatim; **length is measured against the whitespace-stripped string**, not the raw character count — so a line-wrapped body can satisfy the published ``minLength`` as a raw string and still be rejected once stripped. Count bases, not characters. 50–500,000 bp. The 50 bp floor applies to every enhancer model — it is g0-deepstarr's gate; the k-mer model tolerates shorter input but is unaffected above the floor. Requests outside the range are rejected with ``422 validation_failed`` before any model is loaded. Note that ``minLength`` is admission control, not a statement about regime: a sequence at least this long but shorter than the selected model's ``context_window_bp`` (published by ``GET /v1/tasks/{task}/models``) is accepted and scored, but against a window padded out to that size. Compare your length against that field to know whether the model saw real sequence or padding. Longer input is never a problem — the scanner steps one prediction window at a time and pads only the final partial window."},"sequence_name":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Sequence Name","description":"Display name for the sequence (e.g., 'chr1:1000-5000').","default":"sequence"},"model":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Model","description":"Model ID. If omitted, the task's default model is used. The valid ids and the default for this operation are published structurally as ``x-models`` on the operation itself — deliberately **not** as an ``enum`` here, so that adding a model cannot make a previously-generated client reject a valid id. ``GET /v1/tasks/{task}/models`` carries the same roster with full per-model specs."},"options":{"$ref":"#/components/schemas/EnhancerOptions"}},"additionalProperties":false,"type":"object","required":["sequence"],"title":"EnhancerPredictRequest","description":"Body for ``POST /v1/tasks/enhancer/predict``.","example":{"options":{"threshold":0.5},"sequence":"ACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGT","sequence_name":"chr1:1000-3000"}},"ErrorBody":{"properties":{"code":{"type":"string","enum":["bad_request","unauthorized","forbidden","not_found","conflict","job_expired","payload_too_large","sync_too_large","unsupported_format","validation_failed","too_many_requests","rate_limited","internal_error","timeout","insufficient_memory","model_not_found","task_not_supported_by_model","model_loading","service_unavailable","http_error","unknown"],"title":"Code","description":"Machine-readable error code (snake_case). The enum is the complete set the service emits today; treat an unlisted value as a generic failure rather than a parse error, since a new code can ship before a client is regenerated."},"message":{"type":"string","title":"Message","description":"Human-readable summary; safe to surface."},"request_id":{"type":"string","title":"Request Id","description":"Request correlator, always a canonical UUID; mirrors the ``X-Request-Id`` response header. Server-assigned unless you send ``X-Request-Id`` yourself and it parses as a UUID, in which case yours is echoed back; any other value is replaced. Always populated. Quote in support tickets."},"details":{"anyOf":[{"$ref":"#/components/schemas/ValidationFailedDetails"},{"$ref":"#/components/schemas/TaskNotSupportedByModelDetails"},{"$ref":"#/components/schemas/ModelNotFoundDetails"},{"$ref":"#/components/schemas/SyncTooLargeDetails"},{"$ref":"#/components/schemas/GenericDetails"},{"type":"null"}],"title":"Details","description":"Code-specific structured details. See per-code shapes in ValidationFailedDetails, TaskNotSupportedByModelDetails, ModelNotFoundDetails, SyncTooLargeDetails. Other codes may carry a free-form payload or omit details entirely."}},"additionalProperties":true,"type":"object","required":["code","message","request_id"],"title":"ErrorBody","description":"Inner error body (the value of the top-level ``error`` key).\n\n``details`` is a code-specific structured payload. The shape is\ndocumented per code in ``https://docs.genomicintelligence.ai/reference/errors.md`` and modelled\nhere as a discriminated union keyed on the sibling ``code`` field;\ntyped clients should switch on ``code`` first, then read ``details``."},"ErrorResponse":{"properties":{"error":{"$ref":"#/components/schemas/ErrorBody"}},"type":"object","required":["error"],"title":"ErrorResponse","description":"Unified error envelope for every non-2xx response."},"ExpressionCounts":{"properties":{"task":{"type":"string","const":"expression","title":"Task"},"tss_index":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Tss Index","description":"0-based TSS offset the server applied, into the whitespace-stripped ``sequence`` that was submitted. Echoes the request's ``tss_index``, or the implied 4599 when the submission was exactly 9198 bp."},"scored_window":{"anyOf":[{"items":{"type":"integer"},"type":"array"},{"type":"null"}],"title":"Scored Window","description":"``[start, end]`` — the half-open slice of the submitted, whitespace-stripped sequence the server cut for the model. For ``g0-expression`` it is the 9198 bp slice ``[tss_index-4599, tss_index+4599]``, of which the model reads the central part (roughly 3 kb on each side of the TSS, depending on sequence). For a model whose ``bio_spec.trained_window_bp`` is null it is the span actually read, so its width shows how much flank was used."}},"additionalProperties":false,"type":"object","required":["task"],"title":"ExpressionCounts","description":"Expression has no per-call counts — the prediction is a single value.\n\nWhat it carries instead is *windowing provenance*: an expression model\nreads a stretch of sequence around the TSS (how much depends on the\nmodel and on the sequence), while a caller may submit up to 500,000 bp.\nThese fields report which part of the submission the model used (see\n``scored_window``), so the contract is verifiable from the response\nalone rather than taken on trust.\n\nAlways populated by ``POST /v1/tasks/expression/predict``."},"ExpressionData":{"properties":{"model":{"type":"string","title":"Model","description":"Model id that produced this result."},"input":{"$ref":"#/components/schemas/ExpressionInput","description":"Echo of the request: the caller's ``sequence_name``, the ``description`` the prediction was conditioned on, and the ``tss_index`` the server applied. The window that offset produced is ``meta.task_specific_counts.scored_window``; the submitted length is ``meta.sequence_length``."},"summary":{"additionalProperties":true,"type":"object","title":"Summary","description":"Task-specific summary statistics. **Its keys are deliberately not part of this contract**: they are per-task statistics that may be added, renamed or removed without a contract revision, so consumers must not depend on them — branch on the typed fields (``meta`` and this payload's own declared keys) instead."},"formats":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Formats","description":"Optional per-format pre-rendered text payloads (BED/GFF3/…). In every GFF3 this service generates, column 2 (``source``) is the id of the model that produced the feature — the same value as ``model`` above — so a saved track records its own provenance. The one exception is a structure-aware model whose upstream pipeline emits its own canonical GFF3 (annotation's ``g0-annotation``): that document is passed through verbatim and keeps its producer's source value, which names a multi-stage pipeline rather than one model."},"task":{"type":"string","const":"expression","title":"Task"},"prediction":{"additionalProperties":true,"type":"object","title":"Prediction","description":"Expression prediction record: ``{expression, expression_log_tpm, expression_tpm, unit}``."}},"additionalProperties":true,"type":"object","required":["model","input","summary","task","prediction"],"title":"ExpressionData","description":"``data`` shape for ``POST /v1/tasks/expression/predict``.\n\n``input`` echoes the request only: ``sequence_name``, ``description``\nand the ``tss_index`` the server applied. The windowing provenance the\nserver derived from that offset is in ``meta`` — which part of the\nsubmission the model used is ``meta.task_specific_counts.scored_window``\n(see that field), and the submitted length is ``meta.sequence_length``."},"ExpressionInput":{"properties":{"sequence_name":{"type":"string","title":"Sequence Name","description":"The caller's label for the submitted sequence, echoed verbatim. Defaults to ``\"sequence\"`` when the request omitted it."},"description":{"type":"string","title":"Description","description":"The experimental context the prediction was conditioned on (cell type / assay), echoed from ``options.description``."},"tss_index":{"type":"integer","title":"Tss Index","description":"The 0-based TSS offset the server applied, into the whitespace-stripped ``sequence`` that was submitted. Echoes the request's ``tss_index``, or the 4599 implied by a submission of exactly 9198 bp. The window it produced is ``meta.task_specific_counts.scored_window``."}},"additionalProperties":false,"type":"object","required":["sequence_name","description","tss_index"],"title":"ExpressionInput","description":"``data.input`` for ``POST /v1/tasks/expression/predict``.\n\nThree echoes, all of them things the caller sent or the server chose on\nthe caller's behalf. ``tss_index`` is the second kind: it is optional on\nthe request and defaults to 4599 when the submission is exactly\n9,198 bp, so the echo is the only statement of which offset was\nactually applied.\n\nWhat is **not** here, deliberately: ``scored_window`` (read\n``meta.task_specific_counts.scored_window``) and\n``submitted_sequence_length`` (read ``meta.sequence_length``). Both were\nderived twins of a ``meta`` field."},"ExpressionOptions":{"properties":{"description":{"type":"string","minLength":1,"title":"Description","description":"Experimental context (cell type, assay, conditions). **Required** — the model is conditioned on it, e.g. \"assay term name is polyA plus RNA-seq. biosample summary is Homo sapiens K562.\""}},"additionalProperties":false,"type":"object","required":["description"],"title":"ExpressionOptions"},"ExpressionPredictRequest":{"properties":{"sequence":{"type":"string","maxLength":500000,"minLength":9198,"pattern":"^\\s*(?:[ACGNTacgnt]\\s*)+$","title":"Sequence","description":"DNA sequence (A/C/G/T/N, case-insensitive). Whitespace (newlines, spaces, tabs) is stripped first, so a line-wrapped FASTA sequence body may be pasted verbatim; **all lengths and ``tss_index`` are measured against the whitespace-stripped string**. At least 9,198 bp, with the TSS at least 4,599 bp from each end (see ``tss_index``). Longer input is welcome: fetch the selected model's ``bio_spec.recommended_flank_bp`` bp on each side of the TSS. The server cuts that model's slice around ``tss_index`` before inference."},"sequence_name":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Sequence Name","description":"Display name for the sequence (e.g., 'chr1:1000-5000').","default":"sequence"},"model":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Model","description":"Model ID. If omitted, the task's default model is used. The valid ids and the default for this operation are published structurally as ``x-models`` on the operation itself — deliberately **not** as an ``enum`` here, so that adding a model cannot make a previously-generated client reject a valid id. ``GET /v1/tasks/{task}/models`` carries the same roster with full per-model specs."},"options":{"$ref":"#/components/schemas/ExpressionOptions","description":"Expression options. ``options.description`` is required — the model is conditioned on the experimental context."},"tss_index":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Tss Index","description":"0-based offset of the transcription start site **into the whitespace-stripped ``sequence``** (i.e. count nucleotides, not file characters — a line-wrapped FASTA would otherwise be off by its newline count). The response reports in ``meta.task_specific_counts.scored_window`` which part of the submission the selected model used around it (see that field). Required unless ``sequence`` is exactly 9,198 bp, in which case it defaults to 4599 (the only legal value). Must satisfy 4599 <= tss_index <= len(sequence) - 4599, i.e. at least 4,599 bp on each side of the TSS; out-of-range is a 422 rather than an N-padded guess."}},"additionalProperties":false,"type":"object","required":["sequence","options"],"title":"ExpressionPredictRequest","description":"Envelope for ``POST /v1/tasks/expression/predict``.\n\nExpression is the one task whose models read the sequence around a\nTSS rather than the whole input, and how far each model reads is its\nown: ``bio_spec.recommended_flank_bp`` says how many bp to fetch on\neach side of the TSS for that model. Input used to be silently\ntruncated or padded to fit, which produced confident but wrong\nnumbers. The contract now makes the TSS explicit: the caller says\nwhere it is and the *server* cuts the model's slice around it.\n\nThis is a literal route rather than the templated ``/{task}/predict``\none precisely so the published OpenAPI document can carry the\nexpression-specific ``minLength``/``maxLength`` and the typed\n``options`` object — an operation keyed on a path *parameter* cannot\nvary its request schema per value.","example":{"options":{"description":"assay term name is polyA plus RNA-seq. biosample summary is Homo sapiens HepG2."},"sequence":"ACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGT","sequence_name":"ALB","tss_index":4599}},"FindGenesAndPredictExpressionCounts":{"properties":{"genes_found":{"type":"integer","title":"Genes Found","description":"Genes detected by the annotation stage on the input sequence."},"genes_predicted":{"type":"integer","title":"Genes Predicted","description":"Genes whose expression was successfully predicted (TSS-centered window resolved + expression model returned a value)."},"genes_skipped":{"type":"integer","title":"Genes Skipped","description":"Genes annotation found but the expression stage skipped — usually because the TSS-centered window would extend past the input sequence. ``data.expression_predictions[].skip_reason`` carries the per-gene cause."}},"additionalProperties":false,"type":"object","required":["genes_found","genes_predicted","genes_skipped"],"title":"FindGenesAndPredictExpressionCounts","description":"``meta.task_specific_counts`` shape for the composite workflow.\n\nInvariant: ``genes_predicted + genes_skipped == genes_found``."},"FindGenesAndPredictExpressionData":{"properties":{"task":{"type":"string","const":"find_genes_and_predict_expression","title":"Task"},"annotation_model":{"type":"string","title":"Annotation Model"},"expression_model":{"type":"string","title":"Expression Model"},"input":{"$ref":"#/components/schemas/FindGenesAndPredictExpressionInput","description":"Echo of the request: ``sequence_name`` and the ``description`` the expression stage was conditioned on. The submitted length is not echoed here — read ``meta.sequence_length``."},"summary":{"additionalProperties":true,"type":"object","title":"Summary","description":"Aggregate stats: gene counts plus avg/min/max expression across non-skipped predictions. **Its keys are deliberately not part of this contract**: they are per-task statistics that may be added, renamed or removed without a contract revision, so consumers must not depend on them — branch on the typed fields (``meta`` and this payload's own declared keys) instead."},"annotation":{"additionalProperties":true,"type":"object","title":"Annotation","description":"Annotation stage's full ``data`` payload (same shape as ``AnnotationData``)."},"expression_predictions":{"items":{"$ref":"#/components/schemas/GeneExpressionPredictionData"},"type":"array","title":"Expression Predictions","description":"One record per gene found by annotation."}},"additionalProperties":true,"type":"object","required":["task","annotation_model","expression_model","input","summary","annotation","expression_predictions"],"title":"FindGenesAndPredictExpressionData","description":"``data`` shape for ``POST /v1/workflows/find-genes-and-predict-expression``."},"FindGenesAndPredictExpressionInput":{"properties":{"sequence_name":{"type":"string","title":"Sequence Name","description":"The caller's label for the submitted sequence, echoed verbatim. Defaults to ``\"sequence\"`` when the request omitted it."},"description":{"type":"string","title":"Description","description":"The experimental context the expression stage was conditioned on, echoed from ``options.description``."}},"additionalProperties":false,"type":"object","required":["sequence_name","description"],"title":"FindGenesAndPredictExpressionInput","description":"``data.input`` for the composite workflow.\n\nNo ``tss_index``: the composite windows each gene itself and reports the\nresult per gene in ``data.expression_predictions[].tss_position``."},"FindGenesAndPredictExpressionMeta":{"properties":{"job_id":{"type":"string","title":"Job Id"},"request_id":{"type":"string","title":"Request Id","description":"Correlation id for this request, mirrored on the X-Request-Id response header and identical to ``error.request_id`` on the failure envelope."},"task":{"type":"string","const":"find_genes_and_predict_expression","title":"Task","description":"Workflow name. Present so ``meta.task`` is required on every success envelope, composite included, and always agrees with ``data.task``."},"model":{"type":"string","title":"Model","description":"Composite identifier: \"<annotation_model>+<expression_model>\". Use ``annotation_model`` / ``expression_model`` for the parts."},"cold_start":{"type":"boolean","title":"Cold Start","description":"True if EITHER stage had to load its model for this request."},"model_load_time_ms":{"type":"integer","title":"Model Load Time Ms","description":"Sum of per-stage load times (annotation + expression)."},"inference_time_ms":{"type":"integer","title":"Inference Time Ms","description":"Sum of per-stage inference times."},"sequence_length":{"type":"integer","title":"Sequence Length"},"task_specific_counts":{"$ref":"#/components/schemas/FindGenesAndPredictExpressionCounts"},"annotation_model":{"type":"string","title":"Annotation Model"},"expression_model":{"type":"string","title":"Expression Model"},"annotation":{"$ref":"#/components/schemas/StageTimings","description":"Annotation stage cold-start + timing."},"expression":{"$ref":"#/components/schemas/StageTimings","description":"Expression stage cold-start + timing."}},"additionalProperties":true,"type":"object","required":["job_id","request_id","task","model","cold_start","model_load_time_ms","inference_time_ms","sequence_length","task_specific_counts","annotation_model","expression_model","annotation","expression"],"title":"FindGenesAndPredictExpressionMeta","description":"``meta`` shape for ``POST /v1/workflows/find-genes-and-predict-expression``.\n\nInherits the spine fields from the simple-task ``Meta`` (job_id,\ncold_start, *_time_ms, sequence_length, task_specific_counts) but\nadds the composite-specific keys: per-stage model ids and per-stage\ntiming blocks. ``model`` is the canonical concatenation\n``\"<annotation_model>+<expression_model>\"`` — the same string the\nWeb UI displays as the run identifier."},"FindGenesAndPredictExpressionOptions":{"properties":{"description":{"type":"string","minLength":1,"title":"Description","description":"Experimental context (cell type, assay, conditions) applied to every found gene. **Required** — the expression stage is conditioned on it."},"annotation_model":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Annotation Model"},"expression_model":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Expression Model"},"shift_coordinates":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Shift Coordinates"}},"additionalProperties":false,"type":"object","required":["description"],"title":"FindGenesAndPredictExpressionOptions"},"FindGenesAndPredictExpressionRequest":{"properties":{"sequence":{"type":"string","maxLength":500000,"minLength":1000,"pattern":"^\\s*(?:[ACGNTacgnt]\\s*)+$","title":"Sequence","description":"DNA sequence (A/C/G/T/N, case-insensitive). Whitespace (newlines, spaces, tabs) is stripped first, so a line-wrapped FASTA sequence body may be pasted verbatim; **length is measured against the whitespace-stripped string**, not the raw character count — so a line-wrapped body can satisfy the published ``minLength`` as a raw string and still be rejected once stripped. Count bases, not characters. 1,000–500,000 bp. The 1,000 bp floor applies to every annotation model — the annotation stage sets it — the workflow cannot find a gene in less sequence than the gene finder looks at. Requests outside the range are rejected with ``422 validation_failed`` before any model is loaded."},"sequence_name":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Sequence Name","description":"Display name for the sequence (e.g., 'chr1:1000-5000').","default":"sequence"},"model":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Model","description":"Model ID. If omitted, the task's default model is used. The valid ids and the default for this operation are published structurally as ``x-models`` on the operation itself — deliberately **not** as an ``enum`` here, so that adding a model cannot make a previously-generated client reject a valid id. ``GET /v1/tasks/{task}/models`` carries the same roster with full per-model specs."},"options":{"$ref":"#/components/schemas/FindGenesAndPredictExpressionOptions","description":"``options.description`` is required — the expression stage is conditioned on the experimental context."}},"additionalProperties":false,"type":"object","required":["sequence","options"],"title":"FindGenesAndPredictExpressionRequest","description":"Body for ``POST /v1/workflows/find-genes-and-predict-expression``.\n\nThe floor is the annotation stage's — the workflow cannot find a gene\nin less sequence than the gene finder will look at.","example":{"options":{"description":"assay term name is polyA plus RNA-seq. biosample summary is Homo sapiens K562."},"sequence":"ACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGT","sequence_name":"chr8:127,680,000-127,700,000"}},"FindGenesAndPredictExpressionResponse":{"properties":{"data":{"$ref":"#/components/schemas/FindGenesAndPredictExpressionData"},"meta":{"$ref":"#/components/schemas/FindGenesAndPredictExpressionMeta"}},"additionalProperties":true,"type":"object","required":["data","meta"],"title":"FindGenesAndPredictExpressionResponse","description":"Success envelope for ``POST /v1/workflows/find-genes-and-predict-expression``.\n\nPublished in the partner OpenAPI document. Also returned by ``GET\n/v1/tasks/jobs/{job_id}`` when the polled job is a composite run, so\nthat operation's ``200`` is a union of this and\n:class:`PredictResponse`."},"GeneAnnotationProvenance":{"properties":{"build":{"type":"string","title":"Build","description":"GENCODE release, e.g. ``v50lift37``."},"md5":{"type":"string","title":"Md5","description":"MD5 of the GENCODE annotation the catalogue was built from."},"transcripts":{"type":"string","title":"Transcripts","description":"Which transcripts carry a start site. One per gene today, so a gene with an alternative promoter is scored at its MANE start only — stated rather than implied by the release.","default":"MANE Select"},"start_sites":{"type":"integer","title":"Start Sites","description":"Start sites in the catalogue."}},"additionalProperties":false,"type":"object","required":["build","md5","start_sites"],"title":"GeneAnnotationProvenance","description":"The gene annotation the run was scored against."},"GeneExpressionPredictionData":{"properties":{"gene_index":{"type":"integer","title":"Gene Index"},"gene_name":{"type":"string","title":"Gene Name"},"strand":{"type":"string","enum":["+","-"],"title":"Strand"},"tss_position":{"type":"integer","title":"Tss Position","description":"TSS coordinate within the input sequence (bp)."},"centered_sequence_length":{"type":"integer","title":"Centered Sequence Length"},"expression":{"type":"number","title":"Expression","description":"log(TPM + 1)."},"expression_tpm":{"type":"number","title":"Expression Tpm"},"skipped":{"type":"boolean","title":"Skipped"},"skip_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Skip Reason","description":"Present when skipped=True; missing otherwise."}},"additionalProperties":true,"type":"object","required":["gene_index","gene_name","strand","tss_position","centered_sequence_length","expression","expression_tpm","skipped"],"title":"GeneExpressionPredictionData","description":"Per-gene record in ``data.expression_predictions``."},"GenericDetails":{"properties":{},"additionalProperties":true,"type":"object","title":"GenericDetails","description":"Forward-compatibility tail of the :data:`ErrorDetails` union.\n\nAn open object with no required fields. It exists because the union\npreviously ended in a bare ``Any``, which made FastAPI emit\n``\"details\": {}`` — every typed variant was erased from the published\ndocument and a generated client got an untyped blob. This variant\nkeeps new error codes parseable by a strict client while leaving the\nfour modelled shapes visible in ``components.schemas``."},"GenomicVariantInterpretationCounts":{"properties":{"variants_in":{"type":"integer","title":"Variants In","description":"Records read from the input VCF."},"annotated":{"type":"integer","title":"Annotated","description":"Records carrying a prediction in the output."},"not_run":{"type":"integer","title":"Not Run","description":"Records written through unscored — typically because no transcription start site falls within ``options.window``, or because it belongs to a gene outside ``options.genes``. See ``not_run_reasons`` for the breakdown."},"not_run_reasons":{"additionalProperties":{"type":"integer"},"type":"object","title":"Not Run Reasons","description":"Why records were not scored, by reason: ``OUTSIDE_TSS_WINDOW``, ``NO_TSS_ON_CONTIG``, ``NO_SUPPORTED_ALT``, ``NO_REQUESTED_GENE_IN_WINDOW``. Sums to ``not_run``. A reason with no records is omitted."},"annotated_alleles":{"type":"integer","title":"Annotated Alleles","description":"ALT alleles carrying a prediction. Exceeds ``annotated`` where a record is multiallelic.","default":0},"associations":{"type":"integer","title":"Associations","description":"Allele-to-start-site pairs scored — **the unit of model work**, not the record count. One allele near three start sites is three.","default":0},"skipped_alleles":{"type":"integer","title":"Skipped Alleles","description":"ALT alleles ineligible for scoring (symbolic, breakends, the spanning deletion ``*``), listed per record in ``GEX_SKIPPED_ALT``. A record can be annotated for its other alleles and still have some counted here.","default":0}},"additionalProperties":false,"type":"object","required":["variants_in","annotated","not_run"],"title":"GenomicVariantInterpretationCounts","description":"``data.counts`` for the variant workflow.\n\nInvariant: ``annotated + not_run == variants_in``. Every input record is\nwritten to the output, whether or not it could be scored."},"GenomicVariantInterpretationData":{"properties":{"task":{"type":"string","const":"genomic_variant_interpretation","title":"Task"},"client_ref":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Ref","description":"Echo of the request's ``client_ref``, verbatim."},"status":{"type":"string","const":"ok","title":"Status","description":"Present so the payload reads as a receipt. A failed run is a failed job: it comes back as the natural 4xx/5xx with the error envelope, never as a 200 saying ``failed``."},"output":{"$ref":"#/components/schemas/VariantObjectRef","description":"The annotated copy, written beside the input and named after it and the job: ``sample.vcf.gz`` becomes ``sample.annotated.<job>.vcf.gz`` in the same prefix. Read the name from here rather than constructing it."},"counts":{"$ref":"#/components/schemas/GenomicVariantInterpretationCounts"}},"additionalProperties":true,"type":"object","required":["task","status","output","counts"],"title":"GenomicVariantInterpretationData","description":"``data`` for ``POST /v1/workflows/genomic-variant-interpretation``.\n\nA receipt, not a payload. The predictions live in the annotated VCF at\n``output.uri``; this envelope says where that object is and how the run\nwent, so a caller can orchestrate the workflow without parsing a VCF."},"GenomicVariantInterpretationMeta":{"properties":{"job_id":{"type":"string","title":"Job Id"},"request_id":{"type":"string","title":"Request Id","description":"Correlation id for this request, mirrored on the X-Request-Id response header."},"task":{"type":"string","const":"genomic_variant_interpretation","title":"Task"},"model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model","description":"The model that produced these values, and the marker that they are model output at all. **Absent while this workflow is under development**, as is the annotated VCF's ``##GEXModel`` header line: the field is omitted rather than naming a model that did not produce the values. Read the per-tissue log2 fold changes as results only when both are present."},"genome_build":{"type":"string","title":"Genome Build"},"gene_annotation":{"$ref":"#/components/schemas/GeneAnnotationProvenance","description":"Which start-site catalogue produced this result. Published in the receipt as well as the annotated VCF's header because the receipt is what a caller stores, and these values move when the science does."},"options_applied":{"$ref":"#/components/schemas/GenomicVariantInterpretationOptionsApplied","description":"Window and tissues as the run actually used them."},"input":{"$ref":"#/components/schemas/VariantObjectRef","description":"The VCF that was read — the object named by ``input.uri`` on the request. Echoed so a stored receipt is self-contained: it names both what was read and what was written. Always present."}},"additionalProperties":true,"type":"object","required":["job_id","request_id","task","genome_build","gene_annotation","options_applied","input"],"title":"GenomicVariantInterpretationMeta","description":"``meta`` for the variant workflow.\n\nCarries the provenance a result needs to stay interpretable months later:\nwhich assembly, which models, and the options actually applied — which may\ndiffer from those requested only by defaulting."},"GenomicVariantInterpretationOptions":{"properties":{"genome_build":{"type":"string","const":"GRCh37","title":"Genome Build","description":"Assembly the VCF's coordinates refer to. **Required** — a VCF header declares it only sometimes, and guessing it silently misplaces every window. ``GRCh37`` is the only build with a published start-site catalogue; the enum will gain a value when another is published, which is additive."},"window":{"type":"integer","maximum":100000.0,"minimum":1.0,"title":"Window","description":"Maximum distance in bp from a transcription start site for a variant to be scored.","default":5000},"tissues":{"items":{"type":"string"},"type":"array","maxItems":16,"minItems":1,"title":"Tissues","description":"Cell-type contexts to score, one model run each. The expression model is conditioned on these strings and the exact wording moves the prediction. Defaults to ``['heart', 'liver', 'brain']``.","default":["heart","liver","brain"]},"genes":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":1000,"minItems":1},{"type":"null"}],"title":"Genes","description":"Restrict scoring to these genes — a panel. Omit the field entirely to score every gene near a variant; an empty list is a ``422``, because a panel of nothing scores nothing and would otherwise return a green receipt with zero annotations that looks like a coverage result. Accepts HGNC symbols (``BRCA1``) or Ensembl gene ids with or without a version (``ENSG00000141510``, ``ENSG00000141510.17``); symbols are case-insensitive. An identifier that matches no MANE Select gene is a ``400`` naming every unresolved one, rather than being dropped — a panel silently missing a gene returns a result that looks complete and is not.\n\nOmit it to score every gene near a variant. Supplying one is the difference between tens of thousands of scored windows and a handful, so a case restricted to a panel finishes in a fraction of the time. Records near a start site that is **not** in the panel are written through with ``GEX_NOT_RUN_REASON=NO_REQUESTED_GENE_IN_WINDOW``, which is distinct from ``OUTSIDE_TSS_WINDOW``: the first says you did not ask, the second says there was nothing there."}},"additionalProperties":false,"type":"object","required":["genome_build"],"title":"GenomicVariantInterpretationOptions","description":"``options`` for ``POST /v1/workflows/genomic-variant-interpretation``.\n\nEverything the analysis needs from the caller's own case metadata arrives\nhere as a typed field, so the service never parses a partner's metadata\nfile and never depends on its format."},"GenomicVariantInterpretationOptionsApplied":{"properties":{"window":{"type":"integer","title":"Window","description":"TSS proximity window in bp."},"tissues":{"items":{"type":"string"},"type":"array","title":"Tissues","description":"Cell-type contexts scored, in order."},"genes":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Genes","description":"The panel as resolved to Ensembl gene ids, or null when the run was not restricted. Resolved rather than echoed, so a caller can see what their symbols became."}},"additionalProperties":false,"type":"object","required":["window","tissues"],"title":"GenomicVariantInterpretationOptionsApplied","description":"What the run actually used — which differs from the request only by\ndefaulting, and is the only way a caller can confirm which tissues were\nscored."},"GenomicVariantInterpretationRequest":{"properties":{"input":{"oneOf":[{"$ref":"#/components/schemas/S3ObjectInput"}],"title":"Input","discriminator":{"propertyName":"type","mapping":{"s3_object":"#/components/schemas/S3ObjectInput"}}},"client_ref":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Client Ref","description":"Opaque caller string, never parsed, echoed back in the result. It carries the caller's own case identity so this API does not have to model a case. **It does participate in this submission's identity**: the job id is derived from the request, so changing ``client_ref`` is how you deliberately re-run a case that already succeeded. Hashing is not parsing."},"options":{"$ref":"#/components/schemas/GenomicVariantInterpretationOptions"}},"additionalProperties":false,"type":"object","required":["input","options"],"title":"GenomicVariantInterpretationRequest","description":"Body for ``POST /v1/workflows/genomic-variant-interpretation``."},"GenomicVariantInterpretationResponse":{"properties":{"data":{"$ref":"#/components/schemas/GenomicVariantInterpretationData"},"meta":{"$ref":"#/components/schemas/GenomicVariantInterpretationMeta"}},"additionalProperties":true,"type":"object","required":["data","meta"],"title":"GenomicVariantInterpretationResponse","description":"Success envelope for ``POST /v1/workflows/genomic-variant-interpretation``."},"HealthResponse":{"properties":{"status":{"type":"string","enum":["healthy","degraded"],"title":"Status","description":"`healthy` when the service is ready to accept inference; `degraded` only when configured for CUDA but the GPU is unreachable.","examples":["healthy"]},"version":{"type":"string","title":"Version","description":"Build identifier in `YYYY.MM.DD.iteration (commit_hash)` form. Quote this in any bug report so we can pin the exact code.","examples":["2026.05.02.1 (abc1234)"]}},"type":"object","required":["status","version"],"title":"HealthResponse","description":"Public health check response — liveness only.\n\nMinimum-disclosure: no GPU model, no loaded-model state, no driver\nstring. For the full operator payload, call ``/health/detailed``."},"JobLinks":{"properties":{"result":{"type":"string","title":"Result","description":"Path to poll, ``/v1/tasks/jobs/{job_id}``."}},"additionalProperties":true,"type":"object","required":["result"],"title":"JobLinks","description":"Hypermedia links on an async accept body."},"JobListResponse":{"properties":{"jobs":{"items":{"$ref":"#/components/schemas/JobSummary"},"type":"array","title":"Jobs"},"count":{"type":"integer","title":"Count","description":"Number of entries in ``jobs``."}},"additionalProperties":true,"type":"object","required":["jobs","count"],"title":"JobListResponse","description":"Success envelope for ``GET /v1/tasks/jobs``.\n\nOwner-scoped: only jobs submitted with the caller's key are listed."},"JobProgress":{"properties":{"current_percent":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Current Percent","description":"0–100 completion estimate; null before first update."},"message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Message","description":"Human-readable stage label from the adapter."},"elapsed_seconds":{"type":"number","title":"Elapsed Seconds","description":"Wall-clock seconds since the job was accepted."}},"additionalProperties":true,"type":"object","required":["elapsed_seconds"],"title":"JobProgress","description":"``data.progress`` on a ``202`` poll response."},"JobProgressData":{"properties":{"job_id":{"type":"string","title":"Job Id"},"status":{"type":"string","enum":["accepted","running"],"title":"Status"},"progress":{"$ref":"#/components/schemas/JobProgress"}},"additionalProperties":true,"type":"object","required":["job_id","status","progress"],"title":"JobProgressData","description":"``data`` of a ``202`` progress-poll body."},"JobProgressResponse":{"properties":{"data":{"$ref":"#/components/schemas/JobProgressData"},"meta":{"$ref":"#/components/schemas/AsyncMeta"}},"additionalProperties":true,"type":"object","required":["data","meta"],"title":"JobProgressResponse","description":"``202`` returned by ``GET /v1/tasks/jobs/{job_id}`` while a job runs."},"JobSummary":{"properties":{"job_id":{"type":"string","title":"Job Id","description":"Server-generated UUIDv4."},"task":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Task","description":"Task the job ran."},"mode":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mode","description":"\"sync\" or \"async\"."},"status":{"type":"string","enum":["accepted","running","complete","error"],"title":"Status","description":"Job lifecycle state."},"created_at":{"type":"number","title":"Created At","description":"Unix epoch seconds at submission."},"completed_at":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Completed At","description":"Unix epoch seconds at completion; null while running."}},"additionalProperties":true,"type":"object","required":["job_id","status","created_at"],"title":"JobSummary","description":"One entry in ``GET /v1/tasks/jobs``."},"Meta":{"properties":{"job_id":{"type":"string","title":"Job Id","description":"Server-generated UUIDv4. Mirrored on the X-Job-Id response header."},"request_id":{"type":"string","title":"Request Id","description":"Correlation id for this request, mirrored on the X-Request-Id response header and identical to ``error.request_id`` on the failure envelope. Quote it in support requests: it is the one handle that identifies a call whether it succeeded or failed."},"task":{"type":"string","title":"Task","description":"Task name (matches the {task} URL segment). Use this — or ``data.task`` — to narrow the typed unions."},"model":{"type":"string","title":"Model","description":"Model id that ran this inference."},"cold_start":{"type":"boolean","title":"Cold Start","description":"True if the model had to be loaded into GPU memory for this request. Useful for diagnosing first-request latency."},"model_load_time_ms":{"type":"integer","title":"Model Load Time Ms","description":"Milliseconds spent loading the model (0 when cold_start is False)."},"inference_time_ms":{"type":"integer","title":"Inference Time Ms","description":"Milliseconds spent running inference."},"sequence_length":{"type":"integer","title":"Sequence Length","description":"Length of the submitted sequence (bp)."},"task_specific_counts":{"oneOf":[{"$ref":"#/components/schemas/PromoterCounts"},{"$ref":"#/components/schemas/SpliceCounts"},{"$ref":"#/components/schemas/EnhancerCounts"},{"$ref":"#/components/schemas/ChromatinCounts"},{"$ref":"#/components/schemas/AnnotationCounts"},{"$ref":"#/components/schemas/ExpressionCounts"}],"title":"Task Specific Counts","description":"Discriminated counts payload (see per-task ``*Counts`` models).","discriminator":{"propertyName":"task","mapping":{"annotation":"#/components/schemas/AnnotationCounts","chromatin":"#/components/schemas/ChromatinCounts","enhancer":"#/components/schemas/EnhancerCounts","expression":"#/components/schemas/ExpressionCounts","promoter":"#/components/schemas/PromoterCounts","splice":"#/components/schemas/SpliceCounts"}}}},"additionalProperties":true,"type":"object","required":["job_id","request_id","task","model","cold_start","model_load_time_ms","inference_time_ms","sequence_length","task_specific_counts"],"title":"Meta","description":"Metadata envelope shared by every successful predict response."},"ModelNotFoundDetails":{"properties":{"requested_model":{"type":"string","title":"Requested Model","description":"The unrecognised model ID from the request body."},"available_models":{"items":{"type":"string"},"type":"array","title":"Available Models","description":"Models registered for the requested task — every entry is a legal retry for this endpoint."}},"additionalProperties":false,"type":"object","required":["requested_model","available_models"],"title":"ModelNotFoundDetails","description":"``error.code == 'model_not_found'``."},"PredictResponse":{"properties":{"data":{"oneOf":[{"$ref":"#/components/schemas/PromoterData"},{"$ref":"#/components/schemas/SpliceData"},{"$ref":"#/components/schemas/EnhancerData"},{"$ref":"#/components/schemas/ChromatinData"},{"$ref":"#/components/schemas/AnnotationData"},{"$ref":"#/components/schemas/ExpressionData"}],"title":"Data","discriminator":{"propertyName":"task","mapping":{"annotation":"#/components/schemas/AnnotationData","chromatin":"#/components/schemas/ChromatinData","enhancer":"#/components/schemas/EnhancerData","expression":"#/components/schemas/ExpressionData","promoter":"#/components/schemas/PromoterData","splice":"#/components/schemas/SpliceData"}}},"meta":{"$ref":"#/components/schemas/Meta"}},"additionalProperties":true,"type":"object","required":["data","meta"],"title":"PredictResponse","description":"Success envelope for ``POST /v1/tasks/{task}/predict``."},"PromoterCounts":{"properties":{"task":{"type":"string","const":"promoter","title":"Task"},"windows_processed":{"type":"integer","title":"Windows Processed","description":"Number of sliding windows scored."},"regions_found":{"type":"integer","title":"Regions Found","description":"Detected promoter regions in this call."}},"additionalProperties":false,"type":"object","required":["task","windows_processed","regions_found"],"title":"PromoterCounts"},"PromoterData":{"properties":{"model":{"type":"string","title":"Model","description":"Model id that produced this result."},"input":{"$ref":"#/components/schemas/PromoterInput","description":"The caller's label for the submitted sequence, echoed verbatim; nothing derived. The submitted length is ``meta.sequence_length``."},"summary":{"additionalProperties":true,"type":"object","title":"Summary","description":"Task-specific summary statistics. **Its keys are deliberately not part of this contract**: they are per-task statistics that may be added, renamed or removed without a contract revision, so consumers must not depend on them — branch on the typed fields (``meta`` and this payload's own declared keys) instead."},"formats":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Formats","description":"Optional per-format pre-rendered text payloads (BED/GFF3/…). In every GFF3 this service generates, column 2 (``source``) is the id of the model that produced the feature — the same value as ``model`` above — so a saved track records its own provenance. The one exception is a structure-aware model whose upstream pipeline emits its own canonical GFF3 (annotation's ``g0-annotation``): that document is passed through verbatim and keeps its producer's source value, which names a multi-stage pipeline rather than one model."},"task":{"type":"string","const":"promoter","title":"Task"},"regions":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Regions","description":"Detected promoter regions (start/end/score)."},"window_details":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Window Details","description":"Per-window scoring detail (one entry per scanned window)."}},"additionalProperties":true,"type":"object","required":["model","input","summary","task","regions","window_details"],"title":"PromoterData","description":"``data`` shape for ``POST /v1/tasks/promoter/predict``."},"PromoterInput":{"properties":{"sequence_name":{"type":"string","title":"Sequence Name","description":"The caller's label for the submitted sequence, echoed verbatim. Defaults to ``\"sequence\"`` when the request omitted it."}},"additionalProperties":false,"type":"object","required":["sequence_name"],"title":"PromoterInput","description":"``data.input`` for ``POST /v1/tasks/promoter/predict``."},"PromoterOptions":{"properties":{"threshold":{"type":"number","maximum":1.0,"minimum":0.0,"title":"Threshold","default":0.5}},"additionalProperties":false,"type":"object","title":"PromoterOptions"},"PromoterPredictRequest":{"properties":{"sequence":{"type":"string","maxLength":500000,"minLength":300,"pattern":"^\\s*(?:[ACGNTacgnt]\\s*)+$","title":"Sequence","description":"DNA sequence (A/C/G/T/N, case-insensitive). Whitespace (newlines, spaces, tabs) is stripped first, so a line-wrapped FASTA sequence body may be pasted verbatim; **length is measured against the whitespace-stripped string**, not the raw character count — so a line-wrapped body can satisfy the published ``minLength`` as a raw string and still be rejected once stripped. Count bases, not characters. 300–500,000 bp. The 300 bp floor applies to every promoter model — it is the smallest ``context_window_bp`` among them, i.e. the shortest input that fills some promoter model's window exactly, with no padding. Requests outside the range are rejected with ``422 validation_failed`` before any model is loaded. Note that ``minLength`` is admission control, not a statement about regime: a sequence at least this long but shorter than the selected model's ``context_window_bp`` (published by ``GET /v1/tasks/{task}/models``) is accepted and scored, but against a window padded out to that size. Compare your length against that field to know whether the model saw real sequence or padding. Longer input is never a problem — the scanner steps one prediction window at a time and pads only the final partial window."},"sequence_name":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Sequence Name","description":"Display name for the sequence (e.g., 'chr1:1000-5000').","default":"sequence"},"model":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Model","description":"Model ID. If omitted, the task's default model is used. The valid ids and the default for this operation are published structurally as ``x-models`` on the operation itself — deliberately **not** as an ``enum`` here, so that adding a model cannot make a previously-generated client reject a valid id. ``GET /v1/tasks/{task}/models`` carries the same roster with full per-model specs."},"options":{"$ref":"#/components/schemas/PromoterOptions"}},"additionalProperties":false,"type":"object","required":["sequence"],"title":"PromoterPredictRequest","description":"Body for ``POST /v1/tasks/promoter/predict``.","example":{"options":{"threshold":0.5},"sequence":"ACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGT","sequence_name":"chr1:1000-3000"}},"S3ObjectInput":{"properties":{"type":{"type":"string","const":"s3_object","title":"Type"},"uri":{"type":"string","maxLength":1024,"minLength":8,"pattern":"^s3://[^/]+/.+","title":"Uri","description":"Full ``s3://bucket/key`` URI of the VCF to read, e.g. ``s3://bucket/cases/CASE-00123/sample.vcf.gz``. The key must end in ``.vcf``, ``.vcf.gz`` or ``.vcf.bgz``; nothing else in the prefix is listed, opened or read. **The annotated copy is written beside it, named after it and after the job** — ``sample.vcf.gz`` yields ``sample.annotated.<job>.vcf.gz`` in the same prefix, where ``<job>`` is the first eight characters of the ``job_id``. Read the exact name from ``data.output.uri`` rather than constructing it. Two VCFs in one prefix therefore produce two distinct outputs, and so do two different analyses of the SAME VCF — running one file against several panels is the ordinary case, and without the job in the name the second run would overwrite the first while the first receipt still pointed at it. This service must be granted ``s3:GetObject`` on the object and ``s3:PutObject`` on its prefix; ``s3:ListBucket`` is not required."}},"additionalProperties":false,"type":"object","required":["type","uri"],"title":"S3ObjectInput","description":"The VCF to read, named directly by the caller."},"SpliceCounts":{"properties":{"task":{"type":"string","const":"splice","title":"Task"},"windows_processed":{"type":"integer","title":"Windows Processed"},"sites_found":{"type":"integer","title":"Sites Found","description":"Detected splice sites (donor + acceptor)."}},"additionalProperties":false,"type":"object","required":["task","windows_processed","sites_found"],"title":"SpliceCounts"},"SpliceData":{"properties":{"model":{"type":"string","title":"Model","description":"Model id that produced this result."},"input":{"$ref":"#/components/schemas/SpliceInput","description":"The caller's label for the submitted sequence, echoed verbatim; nothing derived. The submitted length is ``meta.sequence_length``."},"summary":{"additionalProperties":true,"type":"object","title":"Summary","description":"Task-specific summary statistics. **Its keys are deliberately not part of this contract**: they are per-task statistics that may be added, renamed or removed without a contract revision, so consumers must not depend on them — branch on the typed fields (``meta`` and this payload's own declared keys) instead."},"formats":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Formats","description":"Optional per-format pre-rendered text payloads (BED/GFF3/…). In every GFF3 this service generates, column 2 (``source``) is the id of the model that produced the feature — the same value as ``model`` above — so a saved track records its own provenance. The one exception is a structure-aware model whose upstream pipeline emits its own canonical GFF3 (annotation's ``g0-annotation``): that document is passed through verbatim and keeps its producer's source value, which names a multi-stage pipeline rather than one model."},"task":{"type":"string","const":"splice","title":"Task"},"sites":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Sites","description":"Detected splice sites (donor / acceptor). **``start``/``end`` bound the scored BPE token, not the junction.** The model reads the sequence as byte-pair-encoded tokens and scores whole tokens, so each site's span is that token's character range — typically 4–8 bp, and varying site to site because token lengths do — while a donor or acceptor junction is a single base. ``token_index`` names the token. Treating the span as the feature's extent, or intersecting it with a base-resolution reference annotation, will be quietly wrong at that scale. The same spans are what ``?format=gff3`` writes into columns 4–5, where they outlive the response that produced them. No base-resolution position is published: deriving one from a token score would be a modelling claim the service cannot currently defend, and an invented precision in a saved file is worse than an honest span (GH#58)."},"tracks":{"additionalProperties":true,"type":"object","title":"Tracks","description":"Per-position score tracks for visualization."},"window_details":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Window Details","description":"Per-window scoring detail."}},"additionalProperties":true,"type":"object","required":["model","input","summary","task","sites","tracks","window_details"],"title":"SpliceData","description":"``data`` shape for ``POST /v1/tasks/splice/predict``."},"SpliceInput":{"properties":{"sequence_name":{"type":"string","title":"Sequence Name","description":"The caller's label for the submitted sequence, echoed verbatim. Defaults to ``\"sequence\"`` when the request omitted it."}},"additionalProperties":false,"type":"object","required":["sequence_name"],"title":"SpliceInput","description":"``data.input`` for ``POST /v1/tasks/splice/predict``."},"SpliceOptions":{"properties":{"threshold":{"type":"number","maximum":1.0,"minimum":0.0,"title":"Threshold","default":0.5},"site_types":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Site Types","description":"Subset of [\"donor\", \"acceptor\"]; default both."}},"additionalProperties":false,"type":"object","title":"SpliceOptions"},"SplicePredictRequest":{"properties":{"sequence":{"type":"string","maxLength":500000,"minLength":100,"pattern":"^\\s*(?:[ACGNTacgnt]\\s*)+$","title":"Sequence","description":"DNA sequence (A/C/G/T/N, case-insensitive). Whitespace (newlines, spaces, tabs) is stripped first, so a line-wrapped FASTA sequence body may be pasted verbatim; **length is measured against the whitespace-stripped string**, not the raw character count — so a line-wrapped body can satisfy the published ``minLength`` as a raw string and still be rejected once stripped. Count bases, not characters. 100–500,000 bp. The 100 bp floor applies to every splice model — it is the splice model's own gate. Requests outside the range are rejected with ``422 validation_failed`` before any model is loaded. Note that ``minLength`` is admission control, not a statement about regime: a sequence at least this long but shorter than the selected model's ``context_window_bp`` (published by ``GET /v1/tasks/{task}/models``) is accepted and scored, but against a window padded out to that size. Compare your length against that field to know whether the model saw real sequence or padding. Longer input is never a problem — the scanner steps one prediction window at a time and pads only the final partial window."},"sequence_name":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Sequence Name","description":"Display name for the sequence (e.g., 'chr1:1000-5000').","default":"sequence"},"model":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Model","description":"Model ID. If omitted, the task's default model is used. The valid ids and the default for this operation are published structurally as ``x-models`` on the operation itself — deliberately **not** as an ``enum`` here, so that adding a model cannot make a previously-generated client reject a valid id. ``GET /v1/tasks/{task}/models`` carries the same roster with full per-model specs."},"options":{"$ref":"#/components/schemas/SpliceOptions"}},"additionalProperties":false,"type":"object","required":["sequence"],"title":"SplicePredictRequest","description":"Body for ``POST /v1/tasks/splice/predict``.","example":{"options":{"threshold":0.5},"sequence":"ACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGTACGT","sequence_name":"chr1:1000-3000"}},"StageTimings":{"properties":{"cold_start":{"type":"boolean","title":"Cold Start","description":"True if the stage's model had to be loaded for this request."},"model_load_time_ms":{"type":"integer","title":"Model Load Time Ms","description":"Milliseconds spent loading."},"inference_time_ms":{"type":"integer","title":"Inference Time Ms","description":"Milliseconds spent running inference."}},"additionalProperties":false,"type":"object","required":["cold_start","model_load_time_ms","inference_time_ms"],"title":"StageTimings","description":"Per-stage timing sub-block on the composite ``meta``."},"SyncTooLargeDetails":{"properties":{"sequence_length":{"type":"integer","title":"Sequence Length","description":"Length of the submitted sequence (bp)."},"threshold":{"type":"integer","title":"Threshold","description":"Per-endpoint sync cap (bp)."}},"additionalProperties":false,"type":"object","required":["sequence_length","threshold"],"title":"SyncTooLargeDetails","description":"``error.code == 'sync_too_large'`` — retry with ``Prefer: respond-async``."},"TaskModelInfo":{"properties":{"id":{"type":"string","title":"Id","description":"Model id — pass as ``model`` in a request body."},"name":{"type":"string","title":"Name","description":"Display name."},"description":{"type":"string","title":"Description","description":"Short description."},"is_default":{"type":"boolean","title":"Is Default","description":"True for the model used when ``model`` is omitted."},"bio_spec":{"anyOf":[{"$ref":"#/components/schemas/BioSpec"},{"type":"null"}],"description":"Model spec, including the enforced length bounds."}},"additionalProperties":true,"type":"object","required":["id","name","description","is_default"],"title":"TaskModelInfo","description":"One entry in ``GET /v1/tasks/{task}/models``."},"TaskModelsResponse":{"properties":{"task":{"type":"string","title":"Task","description":"Echo of the requested task."},"default_model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Default Model","description":"Model id used when the request omits ``model``."},"models":{"items":{"$ref":"#/components/schemas/TaskModelInfo"},"type":"array","title":"Models","description":"Every model registered for this task."}},"additionalProperties":true,"type":"object","required":["task","models"],"title":"TaskModelsResponse","description":"Success envelope for ``GET /v1/tasks/{task}/models``."},"TaskNotSupportedByModelDetails":{"properties":{"task":{"type":"string","title":"Task","description":"Task the partner posted to."},"supported_tasks":{"items":{"type":"string"},"type":"array","title":"Supported Tasks","description":"Tasks this model is registered for."}},"additionalProperties":false,"type":"object","required":["task","supported_tasks"],"title":"TaskNotSupportedByModelDetails","description":"``error.code == 'task_not_supported_by_model'``."},"ValidationFailedDetails":{"properties":{"errors":{"items":{},"type":"array","title":"Errors","description":"FastAPI validation errors array (loc/msg/type)."}},"additionalProperties":false,"type":"object","required":["errors"],"title":"ValidationFailedDetails","description":"Pydantic-rejected request. The dispatcher wraps the FastAPI\nvalidation array under ``details.errors``; each entry has the\nstandard FastAPI ``{loc, msg, type}`` shape."},"VariantObjectRef":{"properties":{"type":{"type":"string","const":"s3_object","title":"Type"},"uri":{"type":"string","title":"Uri","description":"Fully qualified ``s3://`` object URI. For an output, the name is derived from the input's and the job's — read it from here rather than constructing it."}},"additionalProperties":false,"type":"object","required":["type","uri"],"title":"VariantObjectRef","description":"One S3 object: the case's input VCF, or the annotated copy of it."}},"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"gi_…","description":"Partner API key. Issued out of band; see https://docs.genomicintelligence.ai/rest-api.md#2-get-a-key."}}},"tags":[{"name":"Tasks","description":"Per-task inference endpoints (sync and async), the model catalogue, and job lifecycle."},{"name":"Workflows","description":"Multi-stage pipelines that chain two or more task models into one call."},{"name":"Health","description":"Liveness probe and service banner. Public."}],"security":[{"BearerAuth":[]}],"x-contract-revision":19,"x-rate-limit-burst-divisor":6}