@eigenpal/cli 0.20.0 → 0.20.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +3 -2
- package/dist/docs-bundle.json +9 -2
- package/package.json +1 -1
package/dist/docs-bundle.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"title": "Eigenpal OpenAPI specification",
|
|
7
7
|
"description": "Complete machine-readable Public API contract.",
|
|
8
8
|
"source": "api",
|
|
9
|
-
"content": "{\n \"openapi\": \"3.1.0\",\n \"info\": {\n \"title\": \"Eigenpal API\",\n \"version\": \"1.0.0\",\n \"description\": \"Public REST API for inspecting automations, starting and monitoring runs, managing files, collecting human reviews, and running evaluations.\",\n \"contact\": {\n \"name\": \"Eigenpal\",\n \"url\": \"https://eigenpal.com\"\n },\n \"license\": {\n \"name\": \"Apache-2.0\",\n \"url\": \"https://www.apache.org/licenses/LICENSE-2.0\"\n }\n },\n \"servers\": [\n {\n \"url\": \"https://api.eigenpal.com\",\n \"description\": \"Production (canonical API hostname)\"\n }\n ],\n \"security\": [\n {\n \"bearerAuth\": []\n }\n ],\n \"tags\": [\n {\n \"name\": \"Metadata\",\n \"description\": \"Authenticate and inspect the current API context.\"\n },\n {\n \"name\": \"Models\",\n \"description\": \"List text, vision, and OCR models configured for the current tenant environment. This is a catalog inventory, not a live provider health probe.\"\n },\n {\n \"name\": \"Automations\",\n \"description\": \"Inspect runnable workflow and agent automations, their versions, triggers, and source sync state. Move YAML workflows between folders and delete automations.\"\n },\n {\n \"name\": \"Folders\",\n \"description\": \"Create and organize workflow and template folders. Deleting a folder unfiles contained workflows or templates and does not delete them.\"\n },\n {\n \"name\": \"Runs\",\n \"description\": \"Start, monitor, retry, review, and debug automation runs, including artifacts.\"\n },\n {\n \"name\": \"Reviews\",\n \"description\": \"Record human review verdicts, manage corrected outputs, and monitor review health.\"\n },\n {\n \"name\": \"Files\",\n \"description\": \"Upload reusable files for later run or dataset use.\"\n },\n {\n \"name\": \"Templates\",\n \"description\": \"Upload, inspect, version, download, and delete tenant-scoped DOCX and XLSX templates.\"\n },\n {\n \"name\": \"Email servers\",\n \"description\": \"Create and manage outbound email servers for workflow mail. Secrets are encrypted at rest and never returned.\"\n },\n {\n \"name\": \"Evaluation\",\n \"description\": \"Manage datasets, examples, evaluators, experiment batches, evaluator scores, and run promotion workflows.\"\n }\n ],\n \"paths\": {\n \"/v1/auth/check\": {\n \"get\": {\n \"operationId\": \"auth.check\",\n \"summary\": \"Check API key identity\",\n \"description\": \"Return the tenant, user, API key, and scope represented by the current API key.\",\n \"tags\": [\n \"Metadata\"\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Authenticated identity\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/AuthCheckResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations\": {\n \"get\": {\n \"operationId\": \"automations.list\",\n \"summary\": \"List automations\",\n \"description\": \"Returns workflows and agents through one runnable automation collection. Use `type` to narrow to workflows or agents, `search` to find automations by slug, name, or description, and `folderId` to list YAML workflows in a folder (`null` for root).\",\n \"tags\": [\n \"Automations\"\n ],\n \"parameters\": [\n {\n \"in\": \"query\",\n \"name\": \"search\",\n \"schema\": {\n \"description\": \"Substring match against slug, name, or description\",\n \"type\": \"string\"\n },\n \"description\": \"Substring match against slug, name, or description\"\n },\n {\n \"in\": \"query\",\n \"name\": \"type\",\n \"schema\": {\n \"description\": \"Filter by implementation type\",\n \"type\": \"string\",\n \"enum\": [\n \"workflow\",\n \"agent\"\n ]\n },\n \"description\": \"Filter by implementation type\"\n },\n {\n \"in\": \"query\",\n \"name\": \"folderId\",\n \"schema\": {\n \"description\": \"Filter YAML workflows by folder. A folder id matches that folder; `null` matches unfiled workflows at root. Agent automations have no folders, so this filter excludes them. Cannot be combined with `type=agent`.\",\n \"type\": \"string\"\n },\n \"description\": \"Filter YAML workflows by folder. A folder id matches that folder; `null` matches unfiled workflows at root. Agent automations have no folders, so this filter excludes them. Cannot be combined with `type=agent`.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"limit\",\n \"schema\": {\n \"description\": \"Maximum number of automations to return.\",\n \"type\": \"integer\",\n \"minimum\": 1,\n \"maximum\": 100\n },\n \"description\": \"Maximum number of automations to return.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"offset\",\n \"schema\": {\n \"description\": \"Zero-based offset for paging through automations.\",\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 9007199254740991\n },\n \"description\": \"Zero-based offset for paging through automations.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Page of runnable workflow and agent automations.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ListAutomationsResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}\": {\n \"get\": {\n \"operationId\": \"automations.get\",\n \"summary\": \"Get automation\",\n \"description\": \"Get one runnable workflow or agent automation by id or typed alias.\",\n \"tags\": [\n \"Automations\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Workflow id, agent id, or typed alias like workflows.slug / agents.slug\"\n },\n \"required\": true,\n \"description\": \"Workflow id, agent id, or typed alias like workflows.slug / agents.slug\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Automation\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/AutomationDetail\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"patch\": {\n \"operationId\": \"automations.update\",\n \"summary\": \"Move workflow automation\",\n \"description\": \"Move a YAML workflow between organizing folders. `folderPath` auto-creates missing workflow folders; empty or `/` files the workflow at root. Agent automations have no database folder model and are rejected. Identifiers match GET (workflow id, automation id, or `workflows.<slug>`).\",\n \"tags\": [\n \"Automations\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Workflow id, agent id, or typed alias like workflows.slug / agents.slug\"\n },\n \"required\": true,\n \"description\": \"Workflow id, agent id, or typed alias like workflows.slug / agents.slug\"\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/UpdateAutomationRequest\"\n }\n }\n }\n },\n \"responses\": {\n \"200\": {\n \"description\": \"Updated automation\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/AutomationDetail\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"delete\": {\n \"operationId\": \"automations.delete\",\n \"summary\": \"Delete automation\",\n \"description\": \"Delete a workflow or agent automation using the same cleanup as the dashboard. Workflows archive the automations registry parent and keep execution history. Agents delete the agent row, archive the registry parent, and best-effort-delete agent storage. Identifiers match GET.\",\n \"tags\": [\n \"Automations\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Workflow id, agent id, or typed alias like workflows.slug / agents.slug\"\n },\n \"required\": true,\n \"description\": \"Workflow id, agent id, or typed alias like workflows.slug / agents.slug\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Automation deleted\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DeleteAutomationResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}/dataset-review-requests\": {\n \"get\": {\n \"operationId\": \"automations.datasetReviewRequests.list\",\n \"summary\": \"List dataset review requests\",\n \"description\": \"List dataset review requests for one automation, including per-request progress.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias, such as `workflows.slug` or `agents.slug`.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias, such as `workflows.slug` or `agents.slug`.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"status\",\n \"schema\": {\n \"description\": \"Optional comma-separated review statuses to filter by.\",\n \"type\": \"string\"\n },\n \"description\": \"Optional comma-separated review statuses to filter by.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"limit\",\n \"schema\": {\n \"type\": \"integer\",\n \"minimum\": 1,\n \"maximum\": 100\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"offset\",\n \"schema\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 9007199254740991\n }\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Page of dataset review requests.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DatasetReviewRequestList\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"post\": {\n \"operationId\": \"automations.datasetReviewRequests.create\",\n \"summary\": \"Create dataset review request\",\n \"description\": \"Snapshot selected dataset examples into a review request. Include instructions, focusFields to highlight, and ignoredFields for paths reviewers can skip. Optional itemNotes become commented events on those examples.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias, such as `workflows.slug` or `agents.slug`.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias, such as `workflows.slug` or `agents.slug`.\"\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/CreateDatasetReviewRequest\"\n }\n }\n }\n },\n \"responses\": {\n \"201\": {\n \"description\": \"Created dataset review request.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DatasetReviewDetail\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}/dataset-review-requests/{reviewId}\": {\n \"get\": {\n \"operationId\": \"automations.datasetReviewRequests.get\",\n \"summary\": \"Get dataset review request\",\n \"description\": \"Fetch one dataset review request with snapshotted items, progress, focus fields, ignored fields, and events.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"reviewId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Dataset review request id.\"\n },\n \"required\": true,\n \"description\": \"Dataset review request id.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Dataset review request.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DatasetReviewDetail\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"patch\": {\n \"operationId\": \"automations.datasetReviewRequests.update\",\n \"summary\": \"Update dataset review request\",\n \"description\": \"Update review metadata or lifecycle status while the request is draft, open, or paused. Set status to `closed` when review is finished; dataset reconciliation stays manual.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"reviewId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Dataset review request id.\"\n },\n \"required\": true,\n \"description\": \"Dataset review request id.\"\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/UpdateDatasetReviewRequest\"\n }\n }\n }\n },\n \"responses\": {\n \"200\": {\n \"description\": \"Updated dataset review request.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DatasetReviewDetail\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}/dataset-review-requests/{reviewId}/events\": {\n \"get\": {\n \"operationId\": \"automations.datasetReviewRequests.listEvents\",\n \"summary\": \"List dataset review events\",\n \"description\": \"List audit events for one dataset review request.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"reviewId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Dataset review request id.\"\n },\n \"required\": true,\n \"description\": \"Dataset review request id.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Review events.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DatasetReviewEventList\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}/dataset-review-requests/{reviewId}/items\": {\n \"get\": {\n \"operationId\": \"automations.datasetReviewRequests.listItems\",\n \"summary\": \"List dataset review items\",\n \"description\": \"List items for one dataset review request, optionally filtered by item status.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"reviewId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Dataset review request id.\"\n },\n \"required\": true,\n \"description\": \"Dataset review request id.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"status\",\n \"schema\": {\n \"description\": \"Optional comma-separated item statuses to filter by.\",\n \"type\": \"string\"\n },\n \"description\": \"Optional comma-separated item statuses to filter by.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Review items.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DatasetReviewItemList\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}/dataset-review-requests/{reviewId}/items/{itemId}\": {\n \"patch\": {\n \"operationId\": \"automations.datasetReviewRequests.updateItem\",\n \"summary\": \"Update dataset review item\",\n \"description\": \"Approve, edit, reject, reopen, comment, or record a field-decision on one review item while the parent request is draft, open, or paused. Pass `expectedUpdatedAt` from the item the client last observed. Pass `fieldPath` with `action: comment` or `action: field-decision`.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"reviewId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Dataset review request id.\"\n },\n \"required\": true,\n \"description\": \"Dataset review request id.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"itemId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Dataset review item id.\"\n },\n \"required\": true,\n \"description\": \"Dataset review item id.\"\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/UpdateDatasetReviewItem\"\n }\n }\n }\n },\n \"responses\": {\n \"200\": {\n \"description\": \"Updated review item.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DatasetReviewItemResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}/dataset-review-requests/{reviewId}/items/{itemId}/files/{path}\": {\n \"get\": {\n \"operationId\": \"automations.datasetReviewRequests.itemFile.get\",\n \"summary\": \"Download dataset review item input file\",\n \"description\": \"Download one input file belonging to a review item. Authorized by `dataset_review:read` and scoped to files referenced in the item snapshot, so reviewers without workflow read can still preview documents.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"reviewId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Dataset review request id.\"\n },\n \"required\": true,\n \"description\": \"Dataset review request id.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"itemId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Dataset review item id.\"\n },\n \"required\": true,\n \"description\": \"Dataset review item id.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"path\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Slash-delimited path under the example input folder referenced by the item snapshot.\"\n },\n \"required\": true,\n \"description\": \"Slash-delimited path under the example input folder referenced by the item snapshot.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Input file bytes.\",\n \"content\": {\n \"application/octet-stream\": {\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Input file bytes for a review item.\",\n \"format\": \"binary\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}/dataset/export\": {\n \"get\": {\n \"operationId\": \"automations.dataset.export\",\n \"summary\": \"Export automation dataset\",\n \"description\": \"Download the automation dataset as a ZIP archive. The archive uses the examples/<name>/input and examples/<name>/expected folder convention, so it can be re-imported into another automation or environment. Cloud deployments may redirect large archives to a short-lived storage URL.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"exampleIds\",\n \"schema\": {\n \"description\": \"Optional comma-separated dataset example ids to export. Omit to export the full dataset.\",\n \"type\": \"string\"\n },\n \"description\": \"Optional comma-separated dataset example ids to export. Omit to export the full dataset.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Dataset ZIP archive.\",\n \"content\": {\n \"application/octet-stream\": {\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"ZIP archive\",\n \"format\": \"binary\"\n }\n }\n }\n },\n \"302\": {\n \"description\": \"Redirect to a short-lived signed storage download\"\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}/dataset/import\": {\n \"post\": {\n \"operationId\": \"automations.dataset.import\",\n \"summary\": \"Import automation dataset\",\n \"description\": \"Import a dataset ZIP archive using the examples/<name>/input and examples/<name>/expected folder convention. Use `mode=append` for additive imports or `mode=replace` to replace the dataset.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias.\"\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"multipart/form-data\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/AutomationDatasetImportMultipartRequest\"\n }\n }\n }\n },\n \"responses\": {\n \"200\": {\n \"description\": \"Import result\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DatasetImportResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}/evaluators\": {\n \"get\": {\n \"operationId\": \"automations.evaluators.get\",\n \"summary\": \"Get evaluators\",\n \"description\": \"Fetch the evaluator configuration for an automation. Evaluators produce automated `score` results, which are separate from human review verdicts.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Evaluator YAML and parsed configuration.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/EvaluatorConfigResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"put\": {\n \"operationId\": \"automations.evaluators.update\",\n \"summary\": \"Replace evaluators\",\n \"description\": \"Replace the evaluator YAML for an automation. The submitted YAML is validated before it becomes the source for future experiment scores.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias.\"\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/EvaluatorConfigUpdate\"\n }\n }\n }\n },\n \"responses\": {\n \"200\": {\n \"description\": \"Updated evaluator YAML and parsed configuration.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/EvaluatorConfigResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}/examples\": {\n \"get\": {\n \"operationId\": \"automations.examples.list\",\n \"summary\": \"List dataset examples\",\n \"description\": \"List dataset examples for one automation. Examples contain input, expected output, expected files, metadata, and optional overrides used by evaluation runs. Pass `include=metadata` to return ids, names, metadata, and expected file refs without loading input or expected JSON.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias, such as `workflows.slug` or `agents.slug`.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias, such as `workflows.slug` or `agents.slug`.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"limit\",\n \"schema\": {\n \"description\": \"Maximum number of examples to return.\",\n \"type\": \"integer\",\n \"minimum\": 1,\n \"maximum\": 100\n },\n \"description\": \"Maximum number of examples to return.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"offset\",\n \"schema\": {\n \"description\": \"Zero-based offset for paging through examples.\",\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 9007199254740991\n },\n \"description\": \"Zero-based offset for paging through examples.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"include\",\n \"schema\": {\n \"description\": \"Response payload scope. `metadata` returns ids, names, metadata, and expected file refs without loading input or expected JSON.\",\n \"type\": \"string\",\n \"enum\": [\n \"full\",\n \"metadata\"\n ]\n },\n \"description\": \"Response payload scope. `metadata` returns ids, names, metadata, and expected file refs without loading input or expected JSON.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Page of dataset examples.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DatasetExampleList\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"post\": {\n \"operationId\": \"automations.examples.create\",\n \"summary\": \"Create dataset example\",\n \"description\": \"Create one dataset example from JSON fields. Use dataset import for archive-based uploads and file-bearing examples.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias, such as `workflows.slug` or `agents.slug`.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias, such as `workflows.slug` or `agents.slug`.\"\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DatasetExampleMutation\"\n }\n }\n }\n },\n \"responses\": {\n \"201\": {\n \"description\": \"Created dataset example.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DatasetExample\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}/examples/{exampleId}\": {\n \"get\": {\n \"operationId\": \"automations.examples.get\",\n \"summary\": \"Get dataset example\",\n \"description\": \"Fetch one dataset example, including input, expected output, expected files, metadata, and overrides.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"exampleId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Dataset example id. Agent examples may use deterministic name-derived ids returned by list/create responses.\"\n },\n \"required\": true,\n \"description\": \"Dataset example id. Agent examples may use deterministic name-derived ids returned by list/create responses.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Dataset example.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DatasetExample\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"patch\": {\n \"operationId\": \"automations.examples.update\",\n \"summary\": \"Update dataset example\",\n \"description\": \"Partially update a dataset example. Omitted fields are preserved; pass null for nullable fields to clear them.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"exampleId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Dataset example id. Agent examples may use deterministic name-derived ids returned by list/create responses.\"\n },\n \"required\": true,\n \"description\": \"Dataset example id. Agent examples may use deterministic name-derived ids returned by list/create responses.\"\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DatasetExampleUpdate\"\n }\n }\n }\n },\n \"responses\": {\n \"200\": {\n \"description\": \"Updated dataset example.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DatasetExample\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"delete\": {\n \"operationId\": \"automations.examples.delete\",\n \"summary\": \"Delete dataset example\",\n \"description\": \"Delete one dataset example from the automation dataset. This removes the example from future experiments.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"exampleId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Dataset example id. Agent examples may use deterministic name-derived ids returned by list/create responses.\"\n },\n \"required\": true,\n \"description\": \"Dataset example id. Agent examples may use deterministic name-derived ids returned by list/create responses.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Deleted dataset example.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DatasetExample\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}/examples/{exampleId}/expected\": {\n \"get\": {\n \"operationId\": \"automations.examples.expected.files.list\",\n \"summary\": \"List expected files\",\n \"description\": \"List files stored under the expected folder for one automation dataset example.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"exampleId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Dataset example id.\"\n },\n \"required\": true,\n \"description\": \"Dataset example id.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Expected file paths.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DatasetExampleExpectedFileList\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"post\": {\n \"operationId\": \"automations.examples.expected.files.create\",\n \"summary\": \"Upload expected files\",\n \"description\": \"Upload one or more files into the expected folder for an automation dataset example. Use `$file` references such as `expected/result.pdf` from expected JSON to compare file outputs.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"exampleId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Dataset example id.\"\n },\n \"required\": true,\n \"description\": \"Dataset example id.\"\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"multipart/form-data\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DatasetExampleExpectedFileUploadRequest\"\n }\n }\n }\n },\n \"responses\": {\n \"201\": {\n \"description\": \"Uploaded expected files.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DatasetExampleExpectedFileUploadResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}/examples/{exampleId}/expected/{path}\": {\n \"get\": {\n \"operationId\": \"automations.examples.expected.file.get\",\n \"summary\": \"Download expected dataset file\",\n \"description\": \"Download one expected file attached to an automation dataset example.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"exampleId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Dataset example id.\"\n },\n \"required\": true,\n \"description\": \"Dataset example id.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"path\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Path under the example expected folder.\"\n },\n \"required\": true,\n \"description\": \"Path under the example expected folder.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Expected dataset file.\",\n \"content\": {\n \"application/octet-stream\": {\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Expected file bytes.\",\n \"format\": \"binary\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"patch\": {\n \"operationId\": \"automations.examples.expected.file.update\",\n \"summary\": \"Rename expected file\",\n \"description\": \"Rename one expected file attached to an automation dataset example. The parent folder is preserved.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"exampleId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Dataset example id.\"\n },\n \"required\": true,\n \"description\": \"Dataset example id.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"path\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Path under the example expected folder.\"\n },\n \"required\": true,\n \"description\": \"Path under the example expected folder.\"\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DatasetExampleExpectedFileRenameRequest\"\n }\n }\n }\n },\n \"responses\": {\n \"200\": {\n \"description\": \"Renamed expected file.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DatasetExampleExpectedFileRenameResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"delete\": {\n \"operationId\": \"automations.examples.expected.file.delete\",\n \"summary\": \"Delete expected file\",\n \"description\": \"Delete one file from an automation dataset example expected folder.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"exampleId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Dataset example id.\"\n },\n \"required\": true,\n \"description\": \"Dataset example id.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"path\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Path under the example expected folder.\"\n },\n \"required\": true,\n \"description\": \"Path under the example expected folder.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Expected file deleted.\"\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}/examples/{exampleId}/input\": {\n \"get\": {\n \"operationId\": \"automations.examples.input.files.list\",\n \"summary\": \"List input files\",\n \"description\": \"List files stored under the input folder for one automation dataset example.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"exampleId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Dataset example id.\"\n },\n \"required\": true,\n \"description\": \"Dataset example id.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Input file paths.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DatasetExampleInputFileList\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"post\": {\n \"operationId\": \"automations.examples.input.files.create\",\n \"summary\": \"Upload input files\",\n \"description\": \"Upload one or more files into the input folder for an automation dataset example. Use `$file` references such as `input/invoice.pdf` from the example input JSON to consume them.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"exampleId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Dataset example id.\"\n },\n \"required\": true,\n \"description\": \"Dataset example id.\"\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"multipart/form-data\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DatasetExampleInputFileUploadRequest\"\n }\n }\n }\n },\n \"responses\": {\n \"201\": {\n \"description\": \"Uploaded input files.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DatasetExampleInputFileUploadResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}/examples/{exampleId}/input/{path}\": {\n \"get\": {\n \"operationId\": \"automations.examples.input.file.get\",\n \"summary\": \"Download input file\",\n \"description\": \"Download one file from an automation dataset example input folder.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"exampleId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Dataset example id.\"\n },\n \"required\": true,\n \"description\": \"Dataset example id.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"path\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Slash-delimited path under the example input folder.\"\n },\n \"required\": true,\n \"description\": \"Slash-delimited path under the example input folder.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Input file bytes.\",\n \"content\": {\n \"application/octet-stream\": {\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Input file bytes.\",\n \"format\": \"binary\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"patch\": {\n \"operationId\": \"automations.examples.input.file.update\",\n \"summary\": \"Rename input file\",\n \"description\": \"Rename one input file attached to an automation dataset example. The parent folder is preserved.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"exampleId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Dataset example id.\"\n },\n \"required\": true,\n \"description\": \"Dataset example id.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"path\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Slash-delimited path under the example input folder.\"\n },\n \"required\": true,\n \"description\": \"Slash-delimited path under the example input folder.\"\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DatasetExampleInputFileRenameRequest\"\n }\n }\n }\n },\n \"responses\": {\n \"200\": {\n \"description\": \"Renamed input file.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DatasetExampleInputFileRenameResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"delete\": {\n \"operationId\": \"automations.examples.input.file.delete\",\n \"summary\": \"Delete input file\",\n \"description\": \"Delete one file from an automation dataset example input folder.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"exampleId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Dataset example id.\"\n },\n \"required\": true,\n \"description\": \"Dataset example id.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"path\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Slash-delimited path under the example input folder.\"\n },\n \"required\": true,\n \"description\": \"Slash-delimited path under the example input folder.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Input file deleted.\"\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}/examples/{exampleId}/run\": {\n \"post\": {\n \"operationId\": \"automations.examples.run\",\n \"summary\": \"Run dataset example\",\n \"description\": \"Start an asynchronous run using the input from one dataset example. Poll `GET /api/v1/runs/{id}` for completion and use run scores or review endpoints to review the result.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"exampleId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Dataset example id to run.\"\n },\n \"required\": true,\n \"description\": \"Dataset example id to run.\"\n }\n ],\n \"responses\": {\n \"201\": {\n \"description\": \"Example run accepted\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ExampleRunResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}/experiments\": {\n \"get\": {\n \"operationId\": \"automations.experiments.list\",\n \"summary\": \"List experiments\",\n \"description\": \"List experiment batches for one automation. Each experiment runs selected dataset examples and records automated evaluator scores.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"limit\",\n \"schema\": {\n \"description\": \"Maximum number of experiment batches to return.\",\n \"type\": \"integer\",\n \"minimum\": 1,\n \"maximum\": 500\n },\n \"description\": \"Maximum number of experiment batches to return.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"offset\",\n \"schema\": {\n \"description\": \"Zero-based offset for paging through experiment batches.\",\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 9007199254740991\n },\n \"description\": \"Zero-based offset for paging through experiment batches.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"fromDate\",\n \"schema\": {\n \"description\": \"Filter to experiment batches created at or after this date or relative date.\",\n \"type\": \"string\"\n },\n \"description\": \"Filter to experiment batches created at or after this date or relative date.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"toDate\",\n \"schema\": {\n \"description\": \"Filter to experiment batches created at or before this date or relative date.\",\n \"type\": \"string\"\n },\n \"description\": \"Filter to experiment batches created at or before this date or relative date.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Page of experiment batches.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"type\": \"object\",\n \"properties\": {\n \"data\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/Experiment\"\n }\n },\n \"total\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"limit\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"offset\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n }\n },\n \"required\": [\n \"data\",\n \"total\",\n \"limit\",\n \"offset\"\n ],\n \"additionalProperties\": false\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"post\": {\n \"operationId\": \"automations.experiments.create\",\n \"summary\": \"Create experiment\",\n \"description\": \"Start an asynchronous experiment batch for one automation. Omit `examples` to run the full dataset, or pass specific example ids to run a subset.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias.\"\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ExperimentCreate\"\n }\n }\n }\n },\n \"responses\": {\n \"202\": {\n \"description\": \"Experiment accepted and runs enqueued.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ExperimentCreateResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}/experiments/{experimentId}\": {\n \"get\": {\n \"operationId\": \"automations.experiments.get\",\n \"summary\": \"Get experiment\",\n \"description\": \"Fetch one experiment batch with its run summaries and evaluator results grouped by run id.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"experimentId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Experiment batch id.\"\n },\n \"required\": true,\n \"description\": \"Experiment batch id.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Experiment detail with runs and results.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ExperimentDetail\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}/experiments/{experimentId}/cancel\": {\n \"post\": {\n \"operationId\": \"automations.experiments.cancel\",\n \"summary\": \"Cancel experiment\",\n \"description\": \"Request cancellation for an experiment batch. Already-completed runs remain recorded; queued or running work is cancelled when possible.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"experimentId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Experiment batch id.\"\n },\n \"required\": true,\n \"description\": \"Experiment batch id.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Experiment detail after the cancellation request.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ExperimentDetail\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}/experiments/{experimentId}/export\": {\n \"get\": {\n \"operationId\": \"automations.experiments.export\",\n \"summary\": \"Export experiment eval results\",\n \"description\": \"Download eval result rows for a single experiment batch as CSV or JSON.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\"\n },\n \"required\": true\n },\n {\n \"in\": \"path\",\n \"name\": \"experimentId\",\n \"schema\": {\n \"type\": \"string\"\n },\n \"required\": true\n },\n {\n \"in\": \"query\",\n \"name\": \"format\",\n \"schema\": {\n \"type\": \"string\",\n \"enum\": [\n \"csv\",\n \"json\"\n ]\n },\n \"required\": true\n },\n {\n \"in\": \"query\",\n \"name\": \"includeTrace\",\n \"schema\": {\n \"type\": \"string\",\n \"enum\": [\n \"0\",\n \"1\",\n \"true\",\n \"false\"\n ]\n }\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Eval results export\",\n \"content\": {\n \"text/csv\": {\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"CSV or JSON document\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}/experiments/export\": {\n \"get\": {\n \"operationId\": \"automations.experiments.exportAll\",\n \"summary\": \"Export all experiment eval results\",\n \"description\": \"Download every eval result row for an automation as CSV or JSON.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\"\n },\n \"required\": true\n },\n {\n \"in\": \"query\",\n \"name\": \"format\",\n \"schema\": {\n \"type\": \"string\",\n \"enum\": [\n \"csv\",\n \"json\"\n ]\n },\n \"required\": true\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Eval results export\",\n \"content\": {\n \"text/csv\": {\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"CSV or JSON document\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}/experiments/stream\": {\n \"post\": {\n \"operationId\": \"automations.experiments.createStream\",\n \"summary\": \"Create automation experiment with NDJSON progress\",\n \"description\": \"Starts a batch eval experiment for workflow or agent automations and streams per-run completion events as NDJSON.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\"\n },\n \"required\": true\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ExperimentCreate\"\n }\n }\n }\n },\n \"responses\": {\n \"200\": {\n \"description\": \"NDJSON experiment progress stream\",\n \"content\": {\n \"text/plain\": {\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"application/x-ndjson event stream\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}/reviews/health\": {\n \"get\": {\n \"operationId\": \"automations.reviews.health\",\n \"summary\": \"Get automation review health\",\n \"description\": \"Aggregates reviewed correctness, review coverage, bucketed counts, and rolling-window confidence for one automation. Prefer this endpoint for single-automation monitoring dashboards.\",\n \"tags\": [\n \"Reviews\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Workflow id, agent id, or typed alias like workflows.slug / agents.slug.\"\n },\n \"required\": true,\n \"description\": \"Workflow id, agent id, or typed alias like workflows.slug / agents.slug.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"type\",\n \"schema\": {\n \"description\": \"Comma-separated: workflow,agent.\",\n \"type\": \"string\"\n },\n \"description\": \"Comma-separated: workflow,agent.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"status\",\n \"schema\": {\n \"description\": \"Comma-separated execution statuses.\",\n \"type\": \"string\"\n },\n \"description\": \"Comma-separated execution statuses.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"trigger\",\n \"schema\": {\n \"description\": \"Comma-separated trigger types.\",\n \"type\": \"string\"\n },\n \"description\": \"Comma-separated trigger types.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"triggeredBy\",\n \"schema\": {\n \"description\": \"Comma-separated user ids, or __system__ for system-triggered runs.\",\n \"type\": \"string\"\n },\n \"description\": \"Comma-separated user ids, or __system__ for system-triggered runs.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"sourceRef\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"batchId\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"exampleId\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"exampleIdContains\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"from\",\n \"schema\": {\n \"description\": \"Start of the run-created time range. Defaults to now-30d.\",\n \"type\": \"string\"\n },\n \"description\": \"Start of the run-created time range. Defaults to now-30d.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"to\",\n \"schema\": {\n \"description\": \"End of the run-created time range.\",\n \"type\": \"string\"\n },\n \"description\": \"End of the run-created time range.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"completedAfter\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"completedBefore\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"experiments\",\n \"schema\": {\n \"description\": \"Set to false to exclude experiment batch runs.\",\n \"type\": \"string\"\n },\n \"description\": \"Set to false to exclude experiment batch runs.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"bucket\",\n \"schema\": {\n \"description\": \"Calendar bucket size for the bar chart series. Defaults to day.\",\n \"type\": \"string\",\n \"enum\": [\n \"day\",\n \"week\",\n \"month\"\n ]\n },\n \"description\": \"Calendar bucket size for the bar chart series. Defaults to day.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"rollingWindow\",\n \"schema\": {\n \"description\": \"Number of reviewed runs per rolling correctness point. Defaults to 100.\",\n \"type\": \"integer\",\n \"minimum\": 1,\n \"maximum\": 1000\n },\n \"description\": \"Number of reviewed runs per rolling correctness point. Defaults to 100.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"minRollingReviews\",\n \"schema\": {\n \"description\": \"Minimum reviewed runs required before emitting rolling points. Defaults to 1.\",\n \"type\": \"integer\",\n \"minimum\": 1,\n \"maximum\": 1000\n },\n \"description\": \"Minimum reviewed runs required before emitting rolling points. Defaults to 1.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Automation review health metrics.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/RunReviewHealthResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}/sync\": {\n \"post\": {\n \"operationId\": \"automations.sync\",\n \"summary\": \"Sync automation from latest Git release\",\n \"description\": \"Reconciles automation registry metadata and trigger projections from the latest Git source release. This operation is idempotent for unchanged source state: repeated calls against the same latest release leave the same automation registry state and may repeat the same warnings. Requires a Bearer API token for the organization and a user-backed API key. It does not publish source; it reads the already-published latest release manifest. Versioned targets are rejected with 400, missing organization/source/release/manifest state returns 404, invalid manifests return 400, and provider or persistence failures return 5xx.\",\n \"tags\": [\n \"Automations\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation target to sync, such as agents.invoice-agent or workflows.extract. Do not include a version; sync always uses the latest Git release.\"\n },\n \"required\": true,\n \"description\": \"Automation target to sync, such as agents.invoice-agent or workflows.extract. Do not include a version; sync always uses the latest Git release.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Automation metadata, latest release information, and non-fatal sync warnings.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"type\": \"object\",\n \"properties\": {\n \"automation\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\",\n \"description\": \"Automation id after reconciliation.\"\n },\n \"type\": {\n \"type\": \"string\",\n \"enum\": [\n \"agent\",\n \"workflow\"\n ],\n \"description\": \"Automation kind inferred from the source package path.\"\n },\n \"slug\": {\n \"type\": \"string\",\n \"description\": \"Source package slug within agents/ or workflows/.\"\n },\n \"status\": {\n \"type\": \"string\",\n \"enum\": [\n \"active\",\n \"archived\"\n ],\n \"description\": \"Current automation registry status.\"\n },\n \"updatedAt\": {\n \"type\": \"string\",\n \"description\": \"ISO timestamp for the reconciled automation row.\"\n }\n },\n \"required\": [\n \"id\",\n \"type\",\n \"slug\",\n \"status\",\n \"updatedAt\"\n ],\n \"additionalProperties\": false\n },\n \"release\": {\n \"type\": \"object\",\n \"properties\": {\n \"version\": {\n \"type\": \"string\",\n \"description\": \"Latest released source package version that was synced.\"\n },\n \"tag\": {\n \"type\": \"string\",\n \"description\": \"Git release tag read during sync.\"\n },\n \"commit\": {\n \"type\": \"string\",\n \"description\": \"Git commit for the release tag.\"\n }\n },\n \"required\": [\n \"version\",\n \"tag\",\n \"commit\"\n ],\n \"additionalProperties\": false\n },\n \"warnings\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n },\n \"description\": \"Non-fatal source-state warnings, such as unsupported email alias domains.\"\n }\n },\n \"required\": [\n \"automation\",\n \"release\",\n \"warnings\"\n ],\n \"additionalProperties\": false\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}/triggers\": {\n \"get\": {\n \"operationId\": \"automations.triggers.get\",\n \"summary\": \"Get automation triggers\",\n \"description\": \"Read trigger state for a workflow or agent automation. Trigger mutation is not public v1.\",\n \"tags\": [\n \"Automations\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Workflow id, agent id, or typed alias like workflows.slug / agents.slug\"\n },\n \"required\": true,\n \"description\": \"Workflow id, agent id, or typed alias like workflows.slug / agents.slug\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Automation trigger state\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/AutomationTriggersResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}/versions\": {\n \"get\": {\n \"operationId\": \"automations.versions.list\",\n \"summary\": \"List automation versions\",\n \"description\": \"List versions for a workflow or agent automation. YAML workflow lists include tagged releases plus the current untagged snapshot when HEAD is untagged (for example after restore), so the current version is always present. Agent lists remain Git release tags.\",\n \"tags\": [\n \"Automations\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Workflow id, agent id, or typed alias like workflows.slug / agents.slug\"\n },\n \"required\": true,\n \"description\": \"Workflow id, agent id, or typed alias like workflows.slug / agents.slug\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Automation versions\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ListAutomationVersionsResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"post\": {\n \"operationId\": \"automations.versions.create\",\n \"summary\": \"Create a workflow version\",\n \"description\": \"Create a tagged YAML workflow candidate from validated YAML or by copying an existing snapshot (`historyId`). Provide exactly one of `yaml` or `historyId`. Copy creates a new tagged row and leaves the source tag unchanged; it does not retag the original. Defaults to making the new version current. Set `activate: false` to keep it off live traffic until promote — that path requires an existing current workflow version and returns 400 if HEAD is empty. Agent automations are Git-backed and return 400. Requires a Bearer API key or a dashboard session.\",\n \"tags\": [\n \"Automations\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Workflow id, agent id, or typed alias like workflows.slug / agents.slug\"\n },\n \"required\": true,\n \"description\": \"Workflow id, agent id, or typed alias like workflows.slug / agents.slug\"\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/CreateAutomationVersionRequest\"\n }\n }\n }\n },\n \"responses\": {\n \"201\": {\n \"description\": \"Created workflow version.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/AutomationVersion\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"409\": {\n \"description\": \"Conflict. The resource is in a state that forbids the request.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}/versions/{versionId}/promote\": {\n \"post\": {\n \"operationId\": \"automations.versions.promote\",\n \"summary\": \"Promote a workflow version\",\n \"description\": \"Make an existing tagged YAML workflow candidate current without creating another history row. Only tagged version rows can be promoted; untagged snapshots (including restore HEAD) and missing ids return 404. Agent automations return 400. Requires a Bearer API key or a dashboard session.\",\n \"tags\": [\n \"Automations\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Workflow id, agent id, or typed alias like workflows.slug / agents.slug\"\n },\n \"required\": true,\n \"description\": \"Workflow id, agent id, or typed alias like workflows.slug / agents.slug\"\n },\n {\n \"in\": \"path\",\n \"name\": \"versionId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Tagged version id from GET /automations/{id}/versions. Untagged snapshots (for example after restore) and unknown ids return 404.\"\n },\n \"required\": true,\n \"description\": \"Tagged version id from GET /automations/{id}/versions. Untagged snapshots (for example after restore) and unknown ids return 404.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Existing tagged workflow version promoted.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/AutomationVersion\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"409\": {\n \"description\": \"Conflict. The resource is in a state that forbids the request.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}/versions/{versionId}/restore\": {\n \"post\": {\n \"operationId\": \"automations.versions.restore\",\n \"summary\": \"Restore a workflow version\",\n \"description\": \"Restore a YAML workflow automation by copying a previous snapshot into a new untagged current version. The source tag is left unchanged; the new HEAD appears in subsequent version lists as the untagged current row and cannot be promoted until you create a tagged copy. The JSON body may be `{}`; `message` is optional and defaults to a timestamped restore note. Agent automations return 400. Requires a Bearer API key or a dashboard session.\",\n \"tags\": [\n \"Automations\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Workflow id, agent id, or typed alias like workflows.slug / agents.slug\"\n },\n \"required\": true,\n \"description\": \"Workflow id, agent id, or typed alias like workflows.slug / agents.slug\"\n },\n {\n \"in\": \"path\",\n \"name\": \"versionId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Version id from GET /automations/{id}/versions (a workflow history id).\"\n },\n \"required\": true,\n \"description\": \"Version id from GET /automations/{id}/versions (a workflow history id).\"\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/RestoreAutomationVersionRequest\"\n }\n }\n }\n },\n \"responses\": {\n \"201\": {\n \"description\": \"New current version created from the restored snapshot.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/AutomationVersion\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"409\": {\n \"description\": \"Conflict. The resource is in a state that forbids the request.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/email-servers\": {\n \"get\": {\n \"operationId\": \"emailServers.list\",\n \"summary\": \"List email servers\",\n \"description\": \"List outbound email servers for the current workspace. Secrets are never returned; each server includes configuration flags instead of credentials.\",\n \"tags\": [\n \"Email servers\"\n ],\n \"parameters\": [\n {\n \"in\": \"query\",\n \"name\": \"limit\",\n \"schema\": {\n \"description\": \"Maximum number of email servers to return (1–100).\",\n \"type\": \"integer\",\n \"minimum\": 1,\n \"maximum\": 100\n },\n \"description\": \"Maximum number of email servers to return (1–100).\"\n },\n {\n \"in\": \"query\",\n \"name\": \"offset\",\n \"schema\": {\n \"description\": \"Zero-based offset for paging through email servers.\",\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 9007199254740991\n },\n \"description\": \"Zero-based offset for paging through email servers.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Page of email servers\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ListEmailServersResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"post\": {\n \"operationId\": \"emailServers.create\",\n \"summary\": \"Create email server\",\n \"description\": \"Create an outbound email server. Secrets are encrypted at rest and never returned. Names must be unique among live servers in the workspace.\",\n \"tags\": [\n \"Email servers\"\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/CreateEmailServerRequest\"\n }\n }\n }\n },\n \"responses\": {\n \"201\": {\n \"description\": \"Created email server\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/EmailServer\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"409\": {\n \"description\": \"Conflict. The resource is in a state that forbids the request.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/email-servers/{id}\": {\n \"get\": {\n \"operationId\": \"emailServers.get\",\n \"summary\": \"Get email server\",\n \"description\": \"Inspect a stored outbound email server. Cross-tenant and deleted ids are indistinguishable from missing. Secrets are never returned.\",\n \"tags\": [\n \"Email servers\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"maxLength\": 128,\n \"pattern\": \"^ems_[A-Za-z0-9_-]+$\",\n \"description\": \"Email server id (`ems_…`).\"\n },\n \"required\": true,\n \"description\": \"Email server id (`ems_…`).\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Email server\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/EmailServer\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"patch\": {\n \"operationId\": \"emailServers.update\",\n \"summary\": \"Update email server\",\n \"description\": \"Rename, enable/disable, or replace transport configuration. Omitted secrets are retained only when the existing transport is compatible and, for SMTP, the host and username are unchanged. Changing transport or SMTP destination requires a complete valid target; a new password or explicit auth clearing is required when host or username changes.\",\n \"tags\": [\n \"Email servers\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"maxLength\": 128,\n \"pattern\": \"^ems_[A-Za-z0-9_-]+$\",\n \"description\": \"Email server id (`ems_…`).\"\n },\n \"required\": true,\n \"description\": \"Email server id (`ems_…`).\"\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/UpdateEmailServerRequest\"\n }\n }\n }\n },\n \"responses\": {\n \"200\": {\n \"description\": \"Updated email server\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/EmailServer\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"409\": {\n \"description\": \"Conflict. The resource is in a state that forbids the request.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"delete\": {\n \"operationId\": \"emailServers.delete\",\n \"summary\": \"Delete email server\",\n \"description\": \"Soft-delete an outbound email server. Deleted ids are indistinguishable from missing.\",\n \"tags\": [\n \"Email servers\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"maxLength\": 128,\n \"pattern\": \"^ems_[A-Za-z0-9_-]+$\",\n \"description\": \"Email server id (`ems_…`).\"\n },\n \"required\": true,\n \"description\": \"Email server id (`ems_…`).\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Email server deleted\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DeleteEmailServerResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/email-servers/{id}/test\": {\n \"post\": {\n \"operationId\": \"emailServers.test\",\n \"summary\": \"Test email server\",\n \"description\": \"Send a concise connectivity email through the selected stored server. Disabled servers conflict. Provider failures are returned as a generic outcome and never include credentials or the test recipient.\",\n \"tags\": [\n \"Email servers\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"maxLength\": 128,\n \"pattern\": \"^ems_[A-Za-z0-9_-]+$\",\n \"description\": \"Email server id (`ems_…`).\"\n },\n \"required\": true,\n \"description\": \"Email server id (`ems_…`).\"\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/TestEmailServerRequest\"\n }\n }\n }\n },\n \"responses\": {\n \"200\": {\n \"description\": \"Test send result\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/TestEmailServerResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"409\": {\n \"description\": \"Conflict. The resource is in a state that forbids the request.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/experiments/{experimentId}\": {\n \"get\": {\n \"operationId\": \"experiments.resolve\",\n \"summary\": \"Resolve experiment by id\",\n \"description\": \"Returns the owning automation for an experiment batch id. Used when callers only know the experiment id.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"experimentId\",\n \"schema\": {\n \"type\": \"string\"\n },\n \"required\": true\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Experiment reference\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ExperimentRef\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/files\": {\n \"post\": {\n \"operationId\": \"files.create\",\n \"summary\": \"Upload file\",\n \"description\": \"Upload a reusable file that can later be referenced by run inputs or dataset examples.\",\n \"tags\": [\n \"Files\"\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"multipart/form-data\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/CreateFileMultipartRequest\"\n }\n }\n }\n },\n \"responses\": {\n \"200\": {\n \"description\": \"Uploaded file\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/File\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/files/{id}\": {\n \"get\": {\n \"operationId\": \"files.get\",\n \"summary\": \"Get file metadata\",\n \"description\": \"Get metadata for a reusable uploaded file.\",\n \"tags\": [\n \"Files\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"File id\"\n },\n \"required\": true,\n \"description\": \"File id\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"File metadata\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/File\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"delete\": {\n \"operationId\": \"files.delete\",\n \"summary\": \"Delete file\",\n \"description\": \"Delete a reusable uploaded file. Past runs that referenced it stay readable until those runs are deleted.\",\n \"tags\": [\n \"Files\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"File id\"\n },\n \"required\": true,\n \"description\": \"File id\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"File deleted\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DeleteFileResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/files/{id}/content\": {\n \"get\": {\n \"operationId\": \"files.content.get\",\n \"summary\": \"Download file content\",\n \"description\": \"Download bytes for a reusable uploaded file. Direct-enabled deployments redirect responses above their configured body limit to a short-lived signed storage URL; multipart-only/on-prem deployments stream through the API.\",\n \"tags\": [\n \"Files\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"File id\"\n },\n \"required\": true,\n \"description\": \"File id\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"File content\"\n },\n \"302\": {\n \"description\": \"Redirect to a short-lived signed storage download\"\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/files/uploads\": {\n \"post\": {\n \"operationId\": \"files.uploads.create\",\n \"summary\": \"Prepare file upload\",\n \"description\": \"Negotiate HTTP multipart for small bodies, a short-lived signed PUT under the single-object ceiling, or storage-direct multipart (presigned-multipart) for larger files when storage supports MPU. The response transport is authoritative; clients must not guess from file size alone.\",\n \"tags\": [\n \"Files\"\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/CreateFileUploadSessionRequest\"\n }\n }\n }\n },\n \"responses\": {\n \"200\": {\n \"description\": \"Negotiated upload transport\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"anyOf\": [\n {\n \"$ref\": \"#/components/schemas/PresignedFileUploadSession\"\n },\n {\n \"$ref\": \"#/components/schemas/PresignedMultipartFileUploadSession\"\n },\n {\n \"$ref\": \"#/components/schemas/MultipartFileUploadFallback\"\n }\n ]\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/files/uploads/{uploadId}\": {\n \"get\": {\n \"operationId\": \"files.uploads.get\",\n \"summary\": \"Get file upload session\",\n \"description\": \"Return session status for resume. Multipart sessions include authoritative uploaded parts from storage, not client-reported ETags.\",\n \"tags\": [\n \"Files\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"uploadId\",\n \"schema\": {\n \"type\": \"string\"\n },\n \"required\": true\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Upload session\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/FileUploadSession\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"delete\": {\n \"operationId\": \"files.uploads.abort\",\n \"summary\": \"Abort file upload\",\n \"description\": \"Abort a pending storage-direct upload. Multipart sessions call AbortMultipartUpload; pending PUT objects are deleted. Completed canonical files are never deleted.\",\n \"tags\": [\n \"Files\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"uploadId\",\n \"schema\": {\n \"type\": \"string\"\n },\n \"required\": true\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Upload aborted\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/AbortFileUploadResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/files/uploads/{uploadId}/complete\": {\n \"post\": {\n \"operationId\": \"files.uploads.complete\",\n \"summary\": \"Complete file upload\",\n \"description\": \"Verify a storage-direct pending object and promote it into a reusable file. Safe to retry.\",\n \"tags\": [\n \"Files\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"uploadId\",\n \"schema\": {\n \"type\": \"string\"\n },\n \"required\": true\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Completed reusable file\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/File\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/files/uploads/{uploadId}/parts\": {\n \"get\": {\n \"operationId\": \"files.uploads.parts.list\",\n \"summary\": \"List uploaded multipart parts\",\n \"description\": \"List authoritative uploaded parts from storage for resume. Do not trust client-only ETags.\",\n \"tags\": [\n \"Files\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"uploadId\",\n \"schema\": {\n \"type\": \"string\"\n },\n \"required\": true\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Uploaded parts\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ListFileUploadPartsResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"post\": {\n \"operationId\": \"files.uploads.parts.presign\",\n \"summary\": \"Presign one multipart upload part\",\n \"description\": \"Mint a short-lived signed UploadPart URL for one validated part. Part URLs are not issued at session create.\",\n \"tags\": [\n \"Files\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"uploadId\",\n \"schema\": {\n \"type\": \"string\"\n },\n \"required\": true\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/PresignFileUploadPartRequest\"\n }\n }\n }\n },\n \"responses\": {\n \"200\": {\n \"description\": \"Signed part upload\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/PresignFileUploadPartResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/folders\": {\n \"get\": {\n \"operationId\": \"folders.list\",\n \"summary\": \"List folders\",\n \"description\": \"List folders in one tree. `type` is required (`workflow` or `template`). Pass `tree=true` for the full nested tree with counts; otherwise list direct children of `parentId` (`null` for root). Deleting a folder later unfiles contained workflows or templates and does not delete them.\",\n \"tags\": [\n \"Folders\"\n ],\n \"parameters\": [\n {\n \"in\": \"query\",\n \"name\": \"type\",\n \"schema\": {\n \"description\": \"Folder tree to list. Required; there is no default.\",\n \"$ref\": \"#/components/schemas/FolderType\"\n },\n \"required\": true,\n \"description\": \"Folder tree to list. Required; there is no default.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"parentId\",\n \"schema\": {\n \"description\": \"Limit to direct children of this folder. Pass `null` for root folders only. Ignored when `tree=true`.\",\n \"type\": \"string\"\n },\n \"description\": \"Limit to direct children of this folder. Pass `null` for root folders only. Ignored when `tree=true`.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"tree\",\n \"schema\": {\n \"description\": \"When `true`, return the full tree for `type` with child counts (and workflow previews for workflow trees).\",\n \"type\": \"string\"\n },\n \"description\": \"When `true`, return the full tree for `type` with child counts (and workflow previews for workflow trees).\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Folders in the requested tree\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ListFoldersResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"post\": {\n \"operationId\": \"folders.create\",\n \"summary\": \"Create folder\",\n \"description\": \"Create a folder in the workflow or template tree. `type` is required. Missing parents 404; a same-named sibling at that location returns 409. Nested agent directories in Git are source organization only and are not folders.\",\n \"tags\": [\n \"Folders\"\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/CreateFolderRequest\"\n }\n }\n }\n },\n \"responses\": {\n \"201\": {\n \"description\": \"Created folder\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/Folder\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"409\": {\n \"description\": \"Conflict. The resource is in a state that forbids the request.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/folders/{id}\": {\n \"get\": {\n \"operationId\": \"folders.get\",\n \"summary\": \"Get folder\",\n \"description\": \"Get one workflow or template folder by id.\",\n \"tags\": [\n \"Folders\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Folder id (`fldr_…`).\"\n },\n \"required\": true,\n \"description\": \"Folder id (`fldr_…`).\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Folder\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/Folder\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"patch\": {\n \"operationId\": \"folders.update\",\n \"summary\": \"Update folder\",\n \"description\": \"Rename or reparent a folder. Moving a folder onto itself, into a descendant, or into the other tree is rejected. A same-named sibling at the destination returns 409.\",\n \"tags\": [\n \"Folders\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Folder id (`fldr_…`).\"\n },\n \"required\": true,\n \"description\": \"Folder id (`fldr_…`).\"\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/UpdateFolderRequest\"\n }\n }\n }\n },\n \"responses\": {\n \"200\": {\n \"description\": \"Updated folder\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/Folder\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"409\": {\n \"description\": \"Conflict. The resource is in a state that forbids the request.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"delete\": {\n \"operationId\": \"folders.delete\",\n \"summary\": \"Delete folder\",\n \"description\": \"Delete a folder and cascade-delete child folders. Workflows and templates in the tree are unfiled, not deleted.\",\n \"tags\": [\n \"Folders\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Folder id (`fldr_…`).\"\n },\n \"required\": true,\n \"description\": \"Folder id (`fldr_…`).\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Folder deleted\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DeleteFolderResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/human-reviews\": {\n \"get\": {\n \"operationId\": \"humanReviews.list\",\n \"summary\": \"List pending human review tasks\",\n \"description\": \"Cursor-paginated queue of pending human-review tasks for the tenant, oldest first.\",\n \"tags\": [\n \"Human reviews\"\n ],\n \"parameters\": [\n {\n \"in\": \"query\",\n \"name\": \"automationId\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"waitingBefore\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"cursor\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"limit\",\n \"schema\": {\n \"type\": \"integer\",\n \"minimum\": 1,\n \"maximum\": 100\n }\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Pending review tasks\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/HumanReviewListResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/human-reviews/{taskId}\": {\n \"get\": {\n \"operationId\": \"humanReviews.get\",\n \"summary\": \"Get human review task\",\n \"description\": \"Fetch one authorized human-review task with draft data, derived non-file input, files, and decisions.\",\n \"tags\": [\n \"Human reviews\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"taskId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Human review task id\"\n },\n \"required\": true,\n \"description\": \"Human review task id\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Human review task detail\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/HumanReviewTaskResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/human-reviews/{taskId}/approve\": {\n \"post\": {\n \"operationId\": \"humanReviews.approve\",\n \"summary\": \"Approve human review task\",\n \"description\": \"Approve a complete review task and resume the paused run. Requires every required field to be confirmed.\",\n \"tags\": [\n \"Human reviews\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"taskId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Human review task id\"\n },\n \"required\": true,\n \"description\": \"Human review task id\"\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"type\": \"object\",\n \"properties\": {\n \"expectedVersion\": {\n \"type\": \"integer\",\n \"exclusiveMinimum\": 0,\n \"maximum\": 9007199254740991\n }\n },\n \"required\": [\n \"expectedVersion\"\n ],\n \"additionalProperties\": false\n }\n }\n }\n },\n \"responses\": {\n \"200\": {\n \"description\": \"Approved task\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/HumanReviewApproveResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/human-reviews/{taskId}/fields\": {\n \"put\": {\n \"operationId\": \"humanReviews.confirmField\",\n \"summary\": \"Confirm or edit a review field\",\n \"description\": \"Confirm or edit a scalar field using optimistic concurrency and a durable idempotency key.\",\n \"tags\": [\n \"Human reviews\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"taskId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Human review task id\"\n },\n \"required\": true,\n \"description\": \"Human review task id\"\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"type\": \"object\",\n \"properties\": {\n \"expectedVersion\": {\n \"type\": \"integer\",\n \"exclusiveMinimum\": 0,\n \"maximum\": 9007199254740991\n },\n \"idempotencyKey\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 200\n },\n \"path\": {\n \"type\": \"string\"\n },\n \"value\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"number\"\n },\n {\n \"type\": \"boolean\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"confirmed\": {\n \"default\": true,\n \"type\": \"boolean\"\n }\n },\n \"required\": [\n \"expectedVersion\",\n \"idempotencyKey\",\n \"path\",\n \"value\"\n ],\n \"additionalProperties\": false\n }\n }\n }\n },\n \"responses\": {\n \"200\": {\n \"description\": \"Updated task after field confirmation\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/HumanReviewFieldResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/human-reviews/{taskId}/files/{fileId}/content\": {\n \"get\": {\n \"operationId\": \"humanReviews.files.content.get\",\n \"summary\": \"Download human review task file\",\n \"description\": \"Download one file attached to a human-review task after strict tenant, task, and run ownership checks. Large cloud deployments may redirect to a short-lived signed storage URL.\",\n \"tags\": [\n \"Human reviews\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"taskId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Human review task id\"\n },\n \"required\": true,\n \"description\": \"Human review task id\"\n },\n {\n \"in\": \"path\",\n \"name\": \"fileId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"File id listed on the review task\"\n },\n \"required\": true,\n \"description\": \"File id listed on the review task\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Task file content\"\n },\n \"302\": {\n \"description\": \"Redirect to a short-lived signed storage download\"\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/human-reviews/{taskId}/reject\": {\n \"post\": {\n \"operationId\": \"humanReviews.reject\",\n \"summary\": \"Reject human review task\",\n \"description\": \"Reject a review task and fail the paused run with the supplied reason.\",\n \"tags\": [\n \"Human reviews\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"taskId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Human review task id\"\n },\n \"required\": true,\n \"description\": \"Human review task id\"\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"type\": \"object\",\n \"properties\": {\n \"expectedVersion\": {\n \"type\": \"integer\",\n \"exclusiveMinimum\": 0,\n \"maximum\": 9007199254740991\n },\n \"idempotencyKey\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 200\n },\n \"reason\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 5000\n }\n },\n \"required\": [\n \"expectedVersion\",\n \"idempotencyKey\",\n \"reason\"\n ],\n \"additionalProperties\": false\n }\n }\n }\n },\n \"responses\": {\n \"200\": {\n \"description\": \"Rejected task\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/HumanReviewRejectResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/models\": {\n \"get\": {\n \"operationId\": \"models.list\",\n \"summary\": \"List configured models\",\n \"description\": \"List text, vision, and OCR models configured for this tenant's environment from the workspace model catalog. This is a cheap read-only inventory: it does not call providers. `health` is `configured` or `unconfigured` from local credentials, never a live probe. Secrets and provider endpoints are never returned.\",\n \"tags\": [\n \"Models\"\n ],\n \"parameters\": [\n {\n \"in\": \"query\",\n \"name\": \"capability\",\n \"schema\": {\n \"description\": \"Return only models that support this capability (`text`, `vision`, or `ocr`).\",\n \"type\": \"string\",\n \"enum\": [\n \"text\",\n \"vision\",\n \"ocr\"\n ]\n },\n \"description\": \"Return only models that support this capability (`text`, `vision`, or `ocr`).\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Configured models\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ListModelsResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/runs\": {\n \"get\": {\n \"operationId\": \"runs.list\",\n \"summary\": \"List runs\",\n \"description\": \"List workflow and agent runs with cursor pagination.\",\n \"tags\": [\n \"Runs\"\n ],\n \"parameters\": [\n {\n \"in\": \"query\",\n \"name\": \"type\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"source\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"status\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"trigger\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"triggeredBy\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"sourceRef\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"batchId\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"exampleId\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"exampleIdContains\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"from\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"to\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"createdAfter\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"createdBefore\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"completedAfter\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"completedBefore\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"cursor\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"offset\",\n \"schema\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 9007199254740991\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"limit\",\n \"schema\": {\n \"type\": \"integer\",\n \"minimum\": 1,\n \"maximum\": 100\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"ids\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"experiments\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"sort\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"order\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"reviewStatus\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"reviewVerdict\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"hasReview\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"noReview\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"hasCorrections\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"reviewNoteContains\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"reviewCreatedAfter\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"reviewCreatedBefore\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"reviewUpdatedAfter\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"reviewUpdatedBefore\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"reviewClosedAfter\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"reviewClosedBefore\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"sinceLastClosed\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"sampleRate\",\n \"schema\": {\n \"description\": \"Keep runs whose `sampleRank` is below this threshold (0–1). Pages may return fewer than `limit` rows when filtered.\",\n \"type\": \"string\"\n },\n \"description\": \"Keep runs whose `sampleRank` is below this threshold (0–1). Pages may return fewer than `limit` rows when filtered.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Runs page\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/RunsListResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"post\": {\n \"operationId\": \"runs.start\",\n \"summary\": \"Start a run\",\n \"description\": \"Start a run. Send JSON or multipart/form-data.\\n\\nHow to read a run: the envelope is at the root. The automation business result is in `output` (per-automation, not this generic schema). Status is `execution.status` (`execution.retry.nextRun.status` is a later retry). `input`, `usage`, and `debug` appear only with `?expand=`. `eval` is present only on eval-scoped runs.\",\n \"tags\": [\n \"Runs\"\n ],\n \"parameters\": [\n {\n \"in\": \"query\",\n \"name\": \"version\",\n \"schema\": {\n \"description\": \"Release or git ref. Defaults to latest.\",\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"description\": \"Release or git ref. Defaults to latest.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"wait_for_completion\",\n \"schema\": {\n \"description\": \"Seconds to wait before returning (max 600). Omit for async.\",\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 600\n },\n \"description\": \"Seconds to wait before returning (max 600). Omit for async.\"\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/RunStartBody\"\n }\n },\n \"multipart/form-data\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/RunStartMultipartRequest\"\n }\n }\n }\n },\n \"responses\": {\n \"200\": {\n \"description\": \"Run completed while waiting — same body as GET /api/v1/runs/:id\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/Run\"\n }\n }\n }\n },\n \"201\": {\n \"description\": \"Run accepted (async)\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/RunAccepted\"\n }\n }\n }\n },\n \"202\": {\n \"description\": \"Wait expired with a non-terminal status — poll GET /api/v1/runs/:id\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/RunAccepted\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"Trigger disabled or insufficient scope. Run start may return api_trigger_disabled when the API trigger is off, or manual_trigger_disabled for dashboard runs on API-only workflows.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/runs/{id}\": {\n \"get\": {\n \"operationId\": \"runs.get\",\n \"summary\": \"Get a run\",\n \"description\": \"Fetch one run by id. By default this returns core metadata plus terminal output/error fields. Pass `?expand=input,usage,execution,debug` to include detailed sub-objects; `expand=execution` is also where embedded review and expected artifacts appear.\\n\\nHow to read a run: the envelope is at the root. The automation business result is in `output` (per-automation, not this generic schema). Status is `execution.status` (`execution.retry.nextRun.status` is a later retry). `input`, `usage`, and `debug` appear only with `?expand=`. `eval` is present only on eval-scoped runs.\",\n \"tags\": [\n \"Runs\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Run id\"\n },\n \"required\": true,\n \"description\": \"Run id\"\n },\n {\n \"in\": \"query\",\n \"name\": \"expand\",\n \"schema\": {\n \"description\": \"Optional sections: `input`, `usage`, `execution`, `debug`. Terminal runs always include top-level output, files, and error.\",\n \"type\": \"string\"\n },\n \"description\": \"Optional sections: `input`, `usage`, `execution`, `debug`. Terminal runs always include top-level output, files, and error.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Run detail. Expanded sections appear only when requested.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/Run\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/runs/{id}/artifacts\": {\n \"get\": {\n \"operationId\": \"runs.artifacts.list\",\n \"summary\": \"List run artifacts\",\n \"description\": \"Returns a JSON list of downloadable artifact paths for a run. Pass `zip=1` to switch the response to a ZIP download containing output files.\",\n \"tags\": [\n \"Runs\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Run id\"\n },\n \"required\": true,\n \"description\": \"Run id\"\n },\n {\n \"in\": \"query\",\n \"name\": \"zip\",\n \"schema\": {\n \"description\": \"When `1`, download output files as a ZIP instead of listing paths. Does not include trace, scores, or input — use `GET /runs/{id}/scores` and `GET /runs/{id}/trace` for those. Cloud deployments reject archives whose uncompressed inputs exceed 32 MiB (`413 artifacts_zip_too_large`); download files individually or pass a smaller `files=` subset.\",\n \"type\": \"string\",\n \"enum\": [\n \"1\"\n ]\n },\n \"description\": \"When `1`, download output files as a ZIP instead of listing paths. Does not include trace, scores, or input — use `GET /runs/{id}/scores` and `GET /runs/{id}/trace` for those. Cloud deployments reject archives whose uncompressed inputs exceed 32 MiB (`413 artifacts_zip_too_large`); download files individually or pass a smaller `files=` subset.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"bundle\",\n \"schema\": {\n \"description\": \"With `zip=1`, use `review` to download a ZIP with `output/` and `expected/` folders (corrected review artifacts).\",\n \"type\": \"string\",\n \"enum\": [\n \"review\"\n ]\n },\n \"description\": \"With `zip=1`, use `review` to download a ZIP with `output/` and `expected/` folders (corrected review artifacts).\"\n },\n {\n \"in\": \"query\",\n \"name\": \"token\",\n \"schema\": {\n \"description\": \"Signed email download token (zip only; no Bearer required).\",\n \"type\": \"string\"\n },\n \"description\": \"Signed email download token (zip only; no Bearer required).\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"JSON artifact list, or ZIP bytes when `zip=1`.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/RunArtifactsResponse\"\n }\n },\n \"application/octet-stream\": {\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"ZIP archive\",\n \"format\": \"binary\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/runs/{id}/artifacts/{path}\": {\n \"get\": {\n \"operationId\": \"runs.artifacts.get\",\n \"summary\": \"Download run artifact\",\n \"description\": \"Download one artifact by path. Cloud deployments may redirect to a short-lived storage URL for large files.\",\n \"tags\": [\n \"Runs\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\"\n },\n \"required\": true\n },\n {\n \"in\": \"path\",\n \"name\": \"path\",\n \"schema\": {\n \"type\": \"string\"\n },\n \"required\": true\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Run artifact\"\n },\n \"302\": {\n \"description\": \"Redirect to a short-lived signed storage download\"\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/runs/{id}/cancel\": {\n \"post\": {\n \"operationId\": \"runs.cancel\",\n \"summary\": \"Cancel run\",\n \"description\": \"Cancel a queued run or request cancellation of an in-flight run.\",\n \"tags\": [\n \"Runs\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\"\n },\n \"required\": true\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Cancellation result\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/RunCancelResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/runs/{id}/events\": {\n \"get\": {\n \"operationId\": \"runs.events.list\",\n \"summary\": \"List run events\",\n \"description\": \"List a stable chronological lifecycle timeline for a run.\",\n \"tags\": [\n \"Runs\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Run id\"\n },\n \"required\": true,\n \"description\": \"Run id\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Run events\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/RunEventsResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/runs/{id}/promote\": {\n \"post\": {\n \"operationId\": \"runs.promote\",\n \"summary\": \"Promote run to example\",\n \"description\": \"Turn a reviewed run into a dataset example. The new example uses the run input and any corrected output/files stored through the review endpoints.\",\n \"tags\": [\n \"Reviews\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Run id.\"\n },\n \"required\": true,\n \"description\": \"Run id.\"\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/PromoteRunRequest\"\n }\n }\n }\n },\n \"responses\": {\n \"200\": {\n \"description\": \"Created or updated a dataset example from the run\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/PromoteRunResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/runs/{id}/rerun\": {\n \"post\": {\n \"operationId\": \"runs.rerun\",\n \"summary\": \"Retry run\",\n \"description\": \"Start a new run using the source run input. By default the retry uses the latest automation version; pass `version=original` to pin the same source version as the original run.\",\n \"tags\": [\n \"Runs\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Source run id to retry.\"\n },\n \"required\": true,\n \"description\": \"Source run id to retry.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"version\",\n \"schema\": {\n \"description\": \"Version for the new run. `original` pins the source run. Defaults to latest.\",\n \"type\": \"string\"\n },\n \"description\": \"Version for the new run. `original` pins the source run. Defaults to latest.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"wait_for_completion\",\n \"schema\": {\n \"description\": \"Seconds to wait before returning (max 600). Omit for async.\",\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 600\n },\n \"description\": \"Seconds to wait before returning (max 600). Omit for async.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Rerun completed while waiting\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/Run\"\n }\n }\n }\n },\n \"201\": {\n \"description\": \"Rerun accepted (async)\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/RunAccepted\"\n }\n }\n }\n },\n \"202\": {\n \"description\": \"Wait expired with a non-terminal status — poll GET /api/v1/runs/:id\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/RunAccepted\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/runs/{id}/reviews\": {\n \"get\": {\n \"operationId\": \"runs.reviews.get\",\n \"summary\": \"Get run review\",\n \"description\": \"Returns review metadata and corrections for a run. Corrected files are listed at GET /runs/{id}/reviews/expected; embed review + expected artifacts with GET /runs/{id}?expand=execution.\",\n \"tags\": [\n \"Reviews\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Run id.\"\n },\n \"required\": true,\n \"description\": \"Run id.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Run review metadata.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/RunReviewDetail\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"put\": {\n \"operationId\": \"runs.reviews.update\",\n \"summary\": \"Update run review\",\n \"description\": \"Create or replace review metadata for a run.\",\n \"tags\": [\n \"Reviews\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Run id.\"\n },\n \"required\": true,\n \"description\": \"Run id.\"\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/RunReviewRequest\"\n }\n }\n }\n },\n \"responses\": {\n \"200\": {\n \"description\": \"Updated run review metadata.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/RunReviewDetail\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"delete\": {\n \"operationId\": \"runs.reviews.clear\",\n \"summary\": \"Clear run review\",\n \"description\": \"Deletes review metadata, corrections, and corrected files for the run.\",\n \"tags\": [\n \"Reviews\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Run id.\"\n },\n \"required\": true,\n \"description\": \"Run id.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Empty run review state.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/RunReviewDetail\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/runs/{id}/reviews/expected\": {\n \"get\": {\n \"operationId\": \"runs.reviews.expected.get\",\n \"summary\": \"List corrected files\",\n \"description\": \"Returns corrected artifact files attached to the run review. Review metadata and corrected JSON output live at GET /runs/{id}/reviews.\",\n \"tags\": [\n \"Reviews\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Run id.\"\n },\n \"required\": true,\n \"description\": \"Run id.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Corrected artifact files.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/RunReviewExpectedArtifacts\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"post\": {\n \"operationId\": \"runs.reviews.expected.create\",\n \"summary\": \"Add corrected file\",\n \"description\": \"Attach one corrected file to a run review. Send multipart/form-data with `file` and optional `name` to upload a local file, or JSON with `outputFileName` and optional `expectedName` to copy an existing run output file.\",\n \"tags\": [\n \"Reviews\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Run id.\"\n },\n \"required\": true,\n \"description\": \"Run id.\"\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/RunReviewExpectedFileCopyRequest\"\n }\n },\n \"multipart/form-data\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/RunReviewExpectedFileUploadRequest\"\n }\n }\n }\n },\n \"responses\": {\n \"201\": {\n \"description\": \"Corrected file created.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/RunReviewExpectedFileMutationResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/runs/{id}/reviews/expected/{filename}\": {\n \"get\": {\n \"operationId\": \"runs.reviews.expected.file.get\",\n \"summary\": \"Download corrected artifact file\",\n \"description\": \"Downloads one corrected artifact file attached to the run review. Use the `filename` returned by the corrected-output collection endpoint.\",\n \"tags\": [\n \"Reviews\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Run id.\"\n },\n \"required\": true,\n \"description\": \"Run id.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"filename\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Corrected artifact file name or slash-delimited path, as returned by `GET /runs/{id}/reviews/expected`.\"\n },\n \"required\": true,\n \"description\": \"Corrected artifact file name or slash-delimited path, as returned by `GET /runs/{id}/reviews/expected`.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Corrected file bytes.\",\n \"content\": {\n \"application/octet-stream\": {\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Corrected file bytes.\",\n \"format\": \"binary\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"patch\": {\n \"operationId\": \"runs.reviews.expected.file.update\",\n \"summary\": \"Rename corrected artifact file\",\n \"description\": \"Renames one corrected artifact file attached to the run review.\",\n \"tags\": [\n \"Reviews\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Run id.\"\n },\n \"required\": true,\n \"description\": \"Run id.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"filename\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Corrected artifact file name or slash-delimited path, as returned by `GET /runs/{id}/reviews/expected`.\"\n },\n \"required\": true,\n \"description\": \"Corrected artifact file name or slash-delimited path, as returned by `GET /runs/{id}/reviews/expected`.\"\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/RunReviewExpectedFileUpdateRequest\"\n }\n }\n }\n },\n \"responses\": {\n \"200\": {\n \"description\": \"Renamed corrected file.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/RunReviewExpectedFileUpdateResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"delete\": {\n \"operationId\": \"runs.reviews.expected.file.delete\",\n \"summary\": \"Delete corrected artifact file\",\n \"description\": \"Deletes one corrected artifact file attached to the run review.\",\n \"tags\": [\n \"Reviews\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Run id.\"\n },\n \"required\": true,\n \"description\": \"Run id.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"filename\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Corrected artifact file name or slash-delimited path, as returned by `GET /runs/{id}/reviews/expected`.\"\n },\n \"required\": true,\n \"description\": \"Corrected artifact file name or slash-delimited path, as returned by `GET /runs/{id}/reviews/expected`.\"\n }\n ],\n \"responses\": {\n \"204\": {\n \"description\": \"Corrected file deleted; no response body.\"\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/runs/{id}/scores\": {\n \"get\": {\n \"operationId\": \"runs.scores.list\",\n \"summary\": \"List run evaluator scores\",\n \"description\": \"List automated evaluator results for one run. Use `score` for evaluator output and run reviews for human verdicts.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Run id.\"\n },\n \"required\": true,\n \"description\": \"Run id.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Per-evaluator scores for the run\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/RunScoresResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/runs/{id}/steps\": {\n \"get\": {\n \"operationId\": \"runs.steps.list\",\n \"summary\": \"List run steps\",\n \"description\": \"List slim workflow step rows for a run (no input/output payloads) plus the total count. Fetch a single step for full payloads.\",\n \"tags\": [\n \"Runs\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Run id\"\n },\n \"required\": true,\n \"description\": \"Run id\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Run steps\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/RunStepsResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/runs/{id}/steps/{stepExecutionId}\": {\n \"get\": {\n \"operationId\": \"runs.steps.get\",\n \"summary\": \"Get a run step\",\n \"description\": \"Return the full single step execution (including input/output) for on-demand inspection. The step must belong to this run or a child invoke-workflow run.\",\n \"tags\": [\n \"Runs\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Run id\"\n },\n \"required\": true,\n \"description\": \"Run id\"\n },\n {\n \"in\": \"path\",\n \"name\": \"stepExecutionId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Step execution id\"\n },\n \"required\": true,\n \"description\": \"Step execution id\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Full step execution\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/RunStepDetailResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/runs/{id}/trace\": {\n \"get\": {\n \"operationId\": \"runs.trace.get\",\n \"summary\": \"Get run trace\",\n \"description\": \"Return low-level execution trace events for debugging one run. Workflow runs expose observability phases or step records; agent runs expose parsed trace.jsonl events. The shape is intentionally extensible, but common fields are documented.\",\n \"tags\": [\n \"Runs\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Run id.\"\n },\n \"required\": true,\n \"description\": \"Run id.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Run trace events.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/RunTraceResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/runs/{id}/usage\": {\n \"get\": {\n \"operationId\": \"runs.usage.get\",\n \"summary\": \"Get run usage\",\n \"description\": \"Get token, credit, duration, and execution usage for a run.\",\n \"tags\": [\n \"Runs\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Run id\"\n },\n \"required\": true,\n \"description\": \"Run id\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Run usage\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/RunUsageResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/templates\": {\n \"get\": {\n \"operationId\": \"templates.list\",\n \"summary\": \"List templates\",\n \"description\": \"List tenant-scoped DOCX and XLSX template resources.\",\n \"tags\": [\n \"Templates\"\n ],\n \"parameters\": [\n {\n \"in\": \"query\",\n \"name\": \"limit\",\n \"schema\": {\n \"type\": \"integer\",\n \"minimum\": 1,\n \"maximum\": 100\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"offset\",\n \"schema\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 9007199254740991\n }\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Template resources\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ListTemplatesResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"post\": {\n \"operationId\": \"templates.create\",\n \"summary\": \"Upload template\",\n \"description\": \"Create a stable `tmpl_…` resource and its first immutable content revision from a reusable `fileId`. Public SDK helpers `create(file)` and `createFromFileId(fileId)` upload through the Files API when needed, then send this JSON body. Generated clients send `{ fileId }` JSON only. The HTTP route still accepts a multipart `file` for CLI/internal use; that path is not generated into the public SDKs.\",\n \"tags\": [\n \"Templates\"\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/TemplateFileReferenceRequest\"\n }\n }\n }\n },\n \"responses\": {\n \"201\": {\n \"description\": \"Created template\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/CreatedTemplate\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"422\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/templates/{id}\": {\n \"get\": {\n \"operationId\": \"templates.get\",\n \"summary\": \"Inspect template\",\n \"description\": \"Get template metadata, checksum, discovered tokens, grammar capabilities, and current immutable revision. Storage keys are never exposed.\",\n \"tags\": [\n \"Templates\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"pattern\": \"^tmpl_[A-Za-z0-9_-]{21}$\",\n \"description\": \"Logical template id (tmpl_…).\"\n },\n \"required\": true,\n \"description\": \"Logical template id (tmpl_…).\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Template inspection\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/Template\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"put\": {\n \"operationId\": \"templates.replace\",\n \"summary\": \"Create template revision\",\n \"description\": \"Append an immutable revision and advance the logical template pointer from a reusable `fileId`. Public SDK helpers `replace(file)` and `replaceFromFileId(fileId)` upload through the Files API when needed, then send this JSON body. Generated clients send `{ fileId }` JSON only. The HTTP route still accepts a multipart `file` for CLI/internal use; that path is not generated into the public SDKs.\",\n \"tags\": [\n \"Templates\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"pattern\": \"^tmpl_[A-Za-z0-9_-]{21}$\",\n \"description\": \"Logical template id (tmpl_…).\"\n },\n \"required\": true,\n \"description\": \"Logical template id (tmpl_…).\"\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/TemplateReplaceRequest\"\n }\n }\n }\n },\n \"responses\": {\n \"200\": {\n \"description\": \"Updated template\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/Template\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"422\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"delete\": {\n \"operationId\": \"templates.delete\",\n \"summary\": \"Delete template\",\n \"description\": \"Delete the mutable logical template. Immutable revisions are retained so workflows pinned with `templateRevisionId` continue to execute; unpinned workflows can no longer resolve the deleted `tmpl_…` id.\",\n \"tags\": [\n \"Templates\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"pattern\": \"^tmpl_[A-Za-z0-9_-]{21}$\",\n \"description\": \"Logical template id (tmpl_…).\"\n },\n \"required\": true,\n \"description\": \"Logical template id (tmpl_…).\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Template deleted\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DeleteTemplateResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/templates/{id}/content\": {\n \"get\": {\n \"operationId\": \"templates.content.get\",\n \"summary\": \"Download template content\",\n \"description\": \"Download current bytes while the logical template exists, or a specific immutable revision using `revisionId`. Pinned revision downloads remain available after logical template deletion. Large objects may 302 to a short-lived signed storage URL.\",\n \"tags\": [\n \"Templates\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"pattern\": \"^tmpl_[A-Za-z0-9_-]{21}$\",\n \"description\": \"Logical template id (tmpl_…).\"\n },\n \"required\": true,\n \"description\": \"Logical template id (tmpl_…).\"\n },\n {\n \"in\": \"query\",\n \"name\": \"revisionId\",\n \"schema\": {\n \"description\": \"Immutable revision id (tmpr_…). Omit for the current content.\",\n \"type\": \"string\",\n \"pattern\": \"^tmpr_[A-Za-z0-9_-]{21}$\"\n },\n \"description\": \"Immutable revision id (tmpr_…). Omit for the current content.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Template binary content\",\n \"content\": {\n \"application/octet-stream\": {\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Template file bytes (DOCX or XLSX).\",\n \"format\": \"binary\"\n }\n }\n }\n },\n \"302\": {\n \"description\": \"Redirect to a short-lived signed storage download\"\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/templates/{id}/staging\": {\n \"post\": {\n \"operationId\": \"templates.staging\",\n \"summary\": \"Finalize or hard-clean a staged template\",\n \"description\": \"Consume the one-time cleanupProof issued on a staged create. `finalize` makes the template live so later deletion keeps pinned revisions. `cleanup` hard-removes only unpublished resources from that staging attempt. Normal DELETE is unchanged and never takes this path.\",\n \"tags\": [\n \"Templates\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"pattern\": \"^tmpl_[A-Za-z0-9_-]{21}$\",\n \"description\": \"Logical template id (tmpl_…).\"\n },\n \"required\": true,\n \"description\": \"Logical template id (tmpl_…).\"\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/TemplateStagingRequest\"\n }\n }\n }\n },\n \"responses\": {\n \"200\": {\n \"description\": \"Staging action applied\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/TemplateStagingResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"409\": {\n \"description\": \"Conflict. The resource is in a state that forbids the request.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n }\n },\n \"components\": {\n \"schemas\": {\n \"UpdateAutomationRequest\": {\n \"type\": \"object\",\n \"properties\": {\n \"folderId\": {\n \"description\": \"Move a YAML workflow into this workflow folder. `null` files it at the tenant root. Ignored for the folder lookup when `folderPath` is also sent, but a string value is still validated before the path is applied.\",\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"folderPath\": {\n \"description\": \"Slash-separated workflow folder path. Missing folders are created. Empty or `/` means root. When both fields are sent, `folderPath` wins after `folderId` validation.\",\n \"type\": \"string\"\n }\n }\n },\n \"CreateDatasetReviewRequest\": {\n \"type\": \"object\",\n \"properties\": {\n \"title\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"instructions\": {\n \"description\": \"Note shown to the reviewer for the whole request.\",\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"focusFields\": {\n \"description\": \"Expected-output paths to highlight. Other fields stay normal unless listed in ignoredFields.\",\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/DatasetReviewFocusField\"\n }\n },\n \"ignoredFields\": {\n \"description\": \"Expected-output paths reviewers can skip. Shown muted as not required. Prefixes apply to nested leaves.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"itemNotes\": {\n \"description\": \"Optional per-example and per-field notes seeded as commented events at create time.\",\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/DatasetReviewCreateItemNote\"\n }\n },\n \"exampleNames\": {\n \"minItems\": 1,\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"status\": {\n \"type\": \"string\",\n \"enum\": [\n \"draft\",\n \"open\",\n \"paused\"\n ]\n }\n },\n \"required\": [\n \"title\",\n \"exampleNames\"\n ]\n },\n \"DatasetReviewFocusField\": {\n \"type\": \"object\",\n \"properties\": {\n \"path\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"Dotted expected-output path the reviewer should inspect, e.g. vendor.iban.\"\n },\n \"reason\": {\n \"description\": \"Optional reason this field needs attention.\",\n \"anyOf\": [\n {\n \"type\": \"string\",\n \"minLength\": 1\n },\n {\n \"type\": \"null\"\n }\n ]\n }\n },\n \"required\": [\n \"path\"\n ]\n },\n \"DatasetReviewCreateItemNote\": {\n \"type\": \"object\",\n \"properties\": {\n \"exampleName\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"comment\": {\n \"anyOf\": [\n {\n \"type\": \"string\",\n \"minLength\": 1\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"fields\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/DatasetReviewItemFieldNote\"\n }\n }\n },\n \"required\": [\n \"exampleName\"\n ]\n },\n \"DatasetReviewItemFieldNote\": {\n \"type\": \"object\",\n \"properties\": {\n \"path\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"comment\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"required\": [\n \"path\",\n \"comment\"\n ]\n },\n \"UpdateDatasetReviewRequest\": {\n \"type\": \"object\",\n \"properties\": {\n \"title\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"instructions\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"focusFields\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/DatasetReviewFocusField\"\n }\n },\n \"ignoredFields\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"status\": {\n \"type\": \"string\",\n \"enum\": [\n \"draft\",\n \"open\",\n \"paused\",\n \"closed\"\n ]\n }\n },\n \"additionalProperties\": false\n },\n \"UpdateDatasetReviewItem\": {\n \"type\": \"object\",\n \"properties\": {\n \"action\": {\n \"type\": \"string\",\n \"enum\": [\n \"approve\",\n \"edit\",\n \"reject\",\n \"reopen\",\n \"comment\",\n \"field-decision\"\n ]\n },\n \"expected\": {},\n \"comment\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"fieldPath\": {\n \"anyOf\": [\n {\n \"type\": \"string\",\n \"minLength\": 1\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"decision\": {\n \"anyOf\": [\n {\n \"type\": \"string\",\n \"enum\": [\n \"approved\",\n \"rejected\"\n ]\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"expectedUpdatedAt\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"ISO timestamp of the item `updatedAt` the client last observed. Required for optimistic concurrency.\"\n }\n },\n \"required\": [\n \"action\",\n \"expectedUpdatedAt\"\n ]\n },\n \"AutomationDatasetImportMultipartRequest\": {\n \"type\": \"object\",\n \"properties\": {\n \"file\": {\n \"type\": \"string\",\n \"description\": \"Dataset ZIP file\",\n \"format\": \"binary\"\n },\n \"mode\": {\n \"description\": \"`append` adds examples without deleting existing rows. `replace` deletes the current dataset before importing.\",\n \"type\": \"string\",\n \"enum\": [\n \"append\",\n \"replace\"\n ]\n }\n },\n \"required\": [\n \"file\"\n ]\n },\n \"EvaluatorConfigUpdate\": {\n \"type\": \"object\",\n \"properties\": {\n \"yaml\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 1048576,\n \"description\": \"Complete evaluator YAML to validate and store.\"\n }\n },\n \"required\": [\n \"yaml\"\n ],\n \"description\": \"Replacement evaluator configuration.\"\n },\n \"DatasetExampleMutation\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"description\": \"Example name. Required on create; omitted or null uses a generated name where supported.\",\n \"anyOf\": [\n {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 128\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"input\": {\n \"description\": \"Input arguments for the example.\",\n \"anyOf\": [\n {\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {}\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"expected\": {\n \"description\": \"Expected JSON output. Null clears the expected output.\",\n \"anyOf\": [\n {},\n {\n \"type\": \"null\"\n }\n ]\n },\n \"metadata\": {\n \"description\": \"Caller-managed metadata.\",\n \"anyOf\": [\n {\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {}\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"annotation\": {\n \"description\": \"Human note about the example. Null clears the annotation.\",\n \"anyOf\": [\n {\n \"type\": \"string\",\n \"maxLength\": 2000\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"rowOrder\": {\n \"description\": \"Optional display order. Null clears the order.\",\n \"anyOf\": [\n {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 9007199254740991\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"overrides\": {\n \"description\": \"Step output overrides used during example runs.\",\n \"anyOf\": [\n {\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {}\n },\n {\n \"type\": \"null\"\n }\n ]\n }\n },\n \"description\": \"Fields used to create or update a dataset example.\"\n },\n \"DatasetExampleUpdate\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"description\": \"Example name. Required on create; omitted or null uses a generated name where supported.\",\n \"anyOf\": [\n {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 128\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"input\": {\n \"description\": \"Input arguments for the example.\",\n \"anyOf\": [\n {\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {}\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"expected\": {\n \"description\": \"Expected JSON output. Null clears the expected output.\",\n \"anyOf\": [\n {},\n {\n \"type\": \"null\"\n }\n ]\n },\n \"metadata\": {\n \"description\": \"Caller-managed metadata.\",\n \"anyOf\": [\n {\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {}\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"annotation\": {\n \"description\": \"Human note about the example. Null clears the annotation.\",\n \"anyOf\": [\n {\n \"type\": \"string\",\n \"maxLength\": 2000\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"rowOrder\": {\n \"description\": \"Optional display order. Null clears the order.\",\n \"anyOf\": [\n {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 9007199254740991\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"overrides\": {\n \"description\": \"Step output overrides used during example runs.\",\n \"anyOf\": [\n {\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {}\n },\n {\n \"type\": \"null\"\n }\n ]\n }\n },\n \"additionalProperties\": false,\n \"description\": \"Partial update for a dataset example. Omitted fields are preserved.\"\n },\n \"DatasetExampleExpectedFileUploadRequest\": {\n \"type\": \"object\",\n \"properties\": {\n \"file\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\",\n \"format\": \"binary\"\n },\n \"description\": \"One or more expected files to upload.\"\n }\n },\n \"required\": [\n \"file\"\n ]\n },\n \"DatasetExampleExpectedFileRenameRequest\": {\n \"type\": \"object\",\n \"properties\": {\n \"newFilename\": {\n \"type\": \"string\",\n \"description\": \"New basename for the file. The parent folder is preserved.\"\n }\n },\n \"required\": [\n \"newFilename\"\n ]\n },\n \"DatasetExampleInputFileUploadRequest\": {\n \"type\": \"object\",\n \"properties\": {\n \"file\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\",\n \"format\": \"binary\"\n },\n \"description\": \"One or more input files to upload.\"\n }\n },\n \"required\": [\n \"file\"\n ]\n },\n \"DatasetExampleInputFileRenameRequest\": {\n \"type\": \"object\",\n \"properties\": {\n \"newFilename\": {\n \"type\": \"string\",\n \"description\": \"New basename for the file. The parent folder is preserved.\"\n }\n },\n \"required\": [\n \"newFilename\"\n ]\n },\n \"ExperimentCreate\": {\n \"type\": \"object\",\n \"properties\": {\n \"examples\": {\n \"description\": \"Optional dataset example ids to run. Omit to run the full dataset.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n },\n \"batchConcurrency\": {\n \"description\": \"Maximum concurrent example runs for this experiment.\",\n \"anyOf\": [\n {\n \"type\": \"integer\",\n \"exclusiveMinimum\": 0,\n \"maximum\": 9007199254740991\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"sourceRef\": {\n \"description\": \"Optional source version/ref to use for experiment runs.\",\n \"type\": \"string\"\n }\n },\n \"description\": \"Request body for starting an experiment batch.\"\n },\n \"CreateAutomationVersionRequest\": {\n \"anyOf\": [\n {\n \"type\": \"object\",\n \"properties\": {\n \"yaml\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 1048576,\n \"description\": \"Validated workflow YAML to publish as a new tagged version. Mutually exclusive with `historyId`. At most 1 MiB.\"\n },\n \"version\": {\n \"type\": \"string\",\n \"pattern\": \"^\\\\d+\\\\.\\\\d+\\\\.\\\\d+$\",\n \"description\": \"Bare semver tag such as 1.2.0. Do not include a leading v.\"\n },\n \"activate\": {\n \"description\": \"Whether to make the new version current immediately. Defaults to true. Set false to keep a tagged candidate off live traffic until promote. `activate: false` requires an existing current workflow version and returns 400 if HEAD is empty.\",\n \"type\": \"boolean\"\n }\n },\n \"required\": [\n \"yaml\",\n \"version\"\n ],\n \"additionalProperties\": false\n },\n {\n \"type\": \"object\",\n \"properties\": {\n \"historyId\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"Existing version id from GET /automations/{id}/versions. Creates a new tagged snapshot copied from that version; the source tag is left unchanged. Mutually exclusive with `yaml`.\"\n },\n \"version\": {\n \"type\": \"string\",\n \"pattern\": \"^\\\\d+\\\\.\\\\d+\\\\.\\\\d+$\",\n \"description\": \"Bare semver tag such as 1.2.0. Do not include a leading v.\"\n },\n \"activate\": {\n \"description\": \"Whether to make the new version current immediately. Defaults to true. Set false to keep a tagged candidate off live traffic until promote. `activate: false` requires an existing current workflow version and returns 400 if HEAD is empty.\",\n \"type\": \"boolean\"\n }\n },\n \"required\": [\n \"historyId\",\n \"version\"\n ],\n \"additionalProperties\": false\n }\n ],\n \"description\": \"Exactly one of `yaml` or `historyId`, plus a bare semver `version`. YAML is capped at 1 MiB. `historyId` copies the selected snapshot into a new tagged row and does not retag the source. Set `activate: false` to create a detached candidate that does not move live HEAD; that path requires an existing current version.\"\n },\n \"RestoreAutomationVersionRequest\": {\n \"type\": \"object\",\n \"properties\": {\n \"message\": {\n \"description\": \"Optional restore commit message. Defaults to a timestamped restore note.\",\n \"type\": \"string\"\n }\n },\n \"description\": \"Optional JSON body. Send `{}` when no message is needed. Restore always creates a new untagged current snapshot; it does not retag the source version.\"\n },\n \"CreateEmailServerRequest\": {\n \"oneOf\": [\n {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 128\n },\n \"enabled\": {\n \"default\": true,\n \"type\": \"boolean\"\n },\n \"transport\": {\n \"type\": \"string\",\n \"const\": \"resend\"\n },\n \"apiKey\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"fromEmail\": {\n \"type\": \"string\",\n \"format\": \"email\",\n \"pattern\": \"^(?!\\\\.)(?!.*\\\\.\\\\.)([A-Za-z0-9_'+\\\\-\\\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\\\-]*\\\\.)+[A-Za-z]{2,}$\"\n },\n \"fromName\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 128\n }\n },\n \"required\": [\n \"name\",\n \"transport\",\n \"apiKey\",\n \"fromEmail\",\n \"fromName\"\n ],\n \"additionalProperties\": false\n },\n {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 128\n },\n \"enabled\": {\n \"default\": true,\n \"type\": \"boolean\"\n },\n \"transport\": {\n \"type\": \"string\",\n \"const\": \"smtp\"\n },\n \"host\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 253\n },\n \"port\": {\n \"type\": \"integer\",\n \"minimum\": 1,\n \"maximum\": 65535\n },\n \"security\": {\n \"default\": \"starttls\",\n \"type\": \"string\",\n \"enum\": [\n \"starttls\",\n \"tls\",\n \"none\"\n ]\n },\n \"username\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 256\n },\n \"password\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"caPem\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"fromEmail\": {\n \"type\": \"string\",\n \"format\": \"email\",\n \"pattern\": \"^(?!\\\\.)(?!.*\\\\.\\\\.)([A-Za-z0-9_'+\\\\-\\\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\\\-]*\\\\.)+[A-Za-z]{2,}$\"\n },\n \"fromName\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 128\n }\n },\n \"required\": [\n \"name\",\n \"transport\",\n \"host\",\n \"fromEmail\",\n \"fromName\"\n ],\n \"additionalProperties\": false\n }\n ],\n \"type\": \"object\"\n },\n \"UpdateEmailServerRequest\": {\n \"anyOf\": [\n {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 128\n },\n \"enabled\": {\n \"type\": \"boolean\"\n },\n \"transport\": {\n \"type\": \"string\",\n \"const\": \"resend\"\n },\n \"apiKey\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"fromEmail\": {\n \"type\": \"string\",\n \"format\": \"email\",\n \"pattern\": \"^(?!\\\\.)(?!.*\\\\.\\\\.)([A-Za-z0-9_'+\\\\-\\\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\\\-]*\\\\.)+[A-Za-z]{2,}$\"\n },\n \"fromName\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 128\n }\n },\n \"required\": [\n \"transport\",\n \"fromEmail\",\n \"fromName\"\n ],\n \"additionalProperties\": false\n },\n {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 128\n },\n \"enabled\": {\n \"type\": \"boolean\"\n },\n \"transport\": {\n \"type\": \"string\",\n \"const\": \"smtp\"\n },\n \"host\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 253\n },\n \"port\": {\n \"type\": \"integer\",\n \"minimum\": 1,\n \"maximum\": 65535\n },\n \"security\": {\n \"type\": \"string\",\n \"enum\": [\n \"starttls\",\n \"tls\",\n \"none\"\n ]\n },\n \"username\": {\n \"anyOf\": [\n {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 256\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"password\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"caPem\": {\n \"anyOf\": [\n {\n \"type\": \"string\",\n \"minLength\": 1\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"fromEmail\": {\n \"type\": \"string\",\n \"format\": \"email\",\n \"pattern\": \"^(?!\\\\.)(?!.*\\\\.\\\\.)([A-Za-z0-9_'+\\\\-\\\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\\\-]*\\\\.)+[A-Za-z]{2,}$\"\n },\n \"fromName\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 128\n }\n },\n \"required\": [\n \"transport\",\n \"host\",\n \"port\",\n \"security\",\n \"fromEmail\",\n \"fromName\"\n ],\n \"additionalProperties\": false\n },\n {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 128\n },\n \"enabled\": {\n \"type\": \"boolean\"\n }\n },\n \"additionalProperties\": false\n }\n ]\n },\n \"TestEmailServerRequest\": {\n \"type\": \"object\",\n \"properties\": {\n \"to\": {\n \"type\": \"string\",\n \"format\": \"email\",\n \"pattern\": \"^(?!\\\\.)(?!.*\\\\.\\\\.)([A-Za-z0-9_'+\\\\-\\\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\\\-]*\\\\.)+[A-Za-z]{2,}$\"\n }\n },\n \"required\": [\n \"to\"\n ],\n \"additionalProperties\": false\n },\n \"CreateFileMultipartRequest\": {\n \"type\": \"object\",\n \"properties\": {\n \"file\": {\n \"type\": \"string\",\n \"description\": \"Binary file field\",\n \"format\": \"binary\"\n },\n \"purpose\": {\n \"description\": \"Optional lifecycle marker. `run-input` marks a retry-safe temporary run pre-upload reaped after 24 hours. `builder-attachment` marks a Studio builder intermediary (any MIME) with the same TTL.\",\n \"type\": \"string\",\n \"enum\": [\n \"run-input\",\n \"builder-attachment\"\n ]\n }\n },\n \"required\": [\n \"file\"\n ]\n },\n \"CreateFileUploadSessionRequest\": {\n \"type\": \"object\",\n \"properties\": {\n \"filename\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 255\n },\n \"contentType\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 255\n },\n \"size\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 9007199254740991\n },\n \"purpose\": {\n \"type\": \"string\",\n \"enum\": [\n \"run-input\",\n \"builder-attachment\"\n ]\n },\n \"idempotencyKey\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 256\n }\n },\n \"required\": [\n \"filename\",\n \"contentType\",\n \"size\"\n ]\n },\n \"PresignFileUploadPartRequest\": {\n \"type\": \"object\",\n \"properties\": {\n \"partNumber\": {\n \"type\": \"integer\",\n \"minimum\": 1,\n \"maximum\": 10000\n }\n },\n \"required\": [\n \"partNumber\"\n ]\n },\n \"FolderType\": {\n \"type\": \"string\",\n \"enum\": [\n \"workflow\",\n \"template\"\n ]\n },\n \"CreateFolderRequest\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 255,\n \"description\": \"Folder name. Cannot contain `/`.\"\n },\n \"type\": {\n \"description\": \"Which folder tree to create in. Required; there is no default.\",\n \"$ref\": \"#/components/schemas/FolderType\"\n },\n \"parentId\": {\n \"description\": \"Parent folder id. Omit or `null` to create at the tree root.\",\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n }\n },\n \"required\": [\n \"name\",\n \"type\"\n ]\n },\n \"UpdateFolderRequest\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"description\": \"New folder name. Cannot contain `/`.\",\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 255\n },\n \"parentId\": {\n \"description\": \"New parent folder id. `null` moves the folder to the tree root.\",\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n }\n }\n },\n \"RunStartBody\": {\n \"type\": \"object\",\n \"properties\": {\n \"target\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"Automation target without a version suffix, e.g. workflows.invoice or agents.support.\"\n },\n \"input\": {\n \"description\": \"Scalar and structured automation arguments.\",\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {}\n },\n \"files\": {\n \"description\": \"File inputs as ingress references (`{ \\\"$fileId\\\": \\\"file_...\\\" }` or `{ \\\"$inline\\\": { filename, mimeType, base64 } }`). Upload bytes via multipart `files.<fieldName>` parts instead.\",\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {\n \"anyOf\": [\n {\n \"anyOf\": [\n {\n \"type\": \"object\",\n \"properties\": {\n \"$fileId\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"Reusable file-pool id to materialize\"\n }\n },\n \"required\": [\n \"$fileId\"\n ],\n \"additionalProperties\": false\n },\n {\n \"type\": \"object\",\n \"properties\": {\n \"$inline\": {\n \"type\": \"object\",\n \"properties\": {\n \"filename\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"Original filename for the materialized artifact\"\n },\n \"mimeType\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"MIME type for the materialized artifact\"\n },\n \"base64\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"Base64-encoded file bytes\"\n }\n },\n \"required\": [\n \"filename\",\n \"mimeType\",\n \"base64\"\n ],\n \"additionalProperties\": false\n }\n },\n \"required\": [\n \"$inline\"\n ],\n \"additionalProperties\": false\n }\n ]\n },\n {\n \"type\": \"array\",\n \"items\": {\n \"anyOf\": [\n {\n \"type\": \"object\",\n \"properties\": {\n \"$fileId\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"Reusable file-pool id to materialize\"\n }\n },\n \"required\": [\n \"$fileId\"\n ],\n \"additionalProperties\": false\n },\n {\n \"type\": \"object\",\n \"properties\": {\n \"$inline\": {\n \"type\": \"object\",\n \"properties\": {\n \"filename\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"Original filename for the materialized artifact\"\n },\n \"mimeType\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"MIME type for the materialized artifact\"\n },\n \"base64\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"Base64-encoded file bytes\"\n }\n },\n \"required\": [\n \"filename\",\n \"mimeType\",\n \"base64\"\n ],\n \"additionalProperties\": false\n }\n },\n \"required\": [\n \"$inline\"\n ],\n \"additionalProperties\": false\n }\n ]\n }\n }\n ]\n }\n },\n \"overrides\": {\n \"description\": \"Per-step output overrides. Workflow runs only.\",\n \"type\": \"object\",\n \"properties\": {\n \"steps\": {\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {}\n }\n }\n }\n },\n \"metadata\": {\n \"description\": \"Caller-supplied run metadata.\",\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {}\n }\n },\n \"required\": [\n \"target\"\n ],\n \"description\": \"Run envelope. Declare provenance with the `X-Eigenpal-Trigger` header (`api` or `cli`). Legacy 0.5.12 body shapes remain accepted.\"\n },\n \"RunStartMultipartRequest\": {\n \"type\": \"object\",\n \"properties\": {\n \"target\": {\n \"type\": \"string\",\n \"description\": \"Automation target, e.g. `workflows.invoice`.\"\n },\n \"input\": {\n \"description\": \"JSON-encoded scalar input object.\",\n \"type\": \"string\"\n },\n \"overrides\": {\n \"description\": \"JSON-encoded step overrides.\",\n \"type\": \"string\"\n },\n \"metadata\": {\n \"description\": \"JSON-encoded run metadata.\",\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"target\"\n ],\n \"additionalProperties\": {\n \"description\": \"Dynamic binary fields like `files.<fieldName>`.\"\n }\n },\n \"PromoteRunRequest\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"description\": \"Dataset example name to create or update. Defaults to a generated name when omitted.\",\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 128\n }\n },\n \"description\": \"Create or update a dataset example from the run input, actual output, and review corrections.\"\n },\n \"RunReviewRequest\": {\n \"type\": \"object\",\n \"properties\": {\n \"verdict\": {\n \"description\": \"Reviewer verdict. Omit or send null for feedback without a ranking (nit). Defaults are applied client-side only; any verdict/status combination is accepted.\",\n \"anyOf\": [\n {\n \"type\": \"string\",\n \"enum\": [\n \"correct\",\n \"incorrect\"\n ]\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"status\": {\n \"description\": \"Review lifecycle. Defaults from verdict (`correct` → `closed`, otherwise `open`). Use `closed` or `wont_fix` to close an open review.\",\n \"type\": \"string\",\n \"enum\": [\n \"open\",\n \"closed\",\n \"wont_fix\"\n ]\n },\n \"note\": {\n \"description\": \"Reviewer note.\",\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"correctedOutput\": {\n \"description\": \"Corrected JSON output for this run. Send `null` to clear a previously stored correction.\",\n \"anyOf\": [\n {},\n {\n \"type\": \"null\"\n }\n ]\n },\n \"corrections\": {\n \"description\": \"Field and file corrections. When present, replaces the entire correction set for this review. Omit to leave existing corrections unchanged.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\"\n },\n \"kind\": {\n \"type\": \"string\",\n \"enum\": [\n \"field\",\n \"file\"\n ]\n },\n \"path\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"label\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"originalValue\": {},\n \"correctedValue\": {},\n \"note\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"correctedArtifactPath\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n }\n },\n \"required\": [\n \"kind\",\n \"path\"\n ]\n }\n }\n },\n \"description\": \"Create or replace review metadata for a run. Attribution fields (`reviewedBy`, `closedBy`, and their emails) are read-only and populated from the authenticated user or API key creator.\"\n },\n \"RunReviewExpectedFileCopyRequest\": {\n \"type\": \"object\",\n \"properties\": {\n \"outputFileName\": {\n \"type\": \"string\",\n \"description\": \"Name of an existing run output file to copy into corrected artifacts.\"\n },\n \"expectedName\": {\n \"description\": \"Optional name for the copied corrected file. Defaults to the original output file name.\",\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"outputFileName\"\n ],\n \"description\": \"JSON request body for copying one run output file into the corrected artifact set.\"\n },\n \"RunReviewExpectedFileUploadRequest\": {\n \"type\": \"object\",\n \"properties\": {\n \"file\": {\n \"type\": \"string\",\n \"description\": \"Corrected artifact file to upload.\",\n \"format\": \"binary\"\n },\n \"name\": {\n \"description\": \"Optional stored corrected file name. Defaults to the uploaded filename.\",\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"file\"\n ]\n },\n \"RunReviewExpectedFileUpdateRequest\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\",\n \"description\": \"New corrected file name.\"\n }\n },\n \"required\": [\n \"name\"\n ],\n \"description\": \"Rename one corrected file.\"\n },\n \"TemplateFileReferenceRequest\": {\n \"type\": \"object\",\n \"properties\": {\n \"fileId\": {\n \"type\": \"string\",\n \"pattern\": \"^file_[A-Za-z0-9_-]{21}$\",\n \"description\": \"Reusable file id produced by the direct file upload flow. It is consumed as upload transport, not exposed as template identity.\"\n },\n \"name\": {\n \"type\": \"string\"\n },\n \"description\": {\n \"type\": \"string\"\n },\n \"staged\": {\n \"description\": \"When true, the create response includes a one-time cleanupProof for unpublished CLI staging. Normal uploads omit this.\",\n \"type\": \"boolean\"\n }\n },\n \"required\": [\n \"fileId\"\n ]\n },\n \"TemplateReplaceRequest\": {\n \"type\": \"object\",\n \"properties\": {\n \"fileId\": {\n \"type\": \"string\",\n \"pattern\": \"^file_[A-Za-z0-9_-]{21}$\",\n \"description\": \"Reusable file id produced by the direct file upload flow. It is consumed as upload transport, not exposed as template identity.\"\n }\n },\n \"required\": [\n \"fileId\"\n ]\n },\n \"TemplateStagingRequest\": {\n \"type\": \"object\",\n \"properties\": {\n \"proof\": {\n \"type\": \"string\",\n \"minLength\": 16,\n \"maxLength\": 128\n },\n \"action\": {\n \"type\": \"string\",\n \"enum\": [\n \"cleanup\",\n \"finalize\"\n ]\n }\n },\n \"required\": [\n \"proof\",\n \"action\"\n ]\n },\n \"AuthCheckResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"ok\": {\n \"type\": \"boolean\",\n \"const\": true\n },\n \"tenantId\": {\n \"type\": \"string\"\n },\n \"tenantSlug\": {\n \"type\": \"string\"\n },\n \"tenantName\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"userId\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"keyId\": {\n \"type\": \"string\"\n },\n \"email\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"name\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"scope\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n },\n \"wildcardGranted\": {\n \"type\": \"boolean\"\n }\n },\n \"required\": [\n \"ok\",\n \"tenantId\",\n \"tenantSlug\",\n \"tenantName\",\n \"userId\",\n \"keyId\",\n \"email\",\n \"name\",\n \"scope\",\n \"wildcardGranted\"\n ],\n \"additionalProperties\": false\n },\n \"ApiErrorEnvelope\": {\n \"type\": \"object\",\n \"properties\": {\n \"issues\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/ApiErrorIssue\"\n }\n },\n \"requestId\": {\n \"type\": \"string\",\n \"description\": \"Request id echoed via the x-request-id header\"\n },\n \"hint\": {\n \"description\": \"Suggested fix for known error patterns\",\n \"type\": \"string\"\n },\n \"docsUrl\": {\n \"description\": \"Link to relevant docs\",\n \"type\": \"string\"\n },\n \"conflictingWorkflowId\": {\n \"description\": \"Present on 409 workflow_name_conflict responses. Id of the workflow that already owns the requested name.\",\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"issues\",\n \"requestId\"\n ],\n \"additionalProperties\": false\n },\n \"ApiErrorIssue\": {\n \"type\": \"object\",\n \"properties\": {\n \"field\": {\n \"type\": \"string\",\n \"description\": \"JSON path of the offending field, or \\\"<root>\\\"\"\n },\n \"message\": {\n \"type\": \"string\",\n \"description\": \"Human-readable error message\"\n },\n \"code\": {\n \"type\": \"string\",\n \"description\": \"Machine-readable error code (e.g. invalid_value, not_found, api_trigger_disabled, manual_trigger_disabled)\"\n },\n \"severity\": {\n \"type\": \"string\",\n \"enum\": [\n \"error\",\n \"warning\"\n ],\n \"description\": \"Issue severity\"\n }\n },\n \"required\": [\n \"field\",\n \"message\",\n \"code\",\n \"severity\"\n ],\n \"additionalProperties\": false\n },\n \"ListAutomationsResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"data\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/AutomationSummary\"\n }\n },\n \"total\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"limit\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"offset\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n }\n },\n \"required\": [\n \"data\",\n \"total\",\n \"limit\",\n \"offset\"\n ],\n \"additionalProperties\": false\n },\n \"AutomationSummary\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\",\n \"description\": \"Implementation id for the automation. Workflow automations use workflow ids; agent automations use agent workflow ids.\"\n },\n \"type\": {\n \"$ref\": \"#/components/schemas/AutomationType\"\n },\n \"slug\": {\n \"type\": \"string\"\n },\n \"name\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"description\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"status\": {\n \"type\": \"string\"\n },\n \"version\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"triggers\": {\n \"$ref\": \"#/components/schemas/AutomationTriggerState\"\n },\n \"implementationAvailable\": {\n \"description\": \"False when the automations registry row exists but the workflow/agent implementation row is missing.\",\n \"type\": \"boolean\"\n },\n \"folderId\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Workflow folder id. Null for unfiled workflows, agent automations, and orphan registry rows.\"\n },\n \"folderPath\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Slash-separated workflow folder path from the tenant root, such as `billing/invoices`. Null at root and for agent automations.\"\n },\n \"createdAt\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"string\"\n }\n ]\n },\n \"updatedAt\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"string\"\n }\n ]\n }\n },\n \"required\": [\n \"id\",\n \"type\",\n \"slug\",\n \"name\",\n \"folderId\",\n \"folderPath\",\n \"createdAt\"\n ],\n \"additionalProperties\": false\n },\n \"AutomationType\": {\n \"type\": \"string\",\n \"enum\": [\n \"workflow\",\n \"agent\"\n ]\n },\n \"AutomationTriggerState\": {\n \"type\": \"object\",\n \"properties\": {\n \"api\": {\n \"type\": \"boolean\"\n },\n \"email\": {\n \"type\": \"boolean\"\n },\n \"manual\": {\n \"type\": \"boolean\"\n },\n \"cron\": {\n \"type\": \"boolean\"\n }\n },\n \"required\": [\n \"api\",\n \"email\",\n \"manual\",\n \"cron\"\n ],\n \"additionalProperties\": false\n },\n \"AutomationDetail\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\",\n \"description\": \"Implementation id for the automation. Workflow automations use workflow ids; agent automations use agent workflow ids.\"\n },\n \"type\": {\n \"$ref\": \"#/components/schemas/AutomationType\"\n },\n \"slug\": {\n \"type\": \"string\"\n },\n \"name\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"description\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"status\": {\n \"type\": \"string\"\n },\n \"version\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"triggers\": {\n \"$ref\": \"#/components/schemas/AutomationTriggerState\"\n },\n \"implementationAvailable\": {\n \"description\": \"False when the automations registry row exists but the workflow/agent implementation row is missing.\",\n \"type\": \"boolean\"\n },\n \"folderId\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Workflow folder id. Null for unfiled workflows, agent automations, and orphan registry rows.\"\n },\n \"folderPath\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Slash-separated workflow folder path from the tenant root, such as `billing/invoices`. Null at root and for agent automations.\"\n },\n \"createdAt\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"string\"\n }\n ]\n },\n \"updatedAt\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"string\"\n }\n ]\n },\n \"inputSchema\": {\n \"anyOf\": [\n {\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {}\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"outputSchema\": {\n \"anyOf\": [\n {\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {}\n },\n {\n \"type\": \"null\"\n }\n ]\n }\n },\n \"required\": [\n \"id\",\n \"type\",\n \"slug\",\n \"name\",\n \"folderId\",\n \"folderPath\",\n \"createdAt\"\n ],\n \"additionalProperties\": false\n },\n \"DeleteAutomationResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"deleted\": {\n \"type\": \"boolean\",\n \"const\": true\n },\n \"id\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"deleted\",\n \"id\"\n ],\n \"additionalProperties\": false\n },\n \"DatasetReviewRequestList\": {\n \"type\": \"object\",\n \"properties\": {\n \"data\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/DatasetReviewRequest\"\n }\n },\n \"total\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"limit\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"offset\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n }\n },\n \"required\": [\n \"data\",\n \"total\",\n \"limit\",\n \"offset\"\n ],\n \"additionalProperties\": false\n },\n \"DatasetReviewRequest\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\"\n },\n \"automationId\": {\n \"type\": \"string\"\n },\n \"title\": {\n \"type\": \"string\"\n },\n \"instructions\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"focusFields\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/DatasetReviewFocusFieldOutput\"\n }\n },\n \"ignoredFields\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n },\n \"status\": {\n \"type\": \"string\",\n \"enum\": [\n \"draft\",\n \"open\",\n \"paused\",\n \"closed\"\n ]\n },\n \"exampleNames\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n },\n \"progress\": {\n \"$ref\": \"#/components/schemas/DatasetReviewProgress\"\n },\n \"createdBy\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"createdAt\": {\n \"type\": \"string\"\n },\n \"closedAt\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n }\n },\n \"required\": [\n \"id\",\n \"automationId\",\n \"title\",\n \"instructions\",\n \"focusFields\",\n \"ignoredFields\",\n \"status\",\n \"exampleNames\",\n \"progress\",\n \"createdBy\",\n \"createdAt\",\n \"closedAt\"\n ],\n \"additionalProperties\": false\n },\n \"DatasetReviewProgress\": {\n \"type\": \"object\",\n \"properties\": {\n \"total\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 9007199254740991\n },\n \"pending\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 9007199254740991\n },\n \"approved\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 9007199254740991\n },\n \"edited\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 9007199254740991\n },\n \"rejected\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 9007199254740991\n },\n \"remaining\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 9007199254740991,\n \"description\": \"Count of examples still pending a decision.\"\n },\n \"complete\": {\n \"type\": \"boolean\",\n \"description\": \"True when every example has been approved, edited, or rejected. Close the request when review is finished; dataset write-back is always manual.\"\n }\n },\n \"required\": [\n \"total\",\n \"pending\",\n \"approved\",\n \"edited\",\n \"rejected\",\n \"remaining\",\n \"complete\"\n ],\n \"additionalProperties\": false\n },\n \"DatasetReviewDetail\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\"\n },\n \"automationId\": {\n \"type\": \"string\"\n },\n \"title\": {\n \"type\": \"string\"\n },\n \"instructions\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"focusFields\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/DatasetReviewFocusFieldOutput\"\n }\n },\n \"ignoredFields\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n },\n \"status\": {\n \"type\": \"string\",\n \"enum\": [\n \"draft\",\n \"open\",\n \"paused\",\n \"closed\"\n ]\n },\n \"exampleNames\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n },\n \"progress\": {\n \"$ref\": \"#/components/schemas/DatasetReviewProgress\"\n },\n \"createdBy\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"createdAt\": {\n \"type\": \"string\"\n },\n \"closedAt\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"items\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/DatasetReviewItem\"\n }\n },\n \"events\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/DatasetReviewEvent\"\n }\n }\n },\n \"required\": [\n \"id\",\n \"automationId\",\n \"title\",\n \"instructions\",\n \"focusFields\",\n \"ignoredFields\",\n \"status\",\n \"exampleNames\",\n \"progress\",\n \"createdBy\",\n \"createdAt\",\n \"closedAt\",\n \"items\"\n ],\n \"additionalProperties\": false\n },\n \"DatasetReviewItem\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\"\n },\n \"reviewId\": {\n \"type\": \"string\"\n },\n \"exampleName\": {\n \"type\": \"string\"\n },\n \"snapshotInputJson\": {\n \"anyOf\": [\n {\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {}\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"snapshotExpectedJson\": {\n \"anyOf\": [\n {},\n {\n \"type\": \"null\"\n }\n ]\n },\n \"snapshotManifest\": {\n \"type\": \"object\",\n \"properties\": {\n \"expectedFiles\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"name\"\n ],\n \"additionalProperties\": false\n }\n },\n \"metadata\": {\n \"anyOf\": [\n {\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {}\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"inputFileHashes\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"path\": {\n \"type\": \"string\"\n },\n \"sha256\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"path\",\n \"sha256\"\n ],\n \"additionalProperties\": false\n }\n }\n },\n \"required\": [\n \"expectedFiles\",\n \"metadata\"\n ],\n \"additionalProperties\": false\n },\n \"status\": {\n \"type\": \"string\",\n \"enum\": [\n \"pending\",\n \"approved\",\n \"edited\",\n \"rejected\"\n ]\n },\n \"currentExpectedJson\": {\n \"anyOf\": [\n {},\n {\n \"type\": \"null\"\n }\n ]\n },\n \"fieldDecisions\": {\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {\n \"$ref\": \"#/components/schemas/DatasetReviewFieldDecision\"\n }\n },\n \"inputDrifted\": {\n \"type\": \"boolean\",\n \"description\": \"True when live dataset input-file bytes no longer match the hashes captured at request creation.\"\n },\n \"updatedBy\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"updatedAt\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"id\",\n \"reviewId\",\n \"exampleName\",\n \"snapshotInputJson\",\n \"snapshotExpectedJson\",\n \"snapshotManifest\",\n \"status\",\n \"currentExpectedJson\",\n \"fieldDecisions\",\n \"inputDrifted\",\n \"updatedBy\",\n \"updatedAt\"\n ],\n \"additionalProperties\": false\n },\n \"DatasetReviewFieldDecision\": {\n \"type\": \"object\",\n \"properties\": {\n \"decision\": {\n \"type\": \"string\",\n \"enum\": [\n \"approved\",\n \"rejected\"\n ]\n },\n \"comment\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"reviewerId\": {\n \"type\": \"string\"\n },\n \"updatedAt\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"decision\",\n \"reviewerId\",\n \"updatedAt\"\n ],\n \"additionalProperties\": false\n },\n \"DatasetReviewEvent\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\"\n },\n \"reviewId\": {\n \"type\": \"string\"\n },\n \"itemId\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"actorUserId\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"action\": {\n \"type\": \"string\",\n \"enum\": [\n \"created\",\n \"approved\",\n \"edited\",\n \"rejected\",\n \"reopened\",\n \"commented\",\n \"field-decision\"\n ]\n },\n \"diffSummary\": {\n \"anyOf\": [\n {},\n {\n \"type\": \"null\"\n }\n ]\n },\n \"createdAt\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"id\",\n \"reviewId\",\n \"itemId\",\n \"actorUserId\",\n \"action\",\n \"diffSummary\",\n \"createdAt\"\n ],\n \"additionalProperties\": false\n },\n \"DatasetReviewEventList\": {\n \"type\": \"object\",\n \"properties\": {\n \"events\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/DatasetReviewEvent\"\n }\n }\n },\n \"required\": [\n \"events\"\n ],\n \"additionalProperties\": false\n },\n \"DatasetReviewItemList\": {\n \"type\": \"object\",\n \"properties\": {\n \"items\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/DatasetReviewItem\"\n }\n }\n },\n \"required\": [\n \"items\"\n ],\n \"additionalProperties\": false\n },\n \"DatasetReviewItemResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"item\": {\n \"$ref\": \"#/components/schemas/DatasetReviewItem\"\n }\n },\n \"required\": [\n \"item\"\n ],\n \"additionalProperties\": false\n },\n \"DatasetImportResponse\": {\n \"anyOf\": [\n {\n \"type\": \"object\",\n \"properties\": {\n \"mode\": {\n \"type\": \"string\",\n \"const\": \"append\"\n },\n \"created\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"expectedSet\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"skipped\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"issues\": {\n \"type\": \"array\",\n \"items\": {}\n }\n },\n \"required\": [\n \"mode\",\n \"created\",\n \"expectedSet\",\n \"skipped\",\n \"issues\"\n ],\n \"additionalProperties\": false\n },\n {\n \"type\": \"object\",\n \"properties\": {\n \"mode\": {\n \"type\": \"string\",\n \"const\": \"replace\"\n },\n \"created\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"expectedSet\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"deleted\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"filesDeleted\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n }\n },\n \"required\": [\n \"mode\",\n \"created\",\n \"expectedSet\",\n \"deleted\",\n \"filesDeleted\"\n ],\n \"additionalProperties\": false\n }\n ]\n },\n \"EvaluatorConfigResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"automationId\": {\n \"type\": \"string\",\n \"description\": \"Automation that owns this evaluator config.\"\n },\n \"automationType\": {\n \"$ref\": \"#/components/schemas/AutomationType\"\n },\n \"yaml\": {\n \"type\": \"string\",\n \"description\": \"Evaluator configuration YAML.\"\n },\n \"config\": {\n \"type\": \"object\",\n \"properties\": {\n \"evaluators\": {\n \"type\": \"array\",\n \"items\": {},\n \"description\": \"Parsed evaluator definitions from the YAML.\"\n },\n \"passThreshold\": {\n \"type\": \"number\",\n \"description\": \"Overall score threshold required for the experiment to pass.\"\n }\n },\n \"required\": [\n \"evaluators\",\n \"passThreshold\"\n ],\n \"additionalProperties\": false\n }\n },\n \"required\": [\n \"automationId\",\n \"automationType\",\n \"yaml\",\n \"config\"\n ],\n \"additionalProperties\": false,\n \"description\": \"Evaluator YAML and parsed evaluator configuration for an automation.\"\n },\n \"DatasetExampleList\": {\n \"type\": \"object\",\n \"properties\": {\n \"data\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/DatasetExample\"\n }\n },\n \"total\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"limit\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"offset\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n }\n },\n \"required\": [\n \"data\",\n \"total\",\n \"limit\",\n \"offset\"\n ],\n \"additionalProperties\": false\n },\n \"DatasetExample\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\",\n \"description\": \"Stable public example id. Workflow examples use DB ids; agent examples use deterministic name-derived ids.\"\n },\n \"name\": {\n \"type\": \"string\",\n \"description\": \"Human-readable dataset example name.\"\n },\n \"automationId\": {\n \"type\": \"string\",\n \"description\": \"Automation that owns this example.\"\n },\n \"automationType\": {\n \"$ref\": \"#/components/schemas/AutomationType\"\n },\n \"input\": {\n \"anyOf\": [\n {\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {}\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Input arguments used when this example is run. Null when listing with `include=metadata`.\"\n },\n \"expected\": {\n \"anyOf\": [\n {},\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Expected JSON output for evaluator comparisons. Null when listing with `include=metadata`.\"\n },\n \"expectedFiles\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\",\n \"description\": \"Expected file name.\"\n },\n \"url\": {\n \"description\": \"Download URL for the expected file.\",\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"name\"\n ],\n \"additionalProperties\": false\n },\n \"description\": \"Expected files attached to this example.\"\n },\n \"metadata\": {\n \"anyOf\": [\n {\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {}\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Caller-managed metadata for sorting or filtering examples.\"\n },\n \"annotation\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Human note about the example.\"\n },\n \"rowOrder\": {\n \"anyOf\": [\n {\n \"type\": \"number\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Optional display order within the dataset.\"\n },\n \"overrides\": {\n \"anyOf\": [\n {\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {}\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Step output overrides used when running this example.\"\n },\n \"latestRunId\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Most recent run id created from this example.\"\n },\n \"createdAt\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"string\"\n }\n ]\n },\n \"updatedAt\": {\n \"anyOf\": [\n {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"string\"\n }\n ]\n },\n {\n \"type\": \"null\"\n }\n ]\n }\n },\n \"required\": [\n \"id\",\n \"name\",\n \"automationId\",\n \"automationType\",\n \"input\",\n \"expected\",\n \"expectedFiles\",\n \"metadata\",\n \"annotation\",\n \"rowOrder\",\n \"overrides\",\n \"latestRunId\"\n ],\n \"additionalProperties\": false,\n \"description\": \"One input/expected-output row in an automation dataset.\"\n },\n \"DatasetExampleExpectedFileList\": {\n \"type\": \"object\",\n \"properties\": {\n \"files\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n },\n \"description\": \"Paths under the example expected folder.\"\n }\n },\n \"required\": [\n \"files\"\n ],\n \"additionalProperties\": false\n },\n \"DatasetExampleExpectedFileUploadResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"uploaded\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n },\n \"description\": \"Stored expected file paths.\"\n }\n },\n \"required\": [\n \"uploaded\"\n ],\n \"additionalProperties\": false\n },\n \"DatasetExampleExpectedFileRenameResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"ok\": {\n \"type\": \"boolean\",\n \"const\": true\n },\n \"filename\": {\n \"type\": \"string\"\n },\n \"path\": {\n \"type\": \"string\",\n \"description\": \"Updated expected file path.\"\n }\n },\n \"required\": [\n \"ok\",\n \"filename\",\n \"path\"\n ],\n \"additionalProperties\": false\n },\n \"DatasetExampleInputFileList\": {\n \"type\": \"object\",\n \"properties\": {\n \"files\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n },\n \"description\": \"Paths under the example input folder.\"\n }\n },\n \"required\": [\n \"files\"\n ],\n \"additionalProperties\": false\n },\n \"DatasetExampleInputFileUploadResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"uploaded\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n },\n \"description\": \"Stored input file paths.\"\n }\n },\n \"required\": [\n \"uploaded\"\n ],\n \"additionalProperties\": false\n },\n \"DatasetExampleInputFileRenameResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"ok\": {\n \"type\": \"boolean\",\n \"const\": true\n },\n \"filename\": {\n \"type\": \"string\"\n },\n \"path\": {\n \"type\": \"string\",\n \"description\": \"Updated input file path.\"\n }\n },\n \"required\": [\n \"ok\",\n \"filename\",\n \"path\"\n ],\n \"additionalProperties\": false\n },\n \"ExampleRunResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\",\n \"description\": \"Run id created for this example.\"\n },\n \"type\": {\n \"type\": \"string\",\n \"enum\": [\n \"workflow\",\n \"agent\"\n ],\n \"description\": \"Implementation type behind the automation.\"\n },\n \"batchId\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Experiment batch id when the run is associated with a batch. The API also calls this an experiment id in experiment routes.\"\n },\n \"finished\": {\n \"type\": \"boolean\",\n \"const\": false,\n \"description\": \"Example runs are accepted asynchronously.\"\n }\n },\n \"required\": [\n \"id\",\n \"type\",\n \"batchId\",\n \"finished\"\n ],\n \"additionalProperties\": false\n },\n \"Experiment\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\",\n \"description\": \"Experiment batch id. Some CLI commands historically call this a batch id.\"\n },\n \"automationId\": {\n \"type\": \"string\",\n \"description\": \"Automation this experiment belongs to.\"\n },\n \"automationType\": {\n \"$ref\": \"#/components/schemas/AutomationType\"\n },\n \"status\": {\n \"type\": \"string\",\n \"enum\": [\n \"queued\",\n \"running\",\n \"completed\"\n ],\n \"description\": \"Experiment batch status.\"\n },\n \"runCount\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991,\n \"description\": \"Total runs in the experiment.\"\n },\n \"completedCount\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991,\n \"description\": \"Runs that have completed.\"\n },\n \"passedCount\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991,\n \"description\": \"Runs whose evaluator scores passed.\"\n },\n \"failedCount\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991,\n \"description\": \"Runs whose evaluator scores failed.\"\n },\n \"avgScore\": {\n \"anyOf\": [\n {\n \"type\": \"number\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Average automated evaluator score.\"\n },\n \"createdAt\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"string\"\n }\n ]\n },\n \"completedAt\": {\n \"anyOf\": [\n {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"string\"\n }\n ]\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"version\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n }\n },\n \"required\": [\n \"id\",\n \"automationId\",\n \"automationType\",\n \"status\",\n \"runCount\",\n \"completedCount\",\n \"passedCount\",\n \"failedCount\",\n \"avgScore\",\n \"createdAt\",\n \"completedAt\",\n \"version\"\n ],\n \"additionalProperties\": false,\n \"description\": \"Experiment batch summary for an automation dataset run.\"\n },\n \"ExperimentCreateResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\",\n \"description\": \"Experiment batch id.\"\n },\n \"runs\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\",\n \"description\": \"Run id.\"\n },\n \"exampleId\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Dataset example id.\"\n }\n },\n \"required\": [\n \"id\",\n \"exampleId\"\n ],\n \"additionalProperties\": false\n },\n \"description\": \"Runs enqueued for this experiment.\"\n },\n \"total\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991,\n \"description\": \"Number of runs enqueued.\"\n }\n },\n \"required\": [\n \"id\",\n \"runs\",\n \"total\"\n ],\n \"additionalProperties\": false,\n \"description\": \"Accepted experiment batch and the runs it enqueued.\"\n },\n \"ExperimentDetail\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\",\n \"description\": \"Experiment batch id. Some CLI commands historically call this a batch id.\"\n },\n \"automationId\": {\n \"type\": \"string\",\n \"description\": \"Automation this experiment belongs to.\"\n },\n \"automationType\": {\n \"$ref\": \"#/components/schemas/AutomationType\"\n },\n \"status\": {\n \"type\": \"string\",\n \"enum\": [\n \"queued\",\n \"running\",\n \"completed\"\n ],\n \"description\": \"Experiment batch status.\"\n },\n \"runCount\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991,\n \"description\": \"Total runs in the experiment.\"\n },\n \"completedCount\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991,\n \"description\": \"Runs that have completed.\"\n },\n \"passedCount\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991,\n \"description\": \"Runs whose evaluator scores passed.\"\n },\n \"failedCount\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991,\n \"description\": \"Runs whose evaluator scores failed.\"\n },\n \"avgScore\": {\n \"anyOf\": [\n {\n \"type\": \"number\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Average automated evaluator score.\"\n },\n \"createdAt\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"string\"\n }\n ]\n },\n \"completedAt\": {\n \"anyOf\": [\n {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"string\"\n }\n ]\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"version\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"runs\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\",\n \"description\": \"Run id created for the experiment.\"\n },\n \"status\": {\n \"type\": \"string\",\n \"description\": \"Current run status.\"\n },\n \"exampleId\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Dataset example id for the run.\"\n },\n \"exampleName\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Dataset example name for the run.\"\n },\n \"evalScore\": {\n \"anyOf\": [\n {\n \"type\": \"number\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Persisted weighted evaluator score.\"\n },\n \"evalPassed\": {\n \"anyOf\": [\n {\n \"type\": \"boolean\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Persisted aggregate evaluator verdict.\"\n },\n \"createdAt\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"string\"\n }\n ]\n },\n \"completedAt\": {\n \"anyOf\": [\n {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"string\"\n }\n ]\n },\n {\n \"type\": \"null\"\n }\n ]\n }\n },\n \"required\": [\n \"id\",\n \"status\",\n \"exampleId\",\n \"exampleName\",\n \"evalScore\",\n \"evalPassed\",\n \"createdAt\",\n \"completedAt\"\n ],\n \"additionalProperties\": false\n },\n \"description\": \"Runs created for dataset examples in this experiment.\"\n },\n \"resultsByRun\": {\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/EvalResult\"\n }\n },\n \"description\": \"Evaluator results keyed by run id.\"\n }\n },\n \"required\": [\n \"id\",\n \"automationId\",\n \"automationType\",\n \"status\",\n \"runCount\",\n \"completedCount\",\n \"passedCount\",\n \"failedCount\",\n \"avgScore\",\n \"createdAt\",\n \"completedAt\",\n \"version\",\n \"runs\",\n \"resultsByRun\"\n ],\n \"additionalProperties\": false,\n \"description\": \"Experiment batch detail.\"\n },\n \"EvalResult\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\",\n \"description\": \"Evaluator result id.\"\n },\n \"runId\": {\n \"type\": \"string\",\n \"description\": \"Run this score belongs to.\"\n },\n \"automationId\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Automation this score belongs to.\"\n },\n \"evaluatorName\": {\n \"type\": \"string\",\n \"description\": \"Evaluator name from configuration.\"\n },\n \"evaluatorType\": {\n \"type\": \"string\",\n \"description\": \"Evaluator implementation type.\"\n },\n \"score\": {\n \"anyOf\": [\n {\n \"type\": \"number\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Automated evaluator score. Do not confuse this with a human review verdict.\"\n },\n \"passed\": {\n \"anyOf\": [\n {\n \"type\": \"boolean\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Whether this evaluator passed.\"\n },\n \"label\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Optional evaluator label.\"\n },\n \"weight\": {\n \"anyOf\": [\n {\n \"type\": \"number\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Weight used in aggregate scoring.\"\n },\n \"passThreshold\": {\n \"anyOf\": [\n {\n \"type\": \"number\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Score threshold required for this evaluator to pass.\"\n },\n \"description\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Evaluator description.\"\n },\n \"details\": {\n \"anyOf\": [\n {},\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Evaluator-specific details.\"\n },\n \"error\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Evaluator error, when scoring failed.\"\n },\n \"createdAt\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"string\"\n }\n ]\n }\n },\n \"required\": [\n \"id\",\n \"runId\",\n \"automationId\",\n \"evaluatorName\",\n \"evaluatorType\",\n \"score\",\n \"passed\",\n \"label\",\n \"weight\",\n \"passThreshold\",\n \"description\",\n \"details\",\n \"error\",\n \"createdAt\"\n ],\n \"additionalProperties\": false,\n \"description\": \"Automated evaluator result for one run.\"\n },\n \"RunReviewHealthResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"timeRange\": {\n \"type\": \"object\",\n \"properties\": {\n \"from\": {\n \"type\": \"string\"\n },\n \"to\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"from\",\n \"to\"\n ],\n \"additionalProperties\": false\n },\n \"granularity\": {\n \"type\": \"object\",\n \"properties\": {\n \"bucket\": {\n \"type\": \"string\",\n \"enum\": [\n \"day\",\n \"week\",\n \"month\"\n ]\n },\n \"rollingWindow\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"minRollingReviews\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n }\n },\n \"required\": [\n \"bucket\",\n \"rollingWindow\",\n \"minRollingReviews\"\n ],\n \"additionalProperties\": false\n },\n \"summary\": {\n \"$ref\": \"#/components/schemas/RunReviewHealthSummary\"\n },\n \"buckets\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/RunReviewHealthBucket\"\n }\n },\n \"rolling\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/RunReviewHealthRollingPoint\"\n }\n }\n },\n \"required\": [\n \"timeRange\",\n \"granularity\",\n \"summary\",\n \"buckets\",\n \"rolling\"\n ],\n \"additionalProperties\": false\n },\n \"RunReviewHealthSummary\": {\n \"type\": \"object\",\n \"properties\": {\n \"totalRuns\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"reviewedRuns\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991,\n \"description\": \"Runs with a ranked verdict (`correct` or `incorrect`). Null verdict (nit) is excluded.\"\n },\n \"reviewCoverage\": {\n \"anyOf\": [\n {\n \"type\": \"number\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"correctReviews\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"incorrectReviews\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"nitReviews\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991,\n \"description\": \"Runs with a review row and null verdict (nit). Excluded from review coverage and accuracy.\"\n },\n \"reviewedCorrectness\": {\n \"anyOf\": [\n {\n \"type\": \"number\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"confidence\": {\n \"$ref\": \"#/components/schemas/RunReviewHealthConfidence\"\n }\n },\n \"required\": [\n \"totalRuns\",\n \"reviewedRuns\",\n \"reviewCoverage\",\n \"correctReviews\",\n \"incorrectReviews\",\n \"nitReviews\",\n \"reviewedCorrectness\",\n \"confidence\"\n ],\n \"additionalProperties\": false\n },\n \"RunReviewHealthConfidence\": {\n \"type\": \"object\",\n \"properties\": {\n \"lower\": {\n \"anyOf\": [\n {\n \"type\": \"number\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"upper\": {\n \"anyOf\": [\n {\n \"type\": \"number\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"method\": {\n \"type\": \"string\",\n \"const\": \"wilson\"\n }\n },\n \"required\": [\n \"lower\",\n \"upper\",\n \"method\"\n ],\n \"additionalProperties\": false,\n \"description\": \"Wilson score confidence interval for reviewed correctness. Null bounds mean there are no reviewed runs in the sample.\"\n },\n \"RunReviewHealthBucket\": {\n \"type\": \"object\",\n \"properties\": {\n \"start\": {\n \"type\": \"string\"\n },\n \"end\": {\n \"type\": \"string\"\n },\n \"totalRuns\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"reviewedRuns\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991,\n \"description\": \"Runs with a ranked verdict (`correct` or `incorrect`). Null verdict (nit) is excluded.\"\n },\n \"reviewCoverage\": {\n \"anyOf\": [\n {\n \"type\": \"number\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"correctReviews\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"incorrectReviews\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"nitReviews\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991,\n \"description\": \"Runs with a review row and null verdict (nit). Excluded from review coverage and accuracy.\"\n },\n \"reviewedCorrectness\": {\n \"anyOf\": [\n {\n \"type\": \"number\"\n },\n {\n \"type\": \"null\"\n }\n ]\n }\n },\n \"required\": [\n \"start\",\n \"end\",\n \"totalRuns\",\n \"reviewedRuns\",\n \"reviewCoverage\",\n \"correctReviews\",\n \"incorrectReviews\",\n \"nitReviews\",\n \"reviewedCorrectness\"\n ],\n \"additionalProperties\": false\n },\n \"RunReviewHealthRollingPoint\": {\n \"type\": \"object\",\n \"properties\": {\n \"at\": {\n \"type\": \"string\"\n },\n \"reviewedRuns\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991,\n \"description\": \"Runs with a ranked verdict (`correct` or `incorrect`). Null verdict (nit) is excluded.\"\n },\n \"correctReviews\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"reviewedCorrectness\": {\n \"type\": \"number\"\n },\n \"confidenceLower\": {\n \"type\": \"number\"\n },\n \"confidenceUpper\": {\n \"type\": \"number\"\n },\n \"totalRunsInWindow\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991,\n \"description\": \"Total production runs in the rolling window ending at this point.\"\n },\n \"reviewCoverage\": {\n \"type\": \"number\",\n \"description\": \"Share of runs in the rolling window that were reviewed (0-1). Uses the same window size as rolling accuracy, applied to all runs.\"\n }\n },\n \"required\": [\n \"at\",\n \"reviewedRuns\",\n \"correctReviews\",\n \"reviewedCorrectness\",\n \"confidenceLower\",\n \"confidenceUpper\",\n \"totalRunsInWindow\",\n \"reviewCoverage\"\n ],\n \"additionalProperties\": false\n },\n \"AutomationTriggersResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"automationId\": {\n \"type\": \"string\"\n },\n \"type\": {\n \"$ref\": \"#/components/schemas/AutomationType\"\n },\n \"triggers\": {\n \"$ref\": \"#/components/schemas/AutomationTriggerState\"\n }\n },\n \"required\": [\n \"automationId\",\n \"type\",\n \"triggers\"\n ],\n \"additionalProperties\": false\n },\n \"ListAutomationVersionsResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"data\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/AutomationVersion\"\n }\n },\n \"total\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"limit\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"offset\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n }\n },\n \"required\": [\n \"data\",\n \"total\",\n \"limit\",\n \"offset\"\n ],\n \"additionalProperties\": false\n },\n \"AutomationVersion\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\"\n },\n \"automationId\": {\n \"type\": \"string\"\n },\n \"version\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"sourceRef\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"isCurrent\": {\n \"type\": \"boolean\"\n },\n \"createdAt\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"string\"\n }\n ]\n }\n },\n \"required\": [\n \"id\",\n \"automationId\",\n \"version\"\n ],\n \"additionalProperties\": false\n },\n \"ListEmailServersResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"data\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/EmailServer\"\n }\n },\n \"total\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"limit\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"offset\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n }\n },\n \"required\": [\n \"data\",\n \"total\",\n \"limit\",\n \"offset\"\n ],\n \"additionalProperties\": false\n },\n \"EmailServer\": {\n \"oneOf\": [\n {\n \"$ref\": \"#/components/schemas/PublicResendEmailServer\"\n },\n {\n \"$ref\": \"#/components/schemas/PublicSmtpEmailServer\"\n }\n ],\n \"type\": \"object\",\n \"discriminator\": {\n \"propertyName\": \"transport\",\n \"mapping\": {\n \"resend\": \"#/components/schemas/PublicResendEmailServer\",\n \"smtp\": \"#/components/schemas/PublicSmtpEmailServer\"\n }\n }\n },\n \"PublicResendEmailServer\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\",\n \"maxLength\": 128,\n \"pattern\": \"^ems_[A-Za-z0-9_-]+$\"\n },\n \"name\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 128\n },\n \"enabled\": {\n \"type\": \"boolean\"\n },\n \"createdAt\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"string\"\n }\n ]\n },\n \"updatedAt\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"string\"\n }\n ]\n },\n \"transport\": {\n \"type\": \"string\",\n \"const\": \"resend\"\n },\n \"fromEmail\": {\n \"type\": \"string\",\n \"format\": \"email\",\n \"pattern\": \"^(?!\\\\.)(?!.*\\\\.\\\\.)([A-Za-z0-9_'+\\\\-\\\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\\\-]*\\\\.)+[A-Za-z]{2,}$\"\n },\n \"fromName\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 128\n },\n \"apiKeyConfigured\": {\n \"type\": \"boolean\",\n \"const\": true\n }\n },\n \"required\": [\n \"id\",\n \"name\",\n \"enabled\",\n \"createdAt\",\n \"updatedAt\",\n \"transport\",\n \"fromEmail\",\n \"fromName\",\n \"apiKeyConfigured\"\n ],\n \"additionalProperties\": false\n },\n \"PublicSmtpEmailServer\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\",\n \"maxLength\": 128,\n \"pattern\": \"^ems_[A-Za-z0-9_-]+$\"\n },\n \"name\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 128\n },\n \"enabled\": {\n \"type\": \"boolean\"\n },\n \"createdAt\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"string\"\n }\n ]\n },\n \"updatedAt\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"string\"\n }\n ]\n },\n \"transport\": {\n \"type\": \"string\",\n \"const\": \"smtp\"\n },\n \"fromEmail\": {\n \"type\": \"string\",\n \"format\": \"email\",\n \"pattern\": \"^(?!\\\\.)(?!.*\\\\.\\\\.)([A-Za-z0-9_'+\\\\-\\\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\\\-]*\\\\.)+[A-Za-z]{2,}$\"\n },\n \"fromName\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 128\n },\n \"host\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 253\n },\n \"port\": {\n \"type\": \"integer\",\n \"minimum\": 1,\n \"maximum\": 65535\n },\n \"security\": {\n \"type\": \"string\",\n \"enum\": [\n \"starttls\",\n \"tls\",\n \"none\"\n ]\n },\n \"username\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"passwordConfigured\": {\n \"type\": \"boolean\"\n },\n \"caPemConfigured\": {\n \"type\": \"boolean\"\n }\n },\n \"required\": [\n \"id\",\n \"name\",\n \"enabled\",\n \"createdAt\",\n \"updatedAt\",\n \"transport\",\n \"fromEmail\",\n \"fromName\",\n \"host\",\n \"port\",\n \"security\",\n \"username\",\n \"passwordConfigured\",\n \"caPemConfigured\"\n ],\n \"additionalProperties\": false\n },\n \"DeleteEmailServerResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"deleted\": {\n \"type\": \"boolean\",\n \"const\": true\n },\n \"id\": {\n \"type\": \"string\",\n \"maxLength\": 128,\n \"pattern\": \"^ems_[A-Za-z0-9_-]+$\"\n }\n },\n \"required\": [\n \"deleted\",\n \"id\"\n ],\n \"additionalProperties\": false\n },\n \"TestEmailServerResponse\": {\n \"oneOf\": [\n {\n \"type\": \"object\",\n \"properties\": {\n \"ok\": {\n \"type\": \"boolean\",\n \"const\": true\n },\n \"transport\": {\n \"type\": \"string\",\n \"enum\": [\n \"resend\",\n \"smtp\"\n ]\n },\n \"messageId\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"required\": [\n \"ok\",\n \"transport\",\n \"messageId\"\n ],\n \"additionalProperties\": false\n },\n {\n \"type\": \"object\",\n \"properties\": {\n \"ok\": {\n \"type\": \"boolean\",\n \"const\": false\n },\n \"error\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"required\": [\n \"ok\",\n \"error\"\n ],\n \"additionalProperties\": false\n }\n ],\n \"type\": \"object\"\n },\n \"ExperimentRef\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\"\n },\n \"automationId\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"id\",\n \"automationId\"\n ],\n \"additionalProperties\": false\n },\n \"File\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\"\n },\n \"filename\": {\n \"type\": \"string\"\n },\n \"contentType\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"size\": {\n \"anyOf\": [\n {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"purpose\": {\n \"description\": \"Optional lifecycle marker. `run-input` marks a retry-safe temporary run pre-upload reaped after 24 hours. `builder-attachment` marks a Studio builder intermediary (any MIME) with the same TTL. Omitted/null means a durable reusable file.\",\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"createdAt\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"string\"\n }\n ]\n }\n },\n \"required\": [\n \"id\",\n \"filename\",\n \"contentType\",\n \"size\",\n \"createdAt\"\n ],\n \"additionalProperties\": false\n },\n \"DeleteFileResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"deleted\": {\n \"type\": \"boolean\"\n }\n },\n \"required\": [\n \"deleted\"\n ],\n \"additionalProperties\": false\n },\n \"PresignedFileUploadSession\": {\n \"type\": \"object\",\n \"properties\": {\n \"transport\": {\n \"type\": \"string\",\n \"const\": \"presigned-put\"\n },\n \"uploadId\": {\n \"type\": \"string\"\n },\n \"fileId\": {\n \"type\": \"string\"\n },\n \"url\": {\n \"type\": \"string\",\n \"format\": \"uri\"\n },\n \"headers\": {\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {\n \"type\": \"string\"\n }\n },\n \"expiresAt\": {\n \"type\": \"string\",\n \"format\": \"date-time\",\n \"pattern\": \"^(?:(?:\\\\d\\\\d[2468][048]|\\\\d\\\\d[13579][26]|\\\\d\\\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\\\d|30)|(?:02)-(?:0[1-9]|1\\\\d|2[0-8])))T(?:(?:[01]\\\\d|2[0-3]):[0-5]\\\\d(?::[0-5]\\\\d(?:\\\\.\\\\d+)?)?(?:Z))$\"\n },\n \"maxFileSizeBytes\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n }\n },\n \"required\": [\n \"transport\",\n \"uploadId\",\n \"fileId\",\n \"url\",\n \"headers\",\n \"expiresAt\",\n \"maxFileSizeBytes\"\n ],\n \"additionalProperties\": false\n },\n \"PresignedMultipartFileUploadSession\": {\n \"type\": \"object\",\n \"properties\": {\n \"transport\": {\n \"type\": \"string\",\n \"const\": \"presigned-multipart\"\n },\n \"uploadId\": {\n \"type\": \"string\"\n },\n \"fileId\": {\n \"type\": \"string\"\n },\n \"partSizeBytes\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"partCount\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"partsUrl\": {\n \"type\": \"string\"\n },\n \"completeUrl\": {\n \"type\": \"string\"\n },\n \"expiresAt\": {\n \"type\": \"string\",\n \"format\": \"date-time\",\n \"pattern\": \"^(?:(?:\\\\d\\\\d[2468][048]|\\\\d\\\\d[13579][26]|\\\\d\\\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\\\d|30)|(?:02)-(?:0[1-9]|1\\\\d|2[0-8])))T(?:(?:[01]\\\\d|2[0-3]):[0-5]\\\\d(?::[0-5]\\\\d(?:\\\\.\\\\d+)?)?(?:Z))$\"\n },\n \"maxFileSizeBytes\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n }\n },\n \"required\": [\n \"transport\",\n \"uploadId\",\n \"fileId\",\n \"partSizeBytes\",\n \"partCount\",\n \"partsUrl\",\n \"completeUrl\",\n \"expiresAt\",\n \"maxFileSizeBytes\"\n ],\n \"additionalProperties\": false\n },\n \"MultipartFileUploadFallback\": {\n \"type\": \"object\",\n \"properties\": {\n \"transport\": {\n \"type\": \"string\",\n \"const\": \"multipart\"\n },\n \"url\": {\n \"type\": \"string\"\n },\n \"maxFileSizeBytes\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n }\n },\n \"required\": [\n \"transport\",\n \"url\",\n \"maxFileSizeBytes\"\n ],\n \"additionalProperties\": false\n },\n \"FileUploadSession\": {\n \"type\": \"object\",\n \"properties\": {\n \"uploadId\": {\n \"type\": \"string\"\n },\n \"fileId\": {\n \"type\": \"string\"\n },\n \"transport\": {\n \"type\": \"string\",\n \"enum\": [\n \"presigned-put\",\n \"presigned-multipart\"\n ]\n },\n \"status\": {\n \"type\": \"string\"\n },\n \"expiresAt\": {\n \"type\": \"string\",\n \"format\": \"date-time\",\n \"pattern\": \"^(?:(?:\\\\d\\\\d[2468][048]|\\\\d\\\\d[13579][26]|\\\\d\\\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\\\d|30)|(?:02)-(?:0[1-9]|1\\\\d|2[0-8])))T(?:(?:[01]\\\\d|2[0-3]):[0-5]\\\\d(?::[0-5]\\\\d(?:\\\\.\\\\d+)?)?(?:Z))$\"\n },\n \"partSizeBytes\": {\n \"anyOf\": [\n {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"partCount\": {\n \"anyOf\": [\n {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"parts\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"partNumber\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"size\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"etag\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"partNumber\",\n \"etag\"\n ],\n \"additionalProperties\": false\n }\n }\n },\n \"required\": [\n \"uploadId\",\n \"fileId\",\n \"transport\",\n \"status\",\n \"expiresAt\"\n ],\n \"additionalProperties\": false\n },\n \"AbortFileUploadResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"aborted\": {\n \"type\": \"boolean\",\n \"const\": true\n }\n },\n \"required\": [\n \"aborted\"\n ],\n \"additionalProperties\": false\n },\n \"ListFileUploadPartsResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"transport\": {\n \"type\": \"string\",\n \"const\": \"presigned-multipart\"\n },\n \"uploadId\": {\n \"type\": \"string\"\n },\n \"fileId\": {\n \"type\": \"string\"\n },\n \"partSizeBytes\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"partCount\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"expiresAt\": {\n \"type\": \"string\",\n \"format\": \"date-time\",\n \"pattern\": \"^(?:(?:\\\\d\\\\d[2468][048]|\\\\d\\\\d[13579][26]|\\\\d\\\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\\\d|30)|(?:02)-(?:0[1-9]|1\\\\d|2[0-8])))T(?:(?:[01]\\\\d|2[0-3]):[0-5]\\\\d(?::[0-5]\\\\d(?:\\\\.\\\\d+)?)?(?:Z))$\"\n },\n \"parts\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"partNumber\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"size\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"etag\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"partNumber\",\n \"etag\"\n ],\n \"additionalProperties\": false\n }\n }\n },\n \"required\": [\n \"transport\",\n \"uploadId\",\n \"fileId\",\n \"partSizeBytes\",\n \"partCount\",\n \"expiresAt\",\n \"parts\"\n ],\n \"additionalProperties\": false\n },\n \"PresignFileUploadPartResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"transport\": {\n \"type\": \"string\",\n \"const\": \"presigned-multipart\"\n },\n \"partNumber\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"url\": {\n \"type\": \"string\",\n \"format\": \"uri\"\n },\n \"headers\": {\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {\n \"type\": \"string\"\n }\n },\n \"expiresAt\": {\n \"type\": \"string\",\n \"format\": \"date-time\",\n \"pattern\": \"^(?:(?:\\\\d\\\\d[2468][048]|\\\\d\\\\d[13579][26]|\\\\d\\\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\\\d|30)|(?:02)-(?:0[1-9]|1\\\\d|2[0-8])))T(?:(?:[01]\\\\d|2[0-3]):[0-5]\\\\d(?::[0-5]\\\\d(?:\\\\.\\\\d+)?)?(?:Z))$\"\n },\n \"partSizeBytes\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n }\n },\n \"required\": [\n \"transport\",\n \"partNumber\",\n \"url\",\n \"headers\",\n \"expiresAt\",\n \"partSizeBytes\"\n ],\n \"additionalProperties\": false\n },\n \"ListFoldersResponse\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/Folder\"\n }\n },\n \"Folder\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\"\n },\n \"parentId\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"type\": {\n \"$ref\": \"#/components/schemas/FolderType\"\n },\n \"name\": {\n \"type\": \"string\"\n },\n \"createdAt\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"string\"\n }\n ]\n },\n \"childCount\": {\n \"description\": \"Direct subfolder count. Present on tree listings.\",\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"workflowCount\": {\n \"description\": \"Workflows filed directly in this folder. Present on workflow-tree listings.\",\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"previewItems\": {\n \"description\": \"Up to a handful of item names — subfolders first, then workflows — for a peek at folder contents. Present on workflow-tree listings.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n },\n \"kind\": {\n \"type\": \"string\",\n \"enum\": [\n \"folder\",\n \"workflow\"\n ]\n }\n },\n \"required\": [\n \"name\",\n \"kind\"\n ],\n \"additionalProperties\": false\n }\n }\n },\n \"required\": [\n \"id\",\n \"parentId\",\n \"type\",\n \"name\",\n \"createdAt\"\n ],\n \"additionalProperties\": false\n },\n \"DeleteFolderResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"deleted\": {\n \"type\": \"boolean\",\n \"const\": true\n },\n \"id\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"deleted\",\n \"id\"\n ],\n \"additionalProperties\": false\n },\n \"HumanReviewListResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"tasks\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"executionId\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"automationId\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"automationName\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"sourceKind\": {\n \"type\": \"string\",\n \"enum\": [\n \"workflow_step\",\n \"agent_tool\"\n ]\n },\n \"sourceLabel\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"status\": {\n \"type\": \"string\",\n \"enum\": [\n \"pending\",\n \"approved\",\n \"rejected\",\n \"cancelled\"\n ]\n },\n \"requiredCount\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 9007199254740991\n },\n \"confirmedCount\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 9007199254740991\n },\n \"version\": {\n \"type\": \"integer\",\n \"exclusiveMinimum\": 0,\n \"maximum\": 9007199254740991\n },\n \"createdAt\": {\n \"type\": \"string\"\n },\n \"updatedAt\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"id\",\n \"executionId\",\n \"automationId\",\n \"automationName\",\n \"sourceKind\",\n \"sourceLabel\",\n \"status\",\n \"requiredCount\",\n \"confirmedCount\",\n \"version\",\n \"createdAt\",\n \"updatedAt\"\n ],\n \"additionalProperties\": false\n }\n },\n \"nextCursor\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n }\n },\n \"required\": [\n \"tasks\",\n \"nextCursor\"\n ],\n \"additionalProperties\": false\n },\n \"HumanReviewTaskResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"task\": {\n \"$ref\": \"#/components/schemas/HumanReviewTaskDetail\"\n }\n },\n \"required\": [\n \"task\"\n ],\n \"additionalProperties\": false\n },\n \"HumanReviewTaskDetail\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"executionId\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"automationId\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"automationName\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"sourceKind\": {\n \"type\": \"string\",\n \"enum\": [\n \"workflow_step\",\n \"agent_tool\"\n ]\n },\n \"sourceLabel\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"status\": {\n \"type\": \"string\",\n \"enum\": [\n \"pending\",\n \"approved\",\n \"rejected\",\n \"cancelled\"\n ]\n },\n \"requiredCount\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 9007199254740991\n },\n \"confirmedCount\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 9007199254740991\n },\n \"version\": {\n \"type\": \"integer\",\n \"exclusiveMinimum\": 0,\n \"maximum\": 9007199254740991\n },\n \"createdAt\": {\n \"type\": \"string\"\n },\n \"updatedAt\": {\n \"type\": \"string\"\n },\n \"files\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"fileId\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"filename\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"mimeType\": {\n \"type\": \"string\"\n },\n \"size\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 9007199254740991\n },\n \"fieldName\": {\n \"type\": \"string\"\n },\n \"artifactPath\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"role\": {\n \"description\": \"run_input for authorized run input files; attachment for extra current-run files. Omitted on historical tasks and inferred at read time.\",\n \"type\": \"string\",\n \"enum\": [\n \"run_input\",\n \"attachment\"\n ]\n }\n },\n \"required\": [\n \"fileId\",\n \"filename\",\n \"artifactPath\"\n ],\n \"additionalProperties\": false\n }\n },\n \"input\": {\n \"anyOf\": [\n {\n \"oneOf\": [\n {\n \"type\": \"object\",\n \"properties\": {\n \"status\": {\n \"type\": \"string\",\n \"const\": \"available\"\n },\n \"data\": {\n \"anyOf\": [\n {\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {}\n },\n {\n \"type\": \"array\",\n \"items\": {}\n }\n ]\n }\n },\n \"required\": [\n \"status\",\n \"data\"\n ],\n \"additionalProperties\": false\n },\n {\n \"type\": \"object\",\n \"properties\": {\n \"status\": {\n \"type\": \"string\",\n \"const\": \"omitted_too_large\"\n }\n },\n \"required\": [\n \"status\"\n ],\n \"additionalProperties\": false\n }\n ],\n \"type\": \"object\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Non-file trigger input derived at read time. Null when every field is a file or external source id. omitted_too_large when the projection exceeds the review data byte limit.\"\n },\n \"machineData\": {\n \"anyOf\": [\n {\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {}\n },\n {\n \"type\": \"array\",\n \"items\": {}\n }\n ]\n },\n \"draftData\": {\n \"anyOf\": [\n {\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {}\n },\n {\n \"type\": \"array\",\n \"items\": {}\n }\n ]\n },\n \"schema\": {\n \"anyOf\": [\n {\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {}\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"fieldMetadata\": {\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {\n \"type\": \"object\",\n \"properties\": {\n \"confidence\": {\n \"description\": \"Producer-supplied confidence: 0–1 numeric (legacy) or categorical low|medium|high from ai.extract grounding. Not calibrated by Eigenpal.\",\n \"anyOf\": [\n {\n \"type\": \"number\",\n \"minimum\": 0,\n \"maximum\": 1\n },\n {\n \"type\": \"string\",\n \"enum\": [\n \"low\",\n \"medium\",\n \"high\"\n ]\n },\n {\n \"type\": \"string\",\n \"minLength\": 1\n }\n ]\n },\n \"label\": {\n \"description\": \"Short label shown in the review UI\",\n \"type\": \"string\",\n \"maxLength\": 500\n },\n \"description\": {\n \"description\": \"Longer reviewer guidance for this field\",\n \"type\": \"string\",\n \"maxLength\": 5000\n },\n \"review\": {\n \"description\": \"Legacy per-field override kept for existing tasks. Prefer selection.fields.review.\",\n \"default\": \"auto\",\n \"type\": \"string\",\n \"enum\": [\n \"auto\",\n \"always\",\n \"never\"\n ]\n },\n \"display\": {\n \"description\": \"Opaque display metadata preserved for the review UI\",\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {}\n }\n },\n \"additionalProperties\": false\n }\n },\n \"requiredPaths\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n },\n \"selectionReasons\": {\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {\n \"type\": \"string\",\n \"enum\": [\n \"always\",\n \"explicit\",\n \"low_confidence\",\n \"missing_confidence\",\n \"all\",\n \"reviewer_edit\",\n \"threshold_met\",\n \"never\",\n \"excluded\",\n \"unmatched\",\n \"missing_confidence_skip\"\n ]\n }\n },\n \"decisions\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"path\": {\n \"type\": \"string\"\n },\n \"originalValue\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"number\"\n },\n {\n \"type\": \"boolean\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"currentValue\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"number\"\n },\n {\n \"type\": \"boolean\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"required\": {\n \"type\": \"boolean\"\n },\n \"reason\": {\n \"type\": \"string\",\n \"enum\": [\n \"always\",\n \"explicit\",\n \"low_confidence\",\n \"missing_confidence\",\n \"all\",\n \"reviewer_edit\",\n \"threshold_met\",\n \"never\",\n \"excluded\",\n \"unmatched\",\n \"missing_confidence_skip\"\n ]\n },\n \"confirmedBy\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"confirmedAt\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"version\": {\n \"type\": \"integer\",\n \"exclusiveMinimum\": 0,\n \"maximum\": 9007199254740991\n }\n },\n \"required\": [\n \"id\",\n \"path\",\n \"originalValue\",\n \"currentValue\",\n \"required\",\n \"reason\",\n \"confirmedBy\",\n \"confirmedAt\",\n \"version\"\n ],\n \"additionalProperties\": false\n }\n },\n \"instructions\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"completedBy\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"completedAt\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"outcomeReason\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"lineage\": {\n \"description\": \"Optional lineage@1 document resolved from the extract sidecar. Omitted when missing or unreadable. Validate with @openparser/lineage.\",\n \"type\": \"object\",\n \"additionalProperties\": true\n },\n \"parsedDocument\": {\n \"description\": \"Optional ParsedDocument resolved from the extract sidecar. Omitted when missing or unreadable. Validate with @openparser/schema.\",\n \"type\": \"object\",\n \"additionalProperties\": true\n }\n },\n \"required\": [\n \"id\",\n \"executionId\",\n \"automationId\",\n \"automationName\",\n \"sourceKind\",\n \"sourceLabel\",\n \"status\",\n \"requiredCount\",\n \"confirmedCount\",\n \"version\",\n \"createdAt\",\n \"updatedAt\",\n \"files\",\n \"input\",\n \"machineData\",\n \"draftData\",\n \"schema\",\n \"fieldMetadata\",\n \"requiredPaths\",\n \"selectionReasons\",\n \"decisions\",\n \"instructions\",\n \"completedBy\",\n \"completedAt\",\n \"outcomeReason\"\n ],\n \"additionalProperties\": false\n },\n \"HumanReviewApproveResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"task\": {\n \"$ref\": \"#/components/schemas/HumanReviewTaskDetail\"\n }\n },\n \"required\": [\n \"task\"\n ],\n \"additionalProperties\": false\n },\n \"HumanReviewFieldResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"task\": {\n \"$ref\": \"#/components/schemas/HumanReviewTaskDetail\"\n }\n },\n \"required\": [\n \"task\"\n ],\n \"additionalProperties\": false\n },\n \"HumanReviewRejectResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"task\": {\n \"$ref\": \"#/components/schemas/HumanReviewTaskDetail\"\n }\n },\n \"required\": [\n \"task\"\n ],\n \"additionalProperties\": false\n },\n \"ListModelsResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"data\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/PublicModel\"\n }\n },\n \"total\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 9007199254740991\n }\n },\n \"required\": [\n \"data\",\n \"total\"\n ],\n \"additionalProperties\": false\n },\n \"PublicModel\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\"\n },\n \"kind\": {\n \"type\": \"string\",\n \"enum\": [\n \"llm\",\n \"ocr\"\n ]\n },\n \"provider\": {\n \"type\": \"string\"\n },\n \"label\": {\n \"type\": \"string\"\n },\n \"capabilities\": {\n \"minItems\": 1,\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\",\n \"enum\": [\n \"text\",\n \"vision\",\n \"ocr\"\n ]\n }\n },\n \"configured\": {\n \"type\": \"boolean\"\n },\n \"available\": {\n \"type\": \"boolean\"\n },\n \"health\": {\n \"type\": \"string\",\n \"enum\": [\n \"configured\",\n \"unconfigured\",\n \"unknown\"\n ],\n \"description\": \"Configuration state only: `configured` means credentials are present in this environment; `unconfigured` means the catalog entry exists but credentials are missing. This list does not probe live providers, so it never reports healthy/degraded/outage. `unknown` is reserved and is not emitted by this endpoint.\"\n },\n \"defaultFor\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\",\n \"enum\": [\n \"text\",\n \"vision\",\n \"ocr\"\n ]\n }\n },\n \"location\": {\n \"type\": \"string\",\n \"enum\": [\n \"local\",\n \"hosted\"\n ],\n \"description\": \"`local` means on-prem / no cloud provider egress (`local: true` or tesseract). `hosted` means the provider is a cloud API. Endpoints are never returned.\"\n },\n \"limits\": {\n \"$ref\": \"#/components/schemas/PublicModelLimits\"\n },\n \"cost\": {\n \"description\": \"Static Eigenpal credit rates when known without a live vendor catalog. Omitted for OpenParser OCR and for LLMs (token prices are not part of this catalog).\",\n \"$ref\": \"#/components/schemas/PublicModelCost\"\n },\n \"aliases\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n },\n \"tags\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n },\n \"capabilityRank\": {\n \"description\": \"Optional picker rank. Higher is more capable. Omitted on catalog rows that do not set it. Does not change role defaults.\",\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n }\n },\n \"required\": [\n \"id\",\n \"kind\",\n \"provider\",\n \"label\",\n \"capabilities\",\n \"configured\",\n \"available\",\n \"health\",\n \"defaultFor\",\n \"location\",\n \"aliases\",\n \"tags\"\n ],\n \"additionalProperties\": false\n },\n \"PublicModelLimits\": {\n \"type\": \"object\",\n \"properties\": {\n \"requestTimeoutSeconds\": {\n \"type\": \"integer\",\n \"exclusiveMinimum\": 0,\n \"maximum\": 9007199254740991\n },\n \"maxConcurrentRequests\": {\n \"type\": \"integer\",\n \"exclusiveMinimum\": 0,\n \"maximum\": 9007199254740991\n }\n },\n \"additionalProperties\": false\n },\n \"PublicModelCost\": {\n \"type\": \"object\",\n \"properties\": {\n \"creditsPerPage\": {\n \"type\": \"number\",\n \"minimum\": 0\n },\n \"unit\": {\n \"type\": \"string\",\n \"const\": \"credits\"\n }\n },\n \"required\": [\n \"unit\"\n ],\n \"additionalProperties\": false\n },\n \"RunsListResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"runs\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/RunListItem\"\n }\n },\n \"nextCursor\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n }\n },\n \"required\": [\n \"runs\",\n \"nextCursor\"\n ],\n \"additionalProperties\": false\n },\n \"RunListItem\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\"\n },\n \"type\": {\n \"type\": \"string\",\n \"enum\": [\n \"workflow\",\n \"agent\"\n ]\n },\n \"finished\": {\n \"type\": \"boolean\",\n \"description\": \"True when the run has reached a terminal status.\"\n },\n \"sampleRank\": {\n \"type\": \"number\",\n \"minimum\": 0,\n \"maximum\": 1,\n \"description\": \"Deterministic pseudo-random rank in [0, 1) for this run within the tenant. Use with a sample rate threshold to review a stable subset.\"\n },\n \"parentExecutionId\": {\n \"description\": \"Parent run id when this run was started by an invoke-workflow step. Omitted for top-level runs.\",\n \"type\": \"string\"\n },\n \"timing\": {\n \"$ref\": \"#/components/schemas/RunTiming\"\n },\n \"source\": {\n \"$ref\": \"#/components/schemas/RunSource\"\n },\n \"trigger\": {\n \"$ref\": \"#/components/schemas/RunTrigger\"\n },\n \"eval\": {\n \"description\": \"Present only on eval-scoped runs. Omitted otherwise.\",\n \"$ref\": \"#/components/schemas/RunEval\"\n },\n \"error\": {\n \"description\": \"Terminal failure message. Present on terminal runs; null when the run succeeded. Absent while the run is still in flight.\",\n \"$ref\": \"#/components/schemas/RunError\"\n },\n \"execution\": {\n \"$ref\": \"#/components/schemas/RunExecutionMeta\"\n }\n },\n \"required\": [\n \"id\",\n \"type\",\n \"finished\",\n \"sampleRank\",\n \"timing\",\n \"source\",\n \"trigger\",\n \"execution\"\n ],\n \"additionalProperties\": false\n },\n \"RunTiming\": {\n \"type\": \"object\",\n \"properties\": {\n \"createdAt\": {\n \"type\": \"string\"\n },\n \"startedAt\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"completedAt\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"durationMs\": {\n \"anyOf\": [\n {\n \"type\": \"number\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"cancelRequestedAt\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"When the user requested cancel; status may still be `running` until the worker stops.\"\n }\n },\n \"required\": [\n \"createdAt\",\n \"startedAt\",\n \"completedAt\",\n \"durationMs\",\n \"cancelRequestedAt\"\n ],\n \"additionalProperties\": false\n },\n \"RunSource\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\",\n \"description\": \"Owning workflow id or agent id.\"\n },\n \"name\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"version\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Workflow version label (workflow runs only).\"\n },\n \"versionId\": {\n \"description\": \"Captured workflow version id (workflow runs only).\",\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"slug\": {\n \"description\": \"Agent slug (agent runs only).\",\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"model\": {\n \"description\": \"LLM model used (agent runs only).\",\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"git\": {\n \"description\": \"Git provenance (agent runs only).\",\n \"anyOf\": [\n {\n \"$ref\": \"#/components/schemas/RunSourceGit\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"implementationAvailable\": {\n \"description\": \"Whether the live workflow/agent implementation still exists (`GET /api/v1/runs/:id` detail only).\",\n \"type\": \"boolean\"\n },\n \"automationFound\": {\n \"description\": \"Whether the owning automation registry row still exists (`GET /api/v1/runs/:id` detail only).\",\n \"type\": \"boolean\"\n },\n \"currentVersion\": {\n \"description\": \"Current released workflow version label when the source is live (`GET /api/v1/runs/:id` detail only).\",\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n }\n },\n \"required\": [\n \"id\",\n \"name\",\n \"version\"\n ],\n \"additionalProperties\": false\n },\n \"RunSourceGit\": {\n \"type\": \"object\",\n \"properties\": {\n \"requestedRef\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"resolvedRef\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"resolvedTag\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"commitSha\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n }\n },\n \"required\": [\n \"requestedRef\",\n \"resolvedRef\",\n \"resolvedTag\",\n \"commitSha\"\n ],\n \"additionalProperties\": false\n },\n \"RunTrigger\": {\n \"type\": \"object\",\n \"properties\": {\n \"type\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"by\": {\n \"anyOf\": [\n {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\"\n },\n \"name\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"email\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"id\",\n \"name\",\n \"email\"\n ],\n \"additionalProperties\": false\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"email\": {\n \"description\": \"Inbound email trigger details (agent runs, `expand=input` not required).\"\n }\n },\n \"required\": [\n \"type\",\n \"by\"\n ],\n \"additionalProperties\": false\n },\n \"RunEval\": {\n \"type\": \"object\",\n \"properties\": {\n \"example\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Eval example label (agent example name or workflow example id).\"\n },\n \"exampleId\": {\n \"description\": \"Workflow eval example folder id (workflow runs only).\",\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"score\": {\n \"anyOf\": [\n {\n \"type\": \"number\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"passed\": {\n \"anyOf\": [\n {\n \"type\": \"boolean\"\n },\n {\n \"type\": \"null\"\n }\n ]\n }\n },\n \"required\": [\n \"example\",\n \"score\",\n \"passed\"\n ],\n \"additionalProperties\": false\n },\n \"RunError\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"RunExecutionMeta\": {\n \"type\": \"object\",\n \"properties\": {\n \"status\": {\n \"description\": \"Status of this run. `retry.nextRun.status` is a later retry, not this run.\",\n \"$ref\": \"#/components/schemas/ExecutionStatus\"\n },\n \"schemaValid\": {\n \"anyOf\": [\n {\n \"type\": \"boolean\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Whether the completed output matched the workflow or agent output schema.\"\n },\n \"batchId\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Experiment batch id when the run is part of a batch.\"\n },\n \"retry\": {\n \"$ref\": \"#/components/schemas/RunExecutionRetry\"\n },\n \"review\": {\n \"description\": \"Lightweight review state for run list rows.\",\n \"anyOf\": [\n {\n \"$ref\": \"#/components/schemas/RunReviewSummary\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"humanReview\": {\n \"description\": \"Pending in-flight human review when the run is waiting on a reviewer.\",\n \"anyOf\": [\n {\n \"$ref\": \"#/components/schemas/RunHumanReviewSummary\"\n },\n {\n \"type\": \"null\"\n }\n ]\n }\n },\n \"required\": [\n \"status\",\n \"schemaValid\",\n \"batchId\",\n \"retry\"\n ],\n \"additionalProperties\": false\n },\n \"ExecutionStatus\": {\n \"type\": \"string\",\n \"enum\": [\n \"created\",\n \"pending\",\n \"running\",\n \"waiting\",\n \"finalizing\",\n \"completed\",\n \"failed\",\n \"cancelled\",\n \"rejected\"\n ]\n },\n \"RunExecutionRetry\": {\n \"type\": \"object\",\n \"properties\": {\n \"number\": {\n \"type\": \"number\",\n \"description\": \"Retry attempt index (0 = original run).\"\n },\n \"previousRunId\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Run id of the prior attempt in the retry chain.\"\n },\n \"nextRun\": {\n \"anyOf\": [\n {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\"\n },\n \"status\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"id\",\n \"status\"\n ],\n \"additionalProperties\": false\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Retry run spawned from this run, if any. Present on list and detail without `expand`. `status` here is the later retry, not this run.\"\n }\n },\n \"required\": [\n \"number\",\n \"previousRunId\",\n \"nextRun\"\n ],\n \"additionalProperties\": false\n },\n \"RunReviewSummary\": {\n \"type\": \"object\",\n \"properties\": {\n \"verdict\": {\n \"anyOf\": [\n {\n \"type\": \"string\",\n \"enum\": [\n \"correct\",\n \"incorrect\"\n ]\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"status\": {\n \"type\": \"string\",\n \"enum\": [\n \"open\",\n \"closed\",\n \"wont_fix\"\n ]\n },\n \"hasNote\": {\n \"type\": \"boolean\",\n \"description\": \"True when review notes were left.\"\n },\n \"correctionCount\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991,\n \"description\": \"Number of field/file corrections.\"\n }\n },\n \"required\": [\n \"verdict\",\n \"status\",\n \"hasNote\",\n \"correctionCount\"\n ],\n \"additionalProperties\": false\n },\n \"RunHumanReviewSummary\": {\n \"type\": \"object\",\n \"properties\": {\n \"taskId\": {\n \"type\": \"string\"\n },\n \"sourceKind\": {\n \"type\": \"string\",\n \"enum\": [\n \"workflow_step\",\n \"agent_tool\"\n ]\n },\n \"sourceLabel\": {\n \"type\": \"string\"\n },\n \"status\": {\n \"type\": \"string\",\n \"const\": \"pending\"\n },\n \"requiredCount\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 9007199254740991\n },\n \"confirmedCount\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 9007199254740991\n },\n \"version\": {\n \"type\": \"integer\",\n \"exclusiveMinimum\": 0,\n \"maximum\": 9007199254740991\n }\n },\n \"required\": [\n \"taskId\",\n \"sourceKind\",\n \"sourceLabel\",\n \"status\",\n \"requiredCount\",\n \"confirmedCount\",\n \"version\"\n ],\n \"additionalProperties\": false\n },\n \"Run\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\"\n },\n \"type\": {\n \"type\": \"string\",\n \"enum\": [\n \"workflow\",\n \"agent\"\n ]\n },\n \"finished\": {\n \"type\": \"boolean\",\n \"description\": \"True when the run has reached a terminal status.\"\n },\n \"sampleRank\": {\n \"type\": \"number\",\n \"minimum\": 0,\n \"maximum\": 1,\n \"description\": \"Deterministic pseudo-random rank in [0, 1) for this run within the tenant. Use with a sample rate threshold to review a stable subset.\"\n },\n \"parentExecutionId\": {\n \"description\": \"Parent run id when this run was started by an invoke-workflow step. Omitted for top-level runs.\",\n \"type\": \"string\"\n },\n \"timing\": {\n \"$ref\": \"#/components/schemas/RunTiming\"\n },\n \"source\": {\n \"$ref\": \"#/components/schemas/RunSource\"\n },\n \"trigger\": {\n \"$ref\": \"#/components/schemas/RunTrigger\"\n },\n \"eval\": {\n \"description\": \"Present only on eval-scoped runs. Omitted otherwise.\",\n \"$ref\": \"#/components/schemas/RunEval\"\n },\n \"output\": {\n \"description\": \"Completed runs only. Per-automation business result — not a generic schema. Absent until the run completes.\",\n \"anyOf\": [\n {\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {}\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"files\": {\n \"description\": \"Completed runs only. Download with GET /api/v1/runs/:id/artifacts/:path. Absent until the run completes.\",\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/RunArtifact\"\n }\n },\n \"error\": {\n \"description\": \"Terminal failure message. Present on terminal runs; null when the run succeeded. Absent while the run is still in flight.\",\n \"$ref\": \"#/components/schemas/RunError\"\n },\n \"input\": {\n \"description\": \"Present only with `expand=input`.\",\n \"$ref\": \"#/components/schemas/RunInput\"\n },\n \"usage\": {\n \"description\": \"Present only with `expand=usage`. Null for old runs without telemetry.\",\n \"anyOf\": [\n {\n \"$ref\": \"#/components/schemas/RunUsage\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"execution\": {\n \"anyOf\": [\n {\n \"$ref\": \"#/components/schemas/RunExecutionMeta\"\n },\n {\n \"$ref\": \"#/components/schemas/RunExecution\"\n }\n ],\n \"description\": \"Slim execution metadata always present (`status`, `schemaValid`, `batchId`, `retry`). Pass `expand=execution` to replace with full RunExecution (WorkflowRunExecution or AgentRunExecution depending on run type).\"\n },\n \"debug\": {\n \"description\": \"Present only with `expand=debug`.\",\n \"$ref\": \"#/components/schemas/RunDebug\"\n }\n },\n \"required\": [\n \"id\",\n \"type\",\n \"finished\",\n \"sampleRank\",\n \"timing\",\n \"source\",\n \"trigger\",\n \"execution\"\n ],\n \"additionalProperties\": false,\n \"example\": {\n \"id\": \"wfx_01HZXEXAMPLE\",\n \"type\": \"workflow\",\n \"finished\": true,\n \"sampleRank\": 0.42,\n \"timing\": {\n \"createdAt\": \"2026-01-15T10:00:00.000Z\",\n \"startedAt\": \"2026-01-15T10:00:01.000Z\",\n \"completedAt\": \"2026-01-15T10:00:08.000Z\",\n \"durationMs\": 7000,\n \"cancelRequestedAt\": null\n },\n \"source\": {\n \"id\": \"wf_invoice\",\n \"name\": \"Invoice extraction\",\n \"version\": \"3\",\n \"versionId\": \"wfh_3\"\n },\n \"trigger\": {\n \"type\": \"api\",\n \"by\": null\n },\n \"output\": {\n \"vendor\": \"Acme\",\n \"total\": 149.5\n },\n \"files\": [\n {\n \"name\": \"file_1-invoice.json\",\n \"role\": \"output\",\n \"path\": \"output/extract/file_1-invoice.json\",\n \"stepName\": \"extract\"\n }\n ],\n \"error\": null,\n \"execution\": {\n \"status\": \"completed\",\n \"schemaValid\": true,\n \"batchId\": null,\n \"retry\": {\n \"number\": 0,\n \"previousRunId\": null,\n \"nextRun\": null\n }\n }\n }\n },\n \"RunArtifact\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n },\n \"role\": {\n \"type\": \"string\",\n \"description\": \"`input`, `output`, `debug`, `report`, or another stable artifact role.\"\n },\n \"path\": {\n \"type\": \"string\",\n \"description\": \"Canonical artifact path for GET /api/v1/runs/:id/artifacts/:path.\"\n },\n \"stepName\": {\n \"description\": \"Workflow step that produced the file, when known.\",\n \"type\": \"string\"\n },\n \"contentType\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"size\": {\n \"anyOf\": [\n {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n {\n \"type\": \"null\"\n }\n ]\n }\n },\n \"required\": [\n \"name\",\n \"role\",\n \"path\"\n ],\n \"additionalProperties\": false\n },\n \"RunInput\": {\n \"type\": \"object\",\n \"properties\": {\n \"args\": {\n \"description\": \"Input arguments the run was started with.\"\n },\n \"files\": {\n \"description\": \"Uploaded input files (agent runs only).\",\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/RunFile\"\n }\n },\n \"metadata\": {\n \"description\": \"Caller-supplied run metadata, if any.\"\n }\n },\n \"required\": [\n \"args\"\n ],\n \"additionalProperties\": false\n },\n \"RunFile\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"name\"\n ],\n \"additionalProperties\": false\n },\n \"RunUsage\": {\n \"type\": \"object\",\n \"properties\": {\n \"tokens\": {\n \"type\": \"object\",\n \"properties\": {\n \"input\": {\n \"anyOf\": [\n {\n \"type\": \"number\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"output\": {\n \"anyOf\": [\n {\n \"type\": \"number\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"cacheRead\": {\n \"anyOf\": [\n {\n \"type\": \"number\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"cacheWrite\": {\n \"anyOf\": [\n {\n \"type\": \"number\"\n },\n {\n \"type\": \"null\"\n }\n ]\n }\n },\n \"required\": [\n \"input\",\n \"output\",\n \"cacheRead\",\n \"cacheWrite\"\n ],\n \"additionalProperties\": false\n },\n \"creditsCharged\": {\n \"anyOf\": [\n {\n \"type\": \"number\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"durationMs\": {\n \"anyOf\": [\n {\n \"type\": \"number\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"llmCallCount\": {\n \"description\": \"LLM call count (workflow runs only).\",\n \"type\": \"number\"\n },\n \"ocrPagesProcessed\": {\n \"description\": \"OCR pages processed (workflow runs only).\",\n \"type\": \"number\"\n },\n \"agentTurns\": {\n \"description\": \"Agent conversation turns (agent runs only).\",\n \"anyOf\": [\n {\n \"type\": \"number\"\n },\n {\n \"type\": \"null\"\n }\n ]\n }\n },\n \"required\": [\n \"tokens\",\n \"creditsCharged\",\n \"durationMs\"\n ],\n \"additionalProperties\": false\n },\n \"RunExecution\": {\n \"anyOf\": [\n {\n \"$ref\": \"#/components/schemas/WorkflowRunExecution\"\n },\n {\n \"$ref\": \"#/components/schemas/AgentRunExecution\"\n }\n ]\n },\n \"WorkflowRunExecution\": {\n \"type\": \"object\",\n \"properties\": {\n \"status\": {\n \"description\": \"Status of this run. `retry.nextRun.status` is a later retry, not this run.\",\n \"$ref\": \"#/components/schemas/ExecutionStatus\"\n },\n \"schemaValid\": {\n \"anyOf\": [\n {\n \"type\": \"boolean\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Whether the completed output matched the workflow or agent output schema.\"\n },\n \"batchId\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Experiment batch id when the run is part of a batch.\"\n },\n \"retry\": {\n \"$ref\": \"#/components/schemas/RunExecutionRetry\"\n },\n \"review\": {\n \"anyOf\": [\n {\n \"$ref\": \"#/components/schemas/RunReview\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"humanReview\": {\n \"description\": \"Pending in-flight human review when the run is waiting on a reviewer.\",\n \"anyOf\": [\n {\n \"$ref\": \"#/components/schemas/RunHumanReviewSummary\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"steps\": {\n \"type\": \"array\",\n \"items\": {},\n \"description\": \"Slim per-step rows (`id`, name, type, status, timing, order, capped error excerpt). Full `input`/`output` live on `GET /api/v1/runs/{id}/steps/{stepExecutionId}`.\"\n },\n \"childExecutions\": {\n \"description\": \"Child invoke-workflow runs and their steps (`expand=execution`, workflow runs only). Omitted when there are no children.\",\n \"type\": \"array\",\n \"items\": {}\n },\n \"definitionSnapshot\": {\n \"description\": \"Workflow definition snapshot captured when the run was created (`expand=execution`).\",\n \"anyOf\": [\n {},\n {\n \"type\": \"null\"\n }\n ]\n },\n \"expected\": {\n \"description\": \"Ground-truth expected output and files.\",\n \"type\": \"object\",\n \"properties\": {\n \"output\": {},\n \"files\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/RunFile\"\n }\n }\n },\n \"additionalProperties\": false\n }\n },\n \"required\": [\n \"status\",\n \"schemaValid\",\n \"batchId\",\n \"retry\",\n \"steps\"\n ],\n \"additionalProperties\": false\n },\n \"RunReview\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\"\n },\n \"verdict\": {\n \"anyOf\": [\n {\n \"type\": \"string\",\n \"enum\": [\n \"correct\",\n \"incorrect\"\n ]\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"status\": {\n \"type\": \"string\",\n \"enum\": [\n \"open\",\n \"closed\",\n \"wont_fix\"\n ]\n },\n \"note\": {\n \"type\": \"string\"\n },\n \"correctedOutput\": {\n \"anyOf\": [\n {},\n {\n \"type\": \"null\"\n }\n ]\n },\n \"reviewedBy\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"User id of the last reviewer. Read-only; set from the authenticated user or API key creator.\"\n },\n \"reviewedByEmail\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Email of the last reviewer. Read-only; set from the authenticated user or API key creator.\"\n },\n \"reviewedAt\": {\n \"type\": \"string\"\n },\n \"closedBy\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"User id recorded when the review was closed. Read-only; set when status becomes closed or wont_fix.\"\n },\n \"closedByEmail\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Email recorded when the review was closed. Read-only; set when status becomes closed or wont_fix.\"\n },\n \"closedAt\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"closedNote\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"createdAt\": {\n \"type\": \"string\"\n },\n \"updatedAt\": {\n \"type\": \"string\"\n },\n \"corrections\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/RunReviewCorrection\"\n }\n }\n },\n \"required\": [\n \"id\",\n \"verdict\",\n \"status\",\n \"note\",\n \"reviewedBy\",\n \"reviewedByEmail\",\n \"reviewedAt\",\n \"closedBy\",\n \"closedByEmail\",\n \"closedAt\",\n \"closedNote\",\n \"createdAt\",\n \"updatedAt\",\n \"corrections\"\n ],\n \"additionalProperties\": false\n },\n \"RunReviewCorrection\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\"\n },\n \"kind\": {\n \"type\": \"string\",\n \"enum\": [\n \"field\",\n \"file\"\n ]\n },\n \"path\": {\n \"type\": \"string\",\n \"description\": \"JSON Pointer for field corrections, or canonical artifact path for file reviews.\"\n },\n \"label\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"originalValue\": {\n \"anyOf\": [\n {},\n {\n \"type\": \"null\"\n }\n ]\n },\n \"correctedValue\": {\n \"anyOf\": [\n {},\n {\n \"type\": \"null\"\n }\n ]\n },\n \"note\": {\n \"type\": \"string\"\n },\n \"correctedArtifactPath\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"createdAt\": {\n \"type\": \"string\"\n },\n \"updatedAt\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"id\",\n \"kind\",\n \"path\",\n \"label\",\n \"note\",\n \"createdAt\",\n \"updatedAt\"\n ],\n \"additionalProperties\": false\n },\n \"AgentRunExecution\": {\n \"type\": \"object\",\n \"properties\": {\n \"status\": {\n \"description\": \"Status of this run. `retry.nextRun.status` is a later retry, not this run.\",\n \"$ref\": \"#/components/schemas/ExecutionStatus\"\n },\n \"schemaValid\": {\n \"anyOf\": [\n {\n \"type\": \"boolean\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Whether the completed output matched the workflow or agent output schema.\"\n },\n \"batchId\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Experiment batch id when the run is part of a batch.\"\n },\n \"retry\": {\n \"$ref\": \"#/components/schemas/RunExecutionRetry\"\n },\n \"review\": {\n \"anyOf\": [\n {\n \"$ref\": \"#/components/schemas/RunReview\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"humanReview\": {\n \"description\": \"Pending in-flight human review when the run is waiting on a reviewer.\",\n \"anyOf\": [\n {\n \"$ref\": \"#/components/schemas/RunHumanReviewSummary\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"files\": {\n \"type\": \"object\",\n \"properties\": {\n \"output\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/RunFile\"\n },\n \"description\": \"Output artifacts the agent produced.\"\n }\n },\n \"required\": [\n \"output\"\n ],\n \"additionalProperties\": false\n },\n \"expected\": {\n \"description\": \"Ground-truth expected output and files.\",\n \"type\": \"object\",\n \"properties\": {\n \"output\": {},\n \"files\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/RunFile\"\n }\n }\n },\n \"additionalProperties\": false\n },\n \"comparison\": {\n \"description\": \"Expected-vs-actual comparison for eval runs (terminal runs only).\"\n }\n },\n \"required\": [\n \"status\",\n \"schemaValid\",\n \"batchId\",\n \"retry\",\n \"files\"\n ],\n \"additionalProperties\": false\n },\n \"RunDebug\": {\n \"type\": \"object\",\n \"properties\": {\n \"observability\": {\n \"description\": \"Execution phase timeline and structured failure.\"\n },\n \"traceId\": {\n \"description\": \"Workflow trace id for span lookup (workflow runs only).\",\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n }\n },\n \"required\": [\n \"observability\"\n ],\n \"additionalProperties\": false\n },\n \"RunAccepted\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\"\n },\n \"type\": {\n \"type\": \"string\",\n \"enum\": [\n \"workflow\",\n \"agent\"\n ]\n },\n \"finished\": {\n \"type\": \"boolean\",\n \"const\": false\n },\n \"source\": {\n \"$ref\": \"#/components/schemas/RunSource\"\n }\n },\n \"required\": [\n \"id\",\n \"type\",\n \"finished\"\n ],\n \"additionalProperties\": false,\n \"example\": {\n \"id\": \"wfx_01HZXEXAMPLE\",\n \"type\": \"workflow\",\n \"finished\": false,\n \"source\": {\n \"id\": \"wf_invoice\",\n \"name\": \"Invoice extraction\",\n \"version\": null\n }\n }\n },\n \"RunArtifactsResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"artifacts\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/RunArtifact\"\n }\n }\n },\n \"required\": [\n \"artifacts\"\n ],\n \"additionalProperties\": false\n },\n \"RunCancelResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\"\n },\n \"type\": {\n \"type\": \"string\",\n \"enum\": [\n \"workflow\",\n \"agent\"\n ]\n },\n \"finished\": {\n \"type\": \"boolean\",\n \"description\": \"True when the run has reached a terminal status.\"\n },\n \"execution\": {\n \"type\": \"object\",\n \"properties\": {\n \"status\": {\n \"$ref\": \"#/components/schemas/ExecutionStatus\"\n }\n },\n \"required\": [\n \"status\"\n ],\n \"additionalProperties\": false\n },\n \"cancellation\": {\n \"type\": \"object\",\n \"properties\": {\n \"state\": {\n \"type\": \"string\",\n \"enum\": [\n \"cancelled\",\n \"requested\",\n \"already_terminal\"\n ],\n \"description\": \"`cancelled` — the run was terminated immediately (it had not started). `requested` — the run is in-flight; cancellation was requested and the status will become `cancelled` shortly. `already_terminal` — the run had already finished; nothing changed.\"\n },\n \"wasStatus\": {\n \"description\": \"Run status at the time the cancel request was received.\",\n \"$ref\": \"#/components/schemas/ExecutionStatus\"\n }\n },\n \"required\": [\n \"state\",\n \"wasStatus\"\n ],\n \"additionalProperties\": false\n }\n },\n \"required\": [\n \"id\",\n \"type\",\n \"finished\",\n \"execution\",\n \"cancellation\"\n ],\n \"additionalProperties\": false\n },\n \"RunEventsResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"events\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/RunEvent\"\n }\n }\n },\n \"required\": [\n \"events\"\n ],\n \"additionalProperties\": false\n },\n \"RunEvent\": {\n \"type\": \"object\",\n \"properties\": {\n \"type\": {\n \"type\": \"string\"\n },\n \"timestamp\": {\n \"type\": \"string\"\n },\n \"status\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"message\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"metadata\": {\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {}\n }\n },\n \"required\": [\n \"type\",\n \"timestamp\"\n ],\n \"additionalProperties\": false\n },\n \"PromoteRunResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"automationId\": {\n \"type\": \"string\",\n \"description\": \"Automation that owns the promoted example.\"\n },\n \"automationType\": {\n \"type\": \"string\",\n \"enum\": [\n \"workflow\",\n \"agent\"\n ],\n \"description\": \"Implementation type behind the automation.\"\n },\n \"exampleId\": {\n \"type\": \"string\",\n \"description\": \"Dataset example identifier returned for follow-up API calls.\"\n },\n \"name\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Dataset example name.\"\n }\n },\n \"required\": [\n \"automationId\",\n \"automationType\",\n \"exampleId\",\n \"name\"\n ],\n \"additionalProperties\": false\n },\n \"RunReviewDetail\": {\n \"type\": \"object\",\n \"properties\": {\n \"review\": {\n \"anyOf\": [\n {\n \"$ref\": \"#/components/schemas/RunReview\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Review metadata and corrections. Corrected files are listed separately at GET /runs/{id}/reviews/expected.\"\n }\n },\n \"required\": [\n \"review\"\n ],\n \"additionalProperties\": false\n },\n \"RunReviewExpectedArtifacts\": {\n \"type\": \"object\",\n \"properties\": {\n \"files\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/RunFile\"\n },\n \"description\": \"Corrected artifact files attached to the run review. Corrected JSON output lives on the review object at GET /runs/{id}/reviews.\"\n }\n },\n \"required\": [\n \"files\"\n ],\n \"additionalProperties\": false\n },\n \"RunReviewExpectedFileMutationResponse\": {\n \"description\": \"Corrected file created or renamed by the request.\",\n \"$ref\": \"#/components/schemas/RunFile\"\n },\n \"RunReviewExpectedFileUpdateResponse\": {\n \"description\": \"Corrected file after the rename.\",\n \"$ref\": \"#/components/schemas/RunFile\"\n },\n \"RunScoresResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"scores\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/EvalResult\"\n },\n \"description\": \"Automated evaluator scores for the run. These are separate from human review verdicts.\"\n }\n },\n \"required\": [\n \"scores\"\n ],\n \"additionalProperties\": false,\n \"description\": \"Automated evaluator results attached to a run.\"\n },\n \"RunStepsResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"steps\": {\n \"type\": \"array\",\n \"items\": {}\n },\n \"total\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n }\n },\n \"required\": [\n \"steps\",\n \"total\"\n ],\n \"additionalProperties\": false\n },\n \"RunStepDetailResponse\": {},\n \"RunTraceResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"events\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/RunTraceEvent\"\n },\n \"description\": \"Chronological trace events. Workflow runs return observability phases or step executions; agent runs return parsed trace.jsonl events.\"\n }\n },\n \"required\": [\n \"events\"\n ],\n \"additionalProperties\": false\n },\n \"RunTraceEvent\": {\n \"type\": \"object\",\n \"properties\": {\n \"type\": {\n \"description\": \"Event type when present. Agent traces mirror trace.jsonl events; workflow traces use execution phase or step records.\",\n \"type\": \"string\"\n },\n \"phase\": {\n \"description\": \"Workflow execution phase, when present.\",\n \"type\": \"string\"\n },\n \"stepName\": {\n \"description\": \"Workflow step name, when present.\",\n \"type\": \"string\"\n },\n \"status\": {\n \"description\": \"Event or execution status, when present.\",\n \"type\": \"string\"\n },\n \"startedAt\": {\n \"description\": \"Event start timestamp.\",\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"completedAt\": {\n \"description\": \"Event completion timestamp.\",\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"message\": {\n \"description\": \"Human-readable event message.\",\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n }\n },\n \"additionalProperties\": {},\n \"description\": \"Trace event emitted by a workflow or agent run. Extra fields depend on the run type and event source.\"\n },\n \"RunUsageResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"usage\": {\n \"anyOf\": [\n {\n \"$ref\": \"#/components/schemas/RunUsage\"\n },\n {\n \"type\": \"null\"\n }\n ]\n }\n },\n \"required\": [\n \"usage\"\n ],\n \"additionalProperties\": false\n },\n \"ListTemplatesResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"items\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/Template\"\n }\n },\n \"total\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 9007199254740991\n }\n },\n \"required\": [\n \"items\",\n \"total\"\n ],\n \"additionalProperties\": false\n },\n \"Template\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\",\n \"pattern\": \"^tmpl_[A-Za-z0-9_-]{21}$\",\n \"description\": \"Stable logical template id (tmpl_…).\"\n },\n \"name\": {\n \"type\": \"string\"\n },\n \"description\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"filename\": {\n \"type\": \"string\"\n },\n \"format\": {\n \"type\": \"string\",\n \"enum\": [\n \"docx\",\n \"xlsx\"\n ]\n },\n \"mimeType\": {\n \"type\": \"string\"\n },\n \"size\": {\n \"anyOf\": [\n {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 9007199254740991\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"sha256\": {\n \"anyOf\": [\n {\n \"type\": \"string\",\n \"minLength\": 64,\n \"maxLength\": 64\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"tokens\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n },\n \"path\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n },\n \"kind\": {\n \"type\": \"string\",\n \"enum\": [\n \"variable\",\n \"loop\"\n ]\n },\n \"type\": {\n \"type\": \"string\",\n \"enum\": [\n \"string\",\n \"number\",\n \"date\",\n \"boolean\",\n \"array\",\n \"object\"\n ]\n },\n \"required\": {\n \"type\": \"boolean\"\n },\n \"description\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"name\"\n ],\n \"additionalProperties\": false\n }\n },\n \"grammar\": {\n \"type\": \"object\",\n \"properties\": {\n \"syntax\": {\n \"type\": \"string\"\n },\n \"tokenDiscovery\": {\n \"type\": \"boolean\"\n },\n \"capabilities\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\n \"syntax\",\n \"tokenDiscovery\",\n \"capabilities\"\n ],\n \"additionalProperties\": false\n },\n \"currentRevision\": {\n \"anyOf\": [\n {\n \"$ref\": \"#/components/schemas/TemplateRevision\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"createdAt\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"string\"\n }\n ]\n },\n \"updatedAt\": {\n \"anyOf\": [\n {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"string\"\n }\n ]\n },\n {\n \"type\": \"null\"\n }\n ]\n }\n },\n \"required\": [\n \"id\",\n \"name\",\n \"filename\",\n \"format\",\n \"mimeType\",\n \"tokens\",\n \"grammar\",\n \"createdAt\"\n ],\n \"additionalProperties\": false\n },\n \"TemplateRevision\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\",\n \"pattern\": \"^tmpr_[A-Za-z0-9_-]{21}$\",\n \"description\": \"Immutable template revision id (tmpr_…).\"\n },\n \"number\": {\n \"type\": \"integer\",\n \"exclusiveMinimum\": 0,\n \"maximum\": 9007199254740991\n },\n \"sha256\": {\n \"type\": \"string\",\n \"minLength\": 64,\n \"maxLength\": 64\n },\n \"createdAt\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"string\"\n }\n ]\n }\n },\n \"required\": [\n \"id\",\n \"number\",\n \"sha256\",\n \"createdAt\"\n ],\n \"additionalProperties\": false\n },\n \"CreatedTemplate\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\",\n \"pattern\": \"^tmpl_[A-Za-z0-9_-]{21}$\",\n \"description\": \"Stable logical template id (tmpl_…).\"\n },\n \"name\": {\n \"type\": \"string\"\n },\n \"description\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"filename\": {\n \"type\": \"string\"\n },\n \"format\": {\n \"type\": \"string\",\n \"enum\": [\n \"docx\",\n \"xlsx\"\n ]\n },\n \"mimeType\": {\n \"type\": \"string\"\n },\n \"size\": {\n \"anyOf\": [\n {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 9007199254740991\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"sha256\": {\n \"anyOf\": [\n {\n \"type\": \"string\",\n \"minLength\": 64,\n \"maxLength\": 64\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"tokens\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n },\n \"path\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n },\n \"kind\": {\n \"type\": \"string\",\n \"enum\": [\n \"variable\",\n \"loop\"\n ]\n },\n \"type\": {\n \"type\": \"string\",\n \"enum\": [\n \"string\",\n \"number\",\n \"date\",\n \"boolean\",\n \"array\",\n \"object\"\n ]\n },\n \"required\": {\n \"type\": \"boolean\"\n },\n \"description\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"name\"\n ],\n \"additionalProperties\": false\n }\n },\n \"grammar\": {\n \"type\": \"object\",\n \"properties\": {\n \"syntax\": {\n \"type\": \"string\"\n },\n \"tokenDiscovery\": {\n \"type\": \"boolean\"\n },\n \"capabilities\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\n \"syntax\",\n \"tokenDiscovery\",\n \"capabilities\"\n ],\n \"additionalProperties\": false\n },\n \"currentRevision\": {\n \"anyOf\": [\n {\n \"$ref\": \"#/components/schemas/TemplateRevision\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"createdAt\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"string\"\n }\n ]\n },\n \"updatedAt\": {\n \"anyOf\": [\n {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"string\"\n }\n ]\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"cleanupProof\": {\n \"description\": \"One-time proof to finalize or hard-clean this unpublished staged template. Returned only on staged create, never on GET or list.\",\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"id\",\n \"name\",\n \"filename\",\n \"format\",\n \"mimeType\",\n \"tokens\",\n \"grammar\",\n \"createdAt\"\n ],\n \"additionalProperties\": false\n },\n \"DeleteTemplateResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"deleted\": {\n \"type\": \"boolean\"\n }\n },\n \"required\": [\n \"deleted\"\n ],\n \"additionalProperties\": false\n },\n \"TemplateStagingResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"cleaned\": {\n \"type\": \"boolean\"\n },\n \"finalized\": {\n \"type\": \"boolean\"\n }\n },\n \"additionalProperties\": false\n },\n \"DatasetReviewFocusFieldOutput\": {\n \"type\": \"object\",\n \"properties\": {\n \"path\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"Dotted expected-output path the reviewer should inspect, e.g. vendor.iban.\"\n },\n \"reason\": {\n \"description\": \"Optional reason this field needs attention.\",\n \"anyOf\": [\n {\n \"type\": \"string\",\n \"minLength\": 1\n },\n {\n \"type\": \"null\"\n }\n ]\n }\n },\n \"required\": [\n \"path\"\n ],\n \"additionalProperties\": false\n }\n },\n \"securitySchemes\": {\n \"bearerAuth\": {\n \"type\": \"http\",\n \"scheme\": \"bearer\",\n \"description\": \"API key issued from Settings → API Keys. Pass as `Authorization: Bearer <key>`.\"\n }\n }\n }\n}\n"
|
|
9
|
+
"content": "{\n \"openapi\": \"3.1.0\",\n \"info\": {\n \"title\": \"Eigenpal API\",\n \"version\": \"1.0.0\",\n \"description\": \"Public REST API for inspecting automations, starting and monitoring runs, managing files, collecting human reviews, and running evaluations.\",\n \"contact\": {\n \"name\": \"Eigenpal\",\n \"url\": \"https://eigenpal.com\"\n },\n \"license\": {\n \"name\": \"Apache-2.0\",\n \"url\": \"https://www.apache.org/licenses/LICENSE-2.0\"\n }\n },\n \"servers\": [\n {\n \"url\": \"https://api.eigenpal.com\",\n \"description\": \"Production (canonical API hostname)\"\n }\n ],\n \"security\": [\n {\n \"bearerAuth\": []\n }\n ],\n \"tags\": [\n {\n \"name\": \"Metadata\",\n \"description\": \"Authenticate and inspect the current API context.\"\n },\n {\n \"name\": \"Models\",\n \"description\": \"List text, vision, and OCR models configured for the current tenant environment. This is a catalog inventory, not a live provider health probe.\"\n },\n {\n \"name\": \"Automations\",\n \"description\": \"Inspect runnable workflow and agent automations, their versions, triggers, and source sync state. Move YAML workflows between folders and delete automations.\"\n },\n {\n \"name\": \"Folders\",\n \"description\": \"Create and organize workflow and template folders. Deleting a folder unfiles contained workflows or templates and does not delete them.\"\n },\n {\n \"name\": \"Runs\",\n \"description\": \"Start, monitor, retry, review, and debug automation runs, including artifacts.\"\n },\n {\n \"name\": \"Reviews\",\n \"description\": \"Record human review verdicts, manage corrected outputs, and monitor review health.\"\n },\n {\n \"name\": \"Files\",\n \"description\": \"Upload reusable files for later run or dataset use.\"\n },\n {\n \"name\": \"Templates\",\n \"description\": \"Upload, inspect, version, download, and delete tenant-scoped DOCX and XLSX templates.\"\n },\n {\n \"name\": \"Email servers\",\n \"description\": \"Create and manage outbound email servers for workflow mail. Secrets are encrypted at rest and never returned.\"\n },\n {\n \"name\": \"Evaluation\",\n \"description\": \"Manage datasets, examples, evaluators, experiment batches, evaluator scores, and run promotion workflows.\"\n }\n ],\n \"paths\": {\n \"/v1/auth/check\": {\n \"get\": {\n \"operationId\": \"auth.check\",\n \"summary\": \"Check API key identity\",\n \"description\": \"Return the tenant, user, API key, and scope represented by the current API key.\",\n \"tags\": [\n \"Metadata\"\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Authenticated identity\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/AuthCheckResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations\": {\n \"get\": {\n \"operationId\": \"automations.list\",\n \"summary\": \"List automations\",\n \"description\": \"Returns workflows and agents through one runnable automation collection. Use `type` to narrow to workflows or agents, `search` to find automations by slug, name, or description, and `folderId` to list YAML workflows in a folder (`null` for root).\",\n \"tags\": [\n \"Automations\"\n ],\n \"parameters\": [\n {\n \"in\": \"query\",\n \"name\": \"search\",\n \"schema\": {\n \"description\": \"Substring match against slug, name, or description\",\n \"type\": \"string\"\n },\n \"description\": \"Substring match against slug, name, or description\"\n },\n {\n \"in\": \"query\",\n \"name\": \"type\",\n \"schema\": {\n \"description\": \"Filter by implementation type\",\n \"type\": \"string\",\n \"enum\": [\n \"workflow\",\n \"agent\"\n ]\n },\n \"description\": \"Filter by implementation type\"\n },\n {\n \"in\": \"query\",\n \"name\": \"folderId\",\n \"schema\": {\n \"description\": \"Filter YAML workflows by folder. A folder id matches that folder; `null` matches unfiled workflows at root. Agent automations have no folders, so this filter excludes them. Cannot be combined with `type=agent`.\",\n \"type\": \"string\"\n },\n \"description\": \"Filter YAML workflows by folder. A folder id matches that folder; `null` matches unfiled workflows at root. Agent automations have no folders, so this filter excludes them. Cannot be combined with `type=agent`.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"limit\",\n \"schema\": {\n \"description\": \"Maximum number of automations to return.\",\n \"type\": \"integer\",\n \"minimum\": 1,\n \"maximum\": 100\n },\n \"description\": \"Maximum number of automations to return.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"offset\",\n \"schema\": {\n \"description\": \"Zero-based offset for paging through automations.\",\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 9007199254740991\n },\n \"description\": \"Zero-based offset for paging through automations.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Page of runnable workflow and agent automations.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ListAutomationsResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}\": {\n \"get\": {\n \"operationId\": \"automations.get\",\n \"summary\": \"Get automation\",\n \"description\": \"Get one runnable workflow or agent automation by id or typed alias.\",\n \"tags\": [\n \"Automations\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Workflow id, agent id, or typed alias like workflows.slug / agents.slug\"\n },\n \"required\": true,\n \"description\": \"Workflow id, agent id, or typed alias like workflows.slug / agents.slug\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Automation\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/AutomationDetail\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"patch\": {\n \"operationId\": \"automations.update\",\n \"summary\": \"Move workflow automation\",\n \"description\": \"Move a YAML workflow between organizing folders. `folderPath` auto-creates missing workflow folders; empty or `/` files the workflow at root. Agent automations have no database folder model and are rejected. Identifiers match GET (workflow id, automation id, or `workflows.<slug>`).\",\n \"tags\": [\n \"Automations\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Workflow id, agent id, or typed alias like workflows.slug / agents.slug\"\n },\n \"required\": true,\n \"description\": \"Workflow id, agent id, or typed alias like workflows.slug / agents.slug\"\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/UpdateAutomationRequest\"\n }\n }\n }\n },\n \"responses\": {\n \"200\": {\n \"description\": \"Updated automation\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/AutomationDetail\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"delete\": {\n \"operationId\": \"automations.delete\",\n \"summary\": \"Delete automation\",\n \"description\": \"Delete a workflow or agent automation using the same cleanup as the dashboard. Workflows archive the automations registry parent and keep execution history. Agents delete the agent row, archive the registry parent, and best-effort-delete agent storage. Identifiers match GET.\",\n \"tags\": [\n \"Automations\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Workflow id, agent id, or typed alias like workflows.slug / agents.slug\"\n },\n \"required\": true,\n \"description\": \"Workflow id, agent id, or typed alias like workflows.slug / agents.slug\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Automation deleted\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DeleteAutomationResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}/dataset-review-requests\": {\n \"get\": {\n \"operationId\": \"automations.datasetReviewRequests.list\",\n \"summary\": \"List dataset review requests\",\n \"description\": \"List dataset review requests for one automation, including per-request progress.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias, such as `workflows.slug` or `agents.slug`.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias, such as `workflows.slug` or `agents.slug`.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"status\",\n \"schema\": {\n \"description\": \"Optional comma-separated review statuses to filter by.\",\n \"type\": \"string\"\n },\n \"description\": \"Optional comma-separated review statuses to filter by.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"limit\",\n \"schema\": {\n \"type\": \"integer\",\n \"minimum\": 1,\n \"maximum\": 100\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"offset\",\n \"schema\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 9007199254740991\n }\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Page of dataset review requests.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DatasetReviewRequestList\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"post\": {\n \"operationId\": \"automations.datasetReviewRequests.create\",\n \"summary\": \"Create dataset review request\",\n \"description\": \"Snapshot selected dataset examples into a review request. Include instructions, focusFields to highlight, and ignoredFields for paths reviewers can skip. Optional itemNotes become commented events on those examples.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias, such as `workflows.slug` or `agents.slug`.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias, such as `workflows.slug` or `agents.slug`.\"\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/CreateDatasetReviewRequest\"\n }\n }\n }\n },\n \"responses\": {\n \"201\": {\n \"description\": \"Created dataset review request.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DatasetReviewDetail\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}/dataset-review-requests/{reviewId}\": {\n \"get\": {\n \"operationId\": \"automations.datasetReviewRequests.get\",\n \"summary\": \"Get dataset review request\",\n \"description\": \"Fetch one dataset review request with snapshotted items, progress, focus fields, ignored fields, and events.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"reviewId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Dataset review request id.\"\n },\n \"required\": true,\n \"description\": \"Dataset review request id.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Dataset review request.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DatasetReviewDetail\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"patch\": {\n \"operationId\": \"automations.datasetReviewRequests.update\",\n \"summary\": \"Update dataset review request\",\n \"description\": \"Update review metadata or lifecycle status while the request is draft, open, or paused. Set status to `closed` when review is finished; dataset reconciliation stays manual.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"reviewId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Dataset review request id.\"\n },\n \"required\": true,\n \"description\": \"Dataset review request id.\"\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/UpdateDatasetReviewRequest\"\n }\n }\n }\n },\n \"responses\": {\n \"200\": {\n \"description\": \"Updated dataset review request.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DatasetReviewDetail\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}/dataset-review-requests/{reviewId}/events\": {\n \"get\": {\n \"operationId\": \"automations.datasetReviewRequests.listEvents\",\n \"summary\": \"List dataset review events\",\n \"description\": \"List audit events for one dataset review request.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"reviewId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Dataset review request id.\"\n },\n \"required\": true,\n \"description\": \"Dataset review request id.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Review events.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DatasetReviewEventList\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}/dataset-review-requests/{reviewId}/items\": {\n \"get\": {\n \"operationId\": \"automations.datasetReviewRequests.listItems\",\n \"summary\": \"List dataset review items\",\n \"description\": \"List items for one dataset review request, optionally filtered by item status.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"reviewId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Dataset review request id.\"\n },\n \"required\": true,\n \"description\": \"Dataset review request id.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"status\",\n \"schema\": {\n \"description\": \"Optional comma-separated item statuses to filter by.\",\n \"type\": \"string\"\n },\n \"description\": \"Optional comma-separated item statuses to filter by.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Review items.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DatasetReviewItemList\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}/dataset-review-requests/{reviewId}/items/{itemId}\": {\n \"patch\": {\n \"operationId\": \"automations.datasetReviewRequests.updateItem\",\n \"summary\": \"Update dataset review item\",\n \"description\": \"Approve, edit, reject, reopen, comment, or record a field-decision on one review item while the parent request is draft, open, or paused. Pass `expectedUpdatedAt` from the item the client last observed. Pass `fieldPath` with `action: comment` or `action: field-decision`.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"reviewId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Dataset review request id.\"\n },\n \"required\": true,\n \"description\": \"Dataset review request id.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"itemId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Dataset review item id.\"\n },\n \"required\": true,\n \"description\": \"Dataset review item id.\"\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/UpdateDatasetReviewItem\"\n }\n }\n }\n },\n \"responses\": {\n \"200\": {\n \"description\": \"Updated review item.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DatasetReviewItemResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}/dataset-review-requests/{reviewId}/items/{itemId}/files/{path}\": {\n \"get\": {\n \"operationId\": \"automations.datasetReviewRequests.itemFile.get\",\n \"summary\": \"Download dataset review item input file\",\n \"description\": \"Download one input file belonging to a review item. Authorized by `dataset_review:read` and scoped to files referenced in the item snapshot, so reviewers without workflow read can still preview documents.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"reviewId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Dataset review request id.\"\n },\n \"required\": true,\n \"description\": \"Dataset review request id.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"itemId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Dataset review item id.\"\n },\n \"required\": true,\n \"description\": \"Dataset review item id.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"path\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Slash-delimited path under the example input folder referenced by the item snapshot.\"\n },\n \"required\": true,\n \"description\": \"Slash-delimited path under the example input folder referenced by the item snapshot.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Input file bytes.\",\n \"content\": {\n \"application/octet-stream\": {\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Input file bytes for a review item.\",\n \"format\": \"binary\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}/dataset/export\": {\n \"get\": {\n \"operationId\": \"automations.dataset.export\",\n \"summary\": \"Export automation dataset\",\n \"description\": \"Download the automation dataset as a ZIP archive. The archive uses the examples/<name>/input and examples/<name>/expected folder convention, so it can be re-imported into another automation or environment. Cloud deployments may redirect large archives to a short-lived storage URL.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"exampleIds\",\n \"schema\": {\n \"description\": \"Optional comma-separated dataset example ids to export. Omit to export the full dataset.\",\n \"type\": \"string\"\n },\n \"description\": \"Optional comma-separated dataset example ids to export. Omit to export the full dataset.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Dataset ZIP archive.\",\n \"content\": {\n \"application/octet-stream\": {\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"ZIP archive\",\n \"format\": \"binary\"\n }\n }\n }\n },\n \"302\": {\n \"description\": \"Redirect to a short-lived signed storage download\"\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}/dataset/import\": {\n \"post\": {\n \"operationId\": \"automations.dataset.import\",\n \"summary\": \"Import automation dataset\",\n \"description\": \"Import a dataset ZIP archive using the examples/<name>/input and examples/<name>/expected folder convention. Use `mode=append` for additive imports or `mode=replace` to replace the dataset.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias.\"\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"multipart/form-data\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/AutomationDatasetImportMultipartRequest\"\n }\n }\n }\n },\n \"responses\": {\n \"200\": {\n \"description\": \"Import result\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DatasetImportResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}/evaluators\": {\n \"get\": {\n \"operationId\": \"automations.evaluators.get\",\n \"summary\": \"Get evaluators\",\n \"description\": \"Fetch the evaluator configuration for an automation. Evaluators produce automated `score` results, which are separate from human review verdicts.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Evaluator YAML and parsed configuration.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/EvaluatorConfigResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"put\": {\n \"operationId\": \"automations.evaluators.update\",\n \"summary\": \"Replace evaluators\",\n \"description\": \"Replace the evaluator YAML for an automation. The submitted YAML is validated before it becomes the source for future experiment scores.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias.\"\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/EvaluatorConfigUpdate\"\n }\n }\n }\n },\n \"responses\": {\n \"200\": {\n \"description\": \"Updated evaluator YAML and parsed configuration.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/EvaluatorConfigResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}/examples\": {\n \"get\": {\n \"operationId\": \"automations.examples.list\",\n \"summary\": \"List dataset examples\",\n \"description\": \"List dataset examples for one automation. Examples contain input, expected output, expected files, metadata, and optional overrides used by evaluation runs. Pass `include=metadata` to return ids, names, metadata, and expected file refs without loading input or expected JSON.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias, such as `workflows.slug` or `agents.slug`.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias, such as `workflows.slug` or `agents.slug`.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"limit\",\n \"schema\": {\n \"description\": \"Maximum number of examples to return.\",\n \"type\": \"integer\",\n \"minimum\": 1,\n \"maximum\": 100\n },\n \"description\": \"Maximum number of examples to return.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"offset\",\n \"schema\": {\n \"description\": \"Zero-based offset for paging through examples.\",\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 9007199254740991\n },\n \"description\": \"Zero-based offset for paging through examples.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"include\",\n \"schema\": {\n \"description\": \"Response payload scope. `metadata` returns ids, names, metadata, and expected file refs without loading input or expected JSON.\",\n \"type\": \"string\",\n \"enum\": [\n \"full\",\n \"metadata\"\n ]\n },\n \"description\": \"Response payload scope. `metadata` returns ids, names, metadata, and expected file refs without loading input or expected JSON.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Page of dataset examples.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DatasetExampleList\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"post\": {\n \"operationId\": \"automations.examples.create\",\n \"summary\": \"Create dataset example\",\n \"description\": \"Create one dataset example from JSON fields. Use dataset import for archive-based uploads and file-bearing examples.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias, such as `workflows.slug` or `agents.slug`.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias, such as `workflows.slug` or `agents.slug`.\"\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DatasetExampleMutation\"\n }\n }\n }\n },\n \"responses\": {\n \"201\": {\n \"description\": \"Created dataset example.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DatasetExample\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}/examples/{exampleId}\": {\n \"get\": {\n \"operationId\": \"automations.examples.get\",\n \"summary\": \"Get dataset example\",\n \"description\": \"Fetch one dataset example, including input, expected output, expected files, metadata, and overrides.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"exampleId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Dataset example id. Agent examples may use deterministic name-derived ids returned by list/create responses.\"\n },\n \"required\": true,\n \"description\": \"Dataset example id. Agent examples may use deterministic name-derived ids returned by list/create responses.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Dataset example.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DatasetExample\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"patch\": {\n \"operationId\": \"automations.examples.update\",\n \"summary\": \"Update dataset example\",\n \"description\": \"Partially update a dataset example. Omitted fields are preserved; pass null for nullable fields to clear them.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"exampleId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Dataset example id. Agent examples may use deterministic name-derived ids returned by list/create responses.\"\n },\n \"required\": true,\n \"description\": \"Dataset example id. Agent examples may use deterministic name-derived ids returned by list/create responses.\"\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DatasetExampleUpdate\"\n }\n }\n }\n },\n \"responses\": {\n \"200\": {\n \"description\": \"Updated dataset example.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DatasetExample\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"delete\": {\n \"operationId\": \"automations.examples.delete\",\n \"summary\": \"Delete dataset example\",\n \"description\": \"Delete one dataset example from the automation dataset. This removes the example from future experiments.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"exampleId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Dataset example id. Agent examples may use deterministic name-derived ids returned by list/create responses.\"\n },\n \"required\": true,\n \"description\": \"Dataset example id. Agent examples may use deterministic name-derived ids returned by list/create responses.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Deleted dataset example.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DatasetExample\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}/examples/{exampleId}/expected\": {\n \"get\": {\n \"operationId\": \"automations.examples.expected.files.list\",\n \"summary\": \"List expected files\",\n \"description\": \"List files stored under the expected folder for one automation dataset example.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"exampleId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Dataset example id.\"\n },\n \"required\": true,\n \"description\": \"Dataset example id.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Expected file paths.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DatasetExampleExpectedFileList\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"post\": {\n \"operationId\": \"automations.examples.expected.files.create\",\n \"summary\": \"Upload expected files\",\n \"description\": \"Upload one or more files into the expected folder for an automation dataset example. Use `$file` references such as `expected/result.pdf` from expected JSON to compare file outputs.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"exampleId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Dataset example id.\"\n },\n \"required\": true,\n \"description\": \"Dataset example id.\"\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"multipart/form-data\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DatasetExampleExpectedFileUploadRequest\"\n }\n }\n }\n },\n \"responses\": {\n \"201\": {\n \"description\": \"Uploaded expected files.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DatasetExampleExpectedFileUploadResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}/examples/{exampleId}/expected/{path}\": {\n \"get\": {\n \"operationId\": \"automations.examples.expected.file.get\",\n \"summary\": \"Download expected dataset file\",\n \"description\": \"Download one expected file attached to an automation dataset example.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"exampleId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Dataset example id.\"\n },\n \"required\": true,\n \"description\": \"Dataset example id.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"path\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Path under the example expected folder.\"\n },\n \"required\": true,\n \"description\": \"Path under the example expected folder.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Expected dataset file.\",\n \"content\": {\n \"application/octet-stream\": {\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Expected file bytes.\",\n \"format\": \"binary\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"patch\": {\n \"operationId\": \"automations.examples.expected.file.update\",\n \"summary\": \"Rename expected file\",\n \"description\": \"Rename one expected file attached to an automation dataset example. The parent folder is preserved.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"exampleId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Dataset example id.\"\n },\n \"required\": true,\n \"description\": \"Dataset example id.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"path\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Path under the example expected folder.\"\n },\n \"required\": true,\n \"description\": \"Path under the example expected folder.\"\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DatasetExampleExpectedFileRenameRequest\"\n }\n }\n }\n },\n \"responses\": {\n \"200\": {\n \"description\": \"Renamed expected file.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DatasetExampleExpectedFileRenameResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"delete\": {\n \"operationId\": \"automations.examples.expected.file.delete\",\n \"summary\": \"Delete expected file\",\n \"description\": \"Delete one file from an automation dataset example expected folder.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"exampleId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Dataset example id.\"\n },\n \"required\": true,\n \"description\": \"Dataset example id.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"path\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Path under the example expected folder.\"\n },\n \"required\": true,\n \"description\": \"Path under the example expected folder.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Expected file deleted.\"\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}/examples/{exampleId}/input\": {\n \"get\": {\n \"operationId\": \"automations.examples.input.files.list\",\n \"summary\": \"List input files\",\n \"description\": \"List files stored under the input folder for one automation dataset example.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"exampleId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Dataset example id.\"\n },\n \"required\": true,\n \"description\": \"Dataset example id.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Input file paths.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DatasetExampleInputFileList\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"post\": {\n \"operationId\": \"automations.examples.input.files.create\",\n \"summary\": \"Upload input files\",\n \"description\": \"Upload one or more files into the input folder for an automation dataset example. Use `$file` references such as `input/invoice.pdf` from the example input JSON to consume them.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"exampleId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Dataset example id.\"\n },\n \"required\": true,\n \"description\": \"Dataset example id.\"\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"multipart/form-data\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DatasetExampleInputFileUploadRequest\"\n }\n }\n }\n },\n \"responses\": {\n \"201\": {\n \"description\": \"Uploaded input files.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DatasetExampleInputFileUploadResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}/examples/{exampleId}/input/{path}\": {\n \"get\": {\n \"operationId\": \"automations.examples.input.file.get\",\n \"summary\": \"Download input file\",\n \"description\": \"Download one file from an automation dataset example input folder.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"exampleId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Dataset example id.\"\n },\n \"required\": true,\n \"description\": \"Dataset example id.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"path\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Slash-delimited path under the example input folder.\"\n },\n \"required\": true,\n \"description\": \"Slash-delimited path under the example input folder.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Input file bytes.\",\n \"content\": {\n \"application/octet-stream\": {\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Input file bytes.\",\n \"format\": \"binary\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"patch\": {\n \"operationId\": \"automations.examples.input.file.update\",\n \"summary\": \"Rename input file\",\n \"description\": \"Rename one input file attached to an automation dataset example. The parent folder is preserved.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"exampleId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Dataset example id.\"\n },\n \"required\": true,\n \"description\": \"Dataset example id.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"path\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Slash-delimited path under the example input folder.\"\n },\n \"required\": true,\n \"description\": \"Slash-delimited path under the example input folder.\"\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DatasetExampleInputFileRenameRequest\"\n }\n }\n }\n },\n \"responses\": {\n \"200\": {\n \"description\": \"Renamed input file.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DatasetExampleInputFileRenameResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"delete\": {\n \"operationId\": \"automations.examples.input.file.delete\",\n \"summary\": \"Delete input file\",\n \"description\": \"Delete one file from an automation dataset example input folder.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"exampleId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Dataset example id.\"\n },\n \"required\": true,\n \"description\": \"Dataset example id.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"path\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Slash-delimited path under the example input folder.\"\n },\n \"required\": true,\n \"description\": \"Slash-delimited path under the example input folder.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Input file deleted.\"\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}/examples/{exampleId}/run\": {\n \"post\": {\n \"operationId\": \"automations.examples.run\",\n \"summary\": \"Run dataset example\",\n \"description\": \"Start an asynchronous run using the input from one dataset example. Poll `GET /api/v1/runs/{id}` for completion and use run scores or review endpoints to review the result.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"exampleId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Dataset example id to run.\"\n },\n \"required\": true,\n \"description\": \"Dataset example id to run.\"\n }\n ],\n \"responses\": {\n \"201\": {\n \"description\": \"Example run accepted\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ExampleRunResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}/experiments\": {\n \"get\": {\n \"operationId\": \"automations.experiments.list\",\n \"summary\": \"List experiments\",\n \"description\": \"List experiment batches for one automation. Each experiment runs selected dataset examples and records automated evaluator scores.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"limit\",\n \"schema\": {\n \"description\": \"Maximum number of experiment batches to return.\",\n \"type\": \"integer\",\n \"minimum\": 1,\n \"maximum\": 500\n },\n \"description\": \"Maximum number of experiment batches to return.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"offset\",\n \"schema\": {\n \"description\": \"Zero-based offset for paging through experiment batches.\",\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 9007199254740991\n },\n \"description\": \"Zero-based offset for paging through experiment batches.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"fromDate\",\n \"schema\": {\n \"description\": \"Filter to experiment batches created at or after this date or relative date.\",\n \"type\": \"string\"\n },\n \"description\": \"Filter to experiment batches created at or after this date or relative date.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"toDate\",\n \"schema\": {\n \"description\": \"Filter to experiment batches created at or before this date or relative date.\",\n \"type\": \"string\"\n },\n \"description\": \"Filter to experiment batches created at or before this date or relative date.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Page of experiment batches.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"type\": \"object\",\n \"properties\": {\n \"data\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/Experiment\"\n }\n },\n \"total\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"limit\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"offset\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n }\n },\n \"required\": [\n \"data\",\n \"total\",\n \"limit\",\n \"offset\"\n ],\n \"additionalProperties\": false\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"post\": {\n \"operationId\": \"automations.experiments.create\",\n \"summary\": \"Create experiment\",\n \"description\": \"Start an asynchronous experiment batch for one automation. Omit `examples` to run the full dataset, or pass specific example ids to run a subset.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias.\"\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ExperimentCreate\"\n }\n }\n }\n },\n \"responses\": {\n \"202\": {\n \"description\": \"Experiment accepted and runs enqueued.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ExperimentCreateResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}/experiments/{experimentId}\": {\n \"get\": {\n \"operationId\": \"automations.experiments.get\",\n \"summary\": \"Get experiment\",\n \"description\": \"Fetch one experiment batch with its run summaries and evaluator results grouped by run id.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"experimentId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Experiment batch id.\"\n },\n \"required\": true,\n \"description\": \"Experiment batch id.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Experiment detail with runs and results.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ExperimentDetail\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}/experiments/{experimentId}/cancel\": {\n \"post\": {\n \"operationId\": \"automations.experiments.cancel\",\n \"summary\": \"Cancel experiment\",\n \"description\": \"Request cancellation for an experiment batch. Already-completed runs remain recorded; queued or running work is cancelled when possible.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation id or typed alias.\"\n },\n \"required\": true,\n \"description\": \"Automation id or typed alias.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"experimentId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Experiment batch id.\"\n },\n \"required\": true,\n \"description\": \"Experiment batch id.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Experiment detail after the cancellation request.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ExperimentDetail\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}/experiments/{experimentId}/export\": {\n \"get\": {\n \"operationId\": \"automations.experiments.export\",\n \"summary\": \"Export experiment eval results\",\n \"description\": \"Download eval result rows for a single experiment batch as CSV or JSON.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\"\n },\n \"required\": true\n },\n {\n \"in\": \"path\",\n \"name\": \"experimentId\",\n \"schema\": {\n \"type\": \"string\"\n },\n \"required\": true\n },\n {\n \"in\": \"query\",\n \"name\": \"format\",\n \"schema\": {\n \"type\": \"string\",\n \"enum\": [\n \"csv\",\n \"json\"\n ]\n },\n \"required\": true\n },\n {\n \"in\": \"query\",\n \"name\": \"includeTrace\",\n \"schema\": {\n \"type\": \"string\",\n \"enum\": [\n \"0\",\n \"1\",\n \"true\",\n \"false\"\n ]\n }\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Eval results export\",\n \"content\": {\n \"text/csv\": {\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"CSV or JSON document\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}/experiments/export\": {\n \"get\": {\n \"operationId\": \"automations.experiments.exportAll\",\n \"summary\": \"Export all experiment eval results\",\n \"description\": \"Download every eval result row for an automation as CSV or JSON.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\"\n },\n \"required\": true\n },\n {\n \"in\": \"query\",\n \"name\": \"format\",\n \"schema\": {\n \"type\": \"string\",\n \"enum\": [\n \"csv\",\n \"json\"\n ]\n },\n \"required\": true\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Eval results export\",\n \"content\": {\n \"text/csv\": {\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"CSV or JSON document\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}/experiments/stream\": {\n \"post\": {\n \"operationId\": \"automations.experiments.createStream\",\n \"summary\": \"Create automation experiment with NDJSON progress\",\n \"description\": \"Starts a batch eval experiment for workflow or agent automations and streams per-run completion events as NDJSON.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\"\n },\n \"required\": true\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ExperimentCreate\"\n }\n }\n }\n },\n \"responses\": {\n \"200\": {\n \"description\": \"NDJSON experiment progress stream\",\n \"content\": {\n \"text/plain\": {\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"application/x-ndjson event stream\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}/reviews/health\": {\n \"get\": {\n \"operationId\": \"automations.reviews.health\",\n \"summary\": \"Get automation review health\",\n \"description\": \"Aggregates reviewed correctness, review coverage, bucketed counts, and rolling-window confidence for one automation. Prefer this endpoint for single-automation monitoring dashboards.\",\n \"tags\": [\n \"Reviews\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Workflow id, agent id, or typed alias like workflows.slug / agents.slug.\"\n },\n \"required\": true,\n \"description\": \"Workflow id, agent id, or typed alias like workflows.slug / agents.slug.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"type\",\n \"schema\": {\n \"description\": \"Comma-separated: workflow,agent.\",\n \"type\": \"string\"\n },\n \"description\": \"Comma-separated: workflow,agent.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"status\",\n \"schema\": {\n \"description\": \"Comma-separated execution statuses.\",\n \"type\": \"string\"\n },\n \"description\": \"Comma-separated execution statuses.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"trigger\",\n \"schema\": {\n \"description\": \"Comma-separated trigger types.\",\n \"type\": \"string\"\n },\n \"description\": \"Comma-separated trigger types.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"triggeredBy\",\n \"schema\": {\n \"description\": \"Comma-separated user ids, or __system__ for system-triggered runs.\",\n \"type\": \"string\"\n },\n \"description\": \"Comma-separated user ids, or __system__ for system-triggered runs.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"sourceRef\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"batchId\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"exampleId\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"exampleIdContains\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"from\",\n \"schema\": {\n \"description\": \"Start of the run-created time range. Defaults to now-30d.\",\n \"type\": \"string\"\n },\n \"description\": \"Start of the run-created time range. Defaults to now-30d.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"to\",\n \"schema\": {\n \"description\": \"End of the run-created time range.\",\n \"type\": \"string\"\n },\n \"description\": \"End of the run-created time range.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"completedAfter\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"completedBefore\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"experiments\",\n \"schema\": {\n \"description\": \"Set to false to exclude experiment batch runs.\",\n \"type\": \"string\"\n },\n \"description\": \"Set to false to exclude experiment batch runs.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"bucket\",\n \"schema\": {\n \"description\": \"Calendar bucket size for the bar chart series. Defaults to day.\",\n \"type\": \"string\",\n \"enum\": [\n \"day\",\n \"week\",\n \"month\"\n ]\n },\n \"description\": \"Calendar bucket size for the bar chart series. Defaults to day.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"rollingWindow\",\n \"schema\": {\n \"description\": \"Number of reviewed runs per rolling correctness point. Defaults to 100.\",\n \"type\": \"integer\",\n \"minimum\": 1,\n \"maximum\": 1000\n },\n \"description\": \"Number of reviewed runs per rolling correctness point. Defaults to 100.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"minRollingReviews\",\n \"schema\": {\n \"description\": \"Minimum reviewed runs required before emitting rolling points. Defaults to 1.\",\n \"type\": \"integer\",\n \"minimum\": 1,\n \"maximum\": 1000\n },\n \"description\": \"Minimum reviewed runs required before emitting rolling points. Defaults to 1.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Automation review health metrics.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/RunReviewHealthResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}/sync\": {\n \"post\": {\n \"operationId\": \"automations.sync\",\n \"summary\": \"Sync automation from latest Git release\",\n \"description\": \"Reconciles automation registry metadata and trigger projections from the latest Git source release. This operation is idempotent for unchanged source state: repeated calls against the same latest release leave the same automation registry state and may repeat the same warnings. Requires a Bearer API token for the organization and a user-backed API key. It does not publish source; it reads the already-published latest release manifest. Versioned targets are rejected with 400, missing organization/source/release/manifest state returns 404, invalid manifests return 400, and provider or persistence failures return 5xx.\",\n \"tags\": [\n \"Automations\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Automation target to sync, such as agents.invoice-agent or workflows.extract. Do not include a version; sync always uses the latest Git release.\"\n },\n \"required\": true,\n \"description\": \"Automation target to sync, such as agents.invoice-agent or workflows.extract. Do not include a version; sync always uses the latest Git release.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Automation metadata, latest release information, and non-fatal sync warnings.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"type\": \"object\",\n \"properties\": {\n \"automation\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\",\n \"description\": \"Automation id after reconciliation.\"\n },\n \"type\": {\n \"type\": \"string\",\n \"enum\": [\n \"agent\",\n \"workflow\"\n ],\n \"description\": \"Automation kind inferred from the source package path.\"\n },\n \"slug\": {\n \"type\": \"string\",\n \"description\": \"Source package slug within agents/ or workflows/.\"\n },\n \"status\": {\n \"type\": \"string\",\n \"enum\": [\n \"active\",\n \"archived\"\n ],\n \"description\": \"Current automation registry status.\"\n },\n \"updatedAt\": {\n \"type\": \"string\",\n \"description\": \"ISO timestamp for the reconciled automation row.\"\n }\n },\n \"required\": [\n \"id\",\n \"type\",\n \"slug\",\n \"status\",\n \"updatedAt\"\n ],\n \"additionalProperties\": false\n },\n \"release\": {\n \"type\": \"object\",\n \"properties\": {\n \"version\": {\n \"type\": \"string\",\n \"description\": \"Latest released source package version that was synced.\"\n },\n \"tag\": {\n \"type\": \"string\",\n \"description\": \"Git release tag read during sync.\"\n },\n \"commit\": {\n \"type\": \"string\",\n \"description\": \"Git commit for the release tag.\"\n }\n },\n \"required\": [\n \"version\",\n \"tag\",\n \"commit\"\n ],\n \"additionalProperties\": false\n },\n \"warnings\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n },\n \"description\": \"Non-fatal source-state warnings, such as unsupported email alias domains.\"\n }\n },\n \"required\": [\n \"automation\",\n \"release\",\n \"warnings\"\n ],\n \"additionalProperties\": false\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}/triggers\": {\n \"get\": {\n \"operationId\": \"automations.triggers.get\",\n \"summary\": \"Get automation triggers\",\n \"description\": \"Read trigger state for a workflow or agent automation. Trigger mutation is not public v1.\",\n \"tags\": [\n \"Automations\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Workflow id, agent id, or typed alias like workflows.slug / agents.slug\"\n },\n \"required\": true,\n \"description\": \"Workflow id, agent id, or typed alias like workflows.slug / agents.slug\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Automation trigger state\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/AutomationTriggersResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}/versions\": {\n \"get\": {\n \"operationId\": \"automations.versions.list\",\n \"summary\": \"List automation versions\",\n \"description\": \"List versions for a workflow or agent automation. YAML workflow lists include tagged releases plus the current untagged snapshot when HEAD is untagged (for example after restore), so the current version is always present. Agent lists remain Git release tags.\",\n \"tags\": [\n \"Automations\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Workflow id, agent id, or typed alias like workflows.slug / agents.slug\"\n },\n \"required\": true,\n \"description\": \"Workflow id, agent id, or typed alias like workflows.slug / agents.slug\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Automation versions\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ListAutomationVersionsResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"post\": {\n \"operationId\": \"automations.versions.create\",\n \"summary\": \"Create a workflow version\",\n \"description\": \"Create a tagged YAML workflow candidate from validated YAML or by copying an existing snapshot (`historyId`). Provide exactly one of `yaml` or `historyId`. Copy creates a new tagged row and leaves the source tag unchanged; it does not retag the original. Defaults to making the new version current. Set `activate: false` to keep it off live traffic until promote — that path requires an existing current workflow version and returns 400 if HEAD is empty. Agent automations are Git-backed and return 400. Requires a Bearer API key or a dashboard session.\",\n \"tags\": [\n \"Automations\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Workflow id, agent id, or typed alias like workflows.slug / agents.slug\"\n },\n \"required\": true,\n \"description\": \"Workflow id, agent id, or typed alias like workflows.slug / agents.slug\"\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/CreateAutomationVersionRequest\"\n }\n }\n }\n },\n \"responses\": {\n \"201\": {\n \"description\": \"Created workflow version.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/AutomationVersion\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"409\": {\n \"description\": \"Conflict. The resource is in a state that forbids the request.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}/versions/{versionId}/promote\": {\n \"post\": {\n \"operationId\": \"automations.versions.promote\",\n \"summary\": \"Promote a workflow version\",\n \"description\": \"Make an existing tagged YAML workflow candidate current without creating another history row. Only tagged version rows can be promoted; untagged snapshots (including restore HEAD) and missing ids return 404. Agent automations return 400. Requires a Bearer API key or a dashboard session.\",\n \"tags\": [\n \"Automations\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Workflow id, agent id, or typed alias like workflows.slug / agents.slug\"\n },\n \"required\": true,\n \"description\": \"Workflow id, agent id, or typed alias like workflows.slug / agents.slug\"\n },\n {\n \"in\": \"path\",\n \"name\": \"versionId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Tagged version id from GET /automations/{id}/versions. Untagged snapshots (for example after restore) and unknown ids return 404.\"\n },\n \"required\": true,\n \"description\": \"Tagged version id from GET /automations/{id}/versions. Untagged snapshots (for example after restore) and unknown ids return 404.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Existing tagged workflow version promoted.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/AutomationVersion\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"409\": {\n \"description\": \"Conflict. The resource is in a state that forbids the request.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/automations/{id}/versions/{versionId}/restore\": {\n \"post\": {\n \"operationId\": \"automations.versions.restore\",\n \"summary\": \"Restore a workflow version\",\n \"description\": \"Restore a YAML workflow automation by copying a previous snapshot into a new untagged current version. The source tag is left unchanged; the new HEAD appears in subsequent version lists as the untagged current row and cannot be promoted until you create a tagged copy. The JSON body may be `{}`; `message` is optional and defaults to a timestamped restore note. Agent automations return 400. Requires a Bearer API key or a dashboard session.\",\n \"tags\": [\n \"Automations\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Workflow id, agent id, or typed alias like workflows.slug / agents.slug\"\n },\n \"required\": true,\n \"description\": \"Workflow id, agent id, or typed alias like workflows.slug / agents.slug\"\n },\n {\n \"in\": \"path\",\n \"name\": \"versionId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Version id from GET /automations/{id}/versions (a workflow history id).\"\n },\n \"required\": true,\n \"description\": \"Version id from GET /automations/{id}/versions (a workflow history id).\"\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/RestoreAutomationVersionRequest\"\n }\n }\n }\n },\n \"responses\": {\n \"201\": {\n \"description\": \"New current version created from the restored snapshot.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/AutomationVersion\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"409\": {\n \"description\": \"Conflict. The resource is in a state that forbids the request.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/email-servers\": {\n \"get\": {\n \"operationId\": \"emailServers.list\",\n \"summary\": \"List email servers\",\n \"description\": \"List outbound email servers for the current workspace. Secrets are never returned; each server includes configuration flags instead of credentials.\",\n \"tags\": [\n \"Email servers\"\n ],\n \"parameters\": [\n {\n \"in\": \"query\",\n \"name\": \"limit\",\n \"schema\": {\n \"description\": \"Maximum number of email servers to return (1–100).\",\n \"type\": \"integer\",\n \"minimum\": 1,\n \"maximum\": 100\n },\n \"description\": \"Maximum number of email servers to return (1–100).\"\n },\n {\n \"in\": \"query\",\n \"name\": \"offset\",\n \"schema\": {\n \"description\": \"Zero-based offset for paging through email servers.\",\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 9007199254740991\n },\n \"description\": \"Zero-based offset for paging through email servers.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Page of email servers\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ListEmailServersResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"post\": {\n \"operationId\": \"emailServers.create\",\n \"summary\": \"Create email server\",\n \"description\": \"Create an outbound email server. Secrets are encrypted at rest and never returned. Names must be unique among live servers in the workspace.\",\n \"tags\": [\n \"Email servers\"\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/CreateEmailServerRequest\"\n }\n }\n }\n },\n \"responses\": {\n \"201\": {\n \"description\": \"Created email server\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/EmailServer\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"409\": {\n \"description\": \"Conflict. The resource is in a state that forbids the request.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/email-servers/{id}\": {\n \"get\": {\n \"operationId\": \"emailServers.get\",\n \"summary\": \"Get email server\",\n \"description\": \"Inspect a stored outbound email server. Cross-tenant and deleted ids are indistinguishable from missing. Secrets are never returned.\",\n \"tags\": [\n \"Email servers\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"maxLength\": 128,\n \"pattern\": \"^ems_[A-Za-z0-9_-]+$\",\n \"description\": \"Email server id (`ems_…`).\"\n },\n \"required\": true,\n \"description\": \"Email server id (`ems_…`).\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Email server\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/EmailServer\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"patch\": {\n \"operationId\": \"emailServers.update\",\n \"summary\": \"Update email server\",\n \"description\": \"Rename, enable/disable, or replace transport configuration. Omitted secrets are retained only when the existing transport is compatible and, for SMTP, the host and username are unchanged. Changing transport or SMTP destination requires a complete valid target; a new password or explicit auth clearing is required when host or username changes.\",\n \"tags\": [\n \"Email servers\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"maxLength\": 128,\n \"pattern\": \"^ems_[A-Za-z0-9_-]+$\",\n \"description\": \"Email server id (`ems_…`).\"\n },\n \"required\": true,\n \"description\": \"Email server id (`ems_…`).\"\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/UpdateEmailServerRequest\"\n }\n }\n }\n },\n \"responses\": {\n \"200\": {\n \"description\": \"Updated email server\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/EmailServer\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"409\": {\n \"description\": \"Conflict. The resource is in a state that forbids the request.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"delete\": {\n \"operationId\": \"emailServers.delete\",\n \"summary\": \"Delete email server\",\n \"description\": \"Soft-delete an outbound email server. Deleted ids are indistinguishable from missing.\",\n \"tags\": [\n \"Email servers\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"maxLength\": 128,\n \"pattern\": \"^ems_[A-Za-z0-9_-]+$\",\n \"description\": \"Email server id (`ems_…`).\"\n },\n \"required\": true,\n \"description\": \"Email server id (`ems_…`).\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Email server deleted\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DeleteEmailServerResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/email-servers/{id}/test\": {\n \"post\": {\n \"operationId\": \"emailServers.test\",\n \"summary\": \"Test email server\",\n \"description\": \"Send a concise connectivity email through the selected stored server. Disabled servers conflict. Provider failures are returned as a generic outcome and never include credentials or the test recipient.\",\n \"tags\": [\n \"Email servers\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"maxLength\": 128,\n \"pattern\": \"^ems_[A-Za-z0-9_-]+$\",\n \"description\": \"Email server id (`ems_…`).\"\n },\n \"required\": true,\n \"description\": \"Email server id (`ems_…`).\"\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/TestEmailServerRequest\"\n }\n }\n }\n },\n \"responses\": {\n \"200\": {\n \"description\": \"Test send result\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/TestEmailServerResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"409\": {\n \"description\": \"Conflict. The resource is in a state that forbids the request.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/experiments/{experimentId}\": {\n \"get\": {\n \"operationId\": \"experiments.resolve\",\n \"summary\": \"Resolve experiment by id\",\n \"description\": \"Returns the owning automation for an experiment batch id. Used when callers only know the experiment id.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"experimentId\",\n \"schema\": {\n \"type\": \"string\"\n },\n \"required\": true\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Experiment reference\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ExperimentRef\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/files\": {\n \"post\": {\n \"operationId\": \"files.create\",\n \"summary\": \"Upload file\",\n \"description\": \"Upload a reusable file that can later be referenced by run inputs or dataset examples.\",\n \"tags\": [\n \"Files\"\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"multipart/form-data\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/CreateFileMultipartRequest\"\n }\n }\n }\n },\n \"responses\": {\n \"200\": {\n \"description\": \"Uploaded file\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/File\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"402\": {\n \"description\": \"Credit quota exceeded. The organization has spent its allowance; nothing was processed.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"409\": {\n \"description\": \"The organization is being deleted. Its stored files are being removed, so new work that would write to its storage is refused.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/files/{id}\": {\n \"get\": {\n \"operationId\": \"files.get\",\n \"summary\": \"Get file metadata\",\n \"description\": \"Get metadata for a reusable uploaded file.\",\n \"tags\": [\n \"Files\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"File id\"\n },\n \"required\": true,\n \"description\": \"File id\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"File metadata\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/File\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"delete\": {\n \"operationId\": \"files.delete\",\n \"summary\": \"Delete file\",\n \"description\": \"Delete a reusable uploaded file. Past runs that referenced it stay readable until those runs are deleted.\",\n \"tags\": [\n \"Files\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"File id\"\n },\n \"required\": true,\n \"description\": \"File id\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"File deleted\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DeleteFileResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/files/{id}/content\": {\n \"get\": {\n \"operationId\": \"files.content.get\",\n \"summary\": \"Download file content\",\n \"description\": \"Download bytes for a reusable uploaded file. Direct-enabled deployments redirect responses above their configured body limit to a short-lived signed storage URL; multipart-only/on-prem deployments stream through the API.\",\n \"tags\": [\n \"Files\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"File id\"\n },\n \"required\": true,\n \"description\": \"File id\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"File content\"\n },\n \"302\": {\n \"description\": \"Redirect to a short-lived signed storage download\"\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/files/uploads\": {\n \"post\": {\n \"operationId\": \"files.uploads.create\",\n \"summary\": \"Prepare file upload\",\n \"description\": \"Negotiate HTTP multipart for small bodies, a short-lived signed PUT under the single-object ceiling, or storage-direct multipart (presigned-multipart) for larger files when storage supports MPU. The response transport is authoritative; clients must not guess from file size alone.\",\n \"tags\": [\n \"Files\"\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/CreateFileUploadSessionRequest\"\n }\n }\n }\n },\n \"responses\": {\n \"200\": {\n \"description\": \"Negotiated upload transport\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"anyOf\": [\n {\n \"$ref\": \"#/components/schemas/PresignedFileUploadSession\"\n },\n {\n \"$ref\": \"#/components/schemas/PresignedMultipartFileUploadSession\"\n },\n {\n \"$ref\": \"#/components/schemas/MultipartFileUploadFallback\"\n }\n ]\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"402\": {\n \"description\": \"Credit quota exceeded. The organization has spent its allowance; nothing was processed.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"409\": {\n \"description\": \"The organization is being deleted. Its stored files are being removed, so new work that would write to its storage is refused.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/files/uploads/{uploadId}\": {\n \"get\": {\n \"operationId\": \"files.uploads.get\",\n \"summary\": \"Get file upload session\",\n \"description\": \"Return session status for resume. Multipart sessions include authoritative uploaded parts from storage, not client-reported ETags.\",\n \"tags\": [\n \"Files\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"uploadId\",\n \"schema\": {\n \"type\": \"string\"\n },\n \"required\": true\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Upload session\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/FileUploadSession\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"delete\": {\n \"operationId\": \"files.uploads.abort\",\n \"summary\": \"Abort file upload\",\n \"description\": \"Abort a pending storage-direct upload. Multipart sessions call AbortMultipartUpload; pending PUT objects are deleted. Completed canonical files are never deleted.\",\n \"tags\": [\n \"Files\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"uploadId\",\n \"schema\": {\n \"type\": \"string\"\n },\n \"required\": true\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Upload aborted\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/AbortFileUploadResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/files/uploads/{uploadId}/complete\": {\n \"post\": {\n \"operationId\": \"files.uploads.complete\",\n \"summary\": \"Complete file upload\",\n \"description\": \"Verify a storage-direct pending object and promote it into a reusable file. Safe to retry.\",\n \"tags\": [\n \"Files\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"uploadId\",\n \"schema\": {\n \"type\": \"string\"\n },\n \"required\": true\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Completed reusable file\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/File\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"409\": {\n \"description\": \"The organization is being deleted. Its stored files are being removed, so new work that would write to its storage is refused.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/files/uploads/{uploadId}/parts\": {\n \"get\": {\n \"operationId\": \"files.uploads.parts.list\",\n \"summary\": \"List uploaded multipart parts\",\n \"description\": \"List authoritative uploaded parts from storage for resume. Do not trust client-only ETags.\",\n \"tags\": [\n \"Files\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"uploadId\",\n \"schema\": {\n \"type\": \"string\"\n },\n \"required\": true\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Uploaded parts\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ListFileUploadPartsResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"post\": {\n \"operationId\": \"files.uploads.parts.presign\",\n \"summary\": \"Presign one multipart upload part\",\n \"description\": \"Mint a short-lived signed UploadPart URL for one validated part. Part URLs are not issued at session create.\",\n \"tags\": [\n \"Files\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"uploadId\",\n \"schema\": {\n \"type\": \"string\"\n },\n \"required\": true\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/PresignFileUploadPartRequest\"\n }\n }\n }\n },\n \"responses\": {\n \"200\": {\n \"description\": \"Signed part upload\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/PresignFileUploadPartResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"409\": {\n \"description\": \"The organization is being deleted. Its stored files are being removed, so new work that would write to its storage is refused.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/folders\": {\n \"get\": {\n \"operationId\": \"folders.list\",\n \"summary\": \"List folders\",\n \"description\": \"List folders in one tree. `type` is required (`workflow` or `template`). Pass `tree=true` for the full nested tree with counts; otherwise list direct children of `parentId` (`null` for root). Deleting a folder later unfiles contained workflows or templates and does not delete them.\",\n \"tags\": [\n \"Folders\"\n ],\n \"parameters\": [\n {\n \"in\": \"query\",\n \"name\": \"type\",\n \"schema\": {\n \"description\": \"Folder tree to list. Required; there is no default.\",\n \"$ref\": \"#/components/schemas/FolderType\"\n },\n \"required\": true,\n \"description\": \"Folder tree to list. Required; there is no default.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"parentId\",\n \"schema\": {\n \"description\": \"Limit to direct children of this folder. Pass `null` for root folders only. Ignored when `tree=true`.\",\n \"type\": \"string\"\n },\n \"description\": \"Limit to direct children of this folder. Pass `null` for root folders only. Ignored when `tree=true`.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"tree\",\n \"schema\": {\n \"description\": \"When `true`, return the full tree for `type` with child counts (and workflow previews for workflow trees).\",\n \"type\": \"string\"\n },\n \"description\": \"When `true`, return the full tree for `type` with child counts (and workflow previews for workflow trees).\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Folders in the requested tree\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ListFoldersResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"post\": {\n \"operationId\": \"folders.create\",\n \"summary\": \"Create folder\",\n \"description\": \"Create a folder in the workflow or template tree. `type` is required. Missing parents 404; a same-named sibling at that location returns 409. Nested agent directories in Git are source organization only and are not folders.\",\n \"tags\": [\n \"Folders\"\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/CreateFolderRequest\"\n }\n }\n }\n },\n \"responses\": {\n \"201\": {\n \"description\": \"Created folder\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/Folder\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"409\": {\n \"description\": \"Conflict. The resource is in a state that forbids the request.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/folders/{id}\": {\n \"get\": {\n \"operationId\": \"folders.get\",\n \"summary\": \"Get folder\",\n \"description\": \"Get one workflow or template folder by id.\",\n \"tags\": [\n \"Folders\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Folder id (`fldr_…`).\"\n },\n \"required\": true,\n \"description\": \"Folder id (`fldr_…`).\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Folder\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/Folder\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"patch\": {\n \"operationId\": \"folders.update\",\n \"summary\": \"Update folder\",\n \"description\": \"Rename or reparent a folder. Moving a folder onto itself, into a descendant, or into the other tree is rejected. A same-named sibling at the destination returns 409.\",\n \"tags\": [\n \"Folders\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Folder id (`fldr_…`).\"\n },\n \"required\": true,\n \"description\": \"Folder id (`fldr_…`).\"\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/UpdateFolderRequest\"\n }\n }\n }\n },\n \"responses\": {\n \"200\": {\n \"description\": \"Updated folder\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/Folder\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"409\": {\n \"description\": \"Conflict. The resource is in a state that forbids the request.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"delete\": {\n \"operationId\": \"folders.delete\",\n \"summary\": \"Delete folder\",\n \"description\": \"Delete a folder and cascade-delete child folders. Workflows and templates in the tree are unfiled, not deleted.\",\n \"tags\": [\n \"Folders\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Folder id (`fldr_…`).\"\n },\n \"required\": true,\n \"description\": \"Folder id (`fldr_…`).\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Folder deleted\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DeleteFolderResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/human-reviews\": {\n \"get\": {\n \"operationId\": \"humanReviews.list\",\n \"summary\": \"List pending human review tasks\",\n \"description\": \"Cursor-paginated queue of pending human-review tasks for the tenant, oldest first.\",\n \"tags\": [\n \"Human reviews\"\n ],\n \"parameters\": [\n {\n \"in\": \"query\",\n \"name\": \"automationId\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"waitingBefore\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"cursor\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"limit\",\n \"schema\": {\n \"type\": \"integer\",\n \"minimum\": 1,\n \"maximum\": 100\n }\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Pending review tasks\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/HumanReviewListResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/human-reviews/{taskId}\": {\n \"get\": {\n \"operationId\": \"humanReviews.get\",\n \"summary\": \"Get human review task\",\n \"description\": \"Fetch one authorized human-review task with draft data, derived non-file input, files, and decisions.\",\n \"tags\": [\n \"Human reviews\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"taskId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Human review task id\"\n },\n \"required\": true,\n \"description\": \"Human review task id\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Human review task detail\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/HumanReviewTaskResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/human-reviews/{taskId}/approve\": {\n \"post\": {\n \"operationId\": \"humanReviews.approve\",\n \"summary\": \"Approve human review task\",\n \"description\": \"Approve a complete review task and resume the paused run. Requires every required field to be confirmed.\",\n \"tags\": [\n \"Human reviews\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"taskId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Human review task id\"\n },\n \"required\": true,\n \"description\": \"Human review task id\"\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"type\": \"object\",\n \"properties\": {\n \"expectedVersion\": {\n \"type\": \"integer\",\n \"exclusiveMinimum\": 0,\n \"maximum\": 9007199254740991\n }\n },\n \"required\": [\n \"expectedVersion\"\n ],\n \"additionalProperties\": false\n }\n }\n }\n },\n \"responses\": {\n \"200\": {\n \"description\": \"Approved task\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/HumanReviewApproveResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/human-reviews/{taskId}/fields\": {\n \"put\": {\n \"operationId\": \"humanReviews.confirmField\",\n \"summary\": \"Confirm or edit a review field\",\n \"description\": \"Confirm or edit a scalar field using optimistic concurrency and a durable idempotency key.\",\n \"tags\": [\n \"Human reviews\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"taskId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Human review task id\"\n },\n \"required\": true,\n \"description\": \"Human review task id\"\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"type\": \"object\",\n \"properties\": {\n \"expectedVersion\": {\n \"type\": \"integer\",\n \"exclusiveMinimum\": 0,\n \"maximum\": 9007199254740991\n },\n \"idempotencyKey\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 200\n },\n \"path\": {\n \"type\": \"string\"\n },\n \"value\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"number\"\n },\n {\n \"type\": \"boolean\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"confirmed\": {\n \"default\": true,\n \"type\": \"boolean\"\n }\n },\n \"required\": [\n \"expectedVersion\",\n \"idempotencyKey\",\n \"path\",\n \"value\"\n ],\n \"additionalProperties\": false\n }\n }\n }\n },\n \"responses\": {\n \"200\": {\n \"description\": \"Updated task after field confirmation\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/HumanReviewFieldResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/human-reviews/{taskId}/files/{fileId}/content\": {\n \"get\": {\n \"operationId\": \"humanReviews.files.content.get\",\n \"summary\": \"Download human review task file\",\n \"description\": \"Download one file attached to a human-review task after strict tenant, task, and run ownership checks. Large cloud deployments may redirect to a short-lived signed storage URL.\",\n \"tags\": [\n \"Human reviews\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"taskId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Human review task id\"\n },\n \"required\": true,\n \"description\": \"Human review task id\"\n },\n {\n \"in\": \"path\",\n \"name\": \"fileId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"File id listed on the review task\"\n },\n \"required\": true,\n \"description\": \"File id listed on the review task\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Task file content\"\n },\n \"302\": {\n \"description\": \"Redirect to a short-lived signed storage download\"\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/human-reviews/{taskId}/reject\": {\n \"post\": {\n \"operationId\": \"humanReviews.reject\",\n \"summary\": \"Reject human review task\",\n \"description\": \"Reject a review task and fail the paused run with the supplied reason.\",\n \"tags\": [\n \"Human reviews\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"taskId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Human review task id\"\n },\n \"required\": true,\n \"description\": \"Human review task id\"\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"type\": \"object\",\n \"properties\": {\n \"expectedVersion\": {\n \"type\": \"integer\",\n \"exclusiveMinimum\": 0,\n \"maximum\": 9007199254740991\n },\n \"idempotencyKey\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 200\n },\n \"reason\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 5000\n }\n },\n \"required\": [\n \"expectedVersion\",\n \"idempotencyKey\",\n \"reason\"\n ],\n \"additionalProperties\": false\n }\n }\n }\n },\n \"responses\": {\n \"200\": {\n \"description\": \"Rejected task\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/HumanReviewRejectResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/models\": {\n \"get\": {\n \"operationId\": \"models.list\",\n \"summary\": \"List configured models\",\n \"description\": \"List text, vision, and OCR models configured for this tenant's environment from the workspace model catalog. This is a cheap read-only inventory: it does not call providers. `health` is `configured` or `unconfigured` from local credentials, never a live probe. Secrets and provider endpoints are never returned.\",\n \"tags\": [\n \"Models\"\n ],\n \"parameters\": [\n {\n \"in\": \"query\",\n \"name\": \"capability\",\n \"schema\": {\n \"description\": \"Return only models that support this capability (`text`, `vision`, or `ocr`).\",\n \"type\": \"string\",\n \"enum\": [\n \"text\",\n \"vision\",\n \"ocr\"\n ]\n },\n \"description\": \"Return only models that support this capability (`text`, `vision`, or `ocr`).\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Configured models\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ListModelsResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/runs\": {\n \"get\": {\n \"operationId\": \"runs.list\",\n \"summary\": \"List runs\",\n \"description\": \"List workflow and agent runs with cursor pagination.\",\n \"tags\": [\n \"Runs\"\n ],\n \"parameters\": [\n {\n \"in\": \"query\",\n \"name\": \"type\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"source\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"status\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"trigger\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"triggeredBy\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"sourceRef\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"batchId\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"exampleId\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"exampleIdContains\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"from\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"to\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"createdAfter\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"createdBefore\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"completedAfter\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"completedBefore\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"cursor\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"offset\",\n \"schema\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 9007199254740991\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"limit\",\n \"schema\": {\n \"type\": \"integer\",\n \"minimum\": 1,\n \"maximum\": 100\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"ids\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"experiments\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"sort\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"order\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"reviewStatus\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"reviewVerdict\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"hasReview\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"noReview\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"hasCorrections\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"reviewNoteContains\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"reviewCreatedAfter\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"reviewCreatedBefore\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"reviewUpdatedAfter\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"reviewUpdatedBefore\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"reviewClosedAfter\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"reviewClosedBefore\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"sinceLastClosed\",\n \"schema\": {\n \"type\": \"string\"\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"sampleRate\",\n \"schema\": {\n \"description\": \"Keep runs whose `sampleRank` is below this threshold (0–1). Pages may return fewer than `limit` rows when filtered.\",\n \"type\": \"string\"\n },\n \"description\": \"Keep runs whose `sampleRank` is below this threshold (0–1). Pages may return fewer than `limit` rows when filtered.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Runs page\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/RunsListResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"post\": {\n \"operationId\": \"runs.start\",\n \"summary\": \"Start a run\",\n \"description\": \"Start a run. Send JSON or multipart/form-data.\\n\\nHow to read a run: the envelope is at the root. The automation business result is in `output` (per-automation, not this generic schema). Status is `execution.status` (`execution.retry.nextRun.status` is a later retry). `input`, `usage`, and `debug` appear only with `?expand=`. `eval` is present only on eval-scoped runs.\",\n \"tags\": [\n \"Runs\"\n ],\n \"parameters\": [\n {\n \"in\": \"query\",\n \"name\": \"version\",\n \"schema\": {\n \"description\": \"Release or git ref. Defaults to latest.\",\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"description\": \"Release or git ref. Defaults to latest.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"wait_for_completion\",\n \"schema\": {\n \"description\": \"Seconds to wait before returning (max 600). Omit for async.\",\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 600\n },\n \"description\": \"Seconds to wait before returning (max 600). Omit for async.\"\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/RunStartBody\"\n }\n },\n \"multipart/form-data\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/RunStartMultipartRequest\"\n }\n }\n }\n },\n \"responses\": {\n \"200\": {\n \"description\": \"Run completed while waiting — same body as GET /api/v1/runs/:id\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/Run\"\n }\n }\n }\n },\n \"201\": {\n \"description\": \"Run accepted (async)\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/RunAccepted\"\n }\n }\n }\n },\n \"202\": {\n \"description\": \"Wait expired with a non-terminal status — poll GET /api/v1/runs/:id\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/RunAccepted\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"402\": {\n \"description\": \"Credit quota exceeded (insufficient_credits). The organization has spent its allowance; nothing is started.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"Trigger disabled or insufficient scope. Run start may return api_trigger_disabled when the API trigger is off, or manual_trigger_disabled for dashboard runs on API-only workflows.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/runs/{id}\": {\n \"get\": {\n \"operationId\": \"runs.get\",\n \"summary\": \"Get a run\",\n \"description\": \"Fetch one run by id. By default this returns core metadata plus terminal output/error fields. Pass `?expand=input,usage,execution,debug` to include detailed sub-objects; `expand=execution` is also where embedded review and expected artifacts appear.\\n\\nHow to read a run: the envelope is at the root. The automation business result is in `output` (per-automation, not this generic schema). Status is `execution.status` (`execution.retry.nextRun.status` is a later retry). `input`, `usage`, and `debug` appear only with `?expand=`. `eval` is present only on eval-scoped runs.\",\n \"tags\": [\n \"Runs\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Run id\"\n },\n \"required\": true,\n \"description\": \"Run id\"\n },\n {\n \"in\": \"query\",\n \"name\": \"expand\",\n \"schema\": {\n \"description\": \"Optional sections: `input`, `usage`, `execution`, `debug`. Terminal runs always include top-level output, files, and error.\",\n \"type\": \"string\"\n },\n \"description\": \"Optional sections: `input`, `usage`, `execution`, `debug`. Terminal runs always include top-level output, files, and error.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Run detail. Expanded sections appear only when requested.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/Run\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/runs/{id}/artifacts\": {\n \"get\": {\n \"operationId\": \"runs.artifacts.list\",\n \"summary\": \"List run artifacts\",\n \"description\": \"Returns a JSON list of downloadable artifact paths for a run. Pass `zip=1` to switch the response to a ZIP download containing output files.\",\n \"tags\": [\n \"Runs\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Run id\"\n },\n \"required\": true,\n \"description\": \"Run id\"\n },\n {\n \"in\": \"query\",\n \"name\": \"zip\",\n \"schema\": {\n \"description\": \"When `1`, download output files as a ZIP instead of listing paths. Does not include trace, scores, or input — use `GET /runs/{id}/scores` and `GET /runs/{id}/trace` for those. Cloud deployments reject archives whose uncompressed inputs exceed 32 MiB (`413 artifacts_zip_too_large`); download files individually or pass a smaller `files=` subset.\",\n \"type\": \"string\",\n \"enum\": [\n \"1\"\n ]\n },\n \"description\": \"When `1`, download output files as a ZIP instead of listing paths. Does not include trace, scores, or input — use `GET /runs/{id}/scores` and `GET /runs/{id}/trace` for those. Cloud deployments reject archives whose uncompressed inputs exceed 32 MiB (`413 artifacts_zip_too_large`); download files individually or pass a smaller `files=` subset.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"bundle\",\n \"schema\": {\n \"description\": \"With `zip=1`, use `review` to download a ZIP with `output/` and `expected/` folders (corrected review artifacts).\",\n \"type\": \"string\",\n \"enum\": [\n \"review\"\n ]\n },\n \"description\": \"With `zip=1`, use `review` to download a ZIP with `output/` and `expected/` folders (corrected review artifacts).\"\n },\n {\n \"in\": \"query\",\n \"name\": \"token\",\n \"schema\": {\n \"description\": \"Signed email download token (zip only; no Bearer required).\",\n \"type\": \"string\"\n },\n \"description\": \"Signed email download token (zip only; no Bearer required).\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"JSON artifact list, or ZIP bytes when `zip=1`.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/RunArtifactsResponse\"\n }\n },\n \"application/octet-stream\": {\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"ZIP archive\",\n \"format\": \"binary\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/runs/{id}/artifacts/{path}\": {\n \"get\": {\n \"operationId\": \"runs.artifacts.get\",\n \"summary\": \"Download run artifact\",\n \"description\": \"Download one artifact by path. Cloud deployments may redirect to a short-lived storage URL for large files.\",\n \"tags\": [\n \"Runs\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\"\n },\n \"required\": true\n },\n {\n \"in\": \"path\",\n \"name\": \"path\",\n \"schema\": {\n \"type\": \"string\"\n },\n \"required\": true\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Run artifact\"\n },\n \"302\": {\n \"description\": \"Redirect to a short-lived signed storage download\"\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/runs/{id}/cancel\": {\n \"post\": {\n \"operationId\": \"runs.cancel\",\n \"summary\": \"Cancel run\",\n \"description\": \"Cancel a queued run or request cancellation of an in-flight run.\",\n \"tags\": [\n \"Runs\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\"\n },\n \"required\": true\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Cancellation result\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/RunCancelResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/runs/{id}/events\": {\n \"get\": {\n \"operationId\": \"runs.events.list\",\n \"summary\": \"List run events\",\n \"description\": \"List a stable chronological lifecycle timeline for a run.\",\n \"tags\": [\n \"Runs\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Run id\"\n },\n \"required\": true,\n \"description\": \"Run id\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Run events\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/RunEventsResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/runs/{id}/promote\": {\n \"post\": {\n \"operationId\": \"runs.promote\",\n \"summary\": \"Promote run to example\",\n \"description\": \"Turn a reviewed run into a dataset example. The new example uses the run input and any corrected output/files stored through the review endpoints.\",\n \"tags\": [\n \"Reviews\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Run id.\"\n },\n \"required\": true,\n \"description\": \"Run id.\"\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/PromoteRunRequest\"\n }\n }\n }\n },\n \"responses\": {\n \"200\": {\n \"description\": \"Created or updated a dataset example from the run\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/PromoteRunResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"409\": {\n \"description\": \"The organization is being deleted. Its stored files are being removed, so new work that would write to its storage is refused.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/runs/{id}/rerun\": {\n \"post\": {\n \"operationId\": \"runs.rerun\",\n \"summary\": \"Retry run\",\n \"description\": \"Start a new run using the source run input. By default the retry uses the latest automation version; pass `version=original` to pin the same source version as the original run.\",\n \"tags\": [\n \"Runs\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Source run id to retry.\"\n },\n \"required\": true,\n \"description\": \"Source run id to retry.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"version\",\n \"schema\": {\n \"description\": \"Version for the new run. `original` pins the source run. Defaults to latest.\",\n \"type\": \"string\"\n },\n \"description\": \"Version for the new run. `original` pins the source run. Defaults to latest.\"\n },\n {\n \"in\": \"query\",\n \"name\": \"wait_for_completion\",\n \"schema\": {\n \"description\": \"Seconds to wait before returning (max 600). Omit for async.\",\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 600\n },\n \"description\": \"Seconds to wait before returning (max 600). Omit for async.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Rerun completed while waiting\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/Run\"\n }\n }\n }\n },\n \"201\": {\n \"description\": \"Rerun accepted (async)\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/RunAccepted\"\n }\n }\n }\n },\n \"202\": {\n \"description\": \"Wait expired with a non-terminal status — poll GET /api/v1/runs/:id\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/RunAccepted\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/runs/{id}/reviews\": {\n \"get\": {\n \"operationId\": \"runs.reviews.get\",\n \"summary\": \"Get run review\",\n \"description\": \"Returns review metadata and corrections for a run. Corrected files are listed at GET /runs/{id}/reviews/expected; embed review + expected artifacts with GET /runs/{id}?expand=execution.\",\n \"tags\": [\n \"Reviews\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Run id.\"\n },\n \"required\": true,\n \"description\": \"Run id.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Run review metadata.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/RunReviewDetail\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"put\": {\n \"operationId\": \"runs.reviews.update\",\n \"summary\": \"Update run review\",\n \"description\": \"Create or replace review metadata for a run.\",\n \"tags\": [\n \"Reviews\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Run id.\"\n },\n \"required\": true,\n \"description\": \"Run id.\"\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/RunReviewRequest\"\n }\n }\n }\n },\n \"responses\": {\n \"200\": {\n \"description\": \"Updated run review metadata.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/RunReviewDetail\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"delete\": {\n \"operationId\": \"runs.reviews.clear\",\n \"summary\": \"Clear run review\",\n \"description\": \"Deletes review metadata, corrections, and corrected files for the run.\",\n \"tags\": [\n \"Reviews\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Run id.\"\n },\n \"required\": true,\n \"description\": \"Run id.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Empty run review state.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/RunReviewDetail\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/runs/{id}/reviews/expected\": {\n \"get\": {\n \"operationId\": \"runs.reviews.expected.get\",\n \"summary\": \"List corrected files\",\n \"description\": \"Returns corrected artifact files attached to the run review. Review metadata and corrected JSON output live at GET /runs/{id}/reviews.\",\n \"tags\": [\n \"Reviews\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Run id.\"\n },\n \"required\": true,\n \"description\": \"Run id.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Corrected artifact files.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/RunReviewExpectedArtifacts\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"post\": {\n \"operationId\": \"runs.reviews.expected.create\",\n \"summary\": \"Add corrected file\",\n \"description\": \"Attach one corrected file to a run review. Send multipart/form-data with `file` and optional `name` to upload a local file, or JSON with `outputFileName` and optional `expectedName` to copy an existing run output file.\",\n \"tags\": [\n \"Reviews\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Run id.\"\n },\n \"required\": true,\n \"description\": \"Run id.\"\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/RunReviewExpectedFileCopyRequest\"\n }\n },\n \"multipart/form-data\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/RunReviewExpectedFileUploadRequest\"\n }\n }\n }\n },\n \"responses\": {\n \"201\": {\n \"description\": \"Corrected file created.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/RunReviewExpectedFileMutationResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/runs/{id}/reviews/expected/{filename}\": {\n \"get\": {\n \"operationId\": \"runs.reviews.expected.file.get\",\n \"summary\": \"Download corrected artifact file\",\n \"description\": \"Downloads one corrected artifact file attached to the run review. Use the `filename` returned by the corrected-output collection endpoint.\",\n \"tags\": [\n \"Reviews\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Run id.\"\n },\n \"required\": true,\n \"description\": \"Run id.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"filename\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Corrected artifact file name or slash-delimited path, as returned by `GET /runs/{id}/reviews/expected`.\"\n },\n \"required\": true,\n \"description\": \"Corrected artifact file name or slash-delimited path, as returned by `GET /runs/{id}/reviews/expected`.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Corrected file bytes.\",\n \"content\": {\n \"application/octet-stream\": {\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Corrected file bytes.\",\n \"format\": \"binary\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"patch\": {\n \"operationId\": \"runs.reviews.expected.file.update\",\n \"summary\": \"Rename corrected artifact file\",\n \"description\": \"Renames one corrected artifact file attached to the run review.\",\n \"tags\": [\n \"Reviews\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Run id.\"\n },\n \"required\": true,\n \"description\": \"Run id.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"filename\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Corrected artifact file name or slash-delimited path, as returned by `GET /runs/{id}/reviews/expected`.\"\n },\n \"required\": true,\n \"description\": \"Corrected artifact file name or slash-delimited path, as returned by `GET /runs/{id}/reviews/expected`.\"\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/RunReviewExpectedFileUpdateRequest\"\n }\n }\n }\n },\n \"responses\": {\n \"200\": {\n \"description\": \"Renamed corrected file.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/RunReviewExpectedFileUpdateResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"delete\": {\n \"operationId\": \"runs.reviews.expected.file.delete\",\n \"summary\": \"Delete corrected artifact file\",\n \"description\": \"Deletes one corrected artifact file attached to the run review.\",\n \"tags\": [\n \"Reviews\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Run id.\"\n },\n \"required\": true,\n \"description\": \"Run id.\"\n },\n {\n \"in\": \"path\",\n \"name\": \"filename\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Corrected artifact file name or slash-delimited path, as returned by `GET /runs/{id}/reviews/expected`.\"\n },\n \"required\": true,\n \"description\": \"Corrected artifact file name or slash-delimited path, as returned by `GET /runs/{id}/reviews/expected`.\"\n }\n ],\n \"responses\": {\n \"204\": {\n \"description\": \"Corrected file deleted; no response body.\"\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/runs/{id}/scores\": {\n \"get\": {\n \"operationId\": \"runs.scores.list\",\n \"summary\": \"List run evaluator scores\",\n \"description\": \"List automated evaluator results for one run. Use `score` for evaluator output and run reviews for human verdicts.\",\n \"tags\": [\n \"Evaluation\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Run id.\"\n },\n \"required\": true,\n \"description\": \"Run id.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Per-evaluator scores for the run\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/RunScoresResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/runs/{id}/steps\": {\n \"get\": {\n \"operationId\": \"runs.steps.list\",\n \"summary\": \"List run steps\",\n \"description\": \"List slim workflow step rows for a run (no input/output payloads) plus the total count. Fetch a single step for full payloads.\",\n \"tags\": [\n \"Runs\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Run id\"\n },\n \"required\": true,\n \"description\": \"Run id\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Run steps\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/RunStepsResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/runs/{id}/steps/{stepExecutionId}\": {\n \"get\": {\n \"operationId\": \"runs.steps.get\",\n \"summary\": \"Get a run step\",\n \"description\": \"Return the full single step execution (including input/output) for on-demand inspection. The step must belong to this run or a child invoke-workflow run.\",\n \"tags\": [\n \"Runs\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Run id\"\n },\n \"required\": true,\n \"description\": \"Run id\"\n },\n {\n \"in\": \"path\",\n \"name\": \"stepExecutionId\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Step execution id\"\n },\n \"required\": true,\n \"description\": \"Step execution id\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Full step execution\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/RunStepDetailResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/runs/{id}/trace\": {\n \"get\": {\n \"operationId\": \"runs.trace.get\",\n \"summary\": \"Get run trace\",\n \"description\": \"Return low-level execution trace events for debugging one run. Workflow runs expose observability phases or step records; agent runs expose parsed trace.jsonl events. The shape is intentionally extensible, but common fields are documented.\",\n \"tags\": [\n \"Runs\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Run id.\"\n },\n \"required\": true,\n \"description\": \"Run id.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Run trace events.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/RunTraceResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/runs/{id}/usage\": {\n \"get\": {\n \"operationId\": \"runs.usage.get\",\n \"summary\": \"Get run usage\",\n \"description\": \"Get token, credit, duration, and execution usage for a run.\",\n \"tags\": [\n \"Runs\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Run id\"\n },\n \"required\": true,\n \"description\": \"Run id\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Run usage\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/RunUsageResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/templates\": {\n \"get\": {\n \"operationId\": \"templates.list\",\n \"summary\": \"List templates\",\n \"description\": \"List tenant-scoped DOCX and XLSX template resources.\",\n \"tags\": [\n \"Templates\"\n ],\n \"parameters\": [\n {\n \"in\": \"query\",\n \"name\": \"limit\",\n \"schema\": {\n \"type\": \"integer\",\n \"minimum\": 1,\n \"maximum\": 100\n }\n },\n {\n \"in\": \"query\",\n \"name\": \"offset\",\n \"schema\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 9007199254740991\n }\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Template resources\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ListTemplatesResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"post\": {\n \"operationId\": \"templates.create\",\n \"summary\": \"Upload template\",\n \"description\": \"Create a stable `tmpl_…` resource and its first immutable content revision from a reusable `fileId`. Public SDK helpers `create(file)` and `createFromFileId(fileId)` upload through the Files API when needed, then send this JSON body. Generated clients send `{ fileId }` JSON only. The HTTP route still accepts a multipart `file` for CLI/internal use; that path is not generated into the public SDKs.\",\n \"tags\": [\n \"Templates\"\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/TemplateFileReferenceRequest\"\n }\n }\n }\n },\n \"responses\": {\n \"201\": {\n \"description\": \"Created template\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/CreatedTemplate\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"422\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/templates/{id}\": {\n \"get\": {\n \"operationId\": \"templates.get\",\n \"summary\": \"Inspect template\",\n \"description\": \"Get template metadata, checksum, discovered tokens, grammar capabilities, and current immutable revision. Storage keys are never exposed.\",\n \"tags\": [\n \"Templates\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"pattern\": \"^tmpl_[A-Za-z0-9_-]{21}$\",\n \"description\": \"Logical template id (tmpl_…).\"\n },\n \"required\": true,\n \"description\": \"Logical template id (tmpl_…).\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Template inspection\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/Template\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"put\": {\n \"operationId\": \"templates.replace\",\n \"summary\": \"Create template revision\",\n \"description\": \"Append an immutable revision and advance the logical template pointer from a reusable `fileId`. Public SDK helpers `replace(file)` and `replaceFromFileId(fileId)` upload through the Files API when needed, then send this JSON body. Generated clients send `{ fileId }` JSON only. The HTTP route still accepts a multipart `file` for CLI/internal use; that path is not generated into the public SDKs.\",\n \"tags\": [\n \"Templates\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"pattern\": \"^tmpl_[A-Za-z0-9_-]{21}$\",\n \"description\": \"Logical template id (tmpl_…).\"\n },\n \"required\": true,\n \"description\": \"Logical template id (tmpl_…).\"\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/TemplateReplaceRequest\"\n }\n }\n }\n },\n \"responses\": {\n \"200\": {\n \"description\": \"Updated template\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/Template\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"422\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n },\n \"delete\": {\n \"operationId\": \"templates.delete\",\n \"summary\": \"Delete template\",\n \"description\": \"Delete the mutable logical template. Immutable revisions are retained so workflows pinned with `templateRevisionId` continue to execute; unpinned workflows can no longer resolve the deleted `tmpl_…` id.\",\n \"tags\": [\n \"Templates\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"pattern\": \"^tmpl_[A-Za-z0-9_-]{21}$\",\n \"description\": \"Logical template id (tmpl_…).\"\n },\n \"required\": true,\n \"description\": \"Logical template id (tmpl_…).\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Template deleted\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/DeleteTemplateResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/templates/{id}/content\": {\n \"get\": {\n \"operationId\": \"templates.content.get\",\n \"summary\": \"Download template content\",\n \"description\": \"Download current bytes while the logical template exists, or a specific immutable revision using `revisionId`. Pinned revision downloads remain available after logical template deletion. Large objects may 302 to a short-lived signed storage URL.\",\n \"tags\": [\n \"Templates\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"pattern\": \"^tmpl_[A-Za-z0-9_-]{21}$\",\n \"description\": \"Logical template id (tmpl_…).\"\n },\n \"required\": true,\n \"description\": \"Logical template id (tmpl_…).\"\n },\n {\n \"in\": \"query\",\n \"name\": \"revisionId\",\n \"schema\": {\n \"description\": \"Immutable revision id (tmpr_…). Omit for the current content.\",\n \"type\": \"string\",\n \"pattern\": \"^tmpr_[A-Za-z0-9_-]{21}$\"\n },\n \"description\": \"Immutable revision id (tmpr_…). Omit for the current content.\"\n }\n ],\n \"responses\": {\n \"200\": {\n \"description\": \"Template binary content\",\n \"content\": {\n \"application/octet-stream\": {\n \"schema\": {\n \"type\": \"string\",\n \"description\": \"Template file bytes (DOCX or XLSX).\",\n \"format\": \"binary\"\n }\n }\n }\n },\n \"302\": {\n \"description\": \"Redirect to a short-lived signed storage download\"\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n },\n \"/v1/templates/{id}/staging\": {\n \"post\": {\n \"operationId\": \"templates.staging\",\n \"summary\": \"Finalize or hard-clean a staged template\",\n \"description\": \"Consume the one-time cleanupProof issued on a staged create. `finalize` makes the template live so later deletion keeps pinned revisions. `cleanup` hard-removes only unpublished resources from that staging attempt. Normal DELETE is unchanged and never takes this path.\",\n \"tags\": [\n \"Templates\"\n ],\n \"parameters\": [\n {\n \"in\": \"path\",\n \"name\": \"id\",\n \"schema\": {\n \"type\": \"string\",\n \"pattern\": \"^tmpl_[A-Za-z0-9_-]{21}$\",\n \"description\": \"Logical template id (tmpl_…).\"\n },\n \"required\": true,\n \"description\": \"Logical template id (tmpl_…).\"\n }\n ],\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/TemplateStagingRequest\"\n }\n }\n }\n },\n \"responses\": {\n \"200\": {\n \"description\": \"Staging action applied\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/TemplateStagingResponse\"\n }\n }\n }\n },\n \"400\": {\n \"description\": \"Validation error. Request shape did not match the spec.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"401\": {\n \"description\": \"Missing or invalid API key\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"403\": {\n \"description\": \"API key lacks required scope\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"404\": {\n \"description\": \"Resource not found\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"409\": {\n \"description\": \"Conflict. The resource is in a state that forbids the request.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"413\": {\n \"description\": \"Payload too large. Upload exceeded the per-request size cap.\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"429\": {\n \"description\": \"Rate limit exceeded\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"500\": {\n \"description\": \"Internal server error\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n },\n \"503\": {\n \"description\": \"Rate-limit accounting is temporarily unavailable. The request was not processed; retry.\",\n \"headers\": {\n \"Retry-After\": {\n \"description\": \"Seconds until the next request may succeed\",\n \"schema\": {\n \"type\": \"string\"\n }\n }\n },\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"$ref\": \"#/components/schemas/ApiErrorEnvelope\"\n }\n }\n }\n }\n }\n }\n }\n },\n \"components\": {\n \"schemas\": {\n \"UpdateAutomationRequest\": {\n \"type\": \"object\",\n \"properties\": {\n \"folderId\": {\n \"description\": \"Move a YAML workflow into this workflow folder. `null` files it at the tenant root. Ignored for the folder lookup when `folderPath` is also sent, but a string value is still validated before the path is applied.\",\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"folderPath\": {\n \"description\": \"Slash-separated workflow folder path. Missing folders are created. Empty or `/` means root. When both fields are sent, `folderPath` wins after `folderId` validation.\",\n \"type\": \"string\"\n }\n }\n },\n \"CreateDatasetReviewRequest\": {\n \"type\": \"object\",\n \"properties\": {\n \"title\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"instructions\": {\n \"description\": \"Note shown to the reviewer for the whole request.\",\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"focusFields\": {\n \"description\": \"Expected-output paths to highlight. Other fields stay normal unless listed in ignoredFields.\",\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/DatasetReviewFocusField\"\n }\n },\n \"ignoredFields\": {\n \"description\": \"Expected-output paths reviewers can skip. Shown muted as not required. Prefixes apply to nested leaves.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"itemNotes\": {\n \"description\": \"Optional per-example and per-field notes seeded as commented events at create time.\",\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/DatasetReviewCreateItemNote\"\n }\n },\n \"exampleNames\": {\n \"minItems\": 1,\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"status\": {\n \"type\": \"string\",\n \"enum\": [\n \"draft\",\n \"open\",\n \"paused\"\n ]\n }\n },\n \"required\": [\n \"title\",\n \"exampleNames\"\n ]\n },\n \"DatasetReviewFocusField\": {\n \"type\": \"object\",\n \"properties\": {\n \"path\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"Dotted expected-output path the reviewer should inspect, e.g. vendor.iban.\"\n },\n \"reason\": {\n \"description\": \"Optional reason this field needs attention.\",\n \"anyOf\": [\n {\n \"type\": \"string\",\n \"minLength\": 1\n },\n {\n \"type\": \"null\"\n }\n ]\n }\n },\n \"required\": [\n \"path\"\n ]\n },\n \"DatasetReviewCreateItemNote\": {\n \"type\": \"object\",\n \"properties\": {\n \"exampleName\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"comment\": {\n \"anyOf\": [\n {\n \"type\": \"string\",\n \"minLength\": 1\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"fields\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/DatasetReviewItemFieldNote\"\n }\n }\n },\n \"required\": [\n \"exampleName\"\n ]\n },\n \"DatasetReviewItemFieldNote\": {\n \"type\": \"object\",\n \"properties\": {\n \"path\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"comment\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"required\": [\n \"path\",\n \"comment\"\n ]\n },\n \"UpdateDatasetReviewRequest\": {\n \"type\": \"object\",\n \"properties\": {\n \"title\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"instructions\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"focusFields\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/DatasetReviewFocusField\"\n }\n },\n \"ignoredFields\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"status\": {\n \"type\": \"string\",\n \"enum\": [\n \"draft\",\n \"open\",\n \"paused\",\n \"closed\"\n ]\n }\n },\n \"additionalProperties\": false\n },\n \"UpdateDatasetReviewItem\": {\n \"type\": \"object\",\n \"properties\": {\n \"action\": {\n \"type\": \"string\",\n \"enum\": [\n \"approve\",\n \"edit\",\n \"reject\",\n \"reopen\",\n \"comment\",\n \"field-decision\"\n ]\n },\n \"expected\": {},\n \"comment\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"fieldPath\": {\n \"anyOf\": [\n {\n \"type\": \"string\",\n \"minLength\": 1\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"decision\": {\n \"anyOf\": [\n {\n \"type\": \"string\",\n \"enum\": [\n \"approved\",\n \"rejected\"\n ]\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"expectedUpdatedAt\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"ISO timestamp of the item `updatedAt` the client last observed. Required for optimistic concurrency.\"\n }\n },\n \"required\": [\n \"action\",\n \"expectedUpdatedAt\"\n ]\n },\n \"AutomationDatasetImportMultipartRequest\": {\n \"type\": \"object\",\n \"properties\": {\n \"file\": {\n \"type\": \"string\",\n \"description\": \"Dataset ZIP file\",\n \"format\": \"binary\"\n },\n \"mode\": {\n \"description\": \"`append` adds examples without deleting existing rows. `replace` deletes the current dataset before importing.\",\n \"type\": \"string\",\n \"enum\": [\n \"append\",\n \"replace\"\n ]\n }\n },\n \"required\": [\n \"file\"\n ]\n },\n \"EvaluatorConfigUpdate\": {\n \"type\": \"object\",\n \"properties\": {\n \"yaml\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 1048576,\n \"description\": \"Complete evaluator YAML to validate and store.\"\n }\n },\n \"required\": [\n \"yaml\"\n ],\n \"description\": \"Replacement evaluator configuration.\"\n },\n \"DatasetExampleMutation\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"description\": \"Example name. Required on create; omitted or null uses a generated name where supported.\",\n \"anyOf\": [\n {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 128\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"input\": {\n \"description\": \"Input arguments for the example.\",\n \"anyOf\": [\n {\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {}\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"expected\": {\n \"description\": \"Expected JSON output. Null clears the expected output.\",\n \"anyOf\": [\n {},\n {\n \"type\": \"null\"\n }\n ]\n },\n \"metadata\": {\n \"description\": \"Caller-managed metadata.\",\n \"anyOf\": [\n {\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {}\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"annotation\": {\n \"description\": \"Human note about the example. Null clears the annotation.\",\n \"anyOf\": [\n {\n \"type\": \"string\",\n \"maxLength\": 2000\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"rowOrder\": {\n \"description\": \"Optional display order. Null clears the order.\",\n \"anyOf\": [\n {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 9007199254740991\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"overrides\": {\n \"description\": \"Step output overrides used during example runs.\",\n \"anyOf\": [\n {\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {}\n },\n {\n \"type\": \"null\"\n }\n ]\n }\n },\n \"description\": \"Fields used to create or update a dataset example.\"\n },\n \"DatasetExampleUpdate\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"description\": \"Example name. Required on create; omitted or null uses a generated name where supported.\",\n \"anyOf\": [\n {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 128\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"input\": {\n \"description\": \"Input arguments for the example.\",\n \"anyOf\": [\n {\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {}\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"expected\": {\n \"description\": \"Expected JSON output. Null clears the expected output.\",\n \"anyOf\": [\n {},\n {\n \"type\": \"null\"\n }\n ]\n },\n \"metadata\": {\n \"description\": \"Caller-managed metadata.\",\n \"anyOf\": [\n {\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {}\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"annotation\": {\n \"description\": \"Human note about the example. Null clears the annotation.\",\n \"anyOf\": [\n {\n \"type\": \"string\",\n \"maxLength\": 2000\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"rowOrder\": {\n \"description\": \"Optional display order. Null clears the order.\",\n \"anyOf\": [\n {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 9007199254740991\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"overrides\": {\n \"description\": \"Step output overrides used during example runs.\",\n \"anyOf\": [\n {\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {}\n },\n {\n \"type\": \"null\"\n }\n ]\n }\n },\n \"additionalProperties\": false,\n \"description\": \"Partial update for a dataset example. Omitted fields are preserved.\"\n },\n \"DatasetExampleExpectedFileUploadRequest\": {\n \"type\": \"object\",\n \"properties\": {\n \"file\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\",\n \"format\": \"binary\"\n },\n \"description\": \"One or more expected files to upload.\"\n }\n },\n \"required\": [\n \"file\"\n ]\n },\n \"DatasetExampleExpectedFileRenameRequest\": {\n \"type\": \"object\",\n \"properties\": {\n \"newFilename\": {\n \"type\": \"string\",\n \"description\": \"New basename for the file. The parent folder is preserved.\"\n }\n },\n \"required\": [\n \"newFilename\"\n ]\n },\n \"DatasetExampleInputFileUploadRequest\": {\n \"type\": \"object\",\n \"properties\": {\n \"file\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\",\n \"format\": \"binary\"\n },\n \"description\": \"One or more input files to upload.\"\n }\n },\n \"required\": [\n \"file\"\n ]\n },\n \"DatasetExampleInputFileRenameRequest\": {\n \"type\": \"object\",\n \"properties\": {\n \"newFilename\": {\n \"type\": \"string\",\n \"description\": \"New basename for the file. The parent folder is preserved.\"\n }\n },\n \"required\": [\n \"newFilename\"\n ]\n },\n \"ExperimentCreate\": {\n \"type\": \"object\",\n \"properties\": {\n \"examples\": {\n \"description\": \"Optional dataset example ids to run. Omit to run the full dataset.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n },\n \"batchConcurrency\": {\n \"description\": \"Maximum concurrent example runs for this experiment.\",\n \"anyOf\": [\n {\n \"type\": \"integer\",\n \"exclusiveMinimum\": 0,\n \"maximum\": 9007199254740991\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"sourceRef\": {\n \"description\": \"Optional source version/ref to use for experiment runs.\",\n \"type\": \"string\"\n }\n },\n \"description\": \"Request body for starting an experiment batch.\"\n },\n \"CreateAutomationVersionRequest\": {\n \"anyOf\": [\n {\n \"type\": \"object\",\n \"properties\": {\n \"yaml\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 1048576,\n \"description\": \"Validated workflow YAML to publish as a new tagged version. Mutually exclusive with `historyId`. At most 1 MiB.\"\n },\n \"version\": {\n \"type\": \"string\",\n \"pattern\": \"^\\\\d+\\\\.\\\\d+\\\\.\\\\d+$\",\n \"description\": \"Bare semver tag such as 1.2.0. Do not include a leading v.\"\n },\n \"activate\": {\n \"description\": \"Whether to make the new version current immediately. Defaults to true. Set false to keep a tagged candidate off live traffic until promote. `activate: false` requires an existing current workflow version and returns 400 if HEAD is empty.\",\n \"type\": \"boolean\"\n }\n },\n \"required\": [\n \"yaml\",\n \"version\"\n ],\n \"additionalProperties\": false\n },\n {\n \"type\": \"object\",\n \"properties\": {\n \"historyId\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"Existing version id from GET /automations/{id}/versions. Creates a new tagged snapshot copied from that version; the source tag is left unchanged. Mutually exclusive with `yaml`.\"\n },\n \"version\": {\n \"type\": \"string\",\n \"pattern\": \"^\\\\d+\\\\.\\\\d+\\\\.\\\\d+$\",\n \"description\": \"Bare semver tag such as 1.2.0. Do not include a leading v.\"\n },\n \"activate\": {\n \"description\": \"Whether to make the new version current immediately. Defaults to true. Set false to keep a tagged candidate off live traffic until promote. `activate: false` requires an existing current workflow version and returns 400 if HEAD is empty.\",\n \"type\": \"boolean\"\n }\n },\n \"required\": [\n \"historyId\",\n \"version\"\n ],\n \"additionalProperties\": false\n }\n ],\n \"description\": \"Exactly one of `yaml` or `historyId`, plus a bare semver `version`. YAML is capped at 1 MiB. `historyId` copies the selected snapshot into a new tagged row and does not retag the source. Set `activate: false` to create a detached candidate that does not move live HEAD; that path requires an existing current version.\"\n },\n \"RestoreAutomationVersionRequest\": {\n \"type\": \"object\",\n \"properties\": {\n \"message\": {\n \"description\": \"Optional restore commit message. Defaults to a timestamped restore note.\",\n \"type\": \"string\"\n }\n },\n \"description\": \"Optional JSON body. Send `{}` when no message is needed. Restore always creates a new untagged current snapshot; it does not retag the source version.\"\n },\n \"CreateEmailServerRequest\": {\n \"oneOf\": [\n {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 128\n },\n \"enabled\": {\n \"default\": true,\n \"type\": \"boolean\"\n },\n \"transport\": {\n \"type\": \"string\",\n \"const\": \"resend\"\n },\n \"apiKey\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"fromEmail\": {\n \"type\": \"string\",\n \"format\": \"email\",\n \"pattern\": \"^(?!\\\\.)(?!.*\\\\.\\\\.)([A-Za-z0-9_'+\\\\-\\\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\\\-]*\\\\.)+[A-Za-z]{2,}$\"\n },\n \"fromName\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 128\n }\n },\n \"required\": [\n \"name\",\n \"transport\",\n \"apiKey\",\n \"fromEmail\",\n \"fromName\"\n ],\n \"additionalProperties\": false\n },\n {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 128\n },\n \"enabled\": {\n \"default\": true,\n \"type\": \"boolean\"\n },\n \"transport\": {\n \"type\": \"string\",\n \"const\": \"smtp\"\n },\n \"host\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 253\n },\n \"port\": {\n \"type\": \"integer\",\n \"minimum\": 1,\n \"maximum\": 65535\n },\n \"security\": {\n \"default\": \"starttls\",\n \"type\": \"string\",\n \"enum\": [\n \"starttls\",\n \"tls\",\n \"none\"\n ]\n },\n \"username\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 256\n },\n \"password\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"caPem\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"fromEmail\": {\n \"type\": \"string\",\n \"format\": \"email\",\n \"pattern\": \"^(?!\\\\.)(?!.*\\\\.\\\\.)([A-Za-z0-9_'+\\\\-\\\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\\\-]*\\\\.)+[A-Za-z]{2,}$\"\n },\n \"fromName\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 128\n }\n },\n \"required\": [\n \"name\",\n \"transport\",\n \"host\",\n \"fromEmail\",\n \"fromName\"\n ],\n \"additionalProperties\": false\n }\n ],\n \"type\": \"object\"\n },\n \"UpdateEmailServerRequest\": {\n \"anyOf\": [\n {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 128\n },\n \"enabled\": {\n \"type\": \"boolean\"\n },\n \"transport\": {\n \"type\": \"string\",\n \"const\": \"resend\"\n },\n \"apiKey\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"fromEmail\": {\n \"type\": \"string\",\n \"format\": \"email\",\n \"pattern\": \"^(?!\\\\.)(?!.*\\\\.\\\\.)([A-Za-z0-9_'+\\\\-\\\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\\\-]*\\\\.)+[A-Za-z]{2,}$\"\n },\n \"fromName\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 128\n }\n },\n \"required\": [\n \"transport\",\n \"fromEmail\",\n \"fromName\"\n ],\n \"additionalProperties\": false\n },\n {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 128\n },\n \"enabled\": {\n \"type\": \"boolean\"\n },\n \"transport\": {\n \"type\": \"string\",\n \"const\": \"smtp\"\n },\n \"host\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 253\n },\n \"port\": {\n \"type\": \"integer\",\n \"minimum\": 1,\n \"maximum\": 65535\n },\n \"security\": {\n \"type\": \"string\",\n \"enum\": [\n \"starttls\",\n \"tls\",\n \"none\"\n ]\n },\n \"username\": {\n \"anyOf\": [\n {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 256\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"password\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"caPem\": {\n \"anyOf\": [\n {\n \"type\": \"string\",\n \"minLength\": 1\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"fromEmail\": {\n \"type\": \"string\",\n \"format\": \"email\",\n \"pattern\": \"^(?!\\\\.)(?!.*\\\\.\\\\.)([A-Za-z0-9_'+\\\\-\\\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\\\-]*\\\\.)+[A-Za-z]{2,}$\"\n },\n \"fromName\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 128\n }\n },\n \"required\": [\n \"transport\",\n \"host\",\n \"port\",\n \"security\",\n \"fromEmail\",\n \"fromName\"\n ],\n \"additionalProperties\": false\n },\n {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 128\n },\n \"enabled\": {\n \"type\": \"boolean\"\n }\n },\n \"additionalProperties\": false\n }\n ]\n },\n \"TestEmailServerRequest\": {\n \"type\": \"object\",\n \"properties\": {\n \"to\": {\n \"type\": \"string\",\n \"format\": \"email\",\n \"pattern\": \"^(?!\\\\.)(?!.*\\\\.\\\\.)([A-Za-z0-9_'+\\\\-\\\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\\\-]*\\\\.)+[A-Za-z]{2,}$\"\n }\n },\n \"required\": [\n \"to\"\n ],\n \"additionalProperties\": false\n },\n \"CreateFileMultipartRequest\": {\n \"type\": \"object\",\n \"properties\": {\n \"file\": {\n \"type\": \"string\",\n \"description\": \"Binary file field\",\n \"format\": \"binary\"\n },\n \"purpose\": {\n \"description\": \"Optional lifecycle marker. `run-input` marks a retry-safe temporary run pre-upload reaped after 24 hours. `builder-attachment` marks a Studio builder intermediary (any MIME) with the same TTL.\",\n \"type\": \"string\",\n \"enum\": [\n \"run-input\",\n \"builder-attachment\"\n ]\n }\n },\n \"required\": [\n \"file\"\n ]\n },\n \"CreateFileUploadSessionRequest\": {\n \"type\": \"object\",\n \"properties\": {\n \"filename\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 255\n },\n \"contentType\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 255\n },\n \"size\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 9007199254740991\n },\n \"purpose\": {\n \"type\": \"string\",\n \"enum\": [\n \"run-input\",\n \"builder-attachment\"\n ]\n },\n \"idempotencyKey\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 256\n }\n },\n \"required\": [\n \"filename\",\n \"contentType\",\n \"size\"\n ]\n },\n \"PresignFileUploadPartRequest\": {\n \"type\": \"object\",\n \"properties\": {\n \"partNumber\": {\n \"type\": \"integer\",\n \"minimum\": 1,\n \"maximum\": 10000\n }\n },\n \"required\": [\n \"partNumber\"\n ]\n },\n \"FolderType\": {\n \"type\": \"string\",\n \"enum\": [\n \"workflow\",\n \"template\"\n ]\n },\n \"CreateFolderRequest\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 255,\n \"description\": \"Folder name. Cannot contain `/`.\"\n },\n \"type\": {\n \"description\": \"Which folder tree to create in. Required; there is no default.\",\n \"$ref\": \"#/components/schemas/FolderType\"\n },\n \"parentId\": {\n \"description\": \"Parent folder id. Omit or `null` to create at the tree root.\",\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n }\n },\n \"required\": [\n \"name\",\n \"type\"\n ]\n },\n \"UpdateFolderRequest\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"description\": \"New folder name. Cannot contain `/`.\",\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 255\n },\n \"parentId\": {\n \"description\": \"New parent folder id. `null` moves the folder to the tree root.\",\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n }\n }\n },\n \"RunStartBody\": {\n \"type\": \"object\",\n \"properties\": {\n \"target\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"Automation target without a version suffix, e.g. workflows.invoice or agents.support.\"\n },\n \"input\": {\n \"description\": \"Scalar and structured automation arguments.\",\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {}\n },\n \"files\": {\n \"description\": \"File inputs as ingress references (`{ \\\"$fileId\\\": \\\"file_...\\\" }` or `{ \\\"$inline\\\": { filename, mimeType, base64 } }`). Upload bytes via multipart `files.<fieldName>` parts instead.\",\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {\n \"anyOf\": [\n {\n \"anyOf\": [\n {\n \"type\": \"object\",\n \"properties\": {\n \"$fileId\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"Reusable file-pool id to materialize\"\n }\n },\n \"required\": [\n \"$fileId\"\n ],\n \"additionalProperties\": false\n },\n {\n \"type\": \"object\",\n \"properties\": {\n \"$inline\": {\n \"type\": \"object\",\n \"properties\": {\n \"filename\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"Original filename for the materialized artifact\"\n },\n \"mimeType\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"MIME type for the materialized artifact\"\n },\n \"base64\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"Base64-encoded file bytes\"\n }\n },\n \"required\": [\n \"filename\",\n \"mimeType\",\n \"base64\"\n ],\n \"additionalProperties\": false\n }\n },\n \"required\": [\n \"$inline\"\n ],\n \"additionalProperties\": false\n }\n ]\n },\n {\n \"type\": \"array\",\n \"items\": {\n \"anyOf\": [\n {\n \"type\": \"object\",\n \"properties\": {\n \"$fileId\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"Reusable file-pool id to materialize\"\n }\n },\n \"required\": [\n \"$fileId\"\n ],\n \"additionalProperties\": false\n },\n {\n \"type\": \"object\",\n \"properties\": {\n \"$inline\": {\n \"type\": \"object\",\n \"properties\": {\n \"filename\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"Original filename for the materialized artifact\"\n },\n \"mimeType\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"MIME type for the materialized artifact\"\n },\n \"base64\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"Base64-encoded file bytes\"\n }\n },\n \"required\": [\n \"filename\",\n \"mimeType\",\n \"base64\"\n ],\n \"additionalProperties\": false\n }\n },\n \"required\": [\n \"$inline\"\n ],\n \"additionalProperties\": false\n }\n ]\n }\n }\n ]\n }\n },\n \"overrides\": {\n \"description\": \"Per-step output overrides. Workflow runs only.\",\n \"type\": \"object\",\n \"properties\": {\n \"steps\": {\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {}\n }\n }\n }\n },\n \"metadata\": {\n \"description\": \"Caller-supplied run metadata.\",\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {}\n }\n },\n \"required\": [\n \"target\"\n ],\n \"description\": \"Run envelope. Declare provenance with the `X-Eigenpal-Trigger` header (`api` or `cli`). Legacy 0.5.12 body shapes remain accepted.\"\n },\n \"RunStartMultipartRequest\": {\n \"type\": \"object\",\n \"properties\": {\n \"target\": {\n \"type\": \"string\",\n \"description\": \"Automation target, e.g. `workflows.invoice`.\"\n },\n \"input\": {\n \"description\": \"JSON-encoded scalar input object.\",\n \"type\": \"string\"\n },\n \"overrides\": {\n \"description\": \"JSON-encoded step overrides.\",\n \"type\": \"string\"\n },\n \"metadata\": {\n \"description\": \"JSON-encoded run metadata.\",\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"target\"\n ],\n \"additionalProperties\": {\n \"description\": \"Dynamic binary fields like `files.<fieldName>`.\"\n }\n },\n \"PromoteRunRequest\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"description\": \"Dataset example name to create or update. Defaults to a generated name when omitted.\",\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 128\n }\n },\n \"description\": \"Create or update a dataset example from the run input, actual output, and review corrections.\"\n },\n \"RunReviewRequest\": {\n \"type\": \"object\",\n \"properties\": {\n \"verdict\": {\n \"description\": \"Reviewer verdict. Omit or send null for feedback without a ranking (nit). Defaults are applied client-side only; any verdict/status combination is accepted.\",\n \"anyOf\": [\n {\n \"type\": \"string\",\n \"enum\": [\n \"correct\",\n \"incorrect\"\n ]\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"status\": {\n \"description\": \"Review lifecycle. Defaults from verdict (`correct` → `closed`, otherwise `open`). Use `closed` or `wont_fix` to close an open review.\",\n \"type\": \"string\",\n \"enum\": [\n \"open\",\n \"closed\",\n \"wont_fix\"\n ]\n },\n \"note\": {\n \"description\": \"Reviewer note.\",\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"correctedOutput\": {\n \"description\": \"Corrected JSON output for this run. Send `null` to clear a previously stored correction.\",\n \"anyOf\": [\n {},\n {\n \"type\": \"null\"\n }\n ]\n },\n \"corrections\": {\n \"description\": \"Field and file corrections. When present, replaces the entire correction set for this review. Omit to leave existing corrections unchanged.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\"\n },\n \"kind\": {\n \"type\": \"string\",\n \"enum\": [\n \"field\",\n \"file\"\n ]\n },\n \"path\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"label\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"originalValue\": {},\n \"correctedValue\": {},\n \"note\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"correctedArtifactPath\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n }\n },\n \"required\": [\n \"kind\",\n \"path\"\n ]\n }\n }\n },\n \"description\": \"Create or replace review metadata for a run. Attribution fields (`reviewedBy`, `closedBy`, and their emails) are read-only and populated from the authenticated user or API key creator.\"\n },\n \"RunReviewExpectedFileCopyRequest\": {\n \"type\": \"object\",\n \"properties\": {\n \"outputFileName\": {\n \"type\": \"string\",\n \"description\": \"Name of an existing run output file to copy into corrected artifacts.\"\n },\n \"expectedName\": {\n \"description\": \"Optional name for the copied corrected file. Defaults to the original output file name.\",\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"outputFileName\"\n ],\n \"description\": \"JSON request body for copying one run output file into the corrected artifact set.\"\n },\n \"RunReviewExpectedFileUploadRequest\": {\n \"type\": \"object\",\n \"properties\": {\n \"file\": {\n \"type\": \"string\",\n \"description\": \"Corrected artifact file to upload.\",\n \"format\": \"binary\"\n },\n \"name\": {\n \"description\": \"Optional stored corrected file name. Defaults to the uploaded filename.\",\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"file\"\n ]\n },\n \"RunReviewExpectedFileUpdateRequest\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\",\n \"description\": \"New corrected file name.\"\n }\n },\n \"required\": [\n \"name\"\n ],\n \"description\": \"Rename one corrected file.\"\n },\n \"TemplateFileReferenceRequest\": {\n \"type\": \"object\",\n \"properties\": {\n \"fileId\": {\n \"type\": \"string\",\n \"pattern\": \"^file_[A-Za-z0-9_-]{21}$\",\n \"description\": \"Reusable file id produced by the direct file upload flow. It is consumed as upload transport, not exposed as template identity.\"\n },\n \"name\": {\n \"type\": \"string\"\n },\n \"description\": {\n \"type\": \"string\"\n },\n \"staged\": {\n \"description\": \"When true, the create response includes a one-time cleanupProof for unpublished CLI staging. Normal uploads omit this.\",\n \"type\": \"boolean\"\n }\n },\n \"required\": [\n \"fileId\"\n ]\n },\n \"TemplateReplaceRequest\": {\n \"type\": \"object\",\n \"properties\": {\n \"fileId\": {\n \"type\": \"string\",\n \"pattern\": \"^file_[A-Za-z0-9_-]{21}$\",\n \"description\": \"Reusable file id produced by the direct file upload flow. It is consumed as upload transport, not exposed as template identity.\"\n }\n },\n \"required\": [\n \"fileId\"\n ]\n },\n \"TemplateStagingRequest\": {\n \"type\": \"object\",\n \"properties\": {\n \"proof\": {\n \"type\": \"string\",\n \"minLength\": 16,\n \"maxLength\": 128\n },\n \"action\": {\n \"type\": \"string\",\n \"enum\": [\n \"cleanup\",\n \"finalize\"\n ]\n }\n },\n \"required\": [\n \"proof\",\n \"action\"\n ]\n },\n \"AuthCheckResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"ok\": {\n \"type\": \"boolean\",\n \"const\": true\n },\n \"tenantId\": {\n \"type\": \"string\"\n },\n \"tenantSlug\": {\n \"type\": \"string\"\n },\n \"tenantName\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"userId\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"keyId\": {\n \"type\": \"string\"\n },\n \"email\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"name\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"scope\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n },\n \"wildcardGranted\": {\n \"type\": \"boolean\"\n }\n },\n \"required\": [\n \"ok\",\n \"tenantId\",\n \"tenantSlug\",\n \"tenantName\",\n \"userId\",\n \"keyId\",\n \"email\",\n \"name\",\n \"scope\",\n \"wildcardGranted\"\n ],\n \"additionalProperties\": false\n },\n \"ApiErrorEnvelope\": {\n \"type\": \"object\",\n \"properties\": {\n \"issues\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/ApiErrorIssue\"\n }\n },\n \"requestId\": {\n \"type\": \"string\",\n \"description\": \"Request id echoed via the x-request-id header\"\n },\n \"hint\": {\n \"description\": \"Suggested fix for known error patterns\",\n \"type\": \"string\"\n },\n \"docsUrl\": {\n \"description\": \"Link to relevant docs\",\n \"type\": \"string\"\n },\n \"conflictingWorkflowId\": {\n \"description\": \"Present on 409 workflow_name_conflict responses. Id of the workflow that already owns the requested name.\",\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"issues\",\n \"requestId\"\n ],\n \"additionalProperties\": false\n },\n \"ApiErrorIssue\": {\n \"type\": \"object\",\n \"properties\": {\n \"field\": {\n \"type\": \"string\",\n \"description\": \"JSON path of the offending field, or \\\"<root>\\\"\"\n },\n \"message\": {\n \"type\": \"string\",\n \"description\": \"Human-readable error message\"\n },\n \"code\": {\n \"type\": \"string\",\n \"description\": \"Machine-readable error code (e.g. invalid_value, not_found, api_trigger_disabled, manual_trigger_disabled)\"\n },\n \"severity\": {\n \"type\": \"string\",\n \"enum\": [\n \"error\",\n \"warning\"\n ],\n \"description\": \"Issue severity\"\n }\n },\n \"required\": [\n \"field\",\n \"message\",\n \"code\",\n \"severity\"\n ],\n \"additionalProperties\": false\n },\n \"ListAutomationsResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"data\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/AutomationSummary\"\n }\n },\n \"total\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"limit\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"offset\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n }\n },\n \"required\": [\n \"data\",\n \"total\",\n \"limit\",\n \"offset\"\n ],\n \"additionalProperties\": false\n },\n \"AutomationSummary\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\",\n \"description\": \"Implementation id for the automation. Workflow automations use workflow ids; agent automations use agent workflow ids.\"\n },\n \"type\": {\n \"$ref\": \"#/components/schemas/AutomationType\"\n },\n \"slug\": {\n \"type\": \"string\"\n },\n \"name\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"description\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"status\": {\n \"type\": \"string\"\n },\n \"version\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"triggers\": {\n \"$ref\": \"#/components/schemas/AutomationTriggerState\"\n },\n \"implementationAvailable\": {\n \"description\": \"False when the automations registry row exists but the workflow/agent implementation row is missing.\",\n \"type\": \"boolean\"\n },\n \"folderId\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Workflow folder id. Null for unfiled workflows, agent automations, and orphan registry rows.\"\n },\n \"folderPath\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Slash-separated workflow folder path from the tenant root, such as `billing/invoices`. Null at root and for agent automations.\"\n },\n \"createdAt\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"string\"\n }\n ]\n },\n \"updatedAt\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"string\"\n }\n ]\n }\n },\n \"required\": [\n \"id\",\n \"type\",\n \"slug\",\n \"name\",\n \"folderId\",\n \"folderPath\",\n \"createdAt\"\n ],\n \"additionalProperties\": false\n },\n \"AutomationType\": {\n \"type\": \"string\",\n \"enum\": [\n \"workflow\",\n \"agent\"\n ]\n },\n \"AutomationTriggerState\": {\n \"type\": \"object\",\n \"properties\": {\n \"api\": {\n \"type\": \"boolean\"\n },\n \"email\": {\n \"type\": \"boolean\"\n },\n \"manual\": {\n \"type\": \"boolean\"\n },\n \"cron\": {\n \"type\": \"boolean\"\n }\n },\n \"required\": [\n \"api\",\n \"email\",\n \"manual\",\n \"cron\"\n ],\n \"additionalProperties\": false\n },\n \"AutomationDetail\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\",\n \"description\": \"Implementation id for the automation. Workflow automations use workflow ids; agent automations use agent workflow ids.\"\n },\n \"type\": {\n \"$ref\": \"#/components/schemas/AutomationType\"\n },\n \"slug\": {\n \"type\": \"string\"\n },\n \"name\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"description\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"status\": {\n \"type\": \"string\"\n },\n \"version\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"triggers\": {\n \"$ref\": \"#/components/schemas/AutomationTriggerState\"\n },\n \"implementationAvailable\": {\n \"description\": \"False when the automations registry row exists but the workflow/agent implementation row is missing.\",\n \"type\": \"boolean\"\n },\n \"folderId\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Workflow folder id. Null for unfiled workflows, agent automations, and orphan registry rows.\"\n },\n \"folderPath\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Slash-separated workflow folder path from the tenant root, such as `billing/invoices`. Null at root and for agent automations.\"\n },\n \"createdAt\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"string\"\n }\n ]\n },\n \"updatedAt\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"string\"\n }\n ]\n },\n \"inputSchema\": {\n \"anyOf\": [\n {\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {}\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"outputSchema\": {\n \"anyOf\": [\n {\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {}\n },\n {\n \"type\": \"null\"\n }\n ]\n }\n },\n \"required\": [\n \"id\",\n \"type\",\n \"slug\",\n \"name\",\n \"folderId\",\n \"folderPath\",\n \"createdAt\"\n ],\n \"additionalProperties\": false\n },\n \"DeleteAutomationResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"deleted\": {\n \"type\": \"boolean\",\n \"const\": true\n },\n \"id\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"deleted\",\n \"id\"\n ],\n \"additionalProperties\": false\n },\n \"DatasetReviewRequestList\": {\n \"type\": \"object\",\n \"properties\": {\n \"data\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/DatasetReviewRequest\"\n }\n },\n \"total\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"limit\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"offset\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n }\n },\n \"required\": [\n \"data\",\n \"total\",\n \"limit\",\n \"offset\"\n ],\n \"additionalProperties\": false\n },\n \"DatasetReviewRequest\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\"\n },\n \"automationId\": {\n \"type\": \"string\"\n },\n \"title\": {\n \"type\": \"string\"\n },\n \"instructions\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"focusFields\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/DatasetReviewFocusFieldOutput\"\n }\n },\n \"ignoredFields\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n },\n \"status\": {\n \"type\": \"string\",\n \"enum\": [\n \"draft\",\n \"open\",\n \"paused\",\n \"closed\"\n ]\n },\n \"exampleNames\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n },\n \"progress\": {\n \"$ref\": \"#/components/schemas/DatasetReviewProgress\"\n },\n \"createdBy\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"createdAt\": {\n \"type\": \"string\"\n },\n \"closedAt\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n }\n },\n \"required\": [\n \"id\",\n \"automationId\",\n \"title\",\n \"instructions\",\n \"focusFields\",\n \"ignoredFields\",\n \"status\",\n \"exampleNames\",\n \"progress\",\n \"createdBy\",\n \"createdAt\",\n \"closedAt\"\n ],\n \"additionalProperties\": false\n },\n \"DatasetReviewProgress\": {\n \"type\": \"object\",\n \"properties\": {\n \"total\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 9007199254740991\n },\n \"pending\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 9007199254740991\n },\n \"approved\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 9007199254740991\n },\n \"edited\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 9007199254740991\n },\n \"rejected\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 9007199254740991\n },\n \"remaining\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 9007199254740991,\n \"description\": \"Count of examples still pending a decision.\"\n },\n \"complete\": {\n \"type\": \"boolean\",\n \"description\": \"True when every example has been approved, edited, or rejected. Close the request when review is finished; dataset write-back is always manual.\"\n }\n },\n \"required\": [\n \"total\",\n \"pending\",\n \"approved\",\n \"edited\",\n \"rejected\",\n \"remaining\",\n \"complete\"\n ],\n \"additionalProperties\": false\n },\n \"DatasetReviewDetail\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\"\n },\n \"automationId\": {\n \"type\": \"string\"\n },\n \"title\": {\n \"type\": \"string\"\n },\n \"instructions\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"focusFields\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/DatasetReviewFocusFieldOutput\"\n }\n },\n \"ignoredFields\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n },\n \"status\": {\n \"type\": \"string\",\n \"enum\": [\n \"draft\",\n \"open\",\n \"paused\",\n \"closed\"\n ]\n },\n \"exampleNames\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n },\n \"progress\": {\n \"$ref\": \"#/components/schemas/DatasetReviewProgress\"\n },\n \"createdBy\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"createdAt\": {\n \"type\": \"string\"\n },\n \"closedAt\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"items\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/DatasetReviewItem\"\n }\n },\n \"events\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/DatasetReviewEvent\"\n }\n }\n },\n \"required\": [\n \"id\",\n \"automationId\",\n \"title\",\n \"instructions\",\n \"focusFields\",\n \"ignoredFields\",\n \"status\",\n \"exampleNames\",\n \"progress\",\n \"createdBy\",\n \"createdAt\",\n \"closedAt\",\n \"items\"\n ],\n \"additionalProperties\": false\n },\n \"DatasetReviewItem\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\"\n },\n \"reviewId\": {\n \"type\": \"string\"\n },\n \"exampleName\": {\n \"type\": \"string\"\n },\n \"snapshotInputJson\": {\n \"anyOf\": [\n {\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {}\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"snapshotExpectedJson\": {\n \"anyOf\": [\n {},\n {\n \"type\": \"null\"\n }\n ]\n },\n \"snapshotManifest\": {\n \"type\": \"object\",\n \"properties\": {\n \"expectedFiles\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"name\"\n ],\n \"additionalProperties\": false\n }\n },\n \"metadata\": {\n \"anyOf\": [\n {\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {}\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"inputFileHashes\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"path\": {\n \"type\": \"string\"\n },\n \"sha256\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"path\",\n \"sha256\"\n ],\n \"additionalProperties\": false\n }\n }\n },\n \"required\": [\n \"expectedFiles\",\n \"metadata\"\n ],\n \"additionalProperties\": false\n },\n \"status\": {\n \"type\": \"string\",\n \"enum\": [\n \"pending\",\n \"approved\",\n \"edited\",\n \"rejected\"\n ]\n },\n \"currentExpectedJson\": {\n \"anyOf\": [\n {},\n {\n \"type\": \"null\"\n }\n ]\n },\n \"fieldDecisions\": {\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {\n \"$ref\": \"#/components/schemas/DatasetReviewFieldDecision\"\n }\n },\n \"inputDrifted\": {\n \"type\": \"boolean\",\n \"description\": \"True when live dataset input-file bytes no longer match the hashes captured at request creation.\"\n },\n \"updatedBy\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"updatedAt\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"id\",\n \"reviewId\",\n \"exampleName\",\n \"snapshotInputJson\",\n \"snapshotExpectedJson\",\n \"snapshotManifest\",\n \"status\",\n \"currentExpectedJson\",\n \"fieldDecisions\",\n \"inputDrifted\",\n \"updatedBy\",\n \"updatedAt\"\n ],\n \"additionalProperties\": false\n },\n \"DatasetReviewFieldDecision\": {\n \"type\": \"object\",\n \"properties\": {\n \"decision\": {\n \"type\": \"string\",\n \"enum\": [\n \"approved\",\n \"rejected\"\n ]\n },\n \"comment\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"reviewerId\": {\n \"type\": \"string\"\n },\n \"updatedAt\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"decision\",\n \"reviewerId\",\n \"updatedAt\"\n ],\n \"additionalProperties\": false\n },\n \"DatasetReviewEvent\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\"\n },\n \"reviewId\": {\n \"type\": \"string\"\n },\n \"itemId\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"actorUserId\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"action\": {\n \"type\": \"string\",\n \"enum\": [\n \"created\",\n \"approved\",\n \"edited\",\n \"rejected\",\n \"reopened\",\n \"commented\",\n \"field-decision\"\n ]\n },\n \"diffSummary\": {\n \"anyOf\": [\n {},\n {\n \"type\": \"null\"\n }\n ]\n },\n \"createdAt\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"id\",\n \"reviewId\",\n \"itemId\",\n \"actorUserId\",\n \"action\",\n \"diffSummary\",\n \"createdAt\"\n ],\n \"additionalProperties\": false\n },\n \"DatasetReviewEventList\": {\n \"type\": \"object\",\n \"properties\": {\n \"events\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/DatasetReviewEvent\"\n }\n }\n },\n \"required\": [\n \"events\"\n ],\n \"additionalProperties\": false\n },\n \"DatasetReviewItemList\": {\n \"type\": \"object\",\n \"properties\": {\n \"items\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/DatasetReviewItem\"\n }\n }\n },\n \"required\": [\n \"items\"\n ],\n \"additionalProperties\": false\n },\n \"DatasetReviewItemResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"item\": {\n \"$ref\": \"#/components/schemas/DatasetReviewItem\"\n }\n },\n \"required\": [\n \"item\"\n ],\n \"additionalProperties\": false\n },\n \"DatasetImportResponse\": {\n \"anyOf\": [\n {\n \"type\": \"object\",\n \"properties\": {\n \"mode\": {\n \"type\": \"string\",\n \"const\": \"append\"\n },\n \"created\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"expectedSet\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"skipped\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"issues\": {\n \"type\": \"array\",\n \"items\": {}\n }\n },\n \"required\": [\n \"mode\",\n \"created\",\n \"expectedSet\",\n \"skipped\",\n \"issues\"\n ],\n \"additionalProperties\": false\n },\n {\n \"type\": \"object\",\n \"properties\": {\n \"mode\": {\n \"type\": \"string\",\n \"const\": \"replace\"\n },\n \"created\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"expectedSet\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"deleted\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"filesDeleted\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n }\n },\n \"required\": [\n \"mode\",\n \"created\",\n \"expectedSet\",\n \"deleted\",\n \"filesDeleted\"\n ],\n \"additionalProperties\": false\n }\n ]\n },\n \"EvaluatorConfigResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"automationId\": {\n \"type\": \"string\",\n \"description\": \"Automation that owns this evaluator config.\"\n },\n \"automationType\": {\n \"$ref\": \"#/components/schemas/AutomationType\"\n },\n \"yaml\": {\n \"type\": \"string\",\n \"description\": \"Evaluator configuration YAML.\"\n },\n \"config\": {\n \"type\": \"object\",\n \"properties\": {\n \"evaluators\": {\n \"type\": \"array\",\n \"items\": {},\n \"description\": \"Parsed evaluator definitions from the YAML.\"\n },\n \"passThreshold\": {\n \"type\": \"number\",\n \"description\": \"Overall score threshold required for the experiment to pass.\"\n }\n },\n \"required\": [\n \"evaluators\",\n \"passThreshold\"\n ],\n \"additionalProperties\": false\n }\n },\n \"required\": [\n \"automationId\",\n \"automationType\",\n \"yaml\",\n \"config\"\n ],\n \"additionalProperties\": false,\n \"description\": \"Evaluator YAML and parsed evaluator configuration for an automation.\"\n },\n \"DatasetExampleList\": {\n \"type\": \"object\",\n \"properties\": {\n \"data\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/DatasetExample\"\n }\n },\n \"total\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"limit\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"offset\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n }\n },\n \"required\": [\n \"data\",\n \"total\",\n \"limit\",\n \"offset\"\n ],\n \"additionalProperties\": false\n },\n \"DatasetExample\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\",\n \"description\": \"Stable public example id. Workflow examples use DB ids; agent examples use deterministic name-derived ids.\"\n },\n \"name\": {\n \"type\": \"string\",\n \"description\": \"Human-readable dataset example name.\"\n },\n \"automationId\": {\n \"type\": \"string\",\n \"description\": \"Automation that owns this example.\"\n },\n \"automationType\": {\n \"$ref\": \"#/components/schemas/AutomationType\"\n },\n \"input\": {\n \"anyOf\": [\n {\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {}\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Input arguments used when this example is run. Null when listing with `include=metadata`.\"\n },\n \"expected\": {\n \"anyOf\": [\n {},\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Expected JSON output for evaluator comparisons. Null when listing with `include=metadata`.\"\n },\n \"expectedFiles\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\",\n \"description\": \"Expected file name.\"\n },\n \"url\": {\n \"description\": \"Download URL for the expected file.\",\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"name\"\n ],\n \"additionalProperties\": false\n },\n \"description\": \"Expected files attached to this example.\"\n },\n \"metadata\": {\n \"anyOf\": [\n {\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {}\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Caller-managed metadata for sorting or filtering examples.\"\n },\n \"annotation\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Human note about the example.\"\n },\n \"rowOrder\": {\n \"anyOf\": [\n {\n \"type\": \"number\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Optional display order within the dataset.\"\n },\n \"overrides\": {\n \"anyOf\": [\n {\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {}\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Step output overrides used when running this example.\"\n },\n \"latestRunId\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Most recent run id created from this example.\"\n },\n \"createdAt\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"string\"\n }\n ]\n },\n \"updatedAt\": {\n \"anyOf\": [\n {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"string\"\n }\n ]\n },\n {\n \"type\": \"null\"\n }\n ]\n }\n },\n \"required\": [\n \"id\",\n \"name\",\n \"automationId\",\n \"automationType\",\n \"input\",\n \"expected\",\n \"expectedFiles\",\n \"metadata\",\n \"annotation\",\n \"rowOrder\",\n \"overrides\",\n \"latestRunId\"\n ],\n \"additionalProperties\": false,\n \"description\": \"One input/expected-output row in an automation dataset.\"\n },\n \"DatasetExampleExpectedFileList\": {\n \"type\": \"object\",\n \"properties\": {\n \"files\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n },\n \"description\": \"Paths under the example expected folder.\"\n }\n },\n \"required\": [\n \"files\"\n ],\n \"additionalProperties\": false\n },\n \"DatasetExampleExpectedFileUploadResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"uploaded\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n },\n \"description\": \"Stored expected file paths.\"\n }\n },\n \"required\": [\n \"uploaded\"\n ],\n \"additionalProperties\": false\n },\n \"DatasetExampleExpectedFileRenameResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"ok\": {\n \"type\": \"boolean\",\n \"const\": true\n },\n \"filename\": {\n \"type\": \"string\"\n },\n \"path\": {\n \"type\": \"string\",\n \"description\": \"Updated expected file path.\"\n }\n },\n \"required\": [\n \"ok\",\n \"filename\",\n \"path\"\n ],\n \"additionalProperties\": false\n },\n \"DatasetExampleInputFileList\": {\n \"type\": \"object\",\n \"properties\": {\n \"files\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n },\n \"description\": \"Paths under the example input folder.\"\n }\n },\n \"required\": [\n \"files\"\n ],\n \"additionalProperties\": false\n },\n \"DatasetExampleInputFileUploadResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"uploaded\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n },\n \"description\": \"Stored input file paths.\"\n }\n },\n \"required\": [\n \"uploaded\"\n ],\n \"additionalProperties\": false\n },\n \"DatasetExampleInputFileRenameResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"ok\": {\n \"type\": \"boolean\",\n \"const\": true\n },\n \"filename\": {\n \"type\": \"string\"\n },\n \"path\": {\n \"type\": \"string\",\n \"description\": \"Updated input file path.\"\n }\n },\n \"required\": [\n \"ok\",\n \"filename\",\n \"path\"\n ],\n \"additionalProperties\": false\n },\n \"ExampleRunResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\",\n \"description\": \"Run id created for this example.\"\n },\n \"type\": {\n \"type\": \"string\",\n \"enum\": [\n \"workflow\",\n \"agent\"\n ],\n \"description\": \"Implementation type behind the automation.\"\n },\n \"batchId\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Experiment batch id when the run is associated with a batch. The API also calls this an experiment id in experiment routes.\"\n },\n \"finished\": {\n \"type\": \"boolean\",\n \"const\": false,\n \"description\": \"Example runs are accepted asynchronously.\"\n }\n },\n \"required\": [\n \"id\",\n \"type\",\n \"batchId\",\n \"finished\"\n ],\n \"additionalProperties\": false\n },\n \"Experiment\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\",\n \"description\": \"Experiment batch id. Some CLI commands historically call this a batch id.\"\n },\n \"automationId\": {\n \"type\": \"string\",\n \"description\": \"Automation this experiment belongs to.\"\n },\n \"automationType\": {\n \"$ref\": \"#/components/schemas/AutomationType\"\n },\n \"status\": {\n \"type\": \"string\",\n \"enum\": [\n \"queued\",\n \"running\",\n \"completed\"\n ],\n \"description\": \"Experiment batch status.\"\n },\n \"runCount\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991,\n \"description\": \"Total runs in the experiment.\"\n },\n \"completedCount\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991,\n \"description\": \"Runs that have completed.\"\n },\n \"passedCount\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991,\n \"description\": \"Runs whose evaluator scores passed.\"\n },\n \"failedCount\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991,\n \"description\": \"Runs whose evaluator scores failed.\"\n },\n \"avgScore\": {\n \"anyOf\": [\n {\n \"type\": \"number\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Average automated evaluator score.\"\n },\n \"createdAt\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"string\"\n }\n ]\n },\n \"completedAt\": {\n \"anyOf\": [\n {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"string\"\n }\n ]\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"version\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n }\n },\n \"required\": [\n \"id\",\n \"automationId\",\n \"automationType\",\n \"status\",\n \"runCount\",\n \"completedCount\",\n \"passedCount\",\n \"failedCount\",\n \"avgScore\",\n \"createdAt\",\n \"completedAt\",\n \"version\"\n ],\n \"additionalProperties\": false,\n \"description\": \"Experiment batch summary for an automation dataset run.\"\n },\n \"ExperimentCreateResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\",\n \"description\": \"Experiment batch id.\"\n },\n \"runs\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\",\n \"description\": \"Run id.\"\n },\n \"exampleId\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Dataset example id.\"\n }\n },\n \"required\": [\n \"id\",\n \"exampleId\"\n ],\n \"additionalProperties\": false\n },\n \"description\": \"Runs enqueued for this experiment.\"\n },\n \"total\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991,\n \"description\": \"Number of runs enqueued.\"\n }\n },\n \"required\": [\n \"id\",\n \"runs\",\n \"total\"\n ],\n \"additionalProperties\": false,\n \"description\": \"Accepted experiment batch and the runs it enqueued.\"\n },\n \"ExperimentDetail\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\",\n \"description\": \"Experiment batch id. Some CLI commands historically call this a batch id.\"\n },\n \"automationId\": {\n \"type\": \"string\",\n \"description\": \"Automation this experiment belongs to.\"\n },\n \"automationType\": {\n \"$ref\": \"#/components/schemas/AutomationType\"\n },\n \"status\": {\n \"type\": \"string\",\n \"enum\": [\n \"queued\",\n \"running\",\n \"completed\"\n ],\n \"description\": \"Experiment batch status.\"\n },\n \"runCount\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991,\n \"description\": \"Total runs in the experiment.\"\n },\n \"completedCount\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991,\n \"description\": \"Runs that have completed.\"\n },\n \"passedCount\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991,\n \"description\": \"Runs whose evaluator scores passed.\"\n },\n \"failedCount\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991,\n \"description\": \"Runs whose evaluator scores failed.\"\n },\n \"avgScore\": {\n \"anyOf\": [\n {\n \"type\": \"number\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Average automated evaluator score.\"\n },\n \"createdAt\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"string\"\n }\n ]\n },\n \"completedAt\": {\n \"anyOf\": [\n {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"string\"\n }\n ]\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"version\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"runs\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\",\n \"description\": \"Run id created for the experiment.\"\n },\n \"status\": {\n \"type\": \"string\",\n \"description\": \"Current run status.\"\n },\n \"exampleId\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Dataset example id for the run.\"\n },\n \"exampleName\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Dataset example name for the run.\"\n },\n \"evalScore\": {\n \"anyOf\": [\n {\n \"type\": \"number\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Persisted weighted evaluator score.\"\n },\n \"evalPassed\": {\n \"anyOf\": [\n {\n \"type\": \"boolean\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Persisted aggregate evaluator verdict.\"\n },\n \"createdAt\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"string\"\n }\n ]\n },\n \"completedAt\": {\n \"anyOf\": [\n {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"string\"\n }\n ]\n },\n {\n \"type\": \"null\"\n }\n ]\n }\n },\n \"required\": [\n \"id\",\n \"status\",\n \"exampleId\",\n \"exampleName\",\n \"evalScore\",\n \"evalPassed\",\n \"createdAt\",\n \"completedAt\"\n ],\n \"additionalProperties\": false\n },\n \"description\": \"Runs created for dataset examples in this experiment.\"\n },\n \"resultsByRun\": {\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/EvalResult\"\n }\n },\n \"description\": \"Evaluator results keyed by run id.\"\n }\n },\n \"required\": [\n \"id\",\n \"automationId\",\n \"automationType\",\n \"status\",\n \"runCount\",\n \"completedCount\",\n \"passedCount\",\n \"failedCount\",\n \"avgScore\",\n \"createdAt\",\n \"completedAt\",\n \"version\",\n \"runs\",\n \"resultsByRun\"\n ],\n \"additionalProperties\": false,\n \"description\": \"Experiment batch detail.\"\n },\n \"EvalResult\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\",\n \"description\": \"Evaluator result id.\"\n },\n \"runId\": {\n \"type\": \"string\",\n \"description\": \"Run this score belongs to.\"\n },\n \"automationId\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Automation this score belongs to.\"\n },\n \"evaluatorName\": {\n \"type\": \"string\",\n \"description\": \"Evaluator name from configuration.\"\n },\n \"evaluatorType\": {\n \"type\": \"string\",\n \"description\": \"Evaluator implementation type.\"\n },\n \"score\": {\n \"anyOf\": [\n {\n \"type\": \"number\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Automated evaluator score. Do not confuse this with a human review verdict.\"\n },\n \"passed\": {\n \"anyOf\": [\n {\n \"type\": \"boolean\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Whether this evaluator passed.\"\n },\n \"label\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Optional evaluator label.\"\n },\n \"weight\": {\n \"anyOf\": [\n {\n \"type\": \"number\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Weight used in aggregate scoring.\"\n },\n \"passThreshold\": {\n \"anyOf\": [\n {\n \"type\": \"number\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Score threshold required for this evaluator to pass.\"\n },\n \"description\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Evaluator description.\"\n },\n \"details\": {\n \"anyOf\": [\n {},\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Evaluator-specific details.\"\n },\n \"error\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Evaluator error, when scoring failed.\"\n },\n \"createdAt\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"string\"\n }\n ]\n }\n },\n \"required\": [\n \"id\",\n \"runId\",\n \"automationId\",\n \"evaluatorName\",\n \"evaluatorType\",\n \"score\",\n \"passed\",\n \"label\",\n \"weight\",\n \"passThreshold\",\n \"description\",\n \"details\",\n \"error\",\n \"createdAt\"\n ],\n \"additionalProperties\": false,\n \"description\": \"Automated evaluator result for one run.\"\n },\n \"RunReviewHealthResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"timeRange\": {\n \"type\": \"object\",\n \"properties\": {\n \"from\": {\n \"type\": \"string\"\n },\n \"to\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"from\",\n \"to\"\n ],\n \"additionalProperties\": false\n },\n \"granularity\": {\n \"type\": \"object\",\n \"properties\": {\n \"bucket\": {\n \"type\": \"string\",\n \"enum\": [\n \"day\",\n \"week\",\n \"month\"\n ]\n },\n \"rollingWindow\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"minRollingReviews\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n }\n },\n \"required\": [\n \"bucket\",\n \"rollingWindow\",\n \"minRollingReviews\"\n ],\n \"additionalProperties\": false\n },\n \"summary\": {\n \"$ref\": \"#/components/schemas/RunReviewHealthSummary\"\n },\n \"buckets\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/RunReviewHealthBucket\"\n }\n },\n \"rolling\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/RunReviewHealthRollingPoint\"\n }\n }\n },\n \"required\": [\n \"timeRange\",\n \"granularity\",\n \"summary\",\n \"buckets\",\n \"rolling\"\n ],\n \"additionalProperties\": false\n },\n \"RunReviewHealthSummary\": {\n \"type\": \"object\",\n \"properties\": {\n \"totalRuns\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"reviewedRuns\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991,\n \"description\": \"Runs with a ranked verdict (`correct` or `incorrect`). Null verdict (nit) is excluded.\"\n },\n \"reviewCoverage\": {\n \"anyOf\": [\n {\n \"type\": \"number\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"correctReviews\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"incorrectReviews\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"nitReviews\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991,\n \"description\": \"Runs with a review row and null verdict (nit). Excluded from review coverage and accuracy.\"\n },\n \"reviewedCorrectness\": {\n \"anyOf\": [\n {\n \"type\": \"number\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"confidence\": {\n \"$ref\": \"#/components/schemas/RunReviewHealthConfidence\"\n }\n },\n \"required\": [\n \"totalRuns\",\n \"reviewedRuns\",\n \"reviewCoverage\",\n \"correctReviews\",\n \"incorrectReviews\",\n \"nitReviews\",\n \"reviewedCorrectness\",\n \"confidence\"\n ],\n \"additionalProperties\": false\n },\n \"RunReviewHealthConfidence\": {\n \"type\": \"object\",\n \"properties\": {\n \"lower\": {\n \"anyOf\": [\n {\n \"type\": \"number\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"upper\": {\n \"anyOf\": [\n {\n \"type\": \"number\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"method\": {\n \"type\": \"string\",\n \"const\": \"wilson\"\n }\n },\n \"required\": [\n \"lower\",\n \"upper\",\n \"method\"\n ],\n \"additionalProperties\": false,\n \"description\": \"Wilson score confidence interval for reviewed correctness. Null bounds mean there are no reviewed runs in the sample.\"\n },\n \"RunReviewHealthBucket\": {\n \"type\": \"object\",\n \"properties\": {\n \"start\": {\n \"type\": \"string\"\n },\n \"end\": {\n \"type\": \"string\"\n },\n \"totalRuns\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"reviewedRuns\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991,\n \"description\": \"Runs with a ranked verdict (`correct` or `incorrect`). Null verdict (nit) is excluded.\"\n },\n \"reviewCoverage\": {\n \"anyOf\": [\n {\n \"type\": \"number\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"correctReviews\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"incorrectReviews\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"nitReviews\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991,\n \"description\": \"Runs with a review row and null verdict (nit). Excluded from review coverage and accuracy.\"\n },\n \"reviewedCorrectness\": {\n \"anyOf\": [\n {\n \"type\": \"number\"\n },\n {\n \"type\": \"null\"\n }\n ]\n }\n },\n \"required\": [\n \"start\",\n \"end\",\n \"totalRuns\",\n \"reviewedRuns\",\n \"reviewCoverage\",\n \"correctReviews\",\n \"incorrectReviews\",\n \"nitReviews\",\n \"reviewedCorrectness\"\n ],\n \"additionalProperties\": false\n },\n \"RunReviewHealthRollingPoint\": {\n \"type\": \"object\",\n \"properties\": {\n \"at\": {\n \"type\": \"string\"\n },\n \"reviewedRuns\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991,\n \"description\": \"Runs with a ranked verdict (`correct` or `incorrect`). Null verdict (nit) is excluded.\"\n },\n \"correctReviews\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"reviewedCorrectness\": {\n \"type\": \"number\"\n },\n \"confidenceLower\": {\n \"type\": \"number\"\n },\n \"confidenceUpper\": {\n \"type\": \"number\"\n },\n \"totalRunsInWindow\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991,\n \"description\": \"Total production runs in the rolling window ending at this point.\"\n },\n \"reviewCoverage\": {\n \"type\": \"number\",\n \"description\": \"Share of runs in the rolling window that were reviewed (0-1). Uses the same window size as rolling accuracy, applied to all runs.\"\n }\n },\n \"required\": [\n \"at\",\n \"reviewedRuns\",\n \"correctReviews\",\n \"reviewedCorrectness\",\n \"confidenceLower\",\n \"confidenceUpper\",\n \"totalRunsInWindow\",\n \"reviewCoverage\"\n ],\n \"additionalProperties\": false\n },\n \"AutomationTriggersResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"automationId\": {\n \"type\": \"string\"\n },\n \"type\": {\n \"$ref\": \"#/components/schemas/AutomationType\"\n },\n \"triggers\": {\n \"$ref\": \"#/components/schemas/AutomationTriggerState\"\n }\n },\n \"required\": [\n \"automationId\",\n \"type\",\n \"triggers\"\n ],\n \"additionalProperties\": false\n },\n \"ListAutomationVersionsResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"data\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/AutomationVersion\"\n }\n },\n \"total\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"limit\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"offset\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n }\n },\n \"required\": [\n \"data\",\n \"total\",\n \"limit\",\n \"offset\"\n ],\n \"additionalProperties\": false\n },\n \"AutomationVersion\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\"\n },\n \"automationId\": {\n \"type\": \"string\"\n },\n \"version\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"sourceRef\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"isCurrent\": {\n \"type\": \"boolean\"\n },\n \"createdAt\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"string\"\n }\n ]\n }\n },\n \"required\": [\n \"id\",\n \"automationId\",\n \"version\"\n ],\n \"additionalProperties\": false\n },\n \"ListEmailServersResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"data\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/EmailServer\"\n }\n },\n \"total\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"limit\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"offset\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n }\n },\n \"required\": [\n \"data\",\n \"total\",\n \"limit\",\n \"offset\"\n ],\n \"additionalProperties\": false\n },\n \"EmailServer\": {\n \"oneOf\": [\n {\n \"$ref\": \"#/components/schemas/PublicResendEmailServer\"\n },\n {\n \"$ref\": \"#/components/schemas/PublicSmtpEmailServer\"\n }\n ],\n \"type\": \"object\",\n \"discriminator\": {\n \"propertyName\": \"transport\",\n \"mapping\": {\n \"resend\": \"#/components/schemas/PublicResendEmailServer\",\n \"smtp\": \"#/components/schemas/PublicSmtpEmailServer\"\n }\n }\n },\n \"PublicResendEmailServer\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\",\n \"maxLength\": 128,\n \"pattern\": \"^ems_[A-Za-z0-9_-]+$\"\n },\n \"name\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 128\n },\n \"enabled\": {\n \"type\": \"boolean\"\n },\n \"createdAt\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"string\"\n }\n ]\n },\n \"updatedAt\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"string\"\n }\n ]\n },\n \"transport\": {\n \"type\": \"string\",\n \"const\": \"resend\"\n },\n \"fromEmail\": {\n \"type\": \"string\",\n \"format\": \"email\",\n \"pattern\": \"^(?!\\\\.)(?!.*\\\\.\\\\.)([A-Za-z0-9_'+\\\\-\\\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\\\-]*\\\\.)+[A-Za-z]{2,}$\"\n },\n \"fromName\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 128\n },\n \"apiKeyConfigured\": {\n \"type\": \"boolean\",\n \"const\": true\n }\n },\n \"required\": [\n \"id\",\n \"name\",\n \"enabled\",\n \"createdAt\",\n \"updatedAt\",\n \"transport\",\n \"fromEmail\",\n \"fromName\",\n \"apiKeyConfigured\"\n ],\n \"additionalProperties\": false\n },\n \"PublicSmtpEmailServer\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\",\n \"maxLength\": 128,\n \"pattern\": \"^ems_[A-Za-z0-9_-]+$\"\n },\n \"name\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 128\n },\n \"enabled\": {\n \"type\": \"boolean\"\n },\n \"createdAt\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"string\"\n }\n ]\n },\n \"updatedAt\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"string\"\n }\n ]\n },\n \"transport\": {\n \"type\": \"string\",\n \"const\": \"smtp\"\n },\n \"fromEmail\": {\n \"type\": \"string\",\n \"format\": \"email\",\n \"pattern\": \"^(?!\\\\.)(?!.*\\\\.\\\\.)([A-Za-z0-9_'+\\\\-\\\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\\\-]*\\\\.)+[A-Za-z]{2,}$\"\n },\n \"fromName\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 128\n },\n \"host\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"maxLength\": 253\n },\n \"port\": {\n \"type\": \"integer\",\n \"minimum\": 1,\n \"maximum\": 65535\n },\n \"security\": {\n \"type\": \"string\",\n \"enum\": [\n \"starttls\",\n \"tls\",\n \"none\"\n ]\n },\n \"username\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"passwordConfigured\": {\n \"type\": \"boolean\"\n },\n \"caPemConfigured\": {\n \"type\": \"boolean\"\n }\n },\n \"required\": [\n \"id\",\n \"name\",\n \"enabled\",\n \"createdAt\",\n \"updatedAt\",\n \"transport\",\n \"fromEmail\",\n \"fromName\",\n \"host\",\n \"port\",\n \"security\",\n \"username\",\n \"passwordConfigured\",\n \"caPemConfigured\"\n ],\n \"additionalProperties\": false\n },\n \"DeleteEmailServerResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"deleted\": {\n \"type\": \"boolean\",\n \"const\": true\n },\n \"id\": {\n \"type\": \"string\",\n \"maxLength\": 128,\n \"pattern\": \"^ems_[A-Za-z0-9_-]+$\"\n }\n },\n \"required\": [\n \"deleted\",\n \"id\"\n ],\n \"additionalProperties\": false\n },\n \"TestEmailServerResponse\": {\n \"oneOf\": [\n {\n \"type\": \"object\",\n \"properties\": {\n \"ok\": {\n \"type\": \"boolean\",\n \"const\": true\n },\n \"transport\": {\n \"type\": \"string\",\n \"enum\": [\n \"resend\",\n \"smtp\"\n ]\n },\n \"messageId\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"required\": [\n \"ok\",\n \"transport\",\n \"messageId\"\n ],\n \"additionalProperties\": false\n },\n {\n \"type\": \"object\",\n \"properties\": {\n \"ok\": {\n \"type\": \"boolean\",\n \"const\": false\n },\n \"error\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"required\": [\n \"ok\",\n \"error\"\n ],\n \"additionalProperties\": false\n }\n ],\n \"type\": \"object\"\n },\n \"ExperimentRef\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\"\n },\n \"automationId\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"id\",\n \"automationId\"\n ],\n \"additionalProperties\": false\n },\n \"File\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\"\n },\n \"filename\": {\n \"type\": \"string\"\n },\n \"contentType\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"size\": {\n \"anyOf\": [\n {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"purpose\": {\n \"description\": \"Optional lifecycle marker. `run-input` marks a retry-safe temporary run pre-upload reaped after 24 hours. `builder-attachment` marks a Studio builder intermediary (any MIME) with the same TTL. Omitted/null means a durable reusable file.\",\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"createdAt\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"string\"\n }\n ]\n }\n },\n \"required\": [\n \"id\",\n \"filename\",\n \"contentType\",\n \"size\",\n \"createdAt\"\n ],\n \"additionalProperties\": false\n },\n \"DeleteFileResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"deleted\": {\n \"type\": \"boolean\"\n }\n },\n \"required\": [\n \"deleted\"\n ],\n \"additionalProperties\": false\n },\n \"PresignedFileUploadSession\": {\n \"type\": \"object\",\n \"properties\": {\n \"transport\": {\n \"type\": \"string\",\n \"const\": \"presigned-put\"\n },\n \"uploadId\": {\n \"type\": \"string\"\n },\n \"fileId\": {\n \"type\": \"string\"\n },\n \"url\": {\n \"type\": \"string\",\n \"format\": \"uri\"\n },\n \"headers\": {\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {\n \"type\": \"string\"\n }\n },\n \"expiresAt\": {\n \"type\": \"string\",\n \"format\": \"date-time\",\n \"pattern\": \"^(?:(?:\\\\d\\\\d[2468][048]|\\\\d\\\\d[13579][26]|\\\\d\\\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\\\d|30)|(?:02)-(?:0[1-9]|1\\\\d|2[0-8])))T(?:(?:[01]\\\\d|2[0-3]):[0-5]\\\\d(?::[0-5]\\\\d(?:\\\\.\\\\d+)?)?(?:Z))$\"\n },\n \"maxFileSizeBytes\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n }\n },\n \"required\": [\n \"transport\",\n \"uploadId\",\n \"fileId\",\n \"url\",\n \"headers\",\n \"expiresAt\",\n \"maxFileSizeBytes\"\n ],\n \"additionalProperties\": false\n },\n \"PresignedMultipartFileUploadSession\": {\n \"type\": \"object\",\n \"properties\": {\n \"transport\": {\n \"type\": \"string\",\n \"const\": \"presigned-multipart\"\n },\n \"uploadId\": {\n \"type\": \"string\"\n },\n \"fileId\": {\n \"type\": \"string\"\n },\n \"partSizeBytes\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"partCount\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"partsUrl\": {\n \"type\": \"string\"\n },\n \"completeUrl\": {\n \"type\": \"string\"\n },\n \"expiresAt\": {\n \"type\": \"string\",\n \"format\": \"date-time\",\n \"pattern\": \"^(?:(?:\\\\d\\\\d[2468][048]|\\\\d\\\\d[13579][26]|\\\\d\\\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\\\d|30)|(?:02)-(?:0[1-9]|1\\\\d|2[0-8])))T(?:(?:[01]\\\\d|2[0-3]):[0-5]\\\\d(?::[0-5]\\\\d(?:\\\\.\\\\d+)?)?(?:Z))$\"\n },\n \"maxFileSizeBytes\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n }\n },\n \"required\": [\n \"transport\",\n \"uploadId\",\n \"fileId\",\n \"partSizeBytes\",\n \"partCount\",\n \"partsUrl\",\n \"completeUrl\",\n \"expiresAt\",\n \"maxFileSizeBytes\"\n ],\n \"additionalProperties\": false\n },\n \"MultipartFileUploadFallback\": {\n \"type\": \"object\",\n \"properties\": {\n \"transport\": {\n \"type\": \"string\",\n \"const\": \"multipart\"\n },\n \"url\": {\n \"type\": \"string\"\n },\n \"maxFileSizeBytes\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n }\n },\n \"required\": [\n \"transport\",\n \"url\",\n \"maxFileSizeBytes\"\n ],\n \"additionalProperties\": false\n },\n \"FileUploadSession\": {\n \"type\": \"object\",\n \"properties\": {\n \"uploadId\": {\n \"type\": \"string\"\n },\n \"fileId\": {\n \"type\": \"string\"\n },\n \"transport\": {\n \"type\": \"string\",\n \"enum\": [\n \"presigned-put\",\n \"presigned-multipart\"\n ]\n },\n \"status\": {\n \"type\": \"string\"\n },\n \"expiresAt\": {\n \"type\": \"string\",\n \"format\": \"date-time\",\n \"pattern\": \"^(?:(?:\\\\d\\\\d[2468][048]|\\\\d\\\\d[13579][26]|\\\\d\\\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\\\d|30)|(?:02)-(?:0[1-9]|1\\\\d|2[0-8])))T(?:(?:[01]\\\\d|2[0-3]):[0-5]\\\\d(?::[0-5]\\\\d(?:\\\\.\\\\d+)?)?(?:Z))$\"\n },\n \"partSizeBytes\": {\n \"anyOf\": [\n {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"partCount\": {\n \"anyOf\": [\n {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"parts\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"partNumber\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"size\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"etag\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"partNumber\",\n \"etag\"\n ],\n \"additionalProperties\": false\n }\n }\n },\n \"required\": [\n \"uploadId\",\n \"fileId\",\n \"transport\",\n \"status\",\n \"expiresAt\"\n ],\n \"additionalProperties\": false\n },\n \"AbortFileUploadResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"aborted\": {\n \"type\": \"boolean\",\n \"const\": true\n }\n },\n \"required\": [\n \"aborted\"\n ],\n \"additionalProperties\": false\n },\n \"ListFileUploadPartsResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"transport\": {\n \"type\": \"string\",\n \"const\": \"presigned-multipart\"\n },\n \"uploadId\": {\n \"type\": \"string\"\n },\n \"fileId\": {\n \"type\": \"string\"\n },\n \"partSizeBytes\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"partCount\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"expiresAt\": {\n \"type\": \"string\",\n \"format\": \"date-time\",\n \"pattern\": \"^(?:(?:\\\\d\\\\d[2468][048]|\\\\d\\\\d[13579][26]|\\\\d\\\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\\\d|30)|(?:02)-(?:0[1-9]|1\\\\d|2[0-8])))T(?:(?:[01]\\\\d|2[0-3]):[0-5]\\\\d(?::[0-5]\\\\d(?:\\\\.\\\\d+)?)?(?:Z))$\"\n },\n \"parts\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"partNumber\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"size\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"etag\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"partNumber\",\n \"etag\"\n ],\n \"additionalProperties\": false\n }\n }\n },\n \"required\": [\n \"transport\",\n \"uploadId\",\n \"fileId\",\n \"partSizeBytes\",\n \"partCount\",\n \"expiresAt\",\n \"parts\"\n ],\n \"additionalProperties\": false\n },\n \"PresignFileUploadPartResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"transport\": {\n \"type\": \"string\",\n \"const\": \"presigned-multipart\"\n },\n \"partNumber\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"url\": {\n \"type\": \"string\",\n \"format\": \"uri\"\n },\n \"headers\": {\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {\n \"type\": \"string\"\n }\n },\n \"expiresAt\": {\n \"type\": \"string\",\n \"format\": \"date-time\",\n \"pattern\": \"^(?:(?:\\\\d\\\\d[2468][048]|\\\\d\\\\d[13579][26]|\\\\d\\\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\\\d|30)|(?:02)-(?:0[1-9]|1\\\\d|2[0-8])))T(?:(?:[01]\\\\d|2[0-3]):[0-5]\\\\d(?::[0-5]\\\\d(?:\\\\.\\\\d+)?)?(?:Z))$\"\n },\n \"partSizeBytes\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n }\n },\n \"required\": [\n \"transport\",\n \"partNumber\",\n \"url\",\n \"headers\",\n \"expiresAt\",\n \"partSizeBytes\"\n ],\n \"additionalProperties\": false\n },\n \"ListFoldersResponse\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/Folder\"\n }\n },\n \"Folder\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\"\n },\n \"parentId\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"type\": {\n \"$ref\": \"#/components/schemas/FolderType\"\n },\n \"name\": {\n \"type\": \"string\"\n },\n \"createdAt\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"string\"\n }\n ]\n },\n \"childCount\": {\n \"description\": \"Direct subfolder count. Present on tree listings.\",\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"workflowCount\": {\n \"description\": \"Workflows filed directly in this folder. Present on workflow-tree listings.\",\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n \"previewItems\": {\n \"description\": \"Up to a handful of item names — subfolders first, then workflows — for a peek at folder contents. Present on workflow-tree listings.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n },\n \"kind\": {\n \"type\": \"string\",\n \"enum\": [\n \"folder\",\n \"workflow\"\n ]\n }\n },\n \"required\": [\n \"name\",\n \"kind\"\n ],\n \"additionalProperties\": false\n }\n }\n },\n \"required\": [\n \"id\",\n \"parentId\",\n \"type\",\n \"name\",\n \"createdAt\"\n ],\n \"additionalProperties\": false\n },\n \"DeleteFolderResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"deleted\": {\n \"type\": \"boolean\",\n \"const\": true\n },\n \"id\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"deleted\",\n \"id\"\n ],\n \"additionalProperties\": false\n },\n \"HumanReviewListResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"tasks\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"executionId\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"automationId\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"automationName\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"sourceKind\": {\n \"type\": \"string\",\n \"enum\": [\n \"workflow_step\",\n \"agent_tool\"\n ]\n },\n \"sourceLabel\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"status\": {\n \"type\": \"string\",\n \"enum\": [\n \"pending\",\n \"approved\",\n \"rejected\",\n \"cancelled\"\n ]\n },\n \"requiredCount\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 9007199254740991\n },\n \"confirmedCount\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 9007199254740991\n },\n \"version\": {\n \"type\": \"integer\",\n \"exclusiveMinimum\": 0,\n \"maximum\": 9007199254740991\n },\n \"createdAt\": {\n \"type\": \"string\"\n },\n \"updatedAt\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"id\",\n \"executionId\",\n \"automationId\",\n \"automationName\",\n \"sourceKind\",\n \"sourceLabel\",\n \"status\",\n \"requiredCount\",\n \"confirmedCount\",\n \"version\",\n \"createdAt\",\n \"updatedAt\"\n ],\n \"additionalProperties\": false\n }\n },\n \"nextCursor\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n }\n },\n \"required\": [\n \"tasks\",\n \"nextCursor\"\n ],\n \"additionalProperties\": false\n },\n \"HumanReviewTaskResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"task\": {\n \"$ref\": \"#/components/schemas/HumanReviewTaskDetail\"\n }\n },\n \"required\": [\n \"task\"\n ],\n \"additionalProperties\": false\n },\n \"HumanReviewTaskDetail\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"executionId\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"automationId\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"automationName\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"sourceKind\": {\n \"type\": \"string\",\n \"enum\": [\n \"workflow_step\",\n \"agent_tool\"\n ]\n },\n \"sourceLabel\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"status\": {\n \"type\": \"string\",\n \"enum\": [\n \"pending\",\n \"approved\",\n \"rejected\",\n \"cancelled\"\n ]\n },\n \"requiredCount\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 9007199254740991\n },\n \"confirmedCount\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 9007199254740991\n },\n \"version\": {\n \"type\": \"integer\",\n \"exclusiveMinimum\": 0,\n \"maximum\": 9007199254740991\n },\n \"createdAt\": {\n \"type\": \"string\"\n },\n \"updatedAt\": {\n \"type\": \"string\"\n },\n \"files\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"fileId\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"filename\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"mimeType\": {\n \"type\": \"string\"\n },\n \"size\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 9007199254740991\n },\n \"fieldName\": {\n \"type\": \"string\"\n },\n \"artifactPath\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"role\": {\n \"description\": \"run_input for authorized run input files; attachment for extra current-run files. Omitted on historical tasks and inferred at read time.\",\n \"type\": \"string\",\n \"enum\": [\n \"run_input\",\n \"attachment\"\n ]\n }\n },\n \"required\": [\n \"fileId\",\n \"filename\",\n \"artifactPath\"\n ],\n \"additionalProperties\": false\n }\n },\n \"input\": {\n \"anyOf\": [\n {\n \"oneOf\": [\n {\n \"type\": \"object\",\n \"properties\": {\n \"status\": {\n \"type\": \"string\",\n \"const\": \"available\"\n },\n \"data\": {\n \"anyOf\": [\n {\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {}\n },\n {\n \"type\": \"array\",\n \"items\": {}\n }\n ]\n }\n },\n \"required\": [\n \"status\",\n \"data\"\n ],\n \"additionalProperties\": false\n },\n {\n \"type\": \"object\",\n \"properties\": {\n \"status\": {\n \"type\": \"string\",\n \"const\": \"omitted_too_large\"\n }\n },\n \"required\": [\n \"status\"\n ],\n \"additionalProperties\": false\n }\n ],\n \"type\": \"object\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Non-file trigger input derived at read time. Null when every field is a file or external source id. omitted_too_large when the projection exceeds the review data byte limit.\"\n },\n \"machineData\": {\n \"anyOf\": [\n {\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {}\n },\n {\n \"type\": \"array\",\n \"items\": {}\n }\n ]\n },\n \"draftData\": {\n \"anyOf\": [\n {\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {}\n },\n {\n \"type\": \"array\",\n \"items\": {}\n }\n ]\n },\n \"schema\": {\n \"anyOf\": [\n {\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {}\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"fieldMetadata\": {\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {\n \"type\": \"object\",\n \"properties\": {\n \"confidence\": {\n \"description\": \"Producer-supplied confidence: 0–1 numeric (legacy) or categorical low|medium|high from ai.extract grounding. Not calibrated by Eigenpal.\",\n \"anyOf\": [\n {\n \"type\": \"number\",\n \"minimum\": 0,\n \"maximum\": 1\n },\n {\n \"type\": \"string\",\n \"enum\": [\n \"low\",\n \"medium\",\n \"high\"\n ]\n },\n {\n \"type\": \"string\",\n \"minLength\": 1\n }\n ]\n },\n \"label\": {\n \"description\": \"Short label shown in the review UI\",\n \"type\": \"string\",\n \"maxLength\": 500\n },\n \"description\": {\n \"description\": \"Longer reviewer guidance for this field\",\n \"type\": \"string\",\n \"maxLength\": 5000\n },\n \"review\": {\n \"description\": \"Legacy per-field override kept for existing tasks. Prefer selection.fields.review.\",\n \"default\": \"auto\",\n \"type\": \"string\",\n \"enum\": [\n \"auto\",\n \"always\",\n \"never\"\n ]\n },\n \"display\": {\n \"description\": \"Opaque display metadata preserved for the review UI\",\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {}\n }\n },\n \"additionalProperties\": false\n }\n },\n \"requiredPaths\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n },\n \"selectionReasons\": {\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {\n \"type\": \"string\",\n \"enum\": [\n \"always\",\n \"explicit\",\n \"low_confidence\",\n \"missing_confidence\",\n \"all\",\n \"reviewer_edit\",\n \"threshold_met\",\n \"never\",\n \"excluded\",\n \"unmatched\",\n \"missing_confidence_skip\"\n ]\n }\n },\n \"decisions\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"path\": {\n \"type\": \"string\"\n },\n \"originalValue\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"number\"\n },\n {\n \"type\": \"boolean\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"currentValue\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"number\"\n },\n {\n \"type\": \"boolean\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"required\": {\n \"type\": \"boolean\"\n },\n \"reason\": {\n \"type\": \"string\",\n \"enum\": [\n \"always\",\n \"explicit\",\n \"low_confidence\",\n \"missing_confidence\",\n \"all\",\n \"reviewer_edit\",\n \"threshold_met\",\n \"never\",\n \"excluded\",\n \"unmatched\",\n \"missing_confidence_skip\"\n ]\n },\n \"confirmedBy\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"confirmedAt\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"version\": {\n \"type\": \"integer\",\n \"exclusiveMinimum\": 0,\n \"maximum\": 9007199254740991\n }\n },\n \"required\": [\n \"id\",\n \"path\",\n \"originalValue\",\n \"currentValue\",\n \"required\",\n \"reason\",\n \"confirmedBy\",\n \"confirmedAt\",\n \"version\"\n ],\n \"additionalProperties\": false\n }\n },\n \"instructions\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"completedBy\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"completedAt\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"outcomeReason\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"lineage\": {\n \"description\": \"Optional lineage@1 document resolved from the extract sidecar. Omitted when missing or unreadable. Validate with @openparser/lineage.\",\n \"type\": \"object\",\n \"additionalProperties\": true\n },\n \"parsedDocument\": {\n \"description\": \"Optional ParsedDocument resolved from the extract sidecar. Omitted when missing or unreadable. Validate with @openparser/schema.\",\n \"type\": \"object\",\n \"additionalProperties\": true\n }\n },\n \"required\": [\n \"id\",\n \"executionId\",\n \"automationId\",\n \"automationName\",\n \"sourceKind\",\n \"sourceLabel\",\n \"status\",\n \"requiredCount\",\n \"confirmedCount\",\n \"version\",\n \"createdAt\",\n \"updatedAt\",\n \"files\",\n \"input\",\n \"machineData\",\n \"draftData\",\n \"schema\",\n \"fieldMetadata\",\n \"requiredPaths\",\n \"selectionReasons\",\n \"decisions\",\n \"instructions\",\n \"completedBy\",\n \"completedAt\",\n \"outcomeReason\"\n ],\n \"additionalProperties\": false\n },\n \"HumanReviewApproveResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"task\": {\n \"$ref\": \"#/components/schemas/HumanReviewTaskDetail\"\n }\n },\n \"required\": [\n \"task\"\n ],\n \"additionalProperties\": false\n },\n \"HumanReviewFieldResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"task\": {\n \"$ref\": \"#/components/schemas/HumanReviewTaskDetail\"\n }\n },\n \"required\": [\n \"task\"\n ],\n \"additionalProperties\": false\n },\n \"HumanReviewRejectResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"task\": {\n \"$ref\": \"#/components/schemas/HumanReviewTaskDetail\"\n }\n },\n \"required\": [\n \"task\"\n ],\n \"additionalProperties\": false\n },\n \"ListModelsResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"data\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/PublicModel\"\n }\n },\n \"total\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 9007199254740991\n }\n },\n \"required\": [\n \"data\",\n \"total\"\n ],\n \"additionalProperties\": false\n },\n \"PublicModel\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\"\n },\n \"kind\": {\n \"type\": \"string\",\n \"enum\": [\n \"llm\",\n \"ocr\"\n ]\n },\n \"provider\": {\n \"type\": \"string\"\n },\n \"label\": {\n \"type\": \"string\"\n },\n \"capabilities\": {\n \"minItems\": 1,\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\",\n \"enum\": [\n \"text\",\n \"vision\",\n \"ocr\"\n ]\n }\n },\n \"configured\": {\n \"type\": \"boolean\"\n },\n \"available\": {\n \"type\": \"boolean\"\n },\n \"health\": {\n \"type\": \"string\",\n \"enum\": [\n \"configured\",\n \"unconfigured\",\n \"unknown\"\n ],\n \"description\": \"Configuration state only: `configured` means credentials are present in this environment; `unconfigured` means the catalog entry exists but credentials are missing. This list does not probe live providers, so it never reports healthy/degraded/outage. `unknown` is reserved and is not emitted by this endpoint.\"\n },\n \"defaultFor\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\",\n \"enum\": [\n \"text\",\n \"vision\",\n \"ocr\"\n ]\n }\n },\n \"location\": {\n \"type\": \"string\",\n \"enum\": [\n \"local\",\n \"hosted\"\n ],\n \"description\": \"`local` means on-prem / no cloud provider egress (`local: true` or tesseract). `hosted` means the provider is a cloud API. Endpoints are never returned.\"\n },\n \"limits\": {\n \"$ref\": \"#/components/schemas/PublicModelLimits\"\n },\n \"cost\": {\n \"description\": \"Static Eigenpal credit rates when known without a live vendor catalog. Omitted for OpenParser OCR and for LLMs (token prices are not part of this catalog).\",\n \"$ref\": \"#/components/schemas/PublicModelCost\"\n },\n \"aliases\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n },\n \"tags\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n },\n \"capabilityRank\": {\n \"description\": \"Optional picker rank. Higher is more capable. Omitted on catalog rows that do not set it. Does not change role defaults.\",\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n }\n },\n \"required\": [\n \"id\",\n \"kind\",\n \"provider\",\n \"label\",\n \"capabilities\",\n \"configured\",\n \"available\",\n \"health\",\n \"defaultFor\",\n \"location\",\n \"aliases\",\n \"tags\"\n ],\n \"additionalProperties\": false\n },\n \"PublicModelLimits\": {\n \"type\": \"object\",\n \"properties\": {\n \"requestTimeoutSeconds\": {\n \"type\": \"integer\",\n \"exclusiveMinimum\": 0,\n \"maximum\": 9007199254740991\n },\n \"maxConcurrentRequests\": {\n \"type\": \"integer\",\n \"exclusiveMinimum\": 0,\n \"maximum\": 9007199254740991\n }\n },\n \"additionalProperties\": false\n },\n \"PublicModelCost\": {\n \"type\": \"object\",\n \"properties\": {\n \"creditsPerPage\": {\n \"type\": \"number\",\n \"minimum\": 0\n },\n \"unit\": {\n \"type\": \"string\",\n \"const\": \"credits\"\n }\n },\n \"required\": [\n \"unit\"\n ],\n \"additionalProperties\": false\n },\n \"RunsListResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"runs\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/RunListItem\"\n }\n },\n \"nextCursor\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n }\n },\n \"required\": [\n \"runs\",\n \"nextCursor\"\n ],\n \"additionalProperties\": false\n },\n \"RunListItem\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\"\n },\n \"type\": {\n \"type\": \"string\",\n \"enum\": [\n \"workflow\",\n \"agent\"\n ]\n },\n \"finished\": {\n \"type\": \"boolean\",\n \"description\": \"True when the run has reached a terminal status.\"\n },\n \"sampleRank\": {\n \"type\": \"number\",\n \"minimum\": 0,\n \"maximum\": 1,\n \"description\": \"Deterministic pseudo-random rank in [0, 1) for this run within the tenant. Use with a sample rate threshold to review a stable subset.\"\n },\n \"parentExecutionId\": {\n \"description\": \"Parent run id when this run was started by an invoke-workflow step. Omitted for top-level runs.\",\n \"type\": \"string\"\n },\n \"timing\": {\n \"$ref\": \"#/components/schemas/RunTiming\"\n },\n \"source\": {\n \"$ref\": \"#/components/schemas/RunSource\"\n },\n \"trigger\": {\n \"$ref\": \"#/components/schemas/RunTrigger\"\n },\n \"eval\": {\n \"description\": \"Present only on eval-scoped runs. Omitted otherwise.\",\n \"$ref\": \"#/components/schemas/RunEval\"\n },\n \"error\": {\n \"description\": \"Terminal failure message. Present on terminal runs; null when the run succeeded. Absent while the run is still in flight.\",\n \"$ref\": \"#/components/schemas/RunError\"\n },\n \"execution\": {\n \"$ref\": \"#/components/schemas/RunExecutionMeta\"\n }\n },\n \"required\": [\n \"id\",\n \"type\",\n \"finished\",\n \"sampleRank\",\n \"timing\",\n \"source\",\n \"trigger\",\n \"execution\"\n ],\n \"additionalProperties\": false\n },\n \"RunTiming\": {\n \"type\": \"object\",\n \"properties\": {\n \"createdAt\": {\n \"type\": \"string\"\n },\n \"startedAt\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"completedAt\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"durationMs\": {\n \"anyOf\": [\n {\n \"type\": \"number\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"cancelRequestedAt\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"When the user requested cancel; status may still be `running` until the worker stops.\"\n }\n },\n \"required\": [\n \"createdAt\",\n \"startedAt\",\n \"completedAt\",\n \"durationMs\",\n \"cancelRequestedAt\"\n ],\n \"additionalProperties\": false\n },\n \"RunSource\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\",\n \"description\": \"Owning workflow id or agent id.\"\n },\n \"name\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"version\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Workflow version label (workflow runs only).\"\n },\n \"versionId\": {\n \"description\": \"Captured workflow version id (workflow runs only).\",\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"slug\": {\n \"description\": \"Agent slug (agent runs only).\",\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"model\": {\n \"description\": \"LLM model used (agent runs only).\",\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"git\": {\n \"description\": \"Git provenance (agent runs only).\",\n \"anyOf\": [\n {\n \"$ref\": \"#/components/schemas/RunSourceGit\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"implementationAvailable\": {\n \"description\": \"Whether the live workflow/agent implementation still exists (`GET /api/v1/runs/:id` detail only).\",\n \"type\": \"boolean\"\n },\n \"automationFound\": {\n \"description\": \"Whether the owning automation registry row still exists (`GET /api/v1/runs/:id` detail only).\",\n \"type\": \"boolean\"\n },\n \"currentVersion\": {\n \"description\": \"Current released workflow version label when the source is live (`GET /api/v1/runs/:id` detail only).\",\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n }\n },\n \"required\": [\n \"id\",\n \"name\",\n \"version\"\n ],\n \"additionalProperties\": false\n },\n \"RunSourceGit\": {\n \"type\": \"object\",\n \"properties\": {\n \"requestedRef\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"resolvedRef\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"resolvedTag\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"commitSha\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n }\n },\n \"required\": [\n \"requestedRef\",\n \"resolvedRef\",\n \"resolvedTag\",\n \"commitSha\"\n ],\n \"additionalProperties\": false\n },\n \"RunTrigger\": {\n \"type\": \"object\",\n \"properties\": {\n \"type\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"by\": {\n \"anyOf\": [\n {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\"\n },\n \"name\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"email\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"id\",\n \"name\",\n \"email\"\n ],\n \"additionalProperties\": false\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"email\": {\n \"description\": \"Inbound email trigger details (agent runs, `expand=input` not required).\"\n }\n },\n \"required\": [\n \"type\",\n \"by\"\n ],\n \"additionalProperties\": false\n },\n \"RunEval\": {\n \"type\": \"object\",\n \"properties\": {\n \"example\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Eval example label (agent example name or workflow example id).\"\n },\n \"exampleId\": {\n \"description\": \"Workflow eval example folder id (workflow runs only).\",\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"score\": {\n \"anyOf\": [\n {\n \"type\": \"number\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"passed\": {\n \"anyOf\": [\n {\n \"type\": \"boolean\"\n },\n {\n \"type\": \"null\"\n }\n ]\n }\n },\n \"required\": [\n \"example\",\n \"score\",\n \"passed\"\n ],\n \"additionalProperties\": false\n },\n \"RunError\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"RunExecutionMeta\": {\n \"type\": \"object\",\n \"properties\": {\n \"status\": {\n \"description\": \"Status of this run. `retry.nextRun.status` is a later retry, not this run.\",\n \"$ref\": \"#/components/schemas/ExecutionStatus\"\n },\n \"schemaValid\": {\n \"anyOf\": [\n {\n \"type\": \"boolean\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Whether the completed output matched the workflow or agent output schema.\"\n },\n \"batchId\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Experiment batch id when the run is part of a batch.\"\n },\n \"retry\": {\n \"$ref\": \"#/components/schemas/RunExecutionRetry\"\n },\n \"review\": {\n \"description\": \"Lightweight review state for run list rows.\",\n \"anyOf\": [\n {\n \"$ref\": \"#/components/schemas/RunReviewSummary\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"humanReview\": {\n \"description\": \"Pending in-flight human review when the run is waiting on a reviewer.\",\n \"anyOf\": [\n {\n \"$ref\": \"#/components/schemas/RunHumanReviewSummary\"\n },\n {\n \"type\": \"null\"\n }\n ]\n }\n },\n \"required\": [\n \"status\",\n \"schemaValid\",\n \"batchId\",\n \"retry\"\n ],\n \"additionalProperties\": false\n },\n \"ExecutionStatus\": {\n \"type\": \"string\",\n \"enum\": [\n \"created\",\n \"pending\",\n \"running\",\n \"waiting\",\n \"finalizing\",\n \"completed\",\n \"failed\",\n \"cancelled\",\n \"rejected\"\n ]\n },\n \"RunExecutionRetry\": {\n \"type\": \"object\",\n \"properties\": {\n \"number\": {\n \"type\": \"number\",\n \"description\": \"Retry attempt index (0 = original run).\"\n },\n \"previousRunId\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Run id of the prior attempt in the retry chain.\"\n },\n \"nextRun\": {\n \"anyOf\": [\n {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\"\n },\n \"status\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"id\",\n \"status\"\n ],\n \"additionalProperties\": false\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Retry run spawned from this run, if any. Present on list and detail without `expand`. `status` here is the later retry, not this run.\"\n }\n },\n \"required\": [\n \"number\",\n \"previousRunId\",\n \"nextRun\"\n ],\n \"additionalProperties\": false\n },\n \"RunReviewSummary\": {\n \"type\": \"object\",\n \"properties\": {\n \"verdict\": {\n \"anyOf\": [\n {\n \"type\": \"string\",\n \"enum\": [\n \"correct\",\n \"incorrect\"\n ]\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"status\": {\n \"type\": \"string\",\n \"enum\": [\n \"open\",\n \"closed\",\n \"wont_fix\"\n ]\n },\n \"hasNote\": {\n \"type\": \"boolean\",\n \"description\": \"True when review notes were left.\"\n },\n \"correctionCount\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991,\n \"description\": \"Number of field/file corrections.\"\n }\n },\n \"required\": [\n \"verdict\",\n \"status\",\n \"hasNote\",\n \"correctionCount\"\n ],\n \"additionalProperties\": false\n },\n \"RunHumanReviewSummary\": {\n \"type\": \"object\",\n \"properties\": {\n \"taskId\": {\n \"type\": \"string\"\n },\n \"sourceKind\": {\n \"type\": \"string\",\n \"enum\": [\n \"workflow_step\",\n \"agent_tool\"\n ]\n },\n \"sourceLabel\": {\n \"type\": \"string\"\n },\n \"status\": {\n \"type\": \"string\",\n \"const\": \"pending\"\n },\n \"requiredCount\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 9007199254740991\n },\n \"confirmedCount\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 9007199254740991\n },\n \"version\": {\n \"type\": \"integer\",\n \"exclusiveMinimum\": 0,\n \"maximum\": 9007199254740991\n }\n },\n \"required\": [\n \"taskId\",\n \"sourceKind\",\n \"sourceLabel\",\n \"status\",\n \"requiredCount\",\n \"confirmedCount\",\n \"version\"\n ],\n \"additionalProperties\": false\n },\n \"Run\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\"\n },\n \"type\": {\n \"type\": \"string\",\n \"enum\": [\n \"workflow\",\n \"agent\"\n ]\n },\n \"finished\": {\n \"type\": \"boolean\",\n \"description\": \"True when the run has reached a terminal status.\"\n },\n \"sampleRank\": {\n \"type\": \"number\",\n \"minimum\": 0,\n \"maximum\": 1,\n \"description\": \"Deterministic pseudo-random rank in [0, 1) for this run within the tenant. Use with a sample rate threshold to review a stable subset.\"\n },\n \"parentExecutionId\": {\n \"description\": \"Parent run id when this run was started by an invoke-workflow step. Omitted for top-level runs.\",\n \"type\": \"string\"\n },\n \"timing\": {\n \"$ref\": \"#/components/schemas/RunTiming\"\n },\n \"source\": {\n \"$ref\": \"#/components/schemas/RunSource\"\n },\n \"trigger\": {\n \"$ref\": \"#/components/schemas/RunTrigger\"\n },\n \"eval\": {\n \"description\": \"Present only on eval-scoped runs. Omitted otherwise.\",\n \"$ref\": \"#/components/schemas/RunEval\"\n },\n \"output\": {\n \"description\": \"Completed runs only. Per-automation business result — not a generic schema. Absent until the run completes.\",\n \"anyOf\": [\n {\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {}\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"files\": {\n \"description\": \"Completed runs only. Download with GET /api/v1/runs/:id/artifacts/:path. Absent until the run completes.\",\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/RunArtifact\"\n }\n },\n \"error\": {\n \"description\": \"Terminal failure message. Present on terminal runs; null when the run succeeded. Absent while the run is still in flight.\",\n \"$ref\": \"#/components/schemas/RunError\"\n },\n \"input\": {\n \"description\": \"Present only with `expand=input`.\",\n \"$ref\": \"#/components/schemas/RunInput\"\n },\n \"usage\": {\n \"description\": \"Present only with `expand=usage`. Null for old runs without telemetry.\",\n \"anyOf\": [\n {\n \"$ref\": \"#/components/schemas/RunUsage\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"execution\": {\n \"anyOf\": [\n {\n \"$ref\": \"#/components/schemas/RunExecutionMeta\"\n },\n {\n \"$ref\": \"#/components/schemas/RunExecution\"\n }\n ],\n \"description\": \"Slim execution metadata always present (`status`, `schemaValid`, `batchId`, `retry`). Pass `expand=execution` to replace with full RunExecution (WorkflowRunExecution or AgentRunExecution depending on run type).\"\n },\n \"debug\": {\n \"description\": \"Present only with `expand=debug`.\",\n \"$ref\": \"#/components/schemas/RunDebug\"\n }\n },\n \"required\": [\n \"id\",\n \"type\",\n \"finished\",\n \"sampleRank\",\n \"timing\",\n \"source\",\n \"trigger\",\n \"execution\"\n ],\n \"additionalProperties\": false,\n \"example\": {\n \"id\": \"wfx_01HZXEXAMPLE\",\n \"type\": \"workflow\",\n \"finished\": true,\n \"sampleRank\": 0.42,\n \"timing\": {\n \"createdAt\": \"2026-01-15T10:00:00.000Z\",\n \"startedAt\": \"2026-01-15T10:00:01.000Z\",\n \"completedAt\": \"2026-01-15T10:00:08.000Z\",\n \"durationMs\": 7000,\n \"cancelRequestedAt\": null\n },\n \"source\": {\n \"id\": \"wf_invoice\",\n \"name\": \"Invoice extraction\",\n \"version\": \"3\",\n \"versionId\": \"wfh_3\"\n },\n \"trigger\": {\n \"type\": \"api\",\n \"by\": null\n },\n \"output\": {\n \"vendor\": \"Acme\",\n \"total\": 149.5\n },\n \"files\": [\n {\n \"name\": \"file_1-invoice.json\",\n \"role\": \"output\",\n \"path\": \"output/extract/file_1-invoice.json\",\n \"stepName\": \"extract\"\n }\n ],\n \"error\": null,\n \"execution\": {\n \"status\": \"completed\",\n \"schemaValid\": true,\n \"batchId\": null,\n \"retry\": {\n \"number\": 0,\n \"previousRunId\": null,\n \"nextRun\": null\n }\n }\n }\n },\n \"RunArtifact\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n },\n \"role\": {\n \"type\": \"string\",\n \"description\": \"`input`, `output`, `debug`, `report`, or another stable artifact role.\"\n },\n \"path\": {\n \"type\": \"string\",\n \"description\": \"Canonical artifact path for GET /api/v1/runs/:id/artifacts/:path.\"\n },\n \"stepName\": {\n \"description\": \"Workflow step that produced the file, when known.\",\n \"type\": \"string\"\n },\n \"contentType\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"size\": {\n \"anyOf\": [\n {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n },\n {\n \"type\": \"null\"\n }\n ]\n }\n },\n \"required\": [\n \"name\",\n \"role\",\n \"path\"\n ],\n \"additionalProperties\": false\n },\n \"RunInput\": {\n \"type\": \"object\",\n \"properties\": {\n \"args\": {\n \"description\": \"Input arguments the run was started with.\"\n },\n \"files\": {\n \"description\": \"Uploaded input files (agent runs only).\",\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/RunFile\"\n }\n },\n \"metadata\": {\n \"description\": \"Caller-supplied run metadata, if any.\"\n }\n },\n \"required\": [\n \"args\"\n ],\n \"additionalProperties\": false\n },\n \"RunFile\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"name\"\n ],\n \"additionalProperties\": false\n },\n \"RunUsage\": {\n \"type\": \"object\",\n \"properties\": {\n \"tokens\": {\n \"type\": \"object\",\n \"properties\": {\n \"input\": {\n \"anyOf\": [\n {\n \"type\": \"number\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"output\": {\n \"anyOf\": [\n {\n \"type\": \"number\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"cacheRead\": {\n \"anyOf\": [\n {\n \"type\": \"number\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"cacheWrite\": {\n \"anyOf\": [\n {\n \"type\": \"number\"\n },\n {\n \"type\": \"null\"\n }\n ]\n }\n },\n \"required\": [\n \"input\",\n \"output\",\n \"cacheRead\",\n \"cacheWrite\"\n ],\n \"additionalProperties\": false\n },\n \"creditsCharged\": {\n \"anyOf\": [\n {\n \"type\": \"number\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"durationMs\": {\n \"anyOf\": [\n {\n \"type\": \"number\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"llmCallCount\": {\n \"description\": \"LLM call count (workflow runs only).\",\n \"type\": \"number\"\n },\n \"ocrPagesProcessed\": {\n \"description\": \"OCR pages processed (workflow runs only).\",\n \"type\": \"number\"\n },\n \"agentTurns\": {\n \"description\": \"Agent conversation turns (agent runs only).\",\n \"anyOf\": [\n {\n \"type\": \"number\"\n },\n {\n \"type\": \"null\"\n }\n ]\n }\n },\n \"required\": [\n \"tokens\",\n \"creditsCharged\",\n \"durationMs\"\n ],\n \"additionalProperties\": false\n },\n \"RunExecution\": {\n \"anyOf\": [\n {\n \"$ref\": \"#/components/schemas/WorkflowRunExecution\"\n },\n {\n \"$ref\": \"#/components/schemas/AgentRunExecution\"\n }\n ]\n },\n \"WorkflowRunExecution\": {\n \"type\": \"object\",\n \"properties\": {\n \"status\": {\n \"description\": \"Status of this run. `retry.nextRun.status` is a later retry, not this run.\",\n \"$ref\": \"#/components/schemas/ExecutionStatus\"\n },\n \"schemaValid\": {\n \"anyOf\": [\n {\n \"type\": \"boolean\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Whether the completed output matched the workflow or agent output schema.\"\n },\n \"batchId\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Experiment batch id when the run is part of a batch.\"\n },\n \"retry\": {\n \"$ref\": \"#/components/schemas/RunExecutionRetry\"\n },\n \"review\": {\n \"anyOf\": [\n {\n \"$ref\": \"#/components/schemas/RunReview\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"humanReview\": {\n \"description\": \"Pending in-flight human review when the run is waiting on a reviewer.\",\n \"anyOf\": [\n {\n \"$ref\": \"#/components/schemas/RunHumanReviewSummary\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"steps\": {\n \"type\": \"array\",\n \"items\": {},\n \"description\": \"Slim per-step rows (`id`, name, type, status, timing, order, capped error excerpt). Full `input`/`output` live on `GET /api/v1/runs/{id}/steps/{stepExecutionId}`.\"\n },\n \"childExecutions\": {\n \"description\": \"Child invoke-workflow runs and their steps (`expand=execution`, workflow runs only). Omitted when there are no children.\",\n \"type\": \"array\",\n \"items\": {}\n },\n \"definitionSnapshot\": {\n \"description\": \"Workflow definition snapshot captured when the run was created (`expand=execution`).\",\n \"anyOf\": [\n {},\n {\n \"type\": \"null\"\n }\n ]\n },\n \"expected\": {\n \"description\": \"Ground-truth expected output and files.\",\n \"type\": \"object\",\n \"properties\": {\n \"output\": {},\n \"files\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/RunFile\"\n }\n }\n },\n \"additionalProperties\": false\n }\n },\n \"required\": [\n \"status\",\n \"schemaValid\",\n \"batchId\",\n \"retry\",\n \"steps\"\n ],\n \"additionalProperties\": false\n },\n \"RunReview\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\"\n },\n \"verdict\": {\n \"anyOf\": [\n {\n \"type\": \"string\",\n \"enum\": [\n \"correct\",\n \"incorrect\"\n ]\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"status\": {\n \"type\": \"string\",\n \"enum\": [\n \"open\",\n \"closed\",\n \"wont_fix\"\n ]\n },\n \"note\": {\n \"type\": \"string\"\n },\n \"correctedOutput\": {\n \"anyOf\": [\n {},\n {\n \"type\": \"null\"\n }\n ]\n },\n \"reviewedBy\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"User id of the last reviewer. Read-only; set from the authenticated user or API key creator.\"\n },\n \"reviewedByEmail\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Email of the last reviewer. Read-only; set from the authenticated user or API key creator.\"\n },\n \"reviewedAt\": {\n \"type\": \"string\"\n },\n \"closedBy\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"User id recorded when the review was closed. Read-only; set when status becomes closed or wont_fix.\"\n },\n \"closedByEmail\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Email recorded when the review was closed. Read-only; set when status becomes closed or wont_fix.\"\n },\n \"closedAt\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"closedNote\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"createdAt\": {\n \"type\": \"string\"\n },\n \"updatedAt\": {\n \"type\": \"string\"\n },\n \"corrections\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/RunReviewCorrection\"\n }\n }\n },\n \"required\": [\n \"id\",\n \"verdict\",\n \"status\",\n \"note\",\n \"reviewedBy\",\n \"reviewedByEmail\",\n \"reviewedAt\",\n \"closedBy\",\n \"closedByEmail\",\n \"closedAt\",\n \"closedNote\",\n \"createdAt\",\n \"updatedAt\",\n \"corrections\"\n ],\n \"additionalProperties\": false\n },\n \"RunReviewCorrection\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\"\n },\n \"kind\": {\n \"type\": \"string\",\n \"enum\": [\n \"field\",\n \"file\"\n ]\n },\n \"path\": {\n \"type\": \"string\",\n \"description\": \"JSON Pointer for field corrections, or canonical artifact path for file reviews.\"\n },\n \"label\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"originalValue\": {\n \"anyOf\": [\n {},\n {\n \"type\": \"null\"\n }\n ]\n },\n \"correctedValue\": {\n \"anyOf\": [\n {},\n {\n \"type\": \"null\"\n }\n ]\n },\n \"note\": {\n \"type\": \"string\"\n },\n \"correctedArtifactPath\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"createdAt\": {\n \"type\": \"string\"\n },\n \"updatedAt\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"id\",\n \"kind\",\n \"path\",\n \"label\",\n \"note\",\n \"createdAt\",\n \"updatedAt\"\n ],\n \"additionalProperties\": false\n },\n \"AgentRunExecution\": {\n \"type\": \"object\",\n \"properties\": {\n \"status\": {\n \"description\": \"Status of this run. `retry.nextRun.status` is a later retry, not this run.\",\n \"$ref\": \"#/components/schemas/ExecutionStatus\"\n },\n \"schemaValid\": {\n \"anyOf\": [\n {\n \"type\": \"boolean\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Whether the completed output matched the workflow or agent output schema.\"\n },\n \"batchId\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Experiment batch id when the run is part of a batch.\"\n },\n \"retry\": {\n \"$ref\": \"#/components/schemas/RunExecutionRetry\"\n },\n \"review\": {\n \"anyOf\": [\n {\n \"$ref\": \"#/components/schemas/RunReview\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"humanReview\": {\n \"description\": \"Pending in-flight human review when the run is waiting on a reviewer.\",\n \"anyOf\": [\n {\n \"$ref\": \"#/components/schemas/RunHumanReviewSummary\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"files\": {\n \"type\": \"object\",\n \"properties\": {\n \"output\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/RunFile\"\n },\n \"description\": \"Output artifacts the agent produced.\"\n }\n },\n \"required\": [\n \"output\"\n ],\n \"additionalProperties\": false\n },\n \"expected\": {\n \"description\": \"Ground-truth expected output and files.\",\n \"type\": \"object\",\n \"properties\": {\n \"output\": {},\n \"files\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/RunFile\"\n }\n }\n },\n \"additionalProperties\": false\n },\n \"comparison\": {\n \"description\": \"Expected-vs-actual comparison for eval runs (terminal runs only).\"\n }\n },\n \"required\": [\n \"status\",\n \"schemaValid\",\n \"batchId\",\n \"retry\",\n \"files\"\n ],\n \"additionalProperties\": false\n },\n \"RunDebug\": {\n \"type\": \"object\",\n \"properties\": {\n \"observability\": {\n \"description\": \"Execution phase timeline and structured failure.\"\n },\n \"traceId\": {\n \"description\": \"Workflow trace id for span lookup (workflow runs only).\",\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n }\n },\n \"required\": [\n \"observability\"\n ],\n \"additionalProperties\": false\n },\n \"RunAccepted\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\"\n },\n \"type\": {\n \"type\": \"string\",\n \"enum\": [\n \"workflow\",\n \"agent\"\n ]\n },\n \"finished\": {\n \"type\": \"boolean\",\n \"const\": false\n },\n \"source\": {\n \"$ref\": \"#/components/schemas/RunSource\"\n }\n },\n \"required\": [\n \"id\",\n \"type\",\n \"finished\"\n ],\n \"additionalProperties\": false,\n \"example\": {\n \"id\": \"wfx_01HZXEXAMPLE\",\n \"type\": \"workflow\",\n \"finished\": false,\n \"source\": {\n \"id\": \"wf_invoice\",\n \"name\": \"Invoice extraction\",\n \"version\": null\n }\n }\n },\n \"RunArtifactsResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"artifacts\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/RunArtifact\"\n }\n }\n },\n \"required\": [\n \"artifacts\"\n ],\n \"additionalProperties\": false\n },\n \"RunCancelResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\"\n },\n \"type\": {\n \"type\": \"string\",\n \"enum\": [\n \"workflow\",\n \"agent\"\n ]\n },\n \"finished\": {\n \"type\": \"boolean\",\n \"description\": \"True when the run has reached a terminal status.\"\n },\n \"execution\": {\n \"type\": \"object\",\n \"properties\": {\n \"status\": {\n \"$ref\": \"#/components/schemas/ExecutionStatus\"\n }\n },\n \"required\": [\n \"status\"\n ],\n \"additionalProperties\": false\n },\n \"cancellation\": {\n \"type\": \"object\",\n \"properties\": {\n \"state\": {\n \"type\": \"string\",\n \"enum\": [\n \"cancelled\",\n \"requested\",\n \"already_terminal\"\n ],\n \"description\": \"`cancelled` — the run was terminated immediately (it had not started). `requested` — the run is in-flight; cancellation was requested and the status will become `cancelled` shortly. `already_terminal` — the run had already finished; nothing changed.\"\n },\n \"wasStatus\": {\n \"description\": \"Run status at the time the cancel request was received.\",\n \"$ref\": \"#/components/schemas/ExecutionStatus\"\n }\n },\n \"required\": [\n \"state\",\n \"wasStatus\"\n ],\n \"additionalProperties\": false\n }\n },\n \"required\": [\n \"id\",\n \"type\",\n \"finished\",\n \"execution\",\n \"cancellation\"\n ],\n \"additionalProperties\": false\n },\n \"RunEventsResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"events\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/RunEvent\"\n }\n }\n },\n \"required\": [\n \"events\"\n ],\n \"additionalProperties\": false\n },\n \"RunEvent\": {\n \"type\": \"object\",\n \"properties\": {\n \"type\": {\n \"type\": \"string\"\n },\n \"timestamp\": {\n \"type\": \"string\"\n },\n \"status\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"message\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"metadata\": {\n \"type\": \"object\",\n \"propertyNames\": {\n \"type\": \"string\"\n },\n \"additionalProperties\": {}\n }\n },\n \"required\": [\n \"type\",\n \"timestamp\"\n ],\n \"additionalProperties\": false\n },\n \"PromoteRunResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"automationId\": {\n \"type\": \"string\",\n \"description\": \"Automation that owns the promoted example.\"\n },\n \"automationType\": {\n \"type\": \"string\",\n \"enum\": [\n \"workflow\",\n \"agent\"\n ],\n \"description\": \"Implementation type behind the automation.\"\n },\n \"exampleId\": {\n \"type\": \"string\",\n \"description\": \"Dataset example identifier returned for follow-up API calls.\"\n },\n \"name\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Dataset example name.\"\n }\n },\n \"required\": [\n \"automationId\",\n \"automationType\",\n \"exampleId\",\n \"name\"\n ],\n \"additionalProperties\": false\n },\n \"RunReviewDetail\": {\n \"type\": \"object\",\n \"properties\": {\n \"review\": {\n \"anyOf\": [\n {\n \"$ref\": \"#/components/schemas/RunReview\"\n },\n {\n \"type\": \"null\"\n }\n ],\n \"description\": \"Review metadata and corrections. Corrected files are listed separately at GET /runs/{id}/reviews/expected.\"\n }\n },\n \"required\": [\n \"review\"\n ],\n \"additionalProperties\": false\n },\n \"RunReviewExpectedArtifacts\": {\n \"type\": \"object\",\n \"properties\": {\n \"files\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/RunFile\"\n },\n \"description\": \"Corrected artifact files attached to the run review. Corrected JSON output lives on the review object at GET /runs/{id}/reviews.\"\n }\n },\n \"required\": [\n \"files\"\n ],\n \"additionalProperties\": false\n },\n \"RunReviewExpectedFileMutationResponse\": {\n \"description\": \"Corrected file created or renamed by the request.\",\n \"$ref\": \"#/components/schemas/RunFile\"\n },\n \"RunReviewExpectedFileUpdateResponse\": {\n \"description\": \"Corrected file after the rename.\",\n \"$ref\": \"#/components/schemas/RunFile\"\n },\n \"RunScoresResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"scores\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/EvalResult\"\n },\n \"description\": \"Automated evaluator scores for the run. These are separate from human review verdicts.\"\n }\n },\n \"required\": [\n \"scores\"\n ],\n \"additionalProperties\": false,\n \"description\": \"Automated evaluator results attached to a run.\"\n },\n \"RunStepsResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"steps\": {\n \"type\": \"array\",\n \"items\": {}\n },\n \"total\": {\n \"type\": \"integer\",\n \"minimum\": -9007199254740991,\n \"maximum\": 9007199254740991\n }\n },\n \"required\": [\n \"steps\",\n \"total\"\n ],\n \"additionalProperties\": false\n },\n \"RunStepDetailResponse\": {},\n \"RunTraceResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"events\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/RunTraceEvent\"\n },\n \"description\": \"Chronological trace events. Workflow runs return observability phases or step executions; agent runs return parsed trace.jsonl events.\"\n }\n },\n \"required\": [\n \"events\"\n ],\n \"additionalProperties\": false\n },\n \"RunTraceEvent\": {\n \"type\": \"object\",\n \"properties\": {\n \"type\": {\n \"description\": \"Event type when present. Agent traces mirror trace.jsonl events; workflow traces use execution phase or step records.\",\n \"type\": \"string\"\n },\n \"phase\": {\n \"description\": \"Workflow execution phase, when present.\",\n \"type\": \"string\"\n },\n \"stepName\": {\n \"description\": \"Workflow step name, when present.\",\n \"type\": \"string\"\n },\n \"status\": {\n \"description\": \"Event or execution status, when present.\",\n \"type\": \"string\"\n },\n \"startedAt\": {\n \"description\": \"Event start timestamp.\",\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"completedAt\": {\n \"description\": \"Event completion timestamp.\",\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"message\": {\n \"description\": \"Human-readable event message.\",\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n }\n },\n \"additionalProperties\": {},\n \"description\": \"Trace event emitted by a workflow or agent run. Extra fields depend on the run type and event source.\"\n },\n \"RunUsageResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"usage\": {\n \"anyOf\": [\n {\n \"$ref\": \"#/components/schemas/RunUsage\"\n },\n {\n \"type\": \"null\"\n }\n ]\n }\n },\n \"required\": [\n \"usage\"\n ],\n \"additionalProperties\": false\n },\n \"ListTemplatesResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"items\": {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/components/schemas/Template\"\n }\n },\n \"total\": {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 9007199254740991\n }\n },\n \"required\": [\n \"items\",\n \"total\"\n ],\n \"additionalProperties\": false\n },\n \"Template\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\",\n \"pattern\": \"^tmpl_[A-Za-z0-9_-]{21}$\",\n \"description\": \"Stable logical template id (tmpl_…).\"\n },\n \"name\": {\n \"type\": \"string\"\n },\n \"description\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"filename\": {\n \"type\": \"string\"\n },\n \"format\": {\n \"type\": \"string\",\n \"enum\": [\n \"docx\",\n \"xlsx\"\n ]\n },\n \"mimeType\": {\n \"type\": \"string\"\n },\n \"size\": {\n \"anyOf\": [\n {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 9007199254740991\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"sha256\": {\n \"anyOf\": [\n {\n \"type\": \"string\",\n \"minLength\": 64,\n \"maxLength\": 64\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"tokens\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n },\n \"path\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n },\n \"kind\": {\n \"type\": \"string\",\n \"enum\": [\n \"variable\",\n \"loop\"\n ]\n },\n \"type\": {\n \"type\": \"string\",\n \"enum\": [\n \"string\",\n \"number\",\n \"date\",\n \"boolean\",\n \"array\",\n \"object\"\n ]\n },\n \"required\": {\n \"type\": \"boolean\"\n },\n \"description\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"name\"\n ],\n \"additionalProperties\": false\n }\n },\n \"grammar\": {\n \"type\": \"object\",\n \"properties\": {\n \"syntax\": {\n \"type\": \"string\"\n },\n \"tokenDiscovery\": {\n \"type\": \"boolean\"\n },\n \"capabilities\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\n \"syntax\",\n \"tokenDiscovery\",\n \"capabilities\"\n ],\n \"additionalProperties\": false\n },\n \"currentRevision\": {\n \"anyOf\": [\n {\n \"$ref\": \"#/components/schemas/TemplateRevision\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"createdAt\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"string\"\n }\n ]\n },\n \"updatedAt\": {\n \"anyOf\": [\n {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"string\"\n }\n ]\n },\n {\n \"type\": \"null\"\n }\n ]\n }\n },\n \"required\": [\n \"id\",\n \"name\",\n \"filename\",\n \"format\",\n \"mimeType\",\n \"tokens\",\n \"grammar\",\n \"createdAt\"\n ],\n \"additionalProperties\": false\n },\n \"TemplateRevision\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\",\n \"pattern\": \"^tmpr_[A-Za-z0-9_-]{21}$\",\n \"description\": \"Immutable template revision id (tmpr_…).\"\n },\n \"number\": {\n \"type\": \"integer\",\n \"exclusiveMinimum\": 0,\n \"maximum\": 9007199254740991\n },\n \"sha256\": {\n \"type\": \"string\",\n \"minLength\": 64,\n \"maxLength\": 64\n },\n \"createdAt\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"string\"\n }\n ]\n }\n },\n \"required\": [\n \"id\",\n \"number\",\n \"sha256\",\n \"createdAt\"\n ],\n \"additionalProperties\": false\n },\n \"CreatedTemplate\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\",\n \"pattern\": \"^tmpl_[A-Za-z0-9_-]{21}$\",\n \"description\": \"Stable logical template id (tmpl_…).\"\n },\n \"name\": {\n \"type\": \"string\"\n },\n \"description\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"filename\": {\n \"type\": \"string\"\n },\n \"format\": {\n \"type\": \"string\",\n \"enum\": [\n \"docx\",\n \"xlsx\"\n ]\n },\n \"mimeType\": {\n \"type\": \"string\"\n },\n \"size\": {\n \"anyOf\": [\n {\n \"type\": \"integer\",\n \"minimum\": 0,\n \"maximum\": 9007199254740991\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"sha256\": {\n \"anyOf\": [\n {\n \"type\": \"string\",\n \"minLength\": 64,\n \"maxLength\": 64\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"tokens\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n },\n \"path\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n },\n \"kind\": {\n \"type\": \"string\",\n \"enum\": [\n \"variable\",\n \"loop\"\n ]\n },\n \"type\": {\n \"type\": \"string\",\n \"enum\": [\n \"string\",\n \"number\",\n \"date\",\n \"boolean\",\n \"array\",\n \"object\"\n ]\n },\n \"required\": {\n \"type\": \"boolean\"\n },\n \"description\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"name\"\n ],\n \"additionalProperties\": false\n }\n },\n \"grammar\": {\n \"type\": \"object\",\n \"properties\": {\n \"syntax\": {\n \"type\": \"string\"\n },\n \"tokenDiscovery\": {\n \"type\": \"boolean\"\n },\n \"capabilities\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\n \"syntax\",\n \"tokenDiscovery\",\n \"capabilities\"\n ],\n \"additionalProperties\": false\n },\n \"currentRevision\": {\n \"anyOf\": [\n {\n \"$ref\": \"#/components/schemas/TemplateRevision\"\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"createdAt\": {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"string\"\n }\n ]\n },\n \"updatedAt\": {\n \"anyOf\": [\n {\n \"anyOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"string\"\n }\n ]\n },\n {\n \"type\": \"null\"\n }\n ]\n },\n \"cleanupProof\": {\n \"description\": \"One-time proof to finalize or hard-clean this unpublished staged template. Returned only on staged create, never on GET or list.\",\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"id\",\n \"name\",\n \"filename\",\n \"format\",\n \"mimeType\",\n \"tokens\",\n \"grammar\",\n \"createdAt\"\n ],\n \"additionalProperties\": false\n },\n \"DeleteTemplateResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"deleted\": {\n \"type\": \"boolean\"\n }\n },\n \"required\": [\n \"deleted\"\n ],\n \"additionalProperties\": false\n },\n \"TemplateStagingResponse\": {\n \"type\": \"object\",\n \"properties\": {\n \"cleaned\": {\n \"type\": \"boolean\"\n },\n \"finalized\": {\n \"type\": \"boolean\"\n }\n },\n \"additionalProperties\": false\n },\n \"DatasetReviewFocusFieldOutput\": {\n \"type\": \"object\",\n \"properties\": {\n \"path\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"Dotted expected-output path the reviewer should inspect, e.g. vendor.iban.\"\n },\n \"reason\": {\n \"description\": \"Optional reason this field needs attention.\",\n \"anyOf\": [\n {\n \"type\": \"string\",\n \"minLength\": 1\n },\n {\n \"type\": \"null\"\n }\n ]\n }\n },\n \"required\": [\n \"path\"\n ],\n \"additionalProperties\": false\n }\n },\n \"securitySchemes\": {\n \"bearerAuth\": {\n \"type\": \"http\",\n \"scheme\": \"bearer\",\n \"description\": \"API key issued from Settings → API Keys. Pass as `Authorization: Bearer <key>`.\"\n }\n }\n }\n}\n"
|
|
10
10
|
},
|
|
11
11
|
{
|
|
12
12
|
"topic": "api-reference/webhooks",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"title": "Changelog",
|
|
21
21
|
"description": "Production release history for the EigenPal platform.",
|
|
22
22
|
"source": "public",
|
|
23
|
-
"content": "---\ntitle: Changelog\ndescription: Production release history for the EigenPal platform.\n---\n\nEigenPal ships on a unified platform version. Each production release updates Studio, the public API, infrastructure, and (when applicable) the CLI and SDKs together.\n\n{/* GENERATED:CHANGELOG_INDEX START */}\n\n## 0.20.0 (2026-09-22)\n\n### Platform (Studio)\n\n- Datasets can now be sent for client review without exporting files. Create a review request from a dataset, highlight the fields that need attention, mark others as not required, and invite client teammates with the new reviewer role. They walk examples from a dropdown, inspect the fields, leave notes, record per-field decisions, and approve or reject each row. Closing a finished review does not auto-apply changes — reconcile expected outputs manually. The Reviews queue keeps finished requests visible with a status filter so old approvals stay findable. Reviewers see the same Studio shell with permission-aware empty states.\n\n### Public API\n\n- New dataset review endpoints under `/api/v1/automations/:id/dataset-review-requests`: create a review from dataset examples with reviewer `instructions`, `focusFields` (paths plus optional reasons), `ignoredFields` for paths reviewers can skip, and optional `itemNotes`. Approve, edit, reject, reopen, comment, or record a `field-decision` on each example (including clearing a decision with `decision: null`), then poll `progress.complete` and close the request with `PATCH` status. Dataset reconciliation stays manual — nothing is deleted by reject. A new `reviewer` organization role can read review queues and submit item decisions but cannot edit workflows.\n\n### CLI\n\n- `eigenpal workflow dataset review-request` (and the `eigenpal agents dataset` mirror) is the agent-friendly review loop: create a request with reviewer instructions, `--focus` / `--focus-reason` paths, `--ignore` paths reviewers can skip, and per-example `--item-note` / `--field-note` comments; `list`/`get`/`events` expose `progress.complete`, `fieldDecisions`, and `inputDrifted`; `item --action` records approve/reject/comment/edit plus per-field `field-decision` (clear with `--clear` / `--decision null`); `update --status closed` finishes the request. There is no auto-apply — pull and reconcile examples manually. Reject is recommendation-only; nothing is deleted.\n\n### SDK\n\n- `client.automations.datasetReviewRequests` (`dataset_review_requests` in Python) covers the full dataset review lifecycle: list and get with `progress`, `focusFields`, `ignoredFields`, `fieldDecisions`, and `inputDrifted`; create with reviewer instructions and per-field notes; update request metadata or close with status; update items including `field-decision` (pass `decision: null` to clear); and the per-user activity trail. Dataset write-back stays manual — there is no lock endpoint.\n\n### Infrastructure & processing\n\n- Replace the eagerly constructed `eigenpalAjv` singleton with a lazy `getEigenpalAjv()` accessor. Ajv compiles schemas with `new Function`, which the Studio Content-Security-Policy forbids — constructing at import time crashed every page whose client bundle transitively imported `@eigenpal/types` validation (including all review surfaces, which never validate client-side). Server-side call sites are unchanged apart from the accessor.\n\n---\n\n## 0.19.1 (2026-09-21)\n\n- Internal improvements.\n\n---\n\n## 0.19.0 (2026-09-21)\n\n### Platform (Studio)\n\n- Agent builder sessions can now be given storage credentials limited to their own session folder instead of the whole storage account. Set a Cloudflare account id and API token, or an AWS role, and each training sandbox receives a short-lived key that can only read and write its own files. Deployments that do not configure this keep working exactly as before and log a warning, and a new setting makes the platform refuse to start a sandbox unless scoped credentials are available.\n- Studio security hardening. Parsed document text shown in run traces and grounding views is now sanitized before rendering, so a crafted document can no longer inject active content into the page. Observability settings now require administrator access to view, and the values of any authorization headers you configure are masked once saved, so they are never sent back to the browser. Saving a renamed header now asks you to retype its value instead of quietly clearing the configuration. Outbound observability destinations are validated to reject internal and unencrypted endpoints on hosted plans. Editor assets are now served from Eigenpal's own domain instead of a public content network. Self-hosted deployments that use password sign-in no longer accept open self-registration. Creating the first account still works, and anyone holding an invitation can still create their account, but an uninvited visitor can no longer join an existing workspace. Set `EIGENPAL_ALLOW_OPEN_SIGNUP=true` to restore the previous behavior. Agent training and email trigger surfaces are now scoped more tightly. Email alias changes are accepted only through the agent that owns the alias, so editing or revoking one from a different agent's page now reports not found. Opening a training session that belongs to a different workspace or a different agent is refused instead of returning a server error. Each agent workspace now runs with credentials valid only for its own session, so a workspace can no longer act on any session but its own. Sign-in and account safety. Changing your password now signs out your other sessions, so a password change ends access from a device you no longer control. Accepting an invitation now requires the invitation link itself rather than just the invited address, so knowing that someone was invited is no longer enough to create an account in their name. Requests that arrive from another site are refused, which closes cross-site request forgery against pages you are signed in to. Set `EIGENPAL_TRUSTED_ORIGINS` if you serve Eigenpal on more than one hostname.\n\n### Public API\n\n- Agent endpoints that accept an agent id now resolve it strictly within the calling organization. Requesting an id belonging to another organization returns not found instead of reading or modifying it. Run and step endpoints apply the same organization check to execution ids. Uploads that omit a declared length are now measured while they stream and return 413 once they exceed the request limit, rather than being read into memory first. Operator source tokens are accepted only on the source and authentication check endpoints they are documented for. Webhook endpoints are now checked when you save them, not only when a delivery is attempted. A destination the platform cannot deliver to is rejected with a validation error at creation and update time, instead of being accepted and then failing silently on every send. Self-hosted deployments that deliver to their own internal network are unaffected. Every endpoint that starts a new run now honours the automation's trigger settings, the same way `POST /api/v1/runs` already did. That covers rerunning a run, starting an experiment, and running a single dataset example, including their streaming variants. An API key calling one of these on an automation whose API trigger is turned off now receives `403 api_trigger_disabled`, and a dashboard session calling one on an API-only automation receives `403 manual_trigger_disabled`. If an existing integration starts returning 403, turn the API trigger back on for that automation.\n- Self-hosted Prometheus scrapes now require the dedicated scrape token in every deployment. An organization API key is no longer enough to read the cluster snapshot. A deployment without `EIGENPAL_METRICS_SCRAPE_TOKEN` returns 404 on the metrics route, so set the token before upgrading if you scrape today with an API key. The headless workflow server no longer serves a network address without an API token. If you set `HOST` yourself, the server now exits at startup unless you also set `HEADLESS_API_TOKEN` or `HEADLESS_ALLOW_UNAUTHENTICATED_BIND=1`. If you never set `HOST`, the bind address changes from `0.0.0.0` to `127.0.0.1`, which inside a container means a published port stops accepting connections while the container still reports healthy. Either set `HEADLESS_API_TOKEN` (16 characters or more) together with `HOST=0.0.0.0`, or set `HEADLESS_ALLOW_UNAUTHENTICATED_BIND=1` to keep the previous behaviour. Members can no longer pull decrypted agent environment secrets. Use an owner or admin key, or decrypt a secret for a specific run.\n\n### Infrastructure & processing\n\n- Self-hosted Prometheus scrapes now require the dedicated scrape token in every deployment. An organization API key is no longer enough to read the cluster snapshot. A deployment without `EIGENPAL_METRICS_SCRAPE_TOKEN` returns 404 on the metrics route, so set the token before upgrading if you scrape today with an API key. The headless workflow server no longer serves a network address without an API token. If you set `HOST` yourself, the server now exits at startup unless you also set `HEADLESS_API_TOKEN` or `HEADLESS_ALLOW_UNAUTHENTICATED_BIND=1`. If you never set `HOST`, the bind address changes from `0.0.0.0` to `127.0.0.1`, which inside a container means a published port stops accepting connections while the container still reports healthy. Either set `HEADLESS_API_TOKEN` (16 characters or more) together with `HOST=0.0.0.0`, or set `HEADLESS_ALLOW_UNAUTHENTICATED_BIND=1` to keep the previous behaviour. Members can no longer pull decrypted agent environment secrets. Use an owner or admin key, or decrypt a secret for a specific run.\n- Document and archive processing is more resilient to malformed or hostile input. Dataset archive imports now apply a limit on entry count and hold far less memory while expanding, so a small archive can no longer exhaust a request. Office documents are checked against their real expanded size rather than the size recorded inside the file, which blocks highly compressed payloads that previously passed inspection. PDF page rendering moved to a newer engine that removes a document driven code execution path. Script transform steps have a shorter maximum run time that is now capped relative to worker health checks, so a long running script cannot stall other work. With stock settings the ceiling drops from 30 seconds to 15 seconds; self-hosted deployments that need more can raise `HEALTH_LIVENESS_STALE_MS`, since the ceiling is half that value. Workflow processing is more resilient to hostile input. Template rendering now has time and memory ceilings, so a crafted template can no longer stall a worker and delay other runs. Deep merges in the combine transform can no longer be steered into altering shared state. External file sources reject addresses that are not plain HTTP endpoints.\n\n---\n\n## 0.18.0 (2026-09-21)\n\n### Platform (Studio)\n\n- Workflows can crop normalized regions from PDFs and images into JPEG artifacts with the new `transform.crop-regions` step — pair it with parse output and script steps to build figure or layout evidence pipelines without a figure-specific step type. Turn on optional **`cache: true`** on **`ai.parse`** to reuse prior parse output for the same file bytes and parse settings across runs (stored in tenant blob storage; no expiry yet).\n\n---\n\n## 0.17.5 (2026-09-21)\n\n### Platform (Studio)\n\n- Summary Agent: spreadsheet uploads now use a hardened parser that prevents crafted workbook content from causing excessive processing or modifying object prototypes.\n\n### CLI\n\n- CLI skill reference documents the new `ai.figure-crops` workflow step for cropping and captioning figures from parsed PDFs.\n\n### SDK\n\n- Python SDK: installs now require `anyio` 4.14.2 or newer. Earlier versions encoded host names with IDNA 2003 when opening a TLS connection, so a crafted host name could be matched against the wrong certificate. The TypeScript SDK is unaffected.\n\n---\n\n## 0.17.4 (2026-09-18)\n\n### Platform (Studio)\n\n- Strengthen organization access controls so role permissions, API-key scopes, and member removal apply consistently across Studio and the API. Webhook configuration and signing secrets are restricted to organization owners and admins. Service credentials cannot exceed member permissions, while members retain file and review editing through the API.\n- Organization owners can invite new users directly as owners. Owner invitations can only be created and managed by existing owners.\n\n### Public API\n\n- Strengthen organization access controls so role permissions, API-key scopes, and member removal apply consistently across Studio and the API. Webhook configuration and signing secrets are restricted to organization owners and admins. Service credentials cannot exceed member permissions, while members retain file and review editing through the API.\n\n### Infrastructure & processing\n\n- Cloud workflow HTTP and website-reader actions now restrict requests to public HTTP/S destinations, verify TLS for HTTPS requests, and reject HTTPS-to-HTTP redirects. Responses are limited to 20 MiB and requests to 120 seconds. Single-tenant installations retain private-network integration support.\n\n---\n\n## 0.17.3 (2026-09-18)\n\n### Public API\n\n- Large PDF parses are now more reliable under parallel load. The OCR service paces concurrent pages per document so multi-page jobs no longer exhaust inference memory and retry, which previously stalled big documents behind repeated restarts.\n\n---\n\n## 0.17.2 (2026-09-17)\n\n### Platform (Studio)\n\n- Settings gains a Data retention section for workspace admins: see how much file storage past and present runs consume, choose how long eval and other runs are kept, preview what falls past the horizon, and delete those runs in capped passes until clear. Runs that are still active are always kept. Enforcement offers two modes: purge input files only (run history and outputs stay, freeing the bulky source documents while keeping the audit trail) or delete full runs. Storage usage splits run inputs from outputs so admins can see what input-only cleanup would free.\n\n### Public API\n\n- Rerunning a run whose input files were removed by data retention now returns a clear `409 inputs-purged` error instead of failing while copying the missing files. Run history and outputs remain available.\n\n---\n\n## 0.17.1 (2026-09-15)\n\n- Internal improvements.\n\n---\n\n## 0.17.0 (2026-09-15)\n\n### Platform (Studio)\n\n- Studio can connect to a live agent inference session even when that session runs in a local sandbox instead of the hosted cloud environment.\n\n### Infrastructure & processing\n\n- Agent inference can now run in a local container sandbox, so on-prem and air-gapped deployments no longer need a cloud sandbox provider.\n- Agent runs can now execute in customer-hosted sandbox environments instead of only the Eigenpal cloud, and local Docker sandboxes connect reliably on plain localhost setups.\n\n---\n\n## 0.16.13 (2026-09-14)\n\n- Internal improvements.\n\n---\n\n## 0.16.12 (2026-09-14)\n\n### Platform (Studio)\n\n- Studio can import large dataset ZIP archives without taking the app down, including archives whose paths use Windows-style backslashes. Opening a long-running workflow no longer pulls every step’s full input and output at once. Run pages stay available, still show the steps timeline when phase data is missing, and keep the last loaded view if a refresh fails — with a retry control instead of a blank error page.\n\n### Public API\n\n- `GET /api/v1/runs/\\{id}?expand=execution` and `GET /api/v1/runs/\\{id}/steps` now return slim step rows (identity, status, timing, and a capped error excerpt) instead of inlining every step’s input and output. Inspect one step’s full payloads with the new `GET /api/v1/runs/\\{id}/steps/\\{stepExecutionId}` endpoint.\n\n### CLI\n\n- `eigenpal runs get` lists slim step rows by default. Pass `--include input,output` or `--step` to fetch full payloads for the steps you care about.\n\n### SDK\n\n- The TypeScript and Python SDKs now include `GET /api/v1/runs/\\{id}/steps/\\{stepExecutionId}` so you can load one step’s full input and output after listing slim run steps.\n\n---\n\n## 0.16.11 (2026-09-11)\n\n### Platform (Studio)\n\n- Studio: organization switching and other labeled menus now open reliably without a client-side error.\n\n---\n\n## 0.16.10 (2026-09-10)\n\n### Infrastructure & processing\n\n- OCR processing now distinguishes temporary host availability issues from true processing timeouts, keeps redundant production capacity warm, and pages only when unfinished work is affected. Short self-healing interruptions remain visible for diagnosis without generating misleading recovery alerts.\n\n---\n\n## 0.16.9 (2026-09-10)\n\n### Platform (Studio)\n\n- Harden web image handling, document image processing, and email delivery against crafted inputs that could cause remote code execution, excessive resource use, or recipient-validation bypasses.\n\n### Infrastructure & processing\n\n- Harden web image handling, document image processing, and email delivery against crafted inputs that could cause remote code execution, excessive resource use, or recipient-validation bypasses.\n\n---\n\n## 0.16.8 (2026-09-10)\n\n### Platform (Studio)\n\n- Files are easier to recognize throughout Studio with refreshed Office logos, dedicated PDF, archive, text, JSON, and code treatments, plus image thumbnails. File inputs now use a clearer rounded drag-and-drop experience with consistent selected-file previews.\n\n---\n\n## 0.16.7 (2026-09-10)\n\n### Platform (Studio)\n\n- File uploads now infer supported document media types from the filename when clients provide an empty or generic content type, allowing original Outlook messages and macro-enabled workbooks to upload without conversion.\n\n### Public API\n\n- File uploads now infer supported document media types from the filename when clients provide an empty or generic content type, allowing original Outlook messages and macro-enabled workbooks to upload without conversion.\n\n### CLI\n\n- The CLI now uploads macro-enabled Excel workbooks with the correct media type, so original `.xlsm` workflow inputs work without manual conversion.\n\n### SDK\n\n- TypeScript SDK file helpers now infer the correct media types for `.xlsm` workbooks and `.msg` Outlook messages.\n\n### Infrastructure & processing\n\n- Document parsing now reads Excel, legacy Excel, and macro-enabled workbooks directly, preserving every non-empty sheet and its cell evidence without executing formulas or macros. Large single-page extractions are also split into bounded AI context windows instead of failing at the model limit.\n\n---\n\n## 0.16.6 (2026-09-09)\n\n### Infrastructure & processing\n\n- Template processing now enforces memory limits when joining large collections, preventing crafted templates from exhausting worker memory.\n\n---\n\n## 0.16.5 (2026-09-08)\n\n### Platform (Studio)\n\n- Human review is now available in production, including workflow authoring and review queues.\n\n### Public API\n\n- Human review API endpoints are now available in every production organization for listing tasks, confirming fields, and completing reviews.\n\n### Infrastructure & processing\n\n- Workflow and agent runs can now request human review in every production organization.\n\n---\n\n## 0.16.4 (2026-09-08)\n\n### Platform (Studio)\n\n- Studio adds List Archive and Extract Archive File steps for ZIP workflow inputs. Enumerate archive contents, wire `\\{\\{ item.path }}` through foreach, and pass extracted files straight into Parse, Vision, or Search Files without leaving the builder.\n- Studio now finishes multi-GB file uploads with resumable multipart transfers, retrying individual parts without restarting the whole file.\n- Studio workflows now include Search Files: ask a question about a ZIP archive and get a cited answer plus the files the step inspected. Scope the search to a folder inside the archive and use the same model and reasoning controls as other AI steps.\n\n### Public API\n\n- Upload ZIP archives as reusable workflow inputs through the Files API. Archives can be much larger than single documents, so teams can pass bundled evidence, exports, or multi-file drops into the same runs that already accept PDFs and Office files.\n- File uploads can now negotiate a resumable multipart session for multi-GB objects, with on-demand part URLs, authoritative resume listing, and safe completion that never overwrites a finished file.\n- Starting a run from a reusable file id now keeps a private run-owned reference to the original bytes instead of duplicating large uploads. Deleting the reusable file leaves past runs readable until those runs themselves are deleted.\n\n### CLI\n\n- Dataset import and export now keep a single `/api/v1` prefix when the CLI base URL already includes `/api/v1`, so those commands reach the dataset API instead of a doubled `/v1/v1` path.\n- The CLI now uploads large run files with resumable, storage-direct transfers, so multi-GB inputs stream from disk instead of loading into memory or a single request.\n- The CLI now recognizes `.zip` files when uploading reusable workflow inputs, so archive uploads get the correct content type without extra flags.\n\n### SDK\n\n[View full release notes →](/releases/0.16.4)\n\n---\n\n## 0.16.3 (2026-09-08)\n\n### Platform (Studio)\n\n- Human review: open pending reviews directly from run details and confirm unchanged fields inline from the field list.\n\n### Public API\n\n- Human review field confirmations now preserve valid JSON `null` values and return clear validation errors when a reviewed value does not match its schema.\n\n---\n\n## 0.16.2 (2026-09-08)\n\n### Platform (Studio)\n\n- Human review: pause workflows and agents only when selected fields need attention, inspect source files beside structured output with spatial citation highlights when lineage is available, correct and confirm values, then approve the same run to continue. Confidence thresholds, explicit field selection, required-field progress, rejection, and cancellation keep exception review focused instead of forcing teams to recheck every field.\n\n### Public API\n\n- Human review APIs now list pending tasks, return review data and source-file references, persist field corrections and confirmations, and approve or reject paused runs with optimistic concurrency protection. Task detail may also include resolved lineage and parsed-document context when an upstream grounded extract produced sidecars.\n\n### CLI\n\n- Workflow authoring now includes human-review guidance and ready-to-use templates for confidence-based exception review and explicit approval of critical fields.\n\n### SDK\n\n- TypeScript and Python SDKs now expose human-review resources for listing and retrieving tasks, confirming corrected fields, downloading attached source files, and approving or rejecting paused runs.\n\n### Infrastructure & processing\n\n- Grounded extraction now runs the same shared algorithm locally when a parse step supplies a valid structured document and your provider supports strict structured output. Step JSON stays schema-shaped with `_grounding` metadata; lineage and the parsed document graph are stored as optional sidecars for review and audit, not mixed into workflow output. Text-only inputs and unsupported providers continue to use the existing text grounding path with clear degraded markers when the shared path is unavailable.\n\n---\n\n## 0.16.1 (2026-09-07)\n\n### Platform (Studio)\n\n- GPT-6 Astra is available across workflows, agents, evaluations, and vision tasks, with configurable reasoning and current token pricing.\n- Self-hosted PaddleOCR models now appear with clear provider identity in Studio model selectors and settings.\n- Archive imports now reject malformed ZIP64 data safely instead of risking an unbounded processing loop.\n\n### CLI\n\n- CLI archive handling now rejects malformed ZIP64 data safely instead of risking an unbounded processing loop.\n\n### Infrastructure & processing\n\n- GPT-6 Astra is available across workflows, agents, evaluations, and vision tasks, with configurable reasoning and current token pricing.\n- Self-hosted deployments can connect directly to PaddleOCR-VL for high-quality document parsing, with bounded concurrency and long-running PDF support built in.\n\n---\n\n## 0.16.0 (2026-09-07)\n\n### Platform (Studio)\n\n- Agent model pickers are now compact, searchable, grouped by provider, and ordered from the most capable model to the least without changing configured defaults.\n- Send Email is now a first-class workflow action. Add Resend or SMTP servers in Settings → Email servers, then pick a stable `ems_…` server on the step — including generated files from the same run as attachments. Cloud and on-prem share this Settings surface; there is no default server. Secrets stay encrypted, and reads never show credentials. Changing an SMTP host, username, or provider asks you to re-enter the password so a stored secret cannot follow a new destination.\n\n### Public API\n\n- The public API now manages organization email servers at `/v1/email-servers`: list, create, inspect, update, delete, and send a connectivity test. Each server is an `ems_…` resource with a Resend or SMTP transport. Secrets are encrypted and never returned; disabled servers reject tests, and names must be unique among live servers. Updating SMTP to a different host or username requires a new password or explicitly clearing authentication — the previous password is never reused against a new destination.\n\n### CLI\n\n- Manage organization email servers with `eigenpal email-servers`: list and inspect `ems_…` servers, create or update Resend and SMTP providers (including an optional SMTP CA PEM), delete servers, and send a live test message with `--to`. Secrets are read from stdin, a file, or a secure prompt — never from command-line flags.\n\n### SDK\n\n- TypeScript and Python SDKs now manage organization email servers: list, create, inspect, update, delete, and send a connectivity test. Stored credentials are never returned.\n\n### Infrastructure & processing\n\n- Send Email delivers through the organization server selected on the step. There is no fallback: a missing, deleted, or disabled server fails the run. Evaluation runs skip delivery, including workflows invoked from an eval. Cancelling a run aborts an in-flight send. Multi-tenant SMTP servers must resolve to public addresses, while single-tenant deployments can use internal relays. Partial SMTP acceptance reports which recipients were delivered or rejected so operators can avoid duplicate reruns. SMTP may still deliver twice if a worker stops after the relay accepts the message; Resend deduplicates the same step attempt.\n\n---\n\n## 0.15.1 (2026-09-04)\n\n### Infrastructure & processing\n\n- OpenParser OCR capacity now recovers cleanly after failed updates, avoiding unnecessary warm resources while preserving active document processing.\n\n---\n\n## 0.15.0 (2026-09-04)\n\n### Platform (Studio)\n\n- Workflow validation now explains when a catalog model belongs in `provider` instead of the raw `model` override, and reruns preserve clean original filenames in generated outputs and citations.\n- Make document inputs uploaded in Studio datasets available to experiment runs, including examples saved by earlier releases.\n\n### Public API\n\n- Experiment result responses and JSON exports now include evaluator-specific structured details, so clients can identify the exact JSON path, expected value, and actual value behind a failed comparison. CSV exports retain their existing stable columns.\n\n### CLI\n\n- Experiment analysis is now built into the CLI for workflows and agents: summarize pass, fail, error, and score totals; filter failures by evaluator; inspect structured discrepancy paths; and compare actual outputs between batches. Run payloads can be projected with `--select`, and repository-level validation discovers nested workflow projects automatically. Polling commands also expose consistent wait limits and reject flag combinations that cannot produce a reliable verdict. Waiting commands now keep human output concise by default; pass `--json` whenever scripts need the terminal payload.\n- `eigenpal docs` now lists, searches, and reads the complete release-matched platform documentation offline, including detailed evaluator syntax, workflow step guides, CLI reference, and the OpenAPI contract.\n- CLI file uploads now send valid content types for Outlook and unknown files, cancellation confirms the asynchronous request clearly, and run comparisons show every repeated workflow step by branch and iteration path.\n\n### Infrastructure & processing\n\n- Make document inputs uploaded in Studio datasets available to experiment runs, including examples saved by earlier releases.\n- Exact-diff evaluators can exclude volatile fields with `ignore: true`, including nested fields inside a selected object or array. This keeps golden outputs readable while scoring only stable business data such as identities, names, and classifications.\n- Script steps now bind inputs by parameter name, so workflows behave consistently after storage even when JSON key order differs from the authored YAML.\n\n[View full release notes →](/releases/0.15.0)\n\n---\n\n## 0.14.3 (2026-09-04)\n\n### Platform (Studio)\n\n- Model selection now includes the GPT 5.6 Sol, Terra, and Luna lineup plus Claude Fable 5, Fable 5.1, Opus 5, and Sonnet 5. Reasoning effort can be configured for supported workflow steps, agent training and runs, workflow-building chat, and LLM judges; existing choices keep their current provider defaults when the setting is omitted.\n\n### CLI\n\n- Workflow YAML can configure model-aware reasoning effort on AI steps and LLM judges. Omit the setting to preserve each model's current default.\n\n### Infrastructure & processing\n\n- AI processing supports the latest GPT and Claude request formats, including reliable structured extraction with Claude Fable 5 and Fable 5.1. Workflow and agent execution can pass an optional model-aware reasoning effort while preserving previous defaults, and agent sandboxes can use GPT 5.6, Claude Fable 5, Fable 5.1, Opus 5, and Sonnet 5.\n\n---\n\n## 0.14.2 (2026-09-02)\n\n### Infrastructure & processing\n\n- Single-node deployments can now upgrade installations with large legacy datasets without startup failures or loss of trigger configuration.\n\n---\n\n## 0.14.1 (2026-09-02)\n\n### Infrastructure & processing\n\n- Single-node deployments can now upgrade installations with legacy run review data without startup failures.\n\n---\n\n## 0.14.0 (2026-09-02)\n\nThis release gives document teams more control over structured-data quality.\nExact-diff evaluators can express field-specific matching rules, PDF parsing can\npreserve visual layout, and spreadsheet conversion can retain the rows, columns,\nand displayed values that matter to downstream workflows.\n\nCLI authoring guidance makes these capabilities easier to discover and safer to\nautomate, with non-interactive commands failing clearly instead of waiting on\nunavailable prompts.\n\n### Platform (Studio)\n\n- `ai.parse` adds `outputFormat: layout` for native PDF extraction. It returns fixed-width plain text that preserves columns, spacing, and line breaks for multi-column forms and tables that lose meaning when flattened. This PDF-only format must be selected explicitly with `parseMode: native` or `parseMode: native-or-ocr`: native mode fails closed if layout extraction cannot complete, while hybrid mode keeps accepted layout pages and substitutes OCR markdown only for suspect or empty pages. Existing formats and defaults are unchanged.\n- Spreadsheet to JSON now handles `.xls` and `.xlsx` workbooks with configurable headerless input or an explicit header row, named or positional column projection, rectangular ranges, and raw or displayed cell values. Displayed values preserve formatted text such as dates, leading zeros, punctuation, diacritics, and embedded newlines. Blank-cell and blank-row policies make sparse sheets predictable, while optional sheet metadata and diagnostics explain the selected range and non-fatal issues. Existing zero-config output remains `rows`, plus `fileId` when CSV output is enabled; zero-config CSV keeps the full selected sheet, and configured CSV follows the same projection. File, row, column, and cell limits reject unsafe workloads before conversion.\n- Exact-diff evaluators add composable per-field rules for extraction outputs. Choose ordered or unordered comparison independently from `items: at-least | at-most | exactly`, set numeric tolerances, and reject unexpected object fields where strict output shapes matter. Ordered arrays retain prefix-compatible matching, while unordered arrays find the best one-to-one structural pairing instead of depending on row order. Unordered object arrays can also use typed `matchBy` identities such as `sku` or `[country, sku]` for predictable single- or composite-key matching. Studio now provides a rule editor with path-aware validation. Grounding metadata is excluded from scoring, oversized comparison workloads fail safely with bounded diagnostics, and existing evaluator configurations keep their historical behavior.\n\n### Public API\n\n- Template creation now accepts reusable file references correctly, restoring CLI template uploads and workflow pushes that use local DOCX or XLSX files.\n\n### CLI\n\n[View full release notes →](/releases/0.14.0)\n\n---\n\n## 0.13.2 (2026-09-01)\n\n### CLI\n\n- CLI installation no longer downloads packages already included in its self-contained executable, reducing install overhead and improving compatibility with restricted enterprise networks.\n\n---\n\n## 0.13.1 (2026-08-31)\n\n### Platform (Studio)\n\n- Workflows can turn JSON rows into a downloadable Excel workbook with a new JSON to XLSX step. Pick ordered columns, map an array of objects, and get a `.xlsx` run output — including multi-sheet workbooks — without filling a template.\n- Studio now uses the shared theme provider, so system / light / dark stays aligned with OpenParser instead of drifting independently.\n- Publishing a workflow that still has a local `template: ./file.xlsx` path now fails with a clear error. Use `eigenpal workflow push` to upload the file, or set `templateId` to a `tmpl_…` id first.\n- Studio template uploads and replacements now create immutable, checksum-backed revisions and discover tokens consistently across DOCX and XLSX files. Deleting a logical template preserves revision content used by pinned workflows.\n- Fill Template (`transform.template`) now documents workspace `tmpl_...` templates separately from Git agent templates, and Studio copy covers DOCX and XLSX. XLSX files use `\\{placeholder}` and `\\{table:array.prop}` in the spreadsheet; `\\{\\{placeholder}}` in an uploaded sheet warns on upload and fails at fill instead of leaving leftover braces. `templateId` must be a workspace `tmpl_...` ID, not a file ID. Filled values that look like formulas stay text; formulas already in the template stay formulas.\n- Studio now blocks crafted HTML from retaining executable content during sanitization.\n\n### Public API\n\n- Workflow push can fully remove a template it uploaded if publishing then fails. Deleting a template that workflows already pin still keeps those revisions runnable.\n- The public API now lists the text, vision, and OCR models configured for your environment. `GET /v1/models` is a cheap catalog inventory for the current tenant: it reports whether each model is configured and which capability it is the default for, without probing live providers or exposing secrets.\n- The public API now supports the full lifecycle for tenant-scoped DOCX and XLSX templates: upload, inspect, list, download, replace, and delete, with direct-upload support for larger files. Every replacement creates a checksum-backed immutable revision; deleting the logical `tmpl_…` resource preserves revisions already pinned by workflows.\n\n### CLI\n\n- `workflow versions create --file` now resolves local `template:` paths the same way as `workflow push`, and `workflow templates smoke --data` help documents the JSON fixture file path.\n- `eigenpal workflow push` keeps local Office templates inside the workflow project, including when a path uses `../` or a symlink. Files outside that directory need `--allow-external-templates`. Push validates the workflow and version before uploading, creates new template resources instead of moving shared `tmpl_…` pointers, and fully removes those unpublished uploads if publish does not succeed.\n- When resolving a workflow by `wf_…` id, connection failures, auth errors, and server outages now surface their normal CLI messages instead of being misreported as \"workflow not found.\"\n\n[View full release notes →](/releases/0.13.1)\n\n---\n\n## 0.13.0 (2026-08-25)\n\n### Platform (Studio)\n\n- API reference for listing dataset examples now documents `include=metadata`, so you can page through example ids, names, and file refs without loading every payload.\n- Local Studio development no longer keeps a growing on-disk compiler cache that can exhaust memory during long `bun dev` sessions.\n- Studio's sidebar theme picker now supports keyboard navigation across system, light, and dark.\n- Studio dashboard sessions continue to authenticate `/api/v1` calls. Token-based `/api/v1` and `/v1` requests still work without a browser login, and the dedicated API hostname keeps its public routing and CORS behavior.\n- Studio save-as-release still publishes a tagged version as the live workflow. Publishing from an existing snapshot creates a new tagged release instead of rewriting the original tag, so earlier releases stay intact. Connect API docs version pickers follow the public version list, so after restore the current untagged version shows as latest while tagged releases stay selectable.\n\n### Public API\n\n- List dataset examples without pulling every payload. `GET /api/v1/automations/:id/examples` now accepts `include=metadata`, which returns ids, names, annotations, and expected file refs while leaving input and expected JSON unloaded. Keep the default `include=full` when you still need the complete example bodies.\n- You can now create, promote, and restore workflow versions through the public API. Create a tagged candidate with `activate: false` to test it without changing live traffic, then promote that exact version after it qualifies. You can also publish from YAML, copy an existing version into a new release without changing its original tag, or restore an earlier snapshot. Name-conflict errors include `conflictingWorkflowId` so you can see which workflow already owns the name.\n\n### CLI\n\n- `eigenpal workflow versions` can now create, promote, and restore YAML workflow versions through the public API. Tag a candidate from a YAML file or an existing snapshot with an explicit semver, keep it off live traffic with `--no-activate`, then promote that exact version when it qualifies. Restoring still rolls a workflow back by copying a snapshot into a new current version — lists now show that untagged HEAD clearly instead of hiding it. `workflow versions list --limit` and `--offset` page that full public list locally. `--json` prints the sliced `\\{ data, total, limit, offset }` envelope (`total` is the unsliced count), not the raw server payload.\n\n### SDK\n\n- TypeScript and Python SDKs can list dataset examples with `include: \"metadata\"`. That returns ids, names, annotations, and expected file refs without loading each example's input and expected JSON. The default remains a full payload, so existing list calls stay unchanged.\n\n[View full release notes →](/releases/0.13.0)\n\n---\n\n## 0.12.2 (2026-08-21)\n\n### Platform (Studio)\n\n- Document editing: the DOCX editor used for templates, run file review, and Office file previews now follows your light or dark theme, and Save (including Cmd/Ctrl+S) writes back to the document you opened instead of downloading a copy. Documents that fail to open now report the reason instead of showing an empty editor. Placeholder highlighting in DOCX templates is temporarily unavailable.\n- Connect: a workflow that wraps another workflow now documents the full response shape. Its OpenAPI spec, Swagger UI preview, and the response examples and generated types on the Connect page show the nested objects and arrays returned by the workflow it calls, instead of leaving those fields untyped.\n\n---\n\n## 0.12.1 (2026-08-19)\n\n### Platform (Studio)\n\n- Connect: download an OpenAPI spec (swagger.json) and preview it in Swagger UI directly from the Connect page. Selecting a workflow or agent produces a spec for just that automation: the five endpoints needed to integrate it (start a run, poll it, cancel it, list and download artifacts), with the request body documenting its exact input fields and file uploads and run responses typed with its actual output schema. With no selection you get the full platform API spec. Swagger UI is bundled with the product, so the preview also works in on-prem installs without internet access.\n\n---\n\n## 0.12.0 (2026-08-18)\n\n### Platform (Studio)\n\n- The workflow builder chat honors the new `disableTemperature: true` model configuration option, so models that reject a sampling temperature work from the first request.\n- Object-typed workflow inputs can now declare a nested schema. In the workflow builder, choosing the Object type (or an array of objects) opens a property editor where you define each field with its type, description, allowed enum values, and required flag, including nested objects and arrays up to five levels deep. Declared fields are enforced when a run starts: missing required fields and type mismatches are rejected with precise field paths. Downstream steps get full autocomplete and type resolution for nested references such as `\\{\\{ input.metadata.vendor.name }}`, and the declared shape appears in the scope browser and in generated API documentation. The builder flags expressions that reference undeclared nested fields, the run form and evaluation input editor pre-fill the declared required fields, and the AI expression generator sees the nested shape when suggesting expressions. The headless execution server now enforces declared inputs with the same validator, so its API documentation and runtime behavior agree.\n- Grounded OpenParser extraction results can now carry complete field lineage through the Eigenpal web runtime, preserving source evidence and confidence metadata for downstream review experiences.\n\n### Public API\n\n- Object-typed workflow inputs can now declare a nested schema. In the workflow builder, choosing the Object type (or an array of objects) opens a property editor where you define each field with its type, description, allowed enum values, and required flag, including nested objects and arrays up to five levels deep. Declared fields are enforced when a run starts: missing required fields and type mismatches are rejected with precise field paths. Downstream steps get full autocomplete and type resolution for nested references such as `\\{\\{ input.metadata.vendor.name }}`, and the declared shape appears in the scope browser and in generated API documentation. The builder flags expressions that reference undeclared nested fields, the run form and evaluation input editor pre-fill the declared required fields, and the AI expression generator sees the nested shape when suggesting expressions. The headless execution server now enforces declared inputs with the same validator, so its API documentation and runtime behavior agree.\n- Listing runs with `sinceLastClosed=true` works again. Once a review had been closed, asking for the runs recorded since then returned an error instead of the runs, so review tooling that polls for new work had no way to ask \"what has arrived since I last signed off\". The filter now returns those runs.\n\n### Infrastructure & processing\n\n- Model entries in the deployment configuration can now set `disableTemperature: true`. Workflow steps then never send a sampling temperature to that model, which lets reasoning models (and gateways in front of them) that reject the parameter run without a first-call retry.\n- Object-typed workflow inputs can now declare a nested schema. In the workflow builder, choosing the Object type (or an array of objects) opens a property editor where you define each field with its type, description, allowed enum values, and required flag, including nested objects and arrays up to five levels deep. Declared fields are enforced when a run starts: missing required fields and type mismatches are rejected with precise field paths. Downstream steps get full autocomplete and type resolution for nested references such as `\\{\\{ input.metadata.vendor.name }}`, and the declared shape appears in the scope browser and in generated API documentation. The builder flags expressions that reference undeclared nested fields, the run form and evaluation input editor pre-fill the declared required fields, and the AI expression generator sees the nested shape when suggesting expressions. The headless execution server now enforces declared inputs with the same validator, so its API documentation and runtime behavior agree.\n\n---\n\n## 0.11.3 (2026-08-13)\n\n### Platform (Studio)\n\n- API reference pages for starting and reading runs now show complete examples, including `output` and `execution.status`.\n\n### Public API\n\n- Run API: completed-run examples now include `type`, `execution.status`, `output`, `files`, and `error`, instead of a shared async/completed union that dropped those fields. Default GET and list responses populate `execution.retry.nextRun` when a retry exists, and `expand=execution` keeps `schemaValid` instead of clearing it. Child invoke-workflow runs document `parentExecutionId` and `childExecutions`.\n\n### SDK\n\n- Generated run types now distinguish a completed run from the async accepted envelope (`RunAccepted`), and include `parentExecutionId` for child invoke-workflow runs.\n\n---\n\n## 0.11.2 (2026-08-07)\n\n- Internal improvements.\n\n---\n\n## 0.11.1 (2026-08-07)\n\n### Platform (Studio)\n\n- Document and image processing now runs on updated imaging components that carry upstream security fixes.\n\n### Infrastructure & processing\n\n- Document and image processing now runs on updated imaging components that carry upstream security fixes.\n\n---\n\n## 0.11.0 (2026-08-06)\n\n### Platform (Studio)\n\n- Workflow builder chat now works with reasoning models served through a self-hosted `openai-compatible` gateway, instead of failing with a \"temperature is not supported\" error. On models that only accept their own default temperature setting, replies can vary between attempts on the same question.\n- Canonical API hostnames now consistently expose only supported API and operational routes, returning a clear 404 for unsupported discovery paths.\n- Agent Builder attachments now negotiate multipart or storage-direct transfer, so large PDFs and archives can reach the active sandbox without crossing cloud payload limits. Large downloads use the same secure dual path. Self-hosted operators can set `deployment.multipartMaxBytes` in `eigenpal.config.yaml`; the supplied on-prem deployments keep files on multipart and streamed downloads by default.\n- Canonical API hostnames now serve API routes and discovery endpoints reliably without Studio sign-in handling intercepting requests.\n\n### Public API\n\n- Upload and download reusable files up to 100 MiB through one negotiated API: files within the deployment body limit use multipart, while larger cloud transfers use verified storage-direct uploads and short-lived authenticated download links. Retry-safe temporary run and Builder files expire after 24 hours. Existing multipart routes and `studio.eigenpal.com/api/v1` remain compatible, and new integrations can use `api.eigenpal.com/v1`.\n\n### CLI\n\n- The CLI now uses `api.eigenpal.com` as the default cloud API origin and automatically pre-uploads run files that exceed the multipart request limit. Self-hosted users can keep custom API origins and set `EIGENPAL_MULTIPART_MAX_BYTES` to their proxy limit, or `none` to keep all files on multipart.\n\n### SDK\n\n- The TypeScript and Python SDKs now transparently upload large run inputs without crossing cloud request limits, follow secure storage-direct downloads, and default cloud calls to `api.eigenpal.com`. Set `multipartMaxBytes` / `multipart_max_bytes`, or `EIGENPAL_MULTIPART_MAX_BYTES`, to match a self-hosted proxy; use `null` / `None` to keep every run file on multipart. Explicit `files.upload` files remain reusable until deleted.\n- TypeScript file uploads now follow the server-negotiated multipart endpoint, improving compatibility across hosted and self-managed route layouts.\n\n[View full release notes →](/releases/0.11.0)\n\n---\n\n## 0.10.56 (2026-08-05)\n\n### Platform (Studio)\n\n- Agent Builder training chat now shows Pierre file diffs for edit/write, a Pierre syntax-highlighted file view for Read file, secure request-secret password cards (encrypted into the draft; the agent only sees configured/skipped), and a quiet timeline note when you release an agent version from the dashboard.\n\n### Infrastructure & processing\n\n- Production releases that do not change document processing finish faster by reusing verified OCR provider checks from the last successful release, while still re-checking providers when processing code or infrastructure changes.\n\n---\n\n## 0.10.55 (2026-08-05)\n\n### Platform (Studio)\n\n- Agent Builder now resumes your latest draft, clearly distinguishes unsaved edits from saved changes that are not live, and provides direct Save and Release actions. Releases show the current and next version and let you choose a patch, minor, or major update. Dashboard save and release actions remain available to the builder as private context, so it can accurately answer what is live without guessing. Starting a separate draft is explicit, attachments remain available when beginning a conversation, stopped sandboxes can be restarted without losing the draft, and test runs reliably receive JSON-only inputs.\n\n### Public API\n\n- Agent Builder releases now complete live automation synchronization reliably, so a successful release is immediately available without a separate recovery step.\n\n### Infrastructure & processing\n\n- OCR and LLM model catalogs keep loading when the service adds new optional fields, so Studio and Eigenpal no longer fall back to stale model lists during catalog updates.\n- Cloud document processing providers that are already available stay online during routine production updates when their identity is unchanged. New or changed providers stay unavailable until they pass live verification, so customers keep working providers instead of a full outage window.\n\n---\n\n## 0.10.54 (2026-08-04)\n\n### Platform (Studio)\n\n- Workflow Studio now shows each OpenParser OCR model with its actual provider logo, keeps narrow step configuration panels contained, and places settings, theme, and sidebar controls together in a cleaner navigation footer.\n\n---\n\n## 0.10.53 (2026-08-04)\n\n### Platform (Studio)\n\n- OpenParser Studio now visualizes the `openparser@1` document graph directly, including typed elements, figures, tables, relationships, and element-level extraction citations.\n\n### Public API\n\n- OpenParser parse responses now return the unified `openparser@1` document graph, with plain text, canonical Markdown, pages, typed elements, relations, annotations, assets, geometry, confidence, and provider provenance in one predictable contract.\n\n---\n\n## 0.10.52 (2026-08-04)\n\n### Platform (Studio)\n\n- Agent Builder: improve connection recovery so interrupted sessions resume reliably, stale environments are replaced safely, and approval prompts remain retryable when delivery fails.\n\n---\n\n## 0.10.51 (2026-08-03)\n\n- Internal improvements.\n\n---\n\n## 0.10.50 (2026-08-03)\n\n### Platform (Studio)\n\n- OpenParser Studio: pipeline creation no longer reports a duplicate-name error after a successful save, and edits now save reliably from the browser.\n\n---\n\n## 0.10.49 (2026-08-03)\n\n- Internal improvements.\n\n---\n\n## 0.10.48 (2026-07-30)\n\n### Platform (Studio)\n\n- OpenParser Studio now displays canonical OpenParser JSON with readable indentation, including large document results.\n\n---\n\n## 0.10.47 (2026-07-30)\n\n### Platform (Studio)\n\n- OpenParser Studio now keeps large document results responsive, renders OCR markdown with clearer structure, and provides consistent copy and download actions for Markdown and JSON output. Documentation links now reliably open the generated API reference.\n\n### Infrastructure & processing\n\n- OpenParser jobs now recover more safely when document processing capacity becomes unavailable. Retryable failures pause new dispatches, retry without duplicate charges, and bound large-document processing so one document cannot overwhelm the service.\n\n---\n\n## 0.10.46 (2026-07-30)\n\n### Platform (Studio)\n\n- Team settings: bring back the invitation link. Creating an invitation now shows its link straight away whenever no invitation email was delivered, and administrators can pull up the link again at any time from the invitations table. This unblocks onboarding on deployments without email delivery, where handing over the link is the only way to get someone into the workspace.\n- Run details: field grounding now labels flagged fields by what the extraction actually reports, showing \"3 with low confidence\" instead of \"3 to review\". The count is a confidence signal, not an assigned task.\n\n---\n\n## 0.10.45 (2026-07-29)\n\n### Platform (Studio)\n\n- Parse Document setup now clearly separates OCR from Vision AI, automatically offers available OpenParser OCR models, shows each model's per-page price, displays only the controls that affect the selected method, and surfaces structured layout data with tables, figures, polygons, and bounding boxes for downstream workflow steps.\n\n### CLI\n\n- The workflow authoring reference now covers explicit OCR and Vision AI parse modes, optional figure-caption models, and structured layout output.\n\n### Infrastructure & processing\n\n- Document parsing now defaults to higher-fidelity OCR, preserves canonical structured layout alongside Markdown, and automatically supports available OCR models with provider-specific per-page pricing. Other OCR providers retain their existing rates.\n\n---\n\n## 0.10.44 (2026-07-28)\n\n- Internal improvements.\n\n---\n\n## 0.10.43 (2026-07-27)\n\n- Internal improvements.\n\n---\n\n## 0.10.42 (2026-07-27)\n\n- Internal improvements.\n\n---\n\n## 0.10.41 (2026-07-27)\n\n### Platform (Studio)\n\n- Run traces now show each attempt of an AI request. A request that timed out and was retried used to appear as a single long bar, so a step that spent three timeouts on one page looked identical to one slow call. The raw trace now has one bar per try, labelled with the try number, and the run timeline marks a retried call with how many times it was sent. Retried requests also record how long they waited for a free slot, which distinguishes a slow model from a queue backed up behind its own in-flight requests. For documents parsed page by page, each split retry records the pages it covered and how deep the split went.\n- Runs and Experiments improvements: - An experiment run now shows the same input and output panels as the main run view, including input file downloads, per-step output files, and inline field-level output review. - Scored runs show their eval score in the runs list and in the run header, so an experiment's results can be compared without opening each run. - A run that came from an experiment or a dataset example now links straight to that run in the Evals view. - The Live and Experiments toggles on Runs are remembered between visits. - Field grounding: a wide document no longer overflows the panel. Wide tables and long unbroken text scroll inside the document card.\n\n---\n\n## 0.10.40 (2026-07-25)\n\n### Infrastructure & processing\n\n- Processing reliability on busy deployments: health checks are now served independently of document processing, so the service stays responsive to them even while working through a heavy document. It is no longer restarted mid-run just because it is under load, so long-running document runs complete more reliably.\n- Document processing is more resilient on CPU- and memory-constrained deployments. Page rasterization for vision and OCR now runs in isolation, so a single large or malformed document can no longer stall the processing service or cause it to restart mid-run. Runs on big scanned documents that previously failed partway through with \"the worker stopped before this attempt recorded a terminal result\" now complete reliably.\n\n---\n\n## 0.10.39 (2026-07-25)\n\n### Platform (Studio)\n\n- Label Pages runs: the page preview now shows the classified document in the full viewer instead of small thumbnails. PDFs render page-by-page with zoom and navigation and each page's labels shown beside it; Word and other Office documents open in their own preview next to a per-page label list. Filter by a label to focus on just the pages that carry it.\n\n---\n\n## 0.10.38 (2026-07-24)\n\n### Platform (Studio)\n\n- OpenParser Studio: manage extraction pipelines from a dedicated workspace — create, edit, run, duplicate, and delete saved configurations. Jobs show the pipeline and version that produced each result, and you can save a new pipeline from job settings.\n- OpenParser Studio: clearer progress while documents upload, parse, and extract, with live elapsed timing at each stage. Job history and the playground share a unified header with breadcrumbs, improved document and Markdown output viewers, and a cleaner parse sidebar. Choose light or dark theme and manage your account from the sidebar; model selectors and in-product copy are simpler throughout the workspace.\n- Members provisioned through SSO are now read-only in workspace member settings. Their role and access come from your identity provider's groups, so admins can no longer change or remove them by hand, and each SSO member is clearly labeled. Accounts created with a username and password stay fully manageable by admins.\n\n### Public API\n\n- **Breaking:** OpenParser API resource identifiers now use consistent prefixed ids. Parse, extract, and batch jobs return `opj_…` ids instead of UUIDs. Saved extraction pipelines use `oppl_…` instead of `oep_…`. New parse output writes figure image ids as `opfig_…` instead of `ocrfig_…`. Existing jobs and pipelines are remapped automatically on upgrade when the OCR queue is idle enough for migration preflight. Prefer the new formats in job URLs, `parse_job_id`, `pipeline_id`, and batch child `job_id` fields. During the transition, previously issued UUID job ids, `oep_…` pipeline ids, and UUID list cursors remain readable; responses continue to return the preferred `opj_…` / `oppl_…` forms. Historical parse artifacts and `result_json` may still embed legacy `ocrfig_…` figure paths; `GET /files/\\{id}` accepts both `opfig_…` and `ocrfig_…`.\n\n### Infrastructure & processing\n\n- Hardened AI-powered document processing against prompt-injection attempts hidden inside uploaded documents. Instructions embedded in a document can no longer steer extraction, classification, or vision results away from the requested schema, or coax the model into disclosing its own configuration.\n- AI vision step results no longer include internal document storage references in their metadata. The step's `_vision` provenance now records only which pages were inspected and how many were merged, keeping internal storage paths out of workflow output.\n\n---\n\n## 0.10.37 (2026-07-24)\n\n### Platform (Studio)\n\n- New **Label Pages** step tags each page of a document with zero or more labels (multi-label) using AI, and groups the results into a label-to-pages map. Unlike section splitting — which produces one contiguous range per section — this collects pages of the same kind wherever they appear, so scattered pages (for example every signature or photo page throughout a report) can be gathered in one place. The page-inspection step can now take an explicit list of page indices, so you can route the pages for a given label straight into a visual inspection without hand-listing them.\n\n---\n\n## 0.10.36 (2026-07-23)\n\n### Platform (Studio)\n\n- OpenParser Job History now reports the real end-to-end duration for completed parse and extraction jobs instead of showing a zero or unavailable measurement.\n- Running OpenParser jobs now show the document scanning animation from the playground while results are being prepared.\n- Parse and Extract now use consistent operation icons across OpenParser Studio and documentation.\n\n---\n\n## 0.10.35 (2026-07-23)\n\n### Platform (Studio)\n\n- OpenParser sign-in and account creation now redirect directly to the branded authentication flow without an intermediate confirmation page.\n- OpenParser parse jobs now retain both `raw` and `openparser@1` results. Retrieve either representation with `GET /jobs/\\{id}/result?format=...`, switch formats in the Studio Output tab, and start extraction from a raw-format parse job without running OCR again.\n\n### Public API\n\n- OpenParser parse jobs now retain both `raw` and `openparser@1` results. Retrieve either representation with `GET /jobs/\\{id}/result?format=...`, switch formats in the Studio Output tab, and start extraction from a raw-format parse job without running OCR again.\n- OpenParser now keeps recognized text aligned with its original bounding box by default. Set `ocr_options.merge_layout_blocks` to `true` per parse, extraction, batch item, or saved pipeline when merged recognition is preferred over one-to-one text geometry.\n\n---\n\n## 0.10.34 (2026-07-23)\n\n### Platform (Studio)\n\n- OpenParser sign-in and account creation now keep OpenParser branding throughout the authentication experience.\n- OpenParser Studio: uploads and sample documents now open their Job History detail immediately, so browser back and forward navigation follows each run naturally while extraction and result review stay in one place.\n- Run detail now shows clean, readable file names for inputs and outputs instead of internal storage identifiers, and long file names no longer overlap the preview and download buttons.\n\n### Public API\n\n- OpenParser parsing now preserves every detected layout region—including empty title, header, and figure boxes—so document overlays remain complete. The obsolete `figure_assets` option is removed because figure regions are now always retained.\n- OpenParser can now process documents beyond 25 pages and admit batches of up to 100 documents, while retaining per-page safety limits.\n- OpenParser jobs can now stream their retained source documents with `GET /jobs/\\{id}/source`, making it easier to build durable review experiences around past runs.\n- `POST /suggest-schema` now returns the suggested schema inline as a convenience response instead of creating a job that clients must poll.\n\n### Infrastructure & processing\n\n- Documents uploaded without a declared file type are now recognized from their contents, so PDFs, RTF, and Office files parse reliably instead of failing with an \"unsupported file type\" error. This most often helped uploads coming from automated integrations that omit the file type.\n\n---\n\n## 0.10.33 (2026-07-22)\n\n### Platform (Studio)\n\n- OpenParser Studio: make Playground the home page, add shareable social previews, clarify job status and pipeline empty states, and tidy the OCR model selector copy.\n\n### Public API\n\n- OpenParser suggested extraction model catalog (`GET /models/llm` in suggested mode) now surfaces up to 20 recommended models instead of 12, so more current options appear before you need to search.\n\n---\n\n## 0.10.32 (2026-07-22)\n\n- Internal improvements.\n\n---\n\n## 0.10.31 (2026-07-22)\n\n### Platform (Studio)\n\n- OpenParser Studio production sign-in no longer auto-redirects to Eigenpal when you are signed out. Choose **Continue to sign in** on the local OpenParser page to authenticate with your Eigenpal account; sign-out stays on OpenParser.\n\n---\n\n## 0.10.30 (2026-07-22)\n\n### Platform (Studio)\n\n- OpenParser production sign-in now shares Eigenpal sessions across its dedicated domain and returns users to their original OpenParser destination after authentication.\n- OpenParser Playground: remove the doubled border and rounded corners around the document workspace.\n\n### Infrastructure & processing\n\n- OpenParser: restore schema suggestions, use GPT-5.6 Terra as the default extraction model with GPT-4.1 Mini as a certified fallback, tighten compatibility checks, and provide clearer failure guidance.\n\n---\n\n## 0.10.29 (2026-07-22)\n\n### Platform (Studio)\n\n- OpenParser Studio sign-in and sign-up now load the shared identity UI correctly for signed-out visitors.\n\n---\n\n## 0.10.28 (2026-07-22)\n\n### Platform (Studio)\n\n- API keys: keep usable credentials in the primary list and move revoked or expired credentials into a collapsed history section for faster scanning.\n- OpenParser Studio sign-in and sign-up now show OpenParser product copy and logo while retaining the shared Eigenpal identity.\n\n### Public API\n\n- OpenParser model discovery (`GET /models/llm`) now refreshes the live compatible catalog on the API service instead of falling back to a short emergency list when the catalog credential is missing from that process.\n\n### Infrastructure & processing\n\n- OpenParser document processing now bounds source downloads and retries transient storage failures, preventing stalled jobs from running indefinitely.\n\n---\n\n## 0.10.27 (2026-07-21)\n\n### Platform (Studio)\n\n- New Inspect Pages (Vision) step lets a workflow look at the actual page images of a document and return structured results, for details that only exist in the pixels rather than the text. Use it to check whether a document is signed, rate embedded photos, or spot stamps and logos. It works on PDFs, images, and Office documents, and you can point it at a specific page range (for example the section found by a Split step) so it only reviews the pages that matter. The run trace shows the pages it inspected next to the results.\n- Parsing can now describe the figures on a page as text. Enable \"describe figures\" on a Parse step and the images on each page (property photos, charts, stamps) are detected and captioned inline, so later steps that work on text, like Split, can find image-only pages. This is especially useful for scanned documents, where the photo pages carry almost no text on their own. You can provide custom instructions for how figures should be described.\n- Split step results are now also available keyed by section name. A later step can point at one section directly, for example `\\{\\{ steps.split.output.sections.photos.page_range }}`, instead of filtering the full list. This makes wiring a Split step into a downstream step much simpler.\n- The Inspect Pages (Vision) step now takes a Page From / Page To range instead of a single page-range expression, and both are optional. Leave them blank to inspect the whole document, which is processed in chunks and the results merged automatically. This makes it much easier to point the step at a range (for example the start and end of a Split section) or to scan an entire document without writing a range expression.\n\n---\n\n## 0.10.26 (2026-07-21)\n\n### Platform (Studio)\n\n- Wildcard API keys can use the OpenParser OCR API consistently with every other platform capability. Keys can also be restricted to the dedicated `ocr:full` scope when OCR-only access is preferred.\n- Run traces now include a Grounding panel for extract steps: every extracted value is highlighted in the input text, tinted by confidence, and clicking a field or a highlight jumps between them. Grounded fields also show inline context previews of the exact source passage, both in the panel and in the expanded step row. Split steps gain the same visual page-range panel the segmenter uses, with page thumbnails and per-section preview. The workflow builder reflects that grounding is on by default and lets you pick any configured provider as the grounding model, and capturing expected output from a run no longer snapshots volatile grounding metadata into evals.\n\n### Public API\n\n- Wildcard API keys can use the OpenParser OCR API consistently with every other platform capability. Keys can also be restricted to the dedicated `ocr:full` scope when OCR-only access is preferred.\n- OpenParser: completed extraction jobs can now be retrieved reliably with their attempt and usage metadata.\n\n### CLI\n\n- The step catalog now documents grounded extraction as the default: extract steps ship per-field confidence and source spans under the `_grounding` output key unless `grounded: false` is set.\n\n### Infrastructure & processing\n\n- Data extraction now verifies itself by default. Every extract step traces each extracted field back to its exact location in the source text and attaches a confidence level (high, medium, or low) plus a needs-review flag under a reserved `_grounding` output key, so downstream steps and evaluators can route uncertain values to a human. The verification pass runs on your workspace model (any configured provider), chunks long documents automatically, and falls back to deterministic text matching instead of failing the run when no model is available. Set `grounded: false` on a step to opt out.\n\n---\n\n## 0.10.25 (2026-07-20)\n\n### Platform (Studio)\n\n- Failed single sign-on attempts now return to the sign-in page with a clear, actionable message (for example, when an account's email domain isn't authorized or the account hasn't been granted access) instead of a blank error page.\n\n---\n\n## 0.10.24 (2026-07-15)\n\n### Platform (Studio)\n\n- Agent runs graded by configured evaluators now record a weighted score and pass/fail result, visible in the runs feed and run detail responses. Previously only workflow runs carried an evaluator verdict.\n- Email addresses for a workflow are unique across your whole organization, not just the workflow you are editing. Picking one that is already taken used to fail with a server error. It now tells you which workflow already receives email at that address, or that the workflow you are editing already has it, so you know what to do next. Duplicate folder names and duplicate workspace invites also report clearly instead of failing.\n- `ai.extract` with `grounded: true` no longer succeeds silently without producing grounding. When the grounding pass cannot run (missing OpenAI credentials on the worker, or a grounding model that is not an OpenAI model) the step now fails with an error that names the exact misconfiguration. When the pass runs but produces no field grounding, the output carries an explicit degraded marker instead of nothing. The grounding model picker in the workflow builder now only offers OpenAI models, matching what the grounding pass supports.\n- Agent training: when a training session fails to open, the dashboard now shows what went wrong instead of a generic error. The message names the setup step that failed, and a session blocked by secrets that cannot be decrypted says so and points at the agent settings. A session whose setup fails partway through no longer opens on an incomplete workspace.\n- Self-hosted deployments can now sign users in through corporate single sign-on services that use a redirect-and-token flow instead of OIDC. The new protocol supports mutual TLS for the server-to-server exchange, maps directory groups to EigenPal roles (admin, member, viewer) on every SSO sign-in so the directory stays the source of truth, and links existing password accounts by email so nobody loses access when SSO is turned on. Startup validation rejects unsafe callback origins and provider identifiers, while malformed or oversized identity responses fail closed.\n\n### Public API\n\n- Syncing an automation immediately after a release no longer fails with HTTP 500 while the new release tag propagates. The sync endpoint now reports a retryable status with a clear message when the Git source is momentarily unavailable.\n- Fixed single-experiment results export returning HTTP 400 whenever the `includeTrace` query flag was omitted. `workflow experiment results` and the auto-pull at the end of `workflow experiment watch` now download per-evaluator results in JSON and CSV again.\n- Creating an email trigger address that is already in use now returns 409 with a message naming the workflow in your organization that already uses it, instead of 500.\n\n### CLI\n\n- Agent example runs now report a real evaluator verdict in the CLI: `eigenpal run agents.<name> --example <name> --wait` waits for the verdict, prints the weighted score and pass/fail result, and `--fail-on-mismatch` exits non-zero when the run fails its evaluators, matching the existing workflow behavior. When no evaluators are configured, the CLI says so instead of silently reporting nothing.\n- `agents secrets` is now one command group with `list`, `set`, `unset`, `import`, and `export` subcommands (`agents secret` remains as an alias). The new `agents secrets list` shows the secret names and descriptions declared in the package without ever printing values. Previously `set` and `unset` lived under a separate singular command and `secrets list` failed with an argument error.\n- `agents sync` retries automatically with a short backoff when the server reports the Git source as temporarily unavailable, so the sync right after `agents release` succeeds without manual retries.\n- `agents dataset validate` now checks the same layout the server accepts on `agents dataset push`: example folders under `examples/`, file inputs referenced from `input.json` with `\\{ \"$file\": \"input/...\" }`, and `expected.json` optional. Previously the local validator demanded a different layout that push would then reject, so no dataset could satisfy both. Validation errors now point at the exact rule that failed, including a hint when example folders sit at the dataset root instead of under `examples/`. When the agent package carries an input schema, each example's full input object is validated against it (required fields, unknown keys, and value types, with `\\{ \"$file\": ... }` references accepted for file fields), so inputs that would fail at run start are caught locally. Failure-expected examples (`expected.json` with `$error`) are rejected for agent datasets, since agent runs are evaluated only when they complete.\n\n[View full release notes →](/releases/0.10.24)\n\n---\n\n## 0.10.23 (2026-07-15)\n\n- Internal improvements.\n\n---\n\n## 0.10.22 (2026-07-14)\n\n### Platform (Studio)\n\n- Organization members can now configure, test, and manage outbound webhooks from Studio.\n\n---\n\n## 0.10.21 (2026-07-14)\n\n### Platform (Studio)\n\n- Webhooks: notify external systems when workflow or agent runs are created or change status, with signed delivery, custom headers, retry history, testing, and manual redelivery from Studio.\n- Webhook signing secrets are now easier to copy securely from endpoint setup and details, with clearer event selection defaults.\n- Webhook setup now keeps failed submissions actionable with clear inline error feedback.\n\n### Public API\n\n- Run creation and rerun requests now publish signed lifecycle webhooks only after inputs are ready, so API-triggered automations never emit events for runs that fail during setup.\n\n### Infrastructure & processing\n\n- Improved staging worker deployment reliability when compute capacity is fully allocated.\n\n---\n\n## 0.10.20 (2026-07-12)\n\n### Platform (Studio)\n\n- Workflows: configure automatic retries from Studio at the workflow level or override them for individual HTTP GET/HEAD and Website Reader steps.\n\n### CLI\n\n- The bundled workflow reference now documents durable retry policies, inheritance, supported step types, and retry safety limits.\n\n### Infrastructure & processing\n\n- Workflow runs can recover replay-safe network steps from transient failures without restarting completed work, using bounded backoff and durable retry state. Retry behavior is now step-scoped. Legacy whole-run retry settings no longer restart a failed workflow; configure durable retries on eligible steps or through the workflow retry default instead.\n\n---\n\n## 0.10.19 (2026-07-09)\n\n### Platform (Studio)\n\n- Workflow composition is unified on `action.invoke-workflow`: use `execution: inline` (default) to run a target workflow's steps inside the parent run, or `execution: child` for a separate child run. Reusable blocks (`control.block`, `kind: block`) are removed — migrate to inline invoke with `workflow: <name-or-id>`.\n\n### Public API\n\n- Workflow run endpoints now preserve inline invoke snapshots across initial runs, reruns, and dataset executions so composed workflows remain reproducible after target workflows change.\n\n### CLI\n\n- Workflow YAML reference docs now describe `action.invoke-workflow` as the single composition primitive, including inline and child execution modes.\n\n---\n\n## 0.10.18 (2026-07-08)\n\n### Infrastructure & processing\n\n- On-prem deployments: improve OpenShift compatibility so migration and processing jobs can start reliably under random-user security policies.\n\n---\n\n## 0.10.17 (2026-07-08)\n\n### Platform (Studio)\n\n- Document parser: vision parsing can now render PDF pages at higher resolution and image quality for documents where small text or compression artifacts hurt OCR accuracy.\n\n### Infrastructure & processing\n\n- Document parser: vision parsing can now render PDF pages at higher resolution and image quality for documents where small text or compression artifacts hurt OCR accuracy.\n\n---\n\n## 0.10.16 (2026-07-07)\n\n### Platform (Studio)\n\n- Workflow experiment results now preserve evaluator error details alongside each per-evaluator score, so example grading views and tools can distinguish failed judges from unknown results instead of treating them as passing.\n\n### CLI\n\n- `eigenpal run <workflow> --example <name>` now actually grades the example instead of printing `PASS` whenever the run merely finished. It runs the workflow's current published version on the server's stored dataset example, so configured evaluators run automatically and the CLI surfaces the real weighted score and per-evaluator pass/fail. Workflows with no evaluators fall back to a structural diff of the output against the example's stored expected output. The summary reports two separate signals: execution health (`ok`/`errored`) and accuracy. Add `--fail-on-mismatch` to exit non-zero when a graded example fails. Because the run uses the server-side example, push your latest dataset and evaluators (`eigenpal workflow dataset push`, `eigenpal workflow evaluators push`) before running `--example`.\n\n---\n\n## 0.10.15 (2026-07-06)\n\n### Platform (Studio)\n\n- Experiments: make result review easier in Studio with trace exports, clickable score bars, calmer live refreshes, developer-view defaults, and clearer separation between below-threshold results and run errors.\n\n### Public API\n\n- Experiment export endpoints now support JSON exports with full run trace details for deeper debugging and audit review.\n\n### SDK\n\n- SDK clients now expose the trace-inclusive experiment export option for deeper debugging and audit review.\n\n---\n\n## 0.10.14 (2026-07-06)\n\n### Platform (Studio)\n\n- Evaluations: expected workflow failures now report cleaner scores when a run is supposed to stop early. Studio marks non-applicable quality judges as skipped, so successful rejection examples can receive a full score from the structured failure checks that actually apply.\n\n---\n\n## 0.10.13 (2026-07-06)\n\n- Internal improvements.\n\n---\n\n## 0.10.12 (2026-07-06)\n\n- Internal improvements.\n\n---\n\n## 0.10.11 (2026-07-03)\n\n- Internal improvements.\n\n---\n\n## 0.10.10 (2026-07-03)\n\n- Internal improvements.\n\n---\n\n## 0.10.9 (2026-07-02)\n\n### Platform (Studio)\n\n- Build document-processing workflows that split, route, and verify a mixed batch: - **Document separation** detects the boundaries and types of the documents inside one large scan, so a single upload can be broken into its individual documents and each sent to its own extraction pipeline — even for batches hundreds of pages long. - **Multi-way routing** sends each detected document to the right branch by its type, and stays readable on the canvas even with many branches. - **Grounded extraction** attaches a confidence level and source location to each extracted field, flagging values that aren't found verbatim in the document so reviewers know where to look. - The run view now lets you open the detected documents and preview their pages, and inspect the OCR layout with bounding boxes drawn over the page (with a toggle to the extracted text) — right from the step timeline.\n\n### CLI\n\n- The workflow step catalog now lists the new document-separation and multi-way routing steps, plus the grounded-extraction options, so authoring and validating workflows from the CLI stays in step with what the platform supports.\n\n### Infrastructure & processing\n\n- Self-hosted (on-prem) deployments can now run official EigenPal release images, with access provisioned per customer. Images are published only after a release ships and are signed so you can verify their authenticity before deploying.\n\n---\n\n## 0.10.8 (2026-07-01)\n\n### Platform (Studio)\n\n- Single-file workflow inputs now display correctly after a dataset import. Previously an input that takes one file could show an empty file slot; imported examples now match each file to the workflow's declared input shape.\n- Evaluator scoring now uses a single pass threshold for the whole workflow. The score-by-example chart's cutoff line and every evaluator's pass/fail are measured against that one threshold, so the chart, the per-evaluator results, and the run gate always agree. Experiment scores are shown in two states — passing (green) or below threshold (amber).\n- The LLM judge evaluator now requires evaluation criteria. Without them the model invents its own scoring rubric, so the editor marks the field required, renames it to \"Evaluation criteria\" with a worked example, and blocks saving until it is filled in.\n- Workflow folders can now be reorganized. A new \"Move to folder\" action in each folder's menu lets you move a folder (and everything inside it) into another folder or back to the top level, so you can restructure your workspace without recreating folders. Destinations that would nest a folder inside itself are blocked, with a tooltip explaining why.\n- Nested sub-workflows now display and resolve correctly across runs, the workflow builder, and the CLI. In the Runs list, a run that invokes a sub-workflow which itself invokes another sub-workflow now nests every level under its parent, instead of stopping at the first level. In the workflow builder, an \"Invoke Workflow\" step that targets a workflow built from other invoked workflows now shows the real output field types instead of \"unknown\", so you can reference those fields with autocomplete; referencing one of those fields no longer triggers a false \"field not found\" warning. The same resolution now applies when validating and publishing workflows (including via the CLI), so deeply nested invoke chains validate against their real output fields. All of this resolves through arbitrarily deep chains with a safety limit that prevents looping on workflows that invoke each other.\n- Runs: add a simplified review mode with developer-view toggle, review status badges, and inline output review for JSON fields and generated files.\n- New debugging and control primitives for runs. You can now cancel an in-progress run through the API, experiment results report when a batch has fully finished, steps skipped by a condition or an empty loop are reported as skipped rather than succeeded, and each step records the exact configuration it ran with so failures are easier to diagnose.\n- Run detail responses are leaner and more explicit: you choose exactly which sections to expand, and the public run schema now exposes the workflow version, cancellation-request time, and trace, retry, and email-trigger details.\n\n### CLI\n\n- `eigenpal workflow validate` now tells you when a workflow contains Invoke Workflow steps that local validation cannot fully check. Because those steps reference other workflows that live on the server, the command prints a short note pointing you to `validate --online` (or push) to verify the invoke targets, input types, and cycles. The skill guidance now shows the `--online` step in the validate-then-push flow as well.\n- The evaluator configuration reference now reflects the single workflow-level pass threshold. A per-evaluator `passThreshold` is documented as legacy — pass/fail is decided by the one workflow-level threshold — and that workflow-level threshold no longer shows a fixed default, since it is derived when omitted.\n\n### SDK\n\n- The Python SDK now requires Python 3.10 or newer. Python 3.9 has reached the end of its support window, and dropping it keeps the SDK on current, actively maintained dependencies. If you are still on Python 3.9, upgrade to 3.10+ to continue receiving SDK updates.\n\n[View full release notes →](/releases/0.10.8)\n\n---\n\n## 0.10.7 (2026-06-30)\n\n### Platform (Studio)\n\n- Faster dashboard navigation. Lists keep their contents on screen while filters and folders refresh instead of flashing a loading state, document and image previews are cached so they no longer re-download on every navigation, and heavy viewers (PDF, charts, rich text) load on demand for a quicker first paint.\n- Workflows that invoke another workflow now pass file inputs through to the sub-workflow, so file-backed sub-workflow runs no longer fail before they start.\n\n### CLI\n\n- `eigenpal --help` now groups `run`, `rerun`, and `runs` under a dedicated \"Run\" section instead of the catch-all \"Other\" bucket, so starting a run and reading its output is easy to find.\n\n---\n\n## 0.10.6 (2026-06-30)\n\nThis release contains maintenance and reliability improvements with no customer-facing changes.\n\n---\n\n## 0.10.5 (2026-06-29)\n\nThis release makes EigenPal's public changelog a reliable product record. Each release now has a dedicated docs page that explains what changed for Studio, the public API, the CLI, SDKs, and document processing in one place.\n\nThat means teams can follow platform improvements without piecing together GitHub activity or package-specific notes. The changelog is organized around customer-facing product areas, so it is easier to see which changes affect app users, API integrations, developer tools, and processing behavior.\n\n### Platform (Studio)\n\n- Invoke Workflow steps are now typed end to end. Pick a target workflow and map each input it declares to a value, then reference the workflow's output fields and any files it generates from downstream steps with autocomplete. Inputs and outputs are checked when you save and when the step runs, so mismatches surface early instead of failing mid-run.\n- Runs that invoke another workflow now appear nested under their parent run in both the runs feed and the run timeline, and link straight to the sub-workflow's own run and trace.\n- You can view a workflow's inferred output schema (the fields and files it returns, typed from its own steps) without running it.\n- File inputs are preserved consistently across runs, reruns, reviewed examples, and dataset experiments, so reused runs and examples no longer lose or mispoint their files.\n- Creating new organizations and other Git-backed source operations stay reliable even during Git provider outages.\n\n### Public API\n\n- Run file inputs now use a consistent artifact model. Callers provide reusable files with `$fileId` or inline files with `$inline`, and EigenPal materializes them into run-owned artifacts before execution, reruns, promotion, and dataset workflows.\n- A new endpoint returns a workflow's inferred output schema without running it, as JSON Schema or as a TypeScript or Python type.\n\n### CLI\n\n- `eigenpal workflow schema <workflow>` prints a workflow's inferred output schema as JSON Schema, or as a TypeScript or Python type with `--format`.\n\n[View full release notes →](/releases/0.10.5)\n\n---\n\n## 0.10.4 (2026-06-25)\n\n### Platform (Studio)\n\n- Unify file list review surfaces\n\n---\n\n## 0.10.3 (2026-06-24)\n\n### SDK\n\n#### Patch Changes\n\n- e48cb81: Remove `fileVerdict` from run review correction types; file correction intent is encoded via `correctedArtifactPath`.\n\n---\n\n## 0.10.2 (2026-06-24)\n\n### CLI\n\n#### Patch Changes\n\n- ca9ae4f: Workflow inputs can declare an external file `source` (single-tenant on-prem). A `type: file` input with `source: <name>` (e.g. `gpfs`) is provided as a plain string id at run time; the worker resolves it to a file artifact via the configured source before the workflow executes.\n\n---\n\n## 0.10.1 (2026-06-23)\n\n### Public API\n\n- Polish reviews pages and group API reference nav\n\n### Infrastructure & processing\n\n- Client-shareable deployment architecture PDFs\n\n---\n\n## 0.10.0 (2026-06-23)\n\n### Platform (Studio)\n\n- Add simple runs review mode\n\n### Infrastructure & processing\n\n- Autogenerate chart architecture diagram from helm template\n- AWS/GCP/Azure Terraform examples with architecture diagrams\n- Helm chart + local kind for single-tenant on-prem\n\n---\n\n## 0.9.0 (2026-06-22)\n\n### CLI\n\n#### Minor Changes\n\n- c35d5d4: Clean up the public runs and evaluation API surface: move workflow eval operations onto automations, expose run scores/artifacts through the unified runs API, and update CLI/SDK helpers to use the canonical routes.\n\n Breaking: `runs.evalResults` and `GET /api/v1/runs/\\{id}/eval-results` are replaced by `runs.scores` and `GET /api/v1/runs/\\{id}/scores`.\n\n#### Patch Changes\n\n- c35d5d4: Clarify `--max-wait` help text so timeout exit behavior reads naturally.\n\n### SDK\n\n#### Minor Changes\n\n- c35d5d4: Clean up the public runs and evaluation API surface: move workflow eval operations onto automations, expose run scores/artifacts through the unified runs API, and update CLI/SDK helpers to use the canonical routes.\n\n Breaking: `runs.evalResults` and `GET /api/v1/runs/\\{id}/eval-results` are replaced by `runs.scores` and `GET /api/v1/runs/\\{id}/scores`.\n\n[View full release notes →](/releases/0.9.0)\n\n---\n\n## 0.8.0 (2026-06-18)\n\n### CLI\n\n#### Minor Changes\n\n- d620a00: Expose the clean public automation API around automations, runs, files/artifacts, datasets, evaluators, experiments, evaluation results, and run promotion. This intentionally breaks the pre-v1 SDK/CLI surface that exposed workflow- and agent-specific top-level resources outside the explicit legacy compatibility routes.\n\n > [!WARNING]\n > **Breaking change (pre-v1).** The workflow- and agent-specific top-level\n > resources have been removed in favor of a single automation-centric surface.\n > These packages are still 0.x, so this breaking redesign ships as a `minor`\n > bump. Update your integration before upgrading.\n\n #### Removed\n - Top-level workflow resources, e.g. `client.workflows.*`, including\n `client.workflows.executions.runAndWait(...)` and the rest of the\n `client.workflows.executions.*` tree.\n - Top-level agent resources, e.g. `client.agents.*` (runs, reviews, traces,\n files, expected artifacts).\n - Top-level source/git resources, e.g. `client.sources.*`.\n\n[View full release notes →](/releases/0.8.0)\n\n---\n\n## 0.7.2 (2026-06-13)\n\n### SDK\n\n#### Minor Changes\n\n- c5a709c: Public workflow list/detail responses include `apiEnabled` and `triggers`; run definition docs note workflow-only scope.\n\n---\n\n## 0.7.1 (2026-06-13)\n\n### SDK\n\n#### Patch Changes\n\n- 9db3f01: Expose `apiEnabled` and `triggers` on `AgentSummary` for runtime trigger projection.\n\n---\n\n## 0.7.0 (2026-06-12)\n\n### CLI\n\n#### Minor Changes\n\n- 963fd6c: Unify run detail on `GET /api/v1/runs/\\{id}`: return the canonical Run object directly (no `\\{ run: ... }` envelope) and merge expanded fields in-place via documented `expand` tokens. Remove the session-only `expand=internal` dashboard escape hatch; SDKs and CLI now use explicit expand lists.\n\n#### Patch Changes\n\n- 963fd6c: Update runs commands for the grouped run API shape and four expand tokens.\n\n### SDK\n\n#### Minor Changes\n\n- 963fd6c: Unify run detail on `GET /api/v1/runs/\\{id}`: return the canonical Run object directly (no `\\{ run: ... }` envelope) and merge expanded fields in-place via documented `expand` tokens. Remove the session-only `expand=internal` dashboard escape hatch; SDKs and CLI now use explicit expand lists.\n\n#### Patch Changes\n\n- 12c00d8: Docs: clearer wording in the file-input and TypeScript-runtime sections. No API or behavior changes.\n\n---\n\n## 0.6.17 (2026-06-12)\n\n### SDK\n\n#### Patch Changes\n\n- 716c3cf: Update the hosted default API base URL and API-key guidance from `app.eigenpal.com` to `studio.eigenpal.com`.\n\n---\n\n## 0.6.16 (2026-06-12)\n\n### CLI\n\n#### Patch Changes\n\n- 75dd64c: Internal refactor: move the skill tool registry into its own module so other tooling can import it. No change to any command, flag, argument, or output.\n\n---\n\n## 0.6.15 (2026-06-10)\n\n### CLI\n\n#### Minor Changes\n\n- ca87265: Unify workflow and agent run starts behind the canonical `/api/v1/run/\\{target}` endpoint, root `eigenpal run` / `eigenpal rerun` commands, and root SDK `client.run()` / `client.rerun()` methods.\n\n The old nested CLI commands and SDK resource methods for starting workflow or agent runs have been removed.\n\n#### Patch Changes\n\n- 5ea0bb5: `workflow dataset pull` gains `--example-id <id>` (repeatable) to export a single example or a selected subset of a dataset, instead of always pulling the whole dataset. The subset ZIP uses the same archive layout as a full pull, so it re-imports into any dataset via `dataset push --mode append`. Requesting an example id that does not exist for the workflow exits non-zero.\n\n### SDK\n\n#### Minor Changes\n\n- ca87265: Unify workflow and agent run starts behind the canonical `/api/v1/run/\\{target}` endpoint, root `eigenpal run` / `eigenpal rerun` commands, and root SDK `client.run()` / `client.rerun()` methods.\n\n The old nested CLI commands and SDK resource methods for starting workflow or agent runs have been removed.\n\n---\n\n## 0.6.10 (2026-06-08)\n\n### CLI\n\n#### Patch Changes\n\n- 99ca1b4: Unify agent and workflow run commands and SDK helpers on the shared `/api/v1/runs` API, including the public `client.runs` facade and regenerated SDK reference docs.\n\n### SDK\n\n#### Patch Changes\n\n- 99ca1b4: Unify agent and workflow run commands and SDK helpers on the shared `/api/v1/runs` API, including the public `client.runs` facade and regenerated SDK reference docs.\n\n---\n\n## 0.6.9 (2026-06-04)\n\n### SDK\n\n#### Minor Changes\n\n- 5e7c051: Add `observability` (phase timeline + structured failure) to workflow execution and agent run status API responses.\n\n---\n\n## 0.6.6 (2026-06-03)\n\n### CLI\n\n#### Patch Changes\n\n- 245f347: Clean up the agent CLI surface by removing obsolete compatibility commands, moving reruns to `agents rerun`, and replacing run pulls with canonical artifact fetching.\n- 5ab00ee: Tighten permissions on `~/.config/eigenpal/credentials.json` and its parent directory to owner-only (0600 / 0700). Previously the file was written 0600 but the parent directory inherited the user's umask (typically 0755), allowing other local users to list the directory and stat the file. The CLI now also re-tightens permissions on every write, so installs created with older versions are corrected on the next `auth login` / `auth use`.\n\n---\n\n## 0.6.4 (2026-06-03)\n\n### CLI\n\n#### Patch Changes\n\n- c3486a5: Fix agent git cutover QA findings: dashboard runs now navigate to the created run, inbound email aliases preserve mixed-case organization qualifiers, sandbox source materializes under `/workspace/agent`, run artifact downloads use direct paths like `/files/eigenpal.lock`, wait-for-completion responses include source provenance, and CLI wait/watch commands exit nonzero for failed or cancelled runs.\n\n### SDK\n\n#### Patch Changes\n\n- c3486a5: Fix agent git cutover QA findings: dashboard runs now navigate to the created run, inbound email aliases preserve mixed-case organization qualifiers, sandbox source materializes under `/workspace/agent`, run artifact downloads use direct paths like `/files/eigenpal.lock`, wait-for-completion responses include source provenance, and CLI wait/watch commands exit nonzero for failed or cancelled runs.\n\n---\n\n## 0.6.2 (2026-06-02)\n\n### CLI\n\n#### Patch Changes\n\n- d2202b6: List all agent runs for unqualified targets, and reserve source-ref filtering for explicit `@ref` targets.\n\n---\n\n## 0.6.0 (2026-06-02)\n\n### CLI\n\n#### Minor Changes\n\n- 2aeeaf2: Add native source `git save` and branch-aware `git release` flows for Git-backed builder workspaces.\n\n#### Patch Changes\n\n- 2aeeaf2: Complete the agent Git cutover with pluralized agent CLI commands, source-ref run support, lockfile metadata, and regenerated SDK/docs surfaces.\n- 2aeeaf2: Expose Git-backed agent source refs and public source automation APIs consistently across CLI docs and SDK facades.\n\n### SDK\n\n#### Patch Changes\n\n- 2aeeaf2: Complete the agent Git cutover with pluralized agent CLI commands, source-ref run support, lockfile metadata, and regenerated SDK/docs surfaces.\n- 2aeeaf2: Expose Git-backed agent source refs and public source automation APIs consistently across CLI docs and SDK facades.\n\n---\n\n## 0.5.12 (2026-06-02)\n\n### CLI\n\n#### Minor Changes\n\n- d3b0768: Add `control.fail` and `ai.classify` step types, plus the `expected/error.json` dataset assertion format.\n - `control.fail` terminates a workflow with a typed status code + message envelope. Optional `condition` template gates the fail. Compose with `ai.classify` to reject documents that match an undesired label.\n - `ai.classify` runs single-label closed-set classification through the existing extract LLM pipeline. Output is `\\{ label, confidence, reason }`, where `label` is constrained to the configured names.\n - `examples/<name>/expected/error.json` (mutually exclusive with `output.json`) lets eval examples assert that a workflow should fail with a specific `\\{ code, messageContains, step }`. The exact-diff evaluator scores 1 on match, 0 otherwise.\n - `eigenpal workflow validate` now catches `expected/error.json` shape issues and per-step config violations (e.g. `ai.classify` with fewer than two labels) at push time instead of deferring to runtime.\n\n Skill reference docs (`step-types.md`, `dataset-format.md`, `evaluators.md`, `workflow-yaml.md`) updated.\n\n#### Patch Changes\n\n- 99cad97: Skill reference (auto-generated from `WorkflowDefinitionSchema`) now documents the new `values` row for enum inputs, alongside the existing `items` row used by array inputs. Output-only doc refresh — no CLI behavior change.\n- d70f697: Document the `control.parallel`, `control.parallel_map`, `control.foreach`, `control.if`, and `control.block` step types in the bundled skill reference. The auto-generated catalog cannot render nested step shapes, so the YAML form, output access paths (e.g. `steps.<parallel>.output.<branch>.<inner>.<field>`), and scoping rules now live as hand-written prose. Also documents the multi-step iteration hazard: only the LAST inner step's output is keyed into each `items[i]` for `parallel_map` / `foreach` — end the body with a `transform.script` if you need to preserve intermediate fields.\n- ed2cde6: Fix `eigenpal workflow pull` writing a 0-byte file. The v1 single-workflow endpoint now returns the current YAML at the top level (`yamlContent`) via a new `WorkflowDetail` response shape, and the CLI throws a clear error instead of silently writing empty output when no version has been published. Also fixes adjacent regressions caused by the same picker: `workflow list` now shows the workflow name and version columns (previously always `-`), `workflow push --bump` reads the server's current version correctly, the \"did you mean?\" suggestion on a slug typo lists candidates again, and `workflow execution list` shows a duration column computed from the run start/end timestamps.\n\n---\n\n## 0.5.11 (2026-05-26)\n\n### CLI\n\n#### Patch Changes\n\n- 2958f4d: Fix Git-backed source smoke-test polish: hidden `git show` and `git sync` now accept bare agent slugs, and workflow scaffolds use the current `triggerMethods` YAML shape.\n\n---\n\n## 0.5.10 (2026-05-26)\n\n### CLI\n\n#### Patch Changes\n\n- aee7e0c: Add hidden Git source commands for editing trigger policy and encrypted secrets.\n\n---\n\n## 0.5.9 (2026-05-26)\n\n### CLI\n\n#### Major Changes\n\n- fadb59b: CLI command tree reorganized around the data model. Top-level surface is now\n `workflow`, `agent` (reserved), and `skill`; everything that operates on a\n workflow lives under `workflow`, grouped by sub-entity.\n\n Renames (clean break — no aliases):\n - `eigenpal exec <slug>` → `eigenpal workflow execution run <slug>`\n - `eigenpal clear` → `eigenpal workflow clear`\n - `eigenpal install-skill` → `eigenpal skill` (same interactive multiselect UX)\n - `eigenpal execution \\{get,list,watch,compare}` → `eigenpal workflow execution \\{…}`\n - `eigenpal workflow set-definition` → `eigenpal workflow push`\n - `eigenpal workflow get-definition` → `eigenpal workflow pull`\n - `eigenpal workflow set-evaluators` / `get-evaluators` → `workflow evaluators \\{push,pull}`\n - `eigenpal workflow set-dataset` / `get-dataset` / `list-examples` → `workflow dataset \\{push,pull,list}`\n - `eigenpal workflow run-experiment` / `get-experiment-status` / `get-experiment-results` /\n `get-eval-results` / `list-executions` → `workflow experiment \\{run,status,results,eval-results,list}`\n - `eigenpal workflow list-versions` / `restore-version` → `workflow version \\{list,restore}`\n\n[View full release notes →](/releases/0.5.9)\n\n{/* GENERATED:CHANGELOG_INDEX END */}\n"
|
|
23
|
+
"content": "---\ntitle: Changelog\ndescription: Production release history for the EigenPal platform.\n---\n\nEigenPal ships on a unified platform version. Each production release updates Studio, the public API, infrastructure, and (when applicable) the CLI and SDKs together.\n\n{/* GENERATED:CHANGELOG_INDEX START */}\n\n## 0.20.1 (2026-09-23)\n\n### Platform (Studio)\n\n- Credit limits now apply consistently across the product. Agent runs, the workflow builder assistant, and the expression generator are checked against your remaining balance before they start, and the assistant and expression generator now record their usage on your usage page instead of being invisible. A cancelled agent run is billed for the work it actually completed rather than dropping off your usage entirely. Organization creation is capped per account, both by how many you own at once and by how many you create over a rolling window, so one account cannot spin up unlimited free trials. A very long builder conversation is now refused with a message asking you to start a new chat, rather than being sent to the model in full. Deleting an organization now removes its stored files before the organization itself disappears. A large organization can take more than one pass, and the dialog now says accurately what happens: files are removed immediately and clear backups within 7 days.\n\n### Public API\n\n- Starting a run now returns `402 insufficient_credits` when your organization has spent its credit allowance. The check happens before the request body is read, so no files are uploaded and no work begins on a run that cannot be paid for. File uploads return the same status for the same reason, and both are now described in the API reference. The API reference also documents `503`, which endpoints return when request accounting is briefly unavailable. It means the request was not processed and is safe to retry; it is not a rate-limit rejection.\n\n---\n\n## 0.20.0 (2026-09-22)\n\n### Platform (Studio)\n\n- Datasets can now be sent for client review without exporting files. Create a review request from a dataset, highlight the fields that need attention, mark others as not required, and invite client teammates with the new reviewer role. They walk examples from a dropdown, inspect the fields, leave notes, record per-field decisions, and approve or reject each row. Closing a finished review does not auto-apply changes — reconcile expected outputs manually. The Reviews queue keeps finished requests visible with a status filter so old approvals stay findable. Reviewers see the same Studio shell with permission-aware empty states.\n\n### Public API\n\n- New dataset review endpoints under `/api/v1/automations/:id/dataset-review-requests`: create a review from dataset examples with reviewer `instructions`, `focusFields` (paths plus optional reasons), `ignoredFields` for paths reviewers can skip, and optional `itemNotes`. Approve, edit, reject, reopen, comment, or record a `field-decision` on each example (including clearing a decision with `decision: null`), then poll `progress.complete` and close the request with `PATCH` status. Dataset reconciliation stays manual — nothing is deleted by reject. A new `reviewer` organization role can read review queues and submit item decisions but cannot edit workflows.\n\n### CLI\n\n- `eigenpal workflow dataset review-request` (and the `eigenpal agents dataset` mirror) is the agent-friendly review loop: create a request with reviewer instructions, `--focus` / `--focus-reason` paths, `--ignore` paths reviewers can skip, and per-example `--item-note` / `--field-note` comments; `list`/`get`/`events` expose `progress.complete`, `fieldDecisions`, and `inputDrifted`; `item --action` records approve/reject/comment/edit plus per-field `field-decision` (clear with `--clear` / `--decision null`); `update --status closed` finishes the request. There is no auto-apply — pull and reconcile examples manually. Reject is recommendation-only; nothing is deleted.\n\n### SDK\n\n- `client.automations.datasetReviewRequests` (`dataset_review_requests` in Python) covers the full dataset review lifecycle: list and get with `progress`, `focusFields`, `ignoredFields`, `fieldDecisions`, and `inputDrifted`; create with reviewer instructions and per-field notes; update request metadata or close with status; update items including `field-decision` (pass `decision: null` to clear); and the per-user activity trail. Dataset write-back stays manual — there is no lock endpoint.\n\n### Infrastructure & processing\n\n- Replace the eagerly constructed `eigenpalAjv` singleton with a lazy `getEigenpalAjv()` accessor. Ajv compiles schemas with `new Function`, which the Studio Content-Security-Policy forbids — constructing at import time crashed every page whose client bundle transitively imported `@eigenpal/types` validation (including all review surfaces, which never validate client-side). Server-side call sites are unchanged apart from the accessor.\n\n---\n\n## 0.19.1 (2026-09-21)\n\n- Internal improvements.\n\n---\n\n## 0.19.0 (2026-09-21)\n\n### Platform (Studio)\n\n- Agent builder sessions can now be given storage credentials limited to their own session folder instead of the whole storage account. Set a Cloudflare account id and API token, or an AWS role, and each training sandbox receives a short-lived key that can only read and write its own files. Deployments that do not configure this keep working exactly as before and log a warning, and a new setting makes the platform refuse to start a sandbox unless scoped credentials are available.\n- Studio security hardening. Parsed document text shown in run traces and grounding views is now sanitized before rendering, so a crafted document can no longer inject active content into the page. Observability settings now require administrator access to view, and the values of any authorization headers you configure are masked once saved, so they are never sent back to the browser. Saving a renamed header now asks you to retype its value instead of quietly clearing the configuration. Outbound observability destinations are validated to reject internal and unencrypted endpoints on hosted plans. Editor assets are now served from Eigenpal's own domain instead of a public content network. Self-hosted deployments that use password sign-in no longer accept open self-registration. Creating the first account still works, and anyone holding an invitation can still create their account, but an uninvited visitor can no longer join an existing workspace. Set `EIGENPAL_ALLOW_OPEN_SIGNUP=true` to restore the previous behavior. Agent training and email trigger surfaces are now scoped more tightly. Email alias changes are accepted only through the agent that owns the alias, so editing or revoking one from a different agent's page now reports not found. Opening a training session that belongs to a different workspace or a different agent is refused instead of returning a server error. Each agent workspace now runs with credentials valid only for its own session, so a workspace can no longer act on any session but its own. Sign-in and account safety. Changing your password now signs out your other sessions, so a password change ends access from a device you no longer control. Accepting an invitation now requires the invitation link itself rather than just the invited address, so knowing that someone was invited is no longer enough to create an account in their name. Requests that arrive from another site are refused, which closes cross-site request forgery against pages you are signed in to. Set `EIGENPAL_TRUSTED_ORIGINS` if you serve Eigenpal on more than one hostname.\n\n### Public API\n\n- Agent endpoints that accept an agent id now resolve it strictly within the calling organization. Requesting an id belonging to another organization returns not found instead of reading or modifying it. Run and step endpoints apply the same organization check to execution ids. Uploads that omit a declared length are now measured while they stream and return 413 once they exceed the request limit, rather than being read into memory first. Operator source tokens are accepted only on the source and authentication check endpoints they are documented for. Webhook endpoints are now checked when you save them, not only when a delivery is attempted. A destination the platform cannot deliver to is rejected with a validation error at creation and update time, instead of being accepted and then failing silently on every send. Self-hosted deployments that deliver to their own internal network are unaffected. Every endpoint that starts a new run now honours the automation's trigger settings, the same way `POST /api/v1/runs` already did. That covers rerunning a run, starting an experiment, and running a single dataset example, including their streaming variants. An API key calling one of these on an automation whose API trigger is turned off now receives `403 api_trigger_disabled`, and a dashboard session calling one on an API-only automation receives `403 manual_trigger_disabled`. If an existing integration starts returning 403, turn the API trigger back on for that automation.\n- Self-hosted Prometheus scrapes now require the dedicated scrape token in every deployment. An organization API key is no longer enough to read the cluster snapshot. A deployment without `EIGENPAL_METRICS_SCRAPE_TOKEN` returns 404 on the metrics route, so set the token before upgrading if you scrape today with an API key. The headless workflow server no longer serves a network address without an API token. If you set `HOST` yourself, the server now exits at startup unless you also set `HEADLESS_API_TOKEN` or `HEADLESS_ALLOW_UNAUTHENTICATED_BIND=1`. If you never set `HOST`, the bind address changes from `0.0.0.0` to `127.0.0.1`, which inside a container means a published port stops accepting connections while the container still reports healthy. Either set `HEADLESS_API_TOKEN` (16 characters or more) together with `HOST=0.0.0.0`, or set `HEADLESS_ALLOW_UNAUTHENTICATED_BIND=1` to keep the previous behaviour. Members can no longer pull decrypted agent environment secrets. Use an owner or admin key, or decrypt a secret for a specific run.\n\n### Infrastructure & processing\n\n- Self-hosted Prometheus scrapes now require the dedicated scrape token in every deployment. An organization API key is no longer enough to read the cluster snapshot. A deployment without `EIGENPAL_METRICS_SCRAPE_TOKEN` returns 404 on the metrics route, so set the token before upgrading if you scrape today with an API key. The headless workflow server no longer serves a network address without an API token. If you set `HOST` yourself, the server now exits at startup unless you also set `HEADLESS_API_TOKEN` or `HEADLESS_ALLOW_UNAUTHENTICATED_BIND=1`. If you never set `HOST`, the bind address changes from `0.0.0.0` to `127.0.0.1`, which inside a container means a published port stops accepting connections while the container still reports healthy. Either set `HEADLESS_API_TOKEN` (16 characters or more) together with `HOST=0.0.0.0`, or set `HEADLESS_ALLOW_UNAUTHENTICATED_BIND=1` to keep the previous behaviour. Members can no longer pull decrypted agent environment secrets. Use an owner or admin key, or decrypt a secret for a specific run.\n- Document and archive processing is more resilient to malformed or hostile input. Dataset archive imports now apply a limit on entry count and hold far less memory while expanding, so a small archive can no longer exhaust a request. Office documents are checked against their real expanded size rather than the size recorded inside the file, which blocks highly compressed payloads that previously passed inspection. PDF page rendering moved to a newer engine that removes a document driven code execution path. Script transform steps have a shorter maximum run time that is now capped relative to worker health checks, so a long running script cannot stall other work. With stock settings the ceiling drops from 30 seconds to 15 seconds; self-hosted deployments that need more can raise `HEALTH_LIVENESS_STALE_MS`, since the ceiling is half that value. Workflow processing is more resilient to hostile input. Template rendering now has time and memory ceilings, so a crafted template can no longer stall a worker and delay other runs. Deep merges in the combine transform can no longer be steered into altering shared state. External file sources reject addresses that are not plain HTTP endpoints.\n\n---\n\n## 0.18.0 (2026-09-21)\n\n### Platform (Studio)\n\n- Workflows can crop normalized regions from PDFs and images into JPEG artifacts with the new `transform.crop-regions` step — pair it with parse output and script steps to build figure or layout evidence pipelines without a figure-specific step type. Turn on optional **`cache: true`** on **`ai.parse`** to reuse prior parse output for the same file bytes and parse settings across runs (stored in tenant blob storage; no expiry yet).\n\n---\n\n## 0.17.5 (2026-09-21)\n\n### Platform (Studio)\n\n- Summary Agent: spreadsheet uploads now use a hardened parser that prevents crafted workbook content from causing excessive processing or modifying object prototypes.\n\n### CLI\n\n- CLI skill reference documents the new `ai.figure-crops` workflow step for cropping and captioning figures from parsed PDFs.\n\n### SDK\n\n- Python SDK: installs now require `anyio` 4.14.2 or newer. Earlier versions encoded host names with IDNA 2003 when opening a TLS connection, so a crafted host name could be matched against the wrong certificate. The TypeScript SDK is unaffected.\n\n---\n\n## 0.17.4 (2026-09-18)\n\n### Platform (Studio)\n\n- Strengthen organization access controls so role permissions, API-key scopes, and member removal apply consistently across Studio and the API. Webhook configuration and signing secrets are restricted to organization owners and admins. Service credentials cannot exceed member permissions, while members retain file and review editing through the API.\n- Organization owners can invite new users directly as owners. Owner invitations can only be created and managed by existing owners.\n\n### Public API\n\n- Strengthen organization access controls so role permissions, API-key scopes, and member removal apply consistently across Studio and the API. Webhook configuration and signing secrets are restricted to organization owners and admins. Service credentials cannot exceed member permissions, while members retain file and review editing through the API.\n\n### Infrastructure & processing\n\n- Cloud workflow HTTP and website-reader actions now restrict requests to public HTTP/S destinations, verify TLS for HTTPS requests, and reject HTTPS-to-HTTP redirects. Responses are limited to 20 MiB and requests to 120 seconds. Single-tenant installations retain private-network integration support.\n\n---\n\n## 0.17.3 (2026-09-18)\n\n### Public API\n\n- Large PDF parses are now more reliable under parallel load. The OCR service paces concurrent pages per document so multi-page jobs no longer exhaust inference memory and retry, which previously stalled big documents behind repeated restarts.\n\n---\n\n## 0.17.2 (2026-09-17)\n\n### Platform (Studio)\n\n- Settings gains a Data retention section for workspace admins: see how much file storage past and present runs consume, choose how long eval and other runs are kept, preview what falls past the horizon, and delete those runs in capped passes until clear. Runs that are still active are always kept. Enforcement offers two modes: purge input files only (run history and outputs stay, freeing the bulky source documents while keeping the audit trail) or delete full runs. Storage usage splits run inputs from outputs so admins can see what input-only cleanup would free.\n\n### Public API\n\n- Rerunning a run whose input files were removed by data retention now returns a clear `409 inputs-purged` error instead of failing while copying the missing files. Run history and outputs remain available.\n\n---\n\n## 0.17.1 (2026-09-15)\n\n- Internal improvements.\n\n---\n\n## 0.17.0 (2026-09-15)\n\n### Platform (Studio)\n\n- Studio can connect to a live agent inference session even when that session runs in a local sandbox instead of the hosted cloud environment.\n\n### Infrastructure & processing\n\n- Agent inference can now run in a local container sandbox, so on-prem and air-gapped deployments no longer need a cloud sandbox provider.\n- Agent runs can now execute in customer-hosted sandbox environments instead of only the Eigenpal cloud, and local Docker sandboxes connect reliably on plain localhost setups.\n\n---\n\n## 0.16.13 (2026-09-14)\n\n- Internal improvements.\n\n---\n\n## 0.16.12 (2026-09-14)\n\n### Platform (Studio)\n\n- Studio can import large dataset ZIP archives without taking the app down, including archives whose paths use Windows-style backslashes. Opening a long-running workflow no longer pulls every step’s full input and output at once. Run pages stay available, still show the steps timeline when phase data is missing, and keep the last loaded view if a refresh fails — with a retry control instead of a blank error page.\n\n### Public API\n\n- `GET /api/v1/runs/\\{id}?expand=execution` and `GET /api/v1/runs/\\{id}/steps` now return slim step rows (identity, status, timing, and a capped error excerpt) instead of inlining every step’s input and output. Inspect one step’s full payloads with the new `GET /api/v1/runs/\\{id}/steps/\\{stepExecutionId}` endpoint.\n\n### CLI\n\n- `eigenpal runs get` lists slim step rows by default. Pass `--include input,output` or `--step` to fetch full payloads for the steps you care about.\n\n### SDK\n\n- The TypeScript and Python SDKs now include `GET /api/v1/runs/\\{id}/steps/\\{stepExecutionId}` so you can load one step’s full input and output after listing slim run steps.\n\n---\n\n## 0.16.11 (2026-09-11)\n\n### Platform (Studio)\n\n- Studio: organization switching and other labeled menus now open reliably without a client-side error.\n\n---\n\n## 0.16.10 (2026-09-10)\n\n### Infrastructure & processing\n\n- OCR processing now distinguishes temporary host availability issues from true processing timeouts, keeps redundant production capacity warm, and pages only when unfinished work is affected. Short self-healing interruptions remain visible for diagnosis without generating misleading recovery alerts.\n\n---\n\n## 0.16.9 (2026-09-10)\n\n### Platform (Studio)\n\n- Harden web image handling, document image processing, and email delivery against crafted inputs that could cause remote code execution, excessive resource use, or recipient-validation bypasses.\n\n### Infrastructure & processing\n\n- Harden web image handling, document image processing, and email delivery against crafted inputs that could cause remote code execution, excessive resource use, or recipient-validation bypasses.\n\n---\n\n## 0.16.8 (2026-09-10)\n\n### Platform (Studio)\n\n- Files are easier to recognize throughout Studio with refreshed Office logos, dedicated PDF, archive, text, JSON, and code treatments, plus image thumbnails. File inputs now use a clearer rounded drag-and-drop experience with consistent selected-file previews.\n\n---\n\n## 0.16.7 (2026-09-10)\n\n### Platform (Studio)\n\n- File uploads now infer supported document media types from the filename when clients provide an empty or generic content type, allowing original Outlook messages and macro-enabled workbooks to upload without conversion.\n\n### Public API\n\n- File uploads now infer supported document media types from the filename when clients provide an empty or generic content type, allowing original Outlook messages and macro-enabled workbooks to upload without conversion.\n\n### CLI\n\n- The CLI now uploads macro-enabled Excel workbooks with the correct media type, so original `.xlsm` workflow inputs work without manual conversion.\n\n### SDK\n\n- TypeScript SDK file helpers now infer the correct media types for `.xlsm` workbooks and `.msg` Outlook messages.\n\n### Infrastructure & processing\n\n- Document parsing now reads Excel, legacy Excel, and macro-enabled workbooks directly, preserving every non-empty sheet and its cell evidence without executing formulas or macros. Large single-page extractions are also split into bounded AI context windows instead of failing at the model limit.\n\n---\n\n## 0.16.6 (2026-09-09)\n\n### Infrastructure & processing\n\n- Template processing now enforces memory limits when joining large collections, preventing crafted templates from exhausting worker memory.\n\n---\n\n## 0.16.5 (2026-09-08)\n\n### Platform (Studio)\n\n- Human review is now available in production, including workflow authoring and review queues.\n\n### Public API\n\n- Human review API endpoints are now available in every production organization for listing tasks, confirming fields, and completing reviews.\n\n### Infrastructure & processing\n\n- Workflow and agent runs can now request human review in every production organization.\n\n---\n\n## 0.16.4 (2026-09-08)\n\n### Platform (Studio)\n\n- Studio adds List Archive and Extract Archive File steps for ZIP workflow inputs. Enumerate archive contents, wire `\\{\\{ item.path }}` through foreach, and pass extracted files straight into Parse, Vision, or Search Files without leaving the builder.\n- Studio now finishes multi-GB file uploads with resumable multipart transfers, retrying individual parts without restarting the whole file.\n- Studio workflows now include Search Files: ask a question about a ZIP archive and get a cited answer plus the files the step inspected. Scope the search to a folder inside the archive and use the same model and reasoning controls as other AI steps.\n\n### Public API\n\n- Upload ZIP archives as reusable workflow inputs through the Files API. Archives can be much larger than single documents, so teams can pass bundled evidence, exports, or multi-file drops into the same runs that already accept PDFs and Office files.\n- File uploads can now negotiate a resumable multipart session for multi-GB objects, with on-demand part URLs, authoritative resume listing, and safe completion that never overwrites a finished file.\n- Starting a run from a reusable file id now keeps a private run-owned reference to the original bytes instead of duplicating large uploads. Deleting the reusable file leaves past runs readable until those runs themselves are deleted.\n\n### CLI\n\n- Dataset import and export now keep a single `/api/v1` prefix when the CLI base URL already includes `/api/v1`, so those commands reach the dataset API instead of a doubled `/v1/v1` path.\n- The CLI now uploads large run files with resumable, storage-direct transfers, so multi-GB inputs stream from disk instead of loading into memory or a single request.\n- The CLI now recognizes `.zip` files when uploading reusable workflow inputs, so archive uploads get the correct content type without extra flags.\n\n### SDK\n\n[View full release notes →](/releases/0.16.4)\n\n---\n\n## 0.16.3 (2026-09-08)\n\n### Platform (Studio)\n\n- Human review: open pending reviews directly from run details and confirm unchanged fields inline from the field list.\n\n### Public API\n\n- Human review field confirmations now preserve valid JSON `null` values and return clear validation errors when a reviewed value does not match its schema.\n\n---\n\n## 0.16.2 (2026-09-08)\n\n### Platform (Studio)\n\n- Human review: pause workflows and agents only when selected fields need attention, inspect source files beside structured output with spatial citation highlights when lineage is available, correct and confirm values, then approve the same run to continue. Confidence thresholds, explicit field selection, required-field progress, rejection, and cancellation keep exception review focused instead of forcing teams to recheck every field.\n\n### Public API\n\n- Human review APIs now list pending tasks, return review data and source-file references, persist field corrections and confirmations, and approve or reject paused runs with optimistic concurrency protection. Task detail may also include resolved lineage and parsed-document context when an upstream grounded extract produced sidecars.\n\n### CLI\n\n- Workflow authoring now includes human-review guidance and ready-to-use templates for confidence-based exception review and explicit approval of critical fields.\n\n### SDK\n\n- TypeScript and Python SDKs now expose human-review resources for listing and retrieving tasks, confirming corrected fields, downloading attached source files, and approving or rejecting paused runs.\n\n### Infrastructure & processing\n\n- Grounded extraction now runs the same shared algorithm locally when a parse step supplies a valid structured document and your provider supports strict structured output. Step JSON stays schema-shaped with `_grounding` metadata; lineage and the parsed document graph are stored as optional sidecars for review and audit, not mixed into workflow output. Text-only inputs and unsupported providers continue to use the existing text grounding path with clear degraded markers when the shared path is unavailable.\n\n---\n\n## 0.16.1 (2026-09-07)\n\n### Platform (Studio)\n\n- GPT-6 Astra is available across workflows, agents, evaluations, and vision tasks, with configurable reasoning and current token pricing.\n- Self-hosted PaddleOCR models now appear with clear provider identity in Studio model selectors and settings.\n- Archive imports now reject malformed ZIP64 data safely instead of risking an unbounded processing loop.\n\n### CLI\n\n- CLI archive handling now rejects malformed ZIP64 data safely instead of risking an unbounded processing loop.\n\n### Infrastructure & processing\n\n- GPT-6 Astra is available across workflows, agents, evaluations, and vision tasks, with configurable reasoning and current token pricing.\n- Self-hosted deployments can connect directly to PaddleOCR-VL for high-quality document parsing, with bounded concurrency and long-running PDF support built in.\n\n---\n\n## 0.16.0 (2026-09-07)\n\n### Platform (Studio)\n\n- Agent model pickers are now compact, searchable, grouped by provider, and ordered from the most capable model to the least without changing configured defaults.\n- Send Email is now a first-class workflow action. Add Resend or SMTP servers in Settings → Email servers, then pick a stable `ems_…` server on the step — including generated files from the same run as attachments. Cloud and on-prem share this Settings surface; there is no default server. Secrets stay encrypted, and reads never show credentials. Changing an SMTP host, username, or provider asks you to re-enter the password so a stored secret cannot follow a new destination.\n\n### Public API\n\n- The public API now manages organization email servers at `/v1/email-servers`: list, create, inspect, update, delete, and send a connectivity test. Each server is an `ems_…` resource with a Resend or SMTP transport. Secrets are encrypted and never returned; disabled servers reject tests, and names must be unique among live servers. Updating SMTP to a different host or username requires a new password or explicitly clearing authentication — the previous password is never reused against a new destination.\n\n### CLI\n\n- Manage organization email servers with `eigenpal email-servers`: list and inspect `ems_…` servers, create or update Resend and SMTP providers (including an optional SMTP CA PEM), delete servers, and send a live test message with `--to`. Secrets are read from stdin, a file, or a secure prompt — never from command-line flags.\n\n### SDK\n\n- TypeScript and Python SDKs now manage organization email servers: list, create, inspect, update, delete, and send a connectivity test. Stored credentials are never returned.\n\n### Infrastructure & processing\n\n- Send Email delivers through the organization server selected on the step. There is no fallback: a missing, deleted, or disabled server fails the run. Evaluation runs skip delivery, including workflows invoked from an eval. Cancelling a run aborts an in-flight send. Multi-tenant SMTP servers must resolve to public addresses, while single-tenant deployments can use internal relays. Partial SMTP acceptance reports which recipients were delivered or rejected so operators can avoid duplicate reruns. SMTP may still deliver twice if a worker stops after the relay accepts the message; Resend deduplicates the same step attempt.\n\n---\n\n## 0.15.1 (2026-09-04)\n\n### Infrastructure & processing\n\n- OpenParser OCR capacity now recovers cleanly after failed updates, avoiding unnecessary warm resources while preserving active document processing.\n\n---\n\n## 0.15.0 (2026-09-04)\n\n### Platform (Studio)\n\n- Workflow validation now explains when a catalog model belongs in `provider` instead of the raw `model` override, and reruns preserve clean original filenames in generated outputs and citations.\n- Make document inputs uploaded in Studio datasets available to experiment runs, including examples saved by earlier releases.\n\n### Public API\n\n- Experiment result responses and JSON exports now include evaluator-specific structured details, so clients can identify the exact JSON path, expected value, and actual value behind a failed comparison. CSV exports retain their existing stable columns.\n\n### CLI\n\n- Experiment analysis is now built into the CLI for workflows and agents: summarize pass, fail, error, and score totals; filter failures by evaluator; inspect structured discrepancy paths; and compare actual outputs between batches. Run payloads can be projected with `--select`, and repository-level validation discovers nested workflow projects automatically. Polling commands also expose consistent wait limits and reject flag combinations that cannot produce a reliable verdict. Waiting commands now keep human output concise by default; pass `--json` whenever scripts need the terminal payload.\n- `eigenpal docs` now lists, searches, and reads the complete release-matched platform documentation offline, including detailed evaluator syntax, workflow step guides, CLI reference, and the OpenAPI contract.\n- CLI file uploads now send valid content types for Outlook and unknown files, cancellation confirms the asynchronous request clearly, and run comparisons show every repeated workflow step by branch and iteration path.\n\n### Infrastructure & processing\n\n- Make document inputs uploaded in Studio datasets available to experiment runs, including examples saved by earlier releases.\n- Exact-diff evaluators can exclude volatile fields with `ignore: true`, including nested fields inside a selected object or array. This keeps golden outputs readable while scoring only stable business data such as identities, names, and classifications.\n- Script steps now bind inputs by parameter name, so workflows behave consistently after storage even when JSON key order differs from the authored YAML.\n\n[View full release notes →](/releases/0.15.0)\n\n---\n\n## 0.14.3 (2026-09-04)\n\n### Platform (Studio)\n\n- Model selection now includes the GPT 5.6 Sol, Terra, and Luna lineup plus Claude Fable 5, Fable 5.1, Opus 5, and Sonnet 5. Reasoning effort can be configured for supported workflow steps, agent training and runs, workflow-building chat, and LLM judges; existing choices keep their current provider defaults when the setting is omitted.\n\n### CLI\n\n- Workflow YAML can configure model-aware reasoning effort on AI steps and LLM judges. Omit the setting to preserve each model's current default.\n\n### Infrastructure & processing\n\n- AI processing supports the latest GPT and Claude request formats, including reliable structured extraction with Claude Fable 5 and Fable 5.1. Workflow and agent execution can pass an optional model-aware reasoning effort while preserving previous defaults, and agent sandboxes can use GPT 5.6, Claude Fable 5, Fable 5.1, Opus 5, and Sonnet 5.\n\n---\n\n## 0.14.2 (2026-09-02)\n\n### Infrastructure & processing\n\n- Single-node deployments can now upgrade installations with large legacy datasets without startup failures or loss of trigger configuration.\n\n---\n\n## 0.14.1 (2026-09-02)\n\n### Infrastructure & processing\n\n- Single-node deployments can now upgrade installations with legacy run review data without startup failures.\n\n---\n\n## 0.14.0 (2026-09-02)\n\nThis release gives document teams more control over structured-data quality.\nExact-diff evaluators can express field-specific matching rules, PDF parsing can\npreserve visual layout, and spreadsheet conversion can retain the rows, columns,\nand displayed values that matter to downstream workflows.\n\nCLI authoring guidance makes these capabilities easier to discover and safer to\nautomate, with non-interactive commands failing clearly instead of waiting on\nunavailable prompts.\n\n### Platform (Studio)\n\n- `ai.parse` adds `outputFormat: layout` for native PDF extraction. It returns fixed-width plain text that preserves columns, spacing, and line breaks for multi-column forms and tables that lose meaning when flattened. This PDF-only format must be selected explicitly with `parseMode: native` or `parseMode: native-or-ocr`: native mode fails closed if layout extraction cannot complete, while hybrid mode keeps accepted layout pages and substitutes OCR markdown only for suspect or empty pages. Existing formats and defaults are unchanged.\n- Spreadsheet to JSON now handles `.xls` and `.xlsx` workbooks with configurable headerless input or an explicit header row, named or positional column projection, rectangular ranges, and raw or displayed cell values. Displayed values preserve formatted text such as dates, leading zeros, punctuation, diacritics, and embedded newlines. Blank-cell and blank-row policies make sparse sheets predictable, while optional sheet metadata and diagnostics explain the selected range and non-fatal issues. Existing zero-config output remains `rows`, plus `fileId` when CSV output is enabled; zero-config CSV keeps the full selected sheet, and configured CSV follows the same projection. File, row, column, and cell limits reject unsafe workloads before conversion.\n- Exact-diff evaluators add composable per-field rules for extraction outputs. Choose ordered or unordered comparison independently from `items: at-least | at-most | exactly`, set numeric tolerances, and reject unexpected object fields where strict output shapes matter. Ordered arrays retain prefix-compatible matching, while unordered arrays find the best one-to-one structural pairing instead of depending on row order. Unordered object arrays can also use typed `matchBy` identities such as `sku` or `[country, sku]` for predictable single- or composite-key matching. Studio now provides a rule editor with path-aware validation. Grounding metadata is excluded from scoring, oversized comparison workloads fail safely with bounded diagnostics, and existing evaluator configurations keep their historical behavior.\n\n### Public API\n\n- Template creation now accepts reusable file references correctly, restoring CLI template uploads and workflow pushes that use local DOCX or XLSX files.\n\n### CLI\n\n[View full release notes →](/releases/0.14.0)\n\n---\n\n## 0.13.2 (2026-09-01)\n\n### CLI\n\n- CLI installation no longer downloads packages already included in its self-contained executable, reducing install overhead and improving compatibility with restricted enterprise networks.\n\n---\n\n## 0.13.1 (2026-08-31)\n\n### Platform (Studio)\n\n- Workflows can turn JSON rows into a downloadable Excel workbook with a new JSON to XLSX step. Pick ordered columns, map an array of objects, and get a `.xlsx` run output — including multi-sheet workbooks — without filling a template.\n- Studio now uses the shared theme provider, so system / light / dark stays aligned with OpenParser instead of drifting independently.\n- Publishing a workflow that still has a local `template: ./file.xlsx` path now fails with a clear error. Use `eigenpal workflow push` to upload the file, or set `templateId` to a `tmpl_…` id first.\n- Studio template uploads and replacements now create immutable, checksum-backed revisions and discover tokens consistently across DOCX and XLSX files. Deleting a logical template preserves revision content used by pinned workflows.\n- Fill Template (`transform.template`) now documents workspace `tmpl_...` templates separately from Git agent templates, and Studio copy covers DOCX and XLSX. XLSX files use `\\{placeholder}` and `\\{table:array.prop}` in the spreadsheet; `\\{\\{placeholder}}` in an uploaded sheet warns on upload and fails at fill instead of leaving leftover braces. `templateId` must be a workspace `tmpl_...` ID, not a file ID. Filled values that look like formulas stay text; formulas already in the template stay formulas.\n- Studio now blocks crafted HTML from retaining executable content during sanitization.\n\n### Public API\n\n- Workflow push can fully remove a template it uploaded if publishing then fails. Deleting a template that workflows already pin still keeps those revisions runnable.\n- The public API now lists the text, vision, and OCR models configured for your environment. `GET /v1/models` is a cheap catalog inventory for the current tenant: it reports whether each model is configured and which capability it is the default for, without probing live providers or exposing secrets.\n- The public API now supports the full lifecycle for tenant-scoped DOCX and XLSX templates: upload, inspect, list, download, replace, and delete, with direct-upload support for larger files. Every replacement creates a checksum-backed immutable revision; deleting the logical `tmpl_…` resource preserves revisions already pinned by workflows.\n\n### CLI\n\n- `workflow versions create --file` now resolves local `template:` paths the same way as `workflow push`, and `workflow templates smoke --data` help documents the JSON fixture file path.\n- `eigenpal workflow push` keeps local Office templates inside the workflow project, including when a path uses `../` or a symlink. Files outside that directory need `--allow-external-templates`. Push validates the workflow and version before uploading, creates new template resources instead of moving shared `tmpl_…` pointers, and fully removes those unpublished uploads if publish does not succeed.\n- When resolving a workflow by `wf_…` id, connection failures, auth errors, and server outages now surface their normal CLI messages instead of being misreported as \"workflow not found.\"\n\n[View full release notes →](/releases/0.13.1)\n\n---\n\n## 0.13.0 (2026-08-25)\n\n### Platform (Studio)\n\n- API reference for listing dataset examples now documents `include=metadata`, so you can page through example ids, names, and file refs without loading every payload.\n- Local Studio development no longer keeps a growing on-disk compiler cache that can exhaust memory during long `bun dev` sessions.\n- Studio's sidebar theme picker now supports keyboard navigation across system, light, and dark.\n- Studio dashboard sessions continue to authenticate `/api/v1` calls. Token-based `/api/v1` and `/v1` requests still work without a browser login, and the dedicated API hostname keeps its public routing and CORS behavior.\n- Studio save-as-release still publishes a tagged version as the live workflow. Publishing from an existing snapshot creates a new tagged release instead of rewriting the original tag, so earlier releases stay intact. Connect API docs version pickers follow the public version list, so after restore the current untagged version shows as latest while tagged releases stay selectable.\n\n### Public API\n\n- List dataset examples without pulling every payload. `GET /api/v1/automations/:id/examples` now accepts `include=metadata`, which returns ids, names, annotations, and expected file refs while leaving input and expected JSON unloaded. Keep the default `include=full` when you still need the complete example bodies.\n- You can now create, promote, and restore workflow versions through the public API. Create a tagged candidate with `activate: false` to test it without changing live traffic, then promote that exact version after it qualifies. You can also publish from YAML, copy an existing version into a new release without changing its original tag, or restore an earlier snapshot. Name-conflict errors include `conflictingWorkflowId` so you can see which workflow already owns the name.\n\n### CLI\n\n- `eigenpal workflow versions` can now create, promote, and restore YAML workflow versions through the public API. Tag a candidate from a YAML file or an existing snapshot with an explicit semver, keep it off live traffic with `--no-activate`, then promote that exact version when it qualifies. Restoring still rolls a workflow back by copying a snapshot into a new current version — lists now show that untagged HEAD clearly instead of hiding it. `workflow versions list --limit` and `--offset` page that full public list locally. `--json` prints the sliced `\\{ data, total, limit, offset }` envelope (`total` is the unsliced count), not the raw server payload.\n\n### SDK\n\n- TypeScript and Python SDKs can list dataset examples with `include: \"metadata\"`. That returns ids, names, annotations, and expected file refs without loading each example's input and expected JSON. The default remains a full payload, so existing list calls stay unchanged.\n\n[View full release notes →](/releases/0.13.0)\n\n---\n\n## 0.12.2 (2026-08-21)\n\n### Platform (Studio)\n\n- Document editing: the DOCX editor used for templates, run file review, and Office file previews now follows your light or dark theme, and Save (including Cmd/Ctrl+S) writes back to the document you opened instead of downloading a copy. Documents that fail to open now report the reason instead of showing an empty editor. Placeholder highlighting in DOCX templates is temporarily unavailable.\n- Connect: a workflow that wraps another workflow now documents the full response shape. Its OpenAPI spec, Swagger UI preview, and the response examples and generated types on the Connect page show the nested objects and arrays returned by the workflow it calls, instead of leaving those fields untyped.\n\n---\n\n## 0.12.1 (2026-08-19)\n\n### Platform (Studio)\n\n- Connect: download an OpenAPI spec (swagger.json) and preview it in Swagger UI directly from the Connect page. Selecting a workflow or agent produces a spec for just that automation: the five endpoints needed to integrate it (start a run, poll it, cancel it, list and download artifacts), with the request body documenting its exact input fields and file uploads and run responses typed with its actual output schema. With no selection you get the full platform API spec. Swagger UI is bundled with the product, so the preview also works in on-prem installs without internet access.\n\n---\n\n## 0.12.0 (2026-08-18)\n\n### Platform (Studio)\n\n- The workflow builder chat honors the new `disableTemperature: true` model configuration option, so models that reject a sampling temperature work from the first request.\n- Object-typed workflow inputs can now declare a nested schema. In the workflow builder, choosing the Object type (or an array of objects) opens a property editor where you define each field with its type, description, allowed enum values, and required flag, including nested objects and arrays up to five levels deep. Declared fields are enforced when a run starts: missing required fields and type mismatches are rejected with precise field paths. Downstream steps get full autocomplete and type resolution for nested references such as `\\{\\{ input.metadata.vendor.name }}`, and the declared shape appears in the scope browser and in generated API documentation. The builder flags expressions that reference undeclared nested fields, the run form and evaluation input editor pre-fill the declared required fields, and the AI expression generator sees the nested shape when suggesting expressions. The headless execution server now enforces declared inputs with the same validator, so its API documentation and runtime behavior agree.\n- Grounded OpenParser extraction results can now carry complete field lineage through the Eigenpal web runtime, preserving source evidence and confidence metadata for downstream review experiences.\n\n### Public API\n\n- Object-typed workflow inputs can now declare a nested schema. In the workflow builder, choosing the Object type (or an array of objects) opens a property editor where you define each field with its type, description, allowed enum values, and required flag, including nested objects and arrays up to five levels deep. Declared fields are enforced when a run starts: missing required fields and type mismatches are rejected with precise field paths. Downstream steps get full autocomplete and type resolution for nested references such as `\\{\\{ input.metadata.vendor.name }}`, and the declared shape appears in the scope browser and in generated API documentation. The builder flags expressions that reference undeclared nested fields, the run form and evaluation input editor pre-fill the declared required fields, and the AI expression generator sees the nested shape when suggesting expressions. The headless execution server now enforces declared inputs with the same validator, so its API documentation and runtime behavior agree.\n- Listing runs with `sinceLastClosed=true` works again. Once a review had been closed, asking for the runs recorded since then returned an error instead of the runs, so review tooling that polls for new work had no way to ask \"what has arrived since I last signed off\". The filter now returns those runs.\n\n### Infrastructure & processing\n\n- Model entries in the deployment configuration can now set `disableTemperature: true`. Workflow steps then never send a sampling temperature to that model, which lets reasoning models (and gateways in front of them) that reject the parameter run without a first-call retry.\n- Object-typed workflow inputs can now declare a nested schema. In the workflow builder, choosing the Object type (or an array of objects) opens a property editor where you define each field with its type, description, allowed enum values, and required flag, including nested objects and arrays up to five levels deep. Declared fields are enforced when a run starts: missing required fields and type mismatches are rejected with precise field paths. Downstream steps get full autocomplete and type resolution for nested references such as `\\{\\{ input.metadata.vendor.name }}`, and the declared shape appears in the scope browser and in generated API documentation. The builder flags expressions that reference undeclared nested fields, the run form and evaluation input editor pre-fill the declared required fields, and the AI expression generator sees the nested shape when suggesting expressions. The headless execution server now enforces declared inputs with the same validator, so its API documentation and runtime behavior agree.\n\n---\n\n## 0.11.3 (2026-08-13)\n\n### Platform (Studio)\n\n- API reference pages for starting and reading runs now show complete examples, including `output` and `execution.status`.\n\n### Public API\n\n- Run API: completed-run examples now include `type`, `execution.status`, `output`, `files`, and `error`, instead of a shared async/completed union that dropped those fields. Default GET and list responses populate `execution.retry.nextRun` when a retry exists, and `expand=execution` keeps `schemaValid` instead of clearing it. Child invoke-workflow runs document `parentExecutionId` and `childExecutions`.\n\n### SDK\n\n- Generated run types now distinguish a completed run from the async accepted envelope (`RunAccepted`), and include `parentExecutionId` for child invoke-workflow runs.\n\n---\n\n## 0.11.2 (2026-08-07)\n\n- Internal improvements.\n\n---\n\n## 0.11.1 (2026-08-07)\n\n### Platform (Studio)\n\n- Document and image processing now runs on updated imaging components that carry upstream security fixes.\n\n### Infrastructure & processing\n\n- Document and image processing now runs on updated imaging components that carry upstream security fixes.\n\n---\n\n## 0.11.0 (2026-08-06)\n\n### Platform (Studio)\n\n- Workflow builder chat now works with reasoning models served through a self-hosted `openai-compatible` gateway, instead of failing with a \"temperature is not supported\" error. On models that only accept their own default temperature setting, replies can vary between attempts on the same question.\n- Canonical API hostnames now consistently expose only supported API and operational routes, returning a clear 404 for unsupported discovery paths.\n- Agent Builder attachments now negotiate multipart or storage-direct transfer, so large PDFs and archives can reach the active sandbox without crossing cloud payload limits. Large downloads use the same secure dual path. Self-hosted operators can set `deployment.multipartMaxBytes` in `eigenpal.config.yaml`; the supplied on-prem deployments keep files on multipart and streamed downloads by default.\n- Canonical API hostnames now serve API routes and discovery endpoints reliably without Studio sign-in handling intercepting requests.\n\n### Public API\n\n- Upload and download reusable files up to 100 MiB through one negotiated API: files within the deployment body limit use multipart, while larger cloud transfers use verified storage-direct uploads and short-lived authenticated download links. Retry-safe temporary run and Builder files expire after 24 hours. Existing multipart routes and `studio.eigenpal.com/api/v1` remain compatible, and new integrations can use `api.eigenpal.com/v1`.\n\n### CLI\n\n- The CLI now uses `api.eigenpal.com` as the default cloud API origin and automatically pre-uploads run files that exceed the multipart request limit. Self-hosted users can keep custom API origins and set `EIGENPAL_MULTIPART_MAX_BYTES` to their proxy limit, or `none` to keep all files on multipart.\n\n### SDK\n\n- The TypeScript and Python SDKs now transparently upload large run inputs without crossing cloud request limits, follow secure storage-direct downloads, and default cloud calls to `api.eigenpal.com`. Set `multipartMaxBytes` / `multipart_max_bytes`, or `EIGENPAL_MULTIPART_MAX_BYTES`, to match a self-hosted proxy; use `null` / `None` to keep every run file on multipart. Explicit `files.upload` files remain reusable until deleted.\n- TypeScript file uploads now follow the server-negotiated multipart endpoint, improving compatibility across hosted and self-managed route layouts.\n\n[View full release notes →](/releases/0.11.0)\n\n---\n\n## 0.10.56 (2026-08-05)\n\n### Platform (Studio)\n\n- Agent Builder training chat now shows Pierre file diffs for edit/write, a Pierre syntax-highlighted file view for Read file, secure request-secret password cards (encrypted into the draft; the agent only sees configured/skipped), and a quiet timeline note when you release an agent version from the dashboard.\n\n### Infrastructure & processing\n\n- Production releases that do not change document processing finish faster by reusing verified OCR provider checks from the last successful release, while still re-checking providers when processing code or infrastructure changes.\n\n---\n\n## 0.10.55 (2026-08-05)\n\n### Platform (Studio)\n\n- Agent Builder now resumes your latest draft, clearly distinguishes unsaved edits from saved changes that are not live, and provides direct Save and Release actions. Releases show the current and next version and let you choose a patch, minor, or major update. Dashboard save and release actions remain available to the builder as private context, so it can accurately answer what is live without guessing. Starting a separate draft is explicit, attachments remain available when beginning a conversation, stopped sandboxes can be restarted without losing the draft, and test runs reliably receive JSON-only inputs.\n\n### Public API\n\n- Agent Builder releases now complete live automation synchronization reliably, so a successful release is immediately available without a separate recovery step.\n\n### Infrastructure & processing\n\n- OCR and LLM model catalogs keep loading when the service adds new optional fields, so Studio and Eigenpal no longer fall back to stale model lists during catalog updates.\n- Cloud document processing providers that are already available stay online during routine production updates when their identity is unchanged. New or changed providers stay unavailable until they pass live verification, so customers keep working providers instead of a full outage window.\n\n---\n\n## 0.10.54 (2026-08-04)\n\n### Platform (Studio)\n\n- Workflow Studio now shows each OpenParser OCR model with its actual provider logo, keeps narrow step configuration panels contained, and places settings, theme, and sidebar controls together in a cleaner navigation footer.\n\n---\n\n## 0.10.53 (2026-08-04)\n\n### Platform (Studio)\n\n- OpenParser Studio now visualizes the `openparser@1` document graph directly, including typed elements, figures, tables, relationships, and element-level extraction citations.\n\n### Public API\n\n- OpenParser parse responses now return the unified `openparser@1` document graph, with plain text, canonical Markdown, pages, typed elements, relations, annotations, assets, geometry, confidence, and provider provenance in one predictable contract.\n\n---\n\n## 0.10.52 (2026-08-04)\n\n### Platform (Studio)\n\n- Agent Builder: improve connection recovery so interrupted sessions resume reliably, stale environments are replaced safely, and approval prompts remain retryable when delivery fails.\n\n---\n\n## 0.10.51 (2026-08-03)\n\n- Internal improvements.\n\n---\n\n## 0.10.50 (2026-08-03)\n\n### Platform (Studio)\n\n- OpenParser Studio: pipeline creation no longer reports a duplicate-name error after a successful save, and edits now save reliably from the browser.\n\n---\n\n## 0.10.49 (2026-08-03)\n\n- Internal improvements.\n\n---\n\n## 0.10.48 (2026-07-30)\n\n### Platform (Studio)\n\n- OpenParser Studio now displays canonical OpenParser JSON with readable indentation, including large document results.\n\n---\n\n## 0.10.47 (2026-07-30)\n\n### Platform (Studio)\n\n- OpenParser Studio now keeps large document results responsive, renders OCR markdown with clearer structure, and provides consistent copy and download actions for Markdown and JSON output. Documentation links now reliably open the generated API reference.\n\n### Infrastructure & processing\n\n- OpenParser jobs now recover more safely when document processing capacity becomes unavailable. Retryable failures pause new dispatches, retry without duplicate charges, and bound large-document processing so one document cannot overwhelm the service.\n\n---\n\n## 0.10.46 (2026-07-30)\n\n### Platform (Studio)\n\n- Team settings: bring back the invitation link. Creating an invitation now shows its link straight away whenever no invitation email was delivered, and administrators can pull up the link again at any time from the invitations table. This unblocks onboarding on deployments without email delivery, where handing over the link is the only way to get someone into the workspace.\n- Run details: field grounding now labels flagged fields by what the extraction actually reports, showing \"3 with low confidence\" instead of \"3 to review\". The count is a confidence signal, not an assigned task.\n\n---\n\n## 0.10.45 (2026-07-29)\n\n### Platform (Studio)\n\n- Parse Document setup now clearly separates OCR from Vision AI, automatically offers available OpenParser OCR models, shows each model's per-page price, displays only the controls that affect the selected method, and surfaces structured layout data with tables, figures, polygons, and bounding boxes for downstream workflow steps.\n\n### CLI\n\n- The workflow authoring reference now covers explicit OCR and Vision AI parse modes, optional figure-caption models, and structured layout output.\n\n### Infrastructure & processing\n\n- Document parsing now defaults to higher-fidelity OCR, preserves canonical structured layout alongside Markdown, and automatically supports available OCR models with provider-specific per-page pricing. Other OCR providers retain their existing rates.\n\n---\n\n## 0.10.44 (2026-07-28)\n\n- Internal improvements.\n\n---\n\n## 0.10.43 (2026-07-27)\n\n- Internal improvements.\n\n---\n\n## 0.10.42 (2026-07-27)\n\n- Internal improvements.\n\n---\n\n## 0.10.41 (2026-07-27)\n\n### Platform (Studio)\n\n- Run traces now show each attempt of an AI request. A request that timed out and was retried used to appear as a single long bar, so a step that spent three timeouts on one page looked identical to one slow call. The raw trace now has one bar per try, labelled with the try number, and the run timeline marks a retried call with how many times it was sent. Retried requests also record how long they waited for a free slot, which distinguishes a slow model from a queue backed up behind its own in-flight requests. For documents parsed page by page, each split retry records the pages it covered and how deep the split went.\n- Runs and Experiments improvements: - An experiment run now shows the same input and output panels as the main run view, including input file downloads, per-step output files, and inline field-level output review. - Scored runs show their eval score in the runs list and in the run header, so an experiment's results can be compared without opening each run. - A run that came from an experiment or a dataset example now links straight to that run in the Evals view. - The Live and Experiments toggles on Runs are remembered between visits. - Field grounding: a wide document no longer overflows the panel. Wide tables and long unbroken text scroll inside the document card.\n\n---\n\n## 0.10.40 (2026-07-25)\n\n### Infrastructure & processing\n\n- Processing reliability on busy deployments: health checks are now served independently of document processing, so the service stays responsive to them even while working through a heavy document. It is no longer restarted mid-run just because it is under load, so long-running document runs complete more reliably.\n- Document processing is more resilient on CPU- and memory-constrained deployments. Page rasterization for vision and OCR now runs in isolation, so a single large or malformed document can no longer stall the processing service or cause it to restart mid-run. Runs on big scanned documents that previously failed partway through with \"the worker stopped before this attempt recorded a terminal result\" now complete reliably.\n\n---\n\n## 0.10.39 (2026-07-25)\n\n### Platform (Studio)\n\n- Label Pages runs: the page preview now shows the classified document in the full viewer instead of small thumbnails. PDFs render page-by-page with zoom and navigation and each page's labels shown beside it; Word and other Office documents open in their own preview next to a per-page label list. Filter by a label to focus on just the pages that carry it.\n\n---\n\n## 0.10.38 (2026-07-24)\n\n### Platform (Studio)\n\n- OpenParser Studio: manage extraction pipelines from a dedicated workspace — create, edit, run, duplicate, and delete saved configurations. Jobs show the pipeline and version that produced each result, and you can save a new pipeline from job settings.\n- OpenParser Studio: clearer progress while documents upload, parse, and extract, with live elapsed timing at each stage. Job history and the playground share a unified header with breadcrumbs, improved document and Markdown output viewers, and a cleaner parse sidebar. Choose light or dark theme and manage your account from the sidebar; model selectors and in-product copy are simpler throughout the workspace.\n- Members provisioned through SSO are now read-only in workspace member settings. Their role and access come from your identity provider's groups, so admins can no longer change or remove them by hand, and each SSO member is clearly labeled. Accounts created with a username and password stay fully manageable by admins.\n\n### Public API\n\n- **Breaking:** OpenParser API resource identifiers now use consistent prefixed ids. Parse, extract, and batch jobs return `opj_…` ids instead of UUIDs. Saved extraction pipelines use `oppl_…` instead of `oep_…`. New parse output writes figure image ids as `opfig_…` instead of `ocrfig_…`. Existing jobs and pipelines are remapped automatically on upgrade when the OCR queue is idle enough for migration preflight. Prefer the new formats in job URLs, `parse_job_id`, `pipeline_id`, and batch child `job_id` fields. During the transition, previously issued UUID job ids, `oep_…` pipeline ids, and UUID list cursors remain readable; responses continue to return the preferred `opj_…` / `oppl_…` forms. Historical parse artifacts and `result_json` may still embed legacy `ocrfig_…` figure paths; `GET /files/\\{id}` accepts both `opfig_…` and `ocrfig_…`.\n\n### Infrastructure & processing\n\n- Hardened AI-powered document processing against prompt-injection attempts hidden inside uploaded documents. Instructions embedded in a document can no longer steer extraction, classification, or vision results away from the requested schema, or coax the model into disclosing its own configuration.\n- AI vision step results no longer include internal document storage references in their metadata. The step's `_vision` provenance now records only which pages were inspected and how many were merged, keeping internal storage paths out of workflow output.\n\n---\n\n## 0.10.37 (2026-07-24)\n\n### Platform (Studio)\n\n- New **Label Pages** step tags each page of a document with zero or more labels (multi-label) using AI, and groups the results into a label-to-pages map. Unlike section splitting — which produces one contiguous range per section — this collects pages of the same kind wherever they appear, so scattered pages (for example every signature or photo page throughout a report) can be gathered in one place. The page-inspection step can now take an explicit list of page indices, so you can route the pages for a given label straight into a visual inspection without hand-listing them.\n\n---\n\n## 0.10.36 (2026-07-23)\n\n### Platform (Studio)\n\n- OpenParser Job History now reports the real end-to-end duration for completed parse and extraction jobs instead of showing a zero or unavailable measurement.\n- Running OpenParser jobs now show the document scanning animation from the playground while results are being prepared.\n- Parse and Extract now use consistent operation icons across OpenParser Studio and documentation.\n\n---\n\n## 0.10.35 (2026-07-23)\n\n### Platform (Studio)\n\n- OpenParser sign-in and account creation now redirect directly to the branded authentication flow without an intermediate confirmation page.\n- OpenParser parse jobs now retain both `raw` and `openparser@1` results. Retrieve either representation with `GET /jobs/\\{id}/result?format=...`, switch formats in the Studio Output tab, and start extraction from a raw-format parse job without running OCR again.\n\n### Public API\n\n- OpenParser parse jobs now retain both `raw` and `openparser@1` results. Retrieve either representation with `GET /jobs/\\{id}/result?format=...`, switch formats in the Studio Output tab, and start extraction from a raw-format parse job without running OCR again.\n- OpenParser now keeps recognized text aligned with its original bounding box by default. Set `ocr_options.merge_layout_blocks` to `true` per parse, extraction, batch item, or saved pipeline when merged recognition is preferred over one-to-one text geometry.\n\n---\n\n## 0.10.34 (2026-07-23)\n\n### Platform (Studio)\n\n- OpenParser sign-in and account creation now keep OpenParser branding throughout the authentication experience.\n- OpenParser Studio: uploads and sample documents now open their Job History detail immediately, so browser back and forward navigation follows each run naturally while extraction and result review stay in one place.\n- Run detail now shows clean, readable file names for inputs and outputs instead of internal storage identifiers, and long file names no longer overlap the preview and download buttons.\n\n### Public API\n\n- OpenParser parsing now preserves every detected layout region—including empty title, header, and figure boxes—so document overlays remain complete. The obsolete `figure_assets` option is removed because figure regions are now always retained.\n- OpenParser can now process documents beyond 25 pages and admit batches of up to 100 documents, while retaining per-page safety limits.\n- OpenParser jobs can now stream their retained source documents with `GET /jobs/\\{id}/source`, making it easier to build durable review experiences around past runs.\n- `POST /suggest-schema` now returns the suggested schema inline as a convenience response instead of creating a job that clients must poll.\n\n### Infrastructure & processing\n\n- Documents uploaded without a declared file type are now recognized from their contents, so PDFs, RTF, and Office files parse reliably instead of failing with an \"unsupported file type\" error. This most often helped uploads coming from automated integrations that omit the file type.\n\n---\n\n## 0.10.33 (2026-07-22)\n\n### Platform (Studio)\n\n- OpenParser Studio: make Playground the home page, add shareable social previews, clarify job status and pipeline empty states, and tidy the OCR model selector copy.\n\n### Public API\n\n- OpenParser suggested extraction model catalog (`GET /models/llm` in suggested mode) now surfaces up to 20 recommended models instead of 12, so more current options appear before you need to search.\n\n---\n\n## 0.10.32 (2026-07-22)\n\n- Internal improvements.\n\n---\n\n## 0.10.31 (2026-07-22)\n\n### Platform (Studio)\n\n- OpenParser Studio production sign-in no longer auto-redirects to Eigenpal when you are signed out. Choose **Continue to sign in** on the local OpenParser page to authenticate with your Eigenpal account; sign-out stays on OpenParser.\n\n---\n\n## 0.10.30 (2026-07-22)\n\n### Platform (Studio)\n\n- OpenParser production sign-in now shares Eigenpal sessions across its dedicated domain and returns users to their original OpenParser destination after authentication.\n- OpenParser Playground: remove the doubled border and rounded corners around the document workspace.\n\n### Infrastructure & processing\n\n- OpenParser: restore schema suggestions, use GPT-5.6 Terra as the default extraction model with GPT-4.1 Mini as a certified fallback, tighten compatibility checks, and provide clearer failure guidance.\n\n---\n\n## 0.10.29 (2026-07-22)\n\n### Platform (Studio)\n\n- OpenParser Studio sign-in and sign-up now load the shared identity UI correctly for signed-out visitors.\n\n---\n\n## 0.10.28 (2026-07-22)\n\n### Platform (Studio)\n\n- API keys: keep usable credentials in the primary list and move revoked or expired credentials into a collapsed history section for faster scanning.\n- OpenParser Studio sign-in and sign-up now show OpenParser product copy and logo while retaining the shared Eigenpal identity.\n\n### Public API\n\n- OpenParser model discovery (`GET /models/llm`) now refreshes the live compatible catalog on the API service instead of falling back to a short emergency list when the catalog credential is missing from that process.\n\n### Infrastructure & processing\n\n- OpenParser document processing now bounds source downloads and retries transient storage failures, preventing stalled jobs from running indefinitely.\n\n---\n\n## 0.10.27 (2026-07-21)\n\n### Platform (Studio)\n\n- New Inspect Pages (Vision) step lets a workflow look at the actual page images of a document and return structured results, for details that only exist in the pixels rather than the text. Use it to check whether a document is signed, rate embedded photos, or spot stamps and logos. It works on PDFs, images, and Office documents, and you can point it at a specific page range (for example the section found by a Split step) so it only reviews the pages that matter. The run trace shows the pages it inspected next to the results.\n- Parsing can now describe the figures on a page as text. Enable \"describe figures\" on a Parse step and the images on each page (property photos, charts, stamps) are detected and captioned inline, so later steps that work on text, like Split, can find image-only pages. This is especially useful for scanned documents, where the photo pages carry almost no text on their own. You can provide custom instructions for how figures should be described.\n- Split step results are now also available keyed by section name. A later step can point at one section directly, for example `\\{\\{ steps.split.output.sections.photos.page_range }}`, instead of filtering the full list. This makes wiring a Split step into a downstream step much simpler.\n- The Inspect Pages (Vision) step now takes a Page From / Page To range instead of a single page-range expression, and both are optional. Leave them blank to inspect the whole document, which is processed in chunks and the results merged automatically. This makes it much easier to point the step at a range (for example the start and end of a Split section) or to scan an entire document without writing a range expression.\n\n---\n\n## 0.10.26 (2026-07-21)\n\n### Platform (Studio)\n\n- Wildcard API keys can use the OpenParser OCR API consistently with every other platform capability. Keys can also be restricted to the dedicated `ocr:full` scope when OCR-only access is preferred.\n- Run traces now include a Grounding panel for extract steps: every extracted value is highlighted in the input text, tinted by confidence, and clicking a field or a highlight jumps between them. Grounded fields also show inline context previews of the exact source passage, both in the panel and in the expanded step row. Split steps gain the same visual page-range panel the segmenter uses, with page thumbnails and per-section preview. The workflow builder reflects that grounding is on by default and lets you pick any configured provider as the grounding model, and capturing expected output from a run no longer snapshots volatile grounding metadata into evals.\n\n### Public API\n\n- Wildcard API keys can use the OpenParser OCR API consistently with every other platform capability. Keys can also be restricted to the dedicated `ocr:full` scope when OCR-only access is preferred.\n- OpenParser: completed extraction jobs can now be retrieved reliably with their attempt and usage metadata.\n\n### CLI\n\n- The step catalog now documents grounded extraction as the default: extract steps ship per-field confidence and source spans under the `_grounding` output key unless `grounded: false` is set.\n\n### Infrastructure & processing\n\n- Data extraction now verifies itself by default. Every extract step traces each extracted field back to its exact location in the source text and attaches a confidence level (high, medium, or low) plus a needs-review flag under a reserved `_grounding` output key, so downstream steps and evaluators can route uncertain values to a human. The verification pass runs on your workspace model (any configured provider), chunks long documents automatically, and falls back to deterministic text matching instead of failing the run when no model is available. Set `grounded: false` on a step to opt out.\n\n---\n\n## 0.10.25 (2026-07-20)\n\n### Platform (Studio)\n\n- Failed single sign-on attempts now return to the sign-in page with a clear, actionable message (for example, when an account's email domain isn't authorized or the account hasn't been granted access) instead of a blank error page.\n\n---\n\n## 0.10.24 (2026-07-15)\n\n### Platform (Studio)\n\n- Agent runs graded by configured evaluators now record a weighted score and pass/fail result, visible in the runs feed and run detail responses. Previously only workflow runs carried an evaluator verdict.\n- Email addresses for a workflow are unique across your whole organization, not just the workflow you are editing. Picking one that is already taken used to fail with a server error. It now tells you which workflow already receives email at that address, or that the workflow you are editing already has it, so you know what to do next. Duplicate folder names and duplicate workspace invites also report clearly instead of failing.\n- `ai.extract` with `grounded: true` no longer succeeds silently without producing grounding. When the grounding pass cannot run (missing OpenAI credentials on the worker, or a grounding model that is not an OpenAI model) the step now fails with an error that names the exact misconfiguration. When the pass runs but produces no field grounding, the output carries an explicit degraded marker instead of nothing. The grounding model picker in the workflow builder now only offers OpenAI models, matching what the grounding pass supports.\n- Agent training: when a training session fails to open, the dashboard now shows what went wrong instead of a generic error. The message names the setup step that failed, and a session blocked by secrets that cannot be decrypted says so and points at the agent settings. A session whose setup fails partway through no longer opens on an incomplete workspace.\n- Self-hosted deployments can now sign users in through corporate single sign-on services that use a redirect-and-token flow instead of OIDC. The new protocol supports mutual TLS for the server-to-server exchange, maps directory groups to EigenPal roles (admin, member, viewer) on every SSO sign-in so the directory stays the source of truth, and links existing password accounts by email so nobody loses access when SSO is turned on. Startup validation rejects unsafe callback origins and provider identifiers, while malformed or oversized identity responses fail closed.\n\n### Public API\n\n- Syncing an automation immediately after a release no longer fails with HTTP 500 while the new release tag propagates. The sync endpoint now reports a retryable status with a clear message when the Git source is momentarily unavailable.\n- Fixed single-experiment results export returning HTTP 400 whenever the `includeTrace` query flag was omitted. `workflow experiment results` and the auto-pull at the end of `workflow experiment watch` now download per-evaluator results in JSON and CSV again.\n- Creating an email trigger address that is already in use now returns 409 with a message naming the workflow in your organization that already uses it, instead of 500.\n\n### CLI\n\n- Agent example runs now report a real evaluator verdict in the CLI: `eigenpal run agents.<name> --example <name> --wait` waits for the verdict, prints the weighted score and pass/fail result, and `--fail-on-mismatch` exits non-zero when the run fails its evaluators, matching the existing workflow behavior. When no evaluators are configured, the CLI says so instead of silently reporting nothing.\n- `agents secrets` is now one command group with `list`, `set`, `unset`, `import`, and `export` subcommands (`agents secret` remains as an alias). The new `agents secrets list` shows the secret names and descriptions declared in the package without ever printing values. Previously `set` and `unset` lived under a separate singular command and `secrets list` failed with an argument error.\n- `agents sync` retries automatically with a short backoff when the server reports the Git source as temporarily unavailable, so the sync right after `agents release` succeeds without manual retries.\n- `agents dataset validate` now checks the same layout the server accepts on `agents dataset push`: example folders under `examples/`, file inputs referenced from `input.json` with `\\{ \"$file\": \"input/...\" }`, and `expected.json` optional. Previously the local validator demanded a different layout that push would then reject, so no dataset could satisfy both. Validation errors now point at the exact rule that failed, including a hint when example folders sit at the dataset root instead of under `examples/`. When the agent package carries an input schema, each example's full input object is validated against it (required fields, unknown keys, and value types, with `\\{ \"$file\": ... }` references accepted for file fields), so inputs that would fail at run start are caught locally. Failure-expected examples (`expected.json` with `$error`) are rejected for agent datasets, since agent runs are evaluated only when they complete.\n\n[View full release notes →](/releases/0.10.24)\n\n---\n\n## 0.10.23 (2026-07-15)\n\n- Internal improvements.\n\n---\n\n## 0.10.22 (2026-07-14)\n\n### Platform (Studio)\n\n- Organization members can now configure, test, and manage outbound webhooks from Studio.\n\n---\n\n## 0.10.21 (2026-07-14)\n\n### Platform (Studio)\n\n- Webhooks: notify external systems when workflow or agent runs are created or change status, with signed delivery, custom headers, retry history, testing, and manual redelivery from Studio.\n- Webhook signing secrets are now easier to copy securely from endpoint setup and details, with clearer event selection defaults.\n- Webhook setup now keeps failed submissions actionable with clear inline error feedback.\n\n### Public API\n\n- Run creation and rerun requests now publish signed lifecycle webhooks only after inputs are ready, so API-triggered automations never emit events for runs that fail during setup.\n\n### Infrastructure & processing\n\n- Improved staging worker deployment reliability when compute capacity is fully allocated.\n\n---\n\n## 0.10.20 (2026-07-12)\n\n### Platform (Studio)\n\n- Workflows: configure automatic retries from Studio at the workflow level or override them for individual HTTP GET/HEAD and Website Reader steps.\n\n### CLI\n\n- The bundled workflow reference now documents durable retry policies, inheritance, supported step types, and retry safety limits.\n\n### Infrastructure & processing\n\n- Workflow runs can recover replay-safe network steps from transient failures without restarting completed work, using bounded backoff and durable retry state. Retry behavior is now step-scoped. Legacy whole-run retry settings no longer restart a failed workflow; configure durable retries on eligible steps or through the workflow retry default instead.\n\n---\n\n## 0.10.19 (2026-07-09)\n\n### Platform (Studio)\n\n- Workflow composition is unified on `action.invoke-workflow`: use `execution: inline` (default) to run a target workflow's steps inside the parent run, or `execution: child` for a separate child run. Reusable blocks (`control.block`, `kind: block`) are removed — migrate to inline invoke with `workflow: <name-or-id>`.\n\n### Public API\n\n- Workflow run endpoints now preserve inline invoke snapshots across initial runs, reruns, and dataset executions so composed workflows remain reproducible after target workflows change.\n\n### CLI\n\n- Workflow YAML reference docs now describe `action.invoke-workflow` as the single composition primitive, including inline and child execution modes.\n\n---\n\n## 0.10.18 (2026-07-08)\n\n### Infrastructure & processing\n\n- On-prem deployments: improve OpenShift compatibility so migration and processing jobs can start reliably under random-user security policies.\n\n---\n\n## 0.10.17 (2026-07-08)\n\n### Platform (Studio)\n\n- Document parser: vision parsing can now render PDF pages at higher resolution and image quality for documents where small text or compression artifacts hurt OCR accuracy.\n\n### Infrastructure & processing\n\n- Document parser: vision parsing can now render PDF pages at higher resolution and image quality for documents where small text or compression artifacts hurt OCR accuracy.\n\n---\n\n## 0.10.16 (2026-07-07)\n\n### Platform (Studio)\n\n- Workflow experiment results now preserve evaluator error details alongside each per-evaluator score, so example grading views and tools can distinguish failed judges from unknown results instead of treating them as passing.\n\n### CLI\n\n- `eigenpal run <workflow> --example <name>` now actually grades the example instead of printing `PASS` whenever the run merely finished. It runs the workflow's current published version on the server's stored dataset example, so configured evaluators run automatically and the CLI surfaces the real weighted score and per-evaluator pass/fail. Workflows with no evaluators fall back to a structural diff of the output against the example's stored expected output. The summary reports two separate signals: execution health (`ok`/`errored`) and accuracy. Add `--fail-on-mismatch` to exit non-zero when a graded example fails. Because the run uses the server-side example, push your latest dataset and evaluators (`eigenpal workflow dataset push`, `eigenpal workflow evaluators push`) before running `--example`.\n\n---\n\n## 0.10.15 (2026-07-06)\n\n### Platform (Studio)\n\n- Experiments: make result review easier in Studio with trace exports, clickable score bars, calmer live refreshes, developer-view defaults, and clearer separation between below-threshold results and run errors.\n\n### Public API\n\n- Experiment export endpoints now support JSON exports with full run trace details for deeper debugging and audit review.\n\n### SDK\n\n- SDK clients now expose the trace-inclusive experiment export option for deeper debugging and audit review.\n\n---\n\n## 0.10.14 (2026-07-06)\n\n### Platform (Studio)\n\n- Evaluations: expected workflow failures now report cleaner scores when a run is supposed to stop early. Studio marks non-applicable quality judges as skipped, so successful rejection examples can receive a full score from the structured failure checks that actually apply.\n\n---\n\n## 0.10.13 (2026-07-06)\n\n- Internal improvements.\n\n---\n\n## 0.10.12 (2026-07-06)\n\n- Internal improvements.\n\n---\n\n## 0.10.11 (2026-07-03)\n\n- Internal improvements.\n\n---\n\n## 0.10.10 (2026-07-03)\n\n- Internal improvements.\n\n---\n\n## 0.10.9 (2026-07-02)\n\n### Platform (Studio)\n\n- Build document-processing workflows that split, route, and verify a mixed batch: - **Document separation** detects the boundaries and types of the documents inside one large scan, so a single upload can be broken into its individual documents and each sent to its own extraction pipeline — even for batches hundreds of pages long. - **Multi-way routing** sends each detected document to the right branch by its type, and stays readable on the canvas even with many branches. - **Grounded extraction** attaches a confidence level and source location to each extracted field, flagging values that aren't found verbatim in the document so reviewers know where to look. - The run view now lets you open the detected documents and preview their pages, and inspect the OCR layout with bounding boxes drawn over the page (with a toggle to the extracted text) — right from the step timeline.\n\n### CLI\n\n- The workflow step catalog now lists the new document-separation and multi-way routing steps, plus the grounded-extraction options, so authoring and validating workflows from the CLI stays in step with what the platform supports.\n\n### Infrastructure & processing\n\n- Self-hosted (on-prem) deployments can now run official EigenPal release images, with access provisioned per customer. Images are published only after a release ships and are signed so you can verify their authenticity before deploying.\n\n---\n\n## 0.10.8 (2026-07-01)\n\n### Platform (Studio)\n\n- Single-file workflow inputs now display correctly after a dataset import. Previously an input that takes one file could show an empty file slot; imported examples now match each file to the workflow's declared input shape.\n- Evaluator scoring now uses a single pass threshold for the whole workflow. The score-by-example chart's cutoff line and every evaluator's pass/fail are measured against that one threshold, so the chart, the per-evaluator results, and the run gate always agree. Experiment scores are shown in two states — passing (green) or below threshold (amber).\n- The LLM judge evaluator now requires evaluation criteria. Without them the model invents its own scoring rubric, so the editor marks the field required, renames it to \"Evaluation criteria\" with a worked example, and blocks saving until it is filled in.\n- Workflow folders can now be reorganized. A new \"Move to folder\" action in each folder's menu lets you move a folder (and everything inside it) into another folder or back to the top level, so you can restructure your workspace without recreating folders. Destinations that would nest a folder inside itself are blocked, with a tooltip explaining why.\n- Nested sub-workflows now display and resolve correctly across runs, the workflow builder, and the CLI. In the Runs list, a run that invokes a sub-workflow which itself invokes another sub-workflow now nests every level under its parent, instead of stopping at the first level. In the workflow builder, an \"Invoke Workflow\" step that targets a workflow built from other invoked workflows now shows the real output field types instead of \"unknown\", so you can reference those fields with autocomplete; referencing one of those fields no longer triggers a false \"field not found\" warning. The same resolution now applies when validating and publishing workflows (including via the CLI), so deeply nested invoke chains validate against their real output fields. All of this resolves through arbitrarily deep chains with a safety limit that prevents looping on workflows that invoke each other.\n- Runs: add a simplified review mode with developer-view toggle, review status badges, and inline output review for JSON fields and generated files.\n- New debugging and control primitives for runs. You can now cancel an in-progress run through the API, experiment results report when a batch has fully finished, steps skipped by a condition or an empty loop are reported as skipped rather than succeeded, and each step records the exact configuration it ran with so failures are easier to diagnose.\n- Run detail responses are leaner and more explicit: you choose exactly which sections to expand, and the public run schema now exposes the workflow version, cancellation-request time, and trace, retry, and email-trigger details.\n\n### CLI\n\n- `eigenpal workflow validate` now tells you when a workflow contains Invoke Workflow steps that local validation cannot fully check. Because those steps reference other workflows that live on the server, the command prints a short note pointing you to `validate --online` (or push) to verify the invoke targets, input types, and cycles. The skill guidance now shows the `--online` step in the validate-then-push flow as well.\n- The evaluator configuration reference now reflects the single workflow-level pass threshold. A per-evaluator `passThreshold` is documented as legacy — pass/fail is decided by the one workflow-level threshold — and that workflow-level threshold no longer shows a fixed default, since it is derived when omitted.\n\n### SDK\n\n- The Python SDK now requires Python 3.10 or newer. Python 3.9 has reached the end of its support window, and dropping it keeps the SDK on current, actively maintained dependencies. If you are still on Python 3.9, upgrade to 3.10+ to continue receiving SDK updates.\n\n[View full release notes →](/releases/0.10.8)\n\n---\n\n## 0.10.7 (2026-06-30)\n\n### Platform (Studio)\n\n- Faster dashboard navigation. Lists keep their contents on screen while filters and folders refresh instead of flashing a loading state, document and image previews are cached so they no longer re-download on every navigation, and heavy viewers (PDF, charts, rich text) load on demand for a quicker first paint.\n- Workflows that invoke another workflow now pass file inputs through to the sub-workflow, so file-backed sub-workflow runs no longer fail before they start.\n\n### CLI\n\n- `eigenpal --help` now groups `run`, `rerun`, and `runs` under a dedicated \"Run\" section instead of the catch-all \"Other\" bucket, so starting a run and reading its output is easy to find.\n\n---\n\n## 0.10.6 (2026-06-30)\n\nThis release contains maintenance and reliability improvements with no customer-facing changes.\n\n---\n\n## 0.10.5 (2026-06-29)\n\nThis release makes EigenPal's public changelog a reliable product record. Each release now has a dedicated docs page that explains what changed for Studio, the public API, the CLI, SDKs, and document processing in one place.\n\nThat means teams can follow platform improvements without piecing together GitHub activity or package-specific notes. The changelog is organized around customer-facing product areas, so it is easier to see which changes affect app users, API integrations, developer tools, and processing behavior.\n\n### Platform (Studio)\n\n- Invoke Workflow steps are now typed end to end. Pick a target workflow and map each input it declares to a value, then reference the workflow's output fields and any files it generates from downstream steps with autocomplete. Inputs and outputs are checked when you save and when the step runs, so mismatches surface early instead of failing mid-run.\n- Runs that invoke another workflow now appear nested under their parent run in both the runs feed and the run timeline, and link straight to the sub-workflow's own run and trace.\n- You can view a workflow's inferred output schema (the fields and files it returns, typed from its own steps) without running it.\n- File inputs are preserved consistently across runs, reruns, reviewed examples, and dataset experiments, so reused runs and examples no longer lose or mispoint their files.\n- Creating new organizations and other Git-backed source operations stay reliable even during Git provider outages.\n\n### Public API\n\n- Run file inputs now use a consistent artifact model. Callers provide reusable files with `$fileId` or inline files with `$inline`, and EigenPal materializes them into run-owned artifacts before execution, reruns, promotion, and dataset workflows.\n- A new endpoint returns a workflow's inferred output schema without running it, as JSON Schema or as a TypeScript or Python type.\n\n### CLI\n\n- `eigenpal workflow schema <workflow>` prints a workflow's inferred output schema as JSON Schema, or as a TypeScript or Python type with `--format`.\n\n[View full release notes →](/releases/0.10.5)\n\n---\n\n## 0.10.4 (2026-06-25)\n\n### Platform (Studio)\n\n- Unify file list review surfaces\n\n---\n\n## 0.10.3 (2026-06-24)\n\n### SDK\n\n#### Patch Changes\n\n- e48cb81: Remove `fileVerdict` from run review correction types; file correction intent is encoded via `correctedArtifactPath`.\n\n---\n\n## 0.10.2 (2026-06-24)\n\n### CLI\n\n#### Patch Changes\n\n- ca9ae4f: Workflow inputs can declare an external file `source` (single-tenant on-prem). A `type: file` input with `source: <name>` (e.g. `gpfs`) is provided as a plain string id at run time; the worker resolves it to a file artifact via the configured source before the workflow executes.\n\n---\n\n## 0.10.1 (2026-06-23)\n\n### Public API\n\n- Polish reviews pages and group API reference nav\n\n### Infrastructure & processing\n\n- Client-shareable deployment architecture PDFs\n\n---\n\n## 0.10.0 (2026-06-23)\n\n### Platform (Studio)\n\n- Add simple runs review mode\n\n### Infrastructure & processing\n\n- Autogenerate chart architecture diagram from helm template\n- AWS/GCP/Azure Terraform examples with architecture diagrams\n- Helm chart + local kind for single-tenant on-prem\n\n---\n\n## 0.9.0 (2026-06-22)\n\n### CLI\n\n#### Minor Changes\n\n- c35d5d4: Clean up the public runs and evaluation API surface: move workflow eval operations onto automations, expose run scores/artifacts through the unified runs API, and update CLI/SDK helpers to use the canonical routes.\n\n Breaking: `runs.evalResults` and `GET /api/v1/runs/\\{id}/eval-results` are replaced by `runs.scores` and `GET /api/v1/runs/\\{id}/scores`.\n\n#### Patch Changes\n\n- c35d5d4: Clarify `--max-wait` help text so timeout exit behavior reads naturally.\n\n### SDK\n\n#### Minor Changes\n\n- c35d5d4: Clean up the public runs and evaluation API surface: move workflow eval operations onto automations, expose run scores/artifacts through the unified runs API, and update CLI/SDK helpers to use the canonical routes.\n\n Breaking: `runs.evalResults` and `GET /api/v1/runs/\\{id}/eval-results` are replaced by `runs.scores` and `GET /api/v1/runs/\\{id}/scores`.\n\n[View full release notes →](/releases/0.9.0)\n\n---\n\n## 0.8.0 (2026-06-18)\n\n### CLI\n\n#### Minor Changes\n\n- d620a00: Expose the clean public automation API around automations, runs, files/artifacts, datasets, evaluators, experiments, evaluation results, and run promotion. This intentionally breaks the pre-v1 SDK/CLI surface that exposed workflow- and agent-specific top-level resources outside the explicit legacy compatibility routes.\n\n > [!WARNING]\n > **Breaking change (pre-v1).** The workflow- and agent-specific top-level\n > resources have been removed in favor of a single automation-centric surface.\n > These packages are still 0.x, so this breaking redesign ships as a `minor`\n > bump. Update your integration before upgrading.\n\n #### Removed\n - Top-level workflow resources, e.g. `client.workflows.*`, including\n `client.workflows.executions.runAndWait(...)` and the rest of the\n `client.workflows.executions.*` tree.\n - Top-level agent resources, e.g. `client.agents.*` (runs, reviews, traces,\n files, expected artifacts).\n - Top-level source/git resources, e.g. `client.sources.*`.\n\n[View full release notes →](/releases/0.8.0)\n\n---\n\n## 0.7.2 (2026-06-13)\n\n### SDK\n\n#### Minor Changes\n\n- c5a709c: Public workflow list/detail responses include `apiEnabled` and `triggers`; run definition docs note workflow-only scope.\n\n---\n\n## 0.7.1 (2026-06-13)\n\n### SDK\n\n#### Patch Changes\n\n- 9db3f01: Expose `apiEnabled` and `triggers` on `AgentSummary` for runtime trigger projection.\n\n---\n\n## 0.7.0 (2026-06-12)\n\n### CLI\n\n#### Minor Changes\n\n- 963fd6c: Unify run detail on `GET /api/v1/runs/\\{id}`: return the canonical Run object directly (no `\\{ run: ... }` envelope) and merge expanded fields in-place via documented `expand` tokens. Remove the session-only `expand=internal` dashboard escape hatch; SDKs and CLI now use explicit expand lists.\n\n#### Patch Changes\n\n- 963fd6c: Update runs commands for the grouped run API shape and four expand tokens.\n\n### SDK\n\n#### Minor Changes\n\n- 963fd6c: Unify run detail on `GET /api/v1/runs/\\{id}`: return the canonical Run object directly (no `\\{ run: ... }` envelope) and merge expanded fields in-place via documented `expand` tokens. Remove the session-only `expand=internal` dashboard escape hatch; SDKs and CLI now use explicit expand lists.\n\n#### Patch Changes\n\n- 12c00d8: Docs: clearer wording in the file-input and TypeScript-runtime sections. No API or behavior changes.\n\n---\n\n## 0.6.17 (2026-06-12)\n\n### SDK\n\n#### Patch Changes\n\n- 716c3cf: Update the hosted default API base URL and API-key guidance from `app.eigenpal.com` to `studio.eigenpal.com`.\n\n---\n\n## 0.6.16 (2026-06-12)\n\n### CLI\n\n#### Patch Changes\n\n- 75dd64c: Internal refactor: move the skill tool registry into its own module so other tooling can import it. No change to any command, flag, argument, or output.\n\n---\n\n## 0.6.15 (2026-06-10)\n\n### CLI\n\n#### Minor Changes\n\n- ca87265: Unify workflow and agent run starts behind the canonical `/api/v1/run/\\{target}` endpoint, root `eigenpal run` / `eigenpal rerun` commands, and root SDK `client.run()` / `client.rerun()` methods.\n\n The old nested CLI commands and SDK resource methods for starting workflow or agent runs have been removed.\n\n#### Patch Changes\n\n- 5ea0bb5: `workflow dataset pull` gains `--example-id <id>` (repeatable) to export a single example or a selected subset of a dataset, instead of always pulling the whole dataset. The subset ZIP uses the same archive layout as a full pull, so it re-imports into any dataset via `dataset push --mode append`. Requesting an example id that does not exist for the workflow exits non-zero.\n\n### SDK\n\n#### Minor Changes\n\n- ca87265: Unify workflow and agent run starts behind the canonical `/api/v1/run/\\{target}` endpoint, root `eigenpal run` / `eigenpal rerun` commands, and root SDK `client.run()` / `client.rerun()` methods.\n\n The old nested CLI commands and SDK resource methods for starting workflow or agent runs have been removed.\n\n---\n\n## 0.6.10 (2026-06-08)\n\n### CLI\n\n#### Patch Changes\n\n- 99ca1b4: Unify agent and workflow run commands and SDK helpers on the shared `/api/v1/runs` API, including the public `client.runs` facade and regenerated SDK reference docs.\n\n### SDK\n\n#### Patch Changes\n\n- 99ca1b4: Unify agent and workflow run commands and SDK helpers on the shared `/api/v1/runs` API, including the public `client.runs` facade and regenerated SDK reference docs.\n\n---\n\n## 0.6.9 (2026-06-04)\n\n### SDK\n\n#### Minor Changes\n\n- 5e7c051: Add `observability` (phase timeline + structured failure) to workflow execution and agent run status API responses.\n\n---\n\n## 0.6.6 (2026-06-03)\n\n### CLI\n\n#### Patch Changes\n\n- 245f347: Clean up the agent CLI surface by removing obsolete compatibility commands, moving reruns to `agents rerun`, and replacing run pulls with canonical artifact fetching.\n- 5ab00ee: Tighten permissions on `~/.config/eigenpal/credentials.json` and its parent directory to owner-only (0600 / 0700). Previously the file was written 0600 but the parent directory inherited the user's umask (typically 0755), allowing other local users to list the directory and stat the file. The CLI now also re-tightens permissions on every write, so installs created with older versions are corrected on the next `auth login` / `auth use`.\n\n---\n\n## 0.6.4 (2026-06-03)\n\n### CLI\n\n#### Patch Changes\n\n- c3486a5: Fix agent git cutover QA findings: dashboard runs now navigate to the created run, inbound email aliases preserve mixed-case organization qualifiers, sandbox source materializes under `/workspace/agent`, run artifact downloads use direct paths like `/files/eigenpal.lock`, wait-for-completion responses include source provenance, and CLI wait/watch commands exit nonzero for failed or cancelled runs.\n\n### SDK\n\n#### Patch Changes\n\n- c3486a5: Fix agent git cutover QA findings: dashboard runs now navigate to the created run, inbound email aliases preserve mixed-case organization qualifiers, sandbox source materializes under `/workspace/agent`, run artifact downloads use direct paths like `/files/eigenpal.lock`, wait-for-completion responses include source provenance, and CLI wait/watch commands exit nonzero for failed or cancelled runs.\n\n---\n\n## 0.6.2 (2026-06-02)\n\n### CLI\n\n#### Patch Changes\n\n- d2202b6: List all agent runs for unqualified targets, and reserve source-ref filtering for explicit `@ref` targets.\n\n---\n\n## 0.6.0 (2026-06-02)\n\n### CLI\n\n#### Minor Changes\n\n- 2aeeaf2: Add native source `git save` and branch-aware `git release` flows for Git-backed builder workspaces.\n\n#### Patch Changes\n\n- 2aeeaf2: Complete the agent Git cutover with pluralized agent CLI commands, source-ref run support, lockfile metadata, and regenerated SDK/docs surfaces.\n- 2aeeaf2: Expose Git-backed agent source refs and public source automation APIs consistently across CLI docs and SDK facades.\n\n### SDK\n\n#### Patch Changes\n\n- 2aeeaf2: Complete the agent Git cutover with pluralized agent CLI commands, source-ref run support, lockfile metadata, and regenerated SDK/docs surfaces.\n- 2aeeaf2: Expose Git-backed agent source refs and public source automation APIs consistently across CLI docs and SDK facades.\n\n---\n\n## 0.5.12 (2026-06-02)\n\n### CLI\n\n#### Minor Changes\n\n- d3b0768: Add `control.fail` and `ai.classify` step types, plus the `expected/error.json` dataset assertion format.\n - `control.fail` terminates a workflow with a typed status code + message envelope. Optional `condition` template gates the fail. Compose with `ai.classify` to reject documents that match an undesired label.\n - `ai.classify` runs single-label closed-set classification through the existing extract LLM pipeline. Output is `\\{ label, confidence, reason }`, where `label` is constrained to the configured names.\n - `examples/<name>/expected/error.json` (mutually exclusive with `output.json`) lets eval examples assert that a workflow should fail with a specific `\\{ code, messageContains, step }`. The exact-diff evaluator scores 1 on match, 0 otherwise.\n - `eigenpal workflow validate` now catches `expected/error.json` shape issues and per-step config violations (e.g. `ai.classify` with fewer than two labels) at push time instead of deferring to runtime.\n\n Skill reference docs (`step-types.md`, `dataset-format.md`, `evaluators.md`, `workflow-yaml.md`) updated.\n\n#### Patch Changes\n\n- 99cad97: Skill reference (auto-generated from `WorkflowDefinitionSchema`) now documents the new `values` row for enum inputs, alongside the existing `items` row used by array inputs. Output-only doc refresh — no CLI behavior change.\n- d70f697: Document the `control.parallel`, `control.parallel_map`, `control.foreach`, `control.if`, and `control.block` step types in the bundled skill reference. The auto-generated catalog cannot render nested step shapes, so the YAML form, output access paths (e.g. `steps.<parallel>.output.<branch>.<inner>.<field>`), and scoping rules now live as hand-written prose. Also documents the multi-step iteration hazard: only the LAST inner step's output is keyed into each `items[i]` for `parallel_map` / `foreach` — end the body with a `transform.script` if you need to preserve intermediate fields.\n- ed2cde6: Fix `eigenpal workflow pull` writing a 0-byte file. The v1 single-workflow endpoint now returns the current YAML at the top level (`yamlContent`) via a new `WorkflowDetail` response shape, and the CLI throws a clear error instead of silently writing empty output when no version has been published. Also fixes adjacent regressions caused by the same picker: `workflow list` now shows the workflow name and version columns (previously always `-`), `workflow push --bump` reads the server's current version correctly, the \"did you mean?\" suggestion on a slug typo lists candidates again, and `workflow execution list` shows a duration column computed from the run start/end timestamps.\n\n---\n\n## 0.5.11 (2026-05-26)\n\n### CLI\n\n#### Patch Changes\n\n- 2958f4d: Fix Git-backed source smoke-test polish: hidden `git show` and `git sync` now accept bare agent slugs, and workflow scaffolds use the current `triggerMethods` YAML shape.\n\n---\n\n## 0.5.10 (2026-05-26)\n\n### CLI\n\n#### Patch Changes\n\n- aee7e0c: Add hidden Git source commands for editing trigger policy and encrypted secrets.\n\n---\n\n## 0.5.9 (2026-05-26)\n\n### CLI\n\n#### Major Changes\n\n- fadb59b: CLI command tree reorganized around the data model. Top-level surface is now\n `workflow`, `agent` (reserved), and `skill`; everything that operates on a\n workflow lives under `workflow`, grouped by sub-entity.\n\n Renames (clean break — no aliases):\n - `eigenpal exec <slug>` → `eigenpal workflow execution run <slug>`\n - `eigenpal clear` → `eigenpal workflow clear`\n - `eigenpal install-skill` → `eigenpal skill` (same interactive multiselect UX)\n - `eigenpal execution \\{get,list,watch,compare}` → `eigenpal workflow execution \\{…}`\n - `eigenpal workflow set-definition` → `eigenpal workflow push`\n - `eigenpal workflow get-definition` → `eigenpal workflow pull`\n - `eigenpal workflow set-evaluators` / `get-evaluators` → `workflow evaluators \\{push,pull}`\n - `eigenpal workflow set-dataset` / `get-dataset` / `list-examples` → `workflow dataset \\{push,pull,list}`\n - `eigenpal workflow run-experiment` / `get-experiment-status` / `get-experiment-results` /\n `get-eval-results` / `list-executions` → `workflow experiment \\{run,status,results,eval-results,list}`\n - `eigenpal workflow list-versions` / `restore-version` → `workflow version \\{list,restore}`\n\n[View full release notes →](/releases/0.5.9)\n\n{/* GENERATED:CHANGELOG_INDEX END */}\n"
|
|
24
24
|
},
|
|
25
25
|
{
|
|
26
26
|
"topic": "cli/agents",
|
|
@@ -1107,6 +1107,13 @@
|
|
|
1107
1107
|
"source": "public",
|
|
1108
1108
|
"content": "---\ntitle: '0.20.0'\nversion: '0.20.0'\ndate: '2026-09-22'\ncommit: '0ce20920966314cb4335f9fddc51120364dfacb6'\ndescription: 'EigenPal platform release 0.20.0'\n---\n\n## Platform (Studio)\n\n- Datasets can now be sent for client review without exporting files. Create a review request from a dataset, highlight the fields that need attention, mark others as not required, and invite client teammates with the new reviewer role. They walk examples from a dropdown, inspect the fields, leave notes, record per-field decisions, and approve or reject each row. Closing a finished review does not auto-apply changes — reconcile expected outputs manually. The Reviews queue keeps finished requests visible with a status filter so old approvals stay findable. Reviewers see the same Studio shell with permission-aware empty states.\n\n## Public API\n\n- New dataset review endpoints under `/api/v1/automations/:id/dataset-review-requests`: create a review from dataset examples with reviewer `instructions`, `focusFields` (paths plus optional reasons), `ignoredFields` for paths reviewers can skip, and optional `itemNotes`. Approve, edit, reject, reopen, comment, or record a `field-decision` on each example (including clearing a decision with `decision: null`), then poll `progress.complete` and close the request with `PATCH` status. Dataset reconciliation stays manual — nothing is deleted by reject. A new `reviewer` organization role can read review queues and submit item decisions but cannot edit workflows.\n\n## CLI\n\n- `eigenpal workflow dataset review-request` (and the `eigenpal agents dataset` mirror) is the agent-friendly review loop: create a request with reviewer instructions, `--focus` / `--focus-reason` paths, `--ignore` paths reviewers can skip, and per-example `--item-note` / `--field-note` comments; `list`/`get`/`events` expose `progress.complete`, `fieldDecisions`, and `inputDrifted`; `item --action` records approve/reject/comment/edit plus per-field `field-decision` (clear with `--clear` / `--decision null`); `update --status closed` finishes the request. There is no auto-apply — pull and reconcile examples manually. Reject is recommendation-only; nothing is deleted.\n\n## SDK\n\n- `client.automations.datasetReviewRequests` (`dataset_review_requests` in Python) covers the full dataset review lifecycle: list and get with `progress`, `focusFields`, `ignoredFields`, `fieldDecisions`, and `inputDrifted`; create with reviewer instructions and per-field notes; update request metadata or close with status; update items including `field-decision` (pass `decision: null` to clear); and the per-user activity trail. Dataset write-back stays manual — there is no lock endpoint.\n\n## Infrastructure & processing\n\n- Replace the eagerly constructed `eigenpalAjv` singleton with a lazy `getEigenpalAjv()` accessor. Ajv compiles schemas with `new Function`, which the Studio Content-Security-Policy forbids — constructing at import time crashed every page whose client bundle transitively imported `@eigenpal/types` validation (including all review surfaces, which never validate client-side). Server-side call sites are unchanged apart from the accessor.\n"
|
|
1109
1109
|
},
|
|
1110
|
+
{
|
|
1111
|
+
"topic": "releases/0.20.1",
|
|
1112
|
+
"title": "0.20.1",
|
|
1113
|
+
"description": "EigenPal platform release 0.20.1",
|
|
1114
|
+
"source": "public",
|
|
1115
|
+
"content": "---\ntitle: '0.20.1'\nversion: '0.20.1'\ndate: '2026-09-23'\ncommit: 'f97ed661b5a5351fce94c37dec8f06a4ff85b217'\ndescription: 'EigenPal platform release 0.20.1'\n---\n\n## Platform (Studio)\n\n- Credit limits now apply consistently across the product. Agent runs, the workflow builder assistant, and the expression generator are checked against your remaining balance before they start, and the assistant and expression generator now record their usage on your usage page instead of being invisible. A cancelled agent run is billed for the work it actually completed rather than dropping off your usage entirely. Organization creation is capped per account, both by how many you own at once and by how many you create over a rolling window, so one account cannot spin up unlimited free trials. A very long builder conversation is now refused with a message asking you to start a new chat, rather than being sent to the model in full. Deleting an organization now removes its stored files before the organization itself disappears. A large organization can take more than one pass, and the dialog now says accurately what happens: files are removed immediately and clear backups within 7 days.\n\n## Public API\n\n- Starting a run now returns `402 insufficient_credits` when your organization has spent its credit allowance. The check happens before the request body is read, so no files are uploaded and no work begins on a run that cannot be paid for. File uploads return the same status for the same reason, and both are now described in the API reference. The API reference also documents `503`, which endpoints return when request accounting is briefly unavailable. It means the request was not processed and is safe to retry; it is not a rate-limit rejection.\n"
|
|
1116
|
+
},
|
|
1110
1117
|
{
|
|
1111
1118
|
"topic": "releases/0.5.10",
|
|
1112
1119
|
"title": "0.5.10",
|