Nosis Biomarker Analysis API — Integration Guide
For the Nosis engineering team. Covers auth, the upload → run → poll flow, the request and response shapes, limits, versioning, and data handling.
- Template:
nosis-blueprintv0.5.14 · reference ranges v0.1.0 - Contact: Jeph (NGM engineering)
- Last updated: 2026-09-10
- Environment
- Sandbox · Nosis HealthSynthetic or de-identified data only.
- Tier
- DetailedFull retrieval depth.
- Template
nosis-blueprintv0.5.31Stamped on every report astemplate_version.- Reference ranges
- v0.1.0Stamped on every report as
ranges_version. - Interactive reference
- OpenAPI, with live schemasTry each endpoint with your key.
- Service status
- /healthVersions and environment, no key needed.
Release 0.5.14 — 10 September 2026#
Report acceptance and correction#
Task status completed means processing has finished. Check result.validation.passed and the returned artifacts separately. When narrative or source checks fail after the single correction attempt, Markdown and audit metadata are retained and HTML is withheld. Keep that result flagged in the Review Queue; it is not an approved report.
The correction receives the complete reviewed draft and supported findings as untrusted data, so it can preserve valid content while correcting the identified claims. Reporting bounds are kept distinct from assay limits, and missing source units must remain missing in narrative text. Nosis Gap Analysis may retry a recognized transient provider failure once within its original deadline; this does not create a new task or increase the report-correction budget.
Platelet count units such as Thousand/uL are supported. Assessment safety copy reflects the Assessment pathway, and generated HTML excludes internal stylesheet comments. The interactive reference at /api and its OpenAPI document at /api-json now describe nested request fields and success/error responses. Existing URLs, credentials, request fields and historical reports are unchanged.
This update also improves Dutch biomarker matching and supported SI-unit conversions, clarifies assay and collection-date guidance, and adds source range units and selected collection dates to panel audit metadata. Blank result cells are excluded before selecting the latest collected result. Wrapped assay names are kept together, and the equivalent decimal-comma eGFR unit is supported. Narrative generation uses the available source unit for unconverted results and requires supplied evidence for statements about habits or collection timing. New reports use ISO YYYY-MM-DD collection dates; ambiguous or invalid dates are omitted, and older reports retain their original representation. Both tiers perform source-grounding review and retry a nonempty malformed review decision at most once while retaining the same report and source evidence. Valid negative decisions do not receive a retry to seek approval. Panel rows may include source_name, the selected laboratory assay label. It is source data, not an instruction. source: "measured" means reported by the laboratory and does not establish a direct measurement method; server-calculated rows omit source_name. Recognized Dutch current/previous-result tables can supply dates or missing reported rows when their source cells match unambiguously. Ambiguous layouts remain unchanged. Explicit narrative status claims must agree with the panel; a contradiction that persists after report repair withholds HTML and is surfaced in validation.
Generation and review now use one fact representation that separates reported results, laboratory and server calculation origins, known assay methods, and reference bounds. Explicit contradictory prose and unsupported low/high-normal status labels receive one report correction attempt. If they persist, or source review fails or is unavailable, validation.passed is false and outputs.html is false. The flagged Markdown and audit metadata remain available for your Review Queue. Use these fields when deciding whether a report may advance; a completed task means processing ended, not that the report passed validation. Reference retrieval runs against the final reviewed draft.
1. Base URLs and credentials#
| Environment | Base URL | Key |
|---|---|---|
| Sandbox (detailed) | https://nosis-sandbox.api.nextgenerationmedicine.co |
sandbox key |
| Sandbox (lean) | https://nosis-biomarker-analysis-lean-sandbox-production.up.railway.app |
its own sandbox key |
| Production (detailed) | https://nosis.api.nextgenerationmedicine.co — not yet live |
production key |
| Production (lean) | https://nosis-lean.api.nextgenerationmedicine.co — not yet live |
production key |
This guide is published at
/docson your host, andhttps://sandbox.api.nextgenerationmedicine.co/nosis(or/nosis/lean) is the short link that redirects there. The interactive OpenAPI reference is at/api.Your deployment is yours alone: its own host, key, template and reference ranges. The two sandbox tiers are separate services with separate keys; the report contract is identical, lean runs fewer retrieval stages (
totalStages10 rather than 11) and reportspipeline_id: nosis-blueprint-lean.https://nosis-biomarker-analysis-sandbox-production.up.railway.appis the same service under its platform hostname and also works. Production hosts are listed for planning only — they do not exist yet and no production key has been issued.If you received an earlier guide (25 August) describing
/api/developer/v1/biomarker/...routes, discard it. That was a different gateway. This document is the contract:/api/files,/api/pipeline,/api/reportson the host above.
Sandbox and production use separate URLs and separate keys. A sandbox key is rejected by production and vice versa.
Sandbox is synthetic-data only. Do not send real member data until the BAA is executed. Production keys are not issued before then.
The lean host runs the same report contract on a lighter retrieval pipeline (3 knowledge-base reads instead of 6). Output shape is identical.
Auth — Bearer token on every request:
Authorization: Bearer <your-api-key>
Missing or wrong keys return 401 / 403 as JSON on authenticated data
endpoints. Documentation, Swagger and health endpoints are public.
The integration key needs files:write, files:read, pipeline:run,
pipeline:read and reports:read; deletion also needs files:delete.
Keys are bound to the client, environment and instance and can expire or be
revoked. The existing sandbox developer keys expire on 9 October 2026 UTC;
arrange renewal before then. Revocation blocks subsequent authenticated API
calls, but already issued signed storage URLs remain valid until their expiry.
2. The flow#
1. POST /api/files/presign-upload → presigned PUT URL + key
2. PUT <presigned url> → upload the lab PDF directly
3. POST /api/pipeline/start → { taskId }
4. GET /api/pipeline/status/{id} → poll until completed
5. GET /api/reports/{id} → signed URLs for the stored artifacts
Endpoints#
| Endpoint | Purpose |
|---|---|
POST /api/files/presign-upload |
Presigned PUT URL for one lab document, valid 15 minutes. |
POST /api/files/upload |
Multipart upload, field files, up to 10 per request. |
GET /api/files/list?prefix=uploads/ |
List your uploaded objects under a prefix. |
GET /api/files/signed-url/{key} |
Presigned download URL; ?expires= must be an integer from 1 to 3600 seconds, default 3600. |
GET /api/files/download/{key} |
Stream an object's bytes. |
DELETE /api/files/{key} |
Delete an object immediately. |
POST /api/pipeline/start |
Start a run. Returns taskId at once. |
GET /api/pipeline/status/{taskId} |
Poll a run; carries the report inline while it is cached. |
GET /api/reports/{taskId} |
Signed URLs for the stored artifacts. The durable copy. |
GET /health |
Service status and the versions in use. No key required. |
The data endpoints above require the Bearer key. /docs, Swagger at /api
and /health are public.
Step 5 is required, not optional. Step 4 usually returns the full report
inline, but that copy is served from an in-memory cache of the 200 most recent
jobs. After a service restart, on a second instance behind the load balancer,
or once 200 further jobs have run, step 4 returns "completed": true with no
result field. The bucket copy that step 5 points at is the durable one.
Treat inline result as a fast path and step 5 as the source of truth: if
completed is true and result is absent, fetch the artifacts. Do not treat
a missing result on a completed job as a failure.
2.1 Upload a lab document#
POST /api/files/presign-upload
Content-Type: application/json
{ "name": "member-labs.pdf", "mimeType": "application/pdf", "size": 482113 }
{ "uploadUrl": "https://...", "key": "uploads/9f3c....pdf", "fileId": "9f3c...", "expiresIn": 900 }
PUT the bytes to uploadUrl with the same Content-Type, then pass key in
file_keys. The presigned URL is valid for 15 minutes.
Accepted types: PDF, JPEG, PNG, GIF, WebP, TXT, CSV, XLSX.
Alternative for small files: POST /api/files/upload as multipart/form-data
with field files (up to 10 per request).
2.2 Start a run#
POST /api/pipeline/start
Content-Type: application/json
{
"idempotency_key": "nosis-report-7f21c9",
"inputs": {
"member": {
"name": "Jordan Reeves",
"age": 42,
"sex": "male",
"program_status": "core",
"substance_use_status": "In recovery, alcohol-free since March 2024",
"height_cm": 178,
"weight_kg": 82
},
"input_0": "MEMBER CONTEXT\n\nDemographics: ...\nGoals & Priorities: ...\nSleep: ...",
"overall_instructions": "<your current Part II instruction package>",
"file_keys": ["uploads/9f3c....pdf"],
"language": "English",
"User_Preference_Level": "Detailed"
}
}
{
"taskId": "0f8c2e1a-...",
"status": "started",
"pipeline_id": "nosis-blueprint-detailed",
"environment": "sandbox",
"totalStages": 11,
"template_id": "nosis-blueprint",
"template_version": "0.5.14",
"ranges_version": "0.1.0"
}
Fields
| Field | Required | Notes |
|---|---|---|
member |
yes | See below. Populates the report header directly. |
input_0 |
yes | Free-text member context (your Typeform summary). Max 60,000 chars. |
file_keys or inputs.Other_files |
yes | At least one lab document. |
overall_instructions |
no | Your Part II package. Max 120,000 chars. |
Previous_Data |
no | Prior results for longitudinal context. Without it the report treats the labs as a snapshot and will not describe anything as trending. |
language |
no | Default English. See §7. |
User_Preference_Level |
no | Detailed (default on the detailed host) or Default. |
idempotency_key |
no | See §4. |
member:
| Field | Required | Constraint |
|---|---|---|
name |
yes | 1–120 chars |
age |
yes | integer 18–120 |
sex |
yes | male | female — selects sex-specific ranges and markers |
program_status |
yes | assessment | core — selects the §X pathway copy |
substance_use_status |
no | ≤300 chars, member-provided. Never inferred; omitted from the header when absent. |
height_cm |
no | 100–250 — required for BMI |
weight_kg |
no | 30–300 — required for BMI |
For the agreed Nosis integration, include height, weight, age and sex with every request so all applicable calculations, including BMI, can be produced.
Date of birth is not accepted and is never rendered.
Ignored if sent (forced server-side): Report_Type,
intervention_philosophy, design, protocols_store, protocols_thisrun,
protocols_active, Protocol_files. Sending them is not an error.
2.3 Poll for completion#
GET /api/pipeline/status/{taskId}
Running:
{
"status": "running",
"completed": false,
"stage": "Clinical Report",
"stageIndex": 9,
"totalStages": 11,
"created_at": "2026-09-04T09:12:03.000Z",
"updated_at": "2026-09-04T09:18:44.000Z",
"expires_at": "2026-09-11T09:12:03.000Z"
}
Completed (abridged):
{
"status": "completed",
"completed": true,
"stage": "Output Routing",
"stageIndex": 11,
"totalStages": 11,
"template_id": "nosis-blueprint",
"template_version": "0.5.14",
"ranges_version": "0.1.0",
"validation": { "passed": true, "errors": [], "warnings": [] },
"result": {
"output_0": "# Your Nosis Blueprint Report\n\nGenerated September 4, 2026\n\n...",
"Visual_Report": "<!doctype html>…",
"outputs": { "markdown": true, "html": true },
"panel": {
"ranges_version": "0.1.0",
"categories": [
{
"key": "metabolic",
"name": "Blood Sugar & Metabolic Health",
"rows": [
{
"key": "hba1c",
"display_name": "Hemoglobin A1c",
"value": 5.2,
"unit": "%",
"reference_range": { "lo": 4, "hi": 5.4 },
"status": "Optimal",
"source": "measured",
"lab_range": { "lo": 4, "hi": 5.6 },
"lab_range_unit": "%",
"collected_at": "2026-09-01"
}
]
}
]
},
"unmapped_biomarkers": [],
"regenerations": 0,
"credits": { "report": "12", "visual": "0" }
}
}
result.output_0 is the member-facing report in Markdown. That is the
deliverable; everything else is metadata for your review queue.
result.Visual_Report is the same report as a standalone HTML document,
and outputs.html is true. It is rendered in code from the validated
Markdown — not generated by a model — so it is byte-deterministic, carries
exactly the words of output_0 and nothing else, and adds no time or cost to
the run. It is a complete page: inline stylesheet, no external fonts, scripts
or network calls, print-ready (Letter, @page margins, tables never split
mid-row) so you can show it directly, drop it into your review queue, or hand
it to a PDF renderer as-is.
Structure of the HTML, should you want to hook into it:
<header class="report-header">— title and the member lines.- One
<section class="section" id="…">per fixed section:your-snapshot, thensection-i…section-xii. Deep-link with#section-iii. - Section I tables carry the four fixed columns; the Status cell has a class
you can style —
status-optimal,status-suboptimal,status-out-of-range,status-not-classified. - Colours and type live in one
:rootblock at the top of the stylesheet. If you send us your brand tokens we will apply them there; nothing else changes.
If you would rather not parse Markdown or HTML for the numbers, don't:
result.panel carries every biomarker as structured JSON — category, display
name, value, unit, reference range, status and whether it was measured or
calculated. The Section I tables in both formats are rendered from exactly that
object, so the three can never disagree.
Failed:
{
"status": "failed",
"completed": false,
"error": "lab_extraction_failed",
"error_category": "lab_extraction_failed"
}
Unknown or expired id:
{ "statusCode": 404, "error": "job_not_found", "message": "No job with that id..." }
2.4 Retrieve stored artifacts#
GET /api/reports/{taskId}
Returns output_0.md, Visual_Report.html and meta.json with signed URLs
valid for 1 hour. meta.json holds the panel,
validation, versions and timings — no member name and no free-text input.
3. Polling guidance#
- Poll every 15–30 seconds.
- Typical completion: 6–10 minutes.
- Run deadline: 12 minutes — a run exceeding it fails with
error_category: "deadline_exceeded". - In-flight work is not resumed or automatically requeued after a worker restart. Age-based maintenance marks unfinished orphaned jobs failed once they exceed the deadline plus one minute. With an available service and healthy database, the default transition occurs about 13–14 minutes after job creation; until then a lost job can still report running and occupy a concurrency slot. An outage can delay this transition.
- Stop automatic polling after 15 minutes and investigate the recorded status. Retry network failures with the same idempotency key. Use a new key for a deliberate rerun only after the original job is terminal; do not assume a polling timeout means no report was generated.
- Jobs are retained 7 days, then return
404. - A
404means the job is gone, not pending. Do not keep polling it.
Do not use POST /v1/biomarker/run — the synchronous endpoint is not exposed
here, and would exceed the HTTP timeout anyway.
4. Limits#
| Limit | Value | Response when exceeded |
|---|---|---|
Requests per minute, all /api/* |
120 | 429 |
POST /api/pipeline/start per minute |
10 | 429 |
| Concurrent running jobs | 5 | 429 with {"error":"concurrency_limit","limit":5,"retry_after_seconds":60} and a Retry-After header |
overall_instructions |
120,000 chars | 413 with {"error":"instructions_too_long","limit":120000} |
input_0 |
60,000 chars | 400 |
| Upload size | see /api |
413 |
Idempotency. Send idempotency_key on start. A repeat with the same key
within 24 hours returns the original taskId with status: "existing" instead
of starting a second run. Recommended on every submit — it makes your retries
safe.
The admission decision is atomic within the deployment's client, environment, pipeline and configured instance. After 24 hours the key may start a new job; the earlier job retains its separate seven-day audit record. Use a fresh key when intentionally requesting a new report with changed inputs.
5. How your instructions are used#
overall_instructions is your Part II package. It is passed to the report
generator verbatim and shapes tone, emphasis, priorities and what each section
sets out to achieve. Omitting it uses the account's startup-configured guidance.
A supplied string replaces that default; an explicit empty string clears the
default guidance for that request. The Nosis shell and safety rules still apply.
Precedence — highest first:
- Safety and scope rules (NGM) — no diagnosis, no prescription decisions, no detox or taper instructions, no peptides/hormones/IV protocols, no outcome-timeline promises.
- The fixed shell (NGM) — the 13 sections, their order and headings, the biomarker categories, the table structure, and the approved §X and §XII copy.
- Your guidance (Nosis) — everything else.
Ordinary content or presentation preferences cannot override 1 or 2. Attempts to bypass security or clinical safety rules are rejected by screening, as described below. Authorized guidance can change per request without a deploy.
Constraints:
- Do not instruct the model to rename, reorder, add or remove a section heading.
- Do not supply your own §X or §XII text — that copy is inserted by us verbatim.
- Report structure changes require a template version bump; contact us.
Your instructions are screened in the context of authorized enterprise report
guidance. References to the configured shell, fixed copy, tone, section guidance
or clinical rationale are allowed. Attempts to extract hidden instructions,
disclose private data or bypass server safety rules are rejected before lab
extraction and report generation with error_category: "instructions_rejected".
Member context is screened separately; rejected or malformed screening decisions
fail with error_category: "input_rejected". Screening itself uses a model.
6. Report structure#
output_0 always contains a generated header followed by exactly these
level-2 headings, in this order:
# Your Nosis Blueprint Report (header: Generated / Member / Age / Substance Use Status)
## Your Snapshot
## I. Your Complete Biomarker Panel
## II. Your Results in Context
## III. Your Action Plan
## IV. Your Food and Nutrition Plan
## V. Your Supplement Guide
## VI. Your Exercise and Movement Plan
## VII. Your Sleep Plan
## VIII. Your Nervous System Regulation Plan
## IX. Your Real Strengths
## X. What Happens Next
## XI. Sources and Further Reading
## XII. Important Information About This Report
Section I#
One ### <category> per category that has collected biomarkers, each
followed by a results table then #### What This Means. Categories with no
collected biomarkers are absent entirely — no empty headings, no blank rows.
Category order is fixed: Blood Sugar & Metabolic Health · Cholesterol & Cardiovascular Health · Liver Health · Kidney Function & Electrolytes · Blood & Immune Health (Red Blood Cells / White Blood Cells & Immune Function / Platelets) · Thyroid Health · Hormones & Reproductive Health · Nutrients & Iron Status · Fatty Acid Balance.
Tables are generated by us, not by the model:
| What We Measured | Your Result | Reference Range | Status |
Status vocabulary#
Exactly one of:
Optimal · Suboptimal (low) · Suboptimal (high) · Out of range (low) ·
Out of range (high) · Not classified
Not classified means a reliable classification is unavailable. Reasons
include missing applicable ranges, unconfirmed fasting, censored/non-numeric
results or unsupported units. Where no applicable range is available,
reference_range is null and the displayed range is —. Review the warnings;
the narrative must not invent a good/bad classification.
Reference Range is NGM's target range, not the source laboratory's. The
lab's own interval is returned separately as lab_range for your reconciliation.
These bounds remain in the original laboratory units, identified by
lab_range_unit, even when value and unit have been converted to the panel's
display units. For example, calcium may have value: 10 and unit: "mg/dL"
while lab_range remains { "lo": 2.15, "hi": 2.55 } with
lab_range_unit: "mmol/L". The source interval does not determine Status.
lab_range_unit is present only when lab_range is non-null, and is null if
the source unit is unknown. Older stored reports may omit this field.
Measured rows also include collected_at when the selected source result has
a collection date. When duplicate biomarkers have different dates, this is
the selected latest date. Unknown dates and calculated rows omit the field;
no collection date is inferred for a calculated metric. This audit metadata
does not add columns to the report tables.
Ranges and statuses are deterministic for the same marker, normalized value and unit, applicable age/sex/fasting context, and range-table version. Table v0.1.0 was seeded from existing report-prompt thresholds and conventional adult ranges. It remains unsigned pending clinical approval and must not be treated as a clinically approved production catalogue.
Specific clinical review blocker: vitamin D's seeded target is 60–80 ng/mL.
It can label a conventionally adequate 40 ng/mL Suboptimal (low). This target
requires clinical correction/review and sign-off; it must not become a reason
to raise a healthy member's level or recommend a supplement dose. Template 0.5.6
enforces that interpretation boundary and requires an independent, applicable
member-specific indication for targeted supplement advice. Normal limited panels
also cannot establish overall cardiovascular risk or rule out organ disease.
Calculated metrics#
Computed by us in code when the inputs are present, labelled Calculated (BMI is labelled Platform-derived):
BMI · HOMA-IR · AST/ALT Ratio · FIB-4 · Triglyceride/HDL · Neutrophil-to- Lymphocyte Ratio · Free Androgen Index (women) · Free Testosterone (Vermeulen) · Non-HDL · Total Cholesterol/HDL · Globulin · Albumin/Globulin.
A metric whose required inputs are missing or unusable is absent. Free
Testosterone requires measured total testosterone, SHBG and albumin; albumin is
never assumed. HOMA-IR requires confirmed fasting glucose and insulin.
Calculations are omitted when their inputs have conflicting collection dates.
Relevant omissions return calculation_unavailable warnings for your review
queue. Unknown collection dates require source review.
Measured results take precedence over calculations, including a reported
inequality such as <1. Such results retain their printed value and are not
treated as exact numbers for calculation or status classification. Supported
unit conversions are deterministic, including albumin g/L to g/dL and insulin
mIU/L to µIU/mL.
CBC differentials show absolute counts only; percentage rows are dropped.
7. Validation#
Every report is checked structurally before return. Every output must enter
the Nosis Review Queue for human review; do not publish automatically, including
reports where validation.passed is true. Structural validation is not clinical
approval.
"validation": { "passed": true, "errors": [], "warnings": ["unmapped_biomarkers: CA-125"] }
errors— a structural violation. We regenerate once automatically. If it still fails, the report is returned withpassed: falseand the errors listed. Route those to human review.warnings— do not stop generation. Review them before member delivery; missing inputs or uncertain provenance can require correction or verification.
Warnings you will see:
| Warning | Meaning |
|---|---|
unmapped_biomarkers: ... |
Reported biomarkers outside the Nosis panel. Excluded from tables; still available to the narrative. |
unreadable_values: n |
Values present but not usable as exact numbers. Printed text is retained where available and the row is Not classified. |
unit_mismatch: ... |
Reported in a unit we cannot convert. Not classified. |
duplicate_biomarker: n |
Same biomarker twice; latest collection date kept. |
calculation_unavailable: ... |
A required input is missing, unusable, lacks fasting confirmation, or has a conflicting collection date. No invented calculation is displayed. |
fasting_not_confirmed: ... |
Glucose or insulin lacks explicit fasting provenance. It stays visible without a fasting-only reference range or classification. |
redacted_term: "X" ×n |
A vendor or tooling term was removed from the text. |
third_person_voice: n |
Possible drift out of second person. |
fixed_copy_language_mismatch |
Non-English run; §X and §XII remain English (English-only in v1). |
model_emitted_table |
The model wrote a table in §I; it was stripped and replaced with ours. |
8. Versioning#
Start/status responses and saved report metadata identify the report contract:
| Field | Meaning |
|---|---|
template_id |
nosis-blueprint |
template_version |
Report shell, section intents and fixed copy |
ranges_version |
Reference-range table |
Record these versions with each report. Saved meta.json also includes
job_id, client, environment, pipeline_id, inputs_hash,
configuration_hash (when account configuration is active), generation time,
durations, usage, panel and validation. The effective-input hash covers source
contents, demographics and guidance; the configuration hash identifies the
immutable account settings. Upload and error responses do not all carry this
metadata. Treat these artifacts as health data.
Semver, and they move independently. Changes are logged in
src/clients/nosis/CHANGELOG.md; we will notify you before any bump that
changes report structure.
9. Data handling#
- Uploaded labs and generated reports use deployment-specific storage prefixes. The planned object-retention period is 30 days, subject to agreement and a verified bucket lifecycle rule. On 9 September the current sandbox bucket had no lifecycle rules, so automatic 30-day deletion is not active.
- Immediate deletion:
DELETE /api/files/{key}. meta.jsonomits the member name and free-text inputs, but includes clinical panel values and must be treated as sensitive health data. Hashes do not make reports anonymous. Logs and telemetry also require the agreed access, retention and provider controls before real-member use.- Signed download URLs expire after 1 hour.
- BAA: contact Anant. Production keys are not issued before it is executed.
10. Error reference#
| HTTP | error |
Meaning |
|---|---|---|
| 400 | validation_failed |
Missing or invalid field. fields names them. |
| 400 | no_lab_file |
No file_keys and no inline Other_files. |
| 400 | invalid_overall_instructions |
Not a string. |
| 401 / 403 | — | Missing or invalid Bearer token. |
| 404 | job_not_found |
Unknown or expired taskId. |
| 413 | instructions_too_long |
overall_instructions over 120,000 chars. |
| 429 | concurrency_limit |
More than 5 jobs running. Honour Retry-After. |
| 429 | — | Request-rate limit. |
| 503 | — | Object storage or a required credential is not configured. |
Job-level failures (status: "failed") carry error_category:
input_rejected · instructions_rejected · lab_extraction_failed · deadline_exceeded ·
worker_restarted · artifact_persistence_failed · validation_failed · pipeline_error
input_rejected means member-context screening rejected the request or could not
produce a valid decision. instructions_rejected applies to the separate Nosis
guidance screening. Neither failure proceeds to lab extraction or report generation.
artifact_persistence_failed means the required report artifacts were not
successfully saved; that job is failed even if generation finished.
worker_restarted is the age-based stale-job category. It can indicate a worker
restart, stalled work or a terminal state that could not be saved; it is not proof
of a restart. Work is not resumed from a checkpoint. After confirming this
terminal failure, use a new idempotency key for a deliberate rerun. Reusing the
original key within its 24-hour window returns the original failed job. Do not
start a duplicate solely because polling timed out. Completed-report durability
is separate: completed status, validation and artifact references survive a worker
restart. Schedule deployments with no pending/running jobs where possible.
11. Reference and status#
GET /docson any host is this guide, rendered, with that host's base URL and versions at the top.GET /apiis the OpenAPI reference (Swagger) with the live schemas, the limits and the precedence statement for that environment.GET /healthreturns the service status and the versions stamped on every report. No key needed.
When a reported value cannot be converted and its source omitted the unit, source_unit is an empty string. The displayed raw result has no inferred unit and remains Not classified; do not apply the canonical unit field to that raw value.