Tasks
Six tasks, each its own published operation — POST /v1/tasks/promoter/predict, /v1/tasks/splice/predict, /v1/tasks/enhancer/predict, /v1/tasks/chromatin/predict, /v1/tasks/annotation/predict, /v1/tasks/expression/predict — plus two workflows that compose them. The URLs are exactly the strings you already POST to; what changed is that each now has its own request schema, its own minLength, and its own closed options object, instead of one shared PredictRequest. (Regenerate typed clients built against the old shared model.) The same six tasks are also tools over MCP.
Each accepts a DNA sequence (and a sequence_name label) and returns task-specific fields under data; meta is uniform across tasks. Request and response schemas — with copyable examples — are in ReDoc; per-task length caps and latency are in Limits.
| Task | Input (bp) | Model window | Strand-sensitive | Output |
|---|---|---|---|---|
| Promoter | 300–500,000 | 2,000 (300 on the *-300bp models) | Yes (coding strand) | Promoter-region probabilities |
| Splice | 100–500,000 | 15,000 | Yes (transcript orientation) | Donor / acceptor sites |
| Enhancer | 50–500,000 | 249 | Yes (dev/hk channels) | dev + hk activity scores |
| Chromatin | 200–500,000 | 1,000 | No | 919 features in 8 track groups |
| Expression | 9,198–500,000 (+ tss_index) | — (trained_window_bp 9,198) | Yes (coding strand) | Expression in log(TPM+1) |
| Annotation | 1,000–500,000 | — | Plus-strand input | Transcripts with type + exon/intron/CDS structure (GFF3) |
| Find genes + expression | 1,000–500,000 | — | Plus-strand input | Genes found, each with a predicted expression |
| Variant interpretation | A VCF, not a sequence | — | Coordinates, not strand | An annotated copy of your VCF, written back to your bucket |
Where a task is marked strand-sensitive, submit DNA 5'→3' on the gene's coding (sense) strand; for annotation, submit the plus-strand region.
GET /v1/tasks/{task}/models returns {task, default_model, models}; each model's is_default marks the default. The model-list endpoint is authoritative for what each task currently serves.
The "input" column is the accepted range, enforced before any model loads. The "model window" is the model's own context_window_bp: a sequence above the floor but below that window is still scored — against a window padded out to it. See the floor is admission control, not regime.
Model selection
Each task has a default_model and may offer alternatives. List them with GET /v1/tasks/{task}/models (a flat {task, default_model, models} object, not the {data, meta} envelope; it needs the same bearer key, and an unknown task is 404 not_found). To pick one, pass its id in the top-level model field of the request body — not options.model: every task's options object is closed, so an unrecognised key there is 422 validation_failed with loc ["body","options","model"].
Each model's bio_spec carries request_max_bp (the enforced ceiling), context_window_bp (its own window) and trained_window_bp (a fixed receptive field where it has one) — see Limits. Beyond the default human models, promoter offers species-specific variants (Drosophila, yeast, Arabidopsis), and DNABERT k-mer variants exist for promoter, enhancer, and chromatin. The model-list endpoint is authoritative for what each task currently serves; the same roster and default are also published statically as x-models on each predict operation in /v1/openapi.json, for tooling that wants it without a live call.
Options
options is typed and closed per task: unknown keys are rejected with 422 validation_failed (type: extra_forbidden) rather than ignored. The complete set:
| Task | options keys | Required |
|---|---|---|
| Promoter | threshold (0–1, default 0.5) | — |
| Splice | threshold (0–1, default 0.5), site_types (subset of ["donor","acceptor"], default both) | — |
| Enhancer | none — the object accepts no fields | — |
| Chromatin | threshold (0–1, default 0.5) | — |
| Annotation | batch_size (1–128, default 8), shift_coordinates (string, e.g. "UCSC"), reverse_complement (bool, default true) | — |
| Expression | description (string) | description, and options itself |
| Find genes + expression | description, annotation_model, expression_model, batch_size (1–128, default 8), shift_coordinates | options itself; description enforced at runtime |
The tasks, one card each
Each task below has its own notes, an example call from the kit client and from an MCP host, then Applications and Usage tips. On the rendered page (docs.genomicintelligence.ai/tasks) each card also carries Input, Options and Output panels, generated at build time from the pinned /v1/openapi.json so they cannot drift from it; Source on a panel opens that operation in ReDoc. The prose does not restate those schemas; outside the panels, read them in ReDoc or in /v1/openapi.json itself.
POST /v1/tasks/promoter/predictPromoter
Binary classification that detects promoter regions. The default g0-promoter-2000bp is a G0 BERT-Large encoder trained on human promoters from EPDnew. Inputs above 2,000 bp are scanned in windows automatically.
sequence: floor set by the smallestcontext_window_bpamong the promoter models (bounds in the table above); belowg0-promoter-2000bp's own 2,000 bp window the input is padded out to it.options.threshold(0–1, default 0.5): probability cutoff for calling a window a promoter. The only keyPromoterOptionsaccepts.- Strand-sensitive — submit the coding (sense) strand.
Output: per-window promoter probabilities. Also BED and bedGraph — ?format=json|bed|bedgraph (see output formats).
API reference
- ReDoc
- OpenAPI JSON
- Python client
- MCP
POST /v1/tasks/promoter/predict
Scan a sequence for promoter regions.
Open this operation in ReDoc ↗, with the request and response schemas, every status code, and copyable examples.
- Operation
paths["/v1/tasks/promoter/predict"].post- operationId
predict_promoter_v1_tasks_promoter_predict_post- Request body
#/components/schemas/PromoterPredictRequest- 200 response
#/components/schemas/PredictResponse?format=- Output format:
json(default) or one ofbed,bedgraph. Text formats are synchronous-only — combining one withPrefer: respond-asyncis a400. An unsupported value is a415 unsupported_format, never a silent fallback to JSON. Prefer- Set to
respond-asyncto dispatch asynchronously: the server returns202with{data: {job_id, status, links}, meta}immediately and the result is polled fromGET /v1/tasks/jobs/{job_id}. Anything else (or omitting the header) delivers the result synchronously with200. Async is JSON-only — combining it with a textformatis a400. Some endpoints require it above a size threshold and reject sync delivery with413 sync_too_large.
From /v1/openapi.json, pinned here at contract revision 16.
import os
from gi_client import Client # the kit's single-file client
client = Client(api_key=os.environ["GI_API_KEY"]) # sent as Authorization: Bearer gi_...
r = client.predict("promoter", sequence=seq, options={"threshold": 0.5})
regions = r["data"]["regions"]
Ask the MCP server: "Fetch a 100 kb window around human TP53 and scan it for promoter regions."
InputPromoterPredictRequestSource ↗
Closed (additionalProperties: false): a key not listed here is rejected, not ignored.
sequencestringrequiredlength 300 – 500,000pattern ^\s*(?:[ACGNTacgnt]\s*)+$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 publishedminLengthas 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 smallestcontext_window_bpamong them, i.e. the shortest input that fills some promoter model's window exactly, with no padding. Requests outside the range are rejected with422 validation_failedbefore any model is loaded. Note thatminLengthis admission control, not a statement about regime: a sequence at least this long but shorter than the selected model'scontext_window_bp(published byGET /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.modelstring | nulllength ≤ 128Model ID. If omitted, the task's default model is used. The valid ids and the default for this operation are published structurally asx-modelson the operation itself — deliberately not as anenumhere, so that adding a model cannot make a previously-generated client reject a valid id.GET /v1/tasks/{task}/modelscarries the same roster with full per-model specs.sequence_namestring | nulllength ≤ 128default "sequence"Display name for the sequence (e.g., 'chr1:1000-5000').
OutputPredictResponseSource ↗
dataPromoterDatarequiredShow
PromoterDatafields (7)modelstringrequiredModel id that produced this result.inputPromoterInputrequiredThe caller's label for the submitted sequence, echoed verbatim; nothing derived. The submitted length ismeta.sequence_length.Show
PromoterInputfields (1)sequence_namestringrequiredThe caller's label for the submitted sequence, echoed verbatim. Defaults to"sequence"when the request omitted it.
summaryobjectrequiredTask-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 (metaand this payload's own declared keys) instead.taskstringrequired= "promoter"regionsobject[]requiredDetected promoter regions (start/end/score).window_detailsobject[]requiredPer-window scoring detail (one entry per scanned window).formatsobject | nullOptional 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 asmodelabove — 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'sg0-annotation): that document is passed through verbatim and keeps its producer's source value, which names a multi-stage pipeline rather than one model.
metaMetarequiredMetadata envelope shared by every successful predict response.Show
Metafields (9)job_idstringrequiredServer-generated UUIDv4. Mirrored on the X-Job-Id response header.request_idstringrequiredCorrelation id for this request, mirrored on the X-Request-Id response header and identical toerror.request_idon the failure envelope. Quote it in support requests: it is the one handle that identifies a call whether it succeeded or failed.taskstringrequiredTask name (matches the {task} URL segment). Use this — ordata.task— to narrow the typed unions.modelstringrequiredModel id that ran this inference.cold_startbooleanrequiredTrue if the model had to be loaded into GPU memory for this request. Useful for diagnosing first-request latency.model_load_time_msintegerrequiredMilliseconds spent loading the model (0 when cold_start is False).inference_time_msintegerrequiredMilliseconds spent running inference.sequence_lengthintegerrequiredLength of the submitted sequence (bp).task_specific_countsPromoterCountsrequiredDiscriminated counts payload (see per-task*Countsmodels).Show
PromoterCountsfields (3)taskstringrequired= "promoter"windows_processedintegerrequiredNumber of sliding windows scored.regions_foundintegerrequiredDetected promoter regions in this call.
Applications
Use it to locate transcription start regions in unannotated sequence, or to score designed constructs for promoter strength inside an optimisation loop. The per-window detail in data.window_details makes it usable as a fitness signal rather than only a binary call.
Usage tips
- The floor is 300 bp — the
minLengthon this operation's request schema. It is a property of the endpoint, so choosing a differentmodeldoes not lower it. - Input shorter than the model's window is padded, not rejected. A 300 bp submission is scored against
g0-promoter-2000bp's 2,000 bp window; compare your length withbio_spec.context_window_bpfromGET /v1/tasks/promoter/modelsbefore reading much into a marginal call. - Submit the coding (sense) strand. The task is strand-sensitive.
POST /v1/tasks/splice/predictSplice
Token-level classification labeling each position as a splice acceptor (3' site), donor (5' site), or neither. The default g0-splice-bigbird is a G0 BigBird encoder trained on human splice sites from SpliceAI. Long inputs are scanned in a 15,000 bp sliding window; predictions are most reliable in the central region of each window.
-
sequence: the floor (bounds in the table above) is well below the model's 15,000 bp window, so short submissions are scored against heavy padding — treat 15,000 bp as the in-regime size. -
options.threshold(0–1, default 0.5): score cutoff for emitting a site. A response carrying more than 20,000 sites is refused with422 validation_failed— only a very low threshold on a long sequence gets there. If you want everything, use1e-3, not0: it is numerically equivalent (no score moved by more than 4.6e-4 in our benchmark), ~4x faster, and stays under the cap. See Limits. -
options.site_types: subset of["donor", "acceptor"](default both). Withthreshold, the only two keysSpliceOptionsaccepts. -
Strand-specific — submit the transcript's orientation. The wrong strand does not fail loudly, and it does not return near-zero scores either: it returns sites at different positions, often still at high confidence. On our BRCA1 fixture the reverse complement scored 0.9101 and 0.9946 where gene-sense scored 0.9998 and 0.9999; on SMN1 it returned 1 site instead of 17. Neither the site count nor the scores give you a usable check, and there is no
strandflag in the contract, so track orientation on your side. -
start/endbound the scored token, not the junction. The model reads your sequence as BPE tokens and scores whole tokens, so a site's span is that token's character range — typically 4–8 bp, and varying from site to site because token lengths do. A donor or acceptor junction is a single base.token_indexnames the token the span came from. Do not treat the span as the feature's extent, and be careful intersecting it with a base-resolution reference annotation: at that scale it will be quietly wrong. We publish no derived base position — deriving one from a token score would be a modelling claim we cannot currently defend, and invented precision in a file you keep is worse than an honest span. Stated in the contract since revision 5.
Output: detected acceptor and donor sites with scores. Also BED and GFF3 — ?format=json|bed|gff3 (see output formats). The GFF3 source column carries the model id (g0-splice-bigbird); it read gpu_service before contract revision 4. Columns 4–5 of that GFF3 are the token spans described above, so a saved track has token resolution, not base resolution.
API reference
- ReDoc
- OpenAPI JSON
- Python client
- MCP
POST /v1/tasks/splice/predict
Annotate donor and acceptor splice sites.
Open this operation in ReDoc ↗, with the request and response schemas, every status code, and copyable examples.
- Operation
paths["/v1/tasks/splice/predict"].post- operationId
predict_splice_v1_tasks_splice_predict_post- Request body
#/components/schemas/SplicePredictRequest- 200 response
#/components/schemas/PredictResponse?format=- Output format:
json(default) or one ofbed,gff3. Text formats are synchronous-only — combining one withPrefer: respond-asyncis a400. An unsupported value is a415 unsupported_format, never a silent fallback to JSON. Prefer- Set to
respond-asyncto dispatch asynchronously: the server returns202with{data: {job_id, status, links}, meta}immediately and the result is polled fromGET /v1/tasks/jobs/{job_id}. Anything else (or omitting the header) delivers the result synchronously with200. Async is JSON-only — combining it with a textformatis a400. Some endpoints require it above a size threshold and reject sync delivery with413 sync_too_large.
From /v1/openapi.json, pinned here at contract revision 16.
# client = Client(api_key=os.environ["GI_API_KEY"]), as in Promoter
r = client.predict("splice", sequence=seq, options={"threshold": 1e-3, "site_types": ["donor", "acceptor"]})
sites = r["data"]["sites"] # start/end bound a token, not the junction base
Ask the MCP server: "Fetch the human HBB gene sequence and predict its splice sites."
InputSplicePredictRequestSource ↗
Closed (additionalProperties: false): a key not listed here is rejected, not ignored.
sequencestringrequiredlength 100 – 500,000pattern ^\s*(?:[ACGNTacgnt]\s*)+$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 publishedminLengthas 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 with422 validation_failedbefore any model is loaded. Note thatminLengthis admission control, not a statement about regime: a sequence at least this long but shorter than the selected model'scontext_window_bp(published byGET /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.modelstring | nulllength ≤ 128Model ID. If omitted, the task's default model is used. The valid ids and the default for this operation are published structurally asx-modelson the operation itself — deliberately not as anenumhere, so that adding a model cannot make a previously-generated client reject a valid id.GET /v1/tasks/{task}/modelscarries the same roster with full per-model specs.sequence_namestring | nulllength ≤ 128default "sequence"Display name for the sequence (e.g., 'chr1:1000-5000').
OutputPredictResponseSource ↗
dataSpliceDatarequiredShow
SpliceDatafields (8)modelstringrequiredModel id that produced this result.inputSpliceInputrequiredThe caller's label for the submitted sequence, echoed verbatim; nothing derived. The submitted length ismeta.sequence_length.Show
SpliceInputfields (1)sequence_namestringrequiredThe caller's label for the submitted sequence, echoed verbatim. Defaults to"sequence"when the request omitted it.
summaryobjectrequiredTask-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 (metaand this payload's own declared keys) instead.taskstringrequired= "splice"sitesobject[]requiredDetected splice sites (donor / acceptor).start/endbound 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_indexnames 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=gff3writes 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).tracksobjectrequiredPer-position score tracks for visualization.window_detailsobject[]requiredPer-window scoring detail.formatsobject | nullOptional 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 asmodelabove — 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'sg0-annotation): that document is passed through verbatim and keeps its producer's source value, which names a multi-stage pipeline rather than one model.
metaMetarequiredMetadata envelope shared by every successful predict response.Show
Metafields (9)job_idstringrequiredServer-generated UUIDv4. Mirrored on the X-Job-Id response header.request_idstringrequiredCorrelation id for this request, mirrored on the X-Request-Id response header and identical toerror.request_idon the failure envelope. Quote it in support requests: it is the one handle that identifies a call whether it succeeded or failed.taskstringrequiredTask name (matches the {task} URL segment). Use this — ordata.task— to narrow the typed unions.modelstringrequiredModel id that ran this inference.cold_startbooleanrequiredTrue if the model had to be loaded into GPU memory for this request. Useful for diagnosing first-request latency.model_load_time_msintegerrequiredMilliseconds spent loading the model (0 when cold_start is False).inference_time_msintegerrequiredMilliseconds spent running inference.sequence_lengthintegerrequiredLength of the submitted sequence (bp).task_specific_countsSpliceCountsrequiredDiscriminated counts payload (see per-task*Countsmodels).Show
SpliceCountsfields (3)taskstringrequired= "splice"windows_processedintegerrequiredsites_foundintegerrequiredDetected splice sites (donor + acceptor).
Applications
Use it to locate exon boundaries in unannotated transcripts, to check whether a designed edit creates or destroys a splice site, or to screen variants for splice disruption by scoring the reference and the edited sequence side by side.
Usage tips
- Submit the transcript's orientation. The wrong strand does not fail loudly: it returns sites at different positions, often at high confidence, and no score or count identifies a mis-oriented submission afterwards. Reverse-complement minus-strand genes before you call.
- A site's
start/endis a token span, not the junction base — typically 4–8 bp. Locate a boundary to within the span; do not reduce it to one base or intersect it with base-resolution annotation as though it were one. - The floor is 100 bp, the window 15,000 bp. Treat 15,000 bp as the in-regime size.
- Do not send
threshold: 0. A response over 20,000 sites is refused with422 validation_failed;1e-3returns effectively everything and stays under the cap.
POST /v1/tasks/enhancer/predictEnhancer
Regression predicting two scores per window: developmental (dev) and housekeeping (hk). The default g0-deepstarr is a G0 BERT-Base encoder trained on Drosophila enhancers from DeepSTARR. The sequence is split into consecutive, non-overlapping 249 bp windows, each scored independently.
sequence: the floor (bounds in the table above) is admission control — the shortest inputg0-deepstarrwill admit — not a useful size: the model scores 249 bp windows, so anything shorter is accepted and scored against a padded window. Submit ≥ 249 bp to stay in regime.options:EnhancerOptionsaccepts no fields. Send{}or omit it; any key is a422. There is no threshold on this task — it is regression, not classification.
The model is Drosophila-trained and strand-sensitive for the dev/hk channels — use a fly sequence on the gene's coding (sense) strand.
Output: per-window dev and hk scores, embedding bedGraph renderings of each track. bedGraph is also available directly — ?format=json|bedgraph (see output formats).
API reference
- ReDoc
- OpenAPI JSON
- Python client
- MCP
POST /v1/tasks/enhancer/predict
Score enhancer activity (developmental and housekeeping).
Open this operation in ReDoc ↗, with the request and response schemas, every status code, and copyable examples.
- Operation
paths["/v1/tasks/enhancer/predict"].post- operationId
predict_enhancer_v1_tasks_enhancer_predict_post- Request body
#/components/schemas/EnhancerPredictRequest- 200 response
#/components/schemas/PredictResponse?format=- Output format:
json(default) or one ofbedgraph. Text formats are synchronous-only — combining one withPrefer: respond-asyncis a400. An unsupported value is a415 unsupported_format, never a silent fallback to JSON. Prefer- Set to
respond-asyncto dispatch asynchronously: the server returns202with{data: {job_id, status, links}, meta}immediately and the result is polled fromGET /v1/tasks/jobs/{job_id}. Anything else (or omitting the header) delivers the result synchronously with200. Async is JSON-only — combining it with a textformatis a400. Some endpoints require it above a size threshold and reject sync delivery with413 sync_too_large.
From /v1/openapi.json, pinned here at contract revision 16.
# client = Client(api_key=os.environ["GI_API_KEY"]), as in Promoter
r = client.predict("enhancer", sequence=fly_seq) # no options: EnhancerOptions accepts none
windows = r["data"]["windows"]
Ask the MCP server: "Fetch the Drosophila ftz gene and predict enhancer activity."
InputEnhancerPredictRequestSource ↗
Closed (additionalProperties: false): a key not listed here is rejected, not ignored.
sequencestringrequiredlength 50 – 500,000pattern ^\s*(?:[ACGNTacgnt]\s*)+$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 publishedminLengthas 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 with422 validation_failedbefore any model is loaded. Note thatminLengthis admission control, not a statement about regime: a sequence at least this long but shorter than the selected model'scontext_window_bp(published byGET /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.modelstring | nulllength ≤ 128Model ID. If omitted, the task's default model is used. The valid ids and the default for this operation are published structurally asx-modelson the operation itself — deliberately not as anenumhere, so that adding a model cannot make a previously-generated client reject a valid id.GET /v1/tasks/{task}/modelscarries the same roster with full per-model specs.sequence_namestring | nulllength ≤ 128default "sequence"Display name for the sequence (e.g., 'chr1:1000-5000').
OutputPredictResponseSource ↗
dataEnhancerDatarequiredShow
EnhancerDatafields (7)modelstringrequiredModel id that produced this result.inputEnhancerInputrequiredThe caller's label for the submitted sequence, echoed verbatim; nothing derived. The submitted length ismeta.sequence_length.Show
EnhancerInputfields (1)sequence_namestringrequiredThe caller's label for the submitted sequence, echoed verbatim. Defaults to"sequence"when the request omitted it.
summaryobjectrequiredTask-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 (metaand this payload's own declared keys) instead.taskstringrequired= "enhancer"windowsobject[]requiredPer-window enhancer scores.tracksobjectrequiredPer-position score tracks for visualization.formatsobject | nullOptional 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 asmodelabove — 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'sg0-annotation): that document is passed through verbatim and keeps its producer's source value, which names a multi-stage pipeline rather than one model.
metaMetarequiredMetadata envelope shared by every successful predict response.Show
Metafields (9)job_idstringrequiredServer-generated UUIDv4. Mirrored on the X-Job-Id response header.request_idstringrequiredCorrelation id for this request, mirrored on the X-Request-Id response header and identical toerror.request_idon the failure envelope. Quote it in support requests: it is the one handle that identifies a call whether it succeeded or failed.taskstringrequiredTask name (matches the {task} URL segment). Use this — ordata.task— to narrow the typed unions.modelstringrequiredModel id that ran this inference.cold_startbooleanrequiredTrue if the model had to be loaded into GPU memory for this request. Useful for diagnosing first-request latency.model_load_time_msintegerrequiredMilliseconds spent loading the model (0 when cold_start is False).inference_time_msintegerrequiredMilliseconds spent running inference.sequence_lengthintegerrequiredLength of the submitted sequence (bp).task_specific_countsEnhancerCountsrequiredDiscriminated counts payload (see per-task*Countsmodels).Show
EnhancerCountsfields (2)taskstringrequired= "enhancer"windows_processedintegerrequired
Applications
Use it to rank candidate enhancers, or as a dual-objective fitness function when designing regulatory elements that favour one programme (developmental or housekeeping) over the other.
Usage tips
- The floor is 50 bp, the lowest of the six, but the model scores 249 bp windows. Submit at least 249 bp to stay in regime.
- The developmental/housekeeping split is a Drosophila STARR-seq definition (DeepSTARR). Read the two scores as relative activity within a comparison, not as calibrated cross-species values.
- Send no options.
EnhancerOptionsaccepts no fields: send{}or omit it; any key is a422.
POST /v1/tasks/chromatin/predictChromatin
Multi-label classification predicting 919 mammalian chromatin features (DeepSEA-style), grouped into eight categories (DNase, CTCF, Pol2, c-Myc, H3K27ac, H3K27me3, H3K4me1, Other). The default g0-deepsea is a G0 BERT-Base encoder trained on ENCODE data. The sequence is tiled into 1,000 bp windows stepping every 200 bp.
sequence: the model's window is 1,000 bp (floor in the table above), so submit at least that to avoid padding.options.threshold(0–1, default 0.5): only features scoring above this are returned. The only keyChromatinOptionsaccepts.
Output: per-feature probabilities (above the threshold), grouped by category. Also BED — ?format=json|bed (see output formats).
API reference
- ReDoc
- OpenAPI JSON
- Python client
- MCP
POST /v1/tasks/chromatin/predict
Annotate chromatin features (DeepSEA-style, 919 labels).
Open this operation in ReDoc ↗, with the request and response schemas, every status code, and copyable examples.
- Operation
paths["/v1/tasks/chromatin/predict"].post- operationId
predict_chromatin_v1_tasks_chromatin_predict_post- Request body
#/components/schemas/ChromatinPredictRequest- 200 response
#/components/schemas/PredictResponse?format=- Output format:
json(default) or one ofbed. Text formats are synchronous-only — combining one withPrefer: respond-asyncis a400. An unsupported value is a415 unsupported_format, never a silent fallback to JSON. Prefer- Set to
respond-asyncto dispatch asynchronously: the server returns202with{data: {job_id, status, links}, meta}immediately and the result is polled fromGET /v1/tasks/jobs/{job_id}. Anything else (or omitting the header) delivers the result synchronously with200. Async is JSON-only — combining it with a textformatis a400. Some endpoints require it above a size threshold and reject sync delivery with413 sync_too_large.
From /v1/openapi.json, pinned here at contract revision 16.
# client = Client(api_key=os.environ["GI_API_KEY"]), as in Promoter
r = client.predict("chromatin", sequence=seq, options={"threshold": 0.5})
windows = r["data"]["windows"]
print(r["meta"]["task_specific_counts"]["total_annotations"])
Ask the MCP server: "Fetch the human HBB promoter region and predict its chromatin features."
InputChromatinPredictRequestSource ↗
Closed (additionalProperties: false): a key not listed here is rejected, not ignored.
sequencestringrequiredlength 200 – 500,000pattern ^\s*(?:[ACGNTacgnt]\s*)+$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 publishedminLengthas 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 with422 validation_failedbefore any model is loaded. Note thatminLengthis admission control, not a statement about regime: a sequence at least this long but shorter than the selected model'scontext_window_bp(published byGET /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.modelstring | nulllength ≤ 128Model ID. If omitted, the task's default model is used. The valid ids and the default for this operation are published structurally asx-modelson the operation itself — deliberately not as anenumhere, so that adding a model cannot make a previously-generated client reject a valid id.GET /v1/tasks/{task}/modelscarries the same roster with full per-model specs.sequence_namestring | nulllength ≤ 128default "sequence"Display name for the sequence (e.g., 'chr1:1000-5000').
OutputPredictResponseSource ↗
dataChromatinDatarequiredShow
ChromatinDatafields (7)modelstringrequiredModel id that produced this result.inputChromatinInputrequiredThe caller's label for the submitted sequence, echoed verbatim; nothing derived. The submitted length ismeta.sequence_length.Show
ChromatinInputfields (1)sequence_namestringrequiredThe caller's label for the submitted sequence, echoed verbatim. Defaults to"sequence"when the request omitted it.
summaryobjectrequiredTask-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 (metaand this payload's own declared keys) instead.taskstringrequired= "chromatin"windowsobject[]requiredPer-window chromatin annotations.tracksobjectrequiredPer-position score tracks for visualization.formatsobject | nullOptional 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 asmodelabove — 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'sg0-annotation): that document is passed through verbatim and keeps its producer's source value, which names a multi-stage pipeline rather than one model.
metaMetarequiredMetadata envelope shared by every successful predict response.Show
Metafields (9)job_idstringrequiredServer-generated UUIDv4. Mirrored on the X-Job-Id response header.request_idstringrequiredCorrelation id for this request, mirrored on the X-Request-Id response header and identical toerror.request_idon the failure envelope. Quote it in support requests: it is the one handle that identifies a call whether it succeeded or failed.taskstringrequiredTask name (matches the {task} URL segment). Use this — ordata.task— to narrow the typed unions.modelstringrequiredModel id that ran this inference.cold_startbooleanrequiredTrue if the model had to be loaded into GPU memory for this request. Useful for diagnosing first-request latency.model_load_time_msintegerrequiredMilliseconds spent loading the model (0 when cold_start is False).inference_time_msintegerrequiredMilliseconds spent running inference.sequence_lengthintegerrequiredLength of the submitted sequence (bp).task_specific_countsChromatinCountsrequiredDiscriminated counts payload (see per-task*Countsmodels).Show
ChromatinCountsfields (3)taskstringrequired= "chromatin"windows_processedintegerrequiredtotal_annotationsintegerrequiredSum of per-track annotation counts across all windows.
Applications
Use it to ask whether a sequence looks accessible, bound, or marked, and to compare designed variants against a natural reference across many assays at once.
Usage tips
- The floor is 200 bp; the window is 1,000 bp. Submit at least 1,000 bp to avoid padding.
- Lowering
thresholdgrows the response. Only features scoring above it are returned, and each window is scored on all 919. - A count is not a cell type.
meta.task_specific_counts.total_annotationssums calls across every window and every feature; a high count is not evidence about any one cellular context. Read the individual features for that.
POST /v1/tasks/expression/predictExpression
Predicts gene expression from a DNA sequence plus an experimental-context description, on a log(TPM+1) scale. The default g0-expression is trained on ENCODE RNA-seq across cell types.
Expression has its own operation and request schema — POST /v1/tasks/expression/predict, ExpressionPredictRequest — as every task now does. It remains the only one that takes a tss_index and the only one whose options has a required field.
The body accepts exactly five fields — sequence (required), options (required), tss_index, sequence_name, model — and is closed: any other top-level key returns 422 validation_failed.
-
sequence(required): 9,198–500,000 bp, gene-sense strand. The model scores exactly one 9,198 bp window (4,599 bp each side of the TSS) — shorter input is a hard422, never padded or truncated. Lengths are counted after whitespace is stripped, so a line-wrapped FASTA body pastes verbatim (the>header line does not). -
tss_index(integer, 0-based): offset of the TSS into the whitespace-strippedsequence. Required unlesssequenceis exactly 9,198 bp, where it defaults to4599. Must satisfy4599 <= tss_index <= len(sequence) - 4599. The server scoressequence[tss_index - 4599 : tss_index + 4599]. It does not discover the TSS for you and does not reverse-complement. See Limits for the full rules and the silent-wrong-window gotcha. -
options.description(required): free-text experimental context (cell type, assay, conditions).optionsis a closed object —descriptionis its only accepted key, and it must be non-empty. Omitting it returns422 validation_failed.This string is model input, not a label. It conditions the prediction, and the exact wording changes the number: on one fixture, same sequence and same model,
"K562"scored 1.38 and"K562 cells"scored 0.70 log(TPM+1) — roughly a 2x spread in TPM from phrasing alone. There is no enum and no canonical vocabulary. Pick one form and keep it fixed: when you compare predictions across sequences, runs, or releases, a changeddescriptioninvalidates the comparison as surely as a changed sequence.
Output: data.prediction = {expression, expression_log_tpm, expression_tpm, unit} — expression/expression_log_tpm are log(TPM+1); expression_tpm is the back-transformed linear value. JSON only (no text-track formats; ?format= anything but json is 415 unsupported_format).
Windowing provenance is echoed back in two places: meta.task_specific_counts (and data.input) carry tss_index and scored_window — the half-open [start, end] of your submitted sequence that was actually scored, always exactly 9,198 bp wide. The length you submitted (whitespace-stripped) is meta.sequence_length, also echoed as data.input.submitted_sequence_length; the scored width is always 9,198 bp, which is scored_window[1] - scored_window[0]. (data.input.sequence_length was removed at contract revision 13.)
API reference
- ReDoc
- OpenAPI JSON
- Python client
- MCP
POST /v1/tasks/expression/predict
Predict gene expression from a TSS-centred window.
Open this operation in ReDoc ↗, with the request and response schemas, every status code, and copyable examples.
- Operation
paths["/v1/tasks/expression/predict"].post- operationId
predict_expression_v1_tasks_expression_predict_post- Request body
#/components/schemas/ExpressionPredictRequest- 200 response
#/components/schemas/PredictResponse?format=- Output format.
expressionrenders JSON only; any other value is a415 unsupported_format(never a silent fallback). Prefer- Set to
respond-asyncto dispatch asynchronously: the server returns202with{data: {job_id, status, links}, meta}immediately and the result is polled fromGET /v1/tasks/jobs/{job_id}. Anything else (or omitting the header) delivers the result synchronously with200. Async is JSON-only — combining it with a textformatis a400. Some endpoints require it above a size threshold and reject sync delivery with413 sync_too_large.
From /v1/openapi.json, pinned here at contract revision 16.
# client = Client(api_key=os.environ["GI_API_KEY"]), as in Promoter
r = client.predict(
"expression",
sequence=locus, # >= 9,198 bp, gene-sense strand
tss_index=tss, # 0-based, into the whitespace-stripped sequence
options={"description": "K562 cells"},
)
print(r["data"]["prediction"]["expression"]) # log(TPM+1)
print(r["meta"]["task_specific_counts"]["scored_window"]) # assert on this
Ask the MCP server: "Predict HBB expression in K562 cells."
InputExpressionPredictRequestSource ↗
Closed (additionalProperties: false): a key not listed here is rejected, not ignored.
sequencestringrequiredlength 9,198 – 500,000pattern ^\s*(?:[ACGNTacgnt]\s*)+$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 andtss_indexare measured against the whitespace-stripped string. Must be at least 9198 bp — one full TSS-centred training window — and is windowed server-side down to exactly that many bp aroundtss_indexbefore inference.modelstring | nulllength ≤ 128Model ID. If omitted, the task's default model is used. The valid ids and the default for this operation are published structurally asx-modelson the operation itself — deliberately not as anenumhere, so that adding a model cannot make a previously-generated client reject a valid id.GET /v1/tasks/{task}/modelscarries the same roster with full per-model specs.sequence_namestring | nulllength ≤ 128default "sequence"Display name for the sequence (e.g., 'chr1:1000-5000').tss_indexinteger | null≥ 00-based offset of the transcription start site into the whitespace-strippedsequence(i.e. count nucleotides, not file characters — a line-wrapped FASTA would otherwise be off by its newline count). The server scoressequence[tss_index-4599 : tss_index+4599]and echoes the applied window back inmeta.task_specific_counts. Required unlesssequenceis exactly 9198 bp, in which case it defaults to 4599 (the only legal value). Must satisfy 4599 <= tss_index <= len(sequence) - 4599; out-of-range is a 422 rather than an N-padded guess.
OutputPredictResponseSource ↗
dataExpressionDatarequiredShow
ExpressionDatafields (6)modelstringrequiredModel id that produced this result.inputExpressionInputrequiredEcho of the request: the caller'ssequence_name, thedescriptionthe prediction was conditioned on, and thetss_indexthe server applied. The window that offset produced ismeta.task_specific_counts.scored_window; the submitted length ismeta.sequence_length.Show
ExpressionInputfields (3)sequence_namestringrequiredThe caller's label for the submitted sequence, echoed verbatim. Defaults to"sequence"when the request omitted it.descriptionstringrequiredThe experimental context the prediction was conditioned on (cell type / assay), echoed fromoptions.description.tss_indexintegerrequiredThe 0-based TSS offset the server applied, into the whitespace-strippedsequencethat was submitted. Echoes the request'stss_index, or the 4599 implied by a submission of exactly 9198 bp. The window it produced ismeta.task_specific_counts.scored_window.
summaryobjectrequiredTask-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 (metaand this payload's own declared keys) instead.taskstringrequired= "expression"predictionobjectrequiredExpression prediction record:{expression, expression_log_tpm, expression_tpm, unit}.formatsobject | nullOptional 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 asmodelabove — 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'sg0-annotation): that document is passed through verbatim and keeps its producer's source value, which names a multi-stage pipeline rather than one model.
metaMetarequiredMetadata envelope shared by every successful predict response.Show
Metafields (9)job_idstringrequiredServer-generated UUIDv4. Mirrored on the X-Job-Id response header.request_idstringrequiredCorrelation id for this request, mirrored on the X-Request-Id response header and identical toerror.request_idon the failure envelope. Quote it in support requests: it is the one handle that identifies a call whether it succeeded or failed.taskstringrequiredTask name (matches the {task} URL segment). Use this — ordata.task— to narrow the typed unions.modelstringrequiredModel id that ran this inference.cold_startbooleanrequiredTrue if the model had to be loaded into GPU memory for this request. Useful for diagnosing first-request latency.model_load_time_msintegerrequiredMilliseconds spent loading the model (0 when cold_start is False).inference_time_msintegerrequiredMilliseconds spent running inference.sequence_lengthintegerrequiredLength of the submitted sequence (bp).task_specific_countsExpressionCountsrequiredDiscriminated counts payload (see per-task*Countsmodels).Show
ExpressionCountsfields (3)taskstringrequired= "expression"scored_windowinteger[] | null[start, end]— the half-open slice of the submitted, whitespace-stripped sequence that was fed to the model. Always exactly 9198 bp wide:[tss_index-4599, tss_index+4599].tss_indexinteger | null0-based TSS offset the server applied, into the whitespace-strippedsequencethat was submitted. Echoes the request'stss_index, or the implied 4599 when the submission was exactly 9198 bp.
Applications
Use it to estimate the transcriptional output of a locus or a designed promoter under a stated cellular context, and as the objective in an expression-maximising or expression-matching design loop.
Usage tips
- The window is exact. Submit exactly 9,198 bp centred on the TSS, or a longer locus plus
tss_indexand let the service cut it. Under-length input is rejected, never padded. descriptionis conditioning text, not a label. It is fed to the model, so rewording it changes the prediction. Hold it fixed across runs you intend to compare.- An in-range but wrong
tss_indexstill scores — a different window, with a confident200. Read the applied window back frommeta.task_specific_counts.scored_windowrather than assuming the request's. - The sequence is never reverse-complemented. Submit minus-strand genes in transcript orientation.
POST /v1/tasks/annotation/predictAnnotation
Gene finding over long DNA: detects transcripts and returns their intervals. The g0-annotation model (multispecies) predicts transcript boundaries, transcript type (mRNA / lnc_RNA), and full internal exon/intron/CDS structure, and emits a browser-ready GFF3 track. Submit the plus-strand genomic region; the model finds transcripts on both strands. This is the longest-running task, and the only predict operation with a hard sync cap: above 200,000 bp a synchronous JSON request is refused with 413 sync_too_large, details = {sequence_length, threshold} — resend the identical body with Prefer: respond-async. Below that, sync works at any accepted length, but prefer async above ~30,000 bp (see Asynchronous jobs). The cap is on JSON delivery only: ?format=bed and ?format=gff3 are served synchronously at any accepted length, so size those calls against the 300 s proxy timeout yourself.
sequence: the highest floor of the five non-expression tasks (bounds in the table above); the gene finder cannot work below its own window.model(optional, top-level):g0-annotation— the only annotation model, selected by default.options.batch_size(integer 1–128, default 8): windows processed per batch.options.shift_coordinates: "UCSC": rebase output coordinates from a UCSC-stylesequence_name(e.g.chr8:127,680,000-127,800,000). Note that the header goes insequence_name(≤ 128 chars), not in thesequence— a>line inside the sequence fails the alphabet check.options.reverse_complement(bool, defaulttrue): average each locus with its reverse complement, improving minus-strand recall. Setfalsefor a faster single-pass run.
AnnotationOptions accepts those three keys and nothing else.
Output: transcript intervals, each carrying its own strand (+/-) plus tss_position and polya_position. Each transcript additionally carries transcript_type, transcript_type_score, and 0-based half-open exons/introns/cds arrays, and data.formats.gff3 holds a full GFF3 track (also via Accept: text/x-gff3). BED is also available — ?format=json|bed|gff3. See output formats.
API reference
- ReDoc
- OpenAPI JSON
- Python client
- MCP
POST /v1/tasks/annotation/predict
Find genes and their exon/intron/CDS structure.
Open this operation in ReDoc ↗, with the request and response schemas, every status code, and copyable examples.
- Operation
paths["/v1/tasks/annotation/predict"].post- operationId
predict_annotation_v1_tasks_annotation_predict_post- Request body
#/components/schemas/AnnotationPredictRequest- 200 response
#/components/schemas/PredictResponsex-sync-limit-bp- 200,000
?format=- Output format:
json(default) or one ofbed,gff3. Text formats are synchronous-only — combining one withPrefer: respond-asyncis a400. An unsupported value is a415 unsupported_format, never a silent fallback to JSON. Prefer- Set to
respond-asyncto dispatch asynchronously: the server returns202with{data: {job_id, status, links}, meta}immediately and the result is polled fromGET /v1/tasks/jobs/{job_id}. Anything else (or omitting the header) delivers the result synchronously with200. Async is JSON-only — combining it with a textformatis a400. Some endpoints require it above a size threshold and reject sync delivery with413 sync_too_large.
From /v1/openapi.json, pinned here at contract revision 16.
# client = Client(api_key=os.environ["GI_API_KEY"]), as in Promoter
# Prefer: respond-async, then poll GET /v1/tasks/jobs/{job_id}
job_id = client.submit_async("annotation", sequence=region, options={"shift_coordinates": "UCSC"},
sequence_name="chr8:127,680,000-127,800,000")
result = client.wait_for_job(job_id)
transcripts = result["data"]["transcripts"]
Ask the MCP server: "Find the genes in chr8:127,680,000-127,800,000."
InputAnnotationPredictRequestSource ↗
Closed (additionalProperties: false): a key not listed here is rejected, not ignored.
sequencestringrequiredlength 1,000 – 500,000pattern ^\s*(?:[ACGNTacgnt]\s*)+$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 publishedminLengthas 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 with422 validation_failedbefore any model is loaded.modelstring | nulllength ≤ 128Model ID. If omitted, the task's default model is used. The valid ids and the default for this operation are published structurally asx-modelson the operation itself — deliberately not as anenumhere, so that adding a model cannot make a previously-generated client reject a valid id.GET /v1/tasks/{task}/modelscarries the same roster with full per-model specs.sequence_namestring | nulllength ≤ 128default "sequence"Display name for the sequence (e.g., 'chr1:1000-5000').
OutputPredictResponseSource ↗
dataAnnotationDatarequiredShow
AnnotationDatafields (6)modelstringrequiredModel id that produced this result.inputAnnotationInputrequiredThe caller's label for the submitted sequence, echoed verbatim; nothing derived. The submitted length ismeta.sequence_length.Show
AnnotationInputfields (1)sequence_namestringrequiredThe caller's label for the submitted sequence, echoed verbatim. Defaults to"sequence"when the request omitted it.
summaryobjectrequiredTask-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 (metaand this payload's own declared keys) instead.taskstringrequired= "annotation"transcriptsobject[]requiredDetected transcripts. Every transcript carries gene boundaries (start/end/strand/score) plustss_positionandpolya_position. Structure-aware models (g0-annotation) additionally populatetranscript_type(mRNA/lnc_RNA),transcript_type_scoreand 0-based half-openexons/introns/cdsarrays. Theformatsobject exposesbedand, for structure-aware models, a fullgff3track (also available viaAccept: text/x-gff3).formatsobject | nullOptional 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 asmodelabove — 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'sg0-annotation): that document is passed through verbatim and keeps its producer's source value, which names a multi-stage pipeline rather than one model.
metaMetarequiredMetadata envelope shared by every successful predict response.Show
Metafields (9)job_idstringrequiredServer-generated UUIDv4. Mirrored on the X-Job-Id response header.request_idstringrequiredCorrelation id for this request, mirrored on the X-Request-Id response header and identical toerror.request_idon the failure envelope. Quote it in support requests: it is the one handle that identifies a call whether it succeeded or failed.taskstringrequiredTask name (matches the {task} URL segment). Use this — ordata.task— to narrow the typed unions.modelstringrequiredModel id that ran this inference.cold_startbooleanrequiredTrue if the model had to be loaded into GPU memory for this request. Useful for diagnosing first-request latency.model_load_time_msintegerrequiredMilliseconds spent loading the model (0 when cold_start is False).inference_time_msintegerrequiredMilliseconds spent running inference.sequence_lengthintegerrequiredLength of the submitted sequence (bp).task_specific_countsAnnotationCountsrequiredDiscriminated counts payload (see per-task*Countsmodels).Show
AnnotationCountsfields (2)taskstringrequired= "annotation"transcripts_foundintegerrequired
Applications
Use it to annotate assembled contigs or synthetic constructs where no reference annotation exists, and to supply TSS positions (tss_position) to expression when they are not known in advance.
Usage tips
- The floor is 1,000 bp, the highest of the five non-expression tasks.
- One submission finds both strands. Submit the plus-strand region; each transcript carries its own
strand, relative to the sequence as submitted. - This is the slowest task, and the only predict operation with a sync cap. Above 200,000 bp a synchronous JSON request is
413 sync_too_large; sendPrefer: respond-asyncand poll. Below the cap async is a latency preference, not a requirement. reverse_complement: falseis a faster single pass, at some cost in minus-strand recall.
POST /v1/workflows/find-genes-and-predict-expressionFind genes and predict expression
POST /v1/workflows/find-genes-and-predict-expression — a composite that chains the two tasks server-side: annotate the region, centre a 9,198 bp window on each found gene's TSS, and score expression for each. One round trip, no intermediate results shuttled back to your client, and no tss_index to compute.
It is a published operation on the same bearer key as everything else; nothing needs enabling.
sequence: 1,000–500,000 bp — annotation's floor, since the workflow cannot find a gene in less sequence than the gene finder looks at.options(required), andoptions.description(required — the expression stage is conditioned on it; missing or empty is422 validation_failed, "options.description is required (cell type / assay context)"). Also acceptsannotation_model,expression_model,batch_size(1–128, default 8),shift_coordinates. Closed, like every otheroptions.- Above 50,000 bp synchronous delivery is refused with
413 sync_too_large,details={sequence_length, threshold}. Resend the identical body withPrefer: respond-asyncand pollGET /v1/tasks/jobs/{job_id}(see Asynchronous jobs). This is the lower of the contract's two sync caps; annotation carries the other, at 200,000 bp.
Output: data.expression_predictions[], one entry per gene found; a gene the workflow could not score carries a skip_reason. meta.task_specific_counts = {genes_found, genes_predicted, genes_skipped}, with genes_predicted + genes_skipped == genes_found. Unlike the direct expression endpoint, the workflow pads a TSS window with N up to half its width rather than dropping a gene near the edge of your region. JSON only.
API reference
- ReDoc
- OpenAPI JSON
- Python client
- MCP
POST /v1/workflows/find-genes-and-predict-expression
Annotate a raw DNA sequence then predict per-gene expression.
Open this operation in ReDoc ↗, with the request and response schemas, every status code, and copyable examples.
- Operation
paths["/v1/workflows/find-genes-and-predict-expression"].post- operationId
find_genes_and_predict_expression_v1_workflows_find_genes_and_predict_expression_post- Request body
#/components/schemas/FindGenesAndPredictExpressionRequest- 200 response
#/components/schemas/FindGenesAndPredictExpressionResponsex-sync-limit-bp- 50,000
Prefer- Set to
respond-asyncto dispatch asynchronously: the server returns202with{data: {job_id, status, links}, meta}immediately and the result is polled fromGET /v1/tasks/jobs/{job_id}. Anything else (or omitting the header) delivers the result synchronously with200. Async is JSON-only — combining it with a textformatis a400. Some endpoints require it above a size threshold and reject sync delivery with413 sync_too_large.
From /v1/openapi.json, pinned here at contract revision 16.
# client = Client(api_key=os.environ["GI_API_KEY"]), as in Promoter
accepted = client.find_genes_and_predict_expression(region, description="K562 cells", async_=True)
result = client.wait_for_job(accepted["data"]["job_id"])
for gene in result["data"]["expression_predictions"]:
print(gene.get("skip_reason") or gene["expression"])
Ask the MCP server: "Find the genes in chr8:127,680,000-127,800,000 and predict each one's expression in K562."
InputFindGenesAndPredictExpressionRequestSource ↗
Closed (additionalProperties: false): a key not listed here is rejected, not ignored.
sequencestringrequiredlength 1,000 – 500,000pattern ^\s*(?:[ACGNTacgnt]\s*)+$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 publishedminLengthas 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 with422 validation_failedbefore any model is loaded.modelstring | nulllength ≤ 128Model ID. If omitted, the task's default model is used. The valid ids and the default for this operation are published structurally asx-modelson the operation itself — deliberately not as anenumhere, so that adding a model cannot make a previously-generated client reject a valid id.GET /v1/tasks/{task}/modelscarries the same roster with full per-model specs.sequence_namestring | nulllength ≤ 128default "sequence"Display name for the sequence (e.g., 'chr1:1000-5000').
OutputFindGenesAndPredictExpressionResponseSource ↗
dataFindGenesAndPredictExpressionDatarequireddatashape forPOST /v1/workflows/find-genes-and-predict-expression.Show
FindGenesAndPredictExpressionDatafields (7)taskstringrequired= "find_genes_and_predict_expression"annotation_modelstringrequiredexpression_modelstringrequiredinputFindGenesAndPredictExpressionInputrequiredEcho of the request:sequence_nameand thedescriptionthe expression stage was conditioned on. The submitted length is not echoed here — readmeta.sequence_length.Show
FindGenesAndPredictExpressionInputfields (2)sequence_namestringrequiredThe caller's label for the submitted sequence, echoed verbatim. Defaults to"sequence"when the request omitted it.descriptionstringrequiredThe experimental context the expression stage was conditioned on, echoed fromoptions.description.
summaryobjectrequiredAggregate 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 (metaand this payload's own declared keys) instead.annotationobjectrequiredAnnotation stage's fulldatapayload (same shape asAnnotationData).expression_predictionsGeneExpressionPredictionData[]requiredOne record per gene found by annotation.Show
GeneExpressionPredictionDatafields (9)gene_indexintegerrequiredgene_namestringrequiredstrandstringrequiredone of "+", "-"tss_positionintegerrequiredTSS coordinate within the input sequence (bp).centered_sequence_lengthintegerrequiredexpressionnumberrequiredlog(TPM + 1).expression_tpmnumberrequiredskippedbooleanrequiredskip_reasonstring | nullPresent when skipped=True; missing otherwise.
metaFindGenesAndPredictExpressionMetarequiredmetashape forPOST /v1/workflows/find-genes-and-predict-expression. Inherits the spine fields from the simple-taskMeta(job_id, cold_start, *_time_ms, sequence_length, task_specific_counts) but adds the composite-specific keys: per-stage model ids and per-stage timing blocks.modelis the canonical concatenation"<annotation_model>+<expression_model>"— the same string the Web UI displays as the run identifier.Show
FindGenesAndPredictExpressionMetafields (13)job_idstringrequiredrequest_idstringrequiredCorrelation id for this request, mirrored on the X-Request-Id response header and identical toerror.request_idon the failure envelope.taskstringrequired= "find_genes_and_predict_expression"Workflow name. Present someta.taskis required on every success envelope, composite included, and always agrees withdata.task.modelstringrequiredComposite identifier: "<annotation_model>+<expression_model>". Useannotation_model/expression_modelfor the parts.cold_startbooleanrequiredTrue if EITHER stage had to load its model for this request.model_load_time_msintegerrequiredSum of per-stage load times (annotation + expression).inference_time_msintegerrequiredSum of per-stage inference times.sequence_lengthintegerrequiredtask_specific_countsFindGenesAndPredictExpressionCountsrequiredmeta.task_specific_countsshape for the composite workflow. Invariant:genes_predicted + genes_skipped == genes_found.Show
FindGenesAndPredictExpressionCountsfields (3)genes_foundintegerrequiredGenes detected by the annotation stage on the input sequence.genes_predictedintegerrequiredGenes whose expression was successfully predicted (TSS-centered window resolved + expression model returned a value).genes_skippedintegerrequiredGenes annotation found but the expression stage skipped — usually because the TSS-centered window would extend past the input sequence.data.expression_predictions[].skip_reasoncarries the per-gene cause.
annotation_modelstringrequiredexpression_modelstringrequiredannotationStageTimingsrequiredAnnotation stage cold-start + timing.Show
StageTimingsfields (3)cold_startbooleanrequiredTrue if the stage's model had to be loaded for this request.model_load_time_msintegerrequiredMilliseconds spent loading.inference_time_msintegerrequiredMilliseconds spent running inference.
expressionStageTimingsrequiredExpression stage cold-start + timing.Show
StageTimingsfields (3)cold_startbooleanrequiredTrue if the stage's model had to be loaded for this request.model_load_time_msintegerrequiredMilliseconds spent loading.inference_time_msintegerrequiredMilliseconds spent running inference.
Applications
Use it when the TSS positions are not known in advance: it annotates and scores a whole locus in one call, rather than you chaining annotation into expression yourself.
Usage tips
- The floor is 1,000 bp (annotation's), and the ceiling is this endpoint's own 500,000 bp, which is not the expression model's window.
- Above 50,000 bp, go async. A synchronous request is
413 sync_too_large; resend the identical body withPrefer: respond-async. This is the lower of the contract's two sync caps. - A gene near the edge of your region is still scored: its window is padded with
Nrather than the gene dropped. A gene the workflow could not score carriesskip_reason, andgenes_predicted + genes_skipped == genes_found. - JSON only. Unlike the predict operations it has no
?format=parameter.
POST /v1/workflows/genomic-variant-interpretationGenomic variant interpretation
POST /v1/workflows/genomic-variant-interpretation — the one operation that does not take a DNA sequence. You give it the s3:// URI of a VCF in your own object storage; it scores the variants that fall near a transcription start site and writes an annotated copy beside it, named after it. The JSON you get is a receipt: where the annotated file is, and how the run went. You never parse a VCF to drive the workflow, and the annotation format inside it can change without breaking anything you built.
This workflow is not finished. The contract below is real and will not change silently, but the per-tissue values in an annotated file are not final and are not yet to be read as results. A run is model output when, and only when, the response carries meta.model and the annotated VCF carries a ##GEXModel header line — until both appear, treat the numbers as format rather than findings. It also needs a grant on your bucket before it will run for you, so talk to us rather than integrating against it unannounced.
Asynchronous only. A whole-exome case runs for hours, well past any proxy timeout, so Prefer: respond-async is required; a request without it is 400 bad_request. There is no callback — submit, then poll GET /v1/tasks/jobs/{job_id} (see Asynchronous jobs).
POST /v1/workflows/genomic-variant-interpretation
Authorization: Bearer gi_...
Prefer: respond-async
Content-Type: application/json
{
"input": { "type": "s3_object", "uri": "s3://your-bucket/cases/CASE-00123/sample.vcf.gz" },
"client_ref": "CASE-00123",
"options": { "genome_build": "GRCh37" }
}
You name the VCF itself, not a folder — nothing else in the prefix is listed or read, so a manifest, an index, or a second VCF beside it are all irrelevant, and the format of your own case metadata stays yours. Everything the analysis needs arrives as typed options. The key must end in .vcf, .vcf.gz or .vcf.bgz; uncompressed, bgzip- and plain gzip-compressed files are all accepted and you never need to recompress anything.
The annotated copy is written beside the input, named after it and after the job: sample.vcf.gz becomes 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.
The job is in the name because the input alone does not identify a run: analysing one VCF against two different panels produces two different results, and under an input-only name the second would overwrite the first while the first receipt — retained for 24 hours — still pointed at it. Two VCFs in one folder are likewise two independent cases. A resubmission resolves to the same job and so rewrites the same object rather than accumulating copies.
Grant the service s3:GetObject on the object and s3:PutObject on its prefix. No s3:ListBucket is needed, because nothing searches.
input.type:s3_objecttoday. The field is a discriminated union so another kind of input — an inline VCF, a presigned URL — can be added without breaking this one.options.genome_build(required):GRCh37. A VCF header declares its assembly only sometimes, and guessing misplaces every window.options.window: bp from a start site within which a variant is scored. Default5000, range 1–100,000.options.tissues: cell-type contexts, one scoring run each. Default["heart", "liver", "brain"], 1–16 entries. The expression model is conditioned on these strings and the exact wording moves the result.options.genes: restrict scoring to a panel. Accepts HGNC symbols (BRCA1) or Ensembl gene ids with or without a version (ENSG00000141510,ENSG00000141510.17); symbols are case-insensitive, up to 1,000 entries. Omit it to score every gene near a variant.client_ref: an opaque string of yours, ≤128 characters, echoed back. It carries your case identity so this API never has to model a case.
The request is validated before the job is accepted. All of these are 400 bad_request on the POST, so a typo costs a second rather than a poll cycle through a job that fails minutes later: a URI that is not s3://bucket/key; one naming a prefix rather than an object; a key not ending .vcf, .vcf.gz or .vcf.bgz; an object this service cannot read (check the s3:GetObject grant); an empty VCF, or one over 2 GiB; a genes identifier matching no gene; a genome_build with no published start-site catalogue. Anything that goes wrong after acceptance is a job failure visible on the poll — including a file that turns out to be unreadable, or to already carry GEX_* fields, neither of which can be known until it is opened.
A panel is the difference between a long case and a short one. Unrestricted, a whole exome scores tens of thousands of allele-to-start-site pairs; restricted to a handful of genes it scores a handful. Records near a start site that is not in your panel are still written to the output, flagged NO_REQUESTED_GENE_IN_WINDOW — deliberately distinct from OUTSIDE_TSS_WINDOW, because "you did not ask about this gene" and "there was no start site here" are different answers, and a narrow panel should not read as a coverage gap. The resolved panel is echoed in meta.options_applied.genes and recorded in the output VCF's ##GEXRequestedGenes header, so a restricted run cannot later be mistaken for a whole-genome one. An identifier matching no MANE Select gene is a 400 naming every unresolved one — a panel silently missing a gene would return a result that looks complete and is not.
Submitting the same case twice gives you the same job. The job_id is derived from your key, input.uri, the input object's ETag, client_ref and options, so a retry after an ambiguous failure — or a restarted integration — resolves to the run you already have rather than starting a second hours-long pass over the same object. There is no idempotency header to send. Two consequences worth knowing: a failed job re-runs on resubmission, and to deliberately re-run a case that succeeded, change client_ref. Replacing the VCF under an unchanged path also yields a new job, since its ETag is part of the derivation.
Accepted submissions return 202 with data = {job_id, status: "accepted", links}, plus X-Job-Id and Content-Location. On completion the poll returns:
{
"data": {
"task": "genomic_variant_interpretation",
"client_ref": "CASE-00123",
"status": "ok",
"output": { "type": "s3_object", "uri": "s3://your-bucket/cases/CASE-00123/sample.annotated.3eaecf69.vcf.gz" },
"counts": {
"variants_in": 73771,
"annotated": 12721,
"not_run": 61050,
"not_run_reasons": { "OUTSIDE_TSS_WINDOW": 61050 },
"annotated_alleles": 12725,
"associations": 14698,
"skipped_alleles": 10
}
},
"meta": {
"task": "genomic_variant_interpretation",
"genome_build": "GRCh37",
"job_id": "…", "request_id": "…",
"input": { "type": "s3_object", "uri": "s3://your-bucket/cases/CASE-00123/sample.vcf.gz" },
"gene_annotation": {
"build": "v50lift37",
"md5": "bed31c2cead98e9e1989ef7943fb3206",
"transcripts": "MANE Select",
"start_sites": 19153
},
"options_applied": { "window": 5000, "tissues": ["heart", "liver", "brain"], "genes": null }
}
}
Every input record reaches the output, scored or not, so annotated + not_run == variants_in and you can diff input against output record for record. A record that could not be scored is flagged in place with GEX_NOT_RUN and a reason in GEX_NOT_RUN_REASON — OUTSIDE_TSS_WINDOW, NO_TSS_ON_CONTIG, NO_SUPPORTED_ALT, or NO_REQUESTED_GENE_IN_WINDOW when you sent a panel — rather than dropped. The same four appear in counts.not_run_reasons, which sums to not_run. A record with some usable and some unusable ALT alleles — a symbolic allele beside a plain one, say — lists the unusable ones in GEX_SKIPPED_ALT and is still annotated for the rest, so a record can carry both keys. Scored records carry GEX_ANN, one VEP-style entry per supported ALT allele and nearby transcript: Allele|Gene|Gene_ID|Transcript_ID|TSS|Strand|TSS_distance| then one log2 fold-change field per requested tissue. Distances are strand-aware, negative upstream, and the output header records the convention along with the window and the GENCODE release the start sites came from — and the model, once one is named. meta.input echoes the object you named, so a stored receipt names both what was read and what was written. counts.associations is the unit of scoring work — allele-to-start-site pairs, not records — so it is the number to reason about when sizing a case, and meta.gene_annotation is the machine-readable form of that provenance.
meta.model tells you whether these are model output. While this workflow is under development the field is absent, as is the annotated VCF's ##GEXModel header line — the run is not attributed to a model that did not produce the values. Both appear, naming the model, once it is. Everything around them is real today: your file is read, every record is matched against GENCODE v50lift37 MANE Select start sites, every record is written back, and the counts are computed from it.
Submitting a VCF that already carries GEX_* fields — an annotated copy from a previous run, for instance — is a 400: submit the original. Results are retained for 24 hours and then return 410. The annotated file in your own bucket is not on that clock. A job does not survive a deployment of this service: in-flight work is lost and the poll reports 503 with a message to resubmit, so retries belong to you.
This workflow is REST-only — it is not exposed as an MCP tool.
API reference
- ReDoc
- OpenAPI JSON
- Python client
- MCP
POST /v1/workflows/genomic-variant-interpretation
Score the variants in a VCF and return an annotated copy.
Open this operation in ReDoc ↗, with the request and response schemas, every status code, and copyable examples.
- Operation
paths["/v1/workflows/genomic-variant-interpretation"].post- operationId
genomic_variant_interpretation_v1_workflows_genomic_variant_interpretation_post- Request body
#/components/schemas/GenomicVariantInterpretationRequest- 200 response
#/components/schemas/GenomicVariantInterpretationResponsePrefer- Required — this operation is async-only. A case runs for hours, far past any proxy timeout, so a request without
Prefer: respond-asyncis refused with400 bad_requestrather than delivered synchronously.
From /v1/openapi.json, pinned here at contract revision 16.
The kit client does not wrap this workflow. Post it with requests and poll with the client:
import os, requests
from gi_client import Client
key = os.environ["GI_API_KEY"]
r = requests.post(
"https://api.genomicintelligence.ai/v1/workflows/genomic-variant-interpretation",
headers={"Authorization": f"Bearer {key}", "Prefer": "respond-async"},
json={
"input": {"type": "s3_object", "uri": "s3://your-bucket/cases/CASE-00123/sample.vcf.gz"},
"client_ref": "CASE-00123",
"options": {"genome_build": "GRCh37"},
},
timeout=60,
)
receipt = Client(api_key=key).wait_for_job(r.json()["data"]["job_id"], max_wait=6 * 3600)
print(receipt["data"]["output"]["uri"])
This workflow is REST-only; it is not exposed as an MCP tool.
InputGenomicVariantInterpretationRequestSource ↗
Closed (additionalProperties: false): a key not listed here is rejected, not ignored.
inputS3ObjectInputrequiredShow
S3ObjectInputfields (2)typestringrequired= "s3_object"uristringrequiredlength 8 – 1,024pattern ^s3://[^/]+/.+Fulls3://bucket/keyURI of the VCF to read, e.g.s3://bucket/cases/CASE-00123/sample.vcf.gz. The key must end in.vcf,.vcf.gzor.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.gzyieldssample.annotated.<job>.vcf.gzin the same prefix, where<job>is the first eight characters of thejob_id. Read the exact name fromdata.output.urirather 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 granteds3:GetObjecton the object ands3:PutObjecton its prefix;s3:ListBucketis not required.
client_refstring | nulllength ≤ 128Opaque 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 changingclient_refis how you deliberately re-run a case that already succeeded. Hashing is not parsing.
OutputGenomicVariantInterpretationResponseSource ↗
dataGenomicVariantInterpretationDatarequireddataforPOST /v1/workflows/genomic-variant-interpretation. A receipt, not a payload. The predictions live in the annotated VCF atoutput.uri; this envelope says where that object is and how the run went, so a caller can orchestrate the workflow without parsing a VCF.Show
GenomicVariantInterpretationDatafields (5)taskstringrequired= "genomic_variant_interpretation"statusstringrequired= "ok"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 sayingfailed.outputVariantObjectRefrequiredThe annotated copy, written beside the input and named after it and the job:sample.vcf.gzbecomessample.annotated.<job>.vcf.gzin the same prefix. Read the name from here rather than constructing it.Show
VariantObjectReffields (2)typestringrequired= "s3_object"uristringrequiredFully qualifieds3://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.
countsGenomicVariantInterpretationCountsrequireddata.countsfor the variant workflow. Invariant:annotated + not_run == variants_in. Every input record is written to the output, whether or not it could be scored.Show
GenomicVariantInterpretationCountsfields (7)variants_inintegerrequiredRecords read from the input VCF.annotatedintegerrequiredRecords carrying a prediction in the output.not_runintegerrequiredRecords written through unscored — typically because no transcription start site falls withinoptions.window, or because it belongs to a gene outsideoptions.genes. Seenot_run_reasonsfor the breakdown.annotated_allelesintegerdefault 0ALT alleles carrying a prediction. Exceedsannotatedwhere a record is multiallelic.associationsintegerdefault 0Allele-to-start-site pairs scored — the unit of model work, not the record count. One allele near three start sites is three.not_run_reasonsmap<string, integer>Why records were not scored, by reason:OUTSIDE_TSS_WINDOW,NO_TSS_ON_CONTIG,NO_SUPPORTED_ALT,NO_REQUESTED_GENE_IN_WINDOW. Sums tonot_run. A reason with no records is omitted.skipped_allelesintegerdefault 0ALT alleles ineligible for scoring (symbolic, breakends, the spanning deletion*), listed per record inGEX_SKIPPED_ALT. A record can be annotated for its other alleles and still have some counted here.
client_refstring | nullEcho of the request'sclient_ref, verbatim.
metaGenomicVariantInterpretationMetarequiredmetafor the variant workflow. Carries the provenance a result needs to stay interpretable months later: which assembly, which models, and the options actually applied — which may differ from those requested only by defaulting.Show
GenomicVariantInterpretationMetafields (8)job_idstringrequiredrequest_idstringrequiredCorrelation id for this request, mirrored on the X-Request-Id response header.taskstringrequired= "genomic_variant_interpretation"genome_buildstringrequiredgene_annotationGeneAnnotationProvenancerequiredWhich 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.Show
GeneAnnotationProvenancefields (4)buildstringrequiredGENCODE release, e.g.v50lift37.md5stringrequiredMD5 of the GENCODE annotation the catalogue was built from.start_sitesintegerrequiredStart sites in the catalogue.transcriptsstringdefault "MANE Select"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.
options_appliedGenomicVariantInterpretationOptionsAppliedrequiredWindow and tissues as the run actually used them.Show
GenomicVariantInterpretationOptionsAppliedfields (3)windowintegerrequiredTSS proximity window in bp.tissuesstring[]requiredCell-type contexts scored, in order.genesstring[] | nullThe 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.
inputVariantObjectRefrequiredThe VCF that was read — the object named byinput.urion the request. Echoed so a stored receipt is self-contained: it names both what was read and what was written. Always present.Show
VariantObjectReffields (2)typestringrequired= "s3_object"uristringrequiredFully qualifieds3://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.
modelstring | nullThe 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##GEXModelheader 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.
Applications
Use it to score the variants in a case's VCF that fall near a transcription start site, across the tissues you name, and get the annotated VCF back in your own bucket beside the input, where the rest of your pipeline already reads.
Usage tips
- Async only.
Prefer: respond-asyncis required; without it the request is400 bad_request. - Send a gene panel when you have one. Restricted to a handful of genes a case scores a handful of allele-to-start-site pairs instead of tens of thousands.
- The same case twice is the same job. To deliberately re-run a case that succeeded, change
client_ref. tissuesare conditioning text. The exact wording moves the prediction, as with expression'sdescription.- Not results yet. Until the response carries
meta.modeland the VCF a##GEXModelheader, treat the values as format rather than findings.
Next: Limits for caps and latency, or the REST API guide for the call walkthrough.