API Reference

Base URL: http://localhost:8000

All endpoints return JSON. Errors follow the format:

{"detail": "Error message describing what went wrong"}

GET /api/config

Runtime configuration (non-secret values from .env.local).

Response:

{
  "aws_account_id": "123456789012",
  "aws_region": "us-east-1",
  "sagemaker_role_arn": "arn:aws:iam::123456789012:role/SageMakerRole",
  "training_image_classification": "123456789012.dkr.ecr.us-east-1.amazonaws.com/sm-training-byoc-classification:latest",
  "training_image_segmentation": "123456789012.dkr.ecr.us-east-1.amazonaws.com/sm-training-byoc-segmentation:latest",
  "inference_image_classification": "123456789012.dkr.ecr.us-east-1.amazonaws.com/sm-inference-byoc-classification:latest",
  "inference_image_segmentation": "123456789012.dkr.ecr.us-east-1.amazonaws.com/sm-inference-byoc-segmentation:latest",
  "default_data_s3_uri": "s3://your-bucket/training-data/"
}

GET /health

Health check endpoint.

Response:

{"status": "healthy"}

/api/aws — AWS Credentials & S3 Browsing

GET /api/aws/status

Check whether AWS credentials are configured.

Response:

{"configured": true, "source": "environment"}

source is "environment" if auto-configured from env vars/profiles, or "manual" if set via the /configure endpoint.


POST /api/aws/configure

Manually set AWS credentials.

Request body:

{
  "access_key_id": "AKIA...",
  "secret_access_key": "...",
  "region": "us-east-1"
}

Response:

{"status": "success", "message": "AWS credentials configured successfully"}

Errors: 400 (invalid credentials), 500 (internal error)


GET /api/aws/buckets

List all S3 buckets in the account.

Response:

[
  {"name": "my-bucket", "region": "us-east-1", "creation_date": "2024-01-15T10:30:00Z"}
]

Errors: 400 (credentials not configured), 500 (AWS API error)


GET /api/aws/buckets/{bucket_name}/objects

List objects in an S3 bucket.

Query parameters:

Parameter

Type

Default

Description

prefix

string

""

S3 key prefix to filter objects

Response:

{
  "bucket": "my-bucket",
  "objects": [
    {"key": "data/train/", "size": 0, "last_modified": "2024-01-15T10:30:00Z"},
    {"key": "data/train/image1.dcm", "size": 524288, "last_modified": "2024-01-15T10:31:00Z"}
  ]
}

/api/training — Models, Training Jobs, SageMaker

GET /api/training/models

List available model architectures from all task registries (src/classification/model_def.py and src/segmentation/model_def.py).

Response:

{
  "models": [
    {
      "name": "densenet121",
      "description": "DenseNet-121 pretrained on ImageNet",
      "parameters": "7.0M",
      "input_size": "224x224",
      "pretrained": true,
      "task": "classification",
      "dimension": "2D",
      "source_dir": "src/classification"
    }
  ]
}

POST /api/training/models/upload-code

Upload a .zip file containing custom model code.

Query parameters:

Parameter

Type

Required

Description

model_name

string

yes

Name for the custom model

Request: multipart/form-data with field file (.zip only)

Response:

{
  "model_name": "my_custom_model",
  "source_dir": "data/custom_models/my_custom_model",
  "files": ["model_def.py", "train.py", "requirements.txt"]
}

Notes: Rejects absolute paths and .. traversal in the archive.


POST /api/training/models/import

Import a pre-trained model artifact from S3.

Request body:

{
  "model_name": "spine-classifier-v2",
  "s3_bucket": "my-bucket",
  "s3_key": "models/spine_model.pth",
  "model_format": "pytorch",
  "framework_version": "2.1.1",
  "num_classes": 8
}

Response:

{
  "model_id": "uuid-string",
  "model_name": "spine-classifier-v2",
  "s3_source": "s3://my-bucket/models/spine_model.pth",
  "local_path": "data/models/uuid-string/spine_model.pth",
  "model_format": "pytorch",
  "num_classes": 8,
  "imported_at": "2024-06-15T10:30:00",
  "status": "available"
}

GET /api/training/models/imported

List all imported models.

Response:

{"models": [...]}

GET /api/training/models/imported/{model_id}

Get details of a specific imported model.

Response: Single model object or 404.


POST /api/training/start

Start a local training job.

Query parameters:

Parameter

Type

Required

Description

dataset_path

string

yes

Path to the training dataset

Request body:

{
  "model_type": "densenet121",
  "epochs": 10,
  "batch_size": 32,
  "learning_rate": 0.001,
  "optimizer": "adam",
  "loss_function": "cross_entropy"
}

model_type enum: resnet50, vgg16, efficientnet, DenseNet121, ViT, SegResNet, custom

Response:

{
  "job_id": "uuid-string",
  "status": "pending",
  "model_type": "densenet121",
  "created_at": "2024-06-15T10:30:00",
  "completed_at": null,
  "metrics": null
}

GET /api/training/jobs

List all local training jobs.

Response: Array of TrainingJob objects.


GET /api/training/jobs/{job_id}

Get a specific local training job.

Response: TrainingJob object or 404.


GET /api/training/jobs/{job_id}/metrics

Get training metrics (MLflow/TensorBoard integration).

Response:

{
  "job_id": "uuid-string",
  "metrics": {
    "epoch": 5,
    "train_loss": 0.234,
    "val_loss": 0.267,
    "train_accuracy": 0.892,
    "val_accuracy": 0.876,
    "learning_rate": 0.001,
    "tensorboard_url": "http://localhost:6006/#scalars&run=uuid-string",
    "mlflow_url": "http://localhost:5000/#/experiments/1/runs/uuid-string"
  }
}

POST /api/training/jobs/{job_id}/stop

Stop a running local training job.

Response:

{"job_id": "uuid-string", "status": "stopped"}

POST /api/training/sagemaker/validate

Validate data, credentials, IAM role, and image URI before launching a training job.

Request body: SageMakerTrainingConfig (same schema as /sagemaker/start)

Response: Validation result object with checks for S3 access, role validity, ECR image accessibility, and dataset structure.


POST /api/training/sagemaker/start

Start a SageMaker BYOC training job.

Request body:

{
  "job_name": "my-training-2024-06-15",
  "model_name": "densenet121",
  "task_type": "classification",
  "dimension": "2D",
  "epochs": 20,
  "batch_size": 16,
  "learning_rate": 0.001,
  "num_classes": 1,
  "val_interval": 1,
  "instance_type": "ml.g5.xlarge",
  "instance_count": 1,
  "image_uri": "123456789012.dkr.ecr.us-east-1.amazonaws.com/sm-training-byoc-classification:latest",
  "data_s3_uri": "s3://<your-bucket-name>/training-data/",
  "role_arn": "arn:aws:iam::123456789012:role/SageMakerRole",
  "source_dir": "src/classification",
  "entry_point": "train.py",
  "mlflow_tracking_uri": "arn:aws:sagemaker:us-east-1:123456789012:mlflow-tracking-server/my-server",
  "output_s3_uri": "s3://<your-bucket-name>/output/"
}

Response:

{
  "job_name": "my-training-2024-06-15",
  "status": "InProgress",
  "message": "SageMaker training job started"
}

GET /api/training/sagemaker/jobs

List all SageMaker training jobs. Active jobs (InProgress, Stopping) are refreshed from AWS automatically.

Query parameters:

Parameter

Type

Default

Description

local_only

bool

false

Skip AWS refresh; return cached state only

Response:

{
  "jobs": [
    {
      "job_name": "my-training-2024-06-15",
      "status": "Completed",
      "model_name": "densenet121",
      "task_type": "classification",
      "instance_type": "ml.g5.xlarge",
      "model_artifacts": "s3://<your-bucket-name>/output/my-training-2024-06-15/output/model.tar.gz",
      "creation_time": "2024-06-15T10:30:00Z",
      "training_end_time": "2024-06-15T11:15:00Z",
      "billable_seconds": 2700,
      "estimated_cost_usd": 3.04,
      "mlflow_tracking_uri": "arn:aws:sagemaker:...",
      "archived": false,
      "comment": "",
      "artifacts_deleted": false,
      "result": null
    }
  ]
}

GET /api/training/sagemaker/jobs/{job_name}/status

Get current status of a SageMaker training job from AWS.

Response:

{
  "job_name": "my-training-2024-06-15",
  "status": "Completed",
  "model_artifacts": "s3://...",
  "billable_seconds": 2700,
  "estimated_cost_usd": 3.04,
  "creation_time": "2024-06-15T10:30:00Z",
  "training_end_time": "2024-06-15T11:15:00Z"
}

POST /api/training/sagemaker/jobs/{job_name}/stop

Stop a running SageMaker training job.

Response:

{"job_name": "my-training-2024-06-15", "status": "Stopping"}

GET /api/training/sagemaker/jobs/{job_name}/result

Fetch result.json from the job’s model.tar.gz. Downloads from S3 on first call; cached thereafter.

Response:

{
  "job_name": "my-training-2024-06-15",
  "result": {
    "model_name": "densenet121",
    "num_classes": 8,
    "final_epoch": 20,
    "train_accuracy": 0.95,
    "val_accuracy": 0.91,
    "best_val_accuracy": 0.92,
    "data_s3_uri": "s3://<your-bucket-name>/data/",
    "task_type": "classification",
    "dimension": "2D",
    "learning_rate": 0.001,
    "batch_size": 16
  }
}

If result.json is absent from the archive, a reconstructed result is returned with "reconstructed": true and accuracy fields set to null.


DELETE /api/training/sagemaker/jobs/{job_name}

Remove a terminal-state job from local tracking. Cannot remove active jobs.

Response:

{"job_name": "my-training-2024-06-15", "removed": true}

Errors: 404 (not found), 400 (job still active)


POST /api/training/sagemaker/jobs/{job_name}/archive

Archive a job (hidden from default list).

Response:

{"job_name": "my-training-2024-06-15", "archived": true}

POST /api/training/sagemaker/jobs/{job_name}/comment

Add or update a free-text comment on a job.

Request body:

{"comment": "Best run so far — 92% val accuracy"}

Response:

{"job_name": "my-training-2024-06-15", "comment": "Best run so far — 92% val accuracy"}

DELETE /api/training/sagemaker/jobs/{job_name}/artifacts

Delete model.tar.gz from S3 for a completed job.

Response:

{"job_name": "my-training-2024-06-15", "deleted_uri": "s3://<your-bucket-name>/output/model.tar.gz"}

POST /api/training/sagemaker/finetune

Start a fine-tuning job from a completed job’s checkpoint.

Request body: Same as /sagemaker/start with these additional fields:

{
  "checkpoint_s3_uri": "s3://<your-bucket-name>/output/previous-job/output/model.tar.gz",
  "fine_tuned_from": "previous-job-name"
}

checkpoint_s3_uri is required for fine-tuning.

Response:

{
  "job_name": "my-finetune-2024-06-16",
  "status": "InProgress",
  "fine_tuned_from": "previous-job-name",
  "message": "Fine-tuning job started"
}

GET /api/training/sagemaker/mlflow-url

Resolve a SageMaker MLflow tracking server ARN to a presigned HTTP URL.

Query parameters:

Parameter

Type

Required

Description

arn

string

yes

Full ARN or server name

Response:

{"url": "https://mlflow-12345.studio.us-east-1.sagemaker.aws/..."}

Presigned URLs expire after 5 minutes. Handles both mlflow-tracking-server/<name> and mlflow-app/<name> (Studio-managed) ARN formats.


POST /api/training/sagemaker/sync

Pull up to 100 training jobs from AWS and merge into local store.

Query parameters:

Parameter

Type

Default

Description

name_contains

string

none

Filter AWS query by job name substring

Response:

{
  "added": ["new-job-1", "new-job-2"],
  "updated": ["existing-job-1"]
}

/api/deployment — SageMaker Endpoint Deployment

POST /api/deployment/deploy

Create a SageMaker endpoint or import/track an existing one.

Request body:

{
  "endpoint_name": "my-classifier-endpoint",
  "model_artifacts": "s3://<your-bucket-name>/output/job/output/model.tar.gz",
  "image_uri": "123456789012.dkr.ecr.us-east-1.amazonaws.com/sm-inference-byoc-classification:latest",
  "role_arn": "arn:aws:iam::123456789012:role/SageMakerRole",
  "instance_type": "ml.m5.xlarge",
  "instance_count": 1,
  "inference_script": "inference.py",
  "environment": {},
  "async_endpoint": false,
  "output_s3_uri": null,
  "max_concurrent": 10,
  "enable_data_capture": false,
  "capture_s3_uri": null,
  "capture_sampling_pct": 100
}

Field

Default

Notes

model_artifacts

—

Omit to import/track an existing endpoint by name only

image_uri

—

Required when deploying a new endpoint

role_arn

—

Required when deploying a new endpoint

async_endpoint

false

Set true for async inference; output_s3_uri required

enable_data_capture

false

Enable capture at creation time

capture_sampling_pct

100

1–100

Response (new endpoint):

{
  "endpoint_name": "my-classifier-endpoint",
  "status": "Creating",
  "model_name": "my-classifier-endpoint-model",
  "endpoint_config_name": "my-classifier-endpoint-config"
}

Response (import existing):

{
  "endpoint_name": "my-classifier-endpoint",
  "status": "InService",
  "imported": true
}

GET /api/deployment/deployments

List all deployments with refreshed status from AWS. Deleted entries are excluded.

Response:

{
  "deployments": [
    {
      "endpoint_name": "my-classifier-endpoint",
      "status": "InService",
      "instance_type": "ml.m5.xlarge",
      "model_artifacts": "s3://...",
      "creation_time": "2024-06-15T12:00:00Z",
      "invocation_url": "https://runtime.sagemaker.us-east-1.amazonaws.com/endpoints/my-classifier-endpoint/invocations"
    }
  ]
}

GET /api/deployment/deployments/{endpoint_name}/status

Get current endpoint status from AWS.

Response:

{
  "endpoint_name": "my-classifier-endpoint",
  "status": "InService",
  "creation_time": "2024-06-15T12:00:00Z"
}

DELETE /api/deployment/deployments/{endpoint_name}

Delete an endpoint, its endpoint config, and SageMaker model. The local record is removed regardless of AWS API success.

Response:

{"endpoint_name": "my-classifier-endpoint", "status": "Deleting"}

POST /api/deployment/invoke-async

Submit an async inference request to a SageMaker async endpoint.

Request body:

{
  "endpoint_name": "my-async-endpoint",
  "input_s3_uri": "s3://<your-bucket-name>/inputs/request.json",
  "output_s3_uri": "s3://<your-bucket-name>/outputs/"
}

Response:

{
  "output_location": "s3://<your-bucket-name>/outputs/uuid.out",
  "inference_id": "uuid-string"
}

POST /api/deployment/sync

Pull endpoints from AWS and merge into local store.

Query parameters:

Parameter

Type

Default

Description

name_contains

string

none

Filter by endpoint name substring

Response:

{
  "added": ["new-endpoint-1"],
  "updated": ["existing-endpoint-1"]
}

/api/inference — Real-time Endpoint Invocation

POST /api/inference/invoke

Invoke a SageMaker real-time endpoint with a JSON payload.

Request body:

{
  "endpoint_name": "my-classifier-endpoint",
  "task_type": "classification",
  "input_type": "s3_uri",
  "input_value": "s3://<your-bucket-name>/images/scan.dcm",
  "output_s3_uri": "s3://<your-bucket-name>/results/"
}

Field

Values

Description

task_type

classification, segmentation

Determines response format

input_type

s3_uri, file_path

How to send the input to the endpoint

output_s3_uri

—

Optional; saves raw response to S3

Response (classification):

{
  "predictions": [[0.1034, 0.1202, 0.1366, 0.0866, 0.1258, 0.1408, 0.1155, 0.1713]],
  "predicted_class": [7],
  "confidence": [0.1713],
  "task_type": "classification",
  "s3_result_path": "s3://<your-bucket-name>/results/my-classifier-endpoint-result.json"
}

Response (segmentation):

{
  "mask_nifti_b64": "<base64-encoded .nii.gz bytes>",
  "shape": [128, 128, 64],
  "voxels_positive": 14823,
  "voxels_total": 1048576,
  "volume_fraction": 0.0141,
  "task_type": "segmentation"
}

POST /api/inference/invoke-local

Invoke an endpoint with raw file bytes uploaded from the browser.

Query parameters:

Parameter

Type

Required

Description

endpoint_name

string

yes

SageMaker endpoint name

task_type

string

no

classification (default) or segmentation

Request body: Raw binary file content (the entire request body is the file).

Response: Same format as /invoke based on task_type.


GET /api/inference/endpoints

List all InService SageMaker endpoints.

Response:

{
  "endpoints": [
    {"name": "my-classifier-endpoint", "status": "InService", "created": "2024-06-15T12:00:00Z"}
  ]
}

/api/evaluation — Endpoint Evaluation via Processing Jobs

POST /api/evaluation/submit

Submit a SageMaker Processing Job to evaluate a deployed endpoint against a labeled test set.

Request body:

{
  "endpoint_name": "my-classifier-endpoint",
  "data_s3_uri": "s3://<your-bucket-name>/test-data/",
  "output_s3_uri": "s3://<your-bucket-name>/eval-results/my-eval",
  "image_uri": "123456789012.dkr.ecr.us-east-1.amazonaws.com/sm-inference-byoc-classification:latest",
  "role_arn": "arn:aws:iam::123456789012:role/SageMakerRole",
  "instance_type": "ml.m5.xlarge",
  "task_type": "classification"
}

task_type: classification or segmentation

Response:

{
  "job_name": "eval-my-classifier-20240615-103000",
  "status": "InProgress",
  "endpoint_name": "my-classifier-endpoint",
  "data_s3_uri": "s3://<your-bucket-name>/test-data/",
  "output_s3_uri": "s3://<your-bucket-name>/eval-results/my-eval",
  "task_type": "classification",
  "created_at": "2024-06-15T10:30:00Z"
}

GET /api/evaluation/jobs

List all evaluation jobs. In-progress jobs are refreshed from AWS.

Response:

{"jobs": [...]}

GET /api/evaluation/jobs/{job_name}

Get status and metrics for a specific evaluation job.

Response: Job record with status, metrics (once completed), and cached result paths.


DELETE /api/evaluation/jobs/{job_name}

Remove a job record and its local cache. Does not delete S3 outputs.

Response:

{"deleted": "eval-my-classifier-20240615-103000"}

POST /api/evaluation/jobs/{job_name}/download-results

Download output files from S3 into the local cache.

Query parameters:

Parameter

Type

Default

Description

plots_only

bool

false

Download only PNG plots (faster)

Response:

{
  "cached": {
    "metrics.json": "/evaluation-results/job-name/metrics.json",
    "confusion_matrix.png": "/evaluation-results/job-name/confusion_matrix.png",
    "roc_auc.png": "/evaluation-results/job-name/roc_auc.png"
  },
  "job_name": "eval-my-classifier-20240615-103000"
}

GET /api/evaluation/jobs/{job_name}/plots

Return local cache URLs for plot files.

Response:

{
  "plots": {
    "confusion_matrix.png": "/evaluation-results/job-name/confusion_matrix.png",
    "roc_auc.png": "/evaluation-results/job-name/roc_auc.png"
  },
  "task_type": "classification",
  "output_s3_uri": "s3://<your-bucket-name>/eval-results/my-eval",
  "source": "cache"
}

Classification plots: confusion_matrix.png, roc_auc.png, subgroup_accuracy.png Segmentation plots: dice_distribution.png


GET /api/evaluation/jobs/{job_name}/subgroup-metrics

Fetch subgroup_metrics.json from the job’s S3 output. Available only if the test data contained DICOM files with demographic tags.

Response: JSON object with per-subgroup accuracy/metrics breakdowns.

Errors: 404 if subgroup_metrics.json not found.


POST /api/evaluation/sync

Pull evaluation processing jobs from AWS and merge into local store.

Query parameters:

Parameter

Type

Default

Description

name_contains

string

none

Filter by job name substring

Response:

{
  "added": ["eval-job-1"],
  "updated": ["eval-job-2"]
}

/api/monitoring — SageMaker Model Monitor

GET /api/monitoring/capture-summary

Read and aggregate the latest captured traffic for an endpoint.

Query parameters:

Parameter

Type

Default

Description

endpoint_name

string

—

Required. Endpoint to analyze

capture_s3_uri

string

—

Required. Root S3 prefix for capture data

max_files

int

20

Maximum .jsonl files to scan

Response:

{
  "class_distribution": {"class_a": 45, "class_b": 32, "class_c": 23},
  "confidence_histogram": [0, 2, 5, 8, 12, 18, 22, 15, 10, 8],
  "avg_confidence": 0.847,
  "recent_records": [
    {
      "time": "2024-06-15T14:30:00Z",
      "predicted_class": "class_a",
      "confidence": 0.92,
      "probabilities": {"class_a": 0.92, "class_b": 0.05, "class_c": 0.03}
    }
  ],
  "total_records": 100,
  "files_scanned": 5
}

Returns a zero-record summary with a descriptive message if no capture files are found.


POST /api/monitoring/data-capture

Enable or update data capture on an existing SageMaker endpoint.

Request body:

{
  "endpoint_name": "my-classifier-endpoint",
  "capture_s3_uri": "s3://<your-bucket-name>/capture-data/",
  "sampling_percentage": 100
}

sampling_percentage: 1–100 (default 100).

Response:

{
  "endpoint_name": "my-classifier-endpoint",
  "status": "Updating",
  "capture_s3_uri": "s3://<your-bucket-name>/capture-data/"
}

SageMaker updates the endpoint in-place (status shows Updating for a few minutes).


POST /api/monitoring/baseline/data-quality

Submit a SageMaker Processing Job to compute data quality baseline statistics and constraints.

Request body:

{
  "baseline_data_s3_uri": "s3://<your-bucket-name>/baseline-data/",
  "output_s3_uri": "s3://<your-bucket-name>/baseline-output/",
  "role_arn": "arn:aws:iam::123456789012:role/SageMakerRole",
  "instance_type": "ml.m5.xlarge",
  "job_name": "dq-baseline-20240615"
}

job_name is optional (auto-generated if omitted).

Response:

{
  "job_name": "dq-baseline-20240615",
  "status": "InProgress",
  "type": "baseline",
  "output_s3_uri": "s3://<your-bucket-name>/baseline-output/",
  "created_at": "2024-06-15T10:30:00Z"
}

POST /api/monitoring/schedules/data-quality

Create a data quality monitoring schedule.

Request body:

{
  "schedule_name": "my-dq-schedule",
  "endpoint_name": "my-classifier-endpoint",
  "baseline_constraints_s3_uri": "s3://<your-bucket-name>/baseline-output/constraints.json",
  "baseline_statistics_s3_uri": "s3://<your-bucket-name>/baseline-output/statistics.json",
  "output_s3_uri": "s3://<your-bucket-name>/monitor-output/",
  "role_arn": "arn:aws:iam::123456789012:role/SageMakerRole",
  "instance_type": "ml.m5.xlarge",
  "schedule_expression": "cron(0 * ? * * *)"
}

Response:

{
  "schedule_name": "my-dq-schedule",
  "endpoint_name": "my-classifier-endpoint",
  "status": "Scheduled",
  "type": "data_quality",
  "schedule_expression": "cron(0 * ? * * *)",
  "created_at": "2024-06-15T10:30:00Z"
}

POST /api/monitoring/schedules/model-quality

Create a model quality monitoring schedule.

Request body:

{
  "schedule_name": "my-mq-schedule",
  "endpoint_name": "my-classifier-endpoint",
  "ground_truth_s3_uri": "s3://<your-bucket-name>/ground-truth/",
  "output_s3_uri": "s3://<your-bucket-name>/mq-output/",
  "role_arn": "arn:aws:iam::123456789012:role/SageMakerRole",
  "instance_type": "ml.m5.xlarge",
  "schedule_expression": "cron(0 * ? * * *)",
  "problem_type": "MulticlassClassification",
  "inference_attribute": "predicted_label",
  "probability_attribute": null,
  "ground_truth_attribute": "label"
}

problem_type: BinaryClassification, MulticlassClassification, or Regression.

Response:

{
  "schedule_name": "my-mq-schedule",
  "endpoint_name": "my-classifier-endpoint",
  "status": "Scheduled",
  "type": "model_quality",
  "created_at": "2024-06-15T10:30:00Z"
}

GET /api/monitoring/schedules

List all monitoring schedules (newest first).

Query parameters:

Parameter

Type

Default

Description

local_only

bool

false

Skip AWS refresh

Response:

{"schedules": [...]}

GET /api/monitoring/baselines

List all baseline jobs.

Query parameters:

Parameter

Type

Default

Description

local_only

bool

false

Skip AWS refresh for in-progress baselines

Response:

{"baselines": [...]}

GET /api/monitoring/schedules/{schedule_name}

Get status and latest execution summary for a monitoring schedule.

Response:

{
  "schedule_name": "my-dq-schedule",
  "status": "Scheduled",
  "last_execution_status": "Completed",
  "last_execution_time": "2024-06-15T14:00:00Z",
  "processing_job_arn": "arn:aws:sagemaker:...",
  "failure_reason": null
}

DELETE /api/monitoring/schedules/{schedule_name}

Stop and delete a monitoring schedule from AWS and remove from local store.

Response:

{"deleted": "my-dq-schedule"}

DELETE /api/monitoring/baselines/{job_name}

Remove a baseline job record from local tracking.

Response:

{"deleted": "dq-baseline-20240615"}

/api/fairness — Demographic Analysis

POST /api/fairness/scan

Scan DICOM files under an S3 prefix and extract demographic distributions for bias auditing.

Request body:

{
  "s3_uri": "s3://<your-bucket-name>/dicom-data/",
  "max_files": 200
}

Response:

{
  "total_found": 200,
  "total_scanned": 195,
  "errors": 5,
  "distributions": {
    "PatientSex": {"M": 98, "F": 92, "": 5},
    "Modality": {"CR": 150, "DX": 45},
    "BodyPartExamined": {"SPINE": 120, "CHEST": 75}
  },
  "age_buckets": {
    "0-17": 12,
    "18-29": 35,
    "30-44": 52,
    "45-59": 48,
    "60-74": 33,
    "75+": 15
  },
  "missing_rates": {
    "PatientSex": 2.6,
    "PatientAge": 5.1,
    "EthnicGroup": 85.0,
    "PatientRace": 90.0
  },
  "sample": [
    {
      "file": "patient001/image.dcm",
      "PatientSex": "M",
      "PatientAge": "045Y",
      "Modality": "CR"
    }
  ]
}

Extracts: PatientSex, PatientAge, EthnicGroup, PatientRace, Modality, BodyPartExamined. Age strings (045Y, 6M, 2W) are normalized to integer years and bucketed. Sample is capped at 50 rows.


/api/report — Paper / Report Generation

GET /api/report/jobs

List completed training and evaluation jobs available for report generation.

Response:

{
  "training_jobs": [
    {"job_name": "my-training-2024-06-15", "status": "Completed", "model_name": "densenet121"}
  ],
  "evaluation_jobs": [
    {"job_name": "eval-my-classifier-20240615", "status": "Completed", "endpoint_name": "my-endpoint"}
  ]
}

Returns only non-archived, Completed training jobs and Completed evaluation jobs.


POST /api/report/generate

Generate structured academic paper sections from selected jobs.

Request body:

{
  "title": "Spine X-ray Classification Using DenseNet-121",
  "training_job_names": ["my-training-2024-06-15"],
  "evaluation_job_names": ["eval-my-classifier-20240615"],
  "sections": ["abstract", "methods", "results", "discussion"],
  "include_fairness": true
}

Response:

{
  "title": "Spine X-ray Classification Using DenseNet-121",
  "sections": {
    "abstract": "This study presents a deep learning approach...",
    "methods": "We trained a DenseNet-121 model...",
    "results": "The model achieved 92% validation accuracy...",
    "discussion": "Our results demonstrate..."
  }
}