{
  "openapi": "3.1.0",
  "info": {
    "title": "Onrup API",
    "version": "1",
    "summary": "Fine-tune open-weight language models and serve them on an OpenAI-compatible endpoint.",
    "description": "REST over HTTPS with server-sent events for progress. Bearer authentication for both browser sessions and API keys. Idempotency-Key on mutating calls, honoured for 24 hours. Cursor pagination. Breaking changes ship as a new version rather than mutating this one.  Errors return `{\"error\": {\"code\", \"message\", \"detail\"}}` with a stable namespaced code.",
    "contact": {
      "name": "Onrup",
      "url": "https://www.onrup.com/contact"
    }
  },
  "servers": [
    {
      "url": "https://api.onrup.com",
      "description": "Control plane"
    }
  ],
  "tags": [
    {
      "name": "Account"
    },
    {
      "name": "API keys"
    },
    {
      "name": "Datasets"
    },
    {
      "name": "Catalogue"
    },
    {
      "name": "Runs"
    },
    {
      "name": "Operations"
    },
    {
      "name": "Evaluation"
    },
    {
      "name": "Publishing"
    },
    {
      "name": "Deployments"
    },
    {
      "name": "Billing"
    },
    {
      "name": "Inference"
    }
  ],
  "paths": {
    "/v1/me": {
      "get": {
        "summary": "The authenticated identity, tenant and role.",
        "description": "The authenticated identity, tenant and role.",
        "tags": [
          "Account"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "4XX": {
            "description": "A typed error. Branch on `error.code`, which is stable; messages are not."
          }
        }
      },
      "patch": {
        "summary": "Update profile fields on the authenticated user.",
        "description": "Update profile fields on the authenticated user.",
        "tags": [
          "Account"
        ],
        "security": [
          {
            "bearerAuth": [
              "session"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "4XX": {
            "description": "A typed error. Branch on `error.code`, which is stable; messages are not."
          }
        }
      }
    },
    "/v1/keys": {
      "post": {
        "summary": "Create an API key with an explicit scope set.",
        "description": "The secret is returned once and never again.",
        "tags": [
          "API keys"
        ],
        "security": [
          {
            "bearerAuth": [
              "keys:write"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "4XX": {
            "description": "A typed error. Branch on `error.code`, which is stable; messages are not."
          }
        }
      },
      "get": {
        "summary": "List keys with their scopes and last use.",
        "description": "List keys with their scopes and last use.",
        "tags": [
          "API keys"
        ],
        "security": [
          {
            "bearerAuth": [
              "keys:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "4XX": {
            "description": "A typed error. Branch on `error.code`, which is stable; messages are not."
          }
        }
      }
    },
    "/v1/keys/{id}": {
      "delete": {
        "summary": "Revoke a key immediately.",
        "description": "Revoke a key immediately.",
        "tags": [
          "API keys"
        ],
        "security": [
          {
            "bearerAuth": [
              "keys:write"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "4XX": {
            "description": "A typed error. Branch on `error.code`, which is stable; messages are not."
          }
        }
      }
    },
    "/v1/data-assets/uploads": {
      "post": {
        "summary": "Begin a resumable multipart upload.",
        "description": "Returns presigned part URLs; bytes go straight to storage and never traverse the API.",
        "tags": [
          "Datasets"
        ],
        "security": [
          {
            "bearerAuth": [
              "datasets:write"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "4XX": {
            "description": "A typed error. Branch on `error.code`, which is stable; messages are not."
          }
        }
      }
    },
    "/v1/data-assets/uploads/{id}/parts": {
      "post": {
        "summary": "Request further presigned part URLs.",
        "description": "Request further presigned part URLs.",
        "tags": [
          "Datasets"
        ],
        "security": [
          {
            "bearerAuth": [
              "datasets:write"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "4XX": {
            "description": "A typed error. Branch on `error.code`, which is stable; messages are not."
          }
        }
      }
    },
    "/v1/data-assets/uploads/{id}/complete": {
      "post": {
        "summary": "Finalise an upload and trigger validation.",
        "description": "Finalise an upload and trigger validation.",
        "tags": [
          "Datasets"
        ],
        "security": [
          {
            "bearerAuth": [
              "datasets:write"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "4XX": {
            "description": "A typed error. Branch on `error.code`, which is stable; messages are not."
          }
        }
      }
    },
    "/v1/data-assets/uploads/{id}": {
      "get": {
        "summary": "Upload state and which parts have landed.",
        "description": "Upload state and which parts have landed.",
        "tags": [
          "Datasets"
        ],
        "security": [
          {
            "bearerAuth": [
              "datasets:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "4XX": {
            "description": "A typed error. Branch on `error.code`, which is stable; messages are not."
          }
        }
      },
      "delete": {
        "summary": "Abandon an upload and release its parts.",
        "description": "Abandon an upload and release its parts.",
        "tags": [
          "Datasets"
        ],
        "security": [
          {
            "bearerAuth": [
              "datasets:write"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "4XX": {
            "description": "A typed error. Branch on `error.code`, which is stable; messages are not."
          }
        }
      }
    },
    "/v1/data-assets": {
      "get": {
        "summary": "List data assets with kind and state.",
        "description": "List data assets with kind and state.",
        "tags": [
          "Datasets"
        ],
        "security": [
          {
            "bearerAuth": [
              "datasets:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "4XX": {
            "description": "A typed error. Branch on `error.code`, which is stable; messages are not."
          }
        }
      }
    },
    "/v1/data-assets/{id}": {
      "get": {
        "summary": "A single data asset and its manifest.",
        "description": "A single data asset and its manifest.",
        "tags": [
          "Datasets"
        ],
        "security": [
          {
            "bearerAuth": [
              "datasets:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "4XX": {
            "description": "A typed error. Branch on `error.code`, which is stable; messages are not."
          }
        }
      },
      "delete": {
        "summary": "Delete a data asset and its derived artefacts.",
        "description": "Delete a data asset and its derived artefacts.",
        "tags": [
          "Datasets"
        ],
        "security": [
          {
            "bearerAuth": [
              "datasets:write"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "4XX": {
            "description": "A typed error. Branch on `error.code`, which is stable; messages are not."
          }
        }
      }
    },
    "/v1/data-assets/{id}/report": {
      "get": {
        "summary": "The validation report: record counts, token length percentiles, duplicates, truncation risk.",
        "description": "The validation report: record counts, token length percentiles, duplicates, truncation risk.",
        "tags": [
          "Datasets"
        ],
        "security": [
          {
            "bearerAuth": [
              "datasets:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "4XX": {
            "description": "A typed error. Branch on `error.code`, which is stable; messages are not."
          }
        }
      }
    },
    "/v1/data-assets/{id}/generate": {
      "post": {
        "summary": "Expand a seed asset into a full one under a declared cost ceiling.",
        "description": "Expand a seed asset into a full one under a declared cost ceiling.",
        "tags": [
          "Datasets"
        ],
        "security": [
          {
            "bearerAuth": [
              "datasets:write"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "4XX": {
            "description": "A typed error. Branch on `error.code`, which is stable; messages are not."
          }
        }
      }
    },
    "/v1/models": {
      "get": {
        "summary": "Base models with memory thresholds and supported objectives.",
        "description": "Base models with memory thresholds and supported objectives.",
        "tags": [
          "Catalogue"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "4XX": {
            "description": "A typed error. Branch on `error.code`, which is stable; messages are not."
          }
        }
      }
    },
    "/v1/templates/training": {
      "get": {
        "summary": "Training templates, filterable by model.",
        "description": "Add ?include=experimental to see templates outside the stable set.",
        "tags": [
          "Catalogue"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "4XX": {
            "description": "A typed error. Branch on `error.code`, which is stable; messages are not."
          }
        }
      }
    },
    "/v1/templates/inference": {
      "get": {
        "summary": "Inference templates and their scaling options.",
        "description": "Inference templates and their scaling options.",
        "tags": [
          "Catalogue"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "4XX": {
            "description": "A typed error. Branch on `error.code`, which is stable; messages are not."
          }
        }
      }
    },
    "/v1/runs": {
      "post": {
        "summary": "Create a run in draft, against a template and a data asset.",
        "description": "Create a run in draft, against a template and a data asset.",
        "tags": [
          "Runs"
        ],
        "security": [
          {
            "bearerAuth": [
              "runs:write"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "4XX": {
            "description": "A typed error. Branch on `error.code`, which is stable; messages are not."
          }
        }
      },
      "get": {
        "summary": "List runs with state and accrued cost.",
        "description": "List runs with state and accrued cost.",
        "tags": [
          "Runs"
        ],
        "security": [
          {
            "bearerAuth": [
              "runs:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "4XX": {
            "description": "A typed error. Branch on `error.code`, which is stable; messages are not."
          }
        }
      }
    },
    "/v1/runs/{id}/submit": {
      "post": {
        "summary": "Authorise cost and queue the run.",
        "description": "This is where spend is reserved. A run that would breach the limit is rejected here, before compute is leased.",
        "tags": [
          "Runs"
        ],
        "security": [
          {
            "bearerAuth": [
              "runs:write"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "4XX": {
            "description": "A typed error. Branch on `error.code`, which is stable; messages are not."
          }
        }
      }
    },
    "/v1/runs/{id}/cancel": {
      "post": {
        "summary": "Cancel a run and release its reservation.",
        "description": "Cancel a run and release its reservation.",
        "tags": [
          "Runs"
        ],
        "security": [
          {
            "bearerAuth": [
              "runs:write"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "4XX": {
            "description": "A typed error. Branch on `error.code`, which is stable; messages are not."
          }
        }
      }
    },
    "/v1/runs/{id}/resume": {
      "post": {
        "summary": "Resume an interrupted run from its last checkpoint.",
        "description": "Resume an interrupted run from its last checkpoint.",
        "tags": [
          "Runs"
        ],
        "security": [
          {
            "bearerAuth": [
              "runs:write"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "4XX": {
            "description": "A typed error. Branch on `error.code`, which is stable; messages are not."
          }
        }
      }
    },
    "/v1/runs/{id}": {
      "get": {
        "summary": "A single run: state, template, GPU class, cost so far.",
        "description": "A single run: state, template, GPU class, cost so far.",
        "tags": [
          "Runs"
        ],
        "security": [
          {
            "bearerAuth": [
              "runs:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "4XX": {
            "description": "A typed error. Branch on `error.code`, which is stable; messages are not."
          }
        }
      }
    },
    "/v1/runs/{id}/logs": {
      "get": {
        "summary": "Training logs for a run.",
        "description": "Training logs for a run.",
        "tags": [
          "Runs"
        ],
        "security": [
          {
            "bearerAuth": [
              "runs:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "4XX": {
            "description": "A typed error. Branch on `error.code`, which is stable; messages are not."
          }
        }
      }
    },
    "/v1/runs/{id}/metrics": {
      "get": {
        "summary": "Loss, throughput and validation metrics over time.",
        "description": "Loss, throughput and validation metrics over time.",
        "tags": [
          "Runs"
        ],
        "security": [
          {
            "bearerAuth": [
              "runs:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "4XX": {
            "description": "A typed error. Branch on `error.code`, which is stable; messages are not."
          }
        }
      }
    },
    "/v1/runs/{id}/weights": {
      "get": {
        "summary": "A signed URL to download the trained weights.",
        "description": "The adapter, or the merged model where the template produced one.",
        "tags": [
          "Runs"
        ],
        "security": [
          {
            "bearerAuth": [
              "runs:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "4XX": {
            "description": "A typed error. Branch on `error.code`, which is stable; messages are not."
          }
        }
      }
    },
    "/v1/runs/{id}/stream": {
      "get": {
        "summary": "Server-sent event stream of run progress.",
        "description": "Server-sent event stream of run progress.",
        "tags": [
          "Runs"
        ],
        "security": [
          {
            "bearerAuth": [
              "runs:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "4XX": {
            "description": "A typed error. Branch on `error.code`, which is stable; messages are not."
          }
        }
      }
    },
    "/v1/operations/{id}": {
      "get": {
        "summary": "State of any long-running operation.",
        "description": "State of any long-running operation.",
        "tags": [
          "Operations"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "4XX": {
            "description": "A typed error. Branch on `error.code`, which is stable; messages are not."
          }
        }
      }
    },
    "/v1/operations/{id}/events": {
      "get": {
        "summary": "Replay the event log from a cursor.",
        "description": "Pass ?after=<event-id> to continue from where a client left off.",
        "tags": [
          "Operations"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "4XX": {
            "description": "A typed error. Branch on `error.code`, which is stable; messages are not."
          }
        }
      }
    },
    "/v1/operations/{id}/stream": {
      "get": {
        "summary": "Live event stream, resumable via Last-Event-ID.",
        "description": "Live event stream, resumable via Last-Event-ID.",
        "tags": [
          "Operations"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "4XX": {
            "description": "A typed error. Branch on `error.code`, which is stable; messages are not."
          }
        }
      }
    },
    "/v1/operations/{id}/cancel": {
      "post": {
        "summary": "Cancel an operation.",
        "description": "Cancel an operation.",
        "tags": [
          "Operations"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "4XX": {
            "description": "A typed error. Branch on `error.code`, which is stable; messages are not."
          }
        }
      }
    },
    "/v1/operations/{id}/retry-from-checkpoint": {
      "post": {
        "summary": "Restart from the last durable checkpoint.",
        "description": "Restart from the last durable checkpoint.",
        "tags": [
          "Operations"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "4XX": {
            "description": "A typed error. Branch on `error.code`, which is stable; messages are not."
          }
        }
      }
    },
    "/v1/evaluations": {
      "post": {
        "summary": "Run a blinded comparison of a candidate against a baseline.",
        "description": "Declares a cost ceiling; the job stops at the ceiling rather than exceeding it.",
        "tags": [
          "Evaluation"
        ],
        "security": [
          {
            "bearerAuth": [
              "runs:write"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "4XX": {
            "description": "A typed error. Branch on `error.code`, which is stable; messages are not."
          }
        }
      }
    },
    "/v1/evaluations/{id}": {
      "get": {
        "summary": "Evaluation state and summary.",
        "description": "Evaluation state and summary.",
        "tags": [
          "Evaluation"
        ],
        "security": [
          {
            "bearerAuth": [
              "runs:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "4XX": {
            "description": "A typed error. Branch on `error.code`, which is stable; messages are not."
          }
        }
      }
    },
    "/v1/evaluations/{id}/gate": {
      "get": {
        "summary": "The gate verdict: pass, fail or inconclusive, with win rate and interval.",
        "description": "The gate verdict: pass, fail or inconclusive, with win rate and interval.",
        "tags": [
          "Evaluation"
        ],
        "security": [
          {
            "bearerAuth": [
              "runs:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "4XX": {
            "description": "A typed error. Branch on `error.code`, which is stable; messages are not."
          }
        }
      }
    },
    "/v1/evaluations/{id}/results": {
      "get": {
        "summary": "Per-case results, including which side won and why.",
        "description": "Per-case results, including which side won and why.",
        "tags": [
          "Evaluation"
        ],
        "security": [
          {
            "bearerAuth": [
              "runs:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "4XX": {
            "description": "A typed error. Branch on `error.code`, which is stable; messages are not."
          }
        }
      }
    },
    "/v1/runs/{id}/publications": {
      "post": {
        "summary": "Publish a finished run to a model hub.",
        "description": "Weights and a generated model card only. Datasets are never included.",
        "tags": [
          "Publishing"
        ],
        "security": [
          {
            "bearerAuth": [
              "runs:write"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "4XX": {
            "description": "A typed error. Branch on `error.code`, which is stable; messages are not."
          }
        }
      },
      "get": {
        "summary": "Publications for a run.",
        "description": "Publications for a run.",
        "tags": [
          "Publishing"
        ],
        "security": [
          {
            "bearerAuth": [
              "runs:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "4XX": {
            "description": "A typed error. Branch on `error.code`, which is stable; messages are not."
          }
        }
      }
    },
    "/v1/publications/{id}": {
      "get": {
        "summary": "State of a single publication.",
        "description": "State of a single publication.",
        "tags": [
          "Publishing"
        ],
        "security": [
          {
            "bearerAuth": [
              "runs:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "4XX": {
            "description": "A typed error. Branch on `error.code`, which is stable; messages are not."
          }
        }
      }
    },
    "/v1/publications/{id}/cancel": {
      "post": {
        "summary": "Cancel an in-flight publication.",
        "description": "Cancel an in-flight publication.",
        "tags": [
          "Publishing"
        ],
        "security": [
          {
            "bearerAuth": [
              "runs:write"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "4XX": {
            "description": "A typed error. Branch on `error.code`, which is stable; messages are not."
          }
        }
      }
    },
    "/v1/runs/{id}/model-card": {
      "get": {
        "summary": "The generated model card, as markdown or JSON.",
        "description": "The generated model card, as markdown or JSON.",
        "tags": [
          "Publishing"
        ],
        "security": [
          {
            "bearerAuth": [
              "runs:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "4XX": {
            "description": "A typed error. Branch on `error.code`, which is stable; messages are not."
          }
        }
      }
    },
    "/v1/deployments": {
      "post": {
        "summary": "Create an endpoint for a finished run.",
        "description": "min_replicas 0 for scale-to-zero, 1 or more for always warm.",
        "tags": [
          "Deployments"
        ],
        "security": [
          {
            "bearerAuth": [
              "deployments:write"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "4XX": {
            "description": "A typed error. Branch on `error.code`, which is stable; messages are not."
          }
        }
      },
      "get": {
        "summary": "List endpoints with state and hourly rate.",
        "description": "List endpoints with state and hourly rate.",
        "tags": [
          "Deployments"
        ],
        "security": [
          {
            "bearerAuth": [
              "deployments:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "4XX": {
            "description": "A typed error. Branch on `error.code`, which is stable; messages are not."
          }
        }
      }
    },
    "/v1/deployments/{id}/warm": {
      "post": {
        "summary": "Bring a cold endpoint up before traffic arrives.",
        "description": "Bring a cold endpoint up before traffic arrives.",
        "tags": [
          "Deployments"
        ],
        "security": [
          {
            "bearerAuth": [
              "deployments:write"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "4XX": {
            "description": "A typed error. Branch on `error.code`, which is stable; messages are not."
          }
        }
      }
    },
    "/v1/deployments/{id}/retire": {
      "post": {
        "summary": "Retire an endpoint and release its capacity.",
        "description": "Retire an endpoint and release its capacity.",
        "tags": [
          "Deployments"
        ],
        "security": [
          {
            "bearerAuth": [
              "deployments:write"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "4XX": {
            "description": "A typed error. Branch on `error.code`, which is stable; messages are not."
          }
        }
      }
    },
    "/v1/deployments/{id}/resume": {
      "post": {
        "summary": "Return a retired endpoint to service.",
        "description": "Return a retired endpoint to service.",
        "tags": [
          "Deployments"
        ],
        "security": [
          {
            "bearerAuth": [
              "deployments:write"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "4XX": {
            "description": "A typed error. Branch on `error.code`, which is stable; messages are not."
          }
        }
      }
    },
    "/v1/deployments/{id}": {
      "get": {
        "summary": "A single endpoint, its URL and scaling configuration.",
        "description": "A single endpoint, its URL and scaling configuration.",
        "tags": [
          "Deployments"
        ],
        "security": [
          {
            "bearerAuth": [
              "deployments:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "4XX": {
            "description": "A typed error. Branch on `error.code`, which is stable; messages are not."
          }
        }
      }
    },
    "/v1/deployments/{id}/stream": {
      "get": {
        "summary": "Server-sent events for warm-up and scaling transitions.",
        "description": "Server-sent events for warm-up and scaling transitions.",
        "tags": [
          "Deployments"
        ],
        "security": [
          {
            "bearerAuth": [
              "deployments:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "4XX": {
            "description": "A typed error. Branch on `error.code`, which is stable; messages are not."
          }
        }
      }
    },
    "/v1/forecast/cost": {
      "get": {
        "summary": "Estimate a run’s cost before creating it.",
        "description": "Takes model, template and dataset size; returns an estimate and a wait-window indication.",
        "tags": [
          "Billing"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "4XX": {
            "description": "A typed error. Branch on `error.code`, which is stable; messages are not."
          }
        }
      }
    },
    "/v1/billing/entitlement": {
      "get": {
        "summary": "Plan, spend limit, reserved and settled amounts, available headroom.",
        "description": "Plan, spend limit, reserved and settled amounts, available headroom.",
        "tags": [
          "Billing"
        ],
        "security": [
          {
            "bearerAuth": [
              "billing:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "4XX": {
            "description": "A typed error. Branch on `error.code`, which is stable; messages are not."
          }
        }
      }
    },
    "/v1/billing/usage": {
      "get": {
        "summary": "Usage for the current period, including events not yet settled.",
        "description": "Usage for the current period, including events not yet settled.",
        "tags": [
          "Billing"
        ],
        "security": [
          {
            "bearerAuth": [
              "billing:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "4XX": {
            "description": "A typed error. Branch on `error.code`, which is stable; messages are not."
          }
        }
      }
    },
    "/v1/billing/invoices": {
      "get": {
        "summary": "Invoice history.",
        "description": "Invoice history.",
        "tags": [
          "Billing"
        ],
        "security": [
          {
            "bearerAuth": [
              "billing:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "4XX": {
            "description": "A typed error. Branch on `error.code`, which is stable; messages are not."
          }
        }
      }
    },
    "/v1/billing/portal-session": {
      "post": {
        "summary": "A short-lived link to the billing portal.",
        "description": "A short-lived link to the billing portal.",
        "tags": [
          "Billing"
        ],
        "security": [
          {
            "bearerAuth": [
              "session"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "4XX": {
            "description": "A typed error. Branch on `error.code`, which is stable; messages are not."
          }
        }
      }
    },
    "/{tenant}/{deployment}/v1/chat/completions": {
      "post": {
        "summary": "OpenAI-compatible chat completions. Served from serve.onrup.com.",
        "description": "Supports streaming, tool calling and structured output.",
        "tags": [
          "Inference"
        ],
        "security": [
          {
            "bearerAuth": [
              "deployments:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "4XX": {
            "description": "A typed error. Branch on `error.code`, which is stable; messages are not."
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Scopes: runs:read, runs:write, datasets:read, datasets:write, deployments:read, deployments:write, billing:read, keys:read, keys:write. Administrative actions require an interactive session and are unavailable to any API key."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "code",
              "message"
            ],
            "properties": {
              "code": {
                "type": "string",
                "enum": [
                  "auth.invalid_token",
                  "auth.insufficient_scope",
                  "billing.compute_not_entitled",
                  "billing.subscription_not_current",
                  "billing.spend_limit_exceeded",
                  "billing.invalid_estimate",
                  "dataset.validation_failed",
                  "dataset.unsupported_format",
                  "run.invalid_state",
                  "run.template_incompatible",
                  "deployment.capacity_unavailable",
                  "quota.exceeded",
                  "keys.scope_invalid"
                ]
              },
              "message": {
                "type": "string"
              },
              "detail": {
                "type": "object",
                "additionalProperties": true
              }
            }
          }
        }
      }
    }
  }
}