{"openapi":"3.0.0","info":{"title":"mlop API","version":"1.0.0","description":"API for mlop - ML experiment tracking platform"},"servers":[{"url":"https://pluto-api.trainy.ai","description":"API Server"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"API Key","description":"API key obtained from the mlop dashboard"}},"schemas":{"CreateRunResponse":{"type":"object","properties":{"runId":{"type":"number","description":"Numeric ID of the created run"},"number":{"type":"number","nullable":true,"description":"Sequential run number within the project (for display IDs)"},"displayId":{"type":"string","nullable":true,"description":"Human-readable display ID (e.g., 'MMP-1')"},"projectName":{"type":"string","description":"Name of the project"},"organizationSlug":{"type":"string","description":"Organization slug"},"url":{"type":"string","description":"URL to view the run"},"resumed":{"type":"boolean","description":"Whether an existing run was resumed (true) or a new run was created (false)"},"forkedFromRunId":{"type":"number","nullable":true,"description":"ID of the parent run this was forked from (null if not forked)"},"forkStep":{"type":"number","nullable":true,"description":"Step at which the fork occurred (null if not forked)"}},"required":["runId","number","displayId","projectName","organizationSlug","url","resumed"]},"Error":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]},"ResumeRunResponse":{"type":"object","properties":{"runId":{"type":"number","description":"Numeric ID of the resumed run"},"number":{"type":"number","nullable":true,"description":"Sequential run number within the project"},"displayId":{"type":"string","nullable":true,"description":"Human-readable display ID (e.g., 'MMP-1')"},"projectName":{"type":"string","description":"Name of the project"},"organizationSlug":{"type":"string","description":"Organization slug"},"url":{"type":"string","description":"URL to view the run"},"resumed":{"type":"boolean","description":"Always true for this endpoint"}},"required":["runId","number","displayId","projectName","organizationSlug","url","resumed"]},"Success":{"type":"object","properties":{"success":{"type":"boolean"}},"required":["success"]},"RunStatusHistoryResponse":{"type":"object","properties":{"runId":{"type":"number"},"events":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"runId":{"type":"number"},"fromStatus":{"type":"string","nullable":true},"toStatus":{"type":"string"},"source":{"type":"string"},"metadata":{"nullable":true},"actorId":{"type":"string","nullable":true},"apiKeyId":{"type":"string","nullable":true},"createdAt":{"type":"string"}},"required":["id","runId","fromStatus","toStatus","source","actorId","apiKeyId","createdAt"]}}},"required":["runId","events"]},"RunListItem":{"type":"array","items":{"type":"object","properties":{"id":{"type":"number","description":"Numeric run ID"},"name":{"type":"string","description":"Run name"},"number":{"type":"number","nullable":true,"description":"Sequential run number within the project"},"displayId":{"type":"string","nullable":true,"description":"Human-readable display ID (e.g., 'MMP-1')"},"status":{"type":"string","description":"Run status"},"tags":{"type":"array","items":{"type":"string"},"description":"Run tags"},"createdAt":{"type":"string","description":"Creation timestamp"},"_flatConfig":{"type":"object","additionalProperties":{"nullable":true},"description":"Flattened config — only present when includeFieldValues=true"},"_flatSystemMetadata":{"type":"object","additionalProperties":{"nullable":true},"description":"Flattened systemMetadata — only present when includeFieldValues=true"}},"required":["id","name","number","displayId","status","tags","createdAt"]}},"ListRunsResponse":{"type":"object","properties":{"runs":{"$ref":"#/components/schemas/RunListItem"},"total":{"type":"number","description":"Total count of matching runs"}},"required":["runs","total"]},"ValidateApiKeyResponse":{"type":"object","properties":{"valid":{"type":"boolean"},"organization":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"}},"required":["id","slug"]},"user":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"]}},"required":["valid","organization","user"]},"RunDetailsResponse":{"type":"object","properties":{"id":{"type":"number"},"name":{"type":"string"},"number":{"type":"number","nullable":true,"description":"Sequential run number within the project"},"displayId":{"type":"string","nullable":true,"description":"Human-readable display ID (e.g., 'MMP-1')"},"status":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"config":{"nullable":true},"systemMetadata":{"nullable":true},"loggerSettings":{"nullable":true},"statusMetadata":{"nullable":true},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"statusUpdated":{"type":"string","nullable":true},"projectName":{"type":"string"},"externalId":{"type":"string","nullable":true},"forkedFromRunId":{"type":"number","nullable":true},"forkStep":{"type":"number","nullable":true},"logNames":{"type":"array","items":{"type":"object","properties":{"logName":{"type":"string"},"logType":{"type":"string"},"logGroup":{"type":"string","nullable":true}},"required":["logName","logType","logGroup"]}}},"required":["id","name","number","displayId","status","tags","createdAt","updatedAt","statusUpdated","projectName","externalId","forkedFromRunId","forkStep","logNames"]},"RunDetailsByDisplayIdResponse":{"type":"object","properties":{"id":{"type":"number"},"name":{"type":"string"},"number":{"type":"number","nullable":true},"displayId":{"type":"string","nullable":true},"status":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"config":{"nullable":true},"systemMetadata":{"nullable":true},"loggerSettings":{"nullable":true},"statusMetadata":{"nullable":true},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"statusUpdated":{"type":"string","nullable":true},"projectName":{"type":"string"},"externalId":{"type":"string","nullable":true},"logNames":{"type":"array","items":{"type":"object","properties":{"logName":{"type":"string"},"logType":{"type":"string"},"logGroup":{"type":"string","nullable":true}},"required":["logName","logType","logGroup"]}}},"required":["id","name","number","displayId","status","tags","createdAt","updatedAt","statusUpdated","projectName","externalId","logNames"]},"QueryLogsResponse":{"type":"object","properties":{"logs":{"type":"array","items":{"type":"object","properties":{"time":{"type":"string"},"logType":{"type":"string"},"lineNumber":{"type":"number"},"message":{"type":"string"},"step":{"type":"number","nullable":true}},"required":["time","logType","lineNumber","message","step"]}},"total":{"type":"number"}},"required":["logs","total"]},"QueryMetricsResponse":{"type":"object","properties":{"metrics":{"type":"array","items":{"type":"object","properties":{"logName":{"type":"string"},"logGroup":{"type":"string"},"time":{"type":"string"},"step":{"type":"number"},"value":{"type":"number"}},"required":["logName","logGroup","time","step","value"]}}},"required":["metrics"]},"QueryRawMetricsResponse":{"type":"object","properties":{"rows":{"type":"array","items":{"type":"object","properties":{"logGroup":{"type":"string"},"step":{"type":"number"},"time":{"type":"string","description":"Server-side write timestamp (ClickHouse DateTime64(3))."},"value":{"type":"number"},"nonFiniteFlags":{"type":"number","description":"Bitmask: bit0=NaN, bit1=+Inf, bit2=-Inf. When non-zero, `value` is 0 and the flag is the source of truth."}},"required":["logGroup","step","time","value","nonFiniteFlags"]}},"truncated":{"type":"boolean","description":"True when the row count hit `limit` and more rows likely exist — narrow stepMin/stepMax to page."}},"required":["rows","truncated"]},"GetFilesResponse":{"type":"object","properties":{"files":{"type":"array","items":{"type":"object","properties":{"fileName":{"type":"string"},"fileType":{"type":"string"},"fileSize":{"type":"number"},"logName":{"type":"string"},"logGroup":{"type":"string"},"time":{"type":"string"},"step":{"type":"number"},"url":{"type":"string"},"annotations":{"type":"string","nullable":true,"description":"Bounding boxes and segmentation masks as a JSON string, when the file carries them. Note that rows with fileType \"mask\" are returned alongside their images and are not filtered out."}},"required":["fileName","fileType","fileSize","logName","logGroup","time","step","url"]}}},"required":["files"]},"ListProjectsResponse":{"type":"object","properties":{"projects":{"type":"array","items":{"type":"object","properties":{"id":{"type":"number"},"name":{"type":"string"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"runCount":{"type":"number"}},"required":["id","name","createdAt","updatedAt","runCount"]}}},"required":["projects"]},"GetStatisticsResponse":{"type":"object","properties":{"runId":{"type":"number"},"runName":{"type":"string"},"projectName":{"type":"string"},"url":{"type":"string","description":"URL to view this run in the UI"},"metrics":{"type":"array","items":{"type":"object","properties":{"logName":{"type":"string"},"logGroup":{"type":"string"},"count":{"type":"number"},"min":{"type":"number"},"max":{"type":"number"},"mean":{"type":"number"},"stddev":{"type":"number"},"last":{"type":"object","properties":{"step":{"type":"number"},"value":{"type":"number"}},"required":["step","value"]}},"required":["logName","logGroup","count","min","max","mean","stddev","last"]}}},"required":["runId","runName","projectName","url","metrics"]},"CompareRunsResponse":{"type":"object","properties":{"projectName":{"type":"string"},"logName":{"type":"string"},"comparisonUrl":{"type":"string","description":"URL to compare these runs in the UI"},"runs":{"type":"array","items":{"type":"object","properties":{"runId":{"type":"number"},"runName":{"type":"string"},"url":{"type":"string","description":"URL to view this run"},"status":{"type":"string"},"config":{"nullable":true},"stats":{"type":"object","nullable":true,"properties":{"count":{"type":"number"},"min":{"type":"number"},"max":{"type":"number"},"mean":{"type":"number"},"final":{"type":"number","description":"Final value (at last step)"}},"required":["count","min","max","mean","final"]}},"required":["runId","runName","url","status","stats"]}}},"required":["projectName","logName","comparisonUrl","runs"]},"ListMetricNamesResponse":{"type":"object","properties":{"projectName":{"type":"string"},"metricNames":{"type":"array","items":{"type":"string"}}},"required":["projectName","metricNames"]},"LeaderboardResponse":{"type":"object","properties":{"projectName":{"type":"string"},"logName":{"type":"string"},"aggregation":{"type":"string"},"direction":{"type":"string"},"runs":{"type":"array","items":{"type":"object","properties":{"rank":{"type":"number","description":"1-based rank position"},"runId":{"type":"number"},"runName":{"type":"string"},"status":{"type":"string"},"url":{"type":"string","description":"URL to view this run in the UI"},"value":{"type":"number","description":"The aggregated metric value used for ranking"},"config":{"nullable":true},"tags":{"type":"array","items":{"type":"string"}},"createdAt":{"type":"string"}},"required":["rank","runId","runName","status","url","value","tags","createdAt"]}},"total":{"type":"number","description":"Total number of runs that have this metric"}},"required":["projectName","logName","aggregation","direction","runs","total"]}},"parameters":{}},"paths":{"/api/runs/create":{"post":{"tags":["Runs"],"summary":"Create a new run","description":"Creates a new run in the specified project. If the project doesn't exist, it will be created. If externalId is provided and a run with that ID already exists, the existing run is returned (Neptune-style resume for multi-node distributed training).","security":[{"bearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"runName":{"type":"string","description":"Name of the run","example":"training-run-1"},"projectName":{"type":"string","description":"Name of the project","example":"my-project"},"externalId":{"type":"string","nullable":true,"minLength":1,"description":"User-provided run ID for multi-node distributed training. If provided and a run with this ID exists, the existing run is returned.","example":"my-ddp-run-2024"},"tags":{"type":"array","nullable":true,"items":{"type":"string"},"description":"Tags for the run","example":["experiment","v1"]},"loggerSettings":{"type":"string","nullable":true,"description":"Logger settings as JSON string"},"systemMetadata":{"type":"string","nullable":true,"description":"System metadata as JSON string"},"config":{"type":"string","nullable":true,"description":"Run configuration as JSON string","example":"{\"lr\": 0.001}"},"createdAt":{"type":"number","nullable":true,"description":"Creation timestamp in milliseconds"},"updatedAt":{"type":"number","nullable":true,"description":"Update timestamp in milliseconds"},"forkRunId":{"type":"number","nullable":true,"description":"ID of the run to fork from. Creates a child run that inherits metrics up to forkStep."},"forkStep":{"type":"number","nullable":true,"description":"Step at which to fork. Required when forkRunId is provided. The child run inherits all metrics up to and including this step."},"inheritConfig":{"type":"boolean","nullable":true,"description":"Whether to inherit config from the parent run (default: true). Only applies when forkRunId is provided."},"inheritTags":{"type":"boolean","nullable":true,"description":"Whether to inherit tags from the parent run (default: false). Only applies when forkRunId is provided."}},"required":["runName","projectName"]}}}},"responses":{"200":{"description":"Run created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateRunResponse"}}}},"400":{"description":"Organization is at limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/runs/resume":{"post":{"tags":["Runs"],"summary":"Resume an existing run","description":"Resumes an existing run, setting its status back to RUNNING. Returns the same response format as create. Use this when you want to log additional data (e.g., evaluation metrics) to a previously completed run. Provide exactly one of: runId (numeric), displayId (e.g., 'MMP-1'), or externalId (user-provided).","security":[{"bearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"runId":{"type":"number","description":"Numeric ID of the run to resume","example":123},"displayId":{"type":"string","description":"Human-readable display ID (e.g., 'MMP-1')","example":"MMP-1"},"externalId":{"type":"string","description":"User-provided external ID","example":"my-training-run-v1"},"projectName":{"type":"string","description":"Project name (required when using externalId, since externalId is scoped to a project)","example":"my-project"}}}}}},"responses":{"200":{"description":"Run resumed successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResumeRunResponse"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Run not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/runs/status/update":{"post":{"tags":["Runs"],"summary":"Update run status","description":"Updates the status of an existing run (e.g., RUNNING, COMPLETED, FAILED).","security":[{"bearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"runId":{"type":"number","description":"Numeric ID of the run","example":123},"status":{"type":"string","enum":["RUNNING","COMPLETED","FAILED","TERMINATED","CANCELLED"],"description":"New status","example":"COMPLETED"},"statusMetadata":{"type":"string","nullable":true,"description":"Status metadata as JSON string"},"loggerSettings":{"type":"string","nullable":true,"description":"Logger settings to merge"},"statusUpdated":{"type":"integer","nullable":true,"description":"Status-change timestamp in epoch milliseconds (backfill/migration). When omitted, the server stamps now(). Migration tooling replaying a finished run should pass the run's original finish time so its Duration reflects the historical run length, not time-since-import.","example":1750000000000}},"required":["runId","status"]}}}},"responses":{"200":{"description":"Status updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Success"}}}},"400":{"description":"Invalid JSON in request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Run not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/runs/status/history":{"get":{"tags":["Runs"],"summary":"Get run status transition history","description":"Returns the ordered list of status transition events for a run (oldest first). Includes implicit creation event, API-driven updates, resumes, and backend-driven stale/threshold transitions.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"number","nullable":true,"description":"Numeric run ID"},"required":false,"name":"runId","in":"query"}],"responses":{"200":{"description":"Status history","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunStatusHistoryResponse"}}}},"404":{"description":"Run not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/runs/logName/add":{"post":{"tags":["Runs"],"summary":"Add log names to a run","description":"Adds new log names (metrics, console logs, etc.) to an existing run.","security":[{"bearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"runId":{"type":"number","description":"Numeric ID of the run"},"logName":{"type":"array","items":{"type":"string"},"description":"Log names to add","example":["train/loss","train/accuracy"]},"logType":{"type":"string","enum":["METRIC","IMAGE","VIDEO","AUDIO","FILE","TEXT","ARTIFACT","HISTOGRAM","TABLE","DATA"],"description":"Type of log","example":"METRIC"}},"required":["runId","logName","logType"]}}}},"responses":{"200":{"description":"Log names added successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Success"}}}},"404":{"description":"Run not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/runs/tags/update":{"post":{"tags":["Runs"],"summary":"Update run tags","description":"Replaces all tags on a run with the provided tags.","security":[{"bearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"runId":{"type":"number","description":"Numeric ID of the run"},"tags":{"type":"array","items":{"type":"string"},"description":"New tags for the run","example":["production","v2"]}},"required":["runId","tags"]}}}},"responses":{"200":{"description":"Tags updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Success"}}}},"404":{"description":"Run not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/runs/notes/update":{"post":{"tags":["Runs"],"summary":"Update run notes","description":"Updates the notes/description on a run. Set to null or empty string to clear.","security":[{"bearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"runId":{"type":"number","description":"Numeric ID of the run"},"notes":{"type":"string","nullable":true,"maxLength":1000,"description":"Notes/description for the run (max 1000 chars). Set to null or empty string to clear."}},"required":["runId","notes"]}}}},"responses":{"200":{"description":"Notes updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Success"}}}},"404":{"description":"Run not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/runs/config/update":{"post":{"tags":["Runs"],"summary":"Update run config","description":"Merges new configuration with existing run config. New keys override existing keys.","security":[{"bearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"runId":{"type":"number","description":"Numeric ID of the run"},"config":{"type":"string","description":"Configuration as JSON string","example":"{\"model\": \"resnet50\"}"}},"required":["runId","config"]}}}},"responses":{"200":{"description":"Config updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Success"}}}},"400":{"description":"Invalid config JSON","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Run not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/runs/list":{"get":{"tags":["Runs"],"summary":"List runs with optional search and tag filtering","description":"Lists runs in a project with optional search using ILIKE substring matching. Supports tag filtering with OR logic (returns runs with ANY of the specified tags).","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","description":"Project name","example":"my-project"},"required":true,"name":"projectName","in":"query"},{"schema":{"type":"string","description":"Search term for run names (substring match)","example":"training"},"required":false,"name":"search","in":"query"},{"schema":{"type":"string","description":"Comma-separated list of tags to filter by (OR logic)","example":"baseline,experiment"},"required":false,"name":"tags","in":"query"},{"schema":{"type":"number","minimum":1,"maximum":200,"default":50,"description":"Maximum number of runs to return","example":50},"required":false,"name":"limit","in":"query"},{"schema":{"type":"boolean","nullable":true,"default":false,"description":"When true, attach _flatConfig and _flatSystemMetadata to each run. Off by default for lean SDK responses.","example":false},"required":false,"name":"includeFieldValues","in":"query"},{"schema":{"type":"string","description":"JSON-encoded array of {source:'config'|'systemMetadata', key:string}. Restricts _flatConfig/_flatSystemMetadata to the listed keys. Empty array = no field values.","example":"[{\"source\":\"config\",\"key\":\"lr\"}]"},"required":false,"name":"visibleColumns","in":"query"}],"responses":{"200":{"description":"List of runs","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListRunsResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/runs/modelGraph/create":{"post":{"tags":["Runs"],"summary":"Create model graph","description":"Creates a model graph visualization for a run, including nodes and edges.","security":[{"bearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"runId":{"type":"number","description":"Numeric ID of the run"},"graph":{"type":"object","properties":{"format":{"type":"string"},"nodes":{"type":"object","additionalProperties":{"type":"object","properties":{"type":{"type":"string"},"depth":{"type":"integer"},"order":{"type":"integer"},"label":{"type":"string"},"node_id":{"type":"string"},"node_type":{"type":"string","enum":["MODULE","UNKNOWN","CONTAINER","IO"]},"inst_id":{"type":"string"},"args":{"type":"array","items":{"nullable":true}},"kwargs":{"type":"object","additionalProperties":{"nullable":true}},"params":{"type":"object","additionalProperties":{"type":"array","items":{"type":"number"}}},"edges":{"type":"array","items":{"type":"array","items":{"type":"string"}}}},"required":["type","depth"]}}},"required":["format","nodes"],"description":"Graph data with nodes and edges"}},"required":["runId","graph"]}}}},"responses":{"200":{"description":"Model graph created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Success"}}}},"404":{"description":"Run not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/runs/auth/validate":{"get":{"tags":["Auth"],"summary":"Validate API key","description":"Validates the API key and returns organization information. Used by MCP clients to verify credentials.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"API key is valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidateApiKeyResponse"}}}},"401":{"description":"Invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/runs/details/{runId}":{"get":{"tags":["Runs"],"summary":"Get full run details","description":"Returns complete run information including config, metadata, tags, status, and available log names.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"number","nullable":true,"description":"Numeric run ID"},"required":false,"name":"runId","in":"path"}],"responses":{"200":{"description":"Run details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunDetailsResponse"}}}},"404":{"description":"Run not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/runs/details/by-display-id/{displayId}":{"get":{"tags":["Runs"],"summary":"Get run details by display ID","description":"Resolves a human-readable display ID (e.g., 'MMP-1') to a run and returns its details.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","description":"Display ID in PREFIX-NUMBER format (e.g., 'MMP-1')"},"required":true,"name":"displayId","in":"path"}],"responses":{"200":{"description":"Run details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunDetailsByDisplayIdResponse"}}}},"400":{"description":"Invalid display ID format","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Run not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/runs/logs":{"get":{"tags":["Runs"],"summary":"Query console logs from a run","description":"Returns console logs (stdout/stderr) from ClickHouse. Supports filtering by log type and pagination.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"number","nullable":true,"description":"Numeric run ID"},"required":false,"name":"runId","in":"query"},{"schema":{"type":"string","description":"Project name"},"required":true,"name":"projectName","in":"query"},{"schema":{"type":"string","enum":["INFO","ERROR","WARNING","DEBUG","PRINT"],"description":"Filter by log type"},"required":false,"name":"logType","in":"query"},{"schema":{"type":"number","minimum":1,"maximum":10000,"default":1000,"description":"Maximum lines to return"},"required":false,"name":"limit","in":"query"},{"schema":{"type":"number","nullable":true,"minimum":0,"default":0,"description":"Number of lines to skip"},"required":false,"name":"offset","in":"query"}],"responses":{"200":{"description":"Console logs","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QueryLogsResponse"}}}}}}},"/api/runs/metrics":{"get":{"tags":["Runs"],"summary":"Query metrics from a run","description":"Returns time-series metrics from ClickHouse. Supports filtering by metric name, group, and step range. Uses reservoir sampling to limit data points.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"number","nullable":true,"description":"Numeric run ID"},"required":false,"name":"runId","in":"query"},{"schema":{"type":"string","description":"Project name"},"required":true,"name":"projectName","in":"query"},{"schema":{"type":"string","description":"Filter by metric name (e.g., train/loss)"},"required":false,"name":"logName","in":"query"},{"schema":{"type":"string","description":"Filter by metric group (e.g., train)"},"required":false,"name":"logGroup","in":"query"},{"schema":{"type":"number","minimum":1,"maximum":10000,"default":2000,"description":"Maximum data points to return"},"required":false,"name":"limit","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Minimum step number (inclusive). Use with stepMax to query a specific range of steps."},"required":false,"name":"stepMin","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Maximum step number (inclusive). Use with stepMin to query a specific range of steps."},"required":false,"name":"stepMax","in":"query"}],"responses":{"200":{"description":"Metrics data","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QueryMetricsResponse"}}}}}}},"/api/runs/metrics/raw":{"get":{"tags":["Runs"],"summary":"Query raw (un-deduped) metric writes from a run","description":"Returns every row written to ClickHouse for the given (run, metric), including duplicates from resumes/re-logs, with the original write `time`. Reads from the un-deduped `mlop_metrics` table — no FINAL, no reservoir sampling. Each row carries a `nonFiniteFlags` bitmask (bit0=NaN, bit1=+Inf, bit2=-Inf); when a flag is set, `value` is `0` and the flag is the source of truth. Use `/metrics` for analysis or chart rendering — this endpoint is for audit and cleanup.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"number","nullable":true,"description":"Numeric run ID"},"required":false,"name":"runId","in":"query"},{"schema":{"type":"string","description":"Project name"},"required":true,"name":"projectName","in":"query"},{"schema":{"type":"string","description":"Metric name (e.g., train/loss). Required — scoping every raw scan to a single metric keeps payloads bounded."},"required":true,"name":"logName","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Minimum step number (inclusive)."},"required":false,"name":"stepMin","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Maximum step number (inclusive)."},"required":false,"name":"stepMax","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":50000,"default":50000,"description":"Maximum rows to return (default and max: 50000). Page by narrowing stepMin/stepMax when more is needed."},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"Raw metric rows","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QueryRawMetricsResponse"}}}}}}},"/api/runs/files":{"get":{"tags":["Runs"],"summary":"Get files and artifacts from a run","description":"Returns file metadata with presigned URLs for downloading. URLs are valid for 5 days.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"number","nullable":true,"description":"Numeric run ID"},"required":false,"name":"runId","in":"query"},{"schema":{"type":"string","description":"Project name"},"required":true,"name":"projectName","in":"query"},{"schema":{"type":"string","description":"Filter by log name"},"required":false,"name":"logName","in":"query"},{"schema":{"type":"string","description":"Filter by log group"},"required":false,"name":"logGroup","in":"query"}],"responses":{"200":{"description":"Files with presigned URLs","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetFilesResponse"}}}}}}},"/api/runs/projects":{"get":{"tags":["Projects"],"summary":"List all projects","description":"Returns all projects in the organization associated with the API key.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"List of projects","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListProjectsResponse"}}}}}}},"/api/runs/statistics":{"get":{"tags":["Runs"],"summary":"Get statistics for a run's metrics","description":"Returns per-metric aggregates (count, min, max, mean, stddev, last) read from the pre-computed summaries table. Raw, no editorializing — interpretation is the caller's job.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"number","nullable":true,"description":"Numeric run ID"},"required":false,"name":"runId","in":"query"},{"schema":{"type":"string","description":"Project name"},"required":true,"name":"projectName","in":"query"},{"schema":{"type":"string","description":"Filter by specific metric name (e.g., train/loss)"},"required":false,"name":"logName","in":"query"},{"schema":{"type":"string","description":"Filter by metric group (e.g., train)"},"required":false,"name":"logGroup","in":"query"}],"responses":{"200":{"description":"Statistics for metrics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetStatisticsResponse"}}}},"404":{"description":"Run not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/runs/compare":{"get":{"tags":["Runs"],"summary":"Compare metrics across multiple runs","description":"Returns per-run aggregates (count, min, max, mean, final) for a single metric across multiple runs, read from the pre-computed summaries table. Raw, no editorializing — interpretation is the caller's job.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","description":"Comma-separated list of run IDs to compare (e.g., '1,2,5')"},"required":true,"name":"runIds","in":"query"},{"schema":{"type":"string","description":"Project name"},"required":true,"name":"projectName","in":"query"},{"schema":{"type":"string","description":"Metric name to compare (e.g., 'train/loss')"},"required":true,"name":"logName","in":"query"}],"responses":{"200":{"description":"Comparison results","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompareRunsResponse"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/runs/metric-names":{"get":{"tags":["Runs"],"summary":"List distinct metric names in a project","description":"Returns distinct metric names from the pre-computed metric summaries table. Useful for discovering available metrics before querying leaderboard or statistics. Optionally filter by a search substring or specific run IDs.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","description":"Project name"},"required":true,"name":"projectName","in":"query"},{"schema":{"type":"string","description":"Substring search to filter metric names (e.g., 'loss')"},"required":false,"name":"search","in":"query"},{"schema":{"type":"string","description":"Comma-separated run IDs to scope the search (e.g., '1,2,5')"},"required":false,"name":"runIds","in":"query"},{"schema":{"type":"number","nullable":true,"default":500,"description":"Maximum number of metric names to return (default: 500)"},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"List of distinct metric names","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListMetricNamesResponse"}}}}}}},"/api/runs/leaderboard":{"get":{"tags":["Runs"],"summary":"Rank runs by a metric","description":"Returns runs ranked by a metric aggregation (MIN, MAX, AVG, LAST, VARIANCE) using pre-computed metric summaries. Much faster than comparing individual runs. Useful for finding the best runs in a project by loss, accuracy, or any other metric.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","description":"Project name"},"required":true,"name":"projectName","in":"query"},{"schema":{"type":"string","description":"Metric name to rank by (e.g., 'train/loss', 'eval/accuracy')"},"required":true,"name":"logName","in":"query"},{"schema":{"type":"string","enum":["MIN","MAX","AVG","LAST","VARIANCE"],"default":"LAST","description":"Aggregation type: MIN, MAX, AVG, LAST, VARIANCE (default: LAST)"},"required":false,"name":"aggregation","in":"query"},{"schema":{"type":"string","enum":["ASC","DESC"],"default":"ASC","description":"Sort direction: ASC (lowest first) or DESC (highest first). Default: ASC"},"required":false,"name":"direction","in":"query"},{"schema":{"type":"number","nullable":true,"default":20,"description":"Number of runs to return (default: 20, max: 100)"},"required":false,"name":"limit","in":"query"},{"schema":{"type":"number","nullable":true,"default":0,"description":"Offset for pagination (default: 0)"},"required":false,"name":"offset","in":"query"}],"responses":{"200":{"description":"Ranked list of runs with metric values","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LeaderboardResponse"}}}}}}},"/api/runs/{runId}":{"get":{"tags":["Runs"],"summary":"Get run by ID","description":"Decodes a SQID-encoded run ID and returns the numeric ID.","parameters":[{"schema":{"type":"string","description":"SQID-encoded run ID"},"required":true,"name":"runId","in":"path"}],"responses":{"200":{"description":"Run ID decoded successfully","content":{"application/json":{"schema":{"type":"object","properties":{"runId":{"type":"number","description":"Numeric run ID"}},"required":["runId"]}}}}}}}}}