{
 "openapi": "3.1.0",
 "info": {
  "title": "StateSet Computer Use API",
  "version": "0.1.0"
 },
 "paths": {
  "/api/v1/health": {
   "get": {
    "tags": [
     "v1-api",
     "Health"
    ],
    "summary": "V1 Health",
    "description": "Return 200 with a minimal liveness payload, or 503 on db failure.",
    "operationId": "getV1Health",
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HealthResponse"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/system/info": {
   "get": {
    "tags": [
     "v1-api",
     "Health"
    ],
    "summary": "Discoverable platform metadata (version, environment, supported models)",
    "description": "Static metadata about the running API.\n\nUseful for SDKs that want to detect the deployment environment, the\nset of models they can pin, and which optional features are\navailable without hard-coding strings.\n\nCached server-side for 300s via Cache-Control; supports\n`If-None-Match` so clients can avoid re-parsing the JSON when\nnothing has changed.",
    "operationId": "getSystemInfo",
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/SystemInfoResponse"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/system/limits": {
   "get": {
    "tags": [
     "v1-api",
     "Health"
    ],
    "summary": "Discoverable input/output caps as a single source of truth",
    "description": "Surface every numeric cap the v1 API enforces.\n\nLets SDKs validate locally before sending \u2014 `len(instruction) >\ninstruction_max_chars`, etc. Cached for 300s via Cache-Control with\nIf-None-Match support; SDKs can refetch cheaply on app boot.",
    "operationId": "getSystemLimits",
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/SystemLimitsResponse"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/system/changelog": {
   "get": {
    "tags": [
     "v1-api",
     "Health"
    ],
    "summary": "Versioned list of v1 API changes",
    "description": "Programmatic changelog of v1 API additions.\n\nSDKs can poll this to detect new capabilities (\"are there endpoints I\ndon't know about yet?\") without diffing the full OpenAPI spec\nbetween generations. Cached for 300s; supports If-None-Match.",
    "operationId": "getSystemChangelog",
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/SystemChangelogResponse"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/system/benchmarks": {
   "get": {
    "tags": [
     "v1-api",
     "Health"
    ],
    "summary": "Tenant-agnostic platform outcome benchmarks with BPO comparison",
    "description": "Public outcome benchmarks for Strategy \u00a78.6.\n\nNo auth required \u2014 the response is platform-wide, tenant-agnostic,\nand k-anonymized at the SKU level (SKUs below\nPUBLIC_BENCHMARK_MIN_OUTCOMES_PER_SKU are omitted).\n\nCached for 5 minutes so a public-facing marketing page can call this\non every render without thrashing the DB.",
    "operationId": "getSystemBenchmarks",
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/PublicBenchmarksResponse"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/system/webhook-events": {
   "get": {
    "tags": [
     "v1-api",
     "Health"
    ],
    "summary": "Discoverable catalog of webhook event types and payload fields",
    "description": "Programmatic catalog of webhook events.\n\nTenant SDK consumers wiring up a receiver can consult this endpoint\nto know:\n\n  - Which `event_type` strings to expect on the wire\n  - Which payload fields are guaranteed (envelope + per-event)\n  - Which subscription wildcard means \"everything\"\n\nThe catalog is the single source of truth \u2014 both the worker (when\nemitting) and the subscription validators (when accepting an\n`events` array) reference it.\n\nCached for 300s; supports If-None-Match.",
    "operationId": "getWebhookEventCatalog",
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/WebhookEventsResponse"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/jobs/preview": {
   "post": {
    "tags": [
     "v1-api",
     "Trigger"
    ],
    "summary": "Preview Job V1",
    "description": "Dry-run a trigger payload without queueing.\n\nResolves template defaults + per-job overrides into the final\n`params` dict, surfaces what model + agent_mode would actually be\nused, and reports whether the request would currently pass quota.\nDoes NOT create a Job row, consume an idempotency key, or count\nagainst quota \u2014 purely diagnostic.\n\nUseful before sending a large batch: catch the misconfigured\n`agent_type`, the wrong model alias, the missing template default,\nwithout burning the budget.",
    "operationId": "previewJob",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/TriggerRequest"
       }
      }
     },
     "required": true
    },
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/JobPreviewResponse"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/trigger": {
   "post": {
    "tags": [
     "v1-api",
     "Trigger"
    ],
    "summary": "Trigger Agent",
    "description": "Trigger an agent run via the external API.",
    "operationId": "triggerAgent",
    "parameters": [
     {
      "name": "Idempotency-Key",
      "in": "header",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "title": "Idempotency-Key"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/TriggerRequest"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/TriggerResponse"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/trigger/batch": {
   "post": {
    "tags": [
     "v1-api",
     "Trigger"
    ],
    "summary": "Trigger Agent Batch",
    "description": "Submit up to 50 jobs in a single API call.\n\nPer-item validation: bad rows surface as individual errors in the\nresponse without blocking the rest. The whole batch consumes ONE\nrate-limit slot and ONE quota check (sized to the count of\nwell-formed items), so this is the right path for tenants enqueuing\nmany small tasks at once.\n\n**Idempotency.** Pass an `Idempotency-Key` header to make a batch\nreplay-safe: a retried call returns the original batch's job ids and\nsets the `Idempotency-Replayed: true` header. Each item gets a\nderived idempotency key of the form\n`v1.trigger.batch:<your-key>:<index>`, so partial replays are\nwell-defined too.",
    "operationId": "triggerAgentBatch",
    "parameters": [
     {
      "name": "Idempotency-Key",
      "in": "header",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "title": "Idempotency-Key"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/BatchTriggerRequest"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/BatchTriggerResponse"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/templates": {
   "get": {
    "tags": [
     "v1-api",
     "Templates"
    ],
    "summary": "List Templates V1",
    "description": "Discover the `agent_type` values you can use on `/trigger`.\n\nReturns the union of platform built-ins (always queue-able) and any\nTemplate rows your tenant owns. Sorted: built-ins first (alphabetical),\nthen tenant templates.",
    "operationId": "listTemplates",
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "items": {
          "$ref": "#/components/schemas/TemplateInfo"
         },
         "type": "array",
         "title": "Response Listtemplates"
        }
       }
      }
     }
    }
   },
   "post": {
    "tags": [
     "v1-api",
     "Templates"
    ],
    "summary": "Create Template V1",
    "description": "Create a tenant-owned template.\n\nReturns 422 if the name collides with a platform built-in, 409 if a\ntemplate with the same name already exists for the tenant.",
    "operationId": "createTemplate",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateTemplateRequest"
       }
      }
     },
     "required": true
    },
    "responses": {
     "201": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/TemplateInfo"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/webhook-test": {
   "post": {
    "tags": [
     "v1-api",
     "Templates"
    ],
    "summary": "Test Webhook V1",
    "description": "Send a probe POST to verify a webhook URL is reachable.\n\nThe probe carries the **same envelope shape and headers as a\nreal `job.completed` delivery** (with a synthetic flat payload\nunderneath), so the receiver is tested end-to-end before a real\njob is queued. Returns delivery status and round-trip latency.\n\nEnvelope fields (`event_id`, `event_type`, `event_timestamp`,\n`api_version`) are stamped exactly like production deliveries \u2014\ntenants writing receivers against this probe see the same shape\nthey'll see when a real job completes.",
    "operationId": "testWebhook",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/WebhookTestRequest"
       }
      }
     },
     "required": true
    },
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/WebhookTestResponse"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/templates/bulk-delete": {
   "post": {
    "tags": [
     "v1-api",
     "Templates"
    ],
    "summary": "Bulk Delete Templates V1",
    "description": "Delete up to 50 templates by name in one call.\n\nBuilt-in names are skipped per-row (cannot be deleted, ever);\nunknown / cross-tenant names also surface as per-row failures\nrather than failing the batch. Single transaction commit.",
    "operationId": "bulkDeleteTemplates",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/BulkDeleteTemplatesRequest"
       }
      }
     },
     "required": true
    },
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/BulkDeleteTemplatesResponse"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/templates/import": {
   "post": {
    "tags": [
     "v1-api",
     "Templates"
    ],
    "summary": "Import Templates V1",
    "description": "Bulk template import with explicit conflict policy.\n\n`on_conflict=error` is all-or-nothing: any pre-existing name aborts\nthe whole import before any DB writes land. The `skip` and `replace`\nmodes apply per-row and report outcomes individually.\n\nBuilt-in name collisions are rejected per-row regardless of the\nconflict policy \u2014 you can never shadow a platform built-in.",
    "operationId": "importTemplates",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ImportTemplatesRequest"
       }
      }
     },
     "required": true
    },
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ImportTemplatesResponse"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/templates/{name}": {
   "get": {
    "tags": [
     "v1-api",
     "Templates"
    ],
    "summary": "Get Template V1",
    "description": "Single template detail.\n\nReturns the same fields as `GET /templates` plus the `defaults` blob,\nso callers can inspect what params will be auto-merged before they\nsend a `/trigger`. Built-in lookups always succeed; tenant lookups\n404 if the template doesn't belong to the calling tenant.",
    "operationId": "getTemplate",
    "parameters": [
     {
      "name": "name",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "title": "Name"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/TemplateDetail"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   },
   "patch": {
    "tags": [
     "v1-api",
     "Templates"
    ],
    "summary": "Update Template V1",
    "description": "Update description and/or defaults on a tenant-owned template.\n\nThe template `name` is immutable \u2014 to rename, delete and re-create\n(which intentionally orphans referencing job rows from the old name).\nBuilt-in templates cannot be modified.",
    "operationId": "updateTemplate",
    "parameters": [
     {
      "name": "name",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "title": "Name"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateTemplateRequest"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/TemplateInfo"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   },
   "delete": {
    "tags": [
     "v1-api",
     "Templates"
    ],
    "summary": "Delete Template V1",
    "description": "Delete a tenant-owned template.\n\nBuilt-in names cannot be deleted (404). Existing jobs that referenced\nthe template by name continue to work \u2014 the `template` column is\ninformational, not a foreign key.",
    "operationId": "deleteTemplate",
    "parameters": [
     {
      "name": "name",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "title": "Name"
      }
     }
    ],
    "responses": {
     "204": {
      "description": "Successful Response"
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/keys": {
   "get": {
    "tags": [
     "v1-api",
     "Keys"
    ],
    "summary": "List Api Keys V1",
    "description": "List the calling tenant's API keys.\n\nThe plaintext key and the SHA-256 hash are never returned \u2014 only the\nmetadata a caller could need for an audit dashboard (prefix, scopes,\nlast_used_at, etc.). The current request's key is flagged with\n`is_current: true` so callers can self-identify in the list.",
    "operationId": "listApiKeys",
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "items": {
          "$ref": "#/components/schemas/APIKeySummary"
         },
         "type": "array",
         "title": "Response Listapikeys"
        }
       }
      }
     }
    }
   },
   "post": {
    "tags": [
     "v1-api",
     "Keys"
    ],
    "summary": "Create Api Key V1",
    "description": "Create a new API key for the calling tenant.\n\nRequires the `admin` scope on the calling key \u2014 non-admin keys can\nonly read and use keys, not mint new ones. The plaintext is returned\nonce in this response and never again; lose it and the only path\nforward is to delete and re-create.",
    "operationId": "createApiKey",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateAPIKeyRequest"
       }
      }
     },
     "required": true
    },
    "responses": {
     "201": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/CreateAPIKeyResponse"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/auth/whoami": {
   "get": {
    "tags": [
     "v1-api",
     "Keys"
    ],
    "summary": "Auth Whoami V1",
    "description": "Echo the calling key's effective auth context.\n\nUseful for SDK debugging \u2014 \"what scopes do I have, what tenant am I\nbound to?\" Doesn't hit the database; returns whatever\n`get_api_key_tenant` resolved at request time. Reaching this endpoint\nsuccessfully proves the key is active, unexpired, and within rate\nlimit (the auth dependency would have rejected otherwise).",
    "operationId": "whoami",
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/WhoamiResponse"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/keys/{key_id}": {
   "get": {
    "tags": [
     "v1-api",
     "Keys"
    ],
    "summary": "Get Api Key V1",
    "description": "Single-key detail.\n\nMirrors `GET /keys` for one row \u2014 no plaintext, no hash. Useful for\nintegrations that store the `id` separately from the secret and need\nto surface scope/rate-limit metadata without re-listing.",
    "operationId": "getApiKey",
    "parameters": [
     {
      "name": "key_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid",
       "title": "Key Id"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/APIKeySummary"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   },
   "patch": {
    "tags": [
     "v1-api",
     "Keys"
    ],
    "summary": "Update Api Key V1",
    "description": "Update a key's name / scopes / rate limit / active flag.\n\nCannot rotate the underlying secret \u2014 for that, delete and re-create.\nA key cannot deactivate itself (would lock the caller out mid-request),\nso trying to set `is_active=false` on the calling key returns 409.",
    "operationId": "updateApiKey",
    "parameters": [
     {
      "name": "key_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid",
       "title": "Key Id"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateAPIKeyRequest"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/APIKeySummary"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   },
   "delete": {
    "tags": [
     "v1-api",
     "Keys"
    ],
    "summary": "Delete Api Key V1",
    "description": "Permanently revoke an API key.\n\nA key can delete itself \u2014 the response still reaches the caller, but\nevery subsequent request with that key will 401. Use this rather\nthan `is_active=false` if you want the row gone entirely.",
    "operationId": "deleteApiKey",
    "parameters": [
     {
      "name": "key_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid",
       "title": "Key Id"
      }
     }
    ],
    "responses": {
     "204": {
      "description": "Successful Response"
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/approvals": {
   "get": {
    "tags": [
     "v1-api",
     "Approvals"
    ],
    "summary": "List Approvals V1",
    "description": "List approval requests for the calling tenant.\n\nApprovals fire when a job hits an action gated by an approval policy\n(typically destructive operations on connected services). The job\nsits in `awaiting_approval` status until a reviewer calls\n`/approvals/{id}/approve` or `/reject`.",
    "operationId": "listApprovals",
    "parameters": [
     {
      "name": "pending_only",
      "in": "query",
      "required": false,
      "schema": {
       "type": "boolean",
       "description": "When true (default) only return rows still awaiting review. Pass `false` to include approved/rejected/expired rows for audit dashboards.",
       "default": true,
       "title": "Pending Only"
      },
      "description": "When true (default) only return rows still awaiting review. Pass `false` to include approved/rejected/expired rows for audit dashboards."
     }
    ],
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "type": "array",
         "items": {
          "$ref": "#/components/schemas/ApprovalSummary"
         },
         "title": "Response Listapprovals"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/approvals/{approval_id}/approve": {
   "post": {
    "tags": [
     "v1-api",
     "Approvals"
    ],
    "summary": "Approve Approval V1",
    "description": "Approve a pending action \u2014 the worker resumes the job.",
    "operationId": "approveApproval",
    "parameters": [
     {
      "name": "approval_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid",
       "title": "Approval Id"
      }
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "anyOf": [
         {
          "$ref": "#/components/schemas/ApprovalReviewRequest"
         },
         {
          "type": "null"
         }
        ],
        "title": "Body"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ApprovalSummary"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/approvals/{approval_id}/reject": {
   "post": {
    "tags": [
     "v1-api",
     "Approvals"
    ],
    "summary": "Reject Approval V1",
    "description": "Reject a pending action \u2014 the worker treats it as a refused tool call.",
    "operationId": "rejectApproval",
    "parameters": [
     {
      "name": "approval_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid",
       "title": "Approval Id"
      }
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "anyOf": [
         {
          "$ref": "#/components/schemas/ApprovalReviewRequest"
         },
         {
          "type": "null"
         }
        ],
        "title": "Body"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ApprovalSummary"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/approval-policies": {
   "get": {
    "tags": [
     "v1-api",
     "Approvals"
    ],
    "summary": "List Approval Policies V1",
    "description": "List approval policies for the calling tenant.\n\nNewest-first. Returns policy id, name, tool_patterns, and active\nflag \u2014 sensitive (no secrets to redact). Use `is_active=False`\nrows to suspend a policy without deleting; the audit trail is\npreserved either way.",
    "operationId": "listApprovalPolicies",
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "items": {
          "$ref": "#/components/schemas/ApprovalPolicySummary"
         },
         "type": "array",
         "title": "Response Listapprovalpolicies"
        }
       }
      }
     }
    }
   },
   "post": {
    "tags": [
     "v1-api",
     "Approvals"
    ],
    "summary": "Create Approval Policy V1",
    "description": "Create an approval policy.\n\nThe policy fires when a worker tool-call's name matches any of\n`tool_patterns`. Without `auto_approve_rules`, every match\npauses the job and creates an `ApprovalRequest` for human\nreview. With auto-approve rules, matches are silently approved\nbased on the rule (rate-limit windows, allow-listed input\nsubsets, etc. \u2014 see operator docs).\n\nAdmin scope only \u2014 these gates are security-sensitive.",
    "operationId": "createApprovalPolicy",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ApprovalPolicyRequest"
       }
      }
     },
     "required": true
    },
    "responses": {
     "201": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ApprovalPolicySummary"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/approval-policies/{policy_id}": {
   "patch": {
    "tags": [
     "v1-api",
     "Approvals"
    ],
    "summary": "Update Approval Policy V1",
    "description": "Update name / tool_patterns / auto_approve_rules / is_active.\n\nEmpty PATCH (no fields set) returns 422 \u2014 disallows accidental\nno-op writes that would still bump `updated_at` and clutter\naudit trails.",
    "operationId": "updateApprovalPolicy",
    "parameters": [
     {
      "name": "policy_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid",
       "title": "Policy Id"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ApprovalPolicyUpdateRequest"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ApprovalPolicySummary"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   },
   "delete": {
    "tags": [
     "v1-api",
     "Approvals"
    ],
    "summary": "Delete Approval Policy V1",
    "description": "Delete an approval policy. In-flight `ApprovalRequest` rows\nthat referenced the policy are NOT cascaded \u2014 they retain\n`policy_id` for audit but lose the linked policy row. To\nsuspend without losing audit trail, PATCH `is_active=false`.",
    "operationId": "deleteApprovalPolicy",
    "parameters": [
     {
      "name": "policy_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid",
       "title": "Policy Id"
      }
     }
    ],
    "responses": {
     "204": {
      "description": "Successful Response"
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/custom-agents": {
   "get": {
    "tags": [
     "v1-api",
     "Templates"
    ],
    "summary": "List Custom Agents V1",
    "description": "List custom agents for the calling tenant. Newest-first.",
    "operationId": "listCustomAgents",
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "items": {
          "$ref": "#/components/schemas/CustomAgentSummary"
         },
         "type": "array",
         "title": "Response Listcustomagents"
        }
       }
      }
     }
    }
   },
   "post": {
    "tags": [
     "v1-api",
     "Templates"
    ],
    "summary": "Create Custom Agent V1",
    "description": "Create a custom agent.\n\nConfigurations stick until deleted. Use `PATCH` to flip `is_active`\nrather than re-creating to preserve audit history.",
    "operationId": "createCustomAgent",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CustomAgentRequest"
       }
      }
     },
     "required": true
    },
    "responses": {
     "201": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/CustomAgentSummary"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/custom-agents/{agent_id}": {
   "get": {
    "tags": [
     "v1-api",
     "Templates"
    ],
    "summary": "Get Custom Agent V1",
    "description": "Fetch a single custom agent by id.",
    "operationId": "getCustomAgent",
    "parameters": [
     {
      "name": "agent_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid",
       "title": "Agent Id"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/CustomAgentSummary"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   },
   "patch": {
    "tags": [
     "v1-api",
     "Templates"
    ],
    "summary": "Update Custom Agent V1",
    "description": "Update fields on a custom agent. Empty PATCH (no fields) returns 422.",
    "operationId": "updateCustomAgent",
    "parameters": [
     {
      "name": "agent_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid",
       "title": "Agent Id"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CustomAgentUpdateRequest"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/CustomAgentSummary"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   },
   "delete": {
    "tags": [
     "v1-api",
     "Templates"
    ],
    "summary": "Delete Custom Agent V1",
    "description": "Delete a custom agent.\n\nExisting AgentRun rows that referenced this agent are NOT cascaded;\nthey retain `custom_agent_id` for audit but lose the linked row.\nTo suspend without losing audit trail, PATCH `is_active=false`.",
    "operationId": "deleteCustomAgent",
    "parameters": [
     {
      "name": "agent_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid",
       "title": "Agent Id"
      }
     }
    ],
    "responses": {
     "204": {
      "description": "Successful Response"
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/skills": {
   "get": {
    "tags": [
     "v1-api",
     "Templates"
    ],
    "summary": "Platform-wide skill catalog (read-only on v1)",
    "description": "List every published skill. Unscoped by tenant \u2014 same catalog\nfor every caller. Sorted alphabetically by `key` for stable\ncursoring on SDK clients that paginate locally.\n\nTo attach a skill to a custom agent, copy its `key` into the\ncustom agent's `skills` array (see `POST /api/v1/custom-agents`).",
    "operationId": "listSkills",
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "items": {
          "$ref": "#/components/schemas/SkillSummary"
         },
         "type": "array",
         "title": "Response Listskills"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/skills/{key}": {
   "get": {
    "tags": [
     "v1-api",
     "Templates"
    ],
    "summary": "Single skill by stable key",
    "description": "Look up a skill by its stable `key`. 404 when not found.",
    "operationId": "getSkill",
    "parameters": [
     {
      "name": "key",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "title": "Key"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/SkillSummary"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/keys/bulk-revoke": {
   "post": {
    "tags": [
     "v1-api",
     "Keys"
    ],
    "summary": "Bulk Revoke Api Keys V1",
    "description": "Revoke up to 50 keys in one call (admin only).\n\nSelf-protection: the calling key is never auto-revoked even if\nincluded in the list. Use the singular `DELETE /keys/{id}` against\nthe same id from a different key if you really want it gone.\n\nPer-row outcomes \u2014 unknown / cross-tenant ids surface as failures\nwithout aborting the batch.",
    "operationId": "bulkRevokeApiKeys",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/BulkRevokeKeysRequest"
       }
      }
     },
     "required": true
    },
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/BulkRevokeKeysResponse"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/keys/{key_id}/rotate": {
   "post": {
    "tags": [
     "v1-api",
     "Keys"
    ],
    "summary": "Rotate Api Key V1",
    "description": "Issue a new plaintext secret for an existing key, in place.\n\nPreserves the row's id, name, scopes, rate limit, and expiration \u2014\nonly the secret (and therefore key_hash + key_prefix) changes. The\nold plaintext stops working the instant this commits, so callers\nshould orchestrate the cutover: deploy the new value before calling\nrotate, OR have a brief outage if you can tolerate it.\n\nA key can rotate itself; the response carries the new plaintext, but\nthe caller must update their auth header on the next request.",
    "operationId": "rotateApiKey",
    "parameters": [
     {
      "name": "key_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid",
       "title": "Key Id"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/CreateAPIKeyResponse"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/webhooks": {
   "get": {
    "tags": [
     "v1-api",
     "Webhooks"
    ],
    "summary": "List Webhook Endpoints V1",
    "description": "List the calling tenant's registered webhook endpoints (no secrets).",
    "operationId": "listWebhookEndpoints",
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "items": {
          "$ref": "#/components/schemas/WebhookEndpointSummary"
         },
         "type": "array",
         "title": "Response Listwebhookendpoints"
        }
       }
      }
     }
    }
   },
   "post": {
    "tags": [
     "v1-api",
     "Webhooks"
    ],
    "summary": "Create Webhook Endpoint V1",
    "description": "Register a durable webhook endpoint.\n\nReturns the signing secret exactly once on creation. Subsequent reads\nomit it; if you lose it or want to roll a leaked secret, call\n``POST /webhooks/{id}/rotate-secret`` \u2014 it preserves the delivery\nhistory and only changes the signing secret.",
    "operationId": "createWebhookEndpoint",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CreateWebhookEndpointRequest"
       }
      }
     },
     "required": true
    },
    "responses": {
     "201": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/WebhookEndpointWithSecret"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/webhooks/{endpoint_id}": {
   "get": {
    "tags": [
     "v1-api",
     "Webhooks"
    ],
    "summary": "Get Webhook Endpoint V1",
    "description": "Fetch a single webhook endpoint by id.\n\nMirrors the HEAD handler's existence check but returns the endpoint\nsummary body so dashboards/CLIs can show url + events + active\nstate without listing every endpoint. Cross-tenant ids 404 \u2014 the\nsecret is never exposed.",
    "operationId": "getWebhookEndpoint",
    "parameters": [
     {
      "name": "endpoint_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid",
       "title": "Endpoint Id"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/WebhookEndpointSummary"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   },
   "patch": {
    "tags": [
     "v1-api",
     "Webhooks"
    ],
    "summary": "Update Webhook Endpoint V1",
    "description": "Update url / events / active flag on a registered webhook endpoint.\n\nCannot rotate the signing secret \u2014 for that, delete and re-create.\nEmpty PATCH (no fields) returns 422.",
    "operationId": "updateWebhookEndpoint",
    "parameters": [
     {
      "name": "endpoint_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid",
       "title": "Endpoint Id"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateWebhookEndpointRequest"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/WebhookEndpointSummary"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   },
   "delete": {
    "tags": [
     "v1-api",
     "Webhooks"
    ],
    "summary": "Delete Webhook Endpoint V1",
    "description": "Delete a webhook endpoint. In-flight delivery rows are preserved.",
    "operationId": "deleteWebhookEndpoint",
    "parameters": [
     {
      "name": "endpoint_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid",
       "title": "Endpoint Id"
      }
     }
    ],
    "responses": {
     "204": {
      "description": "Successful Response"
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/webhooks/{endpoint_id}/rotate-secret": {
   "post": {
    "tags": [
     "v1-api",
     "Webhooks"
    ],
    "summary": "Mint a new signing secret in place; preserves delivery history.",
    "description": "Issue a new signing secret for an existing webhook endpoint.\n\nMirrors `POST /keys/{id}/rotate`: row identity (id, url, events,\nis_active, created_at) is preserved; only the secret changes.\n`updated_at` advances. The new plaintext secret is returned in\nfull exactly once \u2014 read it before the response goes out the\ndoor, because subsequent reads omit it.\n\nThe old secret stops working the instant this commits. Tenants\nshould orchestrate the cutover the same way as API keys: deploy\nthe new secret to the receiver before calling this, OR tolerate\na brief window of failed-signature deliveries.\n\nDelivery history (success / failure / retry rows) is unchanged \u2014\nrotation deliberately preserves it so audit trails survive.\n\nInactive endpoints 409 (parallel to API key rotate). Cross-tenant\nids 404. Same scope (`admin`) as the rest of the webhook surface.",
    "operationId": "rotateWebhookSecret",
    "parameters": [
     {
      "name": "endpoint_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid",
       "title": "Endpoint Id"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/WebhookEndpointWithSecret"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/webhooks/deliveries/recent": {
   "get": {
    "tags": [
     "v1-api",
     "Webhooks"
    ],
    "summary": "Aggregate webhook delivery view across all tenant endpoints",
    "description": "Recent delivery attempts across **all** the tenant's webhook endpoints.\n\nPer-endpoint history sits at `/webhooks/{id}/deliveries` \u2014 this is\nthe dashboard view: \"show me what every webhook fired in the last\nN attempts, regardless of which endpoint.\" Sorted newest-first.\nCross-tenant leakage prevented by joining through WebhookEndpoint.\n\n**Pagination.** Two modes:\n\n  - Bare `?limit=N` returns the N newest rows, with\n    `X-Next-Cursor` set when the result fills the page (more\n    rows exist).\n  - Pass `?cursor=<value>` to page strictly past the seed \u2014\n    receives only rows strictly older than the cursor's\n    `created_at` (ties broken by id for determinism). Mirror of\n    the cursor pattern on `/jobs`.",
    "operationId": "listRecentWebhookDeliveries",
    "parameters": [
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "schema": {
       "type": "integer",
       "maximum": 500,
       "minimum": 1,
       "default": 100,
       "title": "Limit"
      }
     },
     {
      "name": "status",
      "in": "query",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "description": "Filter to one of: pending, success, failed.",
       "title": "Status"
      },
      "description": "Filter to one of: pending, success, failed."
     },
     {
      "name": "cursor",
      "in": "query",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "description": "Opaque cursor from a previous response's `X-Next-Cursor` header. When supplied, pages strictly past the seed row using a seek predicate \u2014 stable across new deliveries arriving mid-paginate (offset would skip rows; cursor won't). Format is the prior page's last delivery id.",
       "title": "Cursor"
      },
      "description": "Opaque cursor from a previous response's `X-Next-Cursor` header. When supplied, pages strictly past the seed row using a seek predicate \u2014 stable across new deliveries arriving mid-paginate (offset would skip rows; cursor won't). Format is the prior page's last delivery id."
     }
    ],
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "type": "array",
         "items": {
          "$ref": "#/components/schemas/WebhookDeliverySummary"
         },
         "title": "Response Listrecentwebhookdeliveries"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/webhooks/{endpoint_id}/deliveries": {
   "get": {
    "tags": [
     "v1-api",
     "Webhooks"
    ],
    "summary": "List Webhook Deliveries V1",
    "description": "Audit log of delivery attempts against a webhook endpoint.\n\nUseful for debugging \"why didn't my webhook fire?\" \u2014 surfaces the\nHTTP status the receiver returned, retry counts, and the next retry\ntime on failed rows. Sorted newest-first.",
    "operationId": "listWebhookDeliveries",
    "parameters": [
     {
      "name": "endpoint_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid",
       "title": "Endpoint Id"
      }
     },
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "schema": {
       "type": "integer",
       "maximum": 500,
       "minimum": 1,
       "default": 50,
       "title": "Limit"
      }
     },
     {
      "name": "status",
      "in": "query",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "description": "Filter to one of: pending, success, failed.",
       "title": "Status"
      },
      "description": "Filter to one of: pending, success, failed."
     }
    ],
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "type": "array",
         "items": {
          "$ref": "#/components/schemas/WebhookDeliverySummary"
         },
         "title": "Response Listwebhookdeliveries"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/quota": {
   "get": {
    "tags": [
     "v1-api",
     "Usage"
    ],
    "summary": "Get Quota V1",
    "description": "Pre-flight quota check.\n\nCheaper than `/usage` when all you need to know is \"can I send another\nbatch right now?\" \u2014 skips the lifetime aggregation across UsageRecord\nand the by-status job count.",
    "operationId": "getTenantQuota",
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/QuotaResponse"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/billing/projection": {
   "get": {
    "tags": [
     "v1-api",
     "Usage"
    ],
    "summary": "Get Billing Projection V1",
    "description": "Linear projection of end-of-period spend given current burn rate.\n\nLets tenants spot a runaway month early \u2014 \"we're 3 days in and the\nprojection says we'll hit $850 by month-end, time to investigate.\"\nNaive: just extrapolates the average daily cost. Doesn't model\nweekends, demand spikes, or seasonal patterns.",
    "operationId": "getBillingProjection",
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/BillingProjectionResponse"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/usage": {
   "get": {
    "tags": [
     "v1-api",
     "Usage"
    ],
    "summary": "Get Usage V1",
    "description": "Tenant-scoped usage rollup.\n\nReturns lifetime totals (tokens, cost, job count), the by-status job\nbreakdown, and current billing-period spend + quota state. Useful for\ndashboards and pre-flight checks before queueing a large batch.",
    "operationId": "getTenantUsage",
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/app__api__routes__v1__trigger__UsageResponse"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/usage/trend": {
   "get": {
    "tags": [
     "v1-api",
     "Usage"
    ],
    "summary": "Get Usage Trend V1",
    "description": "Daily cost / token / job-count trend.\n\nReturns a zero-filled per-day rollup so dashboards can render a\nsparkline without client-side gap-filling. Always uses UTC calendar\ndays; same-day usage records are aggregated regardless of when in\nthe day they landed.",
    "operationId": "getUsageTrend",
    "parameters": [
     {
      "name": "period",
      "in": "query",
      "required": false,
      "schema": {
       "enum": [
        "7d",
        "30d",
        "90d"
       ],
       "type": "string",
       "description": "Window length. One of 7d / 30d / 90d.",
       "default": "7d",
       "title": "Period"
      },
      "description": "Window length. One of 7d / 30d / 90d."
     }
    ],
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/UsageTrendResponse"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/usage/by-template": {
   "get": {
    "tags": [
     "v1-api",
     "Usage"
    ],
    "summary": "Get Usage By Template V1",
    "description": "Cost / token / job-count rollup grouped by `agent_type`.\n\nJoins UsageRecord against Job to pick up the template name. Sorted\nby cost descending so the biggest line items surface first.",
    "operationId": "getUsageByTemplate",
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/UsageByTemplateResponse"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/usage/by-tool": {
   "get": {
    "tags": [
     "v1-api",
     "Usage"
    ],
    "summary": "Get Usage By Tool V1",
    "description": "Tool-level work breakdown across the tenant's jobs.\n\nJoins ToolExecution \u2192 Job to scope by tenant; aggregates call count,\ntotal + average duration, and a heuristic error count per tool name.\nUseful for spotting whether a slow rollout is \"computer is slow\" vs.\n\"we issue 10x as many bash calls as we used to.\"",
    "operationId": "getUsageByTool",
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/UsageByToolResponse"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/jobs/in-flight": {
   "get": {
    "tags": [
     "v1-api",
     "Jobs"
    ],
    "summary": "Convenience: just queued / running / awaiting_approval jobs",
    "description": "Return the tenant's currently-live jobs in one call.\n\nEquivalent to repeatedly hitting `/jobs?status=queued`,\n`/jobs?status=running`, `/jobs?status=awaiting_approval` and\nconcatenating \u2014 but in one round trip. Sorted oldest-first so a\ndashboard naturally renders work in the order it was queued.\n\nNo pagination because in-flight count is bounded by infrastructure\n(a tenant can't have 10k jobs running simultaneously).",
    "operationId": "listInFlightJobs",
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "items": {
          "$ref": "#/components/schemas/JobStatusResponse"
         },
         "type": "array",
         "title": "Response Listinflightjobs"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/system/health-detail": {
   "get": {
    "tags": [
     "v1-api",
     "Health"
    ],
    "summary": "System Health Detail V1",
    "description": "Extended operational health beyond the basic liveness ping.\n\nTenant-scoped: the failure-rate signal reflects this tenant's jobs\nonly, not the whole platform. Useful for dashboards that want a\none-stop \"is my integration healthy right now?\" panel.",
    "operationId": "getSystemHealthDetail",
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HealthDetailResponse"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/jobs/diff": {
   "get": {
    "tags": [
     "v1-api",
     "Jobs"
    ],
    "summary": "Side-by-side comparison of two of the tenant's jobs",
    "description": "Compare two jobs side-by-side.\n\nUseful for \"did changing the model improve cost?\" or \"which run\nsucceeded \u2014 the original or the duplicate?\". Surfaces the two jobs'\nfull status snapshots plus a `deltas` dict highlighting the fields\nthat actually differ. Both jobs must belong to the calling tenant.",
    "operationId": "diffJobs",
    "parameters": [
     {
      "name": "a",
      "in": "query",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid",
       "description": "UUID of the first job.",
       "title": "A"
      },
      "description": "UUID of the first job."
     },
     {
      "name": "b",
      "in": "query",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid",
       "description": "UUID of the second job.",
       "title": "B"
      },
      "description": "UUID of the second job."
     }
    ],
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/JobDiffResponse"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/jobs/stats": {
   "get": {
    "tags": [
     "v1-api",
     "Jobs"
    ],
    "summary": "Get Job Stats V1",
    "description": "Quick aggregate snapshot across three rolling windows.\n\nUseful for tenant operational dashboards \u2014 answers \"how am I doing\ntoday / this week / this month\" in one round trip. Computed in\nPython over a single query per window so the SQL stays portable\nacross SQLite + Postgres.\n\n`in_flight` is the live count regardless of window (live jobs don't\nhave a `created_at` filter applied, since \"in flight\" is a current\nstate, not a historical event).",
    "operationId": "getJobStats",
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/JobStatsResponse"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/tags": {
   "get": {
    "tags": [
     "v1-api",
     "Jobs"
    ],
    "summary": "List Job Tags V1",
    "description": "Distinct tag values + counts across the tenant's jobs.\n\nPairs with the `?tag=` filter on `GET /jobs` for tag discovery.\nImplementation pulls each tagged job's `params.tags` and aggregates\nin Python \u2014 JSON-stored tags don't have a portable GROUP BY across\nSQLite + Postgres, and tenant volume is bounded.",
    "operationId": "listJobTags",
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/TagListResponse"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/jobs/export": {
   "get": {
    "tags": [
     "v1-api",
     "Jobs"
    ],
    "summary": "Export jobs as CSV or JSONL",
    "description": "Export jobs as CSV or JSONL for compliance / migration.\n\nStreams up to 10k rows per call. For larger volumes, paginate via\n`since`/`until` windows and stitch on the client side. CSV is RFC\n4180-compliant (quoted fields, `\\r\\n` line endings); JSONL is\none JSON object per line.\n\nColumns / fields: `id`, `template`, `status`, `summary`, `error`,\n`input_tokens`, `output_tokens`, `cost_usd`, `created_at`,\n`updated_at`, `tags` (semicolon-joined in CSV).",
    "operationId": "exportJobs",
    "parameters": [
     {
      "name": "format",
      "in": "query",
      "required": false,
      "schema": {
       "enum": [
        "csv",
        "jsonl"
       ],
       "type": "string",
       "description": "Output format. `csv` (default) or `jsonl`.",
       "default": "csv",
       "title": "Format"
      },
      "description": "Output format. `csv` (default) or `jsonl`."
     },
     {
      "name": "status",
      "in": "query",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "description": "Filter to a single status; mirrors `/jobs?status=`.",
       "title": "Status"
      },
      "description": "Filter to a single status; mirrors `/jobs?status=`."
     },
     {
      "name": "template",
      "in": "query",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "description": "Filter to a single agent_type.",
       "title": "Template"
      },
      "description": "Filter to a single agent_type."
     },
     {
      "name": "since",
      "in": "query",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "description": "ISO 8601 lower bound on `created_at`; rows older are excluded.",
       "title": "Since"
      },
      "description": "ISO 8601 lower bound on `created_at`; rows older are excluded."
     },
     {
      "name": "until",
      "in": "query",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "description": "ISO 8601 upper bound on `created_at`; rows newer are excluded.",
       "title": "Until"
      },
      "description": "ISO 8601 upper bound on `created_at`; rows newer are excluded."
     },
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "schema": {
       "type": "integer",
       "maximum": 10000,
       "minimum": 1,
       "description": "Hard cap on rows returned. Max 10000.",
       "default": 10000,
       "title": "Limit"
      },
      "description": "Hard cap on rows returned. Max 10000."
     }
    ],
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {}
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/jobs": {
   "get": {
    "tags": [
     "v1-api",
     "Jobs"
    ],
    "summary": "List Jobs V1",
    "description": "List jobs for the authenticated tenant.\n\nMirrors the dashboard's `/api/jobs/` filters + cursor pagination so v1\ncallers can enumerate their own runs without remembering every job id.",
    "operationId": "listJobs",
    "parameters": [
     {
      "name": "status",
      "in": "query",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "description": "Filter to a single status: queued, running, succeeded, failed, cancelled, awaiting_approval",
       "title": "Status"
      },
      "description": "Filter to a single status: queued, running, succeeded, failed, cancelled, awaiting_approval"
     },
     {
      "name": "template",
      "in": "query",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "description": "Filter to a specific agent_type / template name",
       "title": "Template"
      },
      "description": "Filter to a specific agent_type / template name"
     },
     {
      "name": "search",
      "in": "query",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "description": "Substring match against job id or summary",
       "title": "Search"
      },
      "description": "Substring match against job id or summary"
     },
     {
      "name": "tag",
      "in": "query",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "type": "array",
         "items": {
          "type": "string"
         }
        },
        {
         "type": "null"
        }
       ],
       "description": "Filter to jobs that carry every supplied tag (AND-match). Repeat the parameter to require multiple tags: `?tag=env:prod&tag=owner:billing-team`.",
       "title": "Tag"
      },
      "description": "Filter to jobs that carry every supplied tag (AND-match). Repeat the parameter to require multiple tags: `?tag=env:prod&tag=owner:billing-team`."
     },
     {
      "name": "sort",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string",
       "description": "field:dir \u2014 field is one of created_at|updated_at|status|template|cost_usd; dir is asc|desc",
       "default": "created_at:desc",
       "title": "Sort"
      },
      "description": "field:dir \u2014 field is one of created_at|updated_at|status|template|cost_usd; dir is asc|desc"
     },
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "schema": {
       "type": "integer",
       "maximum": 500,
       "minimum": 1,
       "default": 50,
       "title": "Limit"
      }
     },
     {
      "name": "offset",
      "in": "query",
      "required": false,
      "schema": {
       "type": "integer",
       "minimum": 0,
       "default": 0,
       "title": "Offset"
      }
     },
     {
      "name": "cursor",
      "in": "query",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "description": "Opaque cursor from a previous response's X-Next-Cursor header. When set, supersedes `offset` and pages strictly past the seed row using a seek predicate. Only valid for sort=created_at.",
       "title": "Cursor"
      },
      "description": "Opaque cursor from a previous response's X-Next-Cursor header. When set, supersedes `offset` and pages strictly past the seed row using a seek predicate. Only valid for sort=created_at."
     }
    ],
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "type": "array",
         "items": {
          "$ref": "#/components/schemas/JobStatusResponse"
         },
         "title": "Response Listjobs"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/jobs/{job_id}": {
   "get": {
    "tags": [
     "v1-api",
     "Jobs"
    ],
    "summary": "Get Job Status",
    "description": "Poll job status, with conditional-GET (ETag / If-None-Match) support.\n\nPolling clients can pass back the previous response's `ETag` value as\n`If-None-Match`; an unchanged job returns 304 Not Modified with no\nbody. Saves bytes and downstream JSON parse cost on every tick.",
    "operationId": "getJob",
    "parameters": [
     {
      "name": "job_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid",
       "title": "Job Id"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/JobStatusResponse"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/jobs/{job_id}/artifacts": {
   "get": {
    "tags": [
     "v1-api",
     "Jobs"
    ],
    "summary": "Get Job Artifacts",
    "description": "Get artifacts produced by a job.",
    "operationId": "listJobArtifacts",
    "parameters": [
     {
      "name": "job_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid",
       "title": "Job Id"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "type": "array",
         "items": {
          "$ref": "#/components/schemas/ArtifactResponse"
         },
         "title": "Response Listjobartifacts"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/jobs/{job_id}/result": {
   "get": {
    "tags": [
     "v1-api",
     "Jobs"
    ],
    "summary": "Get Job Result",
    "description": "Get structured result for a completed job.",
    "operationId": "getJobResult",
    "parameters": [
     {
      "name": "job_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid",
       "title": "Job Id"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/JobResultResponse"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/jobs/{job_id}/cost-breakdown": {
   "get": {
    "tags": [
     "v1-api",
     "Jobs"
    ],
    "summary": "Get Job Cost Breakdown V1",
    "description": "Per-job cost breakdown with priced input/output token lines.\n\nUseful when callers see an unexpectedly high `cost_usd` and want to\nknow whether output tokens or input tokens drove it. Pricing comes\nfrom the worker's canonical rate table; jobs that ran without a\npinned model show prices at the deployment-default rate.",
    "operationId": "getJobCostBreakdown",
    "parameters": [
     {
      "name": "job_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid",
       "title": "Job Id"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/CostBreakdownResponse"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/jobs/{job_id}/replay": {
   "get": {
    "tags": [
     "v1-api",
     "Replay"
    ],
    "summary": "Get Job Replay",
    "description": "Ordered tool-execution timeline for a job.\n\nSame shape as the dashboard's `/api/jobs/{id}/replay`, returned as a\nplain JSON array so callers can drive their own debugging UI without\nfetching the full Markdown transcript first.\n\n`tool_output` is truncated to 2000 chars per row to keep responses\nbounded; full output is available via `/jobs/{id}/transcript`.",
    "operationId": "getJobReplay",
    "parameters": [
     {
      "name": "job_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid",
       "title": "Job Id"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "type": "array",
         "items": {
          "$ref": "#/components/schemas/app__api__routes__v1__trigger__ToolExecutionResponse"
         },
         "title": "Response Getjobreplay"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/jobs/{job_id}/replay/{exec_id}/screenshot": {
   "get": {
    "tags": [
     "v1-api",
     "Replay"
    ],
    "summary": "Get Job Replay Screenshot",
    "description": "Presigned URL for a single replay step's screenshot.\n\nURL expires in 300s. Tenants should fetch immediately or refresh by\nre-calling this endpoint \u2014 the URL is not stable across calls.",
    "operationId": "getJobReplayScreenshot",
    "parameters": [
     {
      "name": "job_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid",
       "title": "Job Id"
      }
     },
     {
      "name": "exec_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid",
       "title": "Exec Id"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ScreenshotUrlResponse"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/jobs/{job_id}/messages": {
   "get": {
    "tags": [
     "v1-api",
     "Jobs"
    ],
    "summary": "Raw conversation messages from the agent's checkpoint",
    "description": "Raw conversation messages for a job.\n\nCloses the last reproducibility gap in the v1 API: every other\nartifact is exposed (transcript, replay, screenshots) but the actual\nBetaMessageParam list \u2014 what the agent saw \u2014 was previously\nJWT-only. Useful for \"feed this past run into a follow-up agent\",\nfull-fidelity audit, and debugging across model versions.\n\nReturns an empty list for jobs that never wrote a checkpoint (e.g.\nNSR runs that don't persist conversation state). Tenant-scoped via\nthe parent Job's tenant_id.",
    "operationId": "getJobMessages",
    "parameters": [
     {
      "name": "job_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid",
       "title": "Job Id"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/JobMessagesResponse"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/jobs/{job_id}/transcript": {
   "get": {
    "tags": [
     "v1-api",
     "Jobs"
    ],
    "summary": "Get Job Transcript",
    "description": "Markdown transcript of a single job \u2014 parity with the JWT API.\n\nIncludes job metadata, instruction, summary, error (if any), and the\nfull tool-call timeline with inputs/outputs and screenshot keys.\nUseful for archiving runs or feeding past job context back into a\nfollow-up agent invocation.",
    "operationId": "getJobTranscript",
    "parameters": [
     {
      "name": "job_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid",
       "title": "Job Id"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {}
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/jobs/{job_id}/extend-budget": {
   "post": {
    "tags": [
     "v1-api",
     "Jobs"
    ],
    "summary": "Extend Job Budget V1",
    "description": "Raise `max_cost_usd` on a live job at runtime.\n\nTenants reach for this when a job is mid-flight and approaching its\noriginal cap \u2014 they'd rather pay another dollar than have it\ncancel + lose progress. The new cap is written to `params.max_cost_usd`\nand observed by the worker on its next iteration's cost-cap check.\n\nOnly **live** jobs (queued / running / awaiting_approval) can be\nextended \u2014 terminal jobs return 409. Strictly raise-only: the\nrequested cap must be greater than the current one.",
    "operationId": "extendJobBudget",
    "parameters": [
     {
      "name": "job_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid",
       "title": "Job Id"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ExtendBudgetRequest"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ExtendBudgetResponse"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/jobs/multi-tag": {
   "post": {
    "tags": [
     "v1-api",
     "Jobs"
    ],
    "summary": "Multi Tag Jobs V1",
    "description": "Apply tag updates to up to 50 jobs in one transaction.\n\nTwo modes \u2014 `merge` adds the new tags to whatever's there; `replace`\noverwrites the entire tag set. Per-row outcomes: cross-tenant /\nunknown ids surface as failures without aborting the batch. Single\ncommit at the end so a partial failure leaves the DB consistent.",
    "operationId": "multiTagJobs",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/MultiTagRequest"
       }
      }
     },
     "required": true
    },
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/MultiTagResponse"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/jobs/{job_id}/tags": {
   "patch": {
    "tags": [
     "v1-api",
     "Jobs"
    ],
    "summary": "Update Job Tags V1",
    "description": "Replace the tags on an existing job.\n\nTag values follow the same rules as `TriggerRequest.tags` (\u226420\nentries \u00d7 \u226464 chars, alphanumeric + `_-:`, deduped). Pass `tags: []`\nto clear them entirely. The rest of `params` is preserved.",
    "operationId": "updateJobTags",
    "parameters": [
     {
      "name": "job_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid",
       "title": "Job Id"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/UpdateJobTagsRequest"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/JobTagsResponse"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/jobs/{job_id}/replay-webhook": {
   "post": {
    "tags": [
     "v1-api",
     "Jobs"
    ],
    "summary": "Replay Job Webhook V1",
    "description": "Re-fire the terminal webhook event for an already-finished job.\n\nUseful when the receiver was down during the original event. Only\nworks on jobs in a terminal status (`succeeded` or `failed`) \u2014 live\njobs return 409 because firing twice would confuse downstream\nstate machines that key on `job.completed`.\n\nBoth registered tenant `WebhookEndpoint` rows and ad-hoc per-job\n`webhook_url` deliveries are re-attempted using the same payload\nshape as the original.",
    "operationId": "replayJobWebhook",
    "parameters": [
     {
      "name": "job_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid",
       "title": "Job Id"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ReplayWebhookResponse"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/jobs/{job_id}/cancel": {
   "post": {
    "tags": [
     "v1-api",
     "Jobs"
    ],
    "summary": "Cancel Job V1",
    "description": "Cancel a queued or running job.\n\nMirrors the JWT-API behavior: sets the Redis cancel sentinel before\nflipping the DB row, so even an in-flight worker observes the signal\non its next iteration checkpoint and stops billing tokens.\n\nOptional body `{\"reason\": \"...\"}` is stamped on `job.error` so audit\ntrails show why a cancel happened. Without a body, the default\n`\"Cancelled by user\"` is used (back-compat for clients that POST with\nno payload).",
    "operationId": "cancelJob",
    "parameters": [
     {
      "name": "job_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid",
       "title": "Job Id"
      }
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "anyOf": [
         {
          "$ref": "#/components/schemas/CancelJobRequest"
         },
         {
          "type": "null"
         }
        ],
        "title": "Body"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/JobStatusResponse"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/jobs/cleanup": {
   "post": {
    "tags": [
     "v1-api",
     "Jobs"
    ],
    "summary": "Cleanup Jobs V1",
    "description": "Tenant-managed retention.\n\nPermanently removes terminal-status jobs older than `older_than_days`\n(with their associated UsageRecord and ToolExecution rows via cascade).\nDefault mode is `dry_run=true` so callers can confirm the count\nbefore flipping to a destructive call.\n\nLive jobs (`queued` / `running` / `awaiting_approval`) are never\ndeleted, even if their status appears in the request \u2014 this is a\ndeliberate guardrail against trigger-and-forget tooling.",
    "operationId": "cleanupJobs",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CleanupJobsRequest"
       }
      }
     },
     "required": true
    },
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/CleanupJobsResponse"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/jobs/cancel-by-tag": {
   "post": {
    "tags": [
     "v1-api",
     "Jobs"
    ],
    "summary": "Cancel Jobs By Tag V1",
    "description": "Cancel every live job that matches a tag filter.\n\nAND-match: a job must carry every supplied tag to be cancelled. Only\nqueued / running / awaiting_approval jobs are affected \u2014 terminal\njobs are excluded by the SQL filter, regardless of their tags.\n\nDefault `dry_run=true` so callers always confirm the count before\nissuing a destructive op. Hard cap of 200 cancellations per call to\nkeep the operation bounded; narrow the filter or call repeatedly if\nyou legitimately need more.",
    "operationId": "cancelJobsByTag",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CancelByTagRequest"
       }
      }
     },
     "required": true
    },
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/CancelByTagResponse"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/jobs/cancel-batch": {
   "post": {
    "tags": [
     "v1-api",
     "Jobs"
    ],
    "summary": "Cancel Jobs Batch V1",
    "description": "Cancel up to 50 jobs in one call.\n\nPer-row outcomes \u2014 already-terminal jobs (succeeded/failed/cancelled)\nor unknown ids are reported in their own row without blocking the\nothers. Single Redis sentinel write per cancellable row.",
    "operationId": "cancelJobsBatch",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CancelBatchRequest"
       }
      }
     },
     "required": true
    },
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/CancelBatchResponse"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/jobs/retry-batch": {
   "post": {
    "tags": [
     "v1-api",
     "Jobs"
    ],
    "summary": "Retry Jobs Batch V1",
    "description": "Retry up to 50 failed/cancelled jobs in one call.\n\nPer-item outcomes \u2014 non-retriable jobs (wrong status, cross-tenant,\nunknown id) are reported in their own row without blocking the\nothers. Quota is checked once for the whole batch; if accepting all\nvalid items would push past, the whole batch is rejected (same\ncontract as `/trigger/batch`).\n\nIdempotency is not supported at the batch level \u2014 each row creates a\nfresh retry. To make a retry replay-safe, use `/jobs/{id}/retry`\none-by-one with an `Idempotency-Key`.",
    "operationId": "retryJobsBatch",
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/RetryBatchRequest"
       }
      }
     },
     "required": true
    },
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/RetryBatchResponse"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/jobs/{job_id}/timeline": {
   "get": {
    "tags": [
     "v1-api",
     "Jobs"
    ],
    "summary": "Get Job Timeline V1",
    "description": "Annotated event timeline for a single job.\n\nHigher-level than `/replay`: returns one row per phase\n(job_created, sandbox_ready, each tool call, terminal) with a\none-line summary, ordered chronologically. Useful for dashboards\nthat want to render a job lifecycle without parsing raw tool\ninputs/outputs.",
    "operationId": "getJobTimeline",
    "parameters": [
     {
      "name": "job_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid",
       "title": "Job Id"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/TimelineResponse"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/jobs/{job_id}/clone-to-template": {
   "post": {
    "tags": [
     "v1-api",
     "Jobs"
    ],
    "summary": "Clone Job To Template V1",
    "description": "Promote a job's configuration into a reusable template.\n\nCaptures `params` minus the per-call fields (instruction, idempotency\nkey, etc.) into the new template's `defaults`. Useful workflow:\niterate on a one-off `/trigger` call until it works, then\n`clone-to-template` to make it the team's reusable starting point.\n\nReserved per-call params NOT carried into defaults:\n`instruction` (unless `include_instruction=true`), `tags`,\n`webhook_url`, `webhook_secret`, `output_schema`. Everything else\n(model, effort, max_cost_usd, custom params) is preserved.",
    "operationId": "cloneJobToTemplate",
    "parameters": [
     {
      "name": "job_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid",
       "title": "Job Id"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/CloneJobToTemplateRequest"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/TemplateInfo"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/jobs/{job_id}/duplicate": {
   "post": {
    "tags": [
     "v1-api",
     "Jobs"
    ],
    "summary": "Duplicate Job V1",
    "description": "Clone any job's params + template + agent_mode into a fresh queued run.\n\nDifference from `/replay-as-new` (succeeded only) and `/retry`\n(failed/cancelled only): this works for **any** source status\nincluding `running` and `awaiting_approval`. Useful when you want to\nfork an in-flight run rather than wait for it to terminate, or copy\na config from a long-lived sandbox session into a one-off task.\n\nSource row is never modified; the new job is independent. Quota is\ncharged as a brand-new task.\n\n**Idempotency.** Pass an `Idempotency-Key` header to make the\nduplicate replay-safe: a retried POST returns the original\nduplicate's job id with `Idempotency-Replayed: true` instead of\ncreating another. The key is namespaced per source job so the same\ncaller key can be reused across different sources without collision.",
    "operationId": "duplicateJob",
    "parameters": [
     {
      "name": "job_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid",
       "title": "Job Id"
      }
     },
     {
      "name": "Idempotency-Key",
      "in": "header",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "title": "Idempotency-Key"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/TriggerResponse"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/jobs/{job_id}/replay-as-new": {
   "post": {
    "tags": [
     "v1-api",
     "Jobs"
    ],
    "summary": "Replay Job As New V1",
    "description": "Re-run a *succeeded* job with the same params.\n\nDistinct from `/retry`, which is reserved for failed/cancelled jobs.\nThis is the right call for \"re-fetch this dataset\" / \"regenerate this\nreport\" workflows where the original task was successful but the\noutput is now stale. Quota-checked; original job remains intact.\n\n**Idempotency.** Pass an `Idempotency-Key` header to make the replay\nreplay-safe: a duplicate POST returns the original new-job id with\n`Idempotency-Replayed: true`. Per-source-job key namespace so the\nsame caller key is reusable across different sources.",
    "operationId": "replayJobAsNew",
    "parameters": [
     {
      "name": "job_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid",
       "title": "Job Id"
      }
     },
     {
      "name": "Idempotency-Key",
      "in": "header",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "title": "Idempotency-Key"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/TriggerResponse"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/jobs/{job_id}/retry": {
   "post": {
    "tags": [
     "v1-api",
     "Jobs"
    ],
    "summary": "Retry Job V1",
    "description": "Re-queue a failed or cancelled job with the same params.\n\nCreates a NEW job record (new id, new idempotency key namespace) so\nthe original run remains intact for audit. The retry inherits the\nsource job's `template`, `params`, and `agent_mode`, then enters the\nqueue identically to a `/trigger` call.\n\nOnly `failed` and `cancelled` jobs can be retried; in-flight or\nalready-succeeded jobs return 409.\n\n**Idempotency.** Pass an `Idempotency-Key` header to make the retry\nreplay-safe: a duplicate POST returns the original retry's job id and\nsets `Idempotency-Replayed: true` rather than queueing a second run.\nThe key is namespaced per source job, so the same key is reusable\nacross different source jobs without collision.",
    "operationId": "retryJob",
    "parameters": [
     {
      "name": "job_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid",
       "title": "Job Id"
      }
     },
     {
      "name": "Idempotency-Key",
      "in": "header",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "title": "Idempotency-Key"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/TriggerResponse"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/events/stream": {
   "get": {
    "tags": [
     "v1-api",
     "Jobs"
    ],
    "summary": "Tenant-wide SSE stream of every job's status events",
    "description": "Tenant-wide event stream \u2014 receive status events for every job.\n\nSame SSE shape as `/jobs/{id}/events` but unscoped from a single\njob. Useful for tenant dashboards that want to render an in-flight\npanel without fanning out one connection per job.\n\nEvents are filtered server-side: only events whose `id` belongs to\nthe calling tenant are surfaced. The first lookup for a previously\nunseen job hits the DB; subsequent events for the same job are\nserved from an in-stream cache.\n\nBehaviour:\n- 15s keepalive comments to survive proxies.\n- 30-min lifetime cap; client should reconnect after `event: timeout`.\n- No initial snapshot (the per-tenant set could be huge); use\n  `GET /jobs?status=running` if you need a starting state.",
    "operationId": "streamTenantEvents",
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {}
       }
      }
     }
    }
   }
  },
  "/api/v1/jobs/{job_id}/wait": {
   "post": {
    "tags": [
     "v1-api",
     "Jobs"
    ],
    "summary": "Block until the job reaches terminal status, or until timeout",
    "description": "Synchronously wait for a job to terminate.\n\nUseful for shell scripts and simple HTTP clients that can't consume\nSSE. Returns immediately when the job is already in a terminal\nstatus; otherwise blocks up to `timeout_seconds` (default 30, max\n60) before returning the current state with `is_terminal: false`.\n\nImplementation: server-side polling on a 1-second interval,\nrefreshing the row each tick. Avoids holding an open broker\nsubscription so connection-pool pressure stays bounded \u2014 the\nlong-running idiom is `/events/stream` (SSE) when you need\nintermediate updates rather than just terminal status.",
    "operationId": "waitForJob",
    "parameters": [
     {
      "name": "job_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid",
       "title": "Job Id"
      }
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "anyOf": [
         {
          "$ref": "#/components/schemas/WaitJobRequest"
         },
         {
          "type": "null"
         }
        ],
        "title": "Body"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/WaitJobResponse"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/jobs/{job_id}/events": {
   "get": {
    "tags": [
     "v1-api",
     "Jobs"
    ],
    "summary": "Stream Job Events",
    "description": "Stream Server-Sent Events for a single job.\n\nFilters the global event broker to only events for this job_id and\nonly after confirming the API key's tenant owns the job. Closes the\nstream after a terminal status (succeeded/failed/cancelled) is seen,\nor after the lifetime cap.",
    "operationId": "streamJobEvents",
    "parameters": [
     {
      "name": "job_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid",
       "title": "Job Id"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {}
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/outcomes/stats": {
   "get": {
    "tags": [
     "v1-api"
    ],
    "summary": "Get tenant outcome statistics",
    "description": "Per-SKU rollups for the authenticated tenant over a time window.\n\nPowers the Appendix D.5 5% Dispute-Rate alarm and the Appendix D.6\nquarterly review. Window defaults: last 30 days ending now.",
    "operationId": "getOutcomeStats",
    "parameters": [
     {
      "name": "window_start",
      "in": "query",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "type": "string",
         "format": "date-time"
        },
        {
         "type": "null"
        }
       ],
       "title": "Window Start"
      }
     },
     {
      "name": "window_end",
      "in": "query",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "type": "string",
         "format": "date-time"
        },
        {
         "type": "null"
        }
       ],
       "title": "Window End"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/OutcomeStatsResponse"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/outcomes": {
   "get": {
    "tags": [
     "v1-api"
    ],
    "summary": "List tenant outcomes",
    "description": "List Outcomes for the authenticated tenant.\n\nFilters compose with AND. Default sort: most recently completed first\n(then most recently created for PENDING rows whose completed_at is NULL).",
    "operationId": "listOutcomes",
    "parameters": [
     {
      "name": "type",
      "in": "query",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "enum": [
          "resolved_contact",
          "resolved_return",
          "wismo_resolution",
          "abandoned_cart_recovery",
          "qualified_lead",
          "b2b_reorder",
          "billing_dispute",
          "upsell",
          "pre_purchase_consultation",
          "triage"
         ],
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "title": "Type"
      }
     },
     {
      "name": "status",
      "in": "query",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "enum": [
          "pending",
          "completed",
          "reopened",
          "disputed",
          "confirmed",
          "error",
          "indeterminate"
         ],
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "title": "Status"
      }
     },
     {
      "name": "inquiry_id",
      "in": "query",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "type": "string",
         "maxLength": 160
        },
        {
         "type": "null"
        }
       ],
       "title": "Inquiry Id"
      }
     },
     {
      "name": "completed_after",
      "in": "query",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "type": "string",
         "format": "date-time"
        },
        {
         "type": "null"
        }
       ],
       "title": "Completed After"
      }
     },
     {
      "name": "completed_before",
      "in": "query",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "type": "string",
         "format": "date-time"
        },
        {
         "type": "null"
        }
       ],
       "title": "Completed Before"
      }
     },
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "schema": {
       "type": "integer",
       "maximum": 200,
       "minimum": 1,
       "default": 50,
       "title": "Limit"
      }
     },
     {
      "name": "offset",
      "in": "query",
      "required": false,
      "schema": {
       "type": "integer",
       "minimum": 0,
       "default": 0,
       "title": "Offset"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/OutcomeListResponse"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/outcomes/{outcome_id}": {
   "get": {
    "tags": [
     "v1-api"
    ],
    "summary": "Get one tenant outcome",
    "description": "Fetch a single Outcome by id (tenant-scoped).",
    "operationId": "getOutcome",
    "parameters": [
     {
      "name": "outcome_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid",
       "title": "Outcome Id"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/OutcomeRead"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/outcomes/{outcome_id}/dispute": {
   "post": {
    "tags": [
     "v1-api"
    ],
    "summary": "Dispute an outcome",
    "description": "Flag an Outcome for joint review (Appendix D.2).\n\nIdempotent on the standard Idempotency-Key header \u2014 retried POSTs\nwith the same key return the same dispute row with\n``Idempotency-Replayed: true``.",
    "operationId": "createOutcomeDispute",
    "parameters": [
     {
      "name": "outcome_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid",
       "title": "Outcome Id"
      }
     },
     {
      "name": "Idempotency-Key",
      "in": "header",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "title": "Idempotency-Key"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/OutcomeDisputeCreate"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/OutcomeDisputeRead"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/outcomes/{outcome_id}/disputes": {
   "get": {
    "tags": [
     "v1-api"
    ],
    "summary": "List disputes for an outcome",
    "description": "List all disputes filed against a specific Outcome.",
    "operationId": "listOutcomeDisputes",
    "parameters": [
     {
      "name": "outcome_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid",
       "title": "Outcome Id"
      }
     },
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "schema": {
       "type": "integer",
       "maximum": 200,
       "minimum": 1,
       "default": 50,
       "title": "Limit"
      }
     },
     {
      "name": "offset",
      "in": "query",
      "required": false,
      "schema": {
       "type": "integer",
       "minimum": 0,
       "default": 0,
       "title": "Offset"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/OutcomeDisputeListResponse"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  }
 },
 "components": {
  "schemas": {
   "APIKeySummary": {
    "properties": {
     "id": {
      "type": "string",
      "title": "Id"
     },
     "name": {
      "type": "string",
      "title": "Name"
     },
     "key_prefix": {
      "type": "string",
      "title": "Key Prefix",
      "description": "First 12 chars of the key (e.g. 'sk_ss_aBc12')."
     },
     "scopes": {
      "items": {
       "type": "string"
      },
      "type": "array",
      "title": "Scopes"
     },
     "rate_limit_per_minute": {
      "type": "integer",
      "title": "Rate Limit Per Minute"
     },
     "is_active": {
      "type": "boolean",
      "title": "Is Active"
     },
     "last_used_at": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Last Used At"
     },
     "expires_at": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Expires At"
     },
     "created_at": {
      "type": "string",
      "title": "Created At"
     },
     "is_current": {
      "type": "boolean",
      "title": "Is Current",
      "description": "True for the key making this request (callers can self-identify).",
      "default": false
     }
    },
    "type": "object",
    "required": [
     "id",
     "name",
     "key_prefix",
     "scopes",
     "rate_limit_per_minute",
     "is_active",
     "created_at"
    ],
    "title": "APIKeySummary",
    "description": "Public-safe metadata about an API key. Does NOT include the key\nitself or its hash \u2014 the prefix (first 12 chars) is the most a caller\never sees after creation."
   },
   "AgentCreate": {
    "properties": {
     "name": {
      "type": "string",
      "title": "Name"
     },
     "description": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Description"
     },
     "system_prompt_extension": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "System Prompt Extension"
     },
     "agent_type": {
      "type": "string",
      "title": "Agent Type",
      "default": "custom"
     },
     "skills": {
      "items": {
       "type": "string"
      },
      "type": "array",
      "title": "Skills",
      "default": []
     },
     "tool_permissions": {
      "items": {
       "type": "string"
      },
      "type": "array",
      "title": "Tool Permissions",
      "default": []
     },
     "default_params": {
      "additionalProperties": true,
      "type": "object",
      "title": "Default Params",
      "default": {}
     },
     "trigger_config": {
      "additionalProperties": true,
      "type": "object",
      "title": "Trigger Config",
      "default": {}
     }
    },
    "type": "object",
    "required": [
     "name"
    ],
    "title": "AgentCreate"
   },
   "AgentResponse": {
    "properties": {
     "id": {
      "type": "string",
      "title": "Id"
     },
     "name": {
      "type": "string",
      "title": "Name"
     },
     "description": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Description"
     },
     "system_prompt_extension": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "System Prompt Extension"
     },
     "agent_type": {
      "type": "string",
      "title": "Agent Type"
     },
     "skills": {
      "items": {
       "type": "string"
      },
      "type": "array",
      "title": "Skills"
     },
     "tool_permissions": {
      "items": {
       "type": "string"
      },
      "type": "array",
      "title": "Tool Permissions"
     },
     "default_params": {
      "additionalProperties": true,
      "type": "object",
      "title": "Default Params"
     },
     "trigger_config": {
      "additionalProperties": true,
      "type": "object",
      "title": "Trigger Config"
     },
     "is_active": {
      "type": "boolean",
      "title": "Is Active"
     },
     "is_sandbox": {
      "type": "boolean",
      "title": "Is Sandbox"
     },
     "created_at": {
      "type": "string",
      "title": "Created At"
     }
    },
    "type": "object",
    "required": [
     "id",
     "name",
     "description",
     "system_prompt_extension",
     "agent_type",
     "skills",
     "tool_permissions",
     "default_params",
     "trigger_config",
     "is_active",
     "is_sandbox",
     "created_at"
    ],
    "title": "AgentResponse"
   },
   "AgentRunResponse": {
    "properties": {
     "id": {
      "type": "string",
      "title": "Id"
     },
     "job_id": {
      "type": "string",
      "format": "uuid",
      "title": "Job Id"
     },
     "trigger_source": {
      "type": "string",
      "title": "Trigger Source"
     },
     "created_at": {
      "type": "string",
      "title": "Created At"
     }
    },
    "type": "object",
    "required": [
     "id",
     "job_id",
     "trigger_source",
     "created_at"
    ],
    "title": "AgentRunResponse"
   },
   "AgentSkillAssignment": {
    "properties": {
     "agent_key": {
      "type": "string",
      "maxLength": 64,
      "title": "Agent Key"
     },
     "priority": {
      "type": "integer",
      "maximum": 1000.0,
      "minimum": 0.0,
      "title": "Priority",
      "default": 100
     }
    },
    "type": "object",
    "required": [
     "agent_key"
    ],
    "title": "AgentSkillAssignment"
   },
   "AgentSkillAssignments": {
    "properties": {
     "assignments": {
      "items": {
       "$ref": "#/components/schemas/AgentSkillAssignment"
      },
      "type": "array",
      "title": "Assignments"
     }
    },
    "type": "object",
    "required": [
     "assignments"
    ],
    "title": "AgentSkillAssignments"
   },
   "AgentUpdate": {
    "properties": {
     "name": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Name"
     },
     "description": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Description"
     },
     "system_prompt_extension": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "System Prompt Extension"
     },
     "skills": {
      "anyOf": [
       {
        "items": {
         "type": "string"
        },
        "type": "array"
       },
       {
        "type": "null"
       }
      ],
      "title": "Skills"
     },
     "tool_permissions": {
      "anyOf": [
       {
        "items": {
         "type": "string"
        },
        "type": "array"
       },
       {
        "type": "null"
       }
      ],
      "title": "Tool Permissions"
     },
     "default_params": {
      "anyOf": [
       {
        "additionalProperties": true,
        "type": "object"
       },
       {
        "type": "null"
       }
      ],
      "title": "Default Params"
     },
     "trigger_config": {
      "anyOf": [
       {
        "additionalProperties": true,
        "type": "object"
       },
       {
        "type": "null"
       }
      ],
      "title": "Trigger Config"
     },
     "is_active": {
      "anyOf": [
       {
        "type": "boolean"
       },
       {
        "type": "null"
       }
      ],
      "title": "Is Active"
     }
    },
    "type": "object",
    "title": "AgentUpdate"
   },
   "AnthropicKeyStatus": {
    "properties": {
     "configured": {
      "type": "boolean",
      "title": "Configured"
     },
     "hint": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Hint"
     },
     "created_at": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Created At"
     },
     "updated_at": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Updated At"
     },
     "notes": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Notes"
     }
    },
    "type": "object",
    "required": [
     "configured"
    ],
    "title": "AnthropicKeyStatus",
    "description": "Response shape for GET /billing/anthropic-key.\n\nIntentionally narrow \u2014 only the hint + audit timestamps cross the\nAPI boundary. The raw key never appears in any response."
   },
   "AnthropicKeyUpdate": {
    "properties": {
     "api_key": {
      "type": "string",
      "title": "Api Key"
     },
     "notes": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Notes"
     }
    },
    "type": "object",
    "required": [
     "api_key"
    ],
    "title": "AnthropicKeyUpdate",
    "description": "Body of PUT /billing/anthropic-key.\n\nThe Anthropic console issues keys with the ``sk-ant-api03-`` prefix.\nWe enforce that prefix so a typo or accidentally-pasted Stripe /\nOpenAI key is rejected at the API edge."
   },
   "ApprovalPolicyRequest": {
    "properties": {
     "name": {
      "type": "string",
      "maxLength": 128,
      "minLength": 1,
      "title": "Name",
      "description": "Human-readable policy name (\u2264128 chars). Used in audit logs."
     },
     "tool_patterns": {
      "items": {
       "type": "string"
      },
      "type": "array",
      "maxItems": 100,
      "title": "Tool Patterns",
      "description": "Tool-name patterns that trigger this policy. Glob-style: `computer:*` matches every computer-tool action, `bash:rm *` matches `bash` with `rm`-prefixed input. Each pattern \u2264256 chars."
     },
     "auto_approve_rules": {
      "additionalProperties": true,
      "type": "object",
      "title": "Auto Approve Rules",
      "description": "Optional rules that auto-approve a matching tool call without human review. Free-form dict \u2014 see operator docs for the supported keys (`max_per_hour`, `allow_safe_subset`, etc.)."
     }
    },
    "type": "object",
    "required": [
     "name"
    ],
    "title": "ApprovalPolicyRequest",
    "description": "Body for `POST /api/v1/approval-policies`."
   },
   "ApprovalPolicySummary": {
    "properties": {
     "id": {
      "type": "string",
      "title": "Id"
     },
     "name": {
      "type": "string",
      "title": "Name"
     },
     "tool_patterns": {
      "items": {
       "type": "string"
      },
      "type": "array",
      "title": "Tool Patterns"
     },
     "auto_approve_rules": {
      "additionalProperties": true,
      "type": "object",
      "title": "Auto Approve Rules"
     },
     "is_active": {
      "type": "boolean",
      "title": "Is Active"
     },
     "created_at": {
      "type": "string",
      "title": "Created At"
     },
     "updated_at": {
      "type": "string",
      "title": "Updated At"
     }
    },
    "type": "object",
    "required": [
     "id",
     "name",
     "tool_patterns",
     "auto_approve_rules",
     "is_active",
     "created_at",
     "updated_at"
    ],
    "title": "ApprovalPolicySummary",
    "description": "Returned by every approval-policies endpoint."
   },
   "ApprovalPolicyUpdateRequest": {
    "properties": {
     "name": {
      "anyOf": [
       {
        "type": "string",
        "maxLength": 128,
        "minLength": 1
       },
       {
        "type": "null"
       }
      ],
      "title": "Name"
     },
     "tool_patterns": {
      "anyOf": [
       {
        "items": {
         "type": "string"
        },
        "type": "array",
        "maxItems": 100
       },
       {
        "type": "null"
       }
      ],
      "title": "Tool Patterns"
     },
     "auto_approve_rules": {
      "anyOf": [
       {
        "additionalProperties": true,
        "type": "object"
       },
       {
        "type": "null"
       }
      ],
      "title": "Auto Approve Rules"
     },
     "is_active": {
      "anyOf": [
       {
        "type": "boolean"
       },
       {
        "type": "null"
       }
      ],
      "title": "Is Active"
     }
    },
    "type": "object",
    "title": "ApprovalPolicyUpdateRequest",
    "description": "Body for `PATCH /api/v1/approval-policies/{id}`. All fields optional."
   },
   "ApprovalRequestResponse": {
    "properties": {
     "id": {
      "type": "string",
      "title": "Id"
     },
     "job_id": {
      "type": "string",
      "format": "uuid",
      "title": "Job Id"
     },
     "policy_id": {
      "anyOf": [
       {
        "type": "string",
        "format": "uuid"
       },
       {
        "type": "null"
       }
      ],
      "title": "Policy Id"
     },
     "tool_name": {
      "type": "string",
      "title": "Tool Name"
     },
     "tool_input": {
      "additionalProperties": true,
      "type": "object",
      "title": "Tool Input"
     },
     "screenshot_key": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Screenshot Key"
     },
     "reasoning": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Reasoning"
     },
     "status": {
      "type": "string",
      "title": "Status"
     },
     "reviewed_by": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Reviewed By"
     },
     "review_comment": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Review Comment"
     },
     "expires_at": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Expires At"
     },
     "created_at": {
      "type": "string",
      "title": "Created At"
     }
    },
    "type": "object",
    "required": [
     "id",
     "job_id",
     "policy_id",
     "tool_name",
     "tool_input",
     "screenshot_key",
     "reasoning",
     "status",
     "reviewed_by",
     "review_comment",
     "expires_at",
     "created_at"
    ],
    "title": "ApprovalRequestResponse"
   },
   "ApprovalReviewRequest": {
    "properties": {
     "comment": {
      "anyOf": [
       {
        "type": "string",
        "maxLength": 1000
       },
       {
        "type": "null"
       }
      ],
      "title": "Comment",
      "description": "Free-form review note shown in the audit trail."
     }
    },
    "type": "object",
    "title": "ApprovalReviewRequest",
    "description": "Body for approve/reject \u2014 comment is optional but recommended."
   },
   "ApprovalSummary": {
    "properties": {
     "id": {
      "type": "string",
      "title": "Id"
     },
     "job_id": {
      "type": "string",
      "title": "Job Id"
     },
     "tool_name": {
      "type": "string",
      "title": "Tool Name"
     },
     "tool_input": {
      "additionalProperties": true,
      "type": "object",
      "title": "Tool Input"
     },
     "reasoning": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Reasoning"
     },
     "screenshot_key": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Screenshot Key"
     },
     "status": {
      "type": "string",
      "title": "Status"
     },
     "review_comment": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Review Comment"
     },
     "expires_at": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Expires At"
     },
     "created_at": {
      "type": "string",
      "title": "Created At"
     },
     "updated_at": {
      "type": "string",
      "title": "Updated At"
     }
    },
    "type": "object",
    "required": [
     "id",
     "job_id",
     "tool_name",
     "tool_input",
     "reasoning",
     "screenshot_key",
     "status",
     "review_comment",
     "expires_at",
     "created_at",
     "updated_at"
    ],
    "title": "ApprovalSummary",
    "description": "One pending approval request from a job's `awaiting_approval` state."
   },
   "ArtifactRead": {
    "properties": {
     "id": {
      "type": "string",
      "format": "uuid",
      "title": "Id"
     },
     "job_id": {
      "type": "string",
      "format": "uuid",
      "title": "Job Id"
     },
     "type": {
      "type": "string",
      "title": "Type"
     },
     "storage_key": {
      "type": "string",
      "title": "Storage Key"
     }
    },
    "type": "object",
    "required": [
     "id",
     "job_id",
     "type",
     "storage_key"
    ],
    "title": "ArtifactRead"
   },
   "ArtifactResponse": {
    "properties": {
     "id": {
      "type": "string",
      "title": "Id",
      "description": "Artifact UUID."
     },
     "type": {
      "type": "string",
      "title": "Type",
      "description": "One of: text, image. Indicates content type at storage_key."
     },
     "storage_key": {
      "type": "string",
      "title": "Storage Key",
      "description": "Object-storage key for the artifact."
     },
     "url": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Url",
      "description": "Short-lived presigned download URL when the artifact is downloadable."
     }
    },
    "type": "object",
    "required": [
     "id",
     "type",
     "storage_key"
    ],
    "title": "ArtifactResponse",
    "description": "Pointer to a stored artifact (transcript, screenshot, tool log)."
   },
   "AuthorizeRequest": {
    "properties": {
     "provider": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Provider",
      "description": "OAuth provider: GoogleOAuth, MicrosoftOAuth, GitHubOAuth"
     },
     "organization_id": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Organization Id",
      "description": "WorkOS organization ID for SSO"
     },
     "connection_id": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Connection Id",
      "description": "WorkOS connection ID"
     },
     "login_hint": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Login Hint",
      "description": "Email hint for WorkOS AuthKit"
     },
     "domain_hint": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Domain Hint",
      "description": "Domain hint for WorkOS AuthKit"
     },
     "use_configured_defaults": {
      "type": "boolean",
      "title": "Use Configured Defaults",
      "description": "When false, do not preselect WORKOS_ORGANIZATION_ID / WORKOS_CONNECTION_ID",
      "default": true
     }
    },
    "type": "object",
    "title": "AuthorizeRequest"
   },
   "AuthorizeResponse": {
    "properties": {
     "authorization_url": {
      "type": "string",
      "title": "Authorization Url"
     }
    },
    "type": "object",
    "required": [
     "authorization_url"
    ],
    "title": "AuthorizeResponse"
   },
   "BatchTriggerItemResult": {
    "properties": {
     "index": {
      "type": "integer",
      "title": "Index",
      "description": "0-based index in the input items array."
     },
     "job_id": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Job Id",
      "description": "UUID of the queued job, if accepted."
     },
     "status": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Status",
      "description": "Job status, if accepted ('queued')."
     },
     "error": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Error",
      "description": "Reason this item was rejected, if any."
     }
    },
    "type": "object",
    "required": [
     "index"
    ],
    "title": "BatchTriggerItemResult",
    "description": "Per-row outcome inside a batch response."
   },
   "BatchTriggerRequest": {
    "properties": {
     "items": {
      "items": {
       "$ref": "#/components/schemas/TriggerRequest"
      },
      "type": "array",
      "maxItems": 50,
      "minItems": 1,
      "title": "Items",
      "description": "List of jobs to enqueue (1..50). Each item is validated independently \u2014 bad items are rejected per-row, valid items are still accepted and queued."
     }
    },
    "type": "object",
    "required": [
     "items"
    ],
    "title": "BatchTriggerRequest",
    "description": "Body for `POST /api/v1/trigger/batch`."
   },
   "BatchTriggerResponse": {
    "properties": {
     "accepted": {
      "type": "integer",
      "title": "Accepted",
      "description": "Count of successfully queued jobs."
     },
     "rejected": {
      "type": "integer",
      "title": "Rejected",
      "description": "Count of rejected items."
     },
     "results": {
      "items": {
       "$ref": "#/components/schemas/BatchTriggerItemResult"
      },
      "type": "array",
      "title": "Results",
      "description": "One entry per input item, in original order."
     }
    },
    "type": "object",
    "required": [
     "accepted",
     "rejected",
     "results"
    ],
    "title": "BatchTriggerResponse",
    "description": "Returned by `POST /api/v1/trigger/batch`."
   },
   "BillingProjectionResponse": {
    "properties": {
     "period_start": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Period Start",
      "description": "ISO 8601 of the billing period's start. None when no subscription is on file."
     },
     "period_end": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Period End",
      "description": "ISO 8601 of the billing period's end."
     },
     "days_elapsed": {
      "type": "number",
      "title": "Days Elapsed",
      "description": "Decimal days from period_start to now, capped at the period length."
     },
     "days_remaining": {
      "type": "number",
      "title": "Days Remaining"
     },
     "period_cost_so_far": {
      "type": "number",
      "title": "Period Cost So Far"
     },
     "daily_burn_rate": {
      "type": "number",
      "title": "Daily Burn Rate",
      "description": "period_cost_so_far / max(days_elapsed, 1). USD/day."
     },
     "projected_period_total": {
      "type": "number",
      "title": "Projected Period Total",
      "description": "Linear extrapolation: cost_so_far + (daily_burn_rate \u00d7 days_remaining). Naive \u2014 does not model end-of-month spikes or weekend tapering."
     },
     "projection_basis": {
      "type": "string",
      "enum": [
       "actual",
       "no_subscription",
       "no_window"
      ],
      "title": "Projection Basis",
      "description": "`actual` when we have a real period and at least some elapsed time; `no_subscription` when no subscription row exists; `no_window` when a subscription exists but has no billing_period_start/end (yet to be set by Stripe sync)."
     }
    },
    "type": "object",
    "required": [
     "days_elapsed",
     "days_remaining",
     "period_cost_so_far",
     "daily_burn_rate",
     "projected_period_total",
     "projection_basis"
    ],
    "title": "BillingProjectionResponse",
    "description": "Returned by `GET /api/v1/billing/projection`."
   },
   "BulkDeleteTemplateRow": {
    "properties": {
     "name": {
      "type": "string",
      "title": "Name"
     },
     "deleted": {
      "type": "boolean",
      "title": "Deleted"
     },
     "error": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Error"
     }
    },
    "type": "object",
    "required": [
     "name",
     "deleted"
    ],
    "title": "BulkDeleteTemplateRow"
   },
   "BulkDeleteTemplatesRequest": {
    "properties": {
     "names": {
      "items": {
       "type": "string"
      },
      "type": "array",
      "maxItems": 50,
      "minItems": 1,
      "title": "Names",
      "description": "Template names to delete (1..50). Built-in names are skipped per-row, not rejected."
     }
    },
    "type": "object",
    "required": [
     "names"
    ],
    "title": "BulkDeleteTemplatesRequest",
    "description": "Body for `POST /api/v1/templates/bulk-delete`."
   },
   "BulkDeleteTemplatesResponse": {
    "properties": {
     "deleted": {
      "type": "integer",
      "title": "Deleted"
     },
     "skipped": {
      "type": "integer",
      "title": "Skipped"
     },
     "rows": {
      "items": {
       "$ref": "#/components/schemas/BulkDeleteTemplateRow"
      },
      "type": "array",
      "title": "Rows"
     }
    },
    "type": "object",
    "required": [
     "deleted",
     "skipped",
     "rows"
    ],
    "title": "BulkDeleteTemplatesResponse"
   },
   "BulkRevokeKeyRow": {
    "properties": {
     "key_id": {
      "type": "string",
      "title": "Key Id"
     },
     "revoked": {
      "type": "boolean",
      "title": "Revoked"
     },
     "error": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Error"
     }
    },
    "type": "object",
    "required": [
     "key_id",
     "revoked"
    ],
    "title": "BulkRevokeKeyRow"
   },
   "BulkRevokeKeysRequest": {
    "properties": {
     "key_ids": {
      "items": {
       "type": "string",
       "format": "uuid"
      },
      "type": "array",
      "maxItems": 50,
      "minItems": 1,
      "title": "Key Ids",
      "description": "API key UUIDs to revoke (1..50). The calling key is NEVER auto-revoked \u2014 even if listed, it surfaces as `error: \"cannot revoke the calling key\"`."
     }
    },
    "type": "object",
    "required": [
     "key_ids"
    ],
    "title": "BulkRevokeKeysRequest",
    "description": "Body for `POST /api/v1/keys/bulk-revoke`."
   },
   "BulkRevokeKeysResponse": {
    "properties": {
     "revoked": {
      "type": "integer",
      "title": "Revoked"
     },
     "skipped": {
      "type": "integer",
      "title": "Skipped"
     },
     "rows": {
      "items": {
       "$ref": "#/components/schemas/BulkRevokeKeyRow"
      },
      "type": "array",
      "title": "Rows"
     }
    },
    "type": "object",
    "required": [
     "revoked",
     "skipped",
     "rows"
    ],
    "title": "BulkRevokeKeysResponse"
   },
   "CallbackRequest": {
    "properties": {
     "code": {
      "type": "string",
      "minLength": 1,
      "title": "Code",
      "description": "Authorization code from WorkOS redirect"
     },
     "state": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "State",
      "description": "Signed state from authorize step (validated against cookie)"
     }
    },
    "type": "object",
    "required": [
     "code"
    ],
    "title": "CallbackRequest"
   },
   "CancelBatchItemResult": {
    "properties": {
     "job_id": {
      "type": "string",
      "title": "Job Id"
     },
     "cancelled": {
      "type": "boolean",
      "title": "Cancelled"
     },
     "error": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Error"
     }
    },
    "type": "object",
    "required": [
     "job_id",
     "cancelled"
    ],
    "title": "CancelBatchItemResult",
    "description": "Per-row outcome inside a cancel-batch response."
   },
   "CancelBatchRequest": {
    "properties": {
     "job_ids": {
      "items": {
       "type": "string",
       "format": "uuid"
      },
      "type": "array",
      "maxItems": 50,
      "minItems": 1,
      "title": "Job Ids",
      "description": "List of job UUIDs to cancel (1..50). Already-terminal jobs surface as per-row errors without blocking the rest."
     },
     "reason": {
      "anyOf": [
       {
        "type": "string",
        "maxLength": 500
       },
       {
        "type": "null"
       }
      ],
      "title": "Reason",
      "description": "Optional reason applied to every cancelled row. Stamped on `job.error` like the single-job cancel endpoint."
     }
    },
    "type": "object",
    "required": [
     "job_ids"
    ],
    "title": "CancelBatchRequest",
    "description": "Body for `POST /api/v1/jobs/cancel-batch`."
   },
   "CancelBatchResponse": {
    "properties": {
     "cancelled": {
      "type": "integer",
      "title": "Cancelled"
     },
     "skipped": {
      "type": "integer",
      "title": "Skipped"
     },
     "results": {
      "items": {
       "$ref": "#/components/schemas/CancelBatchItemResult"
      },
      "type": "array",
      "title": "Results"
     }
    },
    "type": "object",
    "required": [
     "cancelled",
     "skipped",
     "results"
    ],
    "title": "CancelBatchResponse",
    "description": "Returned by `POST /api/v1/jobs/cancel-batch`."
   },
   "CancelByTagRequest": {
    "properties": {
     "tags": {
      "items": {
       "type": "string"
      },
      "type": "array",
      "maxItems": 10,
      "minItems": 1,
      "title": "Tags",
      "description": "Tag values to match \u2014 AND-semantics, same as `GET /jobs?tag=`. Up to 10 tags per request."
     },
     "reason": {
      "anyOf": [
       {
        "type": "string",
        "maxLength": 500
       },
       {
        "type": "null"
       }
      ],
      "title": "Reason",
      "description": "Optional reason stamped on every cancelled job."
     },
     "dry_run": {
      "type": "boolean",
      "title": "Dry Run",
      "description": "When true (default), counts what would be cancelled without issuing any cancellations. Always start here; flip to false once the count looks right.",
      "default": true
     }
    },
    "type": "object",
    "required": [
     "tags"
    ],
    "title": "CancelByTagRequest",
    "description": "Body for `POST /api/v1/jobs/cancel-by-tag`."
   },
   "CancelByTagResponse": {
    "properties": {
     "dry_run": {
      "type": "boolean",
      "title": "Dry Run"
     },
     "matched": {
      "type": "integer",
      "title": "Matched"
     },
     "cancelled": {
      "type": "integer",
      "title": "Cancelled"
     },
     "matched_job_ids": {
      "items": {
       "type": "string"
      },
      "type": "array",
      "title": "Matched Job Ids",
      "description": "IDs of every live job that matched the tag filter, regardless of dry_run. Capped at 200 to avoid huge response bodies; if you hit the cap, narrow your tag filter."
     }
    },
    "type": "object",
    "required": [
     "dry_run",
     "matched",
     "cancelled",
     "matched_job_ids"
    ],
    "title": "CancelByTagResponse"
   },
   "CancelJobRequest": {
    "properties": {
     "reason": {
      "anyOf": [
       {
        "type": "string",
        "maxLength": 500
       },
       {
        "type": "null"
       }
      ],
      "title": "Reason",
      "description": "Free-form reason stamped on `job.error` for audit. Cap is 500 chars; over-cap reasons return 422 (no silent truncation). Whitespace-only is normalized to no reason and the default `\"Cancelled by user\"` audit string is used.",
      "examples": [
       "replaced by a fresher run",
       "user clicked Cancel"
      ]
     }
    },
    "type": "object",
    "title": "CancelJobRequest",
    "description": "Optional body for `POST /jobs/{id}/cancel`."
   },
   "ChangelogEntry": {
    "properties": {
     "date": {
      "type": "string",
      "title": "Date",
      "description": "ISO 8601 date (YYYY-MM-DD)."
     },
     "version": {
      "type": "string",
      "title": "Version",
      "description": "Semver-ish version label."
     },
     "summary": {
      "type": "string",
      "title": "Summary",
      "description": "One-line human-readable summary."
     },
     "endpoints": {
      "items": {
       "type": "string"
      },
      "type": "array",
      "title": "Endpoints",
      "description": "Routes added or changed by this entry, formatted as `METHOD /api/v1/path`."
     }
    },
    "type": "object",
    "required": [
     "date",
     "version",
     "summary"
    ],
    "title": "ChangelogEntry",
    "description": "One entry in the v1 API changelog."
   },
   "CheckoutRequest": {
    "properties": {
     "plan": {
      "type": "string",
      "enum": [
       "starter",
       "pro"
      ],
      "title": "Plan"
     },
     "success_url": {
      "type": "string",
      "title": "Success Url",
      "default": ""
     },
     "cancel_url": {
      "type": "string",
      "title": "Cancel Url",
      "default": ""
     },
     "coupon_id": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Coupon Id"
     }
    },
    "type": "object",
    "required": [
     "plan"
    ],
    "title": "CheckoutRequest"
   },
   "CheckoutResponse": {
    "properties": {
     "checkout_url": {
      "type": "string",
      "title": "Checkout Url"
     }
    },
    "type": "object",
    "required": [
     "checkout_url"
    ],
    "title": "CheckoutResponse"
   },
   "CleanupJobsRequest": {
    "properties": {
     "older_than_days": {
      "type": "integer",
      "maximum": 3650.0,
      "minimum": 7.0,
      "title": "Older Than Days",
      "description": "Delete jobs whose `created_at` is older than this many days. Minimum 7 days to prevent accidents \u2014 deletion is permanent and cascades to UsageRecord and ToolExecution rows."
     },
     "statuses": {
      "items": {
       "type": "string"
      },
      "type": "array",
      "title": "Statuses",
      "description": "Only delete jobs in one of these terminal statuses. Live jobs (queued, running, awaiting_approval) are never touched, even if you list them here."
     },
     "dry_run": {
      "type": "boolean",
      "title": "Dry Run",
      "description": "When true (default), counts what would be deleted without deleting anything. Always start here, then re-call with `dry_run=false` once the count looks right.",
      "default": true
     },
     "max_delete": {
      "type": "integer",
      "maximum": 50000.0,
      "minimum": 1.0,
      "title": "Max Delete",
      "description": "Hard cap on rows touched in this call. Lets ops chunk large purges. Default 1000.",
      "default": 1000
     }
    },
    "type": "object",
    "required": [
     "older_than_days"
    ],
    "title": "CleanupJobsRequest",
    "description": "Body for `POST /api/v1/jobs/cleanup`."
   },
   "CleanupJobsResponse": {
    "properties": {
     "dry_run": {
      "type": "boolean",
      "title": "Dry Run"
     },
     "matched": {
      "type": "integer",
      "title": "Matched",
      "description": "Jobs that match the criteria."
     },
     "deleted": {
      "type": "integer",
      "title": "Deleted",
      "description": "Rows actually removed (0 when dry_run=true)."
     },
     "cutoff_at": {
      "type": "string",
      "title": "Cutoff At",
      "description": "Computed `created_at` cutoff, ISO 8601."
     }
    },
    "type": "object",
    "required": [
     "dry_run",
     "matched",
     "deleted",
     "cutoff_at"
    ],
    "title": "CleanupJobsResponse",
    "description": "Returned by `POST /api/v1/jobs/cleanup`."
   },
   "CloneJobToTemplateRequest": {
    "properties": {
     "name": {
      "type": "string",
      "maxLength": 128,
      "minLength": 1,
      "title": "Name",
      "description": "Template name. Same rules as `POST /templates`: alphanumeric + underscore + dash, must not collide with a built-in or an existing tenant template."
     },
     "description": {
      "type": "string",
      "maxLength": 256,
      "minLength": 1,
      "title": "Description",
      "description": "Human-readable purpose; surfaces in `GET /templates`."
     },
     "include_instruction": {
      "type": "boolean",
      "title": "Include Instruction",
      "description": "When true, the source job's `instruction` is captured as a template default. Most callers want false (the instruction is per-call, the template captures the surrounding config).",
      "default": false
     }
    },
    "type": "object",
    "required": [
     "name",
     "description"
    ],
    "title": "CloneJobToTemplateRequest",
    "description": "Body for `POST /api/v1/jobs/{id}/clone-to-template`."
   },
   "ConnectionCreate": {
    "properties": {
     "name": {
      "type": "string",
      "title": "Name"
     },
     "connection_type": {
      "type": "string",
      "title": "Connection Type",
      "default": "saas_admin"
     },
     "domain": {
      "type": "string",
      "title": "Domain"
     },
     "auth_method": {
      "type": "string",
      "title": "Auth Method",
      "default": "live_login_handoff"
     },
     "owner": {
      "type": "string",
      "title": "Owner",
      "default": "Operations"
     },
     "access_policy": {
      "type": "string",
      "title": "Access Policy",
      "default": "approval_required"
     },
     "status": {
      "type": "string",
      "title": "Status",
      "default": "draft"
     },
     "credential_ref": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Credential Ref"
     },
     "metadata": {
      "additionalProperties": true,
      "type": "object",
      "title": "Metadata"
     }
    },
    "type": "object",
    "required": [
     "name",
     "domain"
    ],
    "title": "ConnectionCreate"
   },
   "ConnectionResponse": {
    "properties": {
     "id": {
      "type": "string",
      "title": "Id"
     },
     "name": {
      "type": "string",
      "title": "Name"
     },
     "connection_type": {
      "type": "string",
      "title": "Connection Type"
     },
     "domain": {
      "type": "string",
      "title": "Domain"
     },
     "auth_method": {
      "type": "string",
      "title": "Auth Method"
     },
     "owner": {
      "type": "string",
      "title": "Owner"
     },
     "access_policy": {
      "type": "string",
      "title": "Access Policy"
     },
     "status": {
      "type": "string",
      "title": "Status"
     },
     "credential_ref": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Credential Ref"
     },
     "metadata": {
      "additionalProperties": true,
      "type": "object",
      "title": "Metadata"
     },
     "is_active": {
      "type": "boolean",
      "title": "Is Active"
     },
     "created_at": {
      "type": "string",
      "title": "Created At"
     },
     "updated_at": {
      "type": "string",
      "title": "Updated At"
     }
    },
    "type": "object",
    "required": [
     "id",
     "name",
     "connection_type",
     "domain",
     "auth_method",
     "owner",
     "access_policy",
     "status",
     "credential_ref",
     "metadata",
     "is_active",
     "created_at",
     "updated_at"
    ],
    "title": "ConnectionResponse"
   },
   "ConnectionUpdate": {
    "properties": {
     "name": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Name"
     },
     "connection_type": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Connection Type"
     },
     "domain": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Domain"
     },
     "auth_method": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Auth Method"
     },
     "owner": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Owner"
     },
     "access_policy": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Access Policy"
     },
     "status": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Status"
     },
     "credential_ref": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Credential Ref"
     },
     "metadata": {
      "anyOf": [
       {
        "additionalProperties": true,
        "type": "object"
       },
       {
        "type": "null"
       }
      ],
      "title": "Metadata"
     },
     "is_active": {
      "anyOf": [
       {
        "type": "boolean"
       },
       {
        "type": "null"
       }
      ],
      "title": "Is Active"
     }
    },
    "type": "object",
    "title": "ConnectionUpdate"
   },
   "CostBreakdownLine": {
    "properties": {
     "label": {
      "type": "string",
      "title": "Label",
      "description": "What was billed (e.g. 'input tokens', 'output tokens')."
     },
     "quantity": {
      "type": "integer",
      "title": "Quantity",
      "description": "Token count."
     },
     "rate_per_token": {
      "type": "number",
      "title": "Rate Per Token",
      "description": "USD per token."
     },
     "cost_usd": {
      "type": "number",
      "title": "Cost Usd",
      "description": "quantity \u00d7 rate_per_token, USD."
     }
    },
    "type": "object",
    "required": [
     "label",
     "quantity",
     "rate_per_token",
     "cost_usd"
    ],
    "title": "CostBreakdownLine",
    "description": "One pricing line on a job's spend."
   },
   "CostBreakdownResponse": {
    "properties": {
     "job_id": {
      "type": "string",
      "title": "Job Id"
     },
     "model": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Model",
      "description": "Canonical model id used to price the job. None if the job ran on the deployment default and no per-job model was pinned."
     },
     "lines": {
      "items": {
       "$ref": "#/components/schemas/CostBreakdownLine"
      },
      "type": "array",
      "title": "Lines"
     },
     "total_cost_usd": {
      "type": "number",
      "title": "Total Cost Usd",
      "description": "Sum across lines. May not equal `Job.cost_usd` exactly if the deployment-default pricing differed from the canonical rate table; the response reflects what the priced lines compute to."
     }
    },
    "type": "object",
    "required": [
     "job_id",
     "model",
     "lines",
     "total_cost_usd"
    ],
    "title": "CostBreakdownResponse",
    "description": "Returned by `GET /jobs/{id}/cost-breakdown`."
   },
   "CreateAPIKeyRequest": {
    "properties": {
     "name": {
      "type": "string",
      "maxLength": 128,
      "minLength": 1,
      "title": "Name",
      "description": "Human-readable label, e.g. 'CI bot' or 'Slack integration'."
     },
     "scopes": {
      "items": {
       "type": "string"
      },
      "type": "array",
      "title": "Scopes",
      "description": "Allowed scopes. Empty list = full-access (back-compat). Otherwise must be a subset of: trigger:write, jobs:read, jobs:write, admin."
     },
     "rate_limit_per_minute": {
      "type": "integer",
      "maximum": 10000.0,
      "minimum": 1.0,
      "title": "Rate Limit Per Minute",
      "description": "Per-key request budget. Range 1..10000.",
      "default": 60
     }
    },
    "type": "object",
    "required": [
     "name"
    ],
    "title": "CreateAPIKeyRequest",
    "description": "Body for `POST /api/v1/keys`."
   },
   "CreateAPIKeyResponse": {
    "properties": {
     "id": {
      "type": "string",
      "title": "Id"
     },
     "name": {
      "type": "string",
      "title": "Name"
     },
     "key": {
      "type": "string",
      "title": "Key",
      "description": "Plaintext API key \u2014 store it now. The platform only retains the SHA-256 hash; this is the one and only time the secret is exposed."
     },
     "key_prefix": {
      "type": "string",
      "title": "Key Prefix"
     },
     "scopes": {
      "items": {
       "type": "string"
      },
      "type": "array",
      "title": "Scopes"
     },
     "rate_limit_per_minute": {
      "type": "integer",
      "title": "Rate Limit Per Minute"
     },
     "created_at": {
      "type": "string",
      "title": "Created At"
     }
    },
    "type": "object",
    "required": [
     "id",
     "name",
     "key",
     "key_prefix",
     "scopes",
     "rate_limit_per_minute",
     "created_at"
    ],
    "title": "CreateAPIKeyResponse",
    "description": "Returned by `POST /api/v1/keys` \u2014 the only place the plaintext is shown."
   },
   "CreateEndpointRequest": {
    "properties": {
     "url": {
      "type": "string",
      "title": "Url"
     },
     "events": {
      "items": {
       "type": "string"
      },
      "type": "array",
      "title": "Events",
      "default": [
       "job.completed",
       "job.failed"
      ]
     }
    },
    "type": "object",
    "required": [
     "url"
    ],
    "title": "CreateEndpointRequest"
   },
   "CreateKeyRequest": {
    "properties": {
     "name": {
      "type": "string",
      "title": "Name"
     },
     "scopes": {
      "items": {
       "type": "string"
      },
      "type": "array",
      "title": "Scopes"
     }
    },
    "type": "object",
    "required": [
     "name"
    ],
    "title": "CreateKeyRequest"
   },
   "CreateKeyResponse": {
    "properties": {
     "id": {
      "type": "string",
      "title": "Id"
     },
     "name": {
      "type": "string",
      "title": "Name"
     },
     "key": {
      "type": "string",
      "title": "Key"
     },
     "key_prefix": {
      "type": "string",
      "title": "Key Prefix"
     },
     "scopes": {
      "items": {
       "type": "string"
      },
      "type": "array",
      "title": "Scopes"
     },
     "created_at": {
      "type": "string",
      "title": "Created At"
     }
    },
    "type": "object",
    "required": [
     "id",
     "name",
     "key",
     "key_prefix",
     "scopes",
     "created_at"
    ],
    "title": "CreateKeyResponse"
   },
   "CreateSessionRequest": {
    "properties": {
     "job_id": {
      "type": "integer",
      "title": "Job Id",
      "description": "Associated job ID"
     },
     "agent_name": {
      "type": "string",
      "title": "Agent Name",
      "description": "AGI agent model name",
      "default": "agi-0"
     },
     "task_description": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Task Description",
      "description": "Description of the task"
     }
    },
    "type": "object",
    "required": [
     "job_id"
    ],
    "title": "CreateSessionRequest",
    "description": "Request to create a new AGI session."
   },
   "CreateTemplateRequest": {
    "properties": {
     "name": {
      "type": "string",
      "maxLength": 128,
      "minLength": 1,
      "title": "Name",
      "description": "Template identifier \u2014 passed as `agent_type` on `/trigger`. Alphanumeric + underscore + dash; must not collide with a platform built-in name."
     },
     "description": {
      "type": "string",
      "maxLength": 256,
      "minLength": 1,
      "title": "Description",
      "description": "Human-readable purpose; surfaces in `GET /templates`."
     },
     "defaults": {
      "additionalProperties": true,
      "type": "object",
      "title": "Defaults",
      "description": "Default `params` merged into every trigger that targets this template. The tenant's request payload overrides on key collision."
     }
    },
    "type": "object",
    "required": [
     "name",
     "description"
    ],
    "title": "CreateTemplateRequest",
    "description": "Body for `POST /api/v1/templates`."
   },
   "CreateWebhookEndpointRequest": {
    "properties": {
     "url": {
      "type": "string",
      "title": "Url",
      "description": "Receiver URL. Must start with http:// or https://; \u22642048 chars."
     },
     "events": {
      "items": {
       "type": "string"
      },
      "type": "array",
      "title": "Events",
      "description": "Events to subscribe to. Either explicit names ('job.completed', 'job.failed') or '*' for all."
     }
    },
    "type": "object",
    "required": [
     "url"
    ],
    "title": "CreateWebhookEndpointRequest",
    "description": "Body for `POST /api/v1/webhooks`."
   },
   "CreatedEndpointResponse": {
    "properties": {
     "id": {
      "type": "string",
      "title": "Id"
     },
     "url": {
      "type": "string",
      "title": "Url"
     },
     "events": {
      "items": {
       "type": "string"
      },
      "type": "array",
      "title": "Events"
     },
     "is_active": {
      "type": "boolean",
      "title": "Is Active"
     },
     "created_at": {
      "type": "string",
      "title": "Created At"
     },
     "secret": {
      "type": "string",
      "title": "Secret"
     }
    },
    "type": "object",
    "required": [
     "id",
     "url",
     "events",
     "is_active",
     "created_at",
     "secret"
    ],
    "title": "CreatedEndpointResponse"
   },
   "CustomAgentRequest": {
    "properties": {
     "name": {
      "type": "string",
      "maxLength": 128,
      "minLength": 1,
      "title": "Name",
      "description": "Human-readable agent name (\u2264128 chars)."
     },
     "description": {
      "anyOf": [
       {
        "type": "string",
        "maxLength": 4096
       },
       {
        "type": "null"
       }
      ],
      "title": "Description",
      "description": "Free-form description (\u22644 KB). Surfaces in the dashboard list view."
     },
     "system_prompt_extension": {
      "anyOf": [
       {
        "type": "string",
        "maxLength": 16384
       },
       {
        "type": "null"
       }
      ],
      "title": "System Prompt Extension",
      "description": "Text appended to the platform's default system prompt for this agent's runs (\u226416 KB). Use to give the agent persistent persona or domain-specific instructions."
     },
     "agent_type": {
      "type": "string",
      "maxLength": 64,
      "title": "Agent Type",
      "description": "Tag for this agent's runs; default 'custom'. Free-form.",
      "default": "custom"
     },
     "skills": {
      "items": {
       "type": "string"
      },
      "type": "array",
      "maxItems": 100,
      "title": "Skills",
      "description": "Skill IDs or names to register on each run (\u2264100 entries)."
     },
     "tool_permissions": {
      "items": {
       "type": "string"
      },
      "type": "array",
      "maxItems": 100,
      "title": "Tool Permissions",
      "description": "Allow-list of tool names this agent may use; empty = full default tool set. Useful for sandboxing untrusted prompts."
     },
     "default_params": {
      "additionalProperties": true,
      "type": "object",
      "title": "Default Params",
      "description": "Params merged into every `/trigger` call invoking this agent."
     },
     "trigger_config": {
      "additionalProperties": true,
      "type": "object",
      "title": "Trigger Config",
      "description": "Optional trigger metadata \u2014 e.g. `{type: 'scheduled', cron: '0 9 * * *'}`. Free-form; the worker reads documented keys."
     }
    },
    "type": "object",
    "required": [
     "name"
    ],
    "title": "CustomAgentRequest",
    "description": "Body for `POST /api/v1/custom-agents`."
   },
   "CustomAgentSummary": {
    "properties": {
     "id": {
      "type": "string",
      "title": "Id"
     },
     "name": {
      "type": "string",
      "title": "Name"
     },
     "description": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Description"
     },
     "system_prompt_extension": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "System Prompt Extension"
     },
     "agent_type": {
      "type": "string",
      "title": "Agent Type"
     },
     "skills": {
      "items": {
       "type": "string"
      },
      "type": "array",
      "title": "Skills"
     },
     "tool_permissions": {
      "items": {
       "type": "string"
      },
      "type": "array",
      "title": "Tool Permissions"
     },
     "default_params": {
      "additionalProperties": true,
      "type": "object",
      "title": "Default Params"
     },
     "trigger_config": {
      "additionalProperties": true,
      "type": "object",
      "title": "Trigger Config"
     },
     "is_active": {
      "type": "boolean",
      "title": "Is Active"
     },
     "is_sandbox": {
      "type": "boolean",
      "title": "Is Sandbox"
     },
     "created_at": {
      "type": "string",
      "title": "Created At"
     },
     "updated_at": {
      "type": "string",
      "title": "Updated At"
     }
    },
    "type": "object",
    "required": [
     "id",
     "name",
     "description",
     "system_prompt_extension",
     "agent_type",
     "skills",
     "tool_permissions",
     "default_params",
     "trigger_config",
     "is_active",
     "is_sandbox",
     "created_at",
     "updated_at"
    ],
    "title": "CustomAgentSummary",
    "description": "Returned by every custom-agents endpoint."
   },
   "CustomAgentUpdateRequest": {
    "properties": {
     "name": {
      "anyOf": [
       {
        "type": "string",
        "maxLength": 128,
        "minLength": 1
       },
       {
        "type": "null"
       }
      ],
      "title": "Name"
     },
     "description": {
      "anyOf": [
       {
        "type": "string",
        "maxLength": 4096
       },
       {
        "type": "null"
       }
      ],
      "title": "Description"
     },
     "system_prompt_extension": {
      "anyOf": [
       {
        "type": "string",
        "maxLength": 16384
       },
       {
        "type": "null"
       }
      ],
      "title": "System Prompt Extension"
     },
     "skills": {
      "anyOf": [
       {
        "items": {
         "type": "string"
        },
        "type": "array",
        "maxItems": 100
       },
       {
        "type": "null"
       }
      ],
      "title": "Skills"
     },
     "tool_permissions": {
      "anyOf": [
       {
        "items": {
         "type": "string"
        },
        "type": "array",
        "maxItems": 100
       },
       {
        "type": "null"
       }
      ],
      "title": "Tool Permissions"
     },
     "default_params": {
      "anyOf": [
       {
        "additionalProperties": true,
        "type": "object"
       },
       {
        "type": "null"
       }
      ],
      "title": "Default Params"
     },
     "trigger_config": {
      "anyOf": [
       {
        "additionalProperties": true,
        "type": "object"
       },
       {
        "type": "null"
       }
      ],
      "title": "Trigger Config"
     },
     "is_active": {
      "anyOf": [
       {
        "type": "boolean"
       },
       {
        "type": "null"
       }
      ],
      "title": "Is Active"
     }
    },
    "type": "object",
    "title": "CustomAgentUpdateRequest",
    "description": "Body for `PATCH /api/v1/custom-agents/{id}`. All fields optional."
   },
   "DeliveryResponse": {
    "properties": {
     "id": {
      "type": "string",
      "title": "Id"
     },
     "endpoint_id": {
      "type": "string",
      "format": "uuid",
      "title": "Endpoint Id"
     },
     "event_type": {
      "type": "string",
      "title": "Event Type"
     },
     "status": {
      "type": "string",
      "title": "Status"
     },
     "response_code": {
      "anyOf": [
       {
        "type": "integer"
       },
       {
        "type": "null"
       }
      ],
      "title": "Response Code"
     },
     "attempts": {
      "type": "integer",
      "title": "Attempts"
     },
     "created_at": {
      "type": "string",
      "title": "Created At"
     }
    },
    "type": "object",
    "required": [
     "id",
     "endpoint_id",
     "event_type",
     "status",
     "response_code",
     "attempts",
     "created_at"
    ],
    "title": "DeliveryResponse"
   },
   "DemoArtifactSection": {
    "properties": {
     "heading": {
      "type": "string",
      "title": "Heading"
     },
     "body": {
      "type": "string",
      "title": "Body"
     }
    },
    "type": "object",
    "required": [
     "heading",
     "body"
    ],
    "title": "DemoArtifactSection"
   },
   "DemoMetric": {
    "properties": {
     "label": {
      "type": "string",
      "title": "Label"
     },
     "value": {
      "type": "string",
      "title": "Value"
     },
     "tone": {
      "type": "string",
      "enum": [
       "default",
       "success",
       "warning",
       "info"
      ],
      "title": "Tone",
      "default": "default"
     }
    },
    "type": "object",
    "required": [
     "label",
     "value"
    ],
    "title": "DemoMetric"
   },
   "DemoReplayResponse": {
    "properties": {
     "slug": {
      "type": "string",
      "title": "Slug"
     },
     "title": {
      "type": "string",
      "title": "Title"
     },
     "prompt": {
      "type": "string",
      "title": "Prompt"
     },
     "status": {
      "type": "string",
      "const": "succeeded",
      "title": "Status"
     },
     "sandbox_id": {
      "type": "string",
      "title": "Sandbox Id"
     },
     "model": {
      "type": "string",
      "title": "Model"
     },
     "created_at": {
      "type": "string",
      "title": "Created At"
     },
     "completed_at": {
      "type": "string",
      "title": "Completed At"
     },
     "duration_seconds": {
      "type": "integer",
      "title": "Duration Seconds"
     },
     "cost_usd": {
      "type": "number",
      "title": "Cost Usd"
     },
     "summary": {
      "type": "string",
      "title": "Summary"
     },
     "metrics": {
      "items": {
       "$ref": "#/components/schemas/DemoMetric"
      },
      "type": "array",
      "title": "Metrics"
     },
     "guardrails": {
      "items": {
       "type": "string"
      },
      "type": "array",
      "title": "Guardrails"
     },
     "frames": {
      "items": {
       "$ref": "#/components/schemas/DemoSandboxFrame"
      },
      "type": "array",
      "title": "Frames"
     },
     "timeline": {
      "items": {
       "$ref": "#/components/schemas/DemoToolExecution"
      },
      "type": "array",
      "title": "Timeline"
     },
     "artifact": {
      "items": {
       "$ref": "#/components/schemas/DemoArtifactSection"
      },
      "type": "array",
      "title": "Artifact"
     }
    },
    "type": "object",
    "required": [
     "slug",
     "title",
     "prompt",
     "status",
     "sandbox_id",
     "model",
     "created_at",
     "completed_at",
     "duration_seconds",
     "cost_usd",
     "summary",
     "metrics",
     "guardrails",
     "frames",
     "timeline",
     "artifact"
    ],
    "title": "DemoReplayResponse"
   },
   "DemoSandboxFrame": {
    "properties": {
     "id": {
      "type": "string",
      "title": "Id"
     },
     "title": {
      "type": "string",
      "title": "Title"
     },
     "url": {
      "type": "string",
      "title": "Url"
     },
     "status": {
      "type": "string",
      "title": "Status"
     },
     "highlights": {
      "items": {
       "type": "string"
      },
      "type": "array",
      "title": "Highlights"
     }
    },
    "type": "object",
    "required": [
     "id",
     "title",
     "url",
     "status",
     "highlights"
    ],
    "title": "DemoSandboxFrame"
   },
   "DemoToolExecution": {
    "properties": {
     "id": {
      "type": "string",
      "title": "Id"
     },
     "sequence_number": {
      "type": "integer",
      "title": "Sequence Number"
     },
     "tool_name": {
      "type": "string",
      "title": "Tool Name"
     },
     "tool_input": {
      "additionalProperties": true,
      "type": "object",
      "title": "Tool Input"
     },
     "tool_output": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Tool Output"
     },
     "screenshot_key": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Screenshot Key"
     },
     "thinking_summary": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Thinking Summary"
     },
     "duration_ms": {
      "anyOf": [
       {
        "type": "integer"
       },
       {
        "type": "null"
       }
      ],
      "title": "Duration Ms"
     },
     "created_at": {
      "type": "string",
      "title": "Created At"
     }
    },
    "type": "object",
    "required": [
     "id",
     "sequence_number",
     "tool_name",
     "tool_input",
     "tool_output",
     "screenshot_key",
     "thinking_summary",
     "duration_ms",
     "created_at"
    ],
    "title": "DemoToolExecution"
   },
   "EndpointResponse": {
    "properties": {
     "id": {
      "type": "string",
      "title": "Id"
     },
     "url": {
      "type": "string",
      "title": "Url"
     },
     "events": {
      "items": {
       "type": "string"
      },
      "type": "array",
      "title": "Events"
     },
     "is_active": {
      "type": "boolean",
      "title": "Is Active"
     },
     "created_at": {
      "type": "string",
      "title": "Created At"
     }
    },
    "type": "object",
    "required": [
     "id",
     "url",
     "events",
     "is_active",
     "created_at"
    ],
    "title": "EndpointResponse"
   },
   "EventTypeFilter": {
    "type": "string",
    "enum": [
     "all",
     "task_start",
     "task_end",
     "iteration_start",
     "iteration_end",
     "tool_start",
     "tool_end",
     "api_call",
     "error",
     "metric",
     "health_check",
     "budget_warning",
     "context_compaction"
    ],
    "title": "EventTypeFilter",
    "description": "Event types that can be filtered."
   },
   "ExtendBudgetRequest": {
    "properties": {
     "max_cost_usd": {
      "type": "number",
      "maximum": 1000.0,
      "exclusiveMinimum": 0.0,
      "title": "Max Cost Usd",
      "description": "New cap, USD. Must be strictly higher than the current cap (or set when the job had none). Lowering is rejected with 409 because dropping the cap below the running cost would trip an immediate self-cancellation, which is what tenants are usually trying to avoid by calling this."
     }
    },
    "type": "object",
    "required": [
     "max_cost_usd"
    ],
    "title": "ExtendBudgetRequest",
    "description": "Body for `POST /api/v1/jobs/{id}/extend-budget`."
   },
   "ExtendBudgetResponse": {
    "properties": {
     "job_id": {
      "type": "string",
      "title": "Job Id"
     },
     "previous_max_cost_usd": {
      "anyOf": [
       {
        "type": "number"
       },
       {
        "type": "null"
       }
      ],
      "title": "Previous Max Cost Usd"
     },
     "new_max_cost_usd": {
      "type": "number",
      "title": "New Max Cost Usd"
     },
     "current_cost_usd": {
      "type": "number",
      "title": "Current Cost Usd"
     }
    },
    "type": "object",
    "required": [
     "job_id",
     "previous_max_cost_usd",
     "new_max_cost_usd",
     "current_cost_usd"
    ],
    "title": "ExtendBudgetResponse"
   },
   "HTTPValidationError": {
    "properties": {
     "detail": {
      "items": {
       "$ref": "#/components/schemas/ValidationError"
      },
      "type": "array",
      "title": "Detail"
     }
    },
    "type": "object",
    "title": "HTTPValidationError"
   },
   "HealthDetailResponse": {
    "properties": {
     "status": {
      "type": "string",
      "enum": [
       "ok",
       "degraded",
       "unhealthy"
      ],
      "title": "Status",
      "description": "Aggregate signal: `ok` when nothing's flagged, `degraded` when in-flight count or failure rate crosses warning thresholds, `unhealthy` when the DB itself is unreachable."
     },
     "in_flight_jobs": {
      "type": "integer",
      "title": "In Flight Jobs"
     },
     "failed_last_hour": {
      "type": "integer",
      "title": "Failed Last Hour"
     },
     "succeeded_last_hour": {
      "type": "integer",
      "title": "Succeeded Last Hour"
     },
     "failure_rate_last_hour": {
      "type": "number",
      "title": "Failure Rate Last Hour",
      "description": "failed / (succeeded + failed) over the last hour. 0.0 when no terminal jobs landed in that window \u2014 does not signal health by itself, callers should weigh `total_last_hour` first."
     },
     "total_last_hour": {
      "type": "integer",
      "title": "Total Last Hour"
     },
     "last_used_at": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Last Used At",
      "description": "ISO 8601 of when the calling API key was previously used. Useful for ops dashboards showing key activity timelines."
     },
     "timestamp": {
      "type": "string",
      "title": "Timestamp"
     }
    },
    "type": "object",
    "required": [
     "status",
     "in_flight_jobs",
     "failed_last_hour",
     "succeeded_last_hour",
     "failure_rate_last_hour",
     "total_last_hour",
     "timestamp"
    ],
    "title": "HealthDetailResponse",
    "description": "Returned by `GET /api/v1/system/health-detail`."
   },
   "HealthResponse": {
    "properties": {
     "status": {
      "type": "string",
      "enum": [
       "ok",
       "degraded"
      ],
      "title": "Status"
     },
     "service": {
      "type": "string",
      "title": "Service",
      "description": "Static service identifier."
     },
     "timestamp": {
      "type": "string",
      "title": "Timestamp",
      "description": "ISO 8601 UTC timestamp of the check."
     },
     "checks": {
      "additionalProperties": {
       "type": "string"
      },
      "type": "object",
      "title": "Checks",
      "description": "Per-component check results. Currently only `database`."
     }
    },
    "type": "object",
    "required": [
     "status",
     "service",
     "timestamp",
     "checks"
    ],
    "title": "HealthResponse",
    "description": "Body of `GET /api/v1/health` \u2014 minimal liveness payload.\n\nStatus is `ok` when the DB ping succeeded; `degraded` (alongside HTTP\n503) when it failed. External monitors should treat HTTP status as\nprimary truth and use this body only for human-readable diagnosis."
   },
   "ImportTemplateRow": {
    "properties": {
     "name": {
      "type": "string",
      "title": "Name"
     },
     "action": {
      "type": "string",
      "enum": [
       "created",
       "skipped",
       "replaced",
       "errored"
      ],
      "title": "Action"
     },
     "error": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Error"
     }
    },
    "type": "object",
    "required": [
     "name",
     "action"
    ],
    "title": "ImportTemplateRow"
   },
   "ImportTemplatesRequest": {
    "properties": {
     "templates": {
      "items": {
       "$ref": "#/components/schemas/CreateTemplateRequest"
      },
      "type": "array",
      "maxItems": 50,
      "minItems": 1,
      "title": "Templates",
      "description": "List of templates to import (1..50). Each entry follows the `POST /templates` schema."
     },
     "on_conflict": {
      "type": "string",
      "enum": [
       "skip",
       "replace",
       "error"
      ],
      "title": "On Conflict",
      "description": "What to do when a template name already exists for the tenant: `skip` keeps the existing row and reports it in the response; `replace` overwrites description+defaults; `error` rejects the whole import (no partial writes).",
      "default": "skip"
     }
    },
    "type": "object",
    "required": [
     "templates"
    ],
    "title": "ImportTemplatesRequest",
    "description": "Body for `POST /api/v1/templates/import`."
   },
   "ImportTemplatesResponse": {
    "properties": {
     "created": {
      "type": "integer",
      "title": "Created"
     },
     "skipped": {
      "type": "integer",
      "title": "Skipped"
     },
     "replaced": {
      "type": "integer",
      "title": "Replaced"
     },
     "errored": {
      "type": "integer",
      "title": "Errored"
     },
     "rows": {
      "items": {
       "$ref": "#/components/schemas/ImportTemplateRow"
      },
      "type": "array",
      "title": "Rows"
     }
    },
    "type": "object",
    "required": [
     "created",
     "skipped",
     "replaced",
     "errored",
     "rows"
    ],
    "title": "ImportTemplatesResponse",
    "description": "Returned by `POST /api/v1/templates/import`."
   },
   "InviteRequest": {
    "properties": {
     "email": {
      "type": "string",
      "minLength": 3,
      "title": "Email",
      "description": "Email address to invite"
     },
     "role": {
      "type": "string",
      "title": "Role",
      "description": "Role: owner, admin, or member",
      "default": "member"
     }
    },
    "type": "object",
    "required": [
     "email"
    ],
    "title": "InviteRequest"
   },
   "JobCreate": {
    "properties": {
     "template": {
      "type": "string",
      "title": "Template",
      "description": "Template identifier to run"
     },
     "params": {
      "additionalProperties": true,
      "type": "object",
      "title": "Params",
      "description": "Runtime parameters"
     },
     "agent_mode": {
      "type": "string",
      "enum": [
       "claude",
       "nsr",
       "openai"
      ],
      "title": "Agent Mode",
      "description": "Execution backend: 'claude' (Anthropic LLM), 'openai' (OpenAI GPT-5.6 Sol computer use), or 'nsr' (local neuro-symbolic, zero API tokens).",
      "default": "claude"
     }
    },
    "type": "object",
    "required": [
     "template"
    ],
    "title": "JobCreate"
   },
   "JobDiffResponse": {
    "properties": {
     "a": {
      "$ref": "#/components/schemas/JobDiffSide"
     },
     "b": {
      "$ref": "#/components/schemas/JobDiffSide"
     },
     "deltas": {
      "additionalProperties": {
       "type": "string"
      },
      "type": "object",
      "title": "Deltas",
      "description": "Field-by-field diff summary, e.g. `{'cost_usd': '0.0420 \u2192 0.0085 (-80.95%)'}`. Only fields that actually differ between A and B appear here."
     },
     "same": {
      "items": {
       "type": "string"
      },
      "type": "array",
      "title": "Same",
      "description": "Field names that matched on both sides \u2014 quick visual confirmation."
     }
    },
    "type": "object",
    "required": [
     "a",
     "b",
     "deltas",
     "same"
    ],
    "title": "JobDiffResponse",
    "description": "Returned by `GET /api/v1/jobs/diff?a=...&b=...`."
   },
   "JobDiffSide": {
    "properties": {
     "id": {
      "type": "string",
      "title": "Id"
     },
     "template": {
      "type": "string",
      "title": "Template"
     },
     "status": {
      "type": "string",
      "title": "Status"
     },
     "summary": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Summary"
     },
     "error": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Error"
     },
     "input_tokens": {
      "anyOf": [
       {
        "type": "integer"
       },
       {
        "type": "null"
       }
      ],
      "title": "Input Tokens"
     },
     "output_tokens": {
      "anyOf": [
       {
        "type": "integer"
       },
       {
        "type": "null"
       }
      ],
      "title": "Output Tokens"
     },
     "cost_usd": {
      "anyOf": [
       {
        "type": "number"
       },
       {
        "type": "null"
       }
      ],
      "title": "Cost Usd"
     },
     "duration_seconds": {
      "anyOf": [
       {
        "type": "number"
       },
       {
        "type": "null"
       }
      ],
      "title": "Duration Seconds",
      "description": "updated_at - created_at, in seconds. None when not terminal."
     },
     "model": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Model"
     },
     "effort": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Effort"
     },
     "agent_mode": {
      "type": "string",
      "title": "Agent Mode"
     },
     "tags": {
      "items": {
       "type": "string"
      },
      "type": "array",
      "title": "Tags"
     },
     "instruction_preview": {
      "type": "string",
      "title": "Instruction Preview",
      "description": "First 280 chars of the original instruction."
     }
    },
    "type": "object",
    "required": [
     "id",
     "template",
     "status",
     "agent_mode",
     "instruction_preview"
    ],
    "title": "JobDiffSide",
    "description": "One side of a job-vs-job comparison."
   },
   "JobMessagesResponse": {
    "properties": {
     "job_id": {
      "type": "string",
      "title": "Job Id"
     },
     "messages": {
      "items": {},
      "type": "array",
      "title": "Messages",
      "description": "Raw conversation messages exactly as they sit in the agent's checkpoint \u2014 same shape as Anthropic's BetaMessageParam list. Empty list when no checkpoint exists yet (jobs that finished without persisting state, e.g. NSR runs)."
     },
     "pending_tool_call": {
      "anyOf": [
       {
        "additionalProperties": true,
        "type": "object"
       },
       {
        "type": "null"
       }
      ],
      "title": "Pending Tool Call",
      "description": "If the job is paused on an approval, the tool call awaiting review. None for completed jobs."
     },
     "captured_at": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Captured At",
      "description": "ISO 8601 of when the checkpoint was last written."
     }
    },
    "type": "object",
    "required": [
     "job_id",
     "messages"
    ],
    "title": "JobMessagesResponse",
    "description": "Returned by `GET /api/v1/jobs/{id}/messages`."
   },
   "JobPreviewResponse": {
    "properties": {
     "agent_type": {
      "type": "string",
      "title": "Agent Type"
     },
     "agent_type_kind": {
      "type": "string",
      "enum": [
       "builtin",
       "tenant",
       "unknown"
      ],
      "title": "Agent Type Kind",
      "description": "How the agent_type resolves: `builtin` ships with the platform; `tenant` is owned by your org; `unknown` would be rejected by /trigger but is shown here so callers can confirm typos."
     },
     "instruction": {
      "type": "string",
      "title": "Instruction",
      "description": "The trimmed instruction that would land on the worker."
     },
     "resolved_params": {
      "additionalProperties": true,
      "type": "object",
      "title": "Resolved Params",
      "description": "The full `params` dict the worker would see, with template defaults merged underneath your per-job overrides."
     },
     "resolved_model": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Resolved Model",
      "description": "Canonical model id after alias resolution. None = deployment default."
     },
     "resolved_agent_mode": {
      "type": "string",
      "title": "Resolved Agent Mode",
      "description": "`claude` (default), `openai` (GPT-5.6 Sol), or `nsr` (local engine)."
     },
     "quota_ok": {
      "type": "boolean",
      "title": "Quota Ok",
      "description": "True iff sending this job right now would clear the tenant's quota check."
     },
     "quota_used": {
      "type": "integer",
      "title": "Quota Used"
     },
     "quota_limit": {
      "type": "integer",
      "title": "Quota Limit"
     }
    },
    "type": "object",
    "required": [
     "agent_type",
     "agent_type_kind",
     "instruction",
     "resolved_params",
     "resolved_model",
     "resolved_agent_mode",
     "quota_ok",
     "quota_used",
     "quota_limit"
    ],
    "title": "JobPreviewResponse",
    "description": "Returned by `POST /api/v1/jobs/preview`. Echoes the resolved\nrequest without queueing anything."
   },
   "JobRead": {
    "properties": {
     "id": {
      "type": "string",
      "format": "uuid",
      "title": "Id"
     },
     "tenant_id": {
      "type": "string",
      "format": "uuid",
      "title": "Tenant Id"
     },
     "status": {
      "type": "string",
      "title": "Status"
     },
     "template": {
      "type": "string",
      "title": "Template"
     },
     "params": {
      "additionalProperties": true,
      "type": "object",
      "title": "Params"
     },
     "agent_mode": {
      "type": "string",
      "title": "Agent Mode",
      "default": "claude"
     },
     "summary": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Summary"
     },
     "error": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Error"
     },
     "input_tokens": {
      "anyOf": [
       {
        "type": "integer"
       },
       {
        "type": "null"
       }
      ],
      "title": "Input Tokens"
     },
     "output_tokens": {
      "anyOf": [
       {
        "type": "integer"
       },
       {
        "type": "null"
       }
      ],
      "title": "Output Tokens"
     },
     "cost_usd": {
      "anyOf": [
       {
        "type": "number"
       },
       {
        "type": "null"
       }
      ],
      "title": "Cost Usd"
     },
     "sandbox_id": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Sandbox Id"
     },
     "created_at": {
      "type": "string",
      "format": "date-time",
      "title": "Created At"
     },
     "updated_at": {
      "type": "string",
      "format": "date-time",
      "title": "Updated At"
     }
    },
    "type": "object",
    "required": [
     "id",
     "tenant_id",
     "status",
     "template",
     "params",
     "created_at",
     "updated_at"
    ],
    "title": "JobRead"
   },
   "JobResultResponse": {
    "properties": {
     "id": {
      "type": "string",
      "title": "Id"
     },
     "status": {
      "type": "string",
      "title": "Status"
     },
     "summary": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Summary"
     },
     "error": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Error"
     },
     "artifacts": {
      "items": {
       "$ref": "#/components/schemas/ArtifactResponse"
      },
      "type": "array",
      "title": "Artifacts",
      "default": []
     },
     "cost_usd": {
      "anyOf": [
       {
        "type": "number"
       },
       {
        "type": "null"
       }
      ],
      "title": "Cost Usd"
     }
    },
    "type": "object",
    "required": [
     "id",
     "status"
    ],
    "title": "JobResultResponse",
    "description": "Single-call summary + artifact list. Returned by `/jobs/:id/result`."
   },
   "JobStatsResponse": {
    "properties": {
     "windows": {
      "items": {
       "$ref": "#/components/schemas/JobStatsWindow"
      },
      "type": "array",
      "title": "Windows",
      "description": "Three windows in fixed order: today, last_7d, last_30d."
     }
    },
    "type": "object",
    "required": [
     "windows"
    ],
    "title": "JobStatsResponse",
    "description": "Returned by `GET /api/v1/jobs/stats`."
   },
   "JobStatsWindow": {
    "properties": {
     "window": {
      "type": "string",
      "enum": [
       "today",
       "last_7d",
       "last_30d"
      ],
      "title": "Window"
     },
     "total": {
      "type": "integer",
      "title": "Total",
      "description": "Jobs created within the window."
     },
     "succeeded": {
      "type": "integer",
      "title": "Succeeded"
     },
     "failed": {
      "type": "integer",
      "title": "Failed"
     },
     "cancelled": {
      "type": "integer",
      "title": "Cancelled"
     },
     "in_flight": {
      "type": "integer",
      "title": "In Flight",
      "description": "Queued + running + awaiting_approval, AT THE TIME OF QUERY (not window-bounded)."
     },
     "success_rate": {
      "type": "number",
      "title": "Success Rate",
      "description": "succeeded / (succeeded + failed). 0.0 when neither bucket is populated. Excludes cancelled \u2014 those are user actions, not agent failures."
     },
     "avg_duration_seconds": {
      "type": "number",
      "title": "Avg Duration Seconds",
      "description": "Mean wall-clock between created_at and updated_at across terminal-status jobs in the window. 0.0 when no terminal rows fell in the window."
     },
     "total_cost_usd": {
      "type": "number",
      "title": "Total Cost Usd"
     }
    },
    "type": "object",
    "required": [
     "window",
     "total",
     "succeeded",
     "failed",
     "cancelled",
     "in_flight",
     "success_rate",
     "avg_duration_seconds",
     "total_cost_usd"
    ],
    "title": "JobStatsWindow",
    "description": "Aggregate stats for one rolling window."
   },
   "JobStatusResponse": {
    "properties": {
     "id": {
      "type": "string",
      "title": "Id",
      "description": "Job UUID."
     },
     "status": {
      "type": "string",
      "title": "Status",
      "description": "Current status: queued, running, succeeded, failed, cancelled, awaiting_approval."
     },
     "template": {
      "type": "string",
      "title": "Template",
      "description": "Agent type / template that was used."
     },
     "summary": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Summary",
      "description": "Pipe-separated final assistant text. Populated when the job reaches a terminal state. Truncated to \u22485 segments \u00d7 280 chars."
     },
     "error": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Error",
      "description": "Human-readable error message when status is 'failed' or 'cancelled'."
     },
     "input_tokens": {
      "anyOf": [
       {
        "type": "integer"
       },
       {
        "type": "null"
       }
      ],
      "title": "Input Tokens",
      "description": "Cumulative input tokens consumed."
     },
     "output_tokens": {
      "anyOf": [
       {
        "type": "integer"
       },
       {
        "type": "null"
       }
      ],
      "title": "Output Tokens",
      "description": "Cumulative output tokens generated."
     },
     "cost_usd": {
      "anyOf": [
       {
        "type": "number"
       },
       {
        "type": "null"
       }
      ],
      "title": "Cost Usd",
      "description": "Cumulative billable cost. Priced at the job's selected model rate (not the deployment default)."
     },
     "created_at": {
      "type": "string",
      "title": "Created At",
      "description": "ISO 8601 UTC timestamp."
     },
     "updated_at": {
      "type": "string",
      "title": "Updated At",
      "description": "ISO 8601 UTC timestamp; refreshed on every iteration."
     }
    },
    "type": "object",
    "required": [
     "id",
     "status",
     "template",
     "created_at",
     "updated_at"
    ],
    "title": "JobStatusResponse",
    "description": "Single-job detail. Returned by `/jobs/:id` and as elements of `/jobs`."
   },
   "JobTagsResponse": {
    "properties": {
     "job_id": {
      "type": "string",
      "title": "Job Id"
     },
     "tags": {
      "items": {
       "type": "string"
      },
      "type": "array",
      "title": "Tags"
     }
    },
    "type": "object",
    "required": [
     "job_id",
     "tags"
    ],
    "title": "JobTagsResponse",
    "description": "Returned by `PATCH /api/v1/jobs/{id}/tags`."
   },
   "KeyListItem": {
    "properties": {
     "id": {
      "type": "string",
      "title": "Id"
     },
     "name": {
      "type": "string",
      "title": "Name"
     },
     "key_prefix": {
      "type": "string",
      "title": "Key Prefix"
     },
     "scopes": {
      "items": {
       "type": "string"
      },
      "type": "array",
      "title": "Scopes"
     },
     "last_used_at": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Last Used At"
     },
     "is_active": {
      "type": "boolean",
      "title": "Is Active"
     },
     "created_at": {
      "type": "string",
      "title": "Created At"
     }
    },
    "type": "object",
    "required": [
     "id",
     "name",
     "key_prefix",
     "scopes",
     "last_used_at",
     "is_active",
     "created_at"
    ],
    "title": "KeyListItem"
   },
   "MultiTagItemResult": {
    "properties": {
     "job_id": {
      "type": "string",
      "title": "Job Id"
     },
     "tagged": {
      "type": "boolean",
      "title": "Tagged"
     },
     "tags": {
      "items": {
       "type": "string"
      },
      "type": "array",
      "title": "Tags"
     },
     "error": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Error"
     }
    },
    "type": "object",
    "required": [
     "job_id",
     "tagged"
    ],
    "title": "MultiTagItemResult"
   },
   "MultiTagRequest": {
    "properties": {
     "job_ids": {
      "items": {
       "type": "string",
       "format": "uuid"
      },
      "type": "array",
      "maxItems": 50,
      "minItems": 1,
      "title": "Job Ids",
      "description": "List of job UUIDs to tag (1..50)."
     },
     "tags": {
      "items": {
       "type": "string"
      },
      "type": "array",
      "maxItems": 20,
      "title": "Tags",
      "description": "Tag values to apply. Same per-tag rules as `TriggerRequest.tags`. Pass an empty array with `mode=replace` to clear tags entirely."
     },
     "mode": {
      "type": "string",
      "enum": [
       "replace",
       "merge"
      ],
      "title": "Mode",
      "description": "`merge` (default) adds the supplied tags to whatever's already on each job, deduplicating. `replace` overwrites \u2014 the supplied tags become the complete set, and any existing tags not in the request are removed.",
      "default": "merge"
     }
    },
    "type": "object",
    "required": [
     "job_ids",
     "tags"
    ],
    "title": "MultiTagRequest",
    "description": "Body for `POST /api/v1/jobs/multi-tag`."
   },
   "MultiTagResponse": {
    "properties": {
     "tagged": {
      "type": "integer",
      "title": "Tagged"
     },
     "skipped": {
      "type": "integer",
      "title": "Skipped"
     },
     "results": {
      "items": {
       "$ref": "#/components/schemas/MultiTagItemResult"
      },
      "type": "array",
      "title": "Results"
     }
    },
    "type": "object",
    "required": [
     "tagged",
     "skipped",
     "results"
    ],
    "title": "MultiTagResponse"
   },
   "OutcomeDisputeCreate": {
    "properties": {
     "reason": {
      "type": "string",
      "maxLength": 4000,
      "minLength": 3,
      "title": "Reason"
     }
    },
    "type": "object",
    "required": [
     "reason"
    ],
    "title": "OutcomeDisputeCreate",
    "description": "Customer payload to flag an Outcome for review (Appendix D.2)."
   },
   "OutcomeDisputeListResponse": {
    "properties": {
     "items": {
      "items": {
       "$ref": "#/components/schemas/OutcomeDisputeRead"
      },
      "type": "array",
      "title": "Items"
     },
     "total": {
      "type": "integer",
      "title": "Total"
     },
     "limit": {
      "type": "integer",
      "title": "Limit"
     },
     "offset": {
      "type": "integer",
      "title": "Offset"
     }
    },
    "type": "object",
    "required": [
     "items",
     "total",
     "limit",
     "offset"
    ],
    "title": "OutcomeDisputeListResponse"
   },
   "OutcomeDisputeRead": {
    "properties": {
     "id": {
      "type": "string",
      "format": "uuid",
      "title": "Id"
     },
     "outcome_id": {
      "type": "string",
      "format": "uuid",
      "title": "Outcome Id"
     },
     "tenant_id": {
      "type": "string",
      "format": "uuid",
      "title": "Tenant Id"
     },
     "reason": {
      "type": "string",
      "title": "Reason"
     },
     "flagged_by": {
      "anyOf": [
       {
        "type": "string",
        "format": "uuid"
       },
       {
        "type": "null"
       }
      ],
      "title": "Flagged By"
     },
     "flagged_at": {
      "type": "string",
      "format": "date-time",
      "title": "Flagged At"
     },
     "idempotency_key": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Idempotency Key"
     },
     "credit_applied_usd": {
      "type": "string",
      "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$",
      "title": "Credit Applied Usd"
     },
     "resolution": {
      "anyOf": [
       {
        "type": "string",
        "enum": [
         "confirmed_outcome",
         "confirmed_error",
         "indeterminate"
        ]
       },
       {
        "type": "null"
       }
      ],
      "title": "Resolution"
     },
     "resolved_at": {
      "anyOf": [
       {
        "type": "string",
        "format": "date-time"
       },
       {
        "type": "null"
       }
      ],
      "title": "Resolved At"
     },
     "resolved_by": {
      "anyOf": [
       {
        "type": "string",
        "format": "uuid"
       },
       {
        "type": "null"
       }
      ],
      "title": "Resolved By"
     },
     "root_cause": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Root Cause"
     },
     "review_notes": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Review Notes"
     },
     "stripe_credit_balance_tx_id": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Stripe Credit Balance Tx Id"
     }
    },
    "type": "object",
    "required": [
     "id",
     "outcome_id",
     "tenant_id",
     "reason",
     "flagged_at",
     "credit_applied_usd"
    ],
    "title": "OutcomeDisputeRead"
   },
   "OutcomeDisputeResolve": {
    "properties": {
     "resolution": {
      "type": "string",
      "enum": [
       "confirmed_outcome",
       "confirmed_error",
       "indeterminate"
      ],
      "title": "Resolution"
     },
     "root_cause": {
      "anyOf": [
       {
        "type": "string",
        "maxLength": 8000
       },
       {
        "type": "null"
       }
      ],
      "title": "Root Cause"
     },
     "review_notes": {
      "anyOf": [
       {
        "type": "string",
        "maxLength": 8000
       },
       {
        "type": "null"
       }
      ],
      "title": "Review Notes"
     }
    },
    "type": "object",
    "required": [
     "resolution"
    ],
    "title": "OutcomeDisputeResolve",
    "description": "Internal payload to close a dispute after joint review (Appendix D.3)."
   },
   "OutcomeListResponse": {
    "properties": {
     "items": {
      "items": {
       "$ref": "#/components/schemas/OutcomeRead"
      },
      "type": "array",
      "title": "Items"
     },
     "total": {
      "type": "integer",
      "title": "Total"
     },
     "limit": {
      "type": "integer",
      "title": "Limit"
     },
     "offset": {
      "type": "integer",
      "title": "Offset"
     },
     "next_cursor": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Next Cursor"
     }
    },
    "type": "object",
    "required": [
     "items",
     "total",
     "limit",
     "offset"
    ],
    "title": "OutcomeListResponse",
    "description": "Paginated list envelope. Mirrors the /jobs list shape."
   },
   "OutcomePricingResponse": {
    "properties": {
     "defaults": {
      "additionalProperties": {
       "type": "string"
      },
      "type": "object",
      "title": "Defaults"
     },
     "overrides": {
      "additionalProperties": {
       "type": "string"
      },
      "type": "object",
      "title": "Overrides"
     },
     "effective": {
      "additionalProperties": {
       "type": "string"
      },
      "type": "object",
      "title": "Effective"
     }
    },
    "type": "object",
    "required": [
     "defaults",
     "overrides",
     "effective"
    ],
    "title": "OutcomePricingResponse",
    "description": "Effective per-SKU pricing for the authenticated tenant.\n\n`defaults` lists DEFAULT_SKU_PRICING_USD as USD strings. `overrides`\nis the tenant's Subscription.outcome_pricing dict (also USD\nstrings). `effective` is defaults + overrides merged \u2014 the rate\nthe worker actually bills at."
   },
   "OutcomePricingUpdate": {
    "properties": {
     "overrides": {
      "additionalProperties": {
       "type": "string"
      },
      "type": "object",
      "title": "Overrides"
     }
    },
    "type": "object",
    "required": [
     "overrides"
    ],
    "title": "OutcomePricingUpdate",
    "description": "Body of PUT /billing/outcome-pricing.\n\nMaps each SKU to a USD price as a STRING (preserves Decimal\nprecision across JSON). Empty dict clears all overrides. Unknown\nSKU keys are rejected with 422."
   },
   "OutcomeRead": {
    "properties": {
     "id": {
      "type": "string",
      "format": "uuid",
      "title": "Id"
     },
     "tenant_id": {
      "type": "string",
      "format": "uuid",
      "title": "Tenant Id"
     },
     "type": {
      "type": "string",
      "enum": [
       "resolved_contact",
       "resolved_return",
       "wismo_resolution",
       "abandoned_cart_recovery",
       "qualified_lead",
       "b2b_reorder",
       "billing_dispute",
       "upsell",
       "pre_purchase_consultation",
       "triage"
      ],
      "title": "Type"
     },
     "status": {
      "type": "string",
      "enum": [
       "pending",
       "completed",
       "reopened",
       "disputed",
       "confirmed",
       "error",
       "indeterminate"
      ],
      "title": "Status"
     },
     "inquiry_id": {
      "type": "string",
      "title": "Inquiry Id"
     },
     "price_usd": {
      "type": "string",
      "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$",
      "title": "Price Usd"
     },
     "completion_criterion": {
      "additionalProperties": true,
      "type": "object",
      "title": "Completion Criterion"
     },
     "verification_record": {
      "additionalProperties": true,
      "type": "object",
      "title": "Verification Record"
     },
     "system_of_record_event_id": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "System Of Record Event Id"
     },
     "job_id": {
      "anyOf": [
       {
        "type": "string",
        "format": "uuid"
       },
       {
        "type": "null"
       }
      ],
      "title": "Job Id"
     },
     "parent_outcome_id": {
      "anyOf": [
       {
        "type": "string",
        "format": "uuid"
       },
       {
        "type": "null"
       }
      ],
      "title": "Parent Outcome Id"
     },
     "triggered_human_handoff": {
      "type": "boolean",
      "title": "Triggered Human Handoff",
      "default": false
     },
     "high_value_action": {
      "type": "boolean",
      "title": "High Value Action",
      "default": false
     },
     "created_at": {
      "type": "string",
      "format": "date-time",
      "title": "Created At"
     },
     "completed_at": {
      "anyOf": [
       {
        "type": "string",
        "format": "date-time"
       },
       {
        "type": "null"
       }
      ],
      "title": "Completed At"
     },
     "resolution_window_expires_at": {
      "anyOf": [
       {
        "type": "string",
        "format": "date-time"
       },
       {
        "type": "null"
       }
      ],
      "title": "Resolution Window Expires At"
     },
     "dispute_window_expires_at": {
      "anyOf": [
       {
        "type": "string",
        "format": "date-time"
       },
       {
        "type": "null"
       }
      ],
      "title": "Dispute Window Expires At"
     },
     "updated_at": {
      "type": "string",
      "format": "date-time",
      "title": "Updated At"
     },
     "extra_metadata": {
      "additionalProperties": true,
      "type": "object",
      "title": "Extra Metadata"
     },
     "stripe_meter_event_id": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Stripe Meter Event Id"
     }
    },
    "type": "object",
    "required": [
     "id",
     "tenant_id",
     "type",
     "status",
     "inquiry_id",
     "price_usd",
     "created_at",
     "updated_at"
    ],
    "title": "OutcomeRead",
    "description": "Customer-facing representation of an Outcome row.\n\nMaps 1:1 with the model. Decimal is serialized as a string by default;\nwe keep it as Decimal so downstream billing math stays exact."
   },
   "OutcomeStatsBySKU": {
    "properties": {
     "type": {
      "type": "string",
      "enum": [
       "resolved_contact",
       "resolved_return",
       "wismo_resolution",
       "abandoned_cart_recovery",
       "qualified_lead",
       "b2b_reorder",
       "billing_dispute",
       "upsell",
       "pre_purchase_consultation",
       "triage"
      ],
      "title": "Type"
     },
     "total": {
      "type": "integer",
      "title": "Total"
     },
     "completed": {
      "type": "integer",
      "title": "Completed"
     },
     "disputed": {
      "type": "integer",
      "title": "Disputed"
     },
     "confirmed_errors": {
      "type": "integer",
      "title": "Confirmed Errors"
     },
     "dispute_rate": {
      "type": "number",
      "maximum": 1.0,
      "minimum": 0.0,
      "title": "Dispute Rate"
     },
     "total_billable_usd": {
      "type": "string",
      "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$",
      "title": "Total Billable Usd"
     }
    },
    "type": "object",
    "required": [
     "type",
     "total",
     "completed",
     "disputed",
     "confirmed_errors",
     "dispute_rate",
     "total_billable_usd"
    ],
    "title": "OutcomeStatsBySKU",
    "description": "Per-SKU rollup for the quarterly review (Appendix D.6) and the\nDispute-Rate quality threshold (Appendix D.5)."
   },
   "OutcomeStatsResponse": {
    "properties": {
     "window_start": {
      "type": "string",
      "format": "date-time",
      "title": "Window Start"
     },
     "window_end": {
      "type": "string",
      "format": "date-time",
      "title": "Window End"
     },
     "by_sku": {
      "items": {
       "$ref": "#/components/schemas/OutcomeStatsBySKU"
      },
      "type": "array",
      "title": "By Sku"
     },
     "overall_dispute_rate": {
      "type": "number",
      "maximum": 1.0,
      "minimum": 0.0,
      "title": "Overall Dispute Rate"
     }
    },
    "type": "object",
    "required": [
     "window_start",
     "window_end",
     "by_sku",
     "overall_dispute_rate"
    ],
    "title": "OutcomeStatsResponse"
   },
   "PlanResponse": {
    "properties": {
     "name": {
      "type": "string",
      "title": "Name"
     },
     "display_name": {
      "type": "string",
      "title": "Display Name"
     },
     "marketing_name": {
      "type": "string",
      "title": "Marketing Name"
     },
     "price_label": {
      "type": "string",
      "title": "Price Label"
     },
     "jobs_label": {
      "type": "string",
      "title": "Jobs Label"
     },
     "self_serve": {
      "type": "boolean",
      "title": "Self Serve"
     },
     "stripe_configured": {
      "type": "boolean",
      "title": "Stripe Configured"
     },
     "task_quota": {
      "type": "integer",
      "title": "Task Quota"
     },
     "seats": {
      "type": "integer",
      "title": "Seats"
     }
    },
    "type": "object",
    "required": [
     "name",
     "display_name",
     "marketing_name",
     "price_label",
     "jobs_label",
     "self_serve",
     "stripe_configured",
     "task_quota",
     "seats"
    ],
    "title": "PlanResponse"
   },
   "PolicyCreate": {
    "properties": {
     "name": {
      "type": "string",
      "title": "Name"
     },
     "tool_patterns": {
      "items": {
       "type": "string"
      },
      "type": "array",
      "title": "Tool Patterns",
      "default": []
     },
     "auto_approve_rules": {
      "additionalProperties": true,
      "type": "object",
      "title": "Auto Approve Rules",
      "default": {}
     }
    },
    "type": "object",
    "required": [
     "name"
    ],
    "title": "PolicyCreate"
   },
   "PolicyResponse": {
    "properties": {
     "id": {
      "type": "string",
      "title": "Id"
     },
     "name": {
      "type": "string",
      "title": "Name"
     },
     "tool_patterns": {
      "items": {
       "type": "string"
      },
      "type": "array",
      "title": "Tool Patterns"
     },
     "auto_approve_rules": {
      "additionalProperties": true,
      "type": "object",
      "title": "Auto Approve Rules"
     },
     "is_active": {
      "type": "boolean",
      "title": "Is Active"
     },
     "created_at": {
      "type": "string",
      "title": "Created At"
     }
    },
    "type": "object",
    "required": [
     "id",
     "name",
     "tool_patterns",
     "auto_approve_rules",
     "is_active",
     "created_at"
    ],
    "title": "PolicyResponse"
   },
   "PolicyUpdate": {
    "properties": {
     "name": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Name"
     },
     "tool_patterns": {
      "anyOf": [
       {
        "items": {
         "type": "string"
        },
        "type": "array"
       },
       {
        "type": "null"
       }
      ],
      "title": "Tool Patterns"
     },
     "auto_approve_rules": {
      "anyOf": [
       {
        "additionalProperties": true,
        "type": "object"
       },
       {
        "type": "null"
       }
      ],
      "title": "Auto Approve Rules"
     },
     "is_active": {
      "anyOf": [
       {
        "type": "boolean"
       },
       {
        "type": "null"
       }
      ],
      "title": "Is Active"
     }
    },
    "type": "object",
    "title": "PolicyUpdate"
   },
   "PortalResponse": {
    "properties": {
     "portal_url": {
      "type": "string",
      "title": "Portal Url"
     }
    },
    "type": "object",
    "required": [
     "portal_url"
    ],
    "title": "PortalResponse"
   },
   "PostEventRequest": {
    "properties": {
     "event_type": {
      "type": "string",
      "title": "Event Type",
      "description": "Type of event"
     },
     "timestamp": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Timestamp",
      "description": "ISO timestamp"
     },
     "data": {
      "additionalProperties": true,
      "type": "object",
      "title": "Data",
      "description": "Event payload"
     },
     "agent_type": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Agent Type"
     },
     "request_id": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Request Id"
     }
    },
    "type": "object",
    "required": [
     "event_type"
    ],
    "title": "PostEventRequest",
    "description": "Validated request body for event injection."
   },
   "PublicBenchmarksResponse": {
    "properties": {
     "as_of": {
      "type": "string",
      "format": "date-time",
      "title": "As Of"
     },
     "window_days": {
      "type": "integer",
      "minimum": 1.0,
      "title": "Window Days"
     },
     "platform": {
      "$ref": "#/components/schemas/PublicPlatformStats"
     },
     "by_sku": {
      "items": {
       "$ref": "#/components/schemas/PublicSkuBenchmark"
      },
      "type": "array",
      "title": "By Sku"
     }
    },
    "type": "object",
    "required": [
     "as_of",
     "window_days",
     "platform",
     "by_sku"
    ],
    "title": "PublicBenchmarksResponse",
    "description": "Body of `GET /api/v1/system/benchmarks`."
   },
   "PublicPlatformStats": {
    "properties": {
     "total_outcomes": {
      "type": "integer",
      "title": "Total Outcomes"
     },
     "avg_outcome_usd": {
      "type": "string",
      "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$",
      "title": "Avg Outcome Usd"
     }
    },
    "type": "object",
    "required": [
     "total_outcomes",
     "avg_outcome_usd"
    ],
    "title": "PublicPlatformStats"
   },
   "PublicSkuBenchmark": {
    "properties": {
     "type": {
      "type": "string",
      "enum": [
       "resolved_contact",
       "resolved_return",
       "wismo_resolution",
       "abandoned_cart_recovery",
       "qualified_lead",
       "b2b_reorder",
       "billing_dispute",
       "upsell",
       "pre_purchase_consultation",
       "triage"
      ],
      "title": "Type"
     },
     "avg_usd": {
      "type": "string",
      "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$",
      "title": "Avg Usd"
     },
     "vs_bpo_avg_usd": {
      "anyOf": [
       {
        "type": "string",
        "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"
       },
       {
        "type": "null"
       }
      ],
      "title": "Vs Bpo Avg Usd"
     },
     "savings_pct": {
      "anyOf": [
       {
        "type": "number",
        "maximum": 1.0,
        "minimum": 0.0
       },
       {
        "type": "null"
       }
      ],
      "title": "Savings Pct"
     }
    },
    "type": "object",
    "required": [
     "type",
     "avg_usd"
    ],
    "title": "PublicSkuBenchmark",
    "description": "Tenant-agnostic per-SKU rollup for the public landing page.\n\nNo tenant ids; SKU is included only when it clears the k-anonymity\nfloor (>= PUBLIC_BENCHMARK_MIN_OUTCOMES_PER_SKU in the window)."
   },
   "QuotaResponse": {
    "properties": {
     "plan_name": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Plan Name",
      "description": "Subscription plan label, or None if no subscription is on file."
     },
     "period_tasks_used": {
      "type": "integer",
      "title": "Period Tasks Used"
     },
     "task_quota": {
      "type": "integer",
      "title": "Task Quota"
     },
     "remaining": {
      "type": "integer",
      "title": "Remaining",
      "description": "Convenience: max(quota - used, 0)."
     },
     "is_exhausted": {
      "type": "boolean",
      "title": "Is Exhausted",
      "description": "True iff `remaining == 0`. Tenants can branch on this without arithmetic."
     },
     "billing_period_start": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Billing Period Start"
     },
     "billing_period_end": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Billing Period End"
     }
    },
    "type": "object",
    "required": [
     "period_tasks_used",
     "task_quota",
     "remaining",
     "is_exhausted"
    ],
    "title": "QuotaResponse",
    "description": "Returned by `GET /api/v1/quota`. The minimum payload tenants need\nto decide whether to send another job."
   },
   "ReplayWebhookResponse": {
    "properties": {
     "job_id": {
      "type": "string",
      "title": "Job Id"
     },
     "event_type": {
      "type": "string",
      "title": "Event Type",
      "description": "The terminal event re-fired (job.completed | job.failed)."
     },
     "registered_endpoints_dispatched": {
      "type": "integer",
      "title": "Registered Endpoints Dispatched",
      "description": "Count of registered WebhookEndpoint rows the event was queued to."
     },
     "adhoc_url_delivered": {
      "anyOf": [
       {
        "type": "boolean"
       },
       {
        "type": "null"
       }
      ],
      "title": "Adhoc Url Delivered",
      "description": "If the job carried a `webhook_url` in params, the outcome of the ad-hoc delivery attempt. None when no ad-hoc URL was set."
     }
    },
    "type": "object",
    "required": [
     "job_id",
     "event_type",
     "registered_endpoints_dispatched"
    ],
    "title": "ReplayWebhookResponse",
    "description": "Returned by `POST /api/v1/jobs/{id}/replay-webhook`."
   },
   "RetryBatchItemResult": {
    "properties": {
     "source_job_id": {
      "type": "string",
      "title": "Source Job Id"
     },
     "new_job_id": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "New Job Id"
     },
     "status": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Status"
     },
     "error": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Error"
     }
    },
    "type": "object",
    "required": [
     "source_job_id"
    ],
    "title": "RetryBatchItemResult",
    "description": "Per-row outcome inside a retry-batch response."
   },
   "RetryBatchRequest": {
    "properties": {
     "job_ids": {
      "items": {
       "type": "string",
       "format": "uuid"
      },
      "type": "array",
      "maxItems": 50,
      "minItems": 1,
      "title": "Job Ids",
      "description": "List of source job UUIDs to retry (1..50). Items are validated independently; non-retriable rows surface as per-row errors without blocking the rest."
     }
    },
    "type": "object",
    "required": [
     "job_ids"
    ],
    "title": "RetryBatchRequest",
    "description": "Body for `POST /api/v1/jobs/retry-batch`."
   },
   "RetryBatchResponse": {
    "properties": {
     "accepted": {
      "type": "integer",
      "title": "Accepted"
     },
     "rejected": {
      "type": "integer",
      "title": "Rejected"
     },
     "results": {
      "items": {
       "$ref": "#/components/schemas/RetryBatchItemResult"
      },
      "type": "array",
      "title": "Results"
     }
    },
    "type": "object",
    "required": [
     "accepted",
     "rejected",
     "results"
    ],
    "title": "RetryBatchResponse",
    "description": "Returned by `POST /api/v1/jobs/retry-batch`."
   },
   "ReviewRequest": {
    "properties": {
     "comment": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Comment"
     }
    },
    "type": "object",
    "title": "ReviewRequest"
   },
   "RunRequest": {
    "properties": {
     "instruction": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Instruction"
     },
     "params": {
      "additionalProperties": true,
      "type": "object",
      "title": "Params",
      "default": {}
     },
     "sandbox": {
      "type": "boolean",
      "title": "Sandbox",
      "default": false
     }
    },
    "type": "object",
    "title": "RunRequest"
   },
   "RunResponse": {
    "properties": {
     "job_id": {
      "type": "string",
      "format": "uuid",
      "title": "Job Id"
     },
     "agent_run_id": {
      "type": "string",
      "title": "Agent Run Id"
     },
     "status": {
      "type": "string",
      "title": "Status"
     }
    },
    "type": "object",
    "required": [
     "job_id",
     "agent_run_id",
     "status"
    ],
    "title": "RunResponse"
   },
   "ScreenshotUrlResponse": {
    "properties": {
     "url": {
      "type": "string",
      "title": "Url"
     }
    },
    "type": "object",
    "required": [
     "url"
    ],
    "title": "ScreenshotUrlResponse",
    "description": "Short-lived presigned URL pointing at the screenshot in object storage."
   },
   "SessionStatsResponse": {
    "properties": {
     "total_sessions": {
      "type": "integer",
      "title": "Total Sessions"
     },
     "total_api_calls": {
      "type": "integer",
      "title": "Total Api Calls"
     },
     "total_messages": {
      "type": "integer",
      "title": "Total Messages"
     },
     "average_execution_time_seconds": {
      "type": "number",
      "title": "Average Execution Time Seconds"
     },
     "status_breakdown": {
      "additionalProperties": true,
      "type": "object",
      "title": "Status Breakdown"
     }
    },
    "type": "object",
    "required": [
     "total_sessions",
     "total_api_calls",
     "total_messages",
     "average_execution_time_seconds",
     "status_breakdown"
    ],
    "title": "SessionStatsResponse",
    "description": "Session statistics response."
   },
   "SkillCreate": {
    "properties": {
     "display_name": {
      "type": "string",
      "maxLength": 128,
      "title": "Display Name"
     },
     "description": {
      "type": "string",
      "maxLength": 1024,
      "title": "Description"
     },
     "container_type": {
      "anyOf": [
       {
        "type": "string",
        "enum": [
         "anthropic",
         "custom"
        ]
       },
       {
        "type": "null"
       }
      ],
      "title": "Container Type"
     },
     "container_skill_id": {
      "anyOf": [
       {
        "type": "string",
        "maxLength": 128
       },
       {
        "type": "null"
       }
      ],
      "title": "Container Skill Id"
     },
     "container_version": {
      "type": "string",
      "maxLength": 64,
      "title": "Container Version",
      "default": "latest"
     },
     "container_env_var": {
      "anyOf": [
       {
        "type": "string",
        "maxLength": 128
       },
       {
        "type": "null"
       }
      ],
      "title": "Container Env Var"
     },
     "default_launcher": {
      "anyOf": [
       {
        "type": "string",
        "maxLength": 256
       },
       {
        "type": "null"
       }
      ],
      "title": "Default Launcher"
     },
     "triggers": {
      "items": {
       "type": "string"
      },
      "type": "array",
      "title": "Triggers"
     },
     "tags": {
      "items": {
       "type": "string"
      },
      "type": "array",
      "title": "Tags"
     },
     "resources": {
      "items": {
       "type": "string"
      },
      "type": "array",
      "title": "Resources"
     },
     "key": {
      "type": "string",
      "maxLength": 64,
      "title": "Key"
     }
    },
    "type": "object",
    "required": [
     "display_name",
     "description",
     "key"
    ],
    "title": "SkillCreate"
   },
   "SkillImportRequest": {
    "properties": {
     "markdown": {
      "type": "string",
      "minLength": 10,
      "title": "Markdown"
     },
     "overwrite": {
      "type": "boolean",
      "title": "Overwrite",
      "default": false
     },
     "overwrite_assignments": {
      "type": "boolean",
      "title": "Overwrite Assignments",
      "default": false
     },
     "version_label": {
      "anyOf": [
       {
        "type": "string",
        "maxLength": 64
       },
       {
        "type": "null"
       }
      ],
      "title": "Version Label"
     }
    },
    "type": "object",
    "required": [
     "markdown"
    ],
    "title": "SkillImportRequest"
   },
   "SkillRead": {
    "properties": {
     "display_name": {
      "type": "string",
      "maxLength": 128,
      "title": "Display Name"
     },
     "description": {
      "type": "string",
      "maxLength": 1024,
      "title": "Description"
     },
     "container_type": {
      "anyOf": [
       {
        "type": "string",
        "enum": [
         "anthropic",
         "custom"
        ]
       },
       {
        "type": "null"
       }
      ],
      "title": "Container Type"
     },
     "container_skill_id": {
      "anyOf": [
       {
        "type": "string",
        "maxLength": 128
       },
       {
        "type": "null"
       }
      ],
      "title": "Container Skill Id"
     },
     "container_version": {
      "type": "string",
      "maxLength": 64,
      "title": "Container Version",
      "default": "latest"
     },
     "container_env_var": {
      "anyOf": [
       {
        "type": "string",
        "maxLength": 128
       },
       {
        "type": "null"
       }
      ],
      "title": "Container Env Var"
     },
     "default_launcher": {
      "anyOf": [
       {
        "type": "string",
        "maxLength": 256
       },
       {
        "type": "null"
       }
      ],
      "title": "Default Launcher"
     },
     "triggers": {
      "items": {
       "type": "string"
      },
      "type": "array",
      "title": "Triggers"
     },
     "tags": {
      "items": {
       "type": "string"
      },
      "type": "array",
      "title": "Tags"
     },
     "resources": {
      "items": {
       "type": "string"
      },
      "type": "array",
      "title": "Resources"
     },
     "id": {
      "type": "string",
      "format": "uuid",
      "title": "Id"
     },
     "key": {
      "type": "string",
      "title": "Key"
     },
     "created_at": {
      "type": "string",
      "format": "date-time",
      "title": "Created At"
     },
     "updated_at": {
      "type": "string",
      "format": "date-time",
      "title": "Updated At"
     },
     "agent_keys": {
      "items": {
       "type": "string"
      },
      "type": "array",
      "title": "Agent Keys"
     },
     "agent_mappings": {
      "items": {
       "$ref": "#/components/schemas/AgentSkillAssignment"
      },
      "type": "array",
      "title": "Agent Mappings"
     },
     "latest_version": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Latest Version"
     },
     "version_count": {
      "type": "integer",
      "title": "Version Count",
      "default": 0
     }
    },
    "type": "object",
    "required": [
     "display_name",
     "description",
     "id",
     "key",
     "created_at",
     "updated_at"
    ],
    "title": "SkillRead"
   },
   "SkillSummary": {
    "properties": {
     "key": {
      "type": "string",
      "title": "Key",
      "description": "Stable lookup id; immutable once published."
     },
     "display_name": {
      "type": "string",
      "title": "Display Name",
      "description": "Human-readable name for SDK / UI surfaces."
     },
     "description": {
      "type": "string",
      "title": "Description",
      "description": "What this skill does, \u22641024 chars."
     },
     "container_type": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Container Type",
      "description": "Container/runtime hint, when applicable (e.g. 'docker', 'lambda'). None for generic / inline skills."
     },
     "container_version": {
      "type": "string",
      "title": "Container Version",
      "description": "Version label for the underlying container image.",
      "default": "latest"
     },
     "triggers": {
      "items": {
       "type": "string"
      },
      "type": "array",
      "title": "Triggers",
      "description": "Activation triggers (e.g. 'manual', 'on-tool-call')."
     },
     "tags": {
      "items": {
       "type": "string"
      },
      "type": "array",
      "title": "Tags",
      "description": "Categorization tags (e.g. 'finance', 'compliance')."
     },
     "created_at": {
      "type": "string",
      "title": "Created At"
     },
     "updated_at": {
      "type": "string",
      "title": "Updated At"
     }
    },
    "type": "object",
    "required": [
     "key",
     "display_name",
     "description",
     "created_at",
     "updated_at"
    ],
    "title": "SkillSummary",
    "description": "Returned by `/api/v1/skills` and `/api/v1/skills/{key}`.\n\nSkills are platform-wide \u2014 every tenant sees the same catalog.\nThe `key` is the stable identifier callers reference (e.g. in a\ncustom-agent's `skills` array). Display fields (display_name,\ndescription) are for SDK / dashboard surfacing."
   },
   "SkillUpdate": {
    "properties": {
     "display_name": {
      "anyOf": [
       {
        "type": "string",
        "maxLength": 128
       },
       {
        "type": "null"
       }
      ],
      "title": "Display Name"
     },
     "description": {
      "anyOf": [
       {
        "type": "string",
        "maxLength": 1024
       },
       {
        "type": "null"
       }
      ],
      "title": "Description"
     },
     "container_type": {
      "anyOf": [
       {
        "type": "string",
        "enum": [
         "anthropic",
         "custom"
        ]
       },
       {
        "type": "null"
       }
      ],
      "title": "Container Type"
     },
     "container_skill_id": {
      "anyOf": [
       {
        "type": "string",
        "maxLength": 128
       },
       {
        "type": "null"
       }
      ],
      "title": "Container Skill Id"
     },
     "container_version": {
      "anyOf": [
       {
        "type": "string",
        "maxLength": 64
       },
       {
        "type": "null"
       }
      ],
      "title": "Container Version"
     },
     "container_env_var": {
      "anyOf": [
       {
        "type": "string",
        "maxLength": 128
       },
       {
        "type": "null"
       }
      ],
      "title": "Container Env Var"
     },
     "default_launcher": {
      "anyOf": [
       {
        "type": "string",
        "maxLength": 256
       },
       {
        "type": "null"
       }
      ],
      "title": "Default Launcher"
     },
     "triggers": {
      "anyOf": [
       {
        "items": {
         "type": "string"
        },
        "type": "array"
       },
       {
        "type": "null"
       }
      ],
      "title": "Triggers"
     },
     "tags": {
      "anyOf": [
       {
        "items": {
         "type": "string"
        },
        "type": "array"
       },
       {
        "type": "null"
       }
      ],
      "title": "Tags"
     },
     "resources": {
      "anyOf": [
       {
        "items": {
         "type": "string"
        },
        "type": "array"
       },
       {
        "type": "null"
       }
      ],
      "title": "Resources"
     }
    },
    "type": "object",
    "title": "SkillUpdate"
   },
   "SkillVersionCreate": {
    "properties": {
     "version_label": {
      "type": "string",
      "maxLength": 64,
      "title": "Version Label"
     },
     "metadata": {
      "additionalProperties": true,
      "type": "object",
      "title": "Metadata"
     },
     "markdown": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Markdown"
     }
    },
    "type": "object",
    "required": [
     "version_label"
    ],
    "title": "SkillVersionCreate"
   },
   "SkillVersionRead": {
    "properties": {
     "version_label": {
      "type": "string",
      "maxLength": 64,
      "title": "Version Label"
     },
     "metadata": {
      "additionalProperties": true,
      "type": "object",
      "title": "Metadata"
     },
     "markdown": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Markdown"
     },
     "id": {
      "type": "string",
      "format": "uuid",
      "title": "Id"
     },
     "created_at": {
      "type": "string",
      "format": "date-time",
      "title": "Created At"
     }
    },
    "type": "object",
    "required": [
     "version_label",
     "id",
     "created_at"
    ],
    "title": "SkillVersionRead"
   },
   "SubscriptionResponse": {
    "properties": {
     "plan_name": {
      "type": "string",
      "title": "Plan Name"
     },
     "status": {
      "type": "string",
      "title": "Status"
     },
     "task_quota": {
      "type": "integer",
      "title": "Task Quota"
     },
     "period_tasks_used": {
      "type": "integer",
      "title": "Period Tasks Used"
     },
     "seats": {
      "type": "integer",
      "title": "Seats"
     },
     "billing_period_start": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Billing Period Start"
     },
     "billing_period_end": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Billing Period End"
     }
    },
    "type": "object",
    "required": [
     "plan_name",
     "status",
     "task_quota",
     "period_tasks_used",
     "seats"
    ],
    "title": "SubscriptionResponse"
   },
   "SupportedModelsBlock": {
    "properties": {
     "canonical_ids": {
      "items": {
       "type": "string"
      },
      "type": "array",
      "title": "Canonical Ids",
      "description": "Sorted list of model IDs accepted as-is on `/trigger`."
     },
     "aliases": {
      "additionalProperties": {
       "type": "string"
      },
      "type": "object",
      "title": "Aliases",
      "description": "Friendly alias \u2192 canonical ID. Aliases are case-sensitive."
     },
     "default_model": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Default Model",
      "description": "Deployment default model used when `/trigger.model` is omitted."
     },
     "agent_tool_version": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Agent Tool Version",
      "description": "Configured computer-use tool version for hosted agent-mode jobs."
     },
     "computer_tool_incompatible_model_prefixes": {
      "items": {
       "type": "string"
      },
      "type": "array",
      "title": "Computer Tool Incompatible Model Prefixes",
      "description": "Model ID prefixes rejected for this deployment's computer-use tool version. SDKs should omit `model` or choose another model when an override starts with one of these prefixes."
     }
    },
    "type": "object",
    "required": [
     "canonical_ids",
     "aliases"
    ],
    "title": "SupportedModelsBlock",
    "description": "Sub-shape under `SystemInfoResponse.supported_models`."
   },
   "SystemChangelogResponse": {
    "properties": {
     "current_version": {
      "type": "string",
      "title": "Current Version",
      "description": "The latest version label (matches the top entry's version)."
     },
     "entries": {
      "items": {
       "$ref": "#/components/schemas/ChangelogEntry"
      },
      "type": "array",
      "title": "Entries",
      "description": "Newest-first. SDKs paginate from index 0."
     }
    },
    "type": "object",
    "required": [
     "current_version",
     "entries"
    ],
    "title": "SystemChangelogResponse",
    "description": "Body of `GET /api/v1/system/changelog`."
   },
   "SystemInfoResponse": {
    "properties": {
     "service": {
      "type": "string",
      "title": "Service"
     },
     "api_version": {
      "type": "string",
      "title": "Api Version"
     },
     "environment": {
      "type": "string",
      "title": "Environment"
     },
     "supported_models": {
      "$ref": "#/components/schemas/SupportedModelsBlock"
     },
     "builtin_templates": {
      "items": {
       "type": "string"
      },
      "type": "array",
      "title": "Builtin Templates"
     },
     "features": {
      "additionalProperties": {
       "type": "boolean"
      },
      "type": "object",
      "title": "Features",
      "description": "Feature flags by name \u2192 bool. Stable identifiers; SDK clients branch on the boolean to enable optional code paths."
     }
    },
    "type": "object",
    "required": [
     "service",
     "api_version",
     "environment",
     "supported_models",
     "builtin_templates",
     "features"
    ],
    "title": "SystemInfoResponse",
    "description": "Body of `GET /api/v1/system/info`."
   },
   "SystemLimitsResponse": {
    "properties": {
     "trigger": {
      "additionalProperties": {
       "type": "integer"
      },
      "type": "object",
      "title": "Trigger"
     },
     "batch": {
      "additionalProperties": {
       "type": "integer"
      },
      "type": "object",
      "title": "Batch"
     },
     "tags": {
      "additionalProperties": true,
      "type": "object",
      "title": "Tags"
     },
     "webhooks": {
      "additionalProperties": {
       "type": "integer"
      },
      "type": "object",
      "title": "Webhooks"
     },
     "templates": {
      "additionalProperties": {
       "type": "integer"
      },
      "type": "object",
      "title": "Templates"
     },
     "rate_limit": {
      "additionalProperties": true,
      "type": "object",
      "title": "Rate Limit"
     },
     "cleanup": {
      "additionalProperties": {
       "type": "integer"
      },
      "type": "object",
      "title": "Cleanup"
     },
     "export": {
      "additionalProperties": true,
      "type": "object",
      "title": "Export"
     },
     "cost": {
      "additionalProperties": {
       "type": "number"
      },
      "type": "object",
      "title": "Cost"
     }
    },
    "type": "object",
    "title": "SystemLimitsResponse",
    "description": "Body of `GET /api/v1/system/limits`.\n\nKeys are documented blocks (`trigger`, `batch`, `tags`, ...). Values\ninside each block are free-form numeric/string caps, intentionally\ntyped as `dict[str, Any]` here \u2014 the doc string of the endpoint and\nthe SDK changelog list the exact field names."
   },
   "TagListResponse": {
    "properties": {
     "rows": {
      "items": {
       "$ref": "#/components/schemas/TagSummary"
      },
      "type": "array",
      "title": "Rows",
      "description": "Distinct tag values, sorted by count descending. Empty when the tenant has no tagged jobs."
     },
     "total_unique_tags": {
      "type": "integer",
      "title": "Total Unique Tags"
     }
    },
    "type": "object",
    "required": [
     "rows",
     "total_unique_tags"
    ],
    "title": "TagListResponse",
    "description": "Returned by `GET /api/v1/tags`."
   },
   "TagSummary": {
    "properties": {
     "tag": {
      "type": "string",
      "title": "Tag"
     },
     "count": {
      "type": "integer",
      "title": "Count",
      "description": "Number of jobs carrying this tag."
     }
    },
    "type": "object",
    "required": [
     "tag",
     "count"
    ],
    "title": "TagSummary",
    "description": "One distinct tag value across the tenant's jobs."
   },
   "TemplateCreate": {
    "properties": {
     "name": {
      "type": "string",
      "maxLength": 128,
      "title": "Name"
     },
     "description": {
      "type": "string",
      "maxLength": 256,
      "title": "Description"
     },
     "defaults": {
      "additionalProperties": true,
      "type": "object",
      "title": "Defaults"
     }
    },
    "type": "object",
    "required": [
     "name",
     "description"
    ],
    "title": "TemplateCreate"
   },
   "TemplateDetail": {
    "properties": {
     "name": {
      "type": "string",
      "title": "Name"
     },
     "kind": {
      "type": "string",
      "enum": [
       "builtin",
       "tenant"
      ],
      "title": "Kind"
     },
     "description": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Description"
     },
     "defaults": {
      "additionalProperties": true,
      "type": "object",
      "title": "Defaults",
      "description": "Default `params` merged into every trigger that targets this template. Empty for built-ins."
     }
    },
    "type": "object",
    "required": [
     "name",
     "kind"
    ],
    "title": "TemplateDetail",
    "description": "Full template detail \u2014 adds the `defaults` blob to TemplateInfo."
   },
   "TemplateInfo": {
    "properties": {
     "name": {
      "type": "string",
      "title": "Name",
      "description": "The exact string to pass as `agent_type` on /trigger."
     },
     "kind": {
      "type": "string",
      "enum": [
       "builtin",
       "tenant"
      ],
      "title": "Kind",
      "description": "`builtin` ships with the platform; `tenant` is owned by your org."
     },
     "description": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Description",
      "description": "Human-readable description (tenant templates only)."
     }
    },
    "type": "object",
    "required": [
     "name",
     "kind"
    ],
    "title": "TemplateInfo",
    "description": "One agent_type the caller can target."
   },
   "TemplateRead": {
    "properties": {
     "id": {
      "type": "string",
      "format": "uuid",
      "title": "Id"
     },
     "tenant_id": {
      "type": "string",
      "format": "uuid",
      "title": "Tenant Id"
     },
     "name": {
      "type": "string",
      "title": "Name"
     },
     "description": {
      "type": "string",
      "title": "Description"
     },
     "defaults": {
      "additionalProperties": true,
      "type": "object",
      "title": "Defaults"
     }
    },
    "type": "object",
    "required": [
     "id",
     "tenant_id",
     "name",
     "description",
     "defaults"
    ],
    "title": "TemplateRead"
   },
   "TimelineEvent": {
    "properties": {
     "kind": {
      "type": "string",
      "enum": [
       "job_created",
       "sandbox_ready",
       "tool_call",
       "task_completed",
       "task_failed",
       "task_cancelled"
      ],
      "title": "Kind",
      "description": "Event class. Stable; new kinds may be appended."
     },
     "timestamp": {
      "type": "string",
      "title": "Timestamp",
      "description": "ISO 8601 UTC."
     },
     "summary": {
      "type": "string",
      "title": "Summary",
      "description": "One-line human-readable description."
     },
     "sequence_number": {
      "anyOf": [
       {
        "type": "integer"
       },
       {
        "type": "null"
       }
      ],
      "title": "Sequence Number",
      "description": "For tool_call events, the position in the tool stream."
     },
     "tool_name": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Tool Name",
      "description": "For tool_call events only."
     },
     "duration_ms": {
      "anyOf": [
       {
        "type": "integer"
       },
       {
        "type": "null"
       }
      ],
      "title": "Duration Ms",
      "description": "For tool_call events only."
     },
     "is_error": {
      "type": "boolean",
      "title": "Is Error",
      "description": "True for tool_call rows whose execution errored.",
      "default": false
     }
    },
    "type": "object",
    "required": [
     "kind",
     "timestamp",
     "summary"
    ],
    "title": "TimelineEvent",
    "description": "One annotated event in a job's timeline."
   },
   "TimelineResponse": {
    "properties": {
     "job_id": {
      "type": "string",
      "title": "Job Id"
     },
     "status": {
      "type": "string",
      "title": "Status"
     },
     "events": {
      "items": {
       "$ref": "#/components/schemas/TimelineEvent"
      },
      "type": "array",
      "title": "Events",
      "description": "Chronological. First entry is always job_created."
     }
    },
    "type": "object",
    "required": [
     "job_id",
     "status",
     "events"
    ],
    "title": "TimelineResponse",
    "description": "Returned by `GET /jobs/{id}/timeline`."
   },
   "TokenRequest": {
    "properties": {
     "username": {
      "type": "string",
      "minLength": 1,
      "title": "Username",
      "description": "Username or email"
     },
     "password": {
      "type": "string",
      "minLength": 1,
      "title": "Password",
      "description": "Password"
     },
     "tenant_id": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Tenant Id",
      "description": "Optional tenant identifier"
     }
    },
    "type": "object",
    "required": [
     "username",
     "password"
    ],
    "title": "TokenRequest"
   },
   "TriggerRequest": {
    "properties": {
     "agent_type": {
      "type": "string",
      "title": "Agent Type",
      "description": "Built-in template name (general, analytics_notebook, code_interpreter, jupyter_notebook, outbound_sequence, case_study, slide_deck) or the name of a tenant-owned Template row. Alphanumeric + dash/underscore, \u2264128 chars.",
      "default": "general"
     },
     "instruction": {
      "type": "string",
      "maxLength": 50000,
      "minLength": 1,
      "title": "Instruction",
      "description": "Natural-language task description shown to the agent. Whitespace-only is rejected with 422."
     },
     "params": {
      "additionalProperties": true,
      "type": "object",
      "title": "Params",
      "description": "Free-form template parameters merged into the worker's context. Reserved keys (model, effort_level, max_cost_usd, webhook_url) are populated from the typed fields below."
     },
     "webhook_url": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Webhook Url",
      "description": "Optional one-shot webhook called when the job reaches a terminal state (succeeded / failed). Single best-effort POST, no retries. Provide `webhook_secret` alongside to receive an HMAC-SHA256 signature. Tenants needing reliable delivery should register a tenant webhook via the dashboard instead.",
      "examples": [
       "https://hooks.example.com/cua"
      ]
     },
     "webhook_secret": {
      "anyOf": [
       {
        "type": "string",
        "maxLength": 256,
        "minLength": 16
       },
       {
        "type": "null"
       }
      ],
      "title": "Webhook Secret",
      "description": "Optional shared secret for signing the ad-hoc webhook body. Adds `X-Webhook-Signature: t=<unix>,v1=<hex>` to the delivery where v1 = HMAC-SHA256(secret, f\"{t}.{body}\"). Receivers verify by recomputing the HMAC with the same secret and rejecting deliveries with stale or mismatched signatures. Length 16..256."
     },
     "model": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Model",
      "description": "Pin a provider-compatible model. Claude aliases include haiku / sonnet / opus; agent_mode='openai' accepts gpt-5.6-sol. Canonical IDs are accepted directly. Omit to use the selected provider's default.",
      "examples": [
       "haiku",
       "claude-sonnet-4-6",
       "gpt-5.6-sol"
      ]
     },
     "effort": {
      "anyOf": [
       {
        "type": "string",
        "enum": [
         "low",
         "medium",
         "high",
         "xhigh",
         "max"
        ]
       },
       {
        "type": "null"
       }
      ],
      "title": "Effort",
      "description": "Provider reasoning-effort knob. Accepted values: low, medium, high, xhigh, max. Support depends on the selected model."
     },
     "max_cost_usd": {
      "anyOf": [
       {
        "type": "number",
        "maximum": 1000.0,
        "exclusiveMinimum": 0.0
       },
       {
        "type": "null"
       }
      ],
      "title": "Max Cost Usd",
      "description": "Hard per-job cost ceiling in USD. The worker monitors running cost each iteration; when the cap is crossed the job is cancelled with status='cancelled' before the next API call. Range: (0, 1000].",
      "examples": [
       0.1,
       1.0
      ]
     },
     "agent_mode": {
      "anyOf": [
       {
        "type": "string",
        "enum": [
         "agent",
         "claude",
         "openai",
         "nsr"
        ]
       },
       {
        "type": "null"
       }
      ],
      "title": "Agent Mode",
      "description": "Execution backend. 'agent' (default; alias for 'claude') runs the Anthropic LLM sampling loop. 'openai' runs GPT-5.6 Sol with the Responses API GA computer tool. 'nsr' routes to the local neuro-symbolic engine \u2014 zero API tokens and deterministic."
     },
     "tags": {
      "anyOf": [
       {
        "items": {
         "type": "string"
        },
        "type": "array",
        "maxItems": 20
       },
       {
        "type": "null"
       }
      ],
      "title": "Tags",
      "description": "Free-form labels stored alongside the job. Up to 20 entries, each \u226464 chars, alphanumeric + underscore + dash + colon. Filter on `GET /jobs?tag=<value>` to retrieve a slice.",
      "examples": [
       [
        "env:prod",
        "owner:billing-team"
       ]
      ]
     },
     "outcome_type": {
      "anyOf": [
       {
        "type": "string",
        "enum": [
         "resolved_contact",
         "resolved_return",
         "wismo_resolution",
         "abandoned_cart_recovery",
         "qualified_lead",
         "b2b_reorder",
         "billing_dispute",
         "upsell",
         "pre_purchase_consultation",
         "triage"
        ]
       },
       {
        "type": "null"
       }
      ],
      "title": "Outcome Type",
      "description": "Strategy \u00a74 SKU. Setting this turns the Job into a billable Outcome on success. Choices: resolved_contact ($2), resolved_return ($2), wismo_resolution ($1.50), abandoned_cart_recovery ($3), qualified_lead ($5), b2b_reorder ($5), billing_dispute ($5), upsell ($20), pre_purchase_consultation ($10), triage ($0.50). Order Form may override per-SKU pricing.",
      "examples": [
       "resolved_contact"
      ]
     },
     "inquiry_id": {
      "anyOf": [
       {
        "type": "string",
        "maxLength": 160
       },
       {
        "type": "null"
       }
      ],
      "title": "Inquiry Id",
      "description": "Stable Customer-side identifier for the conversation this Job is working \u2014 typically the upstream system's id (Zendesk ticket, Gorgias conversation, Shopify order). Drives Multi-Touch Consolidation: follow-up Jobs with the same inquiry within the 72h Resolution Window roll up under one billable Outcome (Appendix A.1). Falls back to the Job's UUID if omitted.",
      "examples": [
       "zendesk-12345"
      ]
     },
     "system_of_record_event_id": {
      "anyOf": [
       {
        "type": "string",
        "maxLength": 256
       },
       {
        "type": "null"
       }
      ],
      "title": "System Of Record Event Id",
      "description": "Upstream system-of-record event id proving the Outcome happened (Zendesk ticket id closed, NetSuite RMA id, etc). Required for SoR-bound SKUs (resolved_contact, resolved_return, b2b_reorder, billing_dispute) \u2014 Outcome is not minted without it.",
      "examples": [
       "Z-12345"
      ]
     },
     "triggered_human_handoff": {
      "anyOf": [
       {
        "type": "boolean"
       },
       {
        "type": "null"
       }
      ],
      "title": "Triggered Human Handoff",
      "description": "Set true when the agent escalated to a human. The worker routes such Jobs to a TRIAGE Outcome at $0.50 regardless of the requested SKU (Strategy \u00a74 margin protection)."
     },
     "high_value_action": {
      "anyOf": [
       {
        "type": "boolean"
       },
       {
        "type": "null"
       }
      ],
      "title": "High Value Action",
      "description": "Set true when the resolution involved an Appendix B.3 High-Value Action (refund > threshold, PII modification, subscription/payment-instrument change). Recorded on the Outcome row for audit; a future safety classifier will gate on this flag."
     },
     "completion_criterion": {
      "anyOf": [
       {
        "additionalProperties": true,
        "type": "object"
       },
       {
        "type": "null"
       }
      ],
      "title": "Completion Criterion",
      "description": "Per-SKU proof structure (Appendix A.2). Keys vary by SKU \u2014 resolved_contact accepts ticket_id, reopen_check; wismo_resolution accepts tracking_delivered, session_id, read_receipt; abandoned_cart_recovery accepts order_id, tracked_link, conversion_at; etc. Unrecognized keys are kept under `_unrecognized_keys` rather than rejected.",
      "examples": [
       {
        "reopen_check": true,
        "ticket_id": "Z-12345"
       }
      ]
     },
     "outcome_metadata": {
      "anyOf": [
       {
        "additionalProperties": true,
        "type": "object"
       },
       {
        "type": "null"
       }
      ],
      "title": "Outcome Metadata",
      "description": "Free-form metadata attached to the Outcome row (extra_metadata column). Use for per-customer integration fields you want to surface in the Outcome Accounting Dashboard without polluting completion_criterion."
     },
     "output_schema": {
      "anyOf": [
       {
        "additionalProperties": true,
        "type": "object"
       },
       {
        "type": "null"
       }
      ],
      "title": "Output Schema",
      "description": "Optional JSON Schema constraining the agent's final output. When set, the worker injects a system-prompt directive instructing the agent to emit a single JSON object matching this schema. Validation is currently caller-side \u2014 pull `summary` and `jsonschema.validate()` against it; full agent-side enforcement is a roadmap item. Schemas larger than 8 KB serialised are rejected."
     }
    },
    "type": "object",
    "required": [
     "instruction"
    ],
    "title": "TriggerRequest",
    "description": "Body for `POST /api/v1/trigger`.",
    "example": {
     "agent_type": "general",
     "effort": "low",
     "instruction": "Open https://example.com and report the page title.",
     "max_cost_usd": 0.1,
     "model": "haiku",
     "webhook_url": "https://hooks.example.com/cua"
    }
   },
   "TriggerResponse": {
    "properties": {
     "job_id": {
      "type": "string",
      "title": "Job Id",
      "description": "UUID of the queued job. Use it for subsequent /jobs/:id calls."
     },
     "status": {
      "type": "string",
      "title": "Status",
      "description": "Initial job status \u2014 usually 'queued'. Replays of an idempotent request return the existing job's current status."
     }
    },
    "type": "object",
    "required": [
     "job_id",
     "status"
    ],
    "title": "TriggerResponse",
    "description": "Returned by `POST /api/v1/trigger` after queueing a job."
   },
   "UpdateAPIKeyRequest": {
    "properties": {
     "name": {
      "anyOf": [
       {
        "type": "string",
        "maxLength": 128,
        "minLength": 1
       },
       {
        "type": "null"
       }
      ],
      "title": "Name"
     },
     "scopes": {
      "anyOf": [
       {
        "items": {
         "type": "string"
        },
        "type": "array"
       },
       {
        "type": "null"
       }
      ],
      "title": "Scopes"
     },
     "rate_limit_per_minute": {
      "anyOf": [
       {
        "type": "integer",
        "maximum": 10000.0,
        "minimum": 1.0
       },
       {
        "type": "null"
       }
      ],
      "title": "Rate Limit Per Minute"
     },
     "is_active": {
      "anyOf": [
       {
        "type": "boolean"
       },
       {
        "type": "null"
       }
      ],
      "title": "Is Active"
     }
    },
    "type": "object",
    "title": "UpdateAPIKeyRequest",
    "description": "Body for `PATCH /api/v1/keys/{id}`. All fields optional."
   },
   "UpdateEndpointRequest": {
    "properties": {
     "url": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Url"
     },
     "events": {
      "anyOf": [
       {
        "items": {
         "type": "string"
        },
        "type": "array"
       },
       {
        "type": "null"
       }
      ],
      "title": "Events"
     },
     "is_active": {
      "anyOf": [
       {
        "type": "boolean"
       },
       {
        "type": "null"
       }
      ],
      "title": "Is Active"
     }
    },
    "type": "object",
    "title": "UpdateEndpointRequest"
   },
   "UpdateJobTagsRequest": {
    "properties": {
     "tags": {
      "items": {
       "type": "string"
      },
      "type": "array",
      "maxItems": 20,
      "title": "Tags",
      "description": "Replacement tag list. Pass an empty array to clear tags. Same per-tag rules as `TriggerRequest.tags`."
     }
    },
    "type": "object",
    "required": [
     "tags"
    ],
    "title": "UpdateJobTagsRequest",
    "description": "Body for `PATCH /api/v1/jobs/{id}/tags`."
   },
   "UpdateStatusRequest": {
    "properties": {
     "status": {
      "type": "string",
      "title": "Status"
     },
     "error_message": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Error Message"
     }
    },
    "type": "object",
    "required": [
     "status"
    ],
    "title": "UpdateStatusRequest",
    "description": "Request to update session status."
   },
   "UpdateTemplateRequest": {
    "properties": {
     "description": {
      "anyOf": [
       {
        "type": "string",
        "maxLength": 256,
        "minLength": 1
       },
       {
        "type": "null"
       }
      ],
      "title": "Description",
      "description": "New description; omit to leave unchanged."
     },
     "defaults": {
      "anyOf": [
       {
        "additionalProperties": true,
        "type": "object"
       },
       {
        "type": "null"
       }
      ],
      "title": "Defaults",
      "description": "New defaults dict. Replaces the entire defaults blob \u2014 pass the merged result, not a partial. Omit to leave unchanged."
     }
    },
    "type": "object",
    "title": "UpdateTemplateRequest",
    "description": "Body for `PATCH /api/v1/templates/{name}`. All fields optional \u2014\nomitting a field leaves the existing value untouched."
   },
   "UpdateUserRequest": {
    "properties": {
     "role": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Role",
      "description": "New role for the user"
     }
    },
    "type": "object",
    "title": "UpdateUserRequest"
   },
   "UpdateWebhookEndpointRequest": {
    "properties": {
     "url": {
      "anyOf": [
       {
        "type": "string",
        "maxLength": 512
       },
       {
        "type": "null"
       }
      ],
      "title": "Url"
     },
     "events": {
      "anyOf": [
       {
        "items": {
         "type": "string"
        },
        "type": "array"
       },
       {
        "type": "null"
       }
      ],
      "title": "Events"
     },
     "is_active": {
      "anyOf": [
       {
        "type": "boolean"
       },
       {
        "type": "null"
       }
      ],
      "title": "Is Active"
     }
    },
    "type": "object",
    "title": "UpdateWebhookEndpointRequest",
    "description": "Body for `PATCH /api/v1/webhooks/{id}`. All fields optional."
   },
   "UsageByTemplateResponse": {
    "properties": {
     "rows": {
      "items": {
       "$ref": "#/components/schemas/UsageByTemplateRow"
      },
      "type": "array",
      "title": "Rows",
      "description": "Sorted by cost descending. Empty when the tenant has no usage."
     },
     "total_jobs": {
      "type": "integer",
      "title": "Total Jobs"
     },
     "total_tokens": {
      "type": "integer",
      "title": "Total Tokens"
     },
     "total_cost_usd": {
      "type": "number",
      "title": "Total Cost Usd"
     }
    },
    "type": "object",
    "required": [
     "rows",
     "total_jobs",
     "total_tokens",
     "total_cost_usd"
    ],
    "title": "UsageByTemplateResponse",
    "description": "Returned by `GET /api/v1/usage/by-template`."
   },
   "UsageByTemplateRow": {
    "properties": {
     "template": {
      "type": "string",
      "title": "Template",
      "description": "`agent_type` value (built-in or tenant-owned)."
     },
     "jobs": {
      "type": "integer",
      "title": "Jobs"
     },
     "tokens": {
      "type": "integer",
      "title": "Tokens"
     },
     "cost_usd": {
      "type": "number",
      "title": "Cost Usd"
     }
    },
    "type": "object",
    "required": [
     "template",
     "jobs",
     "tokens",
     "cost_usd"
    ],
    "title": "UsageByTemplateRow",
    "description": "One agent_type's contribution to total tenant spend."
   },
   "UsageByToolResponse": {
    "properties": {
     "rows": {
      "items": {
       "$ref": "#/components/schemas/UsageByToolRow"
      },
      "type": "array",
      "title": "Rows",
      "description": "Sorted by total_duration_ms descending \u2014 heaviest tool first."
     },
     "total_calls": {
      "type": "integer",
      "title": "Total Calls"
     }
    },
    "type": "object",
    "required": [
     "rows",
     "total_calls"
    ],
    "title": "UsageByToolResponse",
    "description": "Returned by `GET /api/v1/usage/by-tool`."
   },
   "UsageByToolRow": {
    "properties": {
     "tool_name": {
      "type": "string",
      "title": "Tool Name",
      "description": "Tool identifier (bash, computer, browser, ...)."
     },
     "calls": {
      "type": "integer",
      "title": "Calls",
      "description": "Total invocations across all jobs."
     },
     "total_duration_ms": {
      "type": "integer",
      "title": "Total Duration Ms",
      "description": "Sum of duration_ms across calls."
     },
     "avg_duration_ms": {
      "type": "number",
      "title": "Avg Duration Ms",
      "description": "Mean duration per call."
     },
     "error_calls": {
      "type": "integer",
      "title": "Error Calls",
      "description": "Count of calls whose tool_output starts with an 'error' marker \u2014 best-effort heuristic, not a strict success/fail classification."
     }
    },
    "type": "object",
    "required": [
     "tool_name",
     "calls",
     "total_duration_ms",
     "avg_duration_ms",
     "error_calls"
    ],
    "title": "UsageByToolRow",
    "description": "One tool's contribution to total tenant work."
   },
   "UsageTrendBucket": {
    "properties": {
     "date": {
      "type": "string",
      "title": "Date",
      "description": "ISO 8601 calendar date (UTC)."
     },
     "jobs": {
      "type": "integer",
      "title": "Jobs",
      "description": "Count of billed runs that completed on this day."
     },
     "tokens": {
      "type": "integer",
      "title": "Tokens",
      "description": "Sum of input + output tokens."
     },
     "cost_usd": {
      "type": "number",
      "title": "Cost Usd",
      "description": "Total billed cost in USD."
     }
    },
    "type": "object",
    "required": [
     "date",
     "jobs",
     "tokens",
     "cost_usd"
    ],
    "title": "UsageTrendBucket",
    "description": "One day's roll-up in a usage trend response."
   },
   "UsageTrendResponse": {
    "properties": {
     "period": {
      "type": "string",
      "title": "Period",
      "description": "The window queried ('7d', '30d', '90d')."
     },
     "start_date": {
      "type": "string",
      "title": "Start Date"
     },
     "end_date": {
      "type": "string",
      "title": "End Date"
     },
     "buckets": {
      "items": {
       "$ref": "#/components/schemas/UsageTrendBucket"
      },
      "type": "array",
      "title": "Buckets",
      "description": "Day-by-day rollup, oldest first, with zero-filled rows for dates that had no activity. Length always equals the period in days."
     }
    },
    "type": "object",
    "required": [
     "period",
     "start_date",
     "end_date",
     "buckets"
    ],
    "title": "UsageTrendResponse",
    "description": "Returned by `GET /api/v1/usage/trend`."
   },
   "UserProfile": {
    "properties": {
     "user_id": {
      "type": "string",
      "title": "User Id"
     },
     "tenant_id": {
      "type": "string",
      "title": "Tenant Id"
     },
     "email": {
      "type": "string",
      "title": "Email"
     },
     "name": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Name"
     },
     "role": {
      "type": "string",
      "title": "Role"
     }
    },
    "type": "object",
    "required": [
     "user_id",
     "tenant_id",
     "email",
     "name",
     "role"
    ],
    "title": "UserProfile"
   },
   "UserRead": {
    "properties": {
     "id": {
      "type": "string",
      "title": "Id"
     },
     "email": {
      "type": "string",
      "title": "Email"
     },
     "name": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Name"
     },
     "role": {
      "type": "string",
      "title": "Role"
     },
     "last_login_at": {
      "anyOf": [
       {
        "type": "string",
        "format": "date-time"
       },
       {
        "type": "null"
       }
      ],
      "title": "Last Login At"
     },
     "created_at": {
      "type": "string",
      "format": "date-time",
      "title": "Created At"
     }
    },
    "type": "object",
    "required": [
     "id",
     "email",
     "name",
     "role",
     "last_login_at",
     "created_at"
    ],
    "title": "UserRead"
   },
   "ValidationError": {
    "properties": {
     "loc": {
      "items": {
       "anyOf": [
        {
         "type": "string"
        },
        {
         "type": "integer"
        }
       ]
      },
      "type": "array",
      "title": "Location"
     },
     "msg": {
      "type": "string",
      "title": "Message"
     },
     "type": {
      "type": "string",
      "title": "Error Type"
     }
    },
    "type": "object",
    "required": [
     "loc",
     "msg",
     "type"
    ],
    "title": "ValidationError"
   },
   "WaitJobRequest": {
    "properties": {
     "timeout_seconds": {
      "type": "integer",
      "maximum": 60.0,
      "minimum": 1.0,
      "title": "Timeout Seconds",
      "description": "How long to block before returning the current state. 1..60 seconds. The endpoint returns as soon as the job reaches a terminal status, so this is only the upper bound.",
      "default": 30
     }
    },
    "type": "object",
    "title": "WaitJobRequest",
    "description": "Body for `POST /api/v1/jobs/{id}/wait`."
   },
   "WaitJobResponse": {
    "properties": {
     "job_id": {
      "type": "string",
      "title": "Job Id"
     },
     "status": {
      "type": "string",
      "title": "Status"
     },
     "is_terminal": {
      "type": "boolean",
      "title": "Is Terminal",
      "description": "True if the job reached `succeeded`/`failed`/`cancelled` before the timeout. False means the timeout fired and the returned status is still in-flight."
     },
     "waited_seconds": {
      "type": "number",
      "title": "Waited Seconds",
      "description": "Wall-clock seconds spent blocking inside the handler."
     },
     "summary": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Summary"
     },
     "error": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Error"
     },
     "cost_usd": {
      "anyOf": [
       {
        "type": "number"
       },
       {
        "type": "null"
       }
      ],
      "title": "Cost Usd"
     }
    },
    "type": "object",
    "required": [
     "job_id",
     "status",
     "is_terminal",
     "waited_seconds"
    ],
    "title": "WaitJobResponse",
    "description": "Returned by `POST /api/v1/jobs/{id}/wait`."
   },
   "WebhookDeliverySummary": {
    "properties": {
     "id": {
      "type": "string",
      "title": "Id"
     },
     "endpoint_id": {
      "type": "string",
      "title": "Endpoint Id"
     },
     "event_type": {
      "type": "string",
      "title": "Event Type"
     },
     "status": {
      "type": "string",
      "title": "Status",
      "description": "pending | success | failed"
     },
     "response_code": {
      "anyOf": [
       {
        "type": "integer"
       },
       {
        "type": "null"
       }
      ],
      "title": "Response Code",
      "description": "HTTP status from the receiver, if a response was received."
     },
     "attempts": {
      "type": "integer",
      "title": "Attempts",
      "description": "Total attempts so far (1..3)."
     },
     "next_retry_at": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Next Retry At",
      "description": "Scheduled retry time, ISO 8601 UTC, when status == 'failed'."
     },
     "created_at": {
      "type": "string",
      "title": "Created At"
     }
    },
    "type": "object",
    "required": [
     "id",
     "endpoint_id",
     "event_type",
     "status",
     "attempts",
     "created_at"
    ],
    "title": "WebhookDeliverySummary",
    "description": "One delivery attempt against a registered webhook endpoint."
   },
   "WebhookEndpointSummary": {
    "properties": {
     "id": {
      "type": "string",
      "title": "Id"
     },
     "url": {
      "type": "string",
      "title": "Url"
     },
     "events": {
      "items": {
       "type": "string"
      },
      "type": "array",
      "title": "Events"
     },
     "is_active": {
      "type": "boolean",
      "title": "Is Active"
     },
     "created_at": {
      "type": "string",
      "title": "Created At"
     },
     "updated_at": {
      "type": "string",
      "title": "Updated At"
     }
    },
    "type": "object",
    "required": [
     "id",
     "url",
     "events",
     "is_active",
     "created_at",
     "updated_at"
    ],
    "title": "WebhookEndpointSummary",
    "description": "Public-safe view of a webhook endpoint."
   },
   "WebhookEndpointWithSecret": {
    "properties": {
     "id": {
      "type": "string",
      "title": "Id"
     },
     "url": {
      "type": "string",
      "title": "Url"
     },
     "events": {
      "items": {
       "type": "string"
      },
      "type": "array",
      "title": "Events"
     },
     "is_active": {
      "type": "boolean",
      "title": "Is Active"
     },
     "created_at": {
      "type": "string",
      "title": "Created At"
     },
     "updated_at": {
      "type": "string",
      "title": "Updated At"
     },
     "secret": {
      "type": "string",
      "title": "Secret",
      "description": "HMAC-SHA256 signing secret. Compare incoming X-Webhook-Signature against `HMAC(secret, f\"{t}.{body}\")`."
     }
    },
    "type": "object",
    "required": [
     "id",
     "url",
     "events",
     "is_active",
     "created_at",
     "updated_at",
     "secret"
    ],
    "title": "WebhookEndpointWithSecret",
    "description": "Same as summary but includes the signing secret. Returned only at\ncreate-time and on explicit `?include_secret=true` reads \u2014 exposing\nevery list response would defeat the secret's purpose."
   },
   "WebhookEventDescriptor": {
    "properties": {
     "name": {
      "type": "string",
      "title": "Name",
      "description": "The `event_type` string surfaced on every webhook delivery."
     },
     "description": {
      "type": "string",
      "title": "Description"
     },
     "when_fires": {
      "type": "string",
      "title": "When Fires",
      "description": "Human-readable trigger condition."
     },
     "payload_fields": {
      "items": {
       "type": "string"
      },
      "type": "array",
      "title": "Payload Fields",
      "description": "Top-level fields receivers can rely on (in addition to the envelope fields `event_id`, `event_type`, `event_timestamp`, `api_version`)."
     }
    },
    "type": "object",
    "required": [
     "name",
     "description",
     "when_fires",
     "payload_fields"
    ],
    "title": "WebhookEventDescriptor",
    "description": "One row in the webhook event catalog."
   },
   "WebhookEventsResponse": {
    "properties": {
     "api_version": {
      "type": "string",
      "title": "Api Version",
      "description": "Schema version of the envelope (matches `api_version` on every delivery)."
     },
     "envelope_fields": {
      "items": {
       "type": "string"
      },
      "type": "array",
      "title": "Envelope Fields",
      "description": "Fields injected by the webhook envelope on every delivery."
     },
     "events": {
      "items": {
       "$ref": "#/components/schemas/WebhookEventDescriptor"
      },
      "type": "array",
      "title": "Events",
      "description": "Every event_type the platform may emit."
     },
     "subscription_wildcard": {
      "type": "string",
      "title": "Subscription Wildcard",
      "description": "When subscribing to a webhook endpoint, this token in the `events` array means 'all event types'."
     }
    },
    "type": "object",
    "required": [
     "api_version",
     "envelope_fields",
     "events",
     "subscription_wildcard"
    ],
    "title": "WebhookEventsResponse",
    "description": "Body of `GET /api/v1/system/webhook-events`."
   },
   "WebhookTestRequest": {
    "properties": {
     "url": {
      "type": "string",
      "title": "Url",
      "description": "Webhook URL to probe. http or https only."
     },
     "secret": {
      "anyOf": [
       {
        "type": "string",
        "maxLength": 256,
        "minLength": 16
       },
       {
        "type": "null"
       }
      ],
      "title": "Secret",
      "description": "Optional shared secret. When set, the probe carries an `X-Webhook-Signature` header signed with the same scheme as production deliveries."
     }
    },
    "type": "object",
    "required": [
     "url"
    ],
    "title": "WebhookTestRequest",
    "description": "Body for `POST /api/v1/webhook-test`."
   },
   "WebhookTestResponse": {
    "properties": {
     "delivered": {
      "type": "boolean",
      "title": "Delivered",
      "description": "True iff the receiver returned 2xx."
     },
     "status_code": {
      "anyOf": [
       {
        "type": "integer"
       },
       {
        "type": "null"
       }
      ],
      "title": "Status Code",
      "description": "HTTP status the receiver returned. None when the request could not complete (network error, timeout)."
     },
     "duration_ms": {
      "type": "integer",
      "title": "Duration Ms",
      "description": "Wall-clock time the probe took, in milliseconds."
     },
     "error": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Error",
      "description": "Network / timeout error message when delivery failed."
     }
    },
    "type": "object",
    "required": [
     "delivered",
     "duration_ms"
    ],
    "title": "WebhookTestResponse",
    "description": "Outcome of a webhook probe."
   },
   "WhoamiResponse": {
    "properties": {
     "tenant_id": {
      "type": "string",
      "title": "Tenant Id"
     },
     "api_key_id": {
      "type": "string",
      "title": "Api Key Id"
     },
     "user_id": {
      "type": "string",
      "title": "User Id"
     },
     "scopes": {
      "items": {
       "type": "string"
      },
      "type": "array",
      "title": "Scopes"
     },
     "is_admin": {
      "type": "boolean",
      "title": "Is Admin",
      "description": "Convenience flag: true iff `admin` is in the key's scope set. Admin keys can manage other keys, webhooks, and templates."
     }
    },
    "type": "object",
    "required": [
     "tenant_id",
     "api_key_id",
     "user_id",
     "scopes",
     "is_admin"
    ],
    "title": "WhoamiResponse",
    "description": "Returned by `GET /api/v1/auth/whoami` \u2014 effective auth context."
   },
   "app__api__routes__agi_sessions__SessionResponse": {
    "properties": {
     "id": {
      "type": "integer",
      "title": "Id"
     },
     "session_id": {
      "type": "string",
      "title": "Session Id"
     },
     "job_id": {
      "type": "integer",
      "title": "Job Id"
     },
     "tenant_id": {
      "type": "integer",
      "title": "Tenant Id"
     },
     "agent_name": {
      "type": "string",
      "title": "Agent Name"
     },
     "vnc_url": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Vnc Url"
     },
     "status": {
      "type": "string",
      "title": "Status"
     },
     "task_description": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Task Description"
     },
     "result_summary": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Result Summary"
     },
     "total_messages": {
      "type": "integer",
      "title": "Total Messages"
     },
     "total_api_calls": {
      "type": "integer",
      "title": "Total Api Calls"
     },
     "execution_time_seconds": {
      "anyOf": [
       {
        "type": "integer"
       },
       {
        "type": "null"
       }
      ],
      "title": "Execution Time Seconds"
     },
     "error_message": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Error Message"
     },
     "error_count": {
      "type": "integer",
      "title": "Error Count"
     },
     "created_at": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Created At"
     },
     "started_at": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Started At"
     },
     "completed_at": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Completed At"
     }
    },
    "type": "object",
    "required": [
     "id",
     "session_id",
     "job_id",
     "tenant_id",
     "agent_name",
     "vnc_url",
     "status",
     "task_description",
     "result_summary",
     "total_messages",
     "total_api_calls",
     "execution_time_seconds",
     "error_message",
     "error_count",
     "created_at",
     "started_at",
     "completed_at"
    ],
    "title": "SessionResponse",
    "description": "AGI session response."
   },
   "app__api__routes__auth__SessionResponse": {
    "properties": {
     "authenticated": {
      "type": "boolean",
      "title": "Authenticated",
      "default": true
     },
     "token_type": {
      "type": "string",
      "title": "Token Type",
      "default": "cookie"
     }
    },
    "type": "object",
    "title": "SessionResponse"
   },
   "app__api__routes__billing__UsageResponse": {
    "properties": {
     "total_jobs": {
      "type": "integer",
      "title": "Total Jobs"
     },
     "total_tokens": {
      "type": "integer",
      "title": "Total Tokens"
     },
     "total_cost_usd": {
      "type": "number",
      "title": "Total Cost Usd"
     },
     "period_tasks_used": {
      "type": "integer",
      "title": "Period Tasks Used"
     },
     "task_quota": {
      "type": "integer",
      "title": "Task Quota"
     },
     "records": {
      "items": {
       "additionalProperties": true,
       "type": "object"
      },
      "type": "array",
      "title": "Records"
     }
    },
    "type": "object",
    "required": [
     "total_jobs",
     "total_tokens",
     "total_cost_usd",
     "period_tasks_used",
     "task_quota",
     "records"
    ],
    "title": "UsageResponse"
   },
   "app__api__routes__replay__ToolExecutionResponse": {
    "properties": {
     "id": {
      "type": "string",
      "title": "Id"
     },
     "sequence_number": {
      "type": "integer",
      "title": "Sequence Number"
     },
     "tool_name": {
      "type": "string",
      "title": "Tool Name"
     },
     "tool_input": {
      "additionalProperties": true,
      "type": "object",
      "title": "Tool Input"
     },
     "tool_output": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Tool Output"
     },
     "screenshot_key": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Screenshot Key"
     },
     "thinking_summary": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Thinking Summary"
     },
     "duration_ms": {
      "anyOf": [
       {
        "type": "integer"
       },
       {
        "type": "null"
       }
      ],
      "title": "Duration Ms"
     },
     "created_at": {
      "type": "string",
      "title": "Created At"
     }
    },
    "type": "object",
    "required": [
     "id",
     "sequence_number",
     "tool_name",
     "tool_input",
     "tool_output",
     "screenshot_key",
     "thinking_summary",
     "duration_ms",
     "created_at"
    ],
    "title": "ToolExecutionResponse"
   },
   "app__api__routes__v1__trigger__ToolExecutionResponse": {
    "properties": {
     "id": {
      "type": "string",
      "title": "Id"
     },
     "sequence_number": {
      "type": "integer",
      "title": "Sequence Number"
     },
     "tool_name": {
      "type": "string",
      "title": "Tool Name"
     },
     "tool_input": {
      "additionalProperties": true,
      "type": "object",
      "title": "Tool Input"
     },
     "tool_output": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Tool Output"
     },
     "screenshot_key": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Screenshot Key"
     },
     "thinking_summary": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Thinking Summary"
     },
     "duration_ms": {
      "anyOf": [
       {
        "type": "integer"
       },
       {
        "type": "null"
       }
      ],
      "title": "Duration Ms"
     },
     "created_at": {
      "type": "string",
      "title": "Created At"
     }
    },
    "type": "object",
    "required": [
     "id",
     "sequence_number",
     "tool_name",
     "tool_input",
     "tool_output",
     "screenshot_key",
     "thinking_summary",
     "duration_ms",
     "created_at"
    ],
    "title": "ToolExecutionResponse",
    "description": "One step in a job's tool-call timeline."
   },
   "app__api__routes__v1__trigger__UsageResponse": {
    "properties": {
     "total_jobs": {
      "type": "integer",
      "title": "Total Jobs"
     },
     "total_tokens": {
      "type": "integer",
      "title": "Total Tokens"
     },
     "total_cost_usd": {
      "type": "number",
      "title": "Total Cost Usd"
     },
     "period_tasks_used": {
      "type": "integer",
      "title": "Period Tasks Used"
     },
     "task_quota": {
      "type": "integer",
      "title": "Task Quota"
     },
     "period_cost_usd": {
      "type": "number",
      "title": "Period Cost Usd"
     },
     "by_status": {
      "additionalProperties": {
       "type": "integer"
      },
      "type": "object",
      "title": "By Status"
     },
     "billing_period_start": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Billing Period Start"
     },
     "billing_period_end": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Billing Period End"
     }
    },
    "type": "object",
    "required": [
     "total_jobs",
     "total_tokens",
     "total_cost_usd",
     "period_tasks_used",
     "task_quota",
     "period_cost_usd",
     "by_status",
     "billing_period_start",
     "billing_period_end"
    ],
    "title": "UsageResponse",
    "description": "Tenant usage rollup. Lifetime + current-billing-period breakdowns."
   }
  },
  "securitySchemes": {
   "api_key": {
    "type": "apiKey",
    "in": "header",
    "name": "X-API-Key",
    "description": "Tenant API key, issued at POST /api/v1/keys"
   }
  }
 },
 "servers": [
  {
   "url": "https://api.computer.stateset.app"
  }
 ],
 "security": [
  {
   "api_key": []
  }
 ]
}