Skill Tracer
Skills › Scientific Agent Skills › genomic-intelligence › api-and-auth.md

api-and-auth.md

150 lines · skills/genomic-intelligence/references/api-and-auth.md at 5f2bc03

Open on GitHub

Most marks come from matching words in the file, so treat them as pointers.

1# REST API & Authentication
2
3Base URL: `https://api.genomicintelligence.ai` (override with `GI_BASE_URL` for
4staging). Live contract: <https://api.genomicintelligence.ai/v1/openapi.json>.
5

REST API & Authentication

Base URL: https://api.genomicintelligence.ai (override with GI_BASE_URL for staging). Live contract: <https://api.genomicintelligence.ai/v1/openapi.json>.

Raw lines 1 to 5
6## Authentication
7
8Prediction and job REST calls need a partner bearer key, sent as
9`Authorization: Bearer <key>`. Public routes needing no key: `/health`, `/docs`,
10`/redoc`, `/v1/openapi.json`, and `GET /v1/tasks/{task}/models`. The
11[official overview](https://docs.genomicintelligence.ai/) documents capability
12discovery as public and rate-limited per source IP.
14```bash
15export GI_API_KEY="gi_yourkeyhere"
16```
18Keys begin with `gi_`. Request one at contact@genomicintelligence.ai. Read the
19key from the environment (or a `.env` via `python-dotenv`); never hardcode or
20commit it.
22> The hosted **MCP** server (`mcp.genomicintelligence.ai/mcp`) is different: it
23> runs **keyless** against a rate- and concurrency-limited public demo tier, with
24> the key optional for higher limits. REST prediction requires a key, but
25> public model discovery does not. See `mcp.md`.

Authentication

Prediction and job REST calls need a partner bearer key, sent as Authorization: Bearer <key>. Public routes needing no key: /health, /docs, /redoc, /v1/openapi.json, and GET /v1/tasks/{task}/models. The official overview documents capability discovery as public and rate-limited per source IP.

export GI_API_KEY="gi_yourkeyhere"

Keys begin with gi_. Request one at contact@genomicintelligence.ai. Read the key from the environment (or a .env via python-dotenv); never hardcode or commit it.

The hosted MCP server (mcp.genomicintelligence.ai/mcp) is different: it runs keyless against a rate- and concurrency-limited public demo tier, with the key optional for higher limits. REST prediction requires a key, but public model discovery does not. See mcp.md.
Raw lines 6 to 26
Uses an outside tool MCP :22
27## Endpoints
29Twelve operations are published in contract revision 16. The six predict paths are **literal, one per
30task**; the published document has no templated `/v1/tasks/{task}/predict`
31operation.
33| Method | Path | Purpose |
34|---|---|---|
35| POST | `/v1/tasks/promoter/predict` | `PromoterPredictRequest` |
36| POST | `/v1/tasks/splice/predict` | `SplicePredictRequest` |
37| POST | `/v1/tasks/enhancer/predict` | `EnhancerPredictRequest` |
38| POST | `/v1/tasks/chromatin/predict` | `ChromatinPredictRequest` |
39| POST | `/v1/tasks/annotation/predict` | `AnnotationPredictRequest` |
40| POST | `/v1/tasks/expression/predict` | `ExpressionPredictRequest` (also requires `options`) |
41| POST | `/v1/workflows/find-genes-and-predict-expression` | Composite: find genes, predict each one's expression |
42| GET | `/v1/tasks/jobs` | Recent own jobs, `limit=1..500` (default 50); flat `{jobs, count}`, no cursor/offset |
43| GET | `/v1/tasks/jobs/{job_id}` | Poll an async job (202 running → 200 terminal) |
44| GET | `/v1/tasks/{task}/models` | List available model IDs for a task |
45| GET | `/health` | Public liveness; does not validate a prediction key |
46| POST | `/v1/workflows/genomic-variant-interpretation` | Separate async-only VCF workflow; see boundary below |
48There is no usable templated route to fall back on: the six literal paths are
49matched first, and any other task segment is `404 not_found`
50(`"Unknown task: bogus"`), never a `422`.
52`Prefer: respond-async` is a declared header parameter on all six predict
53operations and on the composite — it is not an annotation-only extra. Omit it
54for a synchronous `200`; send it for a `202` carrying
55`{data: {job_id, status: "accepted", links}, meta}`, with the id also in
56`Content-Location` and `X-Job-Id`, then poll `GET /v1/tasks/jobs/{job_id}`.
57Async is JSON-only: combining it with a text `format` is a `400`.

Endpoints

Twelve operations are published in contract revision 16. The six predict paths are literal, one per task; the published document has no templated /v1/tasks/{task}/predict operation.

MethodPathPurpose
POST/v1/tasks/promoter/predictPromoterPredictRequest
POST/v1/tasks/splice/predictSplicePredictRequest
POST/v1/tasks/enhancer/predictEnhancerPredictRequest
POST/v1/tasks/chromatin/predictChromatinPredictRequest
POST/v1/tasks/annotation/predictAnnotationPredictRequest
POST/v1/tasks/expression/predictExpressionPredictRequest (also requires options)
POST/v1/workflows/find-genes-and-predict-expressionComposite: find genes, predict each one's expression
GET/v1/tasks/jobsRecent own jobs, limit=1..500 (default 50); flat {jobs, count}, no cursor/offset
GET/v1/tasks/jobs/{job_id}Poll an async job (202 running → 200 terminal)
GET/v1/tasks/{task}/modelsList available model IDs for a task
GET/healthPublic liveness; does not validate a prediction key
POST/v1/workflows/genomic-variant-interpretationSeparate async-only VCF workflow; see boundary below

There is no usable templated route to fall back on: the six literal paths are matched first, and any other task segment is 404 not_found ("Unknown task: bogus"), never a 422.

Prefer: respond-async is a declared header parameter on all six predict operations and on the composite — it is not an annotation-only extra. Omit it for a synchronous 200; send it for a 202 carrying {data: {job_id, status: "accepted", links}, meta}, with the id also in Content-Location and X-Job-Id, then poll GET /v1/tasks/jobs/{job_id}. Async is JSON-only: combining it with a text format is a 400.

Raw lines 27 to 58
59## Request / response
61Request body: `{sequence, sequence_name?, model?, options?}` — but there is no
62longer a shared `PredictRequest`. Each task has its own request model with its own
63`minLength` (promoter 300, splice 100, enhancer 50, chromatin 200, annotation
641,000, expression 9,198, composite 1,000; `maxLength` 500,000 for all), and every
65one is `additionalProperties: false`. `options` is likewise typed and closed per
66task, so an unknown key is `422 validation_failed` with `type: "extra_forbidden"`
67at `loc ["body","options","<key>"]`.
69**`expression` differs further**: its body is
70`{sequence, options, tss_index?, sequence_name?, model?}`, `options` is required
71(`ExpressionOptions.required = ["description"]`, the only key it accepts), and
72`tss_index` is required unless `sequence` is exactly 9,198 bp. See
73`tasks.md#expression`.
75Hand-built requests are unaffected. A client **generated** from an older OpenAPI
76document must be regenerated against the current one: the shared `PredictRequest`
77model such clients were built from is not in the published document.
79Success is a `{data, meta}` envelope; `data` is task-specific (see `tasks.md`),
80`meta` carries model + request info. **Exceptions:** job listing is flat `{jobs, count}`; `GET /v1/tasks/{task}/models`
81is also *not* enveloped — it returns a flat
82`{task, default_model, models: [{id, name, description, is_default, bio_spec}]}`.
84Errors use an `{error}` envelope carrying `code`, `message`, `request_id` and an
85optional `details`; the most common is `422 validation_failed` (wrong sequence
86length — under the floor *or* over 500,000 bp; over-length is not a `413`).

Request / response

Request body: {sequence, sequence_name?, model?, options?} — but there is no longer a shared PredictRequest. Each task has its own request model with its own minLength (promoter 300, splice 100, enhancer 50, chromatin 200, annotation 1,000, expression 9,198, composite 1,000; maxLength 500,000 for all), and every one is additionalProperties: false. options is likewise typed and closed per task, so an unknown key is 422 validation_failed with type: "extra_forbidden" at loc ["body","options","<key>"].

**expression differs further**: its body is {sequence, options, tss_index?, sequence_name?, model?}, options is required (ExpressionOptions.required = ["description"], the only key it accepts), and tss_index is required unless sequence is exactly 9,198 bp. See tasks.md#expression.

Hand-built requests are unaffected. A client generated from an older OpenAPI document must be regenerated against the current one: the shared PredictRequest model such clients were built from is not in the published document.

Success is a {data, meta} envelope; data is task-specific (see tasks.md), meta carries model + request info. Exceptions: job listing is flat {jobs, count}; GET /v1/tasks/{task}/models is also not enveloped — it returns a flat {task, default_model, models: [{id, name, description, is_default, bio_spec}]}.

Errors use an {error} envelope carrying code, message, request_id and an optional details; the most common is 422 validation_failed (wrong sequence length — under the floor or over 500,000 bp; over-length is not a 413).

Raw lines 59 to 87
88## `bio_spec` (from `GET /v1/tasks/{task}/models`)
90- `request_max_bp` — the enforced ceiling: 500,000 for every model.
91- `context_window_bp` — the model's own sliding window; `null` for annotation and
92 expression. The promoter default reports 2,000 (the 300 bp promoter models
93 report 300), splice 15,000, enhancer 249, chromatin 1,000. Compare your sequence
94 length against this to know whether the model scored real sequence or padding.
95- `trained_window_bp` — fixed receptive field; 9,198 for the expression model,
96 `null` for sliding-window models.
97- The legacy `max_seq_length_bp` is not part of `bio_spec` and is absent from the
98 response. It was ambiguous — it read 9,198 for the expression model, the trained
99 window rather than a request cap, so gating on it wrongly rejected the
100 9,198–500,000 bp range expression accepts. Use `request_max_bp`.
102There is no `strand_sensitive` flag. The splice model is strand-specific in
103practice — feed transcript orientation.

bio_spec (from GET /v1/tasks/{task}/models)

  • request_max_bp — the enforced ceiling: 500,000 for every model.
  • context_window_bp — the model's own sliding window; null for annotation and expression. The promoter default reports 2,000 (the 300 bp promoter models report 300), splice 15,000, enhancer 249, chromatin 1,000. Compare your sequence length against this to know whether the model scored real sequence or padding.
  • trained_window_bp — fixed receptive field; 9,198 for the expression model, null for sliding-window models.
  • The legacy max_seq_length_bp is not part of bio_spec and is absent from the response. It was ambiguous — it read 9,198 for the expression model, the trained window rather than a request cap, so gating on it wrongly rejected the 9,198–500,000 bp range expression accepts. Use request_max_bp.

There is no strand_sensitive flag. The splice model is strand-specific in practice — feed transcript orientation.

Raw lines 88 to 104
105## Partner tiers
107Keys are scoped to a tier with concurrency and per-minute caps. A `429` means a
108cap was hit — back off and retry, or ask GI to raise the tier.

Partner tiers

Keys are scoped to a tier with concurrency and per-minute caps. A 429 means a cap was hit — back off and retry, or ask GI to raise the tier.

Raw lines 105 to 109
110## Job lifecycle and response stability
112`GET /v1/tasks/jobs/{job_id}` returns 202 while accepted/running, 200 for a
113successful result, the underlying 4xx/5xx for a failed job, 404 for unknown or
114not-owned work, and 410 for expiration. Completed bodies differ across the six
115tasks, the composite, and VCF receipts: branch on **`data.task`**, not first-match
116union deserialization. Results are documented as retained 24 hours from last
117activity; listing is only a recent list, not a way to page through all history.
119`data.summary` keys can change without a revision. `data.input` is an input-label
120echo, not a general metadata bag: expression has `sequence_name`, `description`,
121`tss_index`; the other five have only `sequence_name`. Use
122`meta.sequence_length` and expression's `meta.task_specific_counts.scored_window`.
124Record both `info.version` and top-level `x-contract-revision`. The latter is
12516 in the reviewed deployment and is the intended contract-change indicator.
126`x-sync-limit-bp` applies to JSON delivery. Annotation text formats stay sync
127above the threshold and may hit gateway timeouts. An edge-generated 504/reset
128may carry no API JSON envelope. Bounded requests and polling do not cancel
129server-side work or make a POST retry idempotent.

Job lifecycle and response stability

GET /v1/tasks/jobs/{job_id} returns 202 while accepted/running, 200 for a successful result, the underlying 4xx/5xx for a failed job, 404 for unknown or not-owned work, and 410 for expiration. Completed bodies differ across the six tasks, the composite, and VCF receipts: branch on **data.task**, not first-match union deserialization. Results are documented as retained 24 hours from last activity; listing is only a recent list, not a way to page through all history.

data.summary keys can change without a revision. data.input is an input-label echo, not a general metadata bag: expression has sequence_name, description, tss_index; the other five have only sequence_name. Use meta.sequence_length and expression's meta.task_specific_counts.scored_window.

Record both info.version and top-level x-contract-revision. The latter is 16 in the reviewed deployment and is the intended contract-change indicator. x-sync-limit-bp applies to JSON delivery. Annotation text formats stay sync above the threshold and may hit gateway timeouts. An edge-generated 504/reset may carry no API JSON envelope. Bounded requests and polling do not cancel server-side work or make a POST retry idempotent.

Raw lines 110 to 130
131## VCF workflow boundary
133The official API also publishes `POST /v1/workflows/genomic-variant-interpretation`.
134This is distinct from calling variants or the sequence tasks above. It requires
135bearer auth and `Prefer: respond-async`; its closed request contains `input`
136(`type: "s3_object"`, `uri` naming a VCF), required `options.genome_build`
137(currently **GRCh37 only**), and optional `client_ref`. Optional settings include
138`window` (1–100,000; default 5,000), `tissues` (1–16 strings), and `genes`
139(1–1,000 symbols/Ensembl gene IDs; omit for all nearby genes, never an empty list).
140The service reads the object and writes an annotated copy beside it; use the
141returned `data.output.uri` rather than constructing a filename.
143This workflow is **under development** in the current official guide. When
144`meta.model` is absent, per-tissue values are not established model results;
145an HTTP 200 receipt is not biological validation. Its input build differs from
146the GRCh38 default used by human sequence acquisition. Identical requests reuse
147a job; changing `client_ref` changes submission identity. Do not infer that
148idempotency rule for the six sequence tasks. No VCF submission or object-storage
149write was executed in this review. Read the [current workflow contract](https://docs.genomicintelligence.ai/tasks#genomic-variant-interpretation)
150before attempting this separate workflow.

VCF workflow boundary

The official API also publishes POST /v1/workflows/genomic-variant-interpretation. This is distinct from calling variants or the sequence tasks above. It requires bearer auth and Prefer: respond-async; its closed request contains input (type: "s3_object", uri naming a VCF), required options.genome_build (currently GRCh37 only), and optional client_ref. Optional settings include window (1–100,000; default 5,000), tissues (1–16 strings), and genes (1–1,000 symbols/Ensembl gene IDs; omit for all nearby genes, never an empty list). The service reads the object and writes an annotated copy beside it; use the returned data.output.uri rather than constructing a filename.

This workflow is under development in the current official guide. When meta.model is absent, per-tissue values are not established model results; an HTTP 200 receipt is not biological validation. Its input build differs from the GRCh38 default used by human sequence acquisition. Identical requests reuse a job; changing client_ref changes submission identity. Do not infer that idempotency rule for the six sequence tasks. No VCF submission or object-storage write was executed in this review. Read the current workflow contract before attempting this separate workflow.

Raw lines 131 to 150