{
  "openapi": "3.1.0",
  "info": {
    "title": "Mubit management API",
    "version": "1.0.0",
    "description": "The management API reads and changes your Mubit organization from code: its projects, keys, calls, tasks,\nadapter versions, lessons, imports, usage and billing. It answers under `https://api.mubit.ai/api/v1`.\n\nAuthenticate with a management key, which starts with `mwm_`, in `Authorization: Bearer <key>`. An organization\nadmin creates management keys in the console. A management key has a role, `read`, `member` or `admin`, and can be\nbound to one project.\n\nThis document lists only the operations the API serves today."
  },
  "servers": [
    {
      "url": "https://api.mubit.ai"
    }
  ],
  "security": [
    {
      "BearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "Org",
      "description": "Your organization."
    },
    {
      "name": "Keys",
      "description": "The inference keys of your organization (read only)."
    },
    {
      "name": "Management Keys",
      "description": "The keys that sign management API calls."
    },
    {
      "name": "Providers",
      "description": "The provider keys your organization added (read only; the keys themselves are never returned)."
    },
    {
      "name": "Projects",
      "description": "The projects of your organization."
    },
    {
      "name": "Calls",
      "description": "The model calls Mubit recorded, and ratings on them."
    },
    {
      "name": "Tasks",
      "description": "The tasks Mubit found in your calls, and their training examples."
    },
    {
      "name": "Fine-tuning",
      "description": "A task's training settings, and starting a training run."
    },
    {
      "name": "Versions",
      "description": "The adapter versions of a task, and moving them through promotion."
    },
    {
      "name": "Lessons",
      "description": "The lessons runtime calibration distilled."
    },
    {
      "name": "Data Ingestion",
      "description": "Imports of past calls."
    },
    {
      "name": "Usage & Billing",
      "description": "Usage figures and billing status."
    },
    {
      "name": "Activity",
      "description": "The activity feed of your projects."
    },
    {
      "name": "Jobs",
      "description": "Long-running work, such as a training run."
    }
  ],
  "paths": {
    "/api/v1/org": {
      "get": {
        "operationId": "getOrg",
        "tags": [
          "Org"
        ],
        "summary": "Get organization details",
        "description": "Returns the authenticated organization metadata and settings.\n\nRole: `read` or higher.",
        "responses": {
          "200": {
            "description": "Organization details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Org"
                },
                "example": {
                  "id": "org_alpha",
                  "name": "Acme Corporation",
                  "slug": "acme",
                  "created_at": "2026-10-26T12:00:00Z",
                  "plan": "enterprise"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v1/keys": {
      "get": {
        "operationId": "listKeys",
        "tags": [
          "Keys"
        ],
        "summary": "List inference keys",
        "description": "Lists the organization's inference keys, active and revoked. The secrets are never returned.\n\nRole: `read` or higher.",
        "parameters": [
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          }
        ],
        "responses": {
          "200": {
            "description": "List of inference keys",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KeyListResponse"
                },
                "example": {
                  "data": [
                    {
                      "id": "key_abc123",
                      "name": "Production key",
                      "prefix": "mbt_prod_",
                      "role": "user",
                      "project": "prj_prod",
                      "status": "active",
                      "created_at": "2026-10-01T00:00:00Z",
                      "expires_at": "2027-01-01T00:00:00Z"
                    }
                  ],
                  "next_cursor": null
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v1/management-keys": {
      "get": {
        "operationId": "listManagementKeys",
        "tags": [
          "Management Keys"
        ],
        "summary": "List management keys",
        "description": "Lists the organization's management keys, newest first, up to `limit`. The secrets are never returned.\n\nRole: `admin`.",
        "parameters": [
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          }
        ],
        "responses": {
          "200": {
            "description": "List of management keys",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ManagementKeyListResponse"
                },
                "example": {
                  "data": [
                    {
                      "id": "mkey_012345",
                      "name": "CI Runner Key",
                      "role": "member",
                      "project": "prj_ci",
                      "status": "active",
                      "created_at": "2026-10-10T00:00:00Z",
                      "last_used_at": "2026-10-25T18:22:00Z"
                    }
                  ],
                  "next_cursor": null
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      },
      "post": {
        "operationId": "createManagementKey",
        "tags": [
          "Management Keys"
        ],
        "summary": "Create management key",
        "description": "Creates a management key. The answer holds the key's secret in `key`, once: store it then. The role can't be higher than the role of the key that creates it (`403 role_ceiling`). With `project`, the key reaches only that project. With `expires_at` (an RFC 3339 time in the future), the key stops working then.\n\nRole: `admin`.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKeyHeader"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateManagementKeyRequest"
              },
              "example": {
                "name": "Deployment Agent",
                "role": "admin",
                "project": null
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Management key created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateManagementKeyResponse"
                },
                "example": {
                  "id": "mkey_987654",
                  "name": "Deployment Agent",
                  "key": "mwm_inst_987654_secrettoken0123456789",
                  "role": "admin",
                  "project": null,
                  "status": "active",
                  "created_at": "2026-10-26T12:00:00Z"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v1/management-keys/{key_id}/rotate": {
      "post": {
        "operationId": "rotateManagementKey",
        "tags": [
          "Management Keys"
        ],
        "summary": "Rotate management key",
        "description": "Gives a management key a new secret, in `key`, once. The old secret stops working within a minute. A key can rotate itself and the keys made with it, never a key of a higher role (`403 role_ceiling`) or another key (`403 forbidden`). A revoked key can't be rotated (`409 state_conflict`).\n\nRole: `admin`.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKeyHeader"
          },
          {
            "name": "key_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Rotated management key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateManagementKeyResponse"
                },
                "example": {
                  "id": "mkey_987654",
                  "name": "Deployment Agent",
                  "key": "mwm_inst_987654_newsecrettoken9876543",
                  "role": "admin",
                  "project": null,
                  "status": "active",
                  "created_at": "2026-10-26T12:00:00Z"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v1/management-keys/{key_id}": {
      "delete": {
        "operationId": "revokeManagementKey",
        "tags": [
          "Management Keys"
        ],
        "summary": "Revoke management key",
        "description": "Revokes a management key. It stops working within a minute, and can't be used again.\n\nRole: `admin`.",
        "parameters": [
          {
            "name": "key_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Management key revoked",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "id",
                    "status"
                  ],
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "revoked"
                      ]
                    }
                  }
                },
                "example": {
                  "id": "mkey_987654",
                  "status": "revoked"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v1/providers": {
      "get": {
        "operationId": "listProviders",
        "tags": [
          "Providers"
        ],
        "summary": "List provider keys",
        "description": "Lists the provider keys the organization added. The keys themselves are never returned.\n\nRole: `read` or higher.",
        "responses": {
          "200": {
            "description": "Configured providers",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProviderListResponse"
                },
                "example": {
                  "data": [
                    {
                      "provider": "openai",
                      "status": "active",
                      "created_at": "2026-10-01T00:00:00Z",
                      "updated_at": "2026-10-15T00:00:00Z"
                    },
                    {
                      "provider": "anthropic",
                      "status": "active",
                      "created_at": "2026-10-05T00:00:00Z",
                      "updated_at": "2026-10-20T00:00:00Z"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v1/projects": {
      "get": {
        "operationId": "listProjects",
        "tags": [
          "Projects"
        ],
        "summary": "List projects",
        "description": "Lists projects within the organization.\n\nRole: `read` or higher.",
        "parameters": [
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          }
        ],
        "responses": {
          "200": {
            "description": "List of projects",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectListResponse"
                },
                "example": {
                  "data": [
                    {
                      "id": "prj_default",
                      "name": "Default Project",
                      "slug": "default",
                      "environment": "production",
                      "created_at": "2026-10-01T00:00:00Z"
                    }
                  ],
                  "next_cursor": null
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v1/projects/{project_id}": {
      "get": {
        "operationId": "getProject",
        "tags": [
          "Projects"
        ],
        "summary": "Get project details",
        "description": "Retrieves details of a specific project.\n\nRole: `read` or higher.",
        "parameters": [
          {
            "name": "project_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Project details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Project"
                },
                "example": {
                  "id": "prj_payments123",
                  "name": "Payments",
                  "slug": "payments",
                  "environment": "production",
                  "created_at": "2026-10-26T12:00:00Z"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v1/calls": {
      "get": {
        "operationId": "listCalls",
        "tags": [
          "Calls"
        ],
        "summary": "List calls",
        "description": "Lists the recorded calls, newest first. Filter by project, model, status and time.\n\nRole: `read` or higher.",
        "parameters": [
          {
            "name": "project",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "model",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "ok",
                "error",
                "discarded"
              ]
            }
          },
          {
            "name": "created_after",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "created_before",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          }
        ],
        "responses": {
          "200": {
            "description": "List of calls",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CallListResponse"
                },
                "example": {
                  "data": [
                    {
                      "id": "call_019283",
                      "project": "prj_prod",
                      "model_requested": "gpt-4o",
                      "served_by": "adapter",
                      "status": "ok",
                      "latency_ms": 245,
                      "created_at": "2026-10-26T11:50:00Z"
                    }
                  ],
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v1/calls/{call_id}": {
      "get": {
        "operationId": "getCall",
        "tags": [
          "Calls"
        ],
        "summary": "Get a call",
        "description": "Returns one call with its request, its answer, who served it, and its timing.\n\nRole: `read` or higher.",
        "parameters": [
          {
            "name": "call_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Call details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CallDetail"
                },
                "example": {
                  "id": "call_019283",
                  "project": "prj_prod",
                  "request": {
                    "messages": [
                      {
                        "role": "user",
                        "content": "Calculate tax"
                      }
                    ]
                  },
                  "response": {
                    "content": "The computed tax is $15.00"
                  },
                  "served_by": "adapter",
                  "status": "ok",
                  "latency_ms": 245,
                  "created_at": "2026-10-26T11:50:00Z"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v1/calls/{call_id}/feedback": {
      "post": {
        "operationId": "addCallFeedback",
        "tags": [
          "Calls"
        ],
        "summary": "Rate a call",
        "description": "Rates a call `up` or `down`, with an optional `comment` (at most 500 characters) and `correction` (at most 8,000 characters): the answer the call should have given. The rating is stored with the call, as a rating in the console is.\n\nRole: `member` or higher.",
        "parameters": [
          {
            "name": "call_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKeyHeader"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "rating"
                ],
                "properties": {
                  "rating": {
                    "type": "string",
                    "enum": [
                      "up",
                      "down"
                    ]
                  },
                  "comment": {
                    "type": "string",
                    "maxLength": 500
                  },
                  "correction": {
                    "type": "string"
                  }
                }
              },
              "example": {
                "rating": "down",
                "comment": "Output missed the sales tax line item."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Feedback recorded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "id",
                    "call_id",
                    "rating"
                  ],
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "call_id": {
                      "type": "string"
                    },
                    "rating": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "id": "fb_09876",
                  "call_id": "call_019283",
                  "rating": "down"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v1/tasks": {
      "get": {
        "operationId": "listTasks",
        "tags": [
          "Tasks"
        ],
        "summary": "List tasks",
        "description": "Lists the tasks Mubit found in your calls, with their row counts, stage and active adapter version.\n\nRole: `read` or higher.",
        "parameters": [
          {
            "name": "project",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          }
        ],
        "responses": {
          "200": {
            "description": "List of tasks",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TaskListResponse"
                },
                "example": {
                  "data": [
                    {
                      "id": "task_triage12",
                      "name": "Support Ticket Triage",
                      "project": "prj_prod",
                      "stage": "training",
                      "rows_count": 85,
                      "active_version": 2,
                      "created_at": "2026-10-10T00:00:00Z"
                    }
                  ],
                  "next_cursor": null
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v1/tasks/{task_id}": {
      "get": {
        "operationId": "getTask",
        "tags": [
          "Tasks"
        ],
        "summary": "Get task details",
        "description": "Returns one task with its stage, its dataset sizes and what to do next.\n\nRole: `read` or higher.",
        "parameters": [
          {
            "name": "task_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Task details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TaskDetail"
                },
                "example": {
                  "id": "task_triage12",
                  "name": "Support Ticket Triage",
                  "project": "prj_prod",
                  "stage": "ready",
                  "rows_count": 85,
                  "holdout_count": 18,
                  "active_version": 2,
                  "recommendation": "serve"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v1/tasks/{task_id}/examples": {
      "get": {
        "operationId": "listTaskExamples",
        "tags": [
          "Tasks"
        ],
        "summary": "List task training examples",
        "description": "Lists the task's training and held-out examples, one page of at most 50 (a higher `limit` returns 50). A row of the next training run has `status` `next` and `split` `train`. A row of the held-out test has `status` `test` and `split` `holdout`. A row left out of the next run has `status` `left_out` and says why in `left_out_reason`. `input` and `expected_output` are excerpts of at most 160 characters. A cursor belongs to its task and query (`400 invalid_cursor` otherwise). This route has its own limit: 120 requests a minute for an organization, across all its keys (`429 rate_limited` with `Retry-After`). The project's example review must be on (`409 state_conflict` otherwise).\n\nRole: `read` or higher.",
        "parameters": [
          {
            "name": "task_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          }
        ],
        "responses": {
          "200": {
            "description": "Task examples",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TaskExampleListResponse"
                },
                "example": {
                  "data": [
                    {
                      "id": "ex_98124",
                      "input": "Refund request for order #1234",
                      "expected_output": "Refund initiated for order #1234",
                      "split": "holdout",
                      "status": "test"
                    }
                  ],
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "409": {
            "description": "The task's project has example review off (`state_conflict`, with `details.reason` `feedback_review_off`), or examples can't be read yet (`engine_too_old`)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": {
                    "code": "engine_too_old",
                    "message": "Training examples can't be read yet",
                    "request_id": "req_409abc"
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/429"
          },
          "500": {
            "$ref": "#/components/responses/500"
          },
          "503": {
            "$ref": "#/components/responses/503"
          }
        }
      }
    },
    "/api/v1/tasks/{task_id}/settings": {
      "get": {
        "operationId": "getTaskSettings",
        "tags": [
          "Fine-tuning"
        ],
        "summary": "Get training settings",
        "description": "Returns the task's training settings: its base model, and the `min_rows`, `max_rows` and `rate_max_per_day` that apply to it. A figure with no value set is null; no default is made up for it. `retrain_interval_s` and `training_window_days` are always null: a task retrains when enough new rows arrive. The `ETag` header is a digest of these figures.\n\nRole: `read` or higher.",
        "parameters": [
          {
            "name": "task_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Task settings",
            "headers": {
              "ETag": {
                "schema": {
                  "type": "string"
                },
                "description": "Current entity tag for optimistic concurrency"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TaskSettings"
                },
                "example": {
                  "base_model": "Qwen/Qwen3-4B-Instruct-2507",
                  "rate_max_per_day": 100,
                  "min_rows": 20,
                  "max_rows": 500,
                  "retrain_interval_s": null,
                  "training_window_days": null
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "500": {
            "$ref": "#/components/responses/500"
          },
          "503": {
            "$ref": "#/components/responses/503"
          }
        }
      }
    },
    "/api/v1/tasks/{task_id}/train": {
      "post": {
        "operationId": "retrainTask",
        "tags": [
          "Fine-tuning"
        ],
        "summary": "Start training",
        "description": "Starts a training run for a new adapter version of the task, and answers `202` with its job. Read the job with [Get job status](#get-job-status). With `dry_run: true` nothing starts: the answer (`200`) says whether a run would start, with `rows` and `need`. The body takes `reason` and `dry_run` only; any other field is `400`. While the run's dataset is still being built, the job has no id yet (`null`) and its status is `preparing`. Too few rows, or a run already in progress, is `409 state_conflict`.\n\nRole: `admin`.",
        "parameters": [
          {
            "name": "task_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKeyHeader"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "type": "string"
                  },
                  "dry_run": {
                    "type": "boolean",
                    "default": false
                  }
                }
              },
              "example": {
                "reason": "Retrain with updated customer support guidelines"
              }
            }
          }
        },
        "responses": {
          "202": {
            "$ref": "#/components/responses/202Job"
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "409": {
            "$ref": "#/components/responses/409"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v1/tasks/{task_id}/versions": {
      "get": {
        "operationId": "listTaskVersions",
        "tags": [
          "Versions"
        ],
        "summary": "List adapter versions",
        "description": "Lists the task's adapter versions.\n\nRole: `read` or higher.",
        "parameters": [
          {
            "name": "task_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          }
        ],
        "responses": {
          "200": {
            "description": "Version list",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VersionListResponse"
                },
                "example": {
                  "data": [
                    {
                      "id": "ver_002",
                      "task_id": "task_triage12",
                      "version_number": 2,
                      "status": "promoted",
                      "score": 0.88,
                      "base_model": "Qwen/Qwen3-4B-Instruct-2507",
                      "created_at": "2026-10-24T00:00:00Z"
                    }
                  ],
                  "next_cursor": null
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v1/versions/{version_id}": {
      "get": {
        "operationId": "getVersion",
        "tags": [
          "Versions"
        ],
        "summary": "Get a version",
        "description": "Returns one adapter version with its test results and its canary and shadow shares.\n\nRole: `read` or higher.",
        "parameters": [
          {
            "name": "version_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Version details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VersionDetail"
                },
                "example": {
                  "id": "ver_002",
                  "task_id": "task_triage12",
                  "version_number": 2,
                  "status": "promoted",
                  "score": 0.88,
                  "canary_percent": 100,
                  "shadow_percent": 0,
                  "eval_metrics": {
                    "accuracy": 0.92,
                    "latency_p50_ms": 180
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v1/versions/{version_id}/promote": {
      "post": {
        "operationId": "promoteVersion",
        "tags": [
          "Versions"
        ],
        "summary": "Promote a version",
        "description": "Promotes the version, so it answers the task's calls. A version that can't be promoted now is `409`.\n\nRole: `admin`.",
        "parameters": [
          {
            "name": "version_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKeyHeader"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "type": "string"
                  }
                }
              },
              "example": {
                "reason": "Cleared 90% accuracy hurdle"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Version promoted",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "id",
                    "status"
                  ],
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "promoted"
                      ]
                    }
                  }
                },
                "example": {
                  "id": "ver_002",
                  "status": "promoted"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "409": {
            "$ref": "#/components/responses/409"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v1/versions/{version_id}/rollback": {
      "post": {
        "operationId": "rollbackVersion",
        "tags": [
          "Versions"
        ],
        "summary": "Roll back a version",
        "description": "Rolls back the promoted version and promotes the version promoted before it again. The version must be the promoted one (`409 not_promoted` otherwise). It takes no body.\n\nRole: `admin`.",
        "parameters": [
          {
            "name": "version_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKeyHeader"
          }
        ],
        "responses": {
          "200": {
            "description": "Version rolled back",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "id",
                    "status",
                    "restored_version_id"
                  ],
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "rolled_back"
                      ]
                    },
                    "restored_version_id": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "id": "ver_2_support-triage",
                  "status": "rolled_back",
                  "restored_version_id": "ver_1_support-triage"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "409": {
            "$ref": "#/components/responses/409"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v1/versions/{version_id}/rollout": {
      "patch": {
        "operationId": "updateVersionRollout",
        "tags": [
          "Versions"
        ],
        "summary": "Set canary or shadow share",
        "description": "Sets the version's canary or shadow share, in percent. `canary_percent` above 0 makes it a canary at that share; `shadow_percent` above 0 makes it a shadow at that share. Both above 0 is `400`: a version is in one state at a time. Both 0 takes a canary or shadow out (`409` for the promoted version). A share you leave out stays as it is. The answer is the share now in effect.\n\nRole: `admin`.",
        "parameters": [
          {
            "name": "version_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "canary_percent": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 100
                  },
                  "shadow_percent": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 100
                  },
                  "reason": {
                    "type": "string",
                    "maxLength": 500
                  }
                }
              },
              "example": {
                "canary_percent": 25
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Rollout updated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "id",
                    "canary_percent",
                    "shadow_percent"
                  ],
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "canary_percent": {
                      "type": "integer"
                    },
                    "shadow_percent": {
                      "type": "integer"
                    }
                  }
                },
                "example": {
                  "id": "ver_2_support-triage",
                  "canary_percent": 25,
                  "shadow_percent": 0
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "409": {
            "$ref": "#/components/responses/409"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v1/lessons": {
      "get": {
        "operationId": "listLessons",
        "tags": [
          "Lessons"
        ],
        "summary": "List lessons",
        "description": "Lists the lessons runtime calibration distilled: rules, pitfalls and guidelines.\n\nRole: `read` or higher.",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "active",
                "pending",
                "rejected"
              ]
            }
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          }
        ],
        "responses": {
          "200": {
            "description": "List of lessons",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LessonListResponse"
                },
                "example": {
                  "data": [
                    {
                      "id": "les_019283",
                      "rule": "Always include tax breakdown in billing responses",
                      "status": "active",
                      "scope": "global",
                      "importance": "high",
                      "recurrence_count": 5,
                      "created_at": "2026-10-20T00:00:00Z"
                    }
                  ],
                  "next_cursor": null
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v1/lessons/{lesson_id}": {
      "get": {
        "operationId": "getLesson",
        "tags": [
          "Lessons"
        ],
        "summary": "Get a lesson",
        "description": "Returns one lesson with its evidence and scope.\n\nRole: `read` or higher.",
        "parameters": [
          {
            "name": "lesson_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Lesson details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LessonDetail"
                },
                "example": {
                  "id": "les_019283",
                  "rule": "Always include tax breakdown in billing responses",
                  "status": "active",
                  "scope": "global",
                  "importance": "high",
                  "citations": [
                    "call_019283",
                    "call_019290"
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v1/imports": {
      "get": {
        "operationId": "listImports",
        "tags": [
          "Data Ingestion"
        ],
        "summary": "List imports",
        "description": "Lists the imports of past calls in the organization's projects, newest first, the last 50 of each project. `total_records` is the number of calls read.\n\nRole: `read` or higher.",
        "parameters": [
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          }
        ],
        "responses": {
          "200": {
            "description": "Import jobs",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ImportListResponse"
                },
                "example": {
                  "data": [
                    {
                      "id": "imp_019283",
                      "source": "braintrust",
                      "status": "succeeded",
                      "total_records": 1200,
                      "created_at": "2026-10-25T00:00:00Z"
                    }
                  ],
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "500": {
            "$ref": "#/components/responses/500"
          },
          "503": {
            "$ref": "#/components/responses/503"
          }
        }
      }
    },
    "/api/v1/usage": {
      "get": {
        "operationId": "getUsage",
        "tags": [
          "Usage & Billing"
        ],
        "summary": "Get usage",
        "description": "Returns the calls, runs and tokens counted, and what the runs cost (`spend_usd`): totals for the window, and in `data` a row for each project and UTC day. The window is `start_date` to `end_date`, both UTC days included. Counts go back 61 days before today: a window that starts earlier, or ends after today, is `400 validation`. Left out, `end_date` is today and `start_date` is the first day of that month.\n\nRole: `read` or higher.",
        "parameters": [
          {
            "name": "project",
            "in": "query",
            "description": "Limits the report to one project of the organization (`prj_...`). Any other project is 404.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "start_date",
            "in": "query",
            "description": "The first UTC day of the window (YYYY-MM-DD), no earlier than 61 days before today: the meter holds nothing of an earlier day, and an earlier start is refused with 400 validation. Left out, the first day of the month of `end_date` (refused in the same way when that day is earlier).",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "end_date",
            "in": "query",
            "description": "The last UTC day of the window (YYYY-MM-DD), not after today (UTC): a day to come has no counts, and an end after today is refused with 400 validation. Left out, today (UTC).",
            "schema": {
              "type": "string",
              "format": "date"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Usage figures",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UsageReport"
                },
                "example": {
                  "start_date": "2026-10-01",
                  "end_date": "2026-10-26",
                  "total_calls": 15420,
                  "total_runs": 15420,
                  "total_tokens": 3200400,
                  "spend_usd": "4.20",
                  "data": [
                    {
                      "date": "2026-10-25",
                      "project": "prj_prod",
                      "calls": 6220,
                      "runs": 6220,
                      "tokens_in": 1100000,
                      "tokens_out": 196400,
                      "spend_usd": "1.70"
                    },
                    {
                      "date": "2026-10-26",
                      "project": "prj_prod",
                      "calls": 9200,
                      "runs": 9200,
                      "tokens_in": 1500000,
                      "tokens_out": 404000,
                      "spend_usd": "2.50"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "500": {
            "$ref": "#/components/responses/500"
          },
          "503": {
            "$ref": "#/components/responses/503"
          }
        }
      }
    },
    "/api/v1/billing": {
      "get": {
        "operationId": "getBilling",
        "tags": [
          "Usage & Billing"
        ],
        "summary": "Get billing status",
        "description": "Returns whether runs are counted (`runs_status`) and the payment card (`has_card`, `card_last4`). Both card fields are null for now, which means not known, not \"no card\": test for null before you test for false. A key of role `admin` also gets the credit balance (`balance_usd`); for other keys the field is left out. Billing belongs to the organization, so a key bound to one project gets `403 project_scoped`.\n\nRole: `read` or higher.",
        "responses": {
          "200": {
            "description": "Billing status",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BillingStatus"
                },
                "example": {
                  "balance_usd": "50.00",
                  "has_card": null,
                  "card_last4": null,
                  "runs_status": "active"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "description": "Forbidden (role_required; project_scoped, because billing is the organization's and a key bound to one project is refused)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": {
                    "code": "project_scoped",
                    "message": "Operation is organization-level and cannot be accessed with a project-scoped credential",
                    "request_id": "req_403abc"
                  }
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/500"
          },
          "503": {
            "$ref": "#/components/responses/503"
          }
        }
      }
    },
    "/api/v1/activity": {
      "get": {
        "operationId": "listActivity",
        "tags": [
          "Activity"
        ],
        "summary": "List activity",
        "description": "Lists your projects' training, rollout, access and policy events, newest first: the newest 100 events of each project. Older events aren't reachable here. `project` limits the feed to one project; a key bound to one project reads that project's.\n\nRole: `read` or higher.",
        "parameters": [
          {
            "name": "project",
            "in": "query",
            "description": "A project of the organization (`prj_...`). Another organization's project has an empty feed; a key bound to one project that names another is 404.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          }
        ],
        "responses": {
          "200": {
            "description": "Activity list",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ActivityListResponse"
                },
                "example": {
                  "data": [
                    {
                      "id": "act_rollout:ad-a:1793012400000000:0000",
                      "actor": "person:user_one",
                      "kind": "version.promoted",
                      "description": "Version 2 of \"Support Triage\" promoted",
                      "created_at": "2026-10-26T11:00:00Z",
                      "project": "prj_prod"
                    }
                  ],
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "500": {
            "$ref": "#/components/responses/500"
          },
          "503": {
            "$ref": "#/components/responses/503"
          }
        }
      }
    },
    "/api/v1/jobs/{job_id}": {
      "get": {
        "operationId": "getJob",
        "tags": [
          "Jobs"
        ],
        "summary": "Get job status",
        "description": "Reads one training job by the id [Start training](#start-training) returned: its status and its times. `type` is `training`. The status is `queued`, `running`, `succeeded`, `failed` or `canceled`. A failed job carries an `error`. A job of another organization is `404`.\n\nRole: `read` or higher.",
        "parameters": [
          {
            "name": "job_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Job status",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Job"
                },
                "example": {
                  "id": "ftjob_019283",
                  "type": "training",
                  "status": "running",
                  "created_at": "2026-10-26T11:55:00Z",
                  "started_at": "2026-10-26T11:55:05Z",
                  "finished_at": null,
                  "result": null,
                  "error": null
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "500": {
            "$ref": "#/components/responses/500"
          },
          "503": {
            "$ref": "#/components/responses/503"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "BearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "A management key (`mwm_...`), sent as `Authorization: Bearer <key>`."
      }
    },
    "parameters": {
      "CursorParam": {
        "name": "cursor",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string"
        },
        "description": "Sealed pagination cursor from previous page"
      },
      "IdempotencyKeyHeader": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": false,
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 255
        },
        "description": "Unique key for safe write retries within 24h"
      },
      "LimitParam": {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 200,
          "default": 50
        },
        "description": "Number of records to return (1-200)"
      }
    },
    "responses": {
      "400": {
        "description": "Bad request (validation, invalid_cursor, out_of_bounds)",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorEnvelope"
            },
            "example": {
              "error": {
                "code": "validation",
                "message": "Missing required parameter 'name'",
                "request_id": "req_400abc"
              }
            }
          }
        }
      },
      "401": {
        "description": "Unauthenticated (missing, invalid, or expired token)",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorEnvelope"
            },
            "example": {
              "error": {
                "code": "unauthenticated",
                "message": "Missing or invalid Bearer credential",
                "request_id": "req_401abc"
              }
            }
          }
        }
      },
      "403": {
        "description": "Forbidden (role_required, role_ceiling, project_scoped, forbidden, or a key that isn't a management key)",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorEnvelope"
            },
            "example": {
              "error": {
                "code": "role_required",
                "message": "Operation requires role 'admin'",
                "request_id": "req_403abc"
              }
            }
          }
        }
      },
      "404": {
        "description": "Not found",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorEnvelope"
            },
            "example": {
              "error": {
                "code": "not_found",
                "message": "Resource does not exist",
                "request_id": "req_404abc"
              }
            }
          }
        }
      },
      "409": {
        "description": "Conflict (idempotency_conflict, state_conflict)",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorEnvelope"
            },
            "example": {
              "error": {
                "code": "idempotency_conflict",
                "message": "Idempotency-Key already used with different payload",
                "request_id": "req_409abc"
              }
            }
          }
        }
      },
      "429": {
        "description": "Rate limited",
        "headers": {
          "Retry-After": {
            "schema": {
              "type": "integer"
            },
            "description": "Seconds until request quota resets"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorEnvelope"
            },
            "example": {
              "error": {
                "code": "rate_limited",
                "message": "Rate limit exceeded",
                "request_id": "req_429abc"
              }
            }
          }
        }
      },
      "500": {
        "description": "Internal server error",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorEnvelope"
            },
            "example": {
              "error": {
                "code": "internal",
                "message": "Internal server error",
                "request_id": "req_500abc"
              }
            }
          }
        }
      },
      "503": {
        "description": "Service unavailable (`unavailable`). Retry after the `Retry-After` seconds.",
        "headers": {
          "Retry-After": {
            "schema": {
              "type": "integer"
            },
            "description": "Seconds to wait before retrying"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorEnvelope"
            },
            "example": {
              "error": {
                "code": "unavailable",
                "message": "Service is temporarily unavailable",
                "request_id": "req_503abc"
              }
            }
          }
        }
      },
      "202Job": {
        "description": "Asynchronous job accepted",
        "headers": {
          "Location": {
            "schema": {
              "type": "string"
            },
            "description": "Path to inspect job status (/api/v1/jobs/{id})"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "job"
              ],
              "properties": {
                "job": {
                  "$ref": "#/components/schemas/Job"
                }
              }
            },
            "example": {
              "job": {
                "id": "job_019283",
                "type": "export",
                "status": "queued",
                "created_at": "2026-10-26T12:00:00Z"
              }
            }
          }
        }
      }
    },
    "schemas": {
      "ActivityEvent": {
        "type": "object",
        "required": [
          "id",
          "actor",
          "kind",
          "description",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "The event's id, starting with `act_`"
          },
          "actor": {
            "type": "string",
            "description": "Who did it: person:<id> or key:<id>; automatic for Mubit's own steps; unknown where none is recorded"
          },
          "kind": {
            "type": "string",
            "description": "The kind of event, such as training.started, training.completed, training.failed, version.promoted, version.rolled_back, key.created, key.rotated, key.revoked or policy.changed"
          },
          "description": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "project": {
            "type": "string",
            "description": "The project the event belongs to (prj_...)"
          }
        }
      },
      "ActivityListResponse": {
        "type": "object",
        "required": [
          "data",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ActivityEvent"
            }
          },
          "next_cursor": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "BillingStatus": {
        "type": "object",
        "required": [
          "has_card",
          "runs_status"
        ],
        "properties": {
          "balance_usd": {
            "type": "string",
            "description": "The credit balance. Returned to a key of role admin only; for any other key the field is left out."
          },
          "has_card": {
            "type": "boolean",
            "nullable": true,
            "description": "Whether a payment card is on file. In 1.0 it is always null, which means not known and does not mean false: the card is held by the payment processor, which this read does not ask."
          },
          "card_last4": {
            "type": "string",
            "nullable": true,
            "description": "The last four digits of the card on file. In 1.0 it is always null (not known), as has_card: null does not mean that there is no card."
          },
          "runs_status": {
            "type": "string",
            "description": "active, or why the organization's runs are not counted: zero_balance, cap_reached or volume_limit"
          }
        }
      },
      "Call": {
        "type": "object",
        "required": [
          "id",
          "project",
          "status",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "project": {
            "type": "string"
          },
          "model_requested": {
            "type": "string"
          },
          "served_by": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "latency_ms": {
            "type": "integer"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "CallDetail": {
        "type": "object",
        "required": [
          "id",
          "project",
          "request",
          "status",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "project": {
            "type": "string"
          },
          "request": {
            "type": "object"
          },
          "response": {
            "type": "object",
            "nullable": true
          },
          "served_by": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "latency_ms": {
            "type": "integer"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "CallListResponse": {
        "type": "object",
        "required": [
          "data",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Call"
            }
          },
          "next_cursor": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "CreateManagementKeyRequest": {
        "type": "object",
        "required": [
          "name",
          "role"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "role": {
            "type": "string",
            "enum": [
              "read",
              "member",
              "admin"
            ]
          },
          "project": {
            "type": "string",
            "nullable": true
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "When the key stops working, an RFC 3339 time in the future. Left out, the key doesn't expire."
          }
        }
      },
      "CreateManagementKeyResponse": {
        "type": "object",
        "required": [
          "id",
          "name",
          "key",
          "role",
          "status",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "key": {
            "type": "string"
          },
          "role": {
            "type": "string"
          },
          "project": {
            "type": "string",
            "nullable": true
          },
          "status": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ErrorEnvelope": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "code",
              "message",
              "request_id"
            ],
            "properties": {
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              },
              "request_id": {
                "type": "string"
              },
              "details": {
                "type": "object",
                "additionalProperties": true
              }
            }
          }
        }
      },
      "ImportJobSummary": {
        "type": "object",
        "required": [
          "id",
          "source",
          "status",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "imp_ and the run's 24 hex digits"
          },
          "source": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "description": "queued, running, succeeded, failed or canceled (a paused run is running)"
          },
          "total_records": {
            "type": "integer",
            "description": "The calls read so far"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ImportListResponse": {
        "type": "object",
        "required": [
          "data",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ImportJobSummary"
            }
          },
          "next_cursor": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "Job": {
        "type": "object",
        "required": [
          "id",
          "type",
          "status",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "nullable": true,
            "description": "Null while the job has no id yet (a training run whose dataset is still being built)"
          },
          "type": {
            "type": "string",
            "description": "The kind of job: training for a training run"
          },
          "status": {
            "type": "string",
            "enum": [
              "preparing",
              "queued",
              "running",
              "succeeded",
              "failed",
              "canceled"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "started_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "finished_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "progress": {
            "type": "object",
            "properties": {
              "done": {
                "type": "integer"
              },
              "total": {
                "type": "integer"
              }
            }
          },
          "result": {
            "type": "object",
            "nullable": true,
            "additionalProperties": true
          },
          "error": {
            "type": "object",
            "nullable": true,
            "description": "Present for a failed job: the code training_failed and a message",
            "properties": {
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              }
            }
          }
        }
      },
      "Key": {
        "type": "object",
        "required": [
          "id",
          "name",
          "role",
          "status",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "prefix": {
            "type": "string"
          },
          "role": {
            "type": "string",
            "enum": [
              "user",
              "reader",
              "worker",
              "admin"
            ]
          },
          "project": {
            "type": "string",
            "nullable": true
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "revoked",
              "expired"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "KeyListResponse": {
        "type": "object",
        "required": [
          "data",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Key"
            }
          },
          "next_cursor": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "Lesson": {
        "type": "object",
        "required": [
          "id",
          "rule",
          "status",
          "scope",
          "importance",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "rule": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "scope": {
            "type": "string"
          },
          "importance": {
            "type": "string"
          },
          "recurrence_count": {
            "type": "integer"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "approval": {
            "description": "The lesson's approval; null when it has none.",
            "oneOf": [
              {
                "$ref": "#/components/schemas/LessonApproval"
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "LessonApproval": {
        "type": "object",
        "required": [
          "state",
          "approved_by",
          "approved_at"
        ],
        "properties": {
          "state": {
            "type": "string",
            "enum": [
              "approved",
              "lapsed"
            ],
            "description": "approved, the approval holds the lesson as it is; lapsed, it no longer does (lapsed_reason says why)."
          },
          "approved_by": {
            "type": "object",
            "required": [
              "type",
              "id"
            ],
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "person",
                  "key"
                ]
              },
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string",
                "description": "A management key's name when it approved"
              }
            }
          },
          "approved_at": {
            "type": "string",
            "format": "date-time"
          },
          "lapsed_reason": {
            "type": "string",
            "enum": [
              "text_changed",
              "not_active",
              "stale"
            ]
          },
          "lapsed_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "LessonDetail": {
        "type": "object",
        "required": [
          "id",
          "rule",
          "status",
          "scope",
          "importance"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "rule": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "scope": {
            "type": "string"
          },
          "importance": {
            "type": "string"
          },
          "citations": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "approval": {
            "description": "The lesson's approval; null when it has none.",
            "oneOf": [
              {
                "$ref": "#/components/schemas/LessonApproval"
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "LessonListResponse": {
        "type": "object",
        "required": [
          "data",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Lesson"
            }
          },
          "next_cursor": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "ManagementKey": {
        "type": "object",
        "required": [
          "id",
          "name",
          "role",
          "status",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "role": {
            "type": "string",
            "enum": [
              "read",
              "member",
              "admin"
            ]
          },
          "project": {
            "type": "string",
            "nullable": true
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "revoked",
              "expired"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "last_used_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "ManagementKeyListResponse": {
        "type": "object",
        "required": [
          "data",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ManagementKey"
            }
          },
          "next_cursor": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "Org": {
        "type": "object",
        "required": [
          "id",
          "name",
          "slug",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "plan": {
            "type": "string"
          }
        }
      },
      "Project": {
        "type": "object",
        "required": [
          "id",
          "name",
          "slug",
          "environment",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "environment": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "version": {
            "type": "integer",
            "description": "The project record's version, where one is reported"
          }
        }
      },
      "ProjectListResponse": {
        "type": "object",
        "required": [
          "data",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Project"
            }
          },
          "next_cursor": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "ProviderListResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "provider",
                "status"
              ],
              "properties": {
                "id": {
                  "type": "string",
                  "description": "The saved key's id"
                },
                "provider": {
                  "type": "string"
                },
                "status": {
                  "type": "string"
                },
                "label": {
                  "type": "string"
                },
                "region": {
                  "type": "string"
                },
                "last4": {
                  "type": "string",
                  "description": "The last four characters of the saved key"
                },
                "version": {
                  "type": "integer",
                  "description": "Goes up by one at each rotate"
                },
                "created_at": {
                  "type": "string",
                  "format": "date-time"
                },
                "updated_at": {
                  "type": "string",
                  "format": "date-time"
                }
              }
            }
          }
        }
      },
      "Task": {
        "type": "object",
        "required": [
          "id",
          "name",
          "project",
          "stage",
          "rows_count",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "project": {
            "type": "string"
          },
          "stage": {
            "type": "string"
          },
          "rows_count": {
            "type": "integer"
          },
          "active_version": {
            "type": "integer",
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "TaskDetail": {
        "type": "object",
        "required": [
          "id",
          "name",
          "project",
          "stage",
          "rows_count"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "project": {
            "type": "string"
          },
          "stage": {
            "type": "string"
          },
          "rows_count": {
            "type": "integer"
          },
          "holdout_count": {
            "type": "integer"
          },
          "active_version": {
            "type": "integer",
            "nullable": true
          },
          "recommendation": {
            "type": "string"
          }
        }
      },
      "TaskExample": {
        "type": "object",
        "required": [
          "id",
          "input",
          "status"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "ex_ and the id of the call the row is made from"
          },
          "input": {
            "type": "string",
            "description": "An excerpt of the row's input, at most 160 characters"
          },
          "expected_output": {
            "type": "string",
            "description": "An excerpt of the row's answer, at most 160 characters"
          },
          "split": {
            "type": "string",
            "enum": [
              "train",
              "holdout"
            ],
            "description": "train for a row of the next training build (status next), holdout for a row of the held-out exam (status test); a row left out has none"
          },
          "status": {
            "type": "string",
            "description": "next (a row of the next training build), test (a row of the held-out exam) or left_out (a row the next build leaves out)"
          },
          "left_out_reason": {
            "type": "string",
            "description": "Why a row with status left_out is not in the next run (no_verdict, person_rejected, row_filter, and others)"
          }
        }
      },
      "TaskExampleListResponse": {
        "type": "object",
        "required": [
          "data",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TaskExample"
            }
          },
          "next_cursor": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "TaskListResponse": {
        "type": "object",
        "required": [
          "data",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Task"
            }
          },
          "next_cursor": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "TaskSettings": {
        "type": "object",
        "description": "A figure with no value set is null. No default is made up for it.",
        "properties": {
          "base_model": {
            "type": "string",
            "nullable": true
          },
          "rate_max_per_day": {
            "type": "integer",
            "nullable": true
          },
          "min_rows": {
            "type": "integer",
            "nullable": true
          },
          "max_rows": {
            "type": "integer",
            "nullable": true
          },
          "retrain_interval_s": {
            "type": "integer",
            "nullable": true
          },
          "training_window_days": {
            "type": "integer",
            "nullable": true
          }
        }
      },
      "UsageDay": {
        "type": "object",
        "required": [
          "date",
          "project",
          "calls",
          "runs",
          "tokens_in",
          "tokens_out",
          "spend_usd"
        ],
        "properties": {
          "date": {
            "type": "string",
            "format": "date"
          },
          "project": {
            "type": "string"
          },
          "calls": {
            "type": "integer"
          },
          "runs": {
            "type": "integer"
          },
          "tokens_in": {
            "type": "integer"
          },
          "tokens_out": {
            "type": "integer"
          },
          "spend_usd": {
            "type": "string"
          }
        }
      },
      "UsageReport": {
        "type": "object",
        "required": [
          "total_calls",
          "total_tokens",
          "spend_usd"
        ],
        "properties": {
          "total_calls": {
            "type": "integer"
          },
          "start_date": {
            "type": "string",
            "format": "date",
            "description": "The first UTC day of the window, included"
          },
          "end_date": {
            "type": "string",
            "format": "date",
            "description": "The last UTC day of the window, included"
          },
          "total_runs": {
            "type": "integer",
            "description": "The runs the calls counted as"
          },
          "total_tokens": {
            "type": "integer"
          },
          "spend_usd": {
            "type": "string",
            "description": "What the runs cost, in dollars with at least cents (0.00 where nothing was charged)"
          },
          "data": {
            "type": "array",
            "description": "A row for each project and UTC day in the dates asked",
            "items": {
              "$ref": "#/components/schemas/UsageDay"
            }
          }
        }
      },
      "Version": {
        "type": "object",
        "required": [
          "id",
          "task_id",
          "version_number",
          "status",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "task_id": {
            "type": "string"
          },
          "version_number": {
            "type": "integer"
          },
          "status": {
            "type": "string"
          },
          "score": {
            "type": "number",
            "nullable": true
          },
          "base_model": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "VersionDetail": {
        "type": "object",
        "required": [
          "id",
          "task_id",
          "version_number",
          "status"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "task_id": {
            "type": "string"
          },
          "version_number": {
            "type": "integer"
          },
          "status": {
            "type": "string"
          },
          "score": {
            "type": "number",
            "nullable": true
          },
          "canary_percent": {
            "type": "integer"
          },
          "shadow_percent": {
            "type": "integer"
          },
          "eval_metrics": {
            "type": "object",
            "additionalProperties": true
          }
        }
      },
      "VersionListResponse": {
        "type": "object",
        "required": [
          "data",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Version"
            }
          },
          "next_cursor": {
            "type": "string",
            "nullable": true
          }
        }
      }
    }
  }
}
