API documentation

MAIND PATH™ platform API · version v1 · base URL https://ai.histopathology.cloud/api · the taxonomy on this page is read live from the platform database

1. Overview

The platform receives whole-slide images (WSI) from outside sources such as the GDC/TCGA archive, GTEx and direct uploads. It files each slide under a controlled vocabulary, checks the file, cuts it into patches, extracts features on GPU servers, and trains or runs diagnosis models on those features.

The API has two audiences:

  • Systems that label slides before sending them in. They read the taxonomy (/api/v1/taxonomy…) and use /resolve to check that a label will be accepted.
  • GPU workers (RunPod feature-extraction, CLAM training and inference servers). The platform sends them jobs, and they report back through the callback endpoints.
Intake→Classification→Storage (Drive)→ Verification→Patch extraction→Feature extraction→ Training / Diagnosis

All responses are JSON. Send Accept: application/json so that validation errors come back as JSON instead of a redirect. Timestamps are ISO-8601.

2. Authentication

Every endpoint under /api/v1 requires a server API key. Keys belong to server records (admin → Settings → Servers). Only keys on active servers are accepted. Send the key in either header:

Authorization: Bearer <api_key>
X-API-Key: <api_key>

Keys are compared in constant time. The server that owns the key is recorded against the calls it makes; for example, a feature-extraction report is stamped with the reporting server.

StatusBodyMeaning
401{"success":false,"message":"Missing Authorization Bearer token."}No key was sent.
403{"success":false,"message":"Invalid API key."}The key is unknown, or its server is inactive.

GET /api/health is the only endpoint that works without a key. Use it to test connectivity.

3. The classification tree

Every slide is filed under a three-level tree. The third level can nest further:

Organ→Category (clinical group)→Disease→finer disease … (up to 5 disease levels)
LevelTableWhat it isIdentity rule
Organorgans The anatomical site; the root of the tree. Organs are curated by an administrator and only ever selected elsewhere, never typed in, so a disease cannot end up under the wrong site. Name is unique.
Categorycategories A clinical group inside one organ, for example Tumor or Normal. Because the group belongs to its organ, "Tumor" of the breast and "Tumor" of the lung are two separate groups. UNIQUE(organ_id, label_en)
Diseasedisease_subtypes A disease entity inside a category. A disease can hold finer diseases through parent_id; for example, Malignant can be refined into IDC and ILC. UNIQUE(organ_id, name) at every depth: within one organ, a disease name identifies exactly one clinical entity.

Rules the platform enforces

  • The leaf rule. A slide must be labelled with the most specific disease available. If a disease has finer diseases under it, it cannot be chosen. Detail that was never captured cannot be recovered later. The error names the choices, for example: "Malignant" is refined further — pick one of: IDC, ILC.
  • Organ boundary. A category belongs to one organ. A disease takes its organ_id from its category and never sets it on its own. If a category is moved to another organ, its diseases move with it. The move is refused if the category already has slides, or if one of its disease names already exists in the destination organ.
  • Depth limit. Diseases nest at most 5 levels deep, where a root disease is depth 1.
  • Deletion guards. The platform refuses to delete an organ, category, disease or stain that slides still use. It also refuses to delete a category that still has diseases, or a disease that still has children.
  • Renames carry through. Renaming a disease rewrites the denormalised samples.disease_subtype text on every slide filed under it.
  • Inactive rows stay in the tree so that historical slides keep their labels, but they are hidden from pickers. /resolve accepts an inactive row and adds a warning.

Each row has a qualified name that reads as a path, for example Breast › Tumor › Malignant › IDC. The /resolve endpoint returns this path.

4. Organs, categories and diseases (live)

This is the current tree for active organs, generated from the database when the page loads. GET /api/v1/taxonomy returns the same data as JSON. The number after each name is its id, which the API accepts in place of the name.

Organ Category Disease — selectable Disease — refined further
  • Brain#4
    • tumor#5
      • malignant #13 refined further — not selectable
        • GBM #14
        • LGG #15
  • Breast#1
    • benign#4
      • Pathological Benign (PB) #7
    • normal#1
      No diseases yet. Slides are filed at group level.
    • tumor#2
      • malignant #2 refined further — not selectable
        • IDC #12
        • ILC #10
  • Lung#2
    • tumor#6
      • malignant #16 refined further — not selectable
        • LUAD #17
        • LUSC #18
  • Prostate#12
    • tumor#7
      • malignant #19 refined further — not selectable
        • PRAD #20

Organs with no categories yet

These organs exist and can be chosen, but no clinical groups are defined under them yet, so a slide cannot be filed against them until an administrator adds one:

Adrenal gland #18   Bladder #11   Bowel #7   Cervix #15   Eye #23   Head & Neck #16   Kidney #3   Liver #5   Lymph #17   Ovary #13   Pancreas #8   Pleura #22   Skin #9   Soft tissue #21   Stomach #6   Testis #20   Thymus #19   Thyroid #10   Uterus #14

5. Stains

The stain says how the tissue was prepared. It is recorded next to the tree, not inside it. A stain can be matched by id, by abbreviation or by full name, ignoring case. For immunohistochemistry stains, the marker column names the target protein.

IDAbbreviationNameTypeMarker
1 H&E Hematoxylin & Eosin Routine —
2 MT Masson's Trichrome Special —
3 PAS Periodic Acid-Schiff Special —
4 PAS-D Periodic Acid-Schiff with Diastase Special —
5 AB Alcian Blue Special —
6 CR Congo Red Special —
7 Reticulin Silver (Reticulin) Stain Special —
8 GMS Gomori Methenamine Silver Special —
9 ZN Ziehl-Neelsen (AFB) Special —
10 ORO Oil Red O Special —
11 Movat Movat Pentachrome Special —
12 IHC-ER Immunohistochemistry — ER Immunohistochemistry (IHC) ER
13 IHC-PR Immunohistochemistry — PR Immunohistochemistry (IHC) PR
14 IHC-HER2 Immunohistochemistry — HER2 Immunohistochemistry (IHC) HER2
15 IHC-Ki67 Immunohistochemistry — Ki67 Immunohistochemistry (IHC) Ki67
16 IHC-p53 Immunohistochemistry — p53 Immunohistochemistry (IHC) p53
17 IHC-PDL1 Immunohistochemistry — PD-L1 Immunohistochemistry (IHC) PD-L1
18 IHC-CD3 Immunohistochemistry — CD3 Immunohistochemistry (IHC) CD3
19 IHC-CD20 Immunohistochemistry — CD20 Immunohistochemistry (IHC) CD20
20 IHC-TTF1 Immunohistochemistry — TTF-1 Immunohistochemistry (IHC) TTF-1
21 IHC-EGFR Immunohistochemistry — EGFR Immunohistochemistry (IHC) EGFR
22 FISH Fluorescence In-Situ Hybridisation In-Situ Hybridisation (ISH) —
23 CISH Chromogenic In-Situ Hybridisation In-Situ Hybridisation (ISH) —
24 Pap Papanicolaou Cytology —
25 Giemsa Giemsa Cytology —
26 DQ Diff-Quik Cytology —

Allowed types: routine, special, IHC, ISH, fluorescent, cytology, other. Names and abbreviations are unique.

How a slide's stain is set. A stain chosen at upload is kept. Otherwise:

  • Slides from TCGA and GTEx projects are assumed to be H&E during verification.
  • If the slide file names a stain, verification reads it with OpenSlide. A stain name the platform has never seen is added automatically as a routine stain, so it should be reviewed afterwards.

6. Scan and processing settings

These settings decide how a slide is processed. They also decide which models can read its features: a model only accepts features made with the same patch size, magnification and feature extractor it was trained on. GET /api/v1/taxonomy/reference returns all three tables below.

Magnifications

IDLabelValueFolder nameActive
1x1010×10xyes
2x2020×20xyes
3x4040×40xyes

Patch sizes

IDPatchOverlapWSI levelActive
1224 × 224 px0 px0yes
2256 × 256 px0 px0yes
4256 × 256 px64 px0yes
3512 × 512 px0 px0yes

Data sources

IDNameFull name
3BRACSIstituto Nazionale Tumori IRCCS - Fondazione Pascale
2GTExGenotype-Tissue Expression
1TCGA-BRCAThe Cancer Genome Atlas - Breast Invasive Carcinoma
4TCGA-GBMThe Cancer Genome Atlas - Glioblastoma Multiforme
5TCGA-LGGThe Cancer Genome Atlas - Brain Lower Grade Glioma
6TCGA-LUADThe Cancer Genome Atlas - Lung Adenocarcinoma
7TCGA-LUSCThe Cancer Genome Atlas - Lung Squamous Cell Carcinoma
8TCGA-PRADThe Cancer Genome Atlas - Prostate Adenocarcinoma

7. How incoming slides are classified

Slides enter the platform in several ways. They do not all carry the same information, so the table below shows which part of the classification each one sets. Every path is idempotent: each slide is identified by a natural key, so running an import again updates rows instead of duplicating them.

Entry pointIdentified bySets organ / category / disease?Notes
GDC manifest TSV
admin → Imports
file_id (GDC UUID) No Creates or updates slide rows with file name, md5, size, state and data source. The barcode is read from the file name.
GDC metadata.cart.*.json file_id; case by GDC case UUID No Adds entity ids, format and access level, and links each slide to its case.
GDC clinical.cart.*.json, clinical CSV, cohort JSON Case UUID; slides matched by file name, then file_id No Writes the patient's clinical record. Only links to slides that already exist; it never creates slides.
php artisan tcga:import-slides file_id Yes, all of it Organ, category, disease and data source are named on the command line (--organ=Breast --category=tumor --subtype=IDC --source=TCGA-BRCA). The command refuses to run if any of them does not exist. It downloads with gdc-client, checks size and md5, uploads to Drive, then writes the row. The stain is the first stain row, H&E.
php artisan gtex:import-manifest GTEx donor id Case organ only The tissue "Breast - Mammary Tissue" becomes organ Breast on the case, taken from the text before the first dash. Writes demographics and the Hardy death scale. Only donors with a matching slide are imported.
Manual upload
admin → Samples
file_name / Drive id / GDC folder UUID Yes, chosen in the form Organ is required. The category must belong to that organ. The disease must belong to that organ and pass the leaf rule.
AI workflow intake
admin → AI workflow
varies Fixed to Breast › tumor, TCGA-BRCA Built for the IDC vs ILC model, so the organ, category and source are fixed.

Before sending a slide in from an outside system, call GET /api/v1/taxonomy/resolve with the organ, category, disease and stain you plan to use. If it returns 200, the label will be accepted. If it returns 422, the errors array says exactly which part is wrong and what the valid choices are.

Linking a slide to its patient case

A slide is linked to its case by the patient barcode. The platform tries entity_submitter_id first, then the file name.

  • TCGA: the first three barcode segments name the patient (TCGA-AC-A23C-01Z-00-DX1 → TCGA-AC-A23C).
  • GTEx: the first two segments name the donor (GTEX-1117F-0126 → GTEX-1117F).

Linking works in both directions: a case that arrives after its slides picks up those orphan slides. Changing a slide's case, organ, category or disease queues a new verification.

Refining labels from the clinical record

A slide imported with only a coarse label, such as "Malignant", often has its exact diagnosis in the patient's GDC clinical record. php artisan taxonomy:refile-from-clinical moves such slides down to the matching leaf disease. It is a dry run unless --apply is passed. It matches on the ICD-O-3 morphology code, not the free-text diagnosis, because the code is a controlled vocabulary:

ICD-O-3MeaningFiled as
8500/3Infiltrating duct carcinoma, NOSIDC
8520/3Infiltrating lobular carcinoma, NOSILC

A slide is only moved when all of these hold:

  • the target disease exists in the slide's own organ and its own category;
  • the barcode's sample type is a tumour (01–09), not adjacent normal tissue (10–19). The diagnosis belongs to the patient, not to every slide the patient has;
  • the slide currently has no disease, or has a coarser ancestor of the target. A slide already filed under a different leaf is reported as a conflict and never overwritten.

Mixed tumours (8522/3, 8523/3, 8524/3) are distinct entities and need a pathologist's decision, so they are reported and left unchanged.

Verification

Every slide is checked before it can be used. The checks are: can OpenSlide open the file, is the file intact, and can a region be read. The platform also checks that the slide has at least 2 pyramid levels, is at least 1024 px on each side, was scanned at 20× or more, and has a valid microns-per-pixel value. It needs enough tissue (at least 10 % of the area or 50 patches) and a usable label. The clinical fields patient id, case id, project, gender and age at index must be present. A slide is failed if any check fails, needs_clinical_info if only clinical fields are missing, and otherwise passed or pending. Blur, artefact and background scores only produce warnings.

8. Pipeline stages and statuses

StageColumnValuesDriven by
Storagestorage_status not_downloaded · downloading · verifying · available · corrupted · missing · upload_failed Upload to Google Drive
Verificationslide_verifications.verification_status pending · passed · failed · needs_clinical_info Verification job
Qualityquality_status pending · passed · rejected · needs_review · needs_clinical_info Mirrors verification
Patchestiling_status pending · processing · done · failed Patch extraction on the platform host
Featuresfeature_extraction_status pending · processing · completed · failed GPU server → POST /api/v1/feature-extraction/report
Training runtraining_runs.status pending · processing · completed · failed · cancelled CLAM server → /api/v1/training/*
Inference runinference_runs.status pending · processing · completed · failed CLAM server → /api/v1/inference/*

A slide can be used for training only when its features are completed, its quality is passed, its verification is passed, and it is marked usable.

Drive paths follow the tree, so files are laid out by source, organ and group:

samples/{source}/{organ}/{category}/{file_id}/{file_name}
sliced_slides/{magnification}/{source}/{organ}/{category}/{case}/sample_{id}_{px}px/patches.tar.gz
features/{model}/{magnification}/{source}/{organ}/{category}/{case}/sample_{id}_{px}px/

9. Endpoint reference

Health

GET/api/healthno auth

Checks connectivity. Needs no key.

curl https://ai.histopathology.cloud/api/health

{"success":true,"service":"histopathology-management-api","time":"2026-09-24T10:00:00+00:00"}

GET/api/v1/healthAPI key

Checks that your key works, and returns the name of the server the key belongs to.

curl -H "Authorization: Bearer $KEY" https://ai.histopathology.cloud/api/v1/health

{"success":true,"server":"runpod-titan-1","time":"2026-09-24T10:00:00+00:00"}

Taxonomy (read-only)

GET/api/v1/taxonomyAPI key

Returns the full tree: organ → categories → diseases, nested to any depth.

QueryTypeDescription
organname or idReturn only this organ. Unknown organ → 404.
include_inactivebooleanInclude inactive organs, categories and diseases.
curl -H "Authorization: Bearer $KEY" "https://ai.histopathology.cloud/api/v1/taxonomy?organ=Breast"

{
  "success": true,
  "levels": ["organ", "category", "disease"],
  "max_disease_depth": 5,
  "organs": [{
    "id": 1, "name": "Breast", "is_active": true,
    "categories": [{
      "id": 4, "label": "Tumor", "is_active": true,
      "diseases": [{
        "id": 7, "name": "Malignant", "depth": 1, "is_leaf": false, "is_active": true,
        "children": [
          {"id": 11, "name": "IDC", "depth": 2, "is_leaf": true, "is_active": true, "children": []},
          {"id": 12, "name": "ILC", "depth": 2, "is_leaf": true, "is_active": true, "children": []}
        ]
      }]
    }]
  }],
  "unrooted_categories": []
}

is_leaf counts inactive children too, which is how the leaf rule counts them. Only diseases with is_leaf: true can be used to label a slide. unrooted_categories lists groups with no organ; they cannot be used.

GET/api/v1/taxonomy/organsAPI key

Returns a flat list of organs, with the number of categories and diseases under each. Accepts include_inactive.

{"success":true,"organs":[{"id":1,"name":"Breast","is_active":true,"categories_count":2,"diseases_count":3}, …]}

GET/api/v1/taxonomy/stainsAPI key

Returns the stain vocabulary (section 5). Accepts include_inactive.

{"success":true,"stains":[{"id":1,"name":"Hematoxylin & Eosin","abbreviation":"H&E","type":"routine",
  "type_label":"Routine","marker":null,"description":"…","is_active":true}, …]}

GET/api/v1/taxonomy/referenceAPI key

Returns magnifications, patch sizes and data sources (section 6).

{"success":true,
 "magnifications":[{"id":2,"label":"x20","value":20,"folder_name":"20x","is_active":true}, …],
 "patch_sizes":[{"id":1,"size_px":224,"overlap_px":0,"wsi_level":0,"label":"224×224 px","ai_model_id":1,"is_active":true}, …],
 "data_sources":[{"id":1,"name":"TCGA-BRCA","full_name":"…","base_url":null,"is_active":true}, …]}

GET/api/v1/taxonomy/resolveAPI key

Checks a label and turns names into ids. It applies the same rules the platform uses when it files a slide, and it writes nothing. Each parameter accepts a name (ignoring case) or an id.

QueryRequiredMatched against
organyesorgan name
categoryyescategory label, only within that organ
diseasenodisease name within that organ. It must sit in the given category and be a leaf.
stainnoabbreviation, then full name
curl -G -H "Authorization: Bearer $KEY" https://ai.histopathology.cloud/api/v1/taxonomy/resolve \
     --data-urlencode organ=Breast --data-urlencode category=Tumor \
     --data-urlencode disease=IDC  --data-urlencode "stain=H&E"

HTTP 200
{
  "success": true,
  "valid": true,
  "classification": {
    "organ":    {"id": 1, "name": "Breast"},
    "category": {"id": 4, "label": "Tumor"},
    "disease":  {"id": 11, "name": "IDC", "parent_id": 7, "depth": 2, "is_leaf": true, "path": ["Malignant", "IDC"]},
    "stain":    {"id": 1, "name": "Hematoxylin & Eosin", "abbreviation": "H&E"}
  },
  "qualified_name": "Breast › Tumor › Malignant › IDC",
  "errors": [],
  "warnings": []
}

An invalid label returns 422 with valid: false. Whatever did resolve is still returned, and every problem is listed in errors:

GET /api/v1/taxonomy/resolve?organ=Breast&category=Tumor&disease=Malignant

HTTP 422
{"success":true,"valid":false, …,
 "errors":["\"Malignant\" is refined further — pick one of: IDC, ILC."],"warnings":[]}
ErrorCause
organ is required. / category is required.The parameter is missing.
No organ matches "…".The organ is unknown.
Organ "X" has no category "…" — choose one of: …The category exists only in another organ, or not at all.
Organ "X" has no disease "…".The disease name is unknown in that organ.
Disease "D" belongs to category "A", not "B".The disease is in the right organ but a different group.
"D" is refined further — pick one of: …Leaf rule: choose a finer disease.
No stain matches "…".The stain is unknown.

Warnings do not make a label invalid. They report inactive rows, and the case where no disease was given although the category defines diseases, so the slide would be filed at group level only.

Feature extraction callbacks

POST/api/v1/feature-extraction/reportAPI key

The GPU worker reports progress on the job it was given (section 10). Send one call each time the status changes.

FieldTypeNotes
sample_idinteger, requiredMust exist.
statusrequiredprocessing · completed · failed
slide_idstringFile name, for logs.
features_gdrive_path, features_gdrive_folder_id, runpod_output_pathstringWhere the features were written. Stored on completed.
patch_count, failed_patch_countinteger ≥ 0Stored on completed.
model_name, model_versionstringThe version is checked later against model requirements, for example TITAN.
error_messagestring ≤ 2000Stored on failed.
curl -X POST -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" -H "Accept: application/json" \
  https://ai.histopathology.cloud/api/v1/feature-extraction/report -d '{
    "sample_id": 42, "slide_id": "TCGA-AC-A23C-01Z-00-DX1.svs", "status": "completed",
    "features_gdrive_path": "features/TITAN/20x/TCGA-BRCA/Breast/Tumor/…/sample_42_224px",
    "patch_count": 5312, "failed_patch_count": 0, "model_name": "TITAN", "model_version": "TITAN-v1"
  }'

{"success":true,"message":"Status updated.","sample":{"id":42,"status":"completed"}}

GET/api/v1/feature-extraction/jobs/{sample}API key

Returns the platform's current record of a slide's feature extraction. A worker can use it to resume after a restart.

{"success":true,"sample":{"id":42,"slide_id":"TCGA-….svs","feature_extraction_status":"completed",
  "feature_extraction_completed_at":"…","features_gdrive_path":"…","features_gdrive_folder_id":null,
  "features_runpod_path":null,"features_patch_count":5312,"features_failed_patch_count":0,
  "features_model_version":"TITAN-v1","feature_extraction_error":null}}

POST/api/v1/servers/{serverId}/update-urlAPI key

A worker registers its own public URL when it boots. Body: {"api_url":"https://…"}. The URL is always written to the server that owns the key; {serverId} in the path is ignored, so one server can never overwrite another's URL.

Training callbacks

POST/api/v1/training/progressAPI key

Sent once per epoch. Each call is appended to metrics.history, and the run is marked processing.

{"run_id": 17, "epoch": 3, "total_epochs": 50,
 "metrics": {"train_loss": 0.41, "val_loss": 0.47, "val_auc": 0.91}}

POST/api/v1/training/reportAPI key

The final result. status is one of completed · failed · cancelled. If metrics is omitted, the existing metrics are kept.

{"run_id": 17, "status": "completed", "metrics": {…},
 "model_path": "training/CLAM/run_17/best_model.pt", "error": null}

Both training endpoints return {"ok":true}, or 404 {"error":"Run not found"}.

Inference callbacks

POST/api/v1/inference/progressAPI key

Optional progress messages. The first one moves the run from pending to processing.

{"inference_run_id": 5, "stage": "loading_features", "message": "Loading .h5 features from Drive"}

POST/api/v1/inference/reportAPI key

The final result. status is completed or failed. class_label is a label from the training run's label_map.

{"inference_run_id": 5, "status": "completed",
 "prediction": {"class_label": "IDC", "class_index": 0, "confidence": 0.923,
                "probabilities": {"0": 0.923, "1": 0.077}},
 "attention_map_path": "inference/results/run_5/attention.png", "error": null}

Both inference endpoints return {"ok":true}, or 404 {"error":"Inference run not found"}.

10. Calls the platform makes to GPU servers

A GPU worker must serve these endpoints. The platform calls them with the worker's own key as the Bearer token. Every worker must answer GET /health without authentication. The platform calls /health before each dispatch: if it is unhealthy, the job is retried after 60 s; if it is unreachable, after 90 s.

Feature extraction worker

CallPurpose
POST {worker}/jobs/startStart one slide. The worker replies {"status":"accepted","job_id":"…"}, and the platform keeps the job_id.
GET {worker}/jobs/{job_id}Used to resume a stalled operation. queued or running means the job is still alive; any other answer re-queues it.
POST {worker}/jobs/start
{
  "sample_id": 42,
  "slide_id": "TCGA-AC-A23C-01Z-00-DX1.svs",
  "patch_size_px": 224,
  "magnification": "x20", "magnification_folder": "20x",
  "gdrive_input_path": "sliced_slides/20x/TCGA-BRCA/Breast/Tumor/…/sample_42_224px",
  "gdrive_input_archive": "patches.tar.gz",
  "gdrive_output_path": "features/TITAN/20x/TCGA-BRCA/Breast/Tumor/…/sample_42_224px",
  "ai_model": {"id": 1, "name": "TITAN", "slug": "…", "huggingface": "…", "version": "v1",
               "embedding_dim": "768", "input_resolution": "512x512"},
  "callback": {"url": "https://ai.histopathology.cloud/api/v1/feature-extraction/report", "token": "<api_key>", "method": "POST"},
  "dispatched_at": "2026-09-24T10:00:00+00:00"
}

A 401 or 403 from the worker fails the job at once. A 404 or 5xx is retried.

CLAM training and inference server

This server's /health must report "service":"clam_training". This stops a training run from being sent to a feature-extraction worker.

CallBody (main fields)
POST {server}/training/start run_id, feature_model, samples_train / samples_val / samples_test (each [{sample_id, label, training_phase, gdrive_features_path, parent_label?}]), training_params (model_type, epochs, learning_rate, bag_size, n_classes, use_class_weights, seed, dropout, …, plus n_parent_classes, hier_weight, child_to_parent for hierarchical runs), label_map, parent_label_map, gdrive_output_dir
POST {server}/inference/start inference_run_id, model_checkpoint_path, feature_model, slide_features_path, slide_name, n_classes, model_type, label_map, gdrive_output_dir

11. From taxonomy to model classes

A training run turns the tree into class labels, in one of three ways:

label_typeOne class perHierarchy
categorycategory (clinical group)flat
disease_subtypediseaseTwo levels: each disease (fine class) is paired with its category (coarse class). If there is more than one category, the model also learns the coarse level.
disease_typethe case's GDC disease_type textflat

A run is limited to one organ: the organ is the scope, the category is the coarse class, and the disease is the fine class. Labels are fixed when the run is dispatched, so editing a slide afterwards cannot change what the model was trained on. Other rules:

  • Every slide in the run must use the same feature model, patch size and magnification.
  • Slides from one patient never appear in more than one split.
  • Every class needs at least one training slide.
  • Validation needs at least 2 slides covering at least 2 classes.

Deployed diagnosis models

ModelClassesRequires
idc_ilc_titan_v1
IDC vs ILC — TITAN features, linear
IDC ILC feature model: TITAN
patch px: 224
magnification: 20x
min patches: 100

Before a slide is scored, its features are checked against the model's requirements. If they were made with a different feature extractor, patch size or magnification, or have too few patches, the slide is refused and the reason is given. A model's classes are plain names, for example IDC; they are not linked to disease ids in the tree.

12. Errors and troubleshooting

StatusMeaning
200OK.
401 / 403The key is missing, or it is invalid or inactive (section 2).
404The sample, run or organ is unknown.
422Validation failed. Laravel returns {"message":"…","errors":{"field":["…"]}}. For /resolve it means the label cannot be filed (see above).
5xxServer error. Retry with backoff. Callbacks are idempotent, so resending the same final report is safe.
  • You get an HTML page instead of JSON: add Accept: application/json.
  • 403 with a key that used to work: the server may have been marked inactive, or its key was rotated in admin → Settings → Servers.
  • A slide never moves past needs_clinical_info: import the case's clinical record (GDC clinical JSON or CSV) so that gender and age at index are present.
  • A training run is refused for mixed organs: a run covers one organ only. Check that every selected slide's category belongs to the same organ.