From 0e4c9ec064ebbbd0f8e1a3a7703c418b04ce501f Mon Sep 17 00:00:00 2001 From: "Marius F. Killinger" Date: Tue, 29 Sep 2026 16:54:44 -0700 Subject: [PATCH 01/15] Update management API spec from staging Staging spec (api.staging.baseten.co/v1/spec) adds the /v1/sandboxes surface over prod. Prod spec still serves 160 paths without sandboxes. Co-Authored-By: Claude Code --- scripts/apigen/specs/management.json | 34020 +++++++++++++++---------- 1 file changed, 20568 insertions(+), 13452 deletions(-) diff --git a/scripts/apigen/specs/management.json b/scripts/apigen/specs/management.json index 245594c..80e474c 100644 --- a/scripts/apigen/specs/management.json +++ b/scripts/apigen/specs/management.json @@ -6,7 +6,7 @@ }, "servers": [ { - "url": "https://api.baseten.co" + "url": "https://api.staging.baseten.co" } ], "security": [ @@ -21,14 +21,14 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/volumes \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/volumes \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/volumes\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'cursor': None, 'namespace': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/volumes\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'cursor': None, 'namespace': None}\n)\n\nprint(response.text)" } ], - "description": "Returns one row per volume in the namespace, each with its tags, head version, and version counts. Pass namespace to choose the namespace, which is required because the volume service has no cross-namespace inventory. Versions live on the versions sub-resource, so this response stays a fixed size per volume no matter how long a volume's history is.", + "description": "Returns one row per volume in the namespace, each with its tags, head version, version counts, and any scheduled expiry. Pass namespace to choose the namespace, which is required because the volume service has no cross-namespace inventory. Versions live on the versions sub-resource, so this response stays a fixed size per volume no matter how long a volume's history is. A volume with no live versions left, whether deleted or expired, is not listed.", "parameters": [ { "name": "cursor", @@ -93,11 +93,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/volumes/token \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"scopes\": null,\n \"namespaces\": null,\n \"volumes\": null,\n \"correlation_id\": null\n}'" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/volumes/token \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"scopes\": null,\n \"namespaces\": null,\n \"volumes\": null,\n \"correlation_id\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/volumes/token\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'scopes': None, 'namespaces': None, 'volumes': None, 'correlation_id': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/volumes/token\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'scopes': None, 'namespaces': None, 'volumes': None, 'correlation_id': None}\n)\n\nprint(response.text)" } ], "description": "Exchanges your API key for a short-lived token that authenticates against Baseten volume storage. A volume token is needed only to push and pull volume data; other volume operations use your API key directly. Tokens expire after one hour and cannot be renewed; exchange again for a fresh token. Push and tag capabilities require organization-level model management permission. Pass correlation_id to link the issued token to a client operation in server logs.", @@ -132,11 +132,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/volumes/namespaces \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/volumes/namespaces \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/volumes/namespaces\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'cursor': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/volumes/namespaces\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'cursor': None}\n)\n\nprint(response.text)" } ], "description": "Returns the namespaces that hold volumes your API key can read, in lowercase. Namespaces are not created directly: a namespace comes into existence when the first volume is pushed into it.", @@ -188,17 +188,201 @@ "x-stability": "unstable" } }, + "/v1/volumes/syncs": { + "get": { + "summary": "Lists volume syncs", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/volumes/syncs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/volumes/syncs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'cursor': None, 'ref': None}\n)\n\nprint(response.text)" + } + ], + "description": "Lists volume syncs in the active workspace, newest first. Results may be narrowed by an exact destination ref.", + "parameters": [ + { + "name": "cursor", + "in": "query", + "required": false, + "description": "Opaque cursor returned by a previous page. Omit to fetch the first page.", + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Cursor" + } + }, + { + "name": "limit", + "in": "query", + "required": false, + "description": "Maximum number of items to return.", + "schema": { + "default": 100, + "maximum": 1000, + "minimum": 1, + "title": "Limit", + "type": "integer" + } + }, + { + "name": "ref", + "in": "query", + "required": false, + "description": "Exact destination reference to match.", + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Ref" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VolumeSyncsV1" + } + } + } + } + }, + "x-stability": "unstable" + }, + "post": { + "summary": "Starts a volume sync", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/volumes/syncs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"source\": null,\n \"destination\": {\n \"ref\": null\n }\n}'" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/volumes/syncs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'source': None, 'destination': {'ref': None}}\n)\n\nprint(response.text)" + } + ], + "description": "Starts one durable asynchronous transfer from a remote source into a BDN volume.", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateVolumeSyncRequestV1" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VolumeSyncV1" + } + } + } + } + }, + "x-stability": "unstable" + } + }, + "/v1/volumes/syncs/{volume_sync_id}": { + "get": { + "summary": "Gets a volume sync", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/volumes/syncs/{volume_sync_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/volumes/syncs/{volume_sync_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VolumeSyncV1" + } + } + } + } + }, + "x-stability": "unstable" + }, + "parameters": [ + { + "$ref": "#/components/parameters/volume_sync_id" + } + ] + }, + "/v1/volumes/syncs/{volume_sync_id}/cancel": { + "post": { + "summary": "Cancels a volume sync", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/volumes/syncs/{volume_sync_id}/cancel \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/volumes/syncs/{volume_sync_id}/cancel\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + } + ], + "description": "Requests cancellation of a pending or running sync. Repeated cancellation and cancellation of terminal syncs return the existing state. Once cancellation is accepted, a later completion callback cannot replace the CANCELED state.", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VolumeSyncV1" + } + } + } + } + }, + "x-stability": "unstable" + }, + "parameters": [ + { + "$ref": "#/components/parameters/volume_sync_id" + } + ] + }, "/v1/volumes/{volume_namespace}/{volume_name}": { "delete": { "summary": "Deletes a volume", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/volumes/{volume_namespace}/{volume_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"expected_sequence\": null\n}'" + "source": "curl --request DELETE \\\n--url https://api.staging.baseten.co/v1/volumes/{volume_namespace}/{volume_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"expected_sequence\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/volumes/{volume_namespace}/{volume_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={'expected_sequence': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/volumes/{volume_namespace}/{volume_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={'expected_sequence': None}\n)\n\nprint(response.text)" } ], "description": "Deletes every live version of the volume, after which the volume stops appearing in listings. The data is not erased: each version stays restorable until its recovery deadline passes, and the versions sub-resource still reports them when you pass include_tombstoned. Deleting a volume that has no live versions left succeeds and reports zero versions deleted.", @@ -239,14 +423,14 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/volumes/{volume_namespace}/{volume_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/volumes/{volume_namespace}/{volume_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/volumes/{volume_namespace}/{volume_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/volumes/{volume_namespace}/{volume_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Returns a volume with its tags, head version, and version counts. Versions live on the versions sub-resource so they can be paged separately.", + "description": "Returns a volume with its tags, head version, version counts, and any scheduled expiry. Versions live on the versions sub-resource so they can be paged separately. A volume whose versions have all been deleted or have expired is still returned, with zero live versions.", "responses": { "200": { "description": "", @@ -268,20 +452,20 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/volumes/{volume_namespace}/{volume_name}/versions \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/volumes/{volume_namespace}/{volume_name}/versions \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/volumes/{volume_namespace}/{volume_name}/versions\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/volumes/{volume_namespace}/{volume_name}/versions\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={}\n)\n\nprint(response.text)" } ], - "description": "Returns every live version of the volume, newest first, each with its digest, size, lifecycle, and the tags pointing at it. Pass include_tombstoned to list deleted versions alongside them.", + "description": "Returns every live version of the volume, newest first, each with its digest, size, lifecycle, the tags pointing at it, and any scheduled expiry. Pass include_tombstoned to list deleted and expired versions alongside them.", "parameters": [ { "name": "include_tombstoned", "in": "query", "required": false, - "description": "Whether to include deleted versions. A deleted version carries a TOMBSTONED lifecycle and stays restorable until its recovery deadline passes.", + "description": "Whether to include deleted and expired versions. Such a version carries a TOMBSTONED lifecycle and stays restorable until its recovery deadline passes.", "schema": { "default": false, "title": "Include Tombstoned", @@ -318,11 +502,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/volumes/{volume_namespace}/{volume_name}/versions/{volume_version} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"expected_sequence\": null\n}'" + "source": "curl --request DELETE \\\n--url https://api.staging.baseten.co/v1/volumes/{volume_namespace}/{volume_name}/versions/{volume_version} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"expected_sequence\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/volumes/{volume_namespace}/{volume_name}/versions/{volume_version}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={'expected_sequence': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/volumes/{volume_namespace}/{volume_name}/versions/{volume_version}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={'expected_sequence': None}\n)\n\nprint(response.text)" } ], "description": "Deletes the version the address names, along with every tag pointing at it. Addressing the version by tag deletes the version the tag points at, not the tag. The data is not erased: the version stays restorable until the recovery deadline in the response passes. Deleting a version that is already deleted is a conflict, not a repeat success.", @@ -366,11 +550,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/volumes/{volume_namespace}/{volume_name}/versions/{volume_version} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/volumes/{volume_namespace}/{volume_name}/versions/{volume_version} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/volumes/{volume_namespace}/{volume_name}/versions/{volume_version}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/volumes/{volume_namespace}/{volume_name}/versions/{volume_version}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Returns a single version of the volume. Address it with `:` for a tag, `@` for a full content digest or a prefix of at least 12 hexadecimal characters, or `head` for the version a reference with no tag or digest resolves to. A digest prefix that matches more than one version is rejected: supply more characters.", @@ -391,18 +575,18 @@ }, "/v1/volumes/{volume_namespace}/{volume_name}/versions/{volume_version}/restore": { "post": { - "summary": "Restores a deleted version of a volume", + "summary": "Restores a deleted or expired version of a volume", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/volumes/{volume_namespace}/{volume_name}/versions/{volume_version}/restore \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"expected_sequence\": null\n}'" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/volumes/{volume_namespace}/{volume_name}/versions/{volume_version}/restore \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"expected_sequence\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/volumes/{volume_namespace}/{volume_name}/versions/{volume_version}/restore\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'expected_sequence': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/volumes/{volume_namespace}/{volume_name}/versions/{volume_version}/restore\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'expected_sequence': None}\n)\n\nprint(response.text)" } ], - "description": "Returns a deleted version to service, provided its recovery deadline has not passed. The tags the version carried when it was deleted are not restored with it, so re-tag it if anything depended on those. Address the version by digest: a deleted version has no tags left to name it by.", + "description": "Returns a deleted or expired version to service, provided its recovery deadline has not passed. The tags the version carried are not restored with it, so re-tag it if anything depended on those, and a restored version never expires until something sets a new expiry. Address the version by digest: a tombstoned version has no tags left to name it by.", "requestBody": { "content": { "application/json": { @@ -439,17 +623,56 @@ } ] }, + "/v1/token": { + "post": { + "summary": "Creates a sandbox access token", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/token \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"scopes\": [\n \"sandboxes\"\n ]\n}'" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/token\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'scopes': ['sandboxes']}\n)\n\nprint(response.text)" + } + ], + "description": "Exchanges your Baseten credentials for a short-lived token that authenticates against the sandbox API. The token carries every team you belong to. Tokens expire after two hours and cannot be renewed; request a new one when needed. This endpoint is experimental and may change or be removed without notice.", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateTokenRequestV1" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TokenV1" + } + } + } + } + }, + "x-stability": "unstable" + } + }, "/v1/secrets": { "get": { "summary": "Gets all secrets (metadata only, no plain text keys)", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/secrets \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/secrets \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/secrets\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/secrets\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "responses": { @@ -470,11 +693,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/secrets \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"name\": \"my_secret\",\n \"value\": \"my_secret_value\"\n}'" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/secrets \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"name\": \"my_secret\",\n \"value\": \"my_secret_value\"\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/secrets\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'name': 'my_secret', 'value': 'my_secret_value'}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/secrets\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'name': 'my_secret', 'value': 'my_secret_value'}\n)\n\nprint(response.text)" } ], "description": "Creates or updates a secret by name. Scoped to the caller's primary team; use the team-scoped variant to target a specific team.", @@ -508,11 +731,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/secrets/{secret_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request DELETE \\\n--url https://api.staging.baseten.co/v1/secrets/{secret_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/secrets/{secret_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/secrets/{secret_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Deletes a secret by name in the specified team, or in the caller's organization default team when no team is specified.", @@ -541,11 +764,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/teams/{team_id}/secrets \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/teams/{team_id}/secrets \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}/secrets\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/teams/{team_id}/secrets\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "responses": { @@ -571,11 +794,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/teams/{team_id}/secrets \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"name\": \"my_secret\",\n \"value\": \"my_secret_value\"\n}'" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/teams/{team_id}/secrets \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"name\": \"my_secret\",\n \"value\": \"my_secret_value\"\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}/secrets\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'name': 'my_secret', 'value': 'my_secret_value'}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/teams/{team_id}/secrets\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'name': 'my_secret', 'value': 'my_secret_value'}\n)\n\nprint(response.text)" } ], "description": "Creates a new secret or updates an existing secret if one with the provided name already exists. The name and creation date of the created or updated secret is returned. This secret belongs to the specified team", @@ -609,11 +832,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/teams/{team_id}/secrets/{secret_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request DELETE \\\n--url https://api.staging.baseten.co/v1/teams/{team_id}/secrets/{secret_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}/secrets/{secret_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/teams/{team_id}/secrets/{secret_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Deletes a secret by name in the specified team, or in the caller's organization default team when no team is specified.", @@ -645,11 +868,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/environment_groups \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/environment_groups \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/environment_groups\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/environment_groups\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Lists environment groups. The team-scoped path targets the team in the path; the top-level path targets the caller's organization default team.", @@ -673,11 +896,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/environment_groups/{env_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/environment_groups/{env_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/environment_groups/{env_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/environment_groups/{env_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Gets a single environment group by name. The team-scoped path targets the team in the path; the top-level path targets the caller's organization default team.", @@ -704,11 +927,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/environment_groups/{env_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"manage_access\": null\n}'" + "source": "curl --request PATCH \\\n--url https://api.staging.baseten.co/v1/environment_groups/{env_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"manage_access\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/environment_groups/{env_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'manage_access': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/environment_groups/{env_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'manage_access': None}\n)\n\nprint(response.text)" } ], "description": "Sets whether the environment is restricted and replaces the list of users granted manage access. The team-scoped path targets the team in the path; the top-level path targets the caller's organization default team.", @@ -742,11 +965,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/teams/{team_id}/environment_groups \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/teams/{team_id}/environment_groups \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}/environment_groups\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/teams/{team_id}/environment_groups\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Lists environment groups. The team-scoped path targets the team in the path; the top-level path targets the caller's organization default team.", @@ -775,11 +998,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/teams/{team_id}/environment_groups/{env_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/teams/{team_id}/environment_groups/{env_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}/environment_groups/{env_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/teams/{team_id}/environment_groups/{env_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Gets a single environment group by name. The team-scoped path targets the team in the path; the top-level path targets the caller's organization default team.", @@ -809,11 +1032,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/teams/{team_id}/environment_groups/{env_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"manage_access\": null\n}'" + "source": "curl --request PATCH \\\n--url https://api.staging.baseten.co/v1/teams/{team_id}/environment_groups/{env_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"manage_access\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}/environment_groups/{env_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'manage_access': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/teams/{team_id}/environment_groups/{env_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'manage_access': None}\n)\n\nprint(response.text)" } ], "description": "Sets whether the environment is restricted and replaces the list of users granted manage access. The team-scoped path targets the team in the path; the top-level path targets the caller's organization default team.", @@ -847,11 +1070,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/teams \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/teams \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'name': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/teams\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'name': None}\n)\n\nprint(response.text)" } ], "description": "Returns a list of all teams the authenticated user has access to.", @@ -895,11 +1118,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/teams/{team_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/teams/{team_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/teams/{team_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Returns a team the authenticated user has access to.", @@ -928,11 +1151,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/regions \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/regions \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/regions\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/regions\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Lists the regions available for new deployments in the caller's organization.", @@ -957,11 +1180,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/teams/{team_id}/regions \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/teams/{team_id}/regions \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}/regions\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/teams/{team_id}/regions\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Lists the regions the team specified in the path can place deployments in.", @@ -991,11 +1214,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/instance_types \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/instance_types \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/instance_types\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/instance_types\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "responses": { @@ -1018,11 +1241,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/loops/user_config \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/loops/user_config \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/user_config\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/loops/user_config\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Returns the caller's Loops user config (per-user accelerator priorities). Null fields mean 'inherit the org-level allowlist'.", @@ -1044,11 +1267,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/loops/user_config \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"trainer_accelerator_priority\": [\n \"H100\",\n \"H200\"\n ],\n \"sampler_accelerator_priority\": [\n \"H100\",\n \"H200\"\n ]\n}'" + "source": "curl --request PATCH \\\n--url https://api.staging.baseten.co/v1/loops/user_config \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"trainer_accelerator_priority\": [\n \"H100\",\n \"H200\"\n ],\n \"sampler_accelerator_priority\": [\n \"H100\",\n \"H200\"\n ]\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/user_config\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'trainer_accelerator_priority': ['H100', 'H200'], 'sampler_accelerator_priority': ['H100', 'H200']}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/loops/user_config\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'trainer_accelerator_priority': ['H100', 'H200'], 'sampler_accelerator_priority': ['H100', 'H200']}\n)\n\nprint(response.text)" } ], "description": "Updates the caller's Loops user config using JSON Merge Patch (RFC 7396) semantics per field: omit a field to leave it unchanged, send null to clear (inherit the org-level allowlist), or send a list to set the allowlist. Empty lists are rejected.", @@ -1082,11 +1305,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/instance_type_prices \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/instance_type_prices \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/instance_type_prices\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/instance_type_prices\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "responses": { @@ -1109,11 +1332,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/prepare_model_upload \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"deployment\": {\n \"config\": null,\n \"raw_config\": null,\n \"user_env\": null,\n \"environment_name\": null,\n \"region\": null,\n \"deploy_timeout_minutes\": null,\n \"deployment_name\": null,\n \"labels\": null\n },\n \"name\": null,\n \"team_id\": null,\n \"model_id\": null\n}'" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/prepare_model_upload \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"deployment\": {\n \"config\": null,\n \"raw_config\": null,\n \"user_env\": null,\n \"environment_name\": null,\n \"region\": null,\n \"deploy_timeout_minutes\": null,\n \"deployment_name\": null,\n \"labels\": null\n },\n \"name\": null,\n \"team_id\": null,\n \"model_id\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/prepare_model_upload\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'deployment': {'config': None, 'raw_config': None, 'user_env': None, 'environment_name': None, 'region': None, 'deploy_timeout_minutes': None, 'deployment_name': None, 'labels': None}, 'name': None, 'team_id': None, 'model_id': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/prepare_model_upload\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'deployment': {'config': None, 'raw_config': None, 'user_env': None, 'environment_name': None, 'region': None, 'deploy_timeout_minutes': None, 'deployment_name': None, 'labels': None}, 'name': None, 'team_id': None, 'model_id': None}\n)\n\nprint(response.text)" } ], "requestBody": { @@ -1146,11 +1369,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/audit_logs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/audit_logs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/audit_logs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'cursor': None, 'direction': 'DESC', 'search': None, 'start_epoch_millis': None, 'end_epoch_millis': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/audit_logs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'cursor': None, 'direction': 'DESC', 'search': None, 'start_epoch_millis': None, 'end_epoch_millis': None}\n)\n\nprint(response.text)" } ], "description": "Returns audit-log entries across the workspace, newest first, covering models, chains, and workspace-level actions. Use the filters to narrow by event type, actor, resource, environment, source, or time window, and the cursor to page. In workspaces with multiple teams, only organization admins can read the workspace audit log.", @@ -1349,11 +1572,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/models \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'name': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'name': None}\n)\n\nprint(response.text)" } ], "parameters": [ @@ -1394,11 +1617,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"source\": null\n}'" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/models \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"source\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'source': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'source': None}\n)\n\nprint(response.text)" } ], "description": "Creates a new model in the caller's organization. The `source` field selects how the model is constructed (currently `library_listing`, which forks an accessible listing from `GET /v1/library_models`). The deployment isn't instantly ready; poll the GET endpoint until status is ACTIVE.", @@ -1432,11 +1655,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/teams/{team_id}/models \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/teams/{team_id}/models \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}/models\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'name': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/teams/{team_id}/models\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'name': None}\n)\n\nprint(response.text)" } ], "parameters": [ @@ -1482,11 +1705,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/teams/{team_id}/models \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"source\": null\n}'" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/teams/{team_id}/models \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"source\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}/models\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'source': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/teams/{team_id}/models\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'source': None}\n)\n\nprint(response.text)" } ], "description": "Creates a new model in the caller's organization. The `source` field selects how the model is constructed (currently `library_listing`, which forks an accessible listing from `GET /v1/library_models`). The deployment isn't instantly ready; poll the GET endpoint until status is ACTIVE.", @@ -1520,11 +1743,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/models/{model_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request DELETE \\\n--url https://api.staging.baseten.co/v1/models/{model_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "responses": { @@ -1550,13 +1773,49 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models/{model_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/models/{model_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ModelV1" + } + } + } + } + } + }, + "patch": { + "summary": "Updates a model by ID", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request PATCH \\\n--url https://api.staging.baseten.co/v1/models/{model_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"name\": \"my-model\"\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'name': 'my-model'}\n)\n\nprint(response.text)" } ], + "description": "Updates the mutable fields of a model and returns the updated model. Renaming does not change the model ID, endpoints, or deployments. Pushes that still use the old model_name create another model or target a model that now uses that name, so update config.yaml after renaming.", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateModelRequestV1" + } + } + }, + "required": true + }, "responses": { "200": { "description": "", @@ -1577,11 +1836,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models/{model_id}/audit_logs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/audit_logs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/audit_logs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'cursor': None, 'direction': 'DESC', 'search': None, 'start_epoch_millis': None, 'end_epoch_millis': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/audit_logs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'cursor': None, 'direction': 'DESC', 'search': None, 'start_epoch_millis': None, 'end_epoch_millis': None}\n)\n\nprint(response.text)" } ], "description": "Returns audit-log entries for a single model, newest first. Use the filters to narrow by event type, actor, deployment, environment, source, or time window, and the cursor to page.", @@ -1785,11 +2044,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'name': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'name': None}\n)\n\nprint(response.text)" } ], "parameters": [ @@ -1835,11 +2094,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"source\": null\n}'" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"source\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'source': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'source': None}\n)\n\nprint(response.text)" } ], "requestBody": { @@ -1872,11 +2131,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/development \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/development \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/development\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/development\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Gets a model's development deployment and returns the deployment.", @@ -1905,11 +2164,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/production \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/production \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/production\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/production\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Gets a model's production deployment and returns the deployment.", @@ -1938,11 +2197,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request DELETE \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Deletes a model's deployment by ID and returns the tombstone of the deployment.", @@ -1972,11 +2231,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Gets a model's deployment by ID and returns the deployment.", @@ -1998,11 +2257,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"name\": \"my-deployment\"\n}'" + "source": "curl --request PATCH \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"name\": \"my-deployment\"\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'name': 'my-deployment'}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'name': 'my-deployment'}\n)\n\nprint(response.text)" } ], "description": "Updates the mutable fields of a deployment and returns the updated deployment.", @@ -2036,11 +2295,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/development/autoscaling_settings \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"min_replica\": 0,\n \"max_replica\": 7,\n \"autoscaling_window\": 600,\n \"scale_down_delay\": 120,\n \"concurrency_target\": 2,\n \"target_utilization_percentage\": 70,\n \"target_in_flight_tokens\": 40000,\n \"max_scale_down_rate\": 20\n}'" + "source": "curl --request PATCH \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/development/autoscaling_settings \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"min_replica\": 0,\n \"max_replica\": 7,\n \"autoscaling_window\": 600,\n \"scale_down_delay\": 120,\n \"concurrency_target\": 2,\n \"target_utilization_percentage\": 70,\n \"target_in_flight_tokens\": 40000,\n \"max_scale_down_rate\": 20\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/development/autoscaling_settings\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'min_replica': 0, 'max_replica': 7, 'autoscaling_window': 600, 'scale_down_delay': 120, 'concurrency_target': 2, 'target_utilization_percentage': 70, 'target_in_flight_tokens': 40000, 'max_scale_down_rate': 20}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/development/autoscaling_settings\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'min_replica': 0, 'max_replica': 7, 'autoscaling_window': 600, 'scale_down_delay': 120, 'concurrency_target': 2, 'target_utilization_percentage': 70, 'target_in_flight_tokens': 40000, 'max_scale_down_rate': 20}\n)\n\nprint(response.text)" } ], "description": "Updates a development deployment's autoscaling settings and returns the update status.", @@ -2079,11 +2338,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/production/autoscaling_settings \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"min_replica\": 0,\n \"max_replica\": 7,\n \"autoscaling_window\": 600,\n \"scale_down_delay\": 120,\n \"concurrency_target\": 2,\n \"target_utilization_percentage\": 70,\n \"target_in_flight_tokens\": 40000,\n \"max_scale_down_rate\": 20\n}'" + "source": "curl --request PATCH \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/production/autoscaling_settings \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"min_replica\": 0,\n \"max_replica\": 7,\n \"autoscaling_window\": 600,\n \"scale_down_delay\": 120,\n \"concurrency_target\": 2,\n \"target_utilization_percentage\": 70,\n \"target_in_flight_tokens\": 40000,\n \"max_scale_down_rate\": 20\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/production/autoscaling_settings\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'min_replica': 0, 'max_replica': 7, 'autoscaling_window': 600, 'scale_down_delay': 120, 'concurrency_target': 2, 'target_utilization_percentage': 70, 'target_in_flight_tokens': 40000, 'max_scale_down_rate': 20}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/production/autoscaling_settings\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'min_replica': 0, 'max_replica': 7, 'autoscaling_window': 600, 'scale_down_delay': 120, 'concurrency_target': 2, 'target_utilization_percentage': 70, 'target_in_flight_tokens': 40000, 'max_scale_down_rate': 20}\n)\n\nprint(response.text)" } ], "description": "Updates a production deployment's autoscaling settings and returns the update status.", @@ -2122,11 +2381,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/autoscaling_settings \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"min_replica\": 0,\n \"max_replica\": 7,\n \"autoscaling_window\": 600,\n \"scale_down_delay\": 120,\n \"concurrency_target\": 2,\n \"target_utilization_percentage\": 70,\n \"target_in_flight_tokens\": 40000,\n \"max_scale_down_rate\": 20\n}'" + "source": "curl --request PATCH \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/autoscaling_settings \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"min_replica\": 0,\n \"max_replica\": 7,\n \"autoscaling_window\": 600,\n \"scale_down_delay\": 120,\n \"concurrency_target\": 2,\n \"target_utilization_percentage\": 70,\n \"target_in_flight_tokens\": 40000,\n \"max_scale_down_rate\": 20\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/autoscaling_settings\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'min_replica': 0, 'max_replica': 7, 'autoscaling_window': 600, 'scale_down_delay': 120, 'concurrency_target': 2, 'target_utilization_percentage': 70, 'target_in_flight_tokens': 40000, 'max_scale_down_rate': 20}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/autoscaling_settings\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'min_replica': 0, 'max_replica': 7, 'autoscaling_window': 600, 'scale_down_delay': 120, 'concurrency_target': 2, 'target_utilization_percentage': 70, 'target_in_flight_tokens': 40000, 'max_scale_down_rate': 20}\n)\n\nprint(response.text)" } ], "description": "Updates a deployment's autoscaling settings and returns the update status.", @@ -2168,11 +2427,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/request_backpressure_settings \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"policy\": \"REJECT_ON_FULL\"\n}'" + "source": "curl --request PATCH \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/request_backpressure_settings \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"policy\": \"REJECT_ON_FULL\"\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/request_backpressure_settings\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'policy': 'REJECT_ON_FULL'}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/request_backpressure_settings\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'policy': 'REJECT_ON_FULL'}\n)\n\nprint(response.text)" } ], "requestBody": { @@ -2213,11 +2472,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/development/promote \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"scale_down_previous_production\": true,\n \"preserve_env_instance_type\": true\n}'" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/development/promote \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"scale_down_previous_production\": true,\n \"preserve_env_instance_type\": true\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/development/promote\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'scale_down_previous_production': True, 'preserve_env_instance_type': True}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/development/promote\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'scale_down_previous_production': True, 'preserve_env_instance_type': True}\n)\n\nprint(response.text)" } ], "description": "Creates a new production deployment from the development deployment and returns the deployment that is building.", @@ -2256,11 +2515,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/promote \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"scale_down_previous_production\": true,\n \"preserve_env_instance_type\": true\n}'" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/promote \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"scale_down_previous_production\": true,\n \"preserve_env_instance_type\": true\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/promote\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'scale_down_previous_production': True, 'preserve_env_instance_type': True}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/promote\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'scale_down_previous_production': True, 'preserve_env_instance_type': True}\n)\n\nprint(response.text)" } ], "description": "Promotes an existing deployment to production and returns the same deployment.", @@ -2302,11 +2561,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/development/activate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/development/activate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/development/activate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/development/activate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Activates a development deployment if not already activated.", @@ -2335,11 +2594,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/production/activate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/production/activate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/production/activate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/production/activate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Activates a production deployment if not already activated.", @@ -2368,11 +2627,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/activate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/activate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/activate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/activate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Activates a deployment if not already activated.", @@ -2404,11 +2663,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/development/deactivate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/development/deactivate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/development/deactivate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/development/deactivate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Deactivates a development deployment if not already deactivated.", @@ -2437,11 +2696,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/production/deactivate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/production/deactivate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/production/deactivate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/production/deactivate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Deactivates a production deployment if not already deactivated.", @@ -2470,11 +2729,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/deactivate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/deactivate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/deactivate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/deactivate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Deactivates a deployment if not already deactivated.", @@ -2506,11 +2765,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/development/retry \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/development/retry \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/development/retry\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/development/retry\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Retries a failed development deployment and returns the retry status and updated deployment.", @@ -2539,11 +2798,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/production/retry \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/production/retry \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/production/retry\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/production/retry\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Retries a failed production deployment and returns the retry status and updated deployment.", @@ -2572,11 +2831,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/retry \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/retry \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/retry\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/retry\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Retries a failed deployment and returns the retry status and updated deployment.", @@ -2608,11 +2867,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/download \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/download \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/download\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/download\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Gets a presigned URL to download the truss tar file for a deployment.", @@ -2644,11 +2903,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/config \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/config \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/config\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'output_format': 'raw'}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/config\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'output_format': 'raw'}\n)\n\nprint(response.text)" } ], "description": "Returns the deployment's config. `output_format` query param picks the shape: 'raw' (config.yaml text), 'parsed' (dict with defaults), or 'both' (default).", @@ -2692,11 +2951,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/logs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/logs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/logs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'start_epoch_millis': None, 'end_epoch_millis': None, 'direction': None, 'limit': None, 'min_level': None, 'replica': None, 'request_id': None, 'component': None, 'search_pattern': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/logs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'start_epoch_millis': None, 'end_epoch_millis': None, 'direction': None, 'limit': None, 'min_level': None, 'replica': None, 'request_id': None, 'component': None, 'search_pattern': None}\n)\n\nprint(response.text)" } ], "description": "Gets all the logs for a model deployment in the given time range, which defaults to the last 30 minutes. A failed or older deployment may only have logs from before that window; pass `start_epoch_millis` to widen it back to the build/deploy time.", @@ -2922,11 +3181,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/logs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"start_epoch_millis\": null,\n \"end_epoch_millis\": null,\n \"direction\": null,\n \"limit\": null,\n \"min_level\": null,\n \"replica\": null,\n \"request_id\": null,\n \"component\": null,\n \"search_pattern\": null\n}'" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/logs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"start_epoch_millis\": null,\n \"end_epoch_millis\": null,\n \"direction\": null,\n \"limit\": null,\n \"min_level\": null,\n \"replica\": null,\n \"request_id\": null,\n \"component\": null,\n \"search_pattern\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/logs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'start_epoch_millis': None, 'end_epoch_millis': None, 'direction': None, 'limit': None, 'min_level': None, 'replica': None, 'request_id': None, 'component': None, 'search_pattern': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/logs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'start_epoch_millis': None, 'end_epoch_millis': None, 'direction': None, 'limit': None, 'min_level': None, 'replica': None, 'request_id': None, 'component': None, 'search_pattern': None}\n)\n\nprint(response.text)" } ], "description": "Use the GET form on this path instead.", @@ -2962,11 +3221,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/patches \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"prev_patch_hash\": null,\n \"next_patch_point\": {\n \"content_hashes\": null,\n \"config\": null\n },\n \"patch_ops\": null\n}'" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/patches \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"prev_patch_hash\": null,\n \"next_patch_point\": {\n \"content_hashes\": null,\n \"config\": null\n },\n \"patch_ops\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/patches\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'prev_patch_hash': None, 'next_patch_point': {'content_hashes': None, 'config': None}, 'patch_ops': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/patches\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'prev_patch_hash': None, 'next_patch_point': {'content_hashes': None, 'config': None}, 'patch_ops': None}\n)\n\nprint(response.text)" } ], "description": "Persists a patch durably without applying it; call the sync endpoint to apply staged patches to the running deployment. The target must be a development deployment (its archive created with `is_development` set to `true`); patching any other deployment is rejected.", @@ -3009,11 +3268,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/patches/state \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/patches/state \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/patches/state\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/patches/state\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Returns the patch point the deployment is recorded as running and the latest staged-but-unsynced point, if any. The watch client computes its next patch off the pending point when present, else the running point.", @@ -3046,11 +3305,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/patches/sync \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{}'" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/patches/sync \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/patches/sync\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/patches/sync\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Applies any staged patches to the running deployment. A 2xx response means the sync reached a verdict: in sync, or a full push is required (needs_full_deploy_reason). A 503 means the sync was not attempted or failed recoverably and should be retried; any other error is terminal.", @@ -3093,11 +3352,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/metrics \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/metrics \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/metrics\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'mode': 'CURRENT', 'start_epoch_millis': None, 'end_epoch_millis': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/metrics\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'mode': 'CURRENT', 'start_epoch_millis': None, 'end_epoch_millis': None}\n)\n\nprint(response.text)" } ], "description": "Gets the metrics for a model deployment in the given time range.", @@ -3191,11 +3450,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/replicas/{replica_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request DELETE \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/replicas/{replica_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/replicas/{replica_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/replicas/{replica_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Terminates a deployment replica and returns the termination status.", @@ -3230,11 +3489,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/ssh/sign \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"public_key\": null,\n \"replica_id\": null\n}'" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/ssh/sign \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"public_key\": null,\n \"replica_id\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/ssh/sign\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'public_key': None, 'replica_id': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/ssh/sign\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'public_key': None, 'replica_id': None}\n)\n\nprint(response.text)" } ], "description": "Signs a short-lived SSH certificate granting access to a running inference model pod. Returns the signed SSH certificate, a JWT token for SSH proxy authentication, the proxy address to connect through, and the certificate expiry time.", @@ -3276,11 +3535,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models/{model_id}/environments \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/environments \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/environments\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/environments\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Gets all environments for a given model.", @@ -3307,11 +3566,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/environments \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"name\": \"staging\",\n \"autoscaling_settings\": {\n \"autoscaling_window\": 800,\n \"concurrency_target\": 3,\n \"max_replica\": 2,\n \"max_scale_down_rate\": null,\n \"min_replica\": 1,\n \"scale_down_delay\": 60,\n \"target_in_flight_tokens\": null,\n \"target_utilization_percentage\": null\n },\n \"promotion_settings\": {\n \"promotion_cleanup_strategy\": null,\n \"ramp_up_duration_seconds\": 600,\n \"ramp_up_while_promoting\": true,\n \"redeploy_on_promotion\": true,\n \"rolling_deploy\": true,\n \"rolling_deploy_config\": null\n },\n \"request_backpressure_settings\": null\n}'" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/environments \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"name\": \"staging\",\n \"autoscaling_settings\": {\n \"autoscaling_window\": 800,\n \"concurrency_target\": 3,\n \"max_replica\": 2,\n \"max_scale_down_rate\": null,\n \"min_replica\": 1,\n \"scale_down_delay\": 60,\n \"target_in_flight_tokens\": null,\n \"target_utilization_percentage\": null\n },\n \"promotion_settings\": {\n \"promotion_cleanup_strategy\": null,\n \"ramp_up_duration_seconds\": 600,\n \"ramp_up_while_promoting\": true,\n \"redeploy_on_promotion\": true,\n \"rolling_deploy\": false,\n \"rolling_deploy_config\": null\n },\n \"request_backpressure_settings\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/environments\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'name': 'staging', 'autoscaling_settings': {'autoscaling_window': 800, 'concurrency_target': 3, 'max_replica': 2, 'max_scale_down_rate': None, 'min_replica': 1, 'scale_down_delay': 60, 'target_in_flight_tokens': None, 'target_utilization_percentage': None}, 'promotion_settings': {'promotion_cleanup_strategy': None, 'ramp_up_duration_seconds': 600, 'ramp_up_while_promoting': True, 'redeploy_on_promotion': True, 'rolling_deploy': True, 'rolling_deploy_config': None}, 'request_backpressure_settings': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/environments\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'name': 'staging', 'autoscaling_settings': {'autoscaling_window': 800, 'concurrency_target': 3, 'max_replica': 2, 'max_scale_down_rate': None, 'min_replica': 1, 'scale_down_delay': 60, 'target_in_flight_tokens': None, 'target_utilization_percentage': None}, 'promotion_settings': {'promotion_cleanup_strategy': None, 'ramp_up_duration_seconds': 600, 'ramp_up_while_promoting': True, 'redeploy_on_promotion': True, 'rolling_deploy': False, 'rolling_deploy_config': None}, 'request_backpressure_settings': None}\n)\n\nprint(response.text)" } ], "description": "Creates an environment for the specified model and returns the environment.", @@ -3345,11 +3604,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/models/{model_id}/environments/{env_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request DELETE \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/environments/{env_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/environments/{env_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/environments/{env_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Deletes an environment and returns its tombstone. Any in-progress promotion to the environment is canceled, and the deployment currently serving the environment is scaled down to zero replicas rather than deleted. The production environment cannot be deleted.", @@ -3379,11 +3638,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models/{model_id}/environments/{env_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/environments/{env_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/environments/{env_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/environments/{env_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Gets an environment's details and returns the environment.", @@ -3405,11 +3664,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/models/{model_id}/environments/{env_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"autoscaling_settings\": {\n \"autoscaling_window\": 800,\n \"concurrency_target\": 3,\n \"max_replica\": 2,\n \"max_scale_down_rate\": null,\n \"min_replica\": 1,\n \"scale_down_delay\": 60,\n \"target_in_flight_tokens\": null,\n \"target_utilization_percentage\": null\n },\n \"promotion_settings\": {\n \"promotion_cleanup_strategy\": null,\n \"ramp_up_duration_seconds\": 600,\n \"ramp_up_while_promoting\": true,\n \"redeploy_on_promotion\": true,\n \"rolling_deploy\": null,\n \"rolling_deploy_config\": null\n },\n \"autoscaling_schedule_settings\": {\n \"schedules\": [\n {\n \"autoscaling_settings\": {\n \"autoscaling_window\": null,\n \"concurrency_target\": null,\n \"max_replica\": 8,\n \"max_scale_down_rate\": null,\n \"min_replica\": 2,\n \"scale_down_delay\": null,\n \"target_in_flight_tokens\": null,\n \"target_utilization_percentage\": null\n },\n \"cadence\": \"DAILY\",\n \"enabled\": true,\n \"end_hour\": 10,\n \"end_minute\": 0,\n \"name\": \"weekday-peak\",\n \"start_hour\": 8,\n \"start_minute\": 0,\n \"weekdays\": [\n \"MONDAY\",\n \"TUESDAY\",\n \"WEDNESDAY\",\n \"THURSDAY\",\n \"FRIDAY\"\n ]\n }\n ],\n \"timezone\": \"America/Los_Angeles\"\n },\n \"request_backpressure_settings\": {\n \"policy\": \"REJECT_ON_FULL\"\n }\n}'" + "source": "curl --request PATCH \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/environments/{env_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"autoscaling_settings\": {\n \"autoscaling_window\": 800,\n \"concurrency_target\": 3,\n \"max_replica\": 2,\n \"max_scale_down_rate\": null,\n \"min_replica\": 1,\n \"scale_down_delay\": 60,\n \"target_in_flight_tokens\": null,\n \"target_utilization_percentage\": null\n },\n \"promotion_settings\": {\n \"promotion_cleanup_strategy\": null,\n \"ramp_up_duration_seconds\": 600,\n \"ramp_up_while_promoting\": true,\n \"redeploy_on_promotion\": true,\n \"rolling_deploy\": null,\n \"rolling_deploy_config\": null\n },\n \"autoscaling_schedule_settings\": {\n \"schedules\": [\n {\n \"autoscaling_settings\": {\n \"autoscaling_window\": null,\n \"concurrency_target\": null,\n \"max_replica\": 8,\n \"max_scale_down_rate\": null,\n \"min_replica\": 2,\n \"scale_down_delay\": null,\n \"target_in_flight_tokens\": null,\n \"target_utilization_percentage\": null\n },\n \"cadence\": \"DAILY\",\n \"enabled\": true,\n \"end_hour\": 10,\n \"end_minute\": 0,\n \"name\": \"weekday-peak\",\n \"start_hour\": 8,\n \"start_minute\": 0,\n \"weekdays\": [\n \"MONDAY\",\n \"TUESDAY\",\n \"WEDNESDAY\",\n \"THURSDAY\",\n \"FRIDAY\"\n ]\n }\n ],\n \"timezone\": \"America/Los_Angeles\"\n },\n \"request_backpressure_settings\": {\n \"policy\": \"REJECT_ON_FULL\"\n }\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/environments/{env_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'autoscaling_settings': {'autoscaling_window': 800, 'concurrency_target': 3, 'max_replica': 2, 'max_scale_down_rate': None, 'min_replica': 1, 'scale_down_delay': 60, 'target_in_flight_tokens': None, 'target_utilization_percentage': None}, 'promotion_settings': {'promotion_cleanup_strategy': None, 'ramp_up_duration_seconds': 600, 'ramp_up_while_promoting': True, 'redeploy_on_promotion': True, 'rolling_deploy': None, 'rolling_deploy_config': None}, 'autoscaling_schedule_settings': {'schedules': [{'autoscaling_settings': {'autoscaling_window': None, 'concurrency_target': None, 'max_replica': 8, 'max_scale_down_rate': None, 'min_replica': 2, 'scale_down_delay': None, 'target_in_flight_tokens': None, 'target_utilization_percentage': None}, 'cadence': 'DAILY', 'enabled': True, 'end_hour': 10, 'end_minute': 0, 'name': 'weekday-peak', 'start_hour': 8, 'start_minute': 0, 'weekdays': ['MONDAY', 'TUESDAY', 'WEDNESDAY', 'THURSDAY', 'FRIDAY']}], 'timezone': 'America/Los_Angeles'}, 'request_backpressure_settings': {'policy': 'REJECT_ON_FULL'}}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/environments/{env_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'autoscaling_settings': {'autoscaling_window': 800, 'concurrency_target': 3, 'max_replica': 2, 'max_scale_down_rate': None, 'min_replica': 1, 'scale_down_delay': 60, 'target_in_flight_tokens': None, 'target_utilization_percentage': None}, 'promotion_settings': {'promotion_cleanup_strategy': None, 'ramp_up_duration_seconds': 600, 'ramp_up_while_promoting': True, 'redeploy_on_promotion': True, 'rolling_deploy': None, 'rolling_deploy_config': None}, 'autoscaling_schedule_settings': {'schedules': [{'autoscaling_settings': {'autoscaling_window': None, 'concurrency_target': None, 'max_replica': 8, 'max_scale_down_rate': None, 'min_replica': 2, 'scale_down_delay': None, 'target_in_flight_tokens': None, 'target_utilization_percentage': None}, 'cadence': 'DAILY', 'enabled': True, 'end_hour': 10, 'end_minute': 0, 'name': 'weekday-peak', 'start_hour': 8, 'start_minute': 0, 'weekdays': ['MONDAY', 'TUESDAY', 'WEDNESDAY', 'THURSDAY', 'FRIDAY']}], 'timezone': 'America/Los_Angeles'}, 'request_backpressure_settings': {'policy': 'REJECT_ON_FULL'}}\n)\n\nprint(response.text)" } ], "description": "Asynchronously updates an environment's settings. Poll the GET endpoint for the applied state.", @@ -3443,11 +3702,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/logs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/environments/{env_name}/logs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/logs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'start_epoch_millis': None, 'end_epoch_millis': None, 'direction': None, 'limit': None, 'min_level': None, 'replica': None, 'request_id': None, 'component': None, 'search_pattern': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/environments/{env_name}/logs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'start_epoch_millis': None, 'end_epoch_millis': None, 'direction': None, 'limit': None, 'min_level': None, 'replica': None, 'request_id': None, 'component': None, 'search_pattern': None}\n)\n\nprint(response.text)" } ], "description": "Gets logs across all deployments that were active on the environment in the given time range, which defaults to the last 30 minutes. Pass `start_epoch_millis` to widen the window back to an earlier deployment's build/deploy time.", @@ -3675,11 +3934,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/metrics \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/environments/{env_name}/metrics \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/metrics\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'mode': 'CURRENT', 'start_epoch_millis': None, 'end_epoch_millis': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/environments/{env_name}/metrics\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'mode': 'CURRENT', 'start_epoch_millis': None, 'end_epoch_millis': None}\n)\n\nprint(response.text)" } ], "description": "Gets metrics aggregated across every deployment that was active on the environment in the given time range. In series mode the window is split at each promotion so that every point reflects the deployment(s) serving the environment at that time.", @@ -3773,11 +4032,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/activate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/environments/{env_name}/activate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/activate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/environments/{env_name}/activate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Activates a deployment associated with an environment if not already activated.", @@ -3809,11 +4068,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/deactivate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/environments/{env_name}/deactivate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/deactivate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/environments/{env_name}/deactivate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Deactivates a deployment associated with an environment if not already deactivated.", @@ -3845,11 +4104,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/promote \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"scale_down_previous_deployment\": true,\n \"deployment_id\": null,\n \"preserve_env_instance_type\": true\n}'" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/environments/{env_name}/promote \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"scale_down_previous_deployment\": true,\n \"deployment_id\": null,\n \"preserve_env_instance_type\": true\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/promote\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'scale_down_previous_deployment': True, 'deployment_id': None, 'preserve_env_instance_type': True}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/environments/{env_name}/promote\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'scale_down_previous_deployment': True, 'deployment_id': None, 'preserve_env_instance_type': True}\n)\n\nprint(response.text)" } ], "description": "Promotes an existing deployment to an environment and returns the promoted deployment.", @@ -3891,11 +4150,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/cancel_promotion \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/environments/{env_name}/cancel_promotion \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/cancel_promotion\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/environments/{env_name}/cancel_promotion\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Cancels an ongoing promotion to an environment and returns the cancellation status.", @@ -3927,11 +4186,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/pause_promotion \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/environments/{env_name}/pause_promotion \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/pause_promotion\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/environments/{env_name}/pause_promotion\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Pauses an in-progress rolling promotion after the current step completes. No further scaling changes are made until resumed.", @@ -3963,11 +4222,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/resume_promotion \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/environments/{env_name}/resume_promotion \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/resume_promotion\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/environments/{env_name}/resume_promotion\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Resumes a paused rolling promotion, continuing from where it was paused.", @@ -3999,11 +4258,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/force_cancel_promotion \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/environments/{env_name}/force_cancel_promotion \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/force_cancel_promotion\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/environments/{env_name}/force_cancel_promotion\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Immediately cancels an in-progress rolling promotion and triggers rollback to the previous version.", @@ -4035,11 +4294,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/force_roll_forward_promotion \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/environments/{env_name}/force_roll_forward_promotion \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/force_roll_forward_promotion\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/environments/{env_name}/force_roll_forward_promotion\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Immediately completes the rolling promotion, shifting all traffic to the new version. This works even if the promotion is in the process of rolling back.", @@ -4071,11 +4330,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/chains \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/chains \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/chains\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "responses": { @@ -4098,11 +4357,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/chains/{chain_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request DELETE \\\n--url https://api.staging.baseten.co/v1/chains/{chain_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/chains/{chain_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "responses": { @@ -4128,11 +4387,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/chains/{chain_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/chains/{chain_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/chains/{chain_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "responses": { @@ -4155,11 +4414,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/chains/{chain_id}/audit_logs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/chains/{chain_id}/audit_logs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}/audit_logs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'cursor': None, 'direction': 'DESC', 'search': None, 'start_epoch_millis': None, 'end_epoch_millis': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/chains/{chain_id}/audit_logs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'cursor': None, 'direction': 'DESC', 'search': None, 'start_epoch_millis': None, 'end_epoch_millis': None}\n)\n\nprint(response.text)" } ], "description": "Returns audit-log entries for a single chain, newest first. Use the filters to narrow by event type, actor, chain deployment, environment, source, or time window, and the cursor to page.", @@ -4363,11 +4622,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/chains/{chain_id}/deployments \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/chains/{chain_id}/deployments \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}/deployments\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/chains/{chain_id}/deployments\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "responses": { @@ -4395,11 +4654,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/chains/{chain_id}/deployments/{chain_deployment_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request DELETE \\\n--url https://api.staging.baseten.co/v1/chains/{chain_id}/deployments/{chain_deployment_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}/deployments/{chain_deployment_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/chains/{chain_id}/deployments/{chain_deployment_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "responses": { @@ -4428,11 +4687,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/chains/{chain_id}/deployments/{chain_deployment_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/chains/{chain_id}/deployments/{chain_deployment_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}/deployments/{chain_deployment_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/chains/{chain_id}/deployments/{chain_deployment_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "responses": { @@ -4455,11 +4714,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/chains/{chain_id}/deployments/{chain_deployment_id}/deactivate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/chains/{chain_id}/deployments/{chain_deployment_id}/deactivate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}/deployments/{chain_deployment_id}/deactivate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/chains/{chain_id}/deployments/{chain_deployment_id}/deactivate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Deactivates a chain deployment and returns the deactivation status.", @@ -4491,11 +4750,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/chains/{chain_id}/deployments/{chain_deployment_id}/chainlets/{chainlet_id}/logs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/chains/{chain_id}/deployments/{chain_deployment_id}/chainlets/{chainlet_id}/logs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}/deployments/{chain_deployment_id}/chainlets/{chainlet_id}/logs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'start_epoch_millis': None, 'end_epoch_millis': None, 'direction': None, 'limit': None, 'min_level': None, 'replica': None, 'request_id': None, 'component': None, 'search_pattern': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/chains/{chain_id}/deployments/{chain_deployment_id}/chainlets/{chainlet_id}/logs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'start_epoch_millis': None, 'end_epoch_millis': None, 'direction': None, 'limit': None, 'min_level': None, 'replica': None, 'request_id': None, 'component': None, 'search_pattern': None}\n)\n\nprint(response.text)" } ], "description": "Resolves the chainlet (by ID, scoped to the given chain deployment) to its underlying model deployment and returns its logs in the given time range.", @@ -4726,11 +4985,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/chains/{chain_id}/environments \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/chains/{chain_id}/environments \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}/environments\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/chains/{chain_id}/environments\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Gets all chain environments for a given chain.", @@ -4757,11 +5016,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/chains/{chain_id}/environments \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"name\": \"staging\",\n \"promotion_settings\": {\n \"promotion_cleanup_strategy\": null,\n \"ramp_up_duration_seconds\": 600,\n \"ramp_up_while_promoting\": true,\n \"redeploy_on_promotion\": true,\n \"rolling_deploy\": null,\n \"rolling_deploy_config\": null\n },\n \"chainlet_settings\": [\n {\n \"autoscaling_settings\": {\n \"autoscaling_window\": 800,\n \"concurrency_target\": 4,\n \"max_replica\": 3,\n \"max_scale_down_rate\": null,\n \"min_replica\": 2,\n \"scale_down_delay\": 63,\n \"target_in_flight_tokens\": null,\n \"target_utilization_percentage\": null\n },\n \"chainlet_name\": \"HelloWorld\",\n \"instance_type_id\": \"2x8\"\n },\n {\n \"autoscaling_settings\": {\n \"autoscaling_window\": null,\n \"concurrency_target\": null,\n \"max_replica\": 3,\n \"max_scale_down_rate\": null,\n \"min_replica\": 3,\n \"scale_down_delay\": null,\n \"target_in_flight_tokens\": null,\n \"target_utilization_percentage\": null\n },\n \"chainlet_name\": \"RandInt\",\n \"instance_type_id\": \"A10Gx8x32\"\n }\n ]\n}'" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/chains/{chain_id}/environments \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"name\": \"staging\",\n \"promotion_settings\": {\n \"promotion_cleanup_strategy\": null,\n \"ramp_up_duration_seconds\": 600,\n \"ramp_up_while_promoting\": true,\n \"redeploy_on_promotion\": true,\n \"rolling_deploy\": null,\n \"rolling_deploy_config\": null\n },\n \"chainlet_settings\": [\n {\n \"autoscaling_settings\": {\n \"autoscaling_window\": 800,\n \"concurrency_target\": 4,\n \"max_replica\": 3,\n \"max_scale_down_rate\": null,\n \"min_replica\": 2,\n \"scale_down_delay\": 63,\n \"target_in_flight_tokens\": null,\n \"target_utilization_percentage\": null\n },\n \"chainlet_name\": \"HelloWorld\",\n \"instance_type_id\": \"2x8\"\n },\n {\n \"autoscaling_settings\": {\n \"autoscaling_window\": null,\n \"concurrency_target\": null,\n \"max_replica\": 3,\n \"max_scale_down_rate\": null,\n \"min_replica\": 3,\n \"scale_down_delay\": null,\n \"target_in_flight_tokens\": null,\n \"target_utilization_percentage\": null\n },\n \"chainlet_name\": \"RandInt\",\n \"instance_type_id\": \"A10Gx8x32\"\n }\n ]\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}/environments\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'name': 'staging', 'promotion_settings': {'promotion_cleanup_strategy': None, 'ramp_up_duration_seconds': 600, 'ramp_up_while_promoting': True, 'redeploy_on_promotion': True, 'rolling_deploy': None, 'rolling_deploy_config': None}, 'chainlet_settings': [{'autoscaling_settings': {'autoscaling_window': 800, 'concurrency_target': 4, 'max_replica': 3, 'max_scale_down_rate': None, 'min_replica': 2, 'scale_down_delay': 63, 'target_in_flight_tokens': None, 'target_utilization_percentage': None}, 'chainlet_name': 'HelloWorld', 'instance_type_id': '2x8'}, {'autoscaling_settings': {'autoscaling_window': None, 'concurrency_target': None, 'max_replica': 3, 'max_scale_down_rate': None, 'min_replica': 3, 'scale_down_delay': None, 'target_in_flight_tokens': None, 'target_utilization_percentage': None}, 'chainlet_name': 'RandInt', 'instance_type_id': 'A10Gx8x32'}]}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/chains/{chain_id}/environments\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'name': 'staging', 'promotion_settings': {'promotion_cleanup_strategy': None, 'ramp_up_duration_seconds': 600, 'ramp_up_while_promoting': True, 'redeploy_on_promotion': True, 'rolling_deploy': None, 'rolling_deploy_config': None}, 'chainlet_settings': [{'autoscaling_settings': {'autoscaling_window': 800, 'concurrency_target': 4, 'max_replica': 3, 'max_scale_down_rate': None, 'min_replica': 2, 'scale_down_delay': 63, 'target_in_flight_tokens': None, 'target_utilization_percentage': None}, 'chainlet_name': 'HelloWorld', 'instance_type_id': '2x8'}, {'autoscaling_settings': {'autoscaling_window': None, 'concurrency_target': None, 'max_replica': 3, 'max_scale_down_rate': None, 'min_replica': 3, 'scale_down_delay': None, 'target_in_flight_tokens': None, 'target_utilization_percentage': None}, 'chainlet_name': 'RandInt', 'instance_type_id': 'A10Gx8x32'}]}\n)\n\nprint(response.text)" } ], "description": "Creates a chain environment. Returns the resulting environment.", @@ -4795,11 +5054,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/chains/{chain_id}/environments/{env_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/chains/{chain_id}/environments/{env_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}/environments/{env_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/chains/{chain_id}/environments/{env_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Gets a chain environment's details and returns the chain environment.", @@ -4829,11 +5088,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/chains/{chain_id}/environments/{env_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"promotion_settings\": {\n \"promotion_cleanup_strategy\": null,\n \"ramp_up_duration_seconds\": 600,\n \"ramp_up_while_promoting\": true,\n \"redeploy_on_promotion\": null,\n \"rolling_deploy\": null,\n \"rolling_deploy_config\": null\n }\n}'" + "source": "curl --request PATCH \\\n--url https://api.staging.baseten.co/v1/chains/{chain_id}/environments/{env_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"promotion_settings\": {\n \"promotion_cleanup_strategy\": null,\n \"ramp_up_duration_seconds\": 600,\n \"ramp_up_while_promoting\": true,\n \"redeploy_on_promotion\": null,\n \"rolling_deploy\": null,\n \"rolling_deploy_config\": null\n }\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}/environments/{env_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'promotion_settings': {'promotion_cleanup_strategy': None, 'ramp_up_duration_seconds': 600, 'ramp_up_while_promoting': True, 'redeploy_on_promotion': None, 'rolling_deploy': None, 'rolling_deploy_config': None}}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/chains/{chain_id}/environments/{env_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'promotion_settings': {'promotion_cleanup_strategy': None, 'ramp_up_duration_seconds': 600, 'ramp_up_while_promoting': True, 'redeploy_on_promotion': None, 'rolling_deploy': None, 'rolling_deploy_config': None}}\n)\n\nprint(response.text)" } ], "description": "Updates a chain environment's settings and returns the chain environment.", @@ -4867,11 +5126,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/chains/{chain_id}/environments/{env_name}/promote \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"scale_down_previous_deployment\": true,\n \"deployment_id\": null\n}'" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/chains/{chain_id}/environments/{env_name}/promote \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"scale_down_previous_deployment\": true,\n \"deployment_id\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}/environments/{env_name}/promote\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'scale_down_previous_deployment': True, 'deployment_id': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/chains/{chain_id}/environments/{env_name}/promote\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'scale_down_previous_deployment': True, 'deployment_id': None}\n)\n\nprint(response.text)" } ], "description": "Promotes an existing chain deployment to an environment and returns the promoted chain deployment.", @@ -4913,11 +5172,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/chains/{chain_id}/environments/{env_name}/chainlet_settings/autoscaling_settings \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"updates\": [\n {\n \"autoscaling_settings\": {\n \"autoscaling_window\": 800,\n \"concurrency_target\": 4,\n \"max_replica\": 3,\n \"max_scale_down_rate\": null,\n \"min_replica\": 2,\n \"scale_down_delay\": 63,\n \"target_in_flight_tokens\": null,\n \"target_utilization_percentage\": null\n },\n \"chainlet_name\": \"HelloWorld\"\n }\n ]\n}'" + "source": "curl --request PATCH \\\n--url https://api.staging.baseten.co/v1/chains/{chain_id}/environments/{env_name}/chainlet_settings/autoscaling_settings \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"updates\": [\n {\n \"autoscaling_settings\": {\n \"autoscaling_window\": 800,\n \"concurrency_target\": 4,\n \"max_replica\": 3,\n \"max_scale_down_rate\": null,\n \"min_replica\": 2,\n \"scale_down_delay\": 63,\n \"target_in_flight_tokens\": null,\n \"target_utilization_percentage\": null\n },\n \"chainlet_name\": \"HelloWorld\"\n }\n ]\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}/environments/{env_name}/chainlet_settings/autoscaling_settings\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'updates': [{'autoscaling_settings': {'autoscaling_window': 800, 'concurrency_target': 4, 'max_replica': 3, 'max_scale_down_rate': None, 'min_replica': 2, 'scale_down_delay': 63, 'target_in_flight_tokens': None, 'target_utilization_percentage': None}, 'chainlet_name': 'HelloWorld'}]}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/chains/{chain_id}/environments/{env_name}/chainlet_settings/autoscaling_settings\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'updates': [{'autoscaling_settings': {'autoscaling_window': 800, 'concurrency_target': 4, 'max_replica': 3, 'max_scale_down_rate': None, 'min_replica': 2, 'scale_down_delay': 63, 'target_in_flight_tokens': None, 'target_utilization_percentage': None}, 'chainlet_name': 'HelloWorld'}]}\n)\n\nprint(response.text)" } ], "description": "Updates a chainlet environment's autoscaling settings and returns the updated chainlet environment settings.", @@ -4959,11 +5218,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/chains/{chain_id}/environments/{env_name}/chainlet_settings/instance_types/update \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"updates\": [\n {\n \"chainlet_name\": \"HelloWorld\",\n \"instance_type_id\": \"1x4\"\n },\n {\n \"chainlet_name\": \"RandInt\",\n \"instance_type_id\": \"A10G:2x24x96\"\n }\n ]\n}'" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/chains/{chain_id}/environments/{env_name}/chainlet_settings/instance_types/update \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"updates\": [\n {\n \"chainlet_name\": \"HelloWorld\",\n \"instance_type_id\": \"1x4\"\n },\n {\n \"chainlet_name\": \"RandInt\",\n \"instance_type_id\": \"A10G:2x24x96\"\n }\n ]\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}/environments/{env_name}/chainlet_settings/instance_types/update\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'updates': [{'chainlet_name': 'HelloWorld', 'instance_type_id': '1x4'}, {'chainlet_name': 'RandInt', 'instance_type_id': 'A10G:2x24x96'}]}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/chains/{chain_id}/environments/{env_name}/chainlet_settings/instance_types/update\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'updates': [{'chainlet_name': 'HelloWorld', 'instance_type_id': '1x4'}, {'chainlet_name': 'RandInt', 'instance_type_id': 'A10G:2x24x96'}]}\n)\n\nprint(response.text)" } ], "description": "Updates a chainlet environment's instance type settings. The chainlet environment setting must exist. When updated, a new chain deployment is created and deployed. It is promoted to the chain environment according to promotion settings on the environment.", @@ -5005,11 +5264,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/teams/{team_id}/training_projects \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"training_project\": {\n \"name\": \"My Training Project\"\n }\n}'" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/teams/{team_id}/training_projects \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"training_project\": {\n \"name\": \"My Training Project\"\n }\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}/training_projects\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'training_project': {'name': 'My Training Project'}}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/teams/{team_id}/training_projects\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'training_project': {'name': 'My Training Project'}}\n)\n\nprint(response.text)" } ], "description": "Upserts a training project with the specified metadata for a team.", @@ -5048,11 +5307,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/training_projects \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/training_projects \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/training_projects\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Lists all training projects for the organization.", @@ -5074,11 +5333,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/training_projects \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"training_project\": {\n \"name\": \"My Training Project\"\n }\n}'" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/training_projects \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"training_project\": {\n \"name\": \"My Training Project\"\n }\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'training_project': {'name': 'My Training Project'}}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/training_projects\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'training_project': {'name': 'My Training Project'}}\n)\n\nprint(response.text)" } ], "description": "Upserts a training project with the specified metadata.", @@ -5112,11 +5371,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Lists all training jobs for the training project.", @@ -5143,11 +5402,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"training_job\": {\n \"image\": {\n \"base_image\": \"hello-world\",\n \"docker_auth\": null\n },\n \"compute\": {\n \"node_count\": 1,\n \"cpu_count\": 1,\n \"memory\": \"2Gi\",\n \"accelerator\": {\n \"accelerator\": \"H100\",\n \"count\": 2\n },\n \"availability_model\": \"spot\"\n },\n \"runtime\": {\n \"start_commands\": [\n \"python main.py\"\n ],\n \"environment_variables\": {\n \"API_KEY\": \"your_api_key_here\",\n \"PATH\": \"/usr/bin\"\n },\n \"enable_cache\": true,\n \"cache_config\": {\n \"enable_legacy_hf_mount\": true,\n \"enabled\": true,\n \"mount_base_path\": \"/root/.cache\",\n \"require_cache_affinity\": true\n },\n \"checkpointing_config\": {\n \"enabled\": true,\n \"checkpoint_path\": \"/mnt/ckpts\",\n \"volume_size_gib\": 10\n },\n \"load_checkpoint_config\": null\n },\n \"name\": \"gpt-oss-job\",\n \"truss_user_env\": null,\n \"interactive_session\": null,\n \"weights\": [\n {\n \"allow_patterns\": null,\n \"auth\": null,\n \"auth_secret_name\": null,\n \"ignore_patterns\": null,\n \"mount_location\": \"/app/models/base\",\n \"source\": \"hf://meta-llama/Llama-3-8B@main\"\n }\n ],\n \"enable_baseten_workdir\": false,\n \"priority\": 0\n }\n}'" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"training_job\": {\n \"image\": {\n \"base_image\": \"hello-world\",\n \"docker_auth\": null\n },\n \"compute\": {\n \"node_count\": 1,\n \"cpu_count\": 1,\n \"memory\": \"2Gi\",\n \"accelerator\": {\n \"accelerator\": \"H100\",\n \"count\": 2\n },\n \"availability_model\": \"spot\"\n },\n \"runtime\": {\n \"start_commands\": [\n \"python main.py\"\n ],\n \"environment_variables\": {\n \"API_KEY\": \"your_api_key_here\",\n \"PATH\": \"/usr/bin\"\n },\n \"enable_cache\": true,\n \"cache_config\": {\n \"enable_legacy_hf_mount\": true,\n \"enabled\": true,\n \"mount_base_path\": \"/root/.cache\",\n \"require_cache_affinity\": true\n },\n \"checkpointing_config\": {\n \"enabled\": true,\n \"checkpoint_path\": \"/mnt/ckpts\",\n \"volume_size_gib\": 10\n },\n \"load_checkpoint_config\": null\n },\n \"name\": \"gpt-oss-job\",\n \"truss_user_env\": null,\n \"interactive_session\": null,\n \"weights\": [\n {\n \"allow_patterns\": null,\n \"auth\": null,\n \"auth_secret_name\": null,\n \"ignore_patterns\": null,\n \"mount_location\": \"/app/models/base\",\n \"source\": \"hf://meta-llama/Llama-3-8B@main\"\n }\n ],\n \"enable_baseten_workdir\": false,\n \"priority\": 0\n }\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'training_job': {'image': {'base_image': 'hello-world', 'docker_auth': None}, 'compute': {'node_count': 1, 'cpu_count': 1, 'memory': '2Gi', 'accelerator': {'accelerator': 'H100', 'count': 2}, 'availability_model': 'spot'}, 'runtime': {'start_commands': ['python main.py'], 'environment_variables': {'API_KEY': 'your_api_key_here', 'PATH': '/usr/bin'}, 'enable_cache': True, 'cache_config': {'enable_legacy_hf_mount': True, 'enabled': True, 'mount_base_path': '/root/.cache', 'require_cache_affinity': True}, 'checkpointing_config': {'enabled': True, 'checkpoint_path': '/mnt/ckpts', 'volume_size_gib': 10}, 'load_checkpoint_config': None}, 'name': 'gpt-oss-job', 'truss_user_env': None, 'interactive_session': None, 'weights': [{'allow_patterns': None, 'auth': None, 'auth_secret_name': None, 'ignore_patterns': None, 'mount_location': '/app/models/base', 'source': 'hf://meta-llama/Llama-3-8B@main'}], 'enable_baseten_workdir': False, 'priority': 0}}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'training_job': {'image': {'base_image': 'hello-world', 'docker_auth': None}, 'compute': {'node_count': 1, 'cpu_count': 1, 'memory': '2Gi', 'accelerator': {'accelerator': 'H100', 'count': 2}, 'availability_model': 'spot'}, 'runtime': {'start_commands': ['python main.py'], 'environment_variables': {'API_KEY': 'your_api_key_here', 'PATH': '/usr/bin'}, 'enable_cache': True, 'cache_config': {'enable_legacy_hf_mount': True, 'enabled': True, 'mount_base_path': '/root/.cache', 'require_cache_affinity': True}, 'checkpointing_config': {'enabled': True, 'checkpoint_path': '/mnt/ckpts', 'volume_size_gib': 10}, 'load_checkpoint_config': None}, 'name': 'gpt-oss-job', 'truss_user_env': None, 'interactive_session': None, 'weights': [{'allow_patterns': None, 'auth': None, 'auth_secret_name': None, 'ignore_patterns': None, 'mount_location': '/app/models/base', 'source': 'hf://meta-llama/Llama-3-8B@main'}], 'enable_baseten_workdir': False, 'priority': 0}}\n)\n\nprint(response.text)" } ], "description": "Creates a training job with the specified configuration.", @@ -5181,11 +5440,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request DELETE \\\n--url https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Deletes a training job. Stops it first if still running.", @@ -5215,11 +5474,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Gets the details of an existing training job.", @@ -5241,11 +5500,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"priority\": 0,\n \"availability_model\": \"spot\"\n}'" + "source": "curl --request PATCH \\\n--url https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"priority\": 0,\n \"availability_model\": \"spot\"\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'priority': 0, 'availability_model': 'spot'}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'priority': 0, 'availability_model': 'spot'}\n)\n\nprint(response.text)" } ], "description": "Updates mutable fields on a PENDING training job: the queue priority (higher priorities are dequeued first) and the availability model (dedicated or spot capacity). Changes take effect on the next queue evaluation, which is triggered immediately.", @@ -5279,11 +5538,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/download \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/download \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/download\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/download\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Returns presigned S3 URLs for the artifacts uploaded by a training job.", @@ -5315,11 +5574,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/recreate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/recreate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/recreate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/recreate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Creates a new training job with the same configuration as an existing training job.", @@ -5351,11 +5610,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/logs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/logs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/logs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'start_epoch_millis': None, 'end_epoch_millis': None, 'direction': None, 'limit': None, 'min_level': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/logs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'start_epoch_millis': None, 'end_epoch_millis': None, 'direction': None, 'limit': None, 'min_level': None}\n)\n\nprint(response.text)" } ], "description": "Gets the logs for a training job with the provided filters.", @@ -5477,11 +5736,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/logs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"start_epoch_millis\": null,\n \"end_epoch_millis\": null,\n \"direction\": null,\n \"limit\": null,\n \"min_level\": null\n}'" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/logs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"start_epoch_millis\": null,\n \"end_epoch_millis\": null,\n \"direction\": null,\n \"limit\": null,\n \"min_level\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/logs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'start_epoch_millis': None, 'end_epoch_millis': None, 'direction': None, 'limit': None, 'min_level': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/logs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'start_epoch_millis': None, 'end_epoch_millis': None, 'direction': None, 'limit': None, 'min_level': None}\n)\n\nprint(response.text)" } ], "description": "Use the GET form on this path instead.", @@ -5517,11 +5776,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/metrics \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/metrics \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/metrics\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'end_epoch_millis': None, 'start_epoch_millis': None, 'step_seconds': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/metrics\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'end_epoch_millis': None, 'start_epoch_millis': None, 'step_seconds': None}\n)\n\nprint(response.text)" } ], "description": "Gets the metrics for a training job.", @@ -5607,11 +5866,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/metrics \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"end_epoch_millis\": null,\n \"start_epoch_millis\": null,\n \"step_seconds\": null\n}'" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/metrics \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"end_epoch_millis\": null,\n \"start_epoch_millis\": null,\n \"step_seconds\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/metrics\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'end_epoch_millis': None, 'start_epoch_millis': None, 'step_seconds': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/metrics\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'end_epoch_millis': None, 'start_epoch_millis': None, 'step_seconds': None}\n)\n\nprint(response.text)" } ], "description": "Use the GET form on this path instead.", @@ -5647,11 +5906,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/stop \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{}'" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/stop \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/stop\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/stop\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Stops a training job.", @@ -5693,11 +5952,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/checkpoints \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/checkpoints \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/checkpoints\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/checkpoints\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Gets the checkpoints for a training job.", @@ -5729,11 +5988,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/checkpoint_files \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/checkpoint_files \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/checkpoint_files\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/checkpoint_files\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={}\n)\n\nprint(response.text)" } ], "description": "Gets presigned URLs for all checkpoint files for a training job.", @@ -5791,11 +6050,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/auth_codes \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/auth_codes \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/auth_codes\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/auth_codes\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Gets authentication codes for all nodes of a training job's interactive sessions.", @@ -5827,11 +6086,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/interactive_sessions/{session_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"timeout_minutes\": null,\n \"trigger\": null\n}'" + "source": "curl --request PATCH \\\n--url https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/interactive_sessions/{session_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"timeout_minutes\": null,\n \"trigger\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/interactive_sessions/{session_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'timeout_minutes': None, 'trigger': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/interactive_sessions/{session_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'timeout_minutes': None, 'trigger': None}\n)\n\nprint(response.text)" } ], "description": "Updates specific fields on a training job's interactive session. Only provided (non-null) fields are updated.", @@ -5876,11 +6135,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/ssh/sign \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"public_key\": null,\n \"replica_id\": null\n}'" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/ssh/sign \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"public_key\": null,\n \"replica_id\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/ssh/sign\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'public_key': None, 'replica_id': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/ssh/sign\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'public_key': None, 'replica_id': None}\n)\n\nprint(response.text)" } ], "description": "Signs a short-lived SSH certificate granting access to a specific training job pod. Returns the signed SSH certificate, a JWT token for SSH proxy authentication, the proxy address to connect through, and the certificate expiry time.", @@ -5922,11 +6181,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/cache/summary \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/training_projects/{training_project_id}/cache/summary \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/cache/summary\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/training_projects/{training_project_id}/cache/summary\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Gets the cache summary for the most recent training job in the project.", @@ -5955,11 +6214,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request DELETE \\\n--url https://api.staging.baseten.co/v1/training_projects/{training_project_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/training_projects/{training_project_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Deletes a training project and all associated training jobs.", @@ -5986,11 +6245,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/training_projects/{training_project_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/training_projects/{training_project_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Gets the details of an existing training project.", @@ -6014,11 +6273,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/training_jobs/search \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"project_id\": \"n4q95w5\",\n \"job_id\": \"p7qr9qv\",\n \"statuses\": [\n \"TRAINING_JOB_RUNNING\",\n \"TRAINING_JOB_COMPLETED\"\n ]\n}'" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/training_jobs/search \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"project_id\": \"n4q95w5\",\n \"job_id\": \"p7qr9qv\",\n \"statuses\": [\n \"TRAINING_JOB_RUNNING\",\n \"TRAINING_JOB_COMPLETED\"\n ]\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_jobs/search\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'project_id': 'n4q95w5', 'job_id': 'p7qr9qv', 'statuses': ['TRAINING_JOB_RUNNING', 'TRAINING_JOB_COMPLETED']}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/training_jobs/search\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'project_id': 'n4q95w5', 'job_id': 'p7qr9qv', 'statuses': ['TRAINING_JOB_RUNNING', 'TRAINING_JOB_COMPLETED']}\n)\n\nprint(response.text)" } ], "description": "Searches training jobs for the organization.", @@ -6052,41 +6311,99 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/loops/capabilities \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/loops/capabilities \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/capabilities\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/loops/capabilities\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'model': 'Qwen/Qwen3-8B', 'use_case': 'rl', 'max_seq_len': 32768}\n)\n\nprint(response.text)" } ], - "description": "Returns the list of models supported by the Loops server, including each model's maximum context length and whether it supports vision-language inputs.", - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GetLoopsCapabilitiesResponseV1" + "description": "Returns the list of models supported by the Loops server, including each model's maximum context length and whether it supports vision-language inputs. Each entry carries an 'enabled' flag saying whether this workspace can run it now, and 'enablement_details' explaining why when it cannot; filter on 'enabled' for the usable set. Capacity is resolved when the run is created, not here. Pass ?model= to ask about one model \u2014 an empty list means Baseten does not support it. Pass ?use_case=sft for a run that needs no sampler, and ?max_seq_len= to check a specific sequence length.", + "parameters": [ + { + "name": "model", + "in": "query", + "required": false, + "description": "Restrict the response to one model, identified by its HuggingFace repo id. A supported model comes back with its 'enabled' flag and, when false, its 'enablement_details'. An empty list means Baseten does not support that model. Omit to list every supported model.", + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" } - } + ], + "default": null, + "examples": [ + "Qwen/Qwen3-8B" + ], + "title": "Model" } - } - } - } - }, - "/v1/loops/sessions": { - "post": { - "summary": "Creates a Loops session", - "x-codeSamples": [ - { - "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/loops/sessions \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { - "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/sessions\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" - } - ], + "name": "use_case", + "in": "query", + "required": false, + "description": "What the caller intends to run. Defaults to 'rl', the stricter of the two: an RL run needs both a trainer and a sampler, so anything enabled for 'rl' is also enabled for 'sft'.", + "schema": { + "$ref": "#/components/schemas/LoopsUseCaseV1", + "default": "rl", + "examples": [ + "rl" + ] + } + }, + { + "name": "max_seq_len", + "in": "query", + "required": false, + "description": "The sequence length the caller intends to train at \u2014 the same value they would pass as 'max_seq_len' when creating the run. Models that cannot serve it are reported as not enabled rather than returned with a ceiling the caller cannot use. Omit for the model's highest enabled sequence length.", + "schema": { + "anyOf": [ + { + "minimum": 1, + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "examples": [ + 32768 + ], + "title": "Max Seq Len" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetLoopsCapabilitiesResponseV1" + } + } + } + } + } + } + }, + "/v1/loops/sessions": { + "post": { + "summary": "Creates a Loops session", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/loops/sessions \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/loops/sessions\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + } + ], "description": "Creates a Loops session scoped to the calling org.", "responses": { "200": { @@ -6108,11 +6425,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/loops/sessions/{session_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/loops/sessions/{session_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/sessions/{session_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/loops/sessions/{session_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Fetches a Loops session by ID.", @@ -6141,11 +6458,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/loops/runs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/loops/runs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/runs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'run_id': 'k4q95w5', 'base_model': 'Qwen/Qwen3-8B', 'scope': 'org'}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/loops/runs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'run_id': 'k4q95w5', 'base_model': 'Qwen/Qwen3-8B', 'scope': 'org'}\n)\n\nprint(response.text)" } ], "description": "Lists Loops runs visible to the requesting user, optionally filtered by run id and/or base model. Defaults to the caller's own runs; pass ?scope=org to list every run in the caller's organization.", @@ -6232,11 +6549,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/loops/runs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"session_id\": null,\n \"base_model\": null,\n \"name\": null,\n \"max_seq_len\": null,\n \"seed\": null,\n \"availability_model\": \"spot\",\n \"path\": \"bt://loops:k4q95w5/weights/step-100\",\n \"reuse_from_run_id\": null,\n \"reuse_from_session_id\": null\n}'" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/loops/runs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"session_id\": null,\n \"base_model\": null,\n \"name\": null,\n \"max_seq_len\": null,\n \"seed\": null,\n \"availability_model\": \"spot\",\n \"path\": \"bt://loops:k4q95w5/weights/step-100\",\n \"reuse_from_run_id\": null,\n \"reuse_from_session_id\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/runs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'session_id': None, 'base_model': None, 'name': None, 'max_seq_len': None, 'seed': None, 'availability_model': 'spot', 'path': 'bt://loops:k4q95w5/weights/step-100', 'reuse_from_run_id': None, 'reuse_from_session_id': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/loops/runs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'session_id': None, 'base_model': None, 'name': None, 'max_seq_len': None, 'seed': None, 'availability_model': 'spot', 'path': 'bt://loops:k4q95w5/weights/step-100', 'reuse_from_run_id': None, 'reuse_from_session_id': None}\n)\n\nprint(response.text)" } ], "description": "Creates a Loops run with an associated sampler in the given session.", @@ -6270,11 +6587,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/loops/runs/{run_id}/deactivate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/loops/runs/{run_id}/deactivate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/runs/{run_id}/deactivate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/loops/runs/{run_id}/deactivate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Shuts down a Loops run by ID, tearing down both the run and its paired sampler. Saved checkpoints remain accessible.", @@ -6303,11 +6620,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/loops/runs/{run_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/loops/runs/{run_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/runs/{run_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/loops/runs/{run_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Fetches a Loops run by ID.", @@ -6336,11 +6653,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/loops/trainers \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"session_id\": null,\n \"base_model\": null,\n \"name\": null,\n \"max_seq_len\": null,\n \"seed\": null,\n \"availability_model\": \"spot\",\n \"path\": \"bt://loops:k4q95w5/weights/step-100\",\n \"reuse_from_run_id\": null,\n \"reuse_from_session_id\": null\n}'" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/loops/trainers \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"session_id\": null,\n \"base_model\": null,\n \"name\": null,\n \"max_seq_len\": null,\n \"seed\": null,\n \"availability_model\": \"spot\",\n \"path\": \"bt://loops:k4q95w5/weights/step-100\",\n \"reuse_from_run_id\": null,\n \"reuse_from_session_id\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/trainers\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'session_id': None, 'base_model': None, 'name': None, 'max_seq_len': None, 'seed': None, 'availability_model': 'spot', 'path': 'bt://loops:k4q95w5/weights/step-100', 'reuse_from_run_id': None, 'reuse_from_session_id': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/loops/trainers\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'session_id': None, 'base_model': None, 'name': None, 'max_seq_len': None, 'seed': None, 'availability_model': 'spot', 'path': 'bt://loops:k4q95w5/weights/step-100', 'reuse_from_run_id': None, 'reuse_from_session_id': None}\n)\n\nprint(response.text)" } ], "description": "Creates a trainer-only Loops run in the given session, without a sampler. To sample from it, create a sampler with POST /v1/loops/samplers and pass this run's ID as run_id to pair the two. List and read the trainer through the /v1/loops/runs endpoints.", @@ -6374,11 +6691,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/loops/samplers \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/loops/samplers \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/samplers\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'scope': 'org'}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/loops/samplers\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'scope': 'org'}\n)\n\nprint(response.text)" } ], "description": "Lists Loops samplers (paired and standalone). Defaults to the caller's own; pass ?scope=org to list every sampler in the caller's organization.", @@ -6423,11 +6740,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/loops/samplers \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"session_id\": null,\n \"base_model\": null,\n \"run_id\": null,\n \"max_seq_length\": null,\n \"model_path\": \"bt://loops:k4q95w5/sampler_weights/step-100\",\n \"reuse_from_session_id\": null\n}'" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/loops/samplers \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"availability_model\": null,\n \"session_id\": null,\n \"base_model\": null,\n \"run_id\": null,\n \"max_seq_length\": null,\n \"model_path\": \"bt://loops:k4q95w5/sampler_weights/step-100\",\n \"reuse_from_session_id\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/samplers\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'session_id': None, 'base_model': None, 'run_id': None, 'max_seq_length': None, 'model_path': 'bt://loops:k4q95w5/sampler_weights/step-100', 'reuse_from_session_id': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/loops/samplers\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'availability_model': None, 'session_id': None, 'base_model': None, 'run_id': None, 'max_seq_length': None, 'model_path': 'bt://loops:k4q95w5/sampler_weights/step-100', 'reuse_from_session_id': None}\n)\n\nprint(response.text)" } ], "description": "Creates a standalone Loops sampler not linked to a run.", @@ -6461,11 +6778,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/loops/samplers/{sampler_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/loops/samplers/{sampler_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/samplers/{sampler_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/loops/samplers/{sampler_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Fetches a Loops sampler by ID.", @@ -6494,11 +6811,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/loops/checkpoints \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/loops/checkpoints \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/checkpoints\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'run_id': 'k4q95w5', 'base_model': 'Qwen/Qwen3-8B', 'checkpoint_path': 'bt://loops:k4q95w5/sampler_weights/step-100'}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/loops/checkpoints\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'run_id': 'k4q95w5', 'base_model': 'Qwen/Qwen3-8B', 'checkpoint_path': 'bt://loops:k4q95w5/sampler_weights/step-100'}\n)\n\nprint(response.text)" } ], "description": "Lists Loops checkpoints filtered by run id, base model, or bt:// URI. Provide exactly one filter.", @@ -6587,11 +6904,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/loops/checkpoints/validate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"checkpoint_path\": \"bt://loops:k4q95w5/sampler_weights/step-100\"\n}'" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/loops/checkpoints/validate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"checkpoint_path\": \"bt://loops:k4q95w5/sampler_weights/step-100\"\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/checkpoints/validate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'checkpoint_path': 'bt://loops:k4q95w5/sampler_weights/step-100'}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/loops/checkpoints/validate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'checkpoint_path': 'bt://loops:k4q95w5/sampler_weights/step-100'}\n)\n\nprint(response.text)" } ], "description": "Returns whether the caller can manage and use this checkpoint.", @@ -6625,11 +6942,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/loops/checkpoints/{checkpoint_id}/files \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/loops/checkpoints/{checkpoint_id}/files \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/checkpoints/{checkpoint_id}/files\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/loops/checkpoints/{checkpoint_id}/files\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={}\n)\n\nprint(response.text)" } ], "description": "Gets presigned URLs for the files under a Loops checkpoint. Returns a paginated list.", @@ -6678,17 +6995,50 @@ } ] }, + "/v1/loops/checkpoints/{checkpoint_id}/source": { + "get": { + "summary": "Gets where a Loops checkpoint's files come from", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/loops/checkpoints/{checkpoint_id}/source \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/loops/checkpoints/{checkpoint_id}/source\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + } + ], + "description": "Reports how to fetch a checkpoint's files: `s3` when the files endpoint serves presigned URLs for it, or `volume` with the ref to pull. Clients that download checkpoints should ask here first.", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LoopsCheckpointSourceResponseV1" + } + } + } + } + } + }, + "parameters": [ + { + "$ref": "#/components/parameters/checkpoint_id" + } + ] + }, "/v1/loops/deployments": { "get": { "summary": "Lists Loops deployments", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/loops/deployments \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/loops/deployments \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/deployments\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'scope': 'org'}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/loops/deployments\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'scope': 'org'}\n)\n\nprint(response.text)" } ], "description": "Lists Loops deployments. Defaults to the caller's own; pass ?scope=org to list every deployment in the caller's organization. Returns every deployment regardless of status; clients filter terminal states.", @@ -6735,11 +7085,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/loops/deployments/{deployment_id}/deactivate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/loops/deployments/{deployment_id}/deactivate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/deployments/{deployment_id}/deactivate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/loops/deployments/{deployment_id}/deactivate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Shuts down a Loops deployment by ID. Saved checkpoints remain accessible. Resolving the base model to a deployment ID is the caller's responsibility: list deployments and pick the active one.", @@ -6768,11 +7118,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/loops/deployments/{deployment_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/loops/deployments/{deployment_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/deployments/{deployment_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/loops/deployments/{deployment_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Fetches a Loops deployment by ID, including its latest status.", @@ -6801,11 +7151,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/loops/deployments/{deployment_id}/debug_archive/files \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/loops/deployments/{deployment_id}/debug_archive/files \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/deployments/{deployment_id}/debug_archive/files\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'page_token': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/loops/deployments/{deployment_id}/debug_archive/files\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'page_token': None}\n)\n\nprint(response.text)" } ], "description": "Gets presigned download URLs for a Loops deployment's debug archive.", @@ -6867,11 +7217,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/loops/deployments/{deployment_id}/metrics \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"end_epoch_millis\": null,\n \"start_epoch_millis\": null,\n \"step_seconds\": null,\n \"time_divisor_seconds\": null\n}'" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/loops/deployments/{deployment_id}/metrics \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"end_epoch_millis\": null,\n \"start_epoch_millis\": null,\n \"step_seconds\": null,\n \"time_divisor_seconds\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/deployments/{deployment_id}/metrics\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'end_epoch_millis': None, 'start_epoch_millis': None, 'step_seconds': None, 'time_divisor_seconds': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/loops/deployments/{deployment_id}/metrics\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'end_epoch_millis': None, 'start_epoch_millis': None, 'step_seconds': None, 'time_divisor_seconds': None}\n)\n\nprint(response.text)" } ], "description": "Returns per-node GPU/CPU/memory utilization and Knative queue-proxy request rate / concurrency / latency for the trainer pods. The sampler half of a Loops deployment is an OracleVersion and uses the existing model-metrics endpoint.", @@ -6910,11 +7260,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/loops/deployments/{deployment_id}/logs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/loops/deployments/{deployment_id}/logs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/deployments/{deployment_id}/logs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'start_epoch_millis': None, 'end_epoch_millis': None, 'direction': None, 'limit': None, 'min_level': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/loops/deployments/{deployment_id}/logs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'start_epoch_millis': None, 'end_epoch_millis': None, 'direction': None, 'limit': None, 'min_level': None}\n)\n\nprint(response.text)" } ], "description": "Fetches logs from the trainer pods of a Loops deployment. Visible to any member of the deployment's team.", @@ -7035,11 +7385,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/teams/{team_id}/loops/sessions \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/teams/{team_id}/loops/sessions \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}/loops/sessions\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/teams/{team_id}/loops/sessions\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Creates a Loops session scoped to the calling org.", @@ -7068,11 +7418,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/teams/{team_id}/loops/runs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/teams/{team_id}/loops/runs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}/loops/runs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'run_id': 'k4q95w5', 'base_model': 'Qwen/Qwen3-8B', 'scope': 'org'}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/teams/{team_id}/loops/runs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'run_id': 'k4q95w5', 'base_model': 'Qwen/Qwen3-8B', 'scope': 'org'}\n)\n\nprint(response.text)" } ], "description": "Lists Loops runs in the given team, visible to the requesting user, optionally filtered by run id and/or base model.", @@ -7164,11 +7514,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/teams/{team_id}/loops/runs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"session_id\": null,\n \"base_model\": null,\n \"name\": null,\n \"max_seq_len\": null,\n \"seed\": null,\n \"availability_model\": \"spot\",\n \"path\": \"bt://loops:k4q95w5/weights/step-100\",\n \"reuse_from_run_id\": null,\n \"reuse_from_session_id\": null\n}'" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/teams/{team_id}/loops/runs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"session_id\": null,\n \"base_model\": null,\n \"name\": null,\n \"max_seq_len\": null,\n \"seed\": null,\n \"availability_model\": \"spot\",\n \"path\": \"bt://loops:k4q95w5/weights/step-100\",\n \"reuse_from_run_id\": null,\n \"reuse_from_session_id\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}/loops/runs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'session_id': None, 'base_model': None, 'name': None, 'max_seq_len': None, 'seed': None, 'availability_model': 'spot', 'path': 'bt://loops:k4q95w5/weights/step-100', 'reuse_from_run_id': None, 'reuse_from_session_id': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/teams/{team_id}/loops/runs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'session_id': None, 'base_model': None, 'name': None, 'max_seq_len': None, 'seed': None, 'availability_model': 'spot', 'path': 'bt://loops:k4q95w5/weights/step-100', 'reuse_from_run_id': None, 'reuse_from_session_id': None}\n)\n\nprint(response.text)" } ], "description": "Creates a Loops run with an associated sampler in the given session; the run's infrastructure belongs to the given team.", @@ -7202,11 +7552,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/teams/{team_id}/loops/trainers \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"session_id\": null,\n \"base_model\": null,\n \"name\": null,\n \"max_seq_len\": null,\n \"seed\": null,\n \"availability_model\": \"spot\",\n \"path\": \"bt://loops:k4q95w5/weights/step-100\",\n \"reuse_from_run_id\": null,\n \"reuse_from_session_id\": null\n}'" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/teams/{team_id}/loops/trainers \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"session_id\": null,\n \"base_model\": null,\n \"name\": null,\n \"max_seq_len\": null,\n \"seed\": null,\n \"availability_model\": \"spot\",\n \"path\": \"bt://loops:k4q95w5/weights/step-100\",\n \"reuse_from_run_id\": null,\n \"reuse_from_session_id\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}/loops/trainers\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'session_id': None, 'base_model': None, 'name': None, 'max_seq_len': None, 'seed': None, 'availability_model': 'spot', 'path': 'bt://loops:k4q95w5/weights/step-100', 'reuse_from_run_id': None, 'reuse_from_session_id': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/teams/{team_id}/loops/trainers\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'session_id': None, 'base_model': None, 'name': None, 'max_seq_len': None, 'seed': None, 'availability_model': 'spot', 'path': 'bt://loops:k4q95w5/weights/step-100', 'reuse_from_run_id': None, 'reuse_from_session_id': None}\n)\n\nprint(response.text)" } ], "description": "Creates a trainer-only Loops run in the given session, without a sampler. To sample from it, create a sampler with POST /v1/loops/samplers and pass this run's ID as run_id to pair the two. List and read the trainer through the /v1/loops/runs endpoints.", @@ -7245,11 +7595,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/teams/{team_id}/loops/samplers \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/teams/{team_id}/loops/samplers \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}/loops/samplers\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'scope': 'org'}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/teams/{team_id}/loops/samplers\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'scope': 'org'}\n)\n\nprint(response.text)" } ], "description": "Lists Loops samplers (paired and standalone) in the given team, visible to the requesting user. Defaults to the caller's own; pass ?scope=org to list every sampler in the team.", @@ -7299,11 +7649,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/teams/{team_id}/loops/samplers \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"session_id\": null,\n \"base_model\": null,\n \"run_id\": null,\n \"max_seq_length\": null,\n \"model_path\": \"bt://loops:k4q95w5/sampler_weights/step-100\",\n \"reuse_from_session_id\": null\n}'" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/teams/{team_id}/loops/samplers \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"availability_model\": null,\n \"session_id\": null,\n \"base_model\": null,\n \"run_id\": null,\n \"max_seq_length\": null,\n \"model_path\": \"bt://loops:k4q95w5/sampler_weights/step-100\",\n \"reuse_from_session_id\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}/loops/samplers\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'session_id': None, 'base_model': None, 'run_id': None, 'max_seq_length': None, 'model_path': 'bt://loops:k4q95w5/sampler_weights/step-100', 'reuse_from_session_id': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/teams/{team_id}/loops/samplers\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'availability_model': None, 'session_id': None, 'base_model': None, 'run_id': None, 'max_seq_length': None, 'model_path': 'bt://loops:k4q95w5/sampler_weights/step-100', 'reuse_from_session_id': None}\n)\n\nprint(response.text)" } ], "description": "Creates a standalone Loops sampler not linked to a run; the sampler belongs to the given team.", @@ -7337,11 +7687,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/training/capacity \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/training/capacity \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training/capacity\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/training/capacity\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Returns GPU capacity limits (baseline and peak) and current usage for the organization.", @@ -7363,11 +7713,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/training/capacity \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"team_id\": null,\n \"gpu_type\": null,\n \"max_gpus\": 8\n}'" + "source": "curl --request PATCH \\\n--url https://api.staging.baseten.co/v1/training/capacity \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"team_id\": null,\n \"gpu_type\": null,\n \"max_gpus\": 8\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training/capacity\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'team_id': None, 'gpu_type': None, 'max_gpus': 8}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/training/capacity\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'team_id': None, 'gpu_type': None, 'max_gpus': 8}\n)\n\nprint(response.text)" } ], "description": "Sets the max concurrent GPUs of a given type a team may use. Creates the limit if one doesn't exist for this (team, gpu_type) pair, otherwise updates it in place. Org-admin only: this is a ceiling the org imposes on the team, not something the team manages for itself.", @@ -7401,11 +7751,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/training/jobs/{training_job_id}/queue_context \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/training/jobs/{training_job_id}/queue_context \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training/jobs/{training_job_id}/queue_context\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/training/jobs/{training_job_id}/queue_context\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Returns the (org, gpu_type) capacity pool the job was gated by, jobs that were holding GPU capacity in that pool when this job was submitted, and every TrainingJobStatus event in [submitted_at, released_at] for those jobs, useful for understanding why a job sat in PENDING. Caller must be an org admin and the job must belong to the caller's org.", @@ -7435,11 +7785,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/blobs/credentials/model \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/blobs/credentials/model \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/blobs/credentials/model\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/blobs/credentials/model\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "responses": { @@ -7462,11 +7812,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/blobs/credentials/train \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/blobs/credentials/train \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/blobs/credentials/train\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/blobs/credentials/train\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "responses": { @@ -7489,11 +7839,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/teams/{team_id}/api_keys \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"name\": \"my-api-key\",\n \"type\": \"PERSONAL\"\n}'" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/teams/{team_id}/api_keys \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"name\": \"my-api-key\",\n \"type\": \"PERSONAL\"\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}/api_keys\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'name': 'my-api-key', 'type': 'PERSONAL'}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/teams/{team_id}/api_keys\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'name': 'my-api-key', 'type': 'PERSONAL'}\n)\n\nprint(response.text)" } ], "description": "Creates a team API key with the provided name and type. The API key is returned in the response.", @@ -7532,14 +7882,44 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/api_keys \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/api_keys \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/api_keys\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/api_keys\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'type': 'WORKSPACE_INVOKE'}\n)\n\nprint(response.text)" } ], "description": "Returns metadata for your personal API keys and the workspace and team API keys you can manage. Organization admins also receive every member's personal API keys, each with an owner identifying the member it belongs to.", + "parameters": [ + { + "name": "type", + "in": "query", + "required": false, + "description": "Filter by API key type", + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/APIKeyCategory" + }, + { + "type": "null" + } + ], + "default": null + } + }, + { + "name": "created_by_me", + "in": "query", + "required": false, + "description": "Return only keys created by the authenticated user", + "schema": { + "default": false, + "title": "Created By Me", + "type": "boolean" + } + } + ], "responses": { "200": { "description": "", @@ -7558,11 +7938,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/api_keys \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"name\": \"my-api-key\",\n \"type\": \"PERSONAL\"\n}'" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/api_keys \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"name\": \"my-api-key\",\n \"type\": \"PERSONAL\"\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/api_keys\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'name': 'my-api-key', 'type': 'PERSONAL'}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/api_keys\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'name': 'my-api-key', 'type': 'PERSONAL'}\n)\n\nprint(response.text)" } ], "description": "Creates an API key with the provided name and type. The API key is returned in the response.", @@ -7596,11 +7976,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/api_keys/{api_key_prefix} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request DELETE \\\n--url https://api.staging.baseten.co/v1/api_keys/{api_key_prefix} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/api_keys/{api_key_prefix}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/api_keys/{api_key_prefix}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Deletes an API key by prefix and returns info about the API key.", @@ -7629,11 +8009,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/model_apis \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/model_apis \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/model_apis\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'cursor': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/model_apis\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'cursor': None}\n)\n\nprint(response.text)" } ], "description": "Lists Model APIs visible to the caller. By default returns the full catalog; pass `added_only=true` to restrict to Model APIs the workspace has added.", @@ -7701,11 +8081,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/model_apis/usage \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/model_apis/usage \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/model_apis/usage\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'start_time': None, 'end_time': None, 'bucket_width': '1m', 'limit': None, 'cursor': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/model_apis/usage\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'start_time': None, 'end_time': None, 'bucket_width': '1m', 'limit': None, 'cursor': None}\n)\n\nprint(response.text)" } ], "description": "Returns your organization's Model APIs token usage as a series of contiguous time buckets, broken down by the dimensions you pass in group_by. Buckets with no usage are included, so the series has no gaps. Usage is retained for 92 days, so buckets older than that are returned with no results.", @@ -7867,11 +8247,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/model_apis/{model_api_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/model_apis/{model_api_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/model_apis/{model_api_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/model_apis/{model_api_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Fetches a Model API by name, with workspace overlay when added.", @@ -7900,11 +8280,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/llm_models \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"resources\": null,\n \"region\": null,\n \"llm_version\": null,\n \"model_metadata\": null,\n \"autoscaling_settings\": {\n \"autoscaling_window\": 600,\n \"concurrency_target\": null,\n \"max_replica\": 5,\n \"max_scale_down_rate\": null,\n \"min_replica\": 1,\n \"scale_down_delay\": 300,\n \"target_in_flight_tokens\": null,\n \"target_utilization_percentage\": null\n },\n \"additional_autoscaling_config\": {\n \"metrics\": [\n {\n \"name\": \"in_flight_tokens\",\n \"target\": 40000\n }\n ]\n },\n \"metadata\": {\n \"environment\": \"production\",\n \"git_sha\": \"abc123\"\n },\n \"weights\": [\n {\n \"mount_location\": \"/models/base\",\n \"source\": \"hf://meta-llama/Llama-3-8B\"\n }\n ],\n \"name\": null\n}'" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/llm_models \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"resources\": null,\n \"region\": null,\n \"llm_version\": null,\n \"model_metadata\": null,\n \"autoscaling_settings\": {\n \"autoscaling_window\": 600,\n \"concurrency_target\": null,\n \"max_replica\": 5,\n \"max_scale_down_rate\": null,\n \"min_replica\": 1,\n \"scale_down_delay\": 300,\n \"target_in_flight_tokens\": null,\n \"target_utilization_percentage\": null\n },\n \"additional_autoscaling_config\": {\n \"metrics\": [\n {\n \"name\": \"in_flight_tokens\",\n \"target\": 40000\n }\n ]\n },\n \"metadata\": {\n \"environment\": \"production\",\n \"git_sha\": \"abc123\"\n },\n \"weights\": [\n {\n \"mount_location\": \"/models/base\",\n \"source\": \"hf://meta-llama/Llama-3-8B\"\n }\n ],\n \"name\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/llm_models\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'resources': None, 'region': None, 'llm_version': None, 'model_metadata': None, 'autoscaling_settings': {'autoscaling_window': 600, 'concurrency_target': None, 'max_replica': 5, 'max_scale_down_rate': None, 'min_replica': 1, 'scale_down_delay': 300, 'target_in_flight_tokens': None, 'target_utilization_percentage': None}, 'additional_autoscaling_config': {'metrics': [{'name': 'in_flight_tokens', 'target': 40000}]}, 'metadata': {'environment': 'production', 'git_sha': 'abc123'}, 'weights': [{'mount_location': '/models/base', 'source': 'hf://meta-llama/Llama-3-8B'}], 'name': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/llm_models\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'resources': None, 'region': None, 'llm_version': None, 'model_metadata': None, 'autoscaling_settings': {'autoscaling_window': 600, 'concurrency_target': None, 'max_replica': 5, 'max_scale_down_rate': None, 'min_replica': 1, 'scale_down_delay': 300, 'target_in_flight_tokens': None, 'target_utilization_percentage': None}, 'additional_autoscaling_config': {'metrics': [{'name': 'in_flight_tokens', 'target': 40000}]}, 'metadata': {'environment': 'production', 'git_sha': 'abc123'}, 'weights': [{'mount_location': '/models/base', 'source': 'hf://meta-llama/Llama-3-8B'}], 'name': None}\n)\n\nprint(response.text)" } ], "requestBody": { @@ -7937,11 +8317,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/teams/{team_id}/llm_models \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"resources\": null,\n \"region\": null,\n \"llm_version\": null,\n \"model_metadata\": null,\n \"autoscaling_settings\": {\n \"autoscaling_window\": 600,\n \"concurrency_target\": null,\n \"max_replica\": 5,\n \"max_scale_down_rate\": null,\n \"min_replica\": 1,\n \"scale_down_delay\": 300,\n \"target_in_flight_tokens\": null,\n \"target_utilization_percentage\": null\n },\n \"additional_autoscaling_config\": {\n \"metrics\": [\n {\n \"name\": \"in_flight_tokens\",\n \"target\": 40000\n }\n ]\n },\n \"metadata\": {\n \"environment\": \"production\",\n \"git_sha\": \"abc123\"\n },\n \"weights\": [\n {\n \"mount_location\": \"/models/base\",\n \"source\": \"hf://meta-llama/Llama-3-8B\"\n }\n ],\n \"name\": null\n}'" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/teams/{team_id}/llm_models \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"resources\": null,\n \"region\": null,\n \"llm_version\": null,\n \"model_metadata\": null,\n \"autoscaling_settings\": {\n \"autoscaling_window\": 600,\n \"concurrency_target\": null,\n \"max_replica\": 5,\n \"max_scale_down_rate\": null,\n \"min_replica\": 1,\n \"scale_down_delay\": 300,\n \"target_in_flight_tokens\": null,\n \"target_utilization_percentage\": null\n },\n \"additional_autoscaling_config\": {\n \"metrics\": [\n {\n \"name\": \"in_flight_tokens\",\n \"target\": 40000\n }\n ]\n },\n \"metadata\": {\n \"environment\": \"production\",\n \"git_sha\": \"abc123\"\n },\n \"weights\": [\n {\n \"mount_location\": \"/models/base\",\n \"source\": \"hf://meta-llama/Llama-3-8B\"\n }\n ],\n \"name\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}/llm_models\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'resources': None, 'region': None, 'llm_version': None, 'model_metadata': None, 'autoscaling_settings': {'autoscaling_window': 600, 'concurrency_target': None, 'max_replica': 5, 'max_scale_down_rate': None, 'min_replica': 1, 'scale_down_delay': 300, 'target_in_flight_tokens': None, 'target_utilization_percentage': None}, 'additional_autoscaling_config': {'metrics': [{'name': 'in_flight_tokens', 'target': 40000}]}, 'metadata': {'environment': 'production', 'git_sha': 'abc123'}, 'weights': [{'mount_location': '/models/base', 'source': 'hf://meta-llama/Llama-3-8B'}], 'name': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/teams/{team_id}/llm_models\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'resources': None, 'region': None, 'llm_version': None, 'model_metadata': None, 'autoscaling_settings': {'autoscaling_window': 600, 'concurrency_target': None, 'max_replica': 5, 'max_scale_down_rate': None, 'min_replica': 1, 'scale_down_delay': 300, 'target_in_flight_tokens': None, 'target_utilization_percentage': None}, 'additional_autoscaling_config': {'metrics': [{'name': 'in_flight_tokens', 'target': 40000}]}, 'metadata': {'environment': 'production', 'git_sha': 'abc123'}, 'weights': [{'mount_location': '/models/base', 'source': 'hf://meta-llama/Llama-3-8B'}], 'name': None}\n)\n\nprint(response.text)" } ], "requestBody": { @@ -7979,11 +8359,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/llm_models/{model_id}/deployments \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"resources\": null,\n \"region\": null,\n \"llm_version\": null,\n \"model_metadata\": null,\n \"autoscaling_settings\": {\n \"autoscaling_window\": 600,\n \"concurrency_target\": null,\n \"max_replica\": 5,\n \"max_scale_down_rate\": null,\n \"min_replica\": 1,\n \"scale_down_delay\": 300,\n \"target_in_flight_tokens\": null,\n \"target_utilization_percentage\": null\n },\n \"additional_autoscaling_config\": {\n \"metrics\": [\n {\n \"name\": \"in_flight_tokens\",\n \"target\": 40000\n }\n ]\n },\n \"metadata\": {\n \"environment\": \"production\",\n \"git_sha\": \"abc123\"\n },\n \"weights\": [\n {\n \"mount_location\": \"/models/base\",\n \"source\": \"hf://meta-llama/Llama-3-8B\"\n }\n ]\n}'" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/llm_models/{model_id}/deployments \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"resources\": null,\n \"region\": null,\n \"llm_version\": null,\n \"model_metadata\": null,\n \"autoscaling_settings\": {\n \"autoscaling_window\": 600,\n \"concurrency_target\": null,\n \"max_replica\": 5,\n \"max_scale_down_rate\": null,\n \"min_replica\": 1,\n \"scale_down_delay\": 300,\n \"target_in_flight_tokens\": null,\n \"target_utilization_percentage\": null\n },\n \"additional_autoscaling_config\": {\n \"metrics\": [\n {\n \"name\": \"in_flight_tokens\",\n \"target\": 40000\n }\n ]\n },\n \"metadata\": {\n \"environment\": \"production\",\n \"git_sha\": \"abc123\"\n },\n \"weights\": [\n {\n \"mount_location\": \"/models/base\",\n \"source\": \"hf://meta-llama/Llama-3-8B\"\n }\n ]\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/llm_models/{model_id}/deployments\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'resources': None, 'region': None, 'llm_version': None, 'model_metadata': None, 'autoscaling_settings': {'autoscaling_window': 600, 'concurrency_target': None, 'max_replica': 5, 'max_scale_down_rate': None, 'min_replica': 1, 'scale_down_delay': 300, 'target_in_flight_tokens': None, 'target_utilization_percentage': None}, 'additional_autoscaling_config': {'metrics': [{'name': 'in_flight_tokens', 'target': 40000}]}, 'metadata': {'environment': 'production', 'git_sha': 'abc123'}, 'weights': [{'mount_location': '/models/base', 'source': 'hf://meta-llama/Llama-3-8B'}]}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/llm_models/{model_id}/deployments\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'resources': None, 'region': None, 'llm_version': None, 'model_metadata': None, 'autoscaling_settings': {'autoscaling_window': 600, 'concurrency_target': None, 'max_replica': 5, 'max_scale_down_rate': None, 'min_replica': 1, 'scale_down_delay': 300, 'target_in_flight_tokens': None, 'target_utilization_percentage': None}, 'additional_autoscaling_config': {'metrics': [{'name': 'in_flight_tokens', 'target': 40000}]}, 'metadata': {'environment': 'production', 'git_sha': 'abc123'}, 'weights': [{'mount_location': '/models/base', 'source': 'hf://meta-llama/Llama-3-8B'}]}\n)\n\nprint(response.text)" } ], "requestBody": { @@ -8021,11 +8401,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/library_listings \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/library_listings \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/library_listings\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/library_listings\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Returns all library listings for the authenticated user's organization.", @@ -8047,11 +8427,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/library_listings \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"display_name\": null,\n \"user_defined_id\": null\n}'" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/library_listings \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"display_name\": null,\n \"user_defined_id\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/library_listings\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'display_name': None, 'user_defined_id': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/library_listings\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'display_name': None, 'user_defined_id': None}\n)\n\nprint(response.text)" } ], "description": "Creates a new library listing for the authenticated user's organization.", @@ -8085,11 +8465,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/library_listings/{user_defined_listing_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request DELETE \\\n--url https://api.staging.baseten.co/v1/library_listings/{user_defined_listing_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/library_listings/{user_defined_listing_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/library_listings/{user_defined_listing_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Deletes a library listing and all of its associated versions. Any versions that are currently live will also be removed.", @@ -8116,11 +8496,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/library_listings/{user_defined_listing_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/library_listings/{user_defined_listing_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/library_listings/{user_defined_listing_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/library_listings/{user_defined_listing_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Returns a specific library listing by its user-defined identifier.", @@ -8142,11 +8522,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/library_listings/{user_defined_listing_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"display_name\": null,\n \"is_public\": null,\n \"trending\": null,\n \"metadata\": null\n}'" + "source": "curl --request PATCH \\\n--url https://api.staging.baseten.co/v1/library_listings/{user_defined_listing_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"display_name\": null,\n \"is_public\": null,\n \"trending\": null,\n \"metadata\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/library_listings/{user_defined_listing_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'display_name': None, 'is_public': None, 'trending': None, 'metadata': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/library_listings/{user_defined_listing_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'display_name': None, 'is_public': None, 'trending': None, 'metadata': None}\n)\n\nprint(response.text)" } ], "description": "Updates a library listing. Supported fields are the display name, public visibility, trending status, and the model-level metadata. When metadata is provided, it replaces the stored metadata.", @@ -8180,11 +8560,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/library_listings/{user_defined_listing_id}/versions \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/library_listings/{user_defined_listing_id}/versions \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/library_listings/{user_defined_listing_id}/versions\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/library_listings/{user_defined_listing_id}/versions\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Returns all versions for a specific library listing.", @@ -8211,11 +8591,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/library_listings/{user_defined_listing_id}/versions \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"display_name\": null,\n \"oracle_version_id\": null,\n \"version_tag\": null\n}'" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/library_listings/{user_defined_listing_id}/versions \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"display_name\": null,\n \"oracle_version_id\": null,\n \"version_tag\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/library_listings/{user_defined_listing_id}/versions\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'display_name': None, 'oracle_version_id': None, 'version_tag': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/library_listings/{user_defined_listing_id}/versions\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'display_name': None, 'oracle_version_id': None, 'version_tag': None}\n)\n\nprint(response.text)" } ], "description": "Creates a new library listing version from an existing model version. The model version must be fully built (have an image_uri). If a listing with the given id already exists for the org, a new version is added. Otherwise, a new listing is created.", @@ -8249,11 +8629,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/library_listings/{user_defined_listing_id}/versions/{version_tag} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request DELETE \\\n--url https://api.staging.baseten.co/v1/library_listings/{user_defined_listing_id}/versions/{version_tag} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/library_listings/{user_defined_listing_id}/versions/{version_tag}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/library_listings/{user_defined_listing_id}/versions/{version_tag}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Deletes a specific version of a library listing. Deleting a live version will fail with a 400 error; demote the version first by setting another version as live.", @@ -8283,11 +8663,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/library_listings/{user_defined_listing_id}/versions/{version_tag} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/library_listings/{user_defined_listing_id}/versions/{version_tag} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/library_listings/{user_defined_listing_id}/versions/{version_tag}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/library_listings/{user_defined_listing_id}/versions/{version_tag}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Returns a specific version of a library listing.", @@ -8309,11 +8689,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/library_listings/{user_defined_listing_id}/versions/{version_tag} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"is_live\": null,\n \"allow_truss_download\": null,\n \"benchmark\": null\n}'" + "source": "curl --request PATCH \\\n--url https://api.staging.baseten.co/v1/library_listings/{user_defined_listing_id}/versions/{version_tag} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"is_live\": null,\n \"allow_truss_download\": null,\n \"benchmark\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/library_listings/{user_defined_listing_id}/versions/{version_tag}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'is_live': None, 'allow_truss_download': None, 'benchmark': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/library_listings/{user_defined_listing_id}/versions/{version_tag}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'is_live': None, 'allow_truss_download': None, 'benchmark': None}\n)\n\nprint(response.text)" } ], "description": "Updates a library listing version. Setting is_live to true will demote the current live version. When a benchmark is provided, it replaces the stored benchmark.", @@ -8347,11 +8727,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/billing/model_apis \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/billing/model_apis \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/billing/model_apis\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'cursor': None, 'start_date': None, 'end_date': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/billing/model_apis\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'cursor': None, 'start_date': None, 'end_date': None}\n)\n\nprint(response.text)" } ], "description": "Returns daily Model API costs in USD for your organization, with optional filtering and grouping by API key, user, model, and service tier. Results may differ from finalized invoice amounts. Cost history is available from August 5, 2026 at 20:45 UTC. August 5 is a partial day; earlier dates are unavailable.", @@ -8511,11 +8891,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/billing/usage_summary \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/billing/usage_summary \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/billing/usage_summary\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'start_date': None, 'end_date': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/billing/usage_summary\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'start_date': None, 'end_date': None}\n)\n\nprint(response.text)" } ], "description": "Returns billing usage data within the specified date range. Includes dedicated model serving, training, and model APIs usage. The date range must not exceed 31 days.", @@ -8557,17 +8937,77 @@ } } }, + "/v1/billing/tool_call_usage": { + "get": { + "summary": "Gets server-side tool call usage", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/billing/tool_call_usage \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/billing/tool_call_usage\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'start_date': None, 'end_date': None}\n)\n\nprint(response.text)" + } + ], + "description": "Returns your organization's server-side tool call usage (web search and fetch tools Baseten executes on your behalf) as daily rows grouped by provider, charge unit (sku), and model.", + "parameters": [ + { + "name": "start_date", + "in": "query", + "required": true, + "description": "Inclusive UTC calendar day at the start of the query range.", + "schema": { + "format": "date", + "title": "Start Date", + "type": "string" + } + }, + { + "name": "end_date", + "in": "query", + "required": false, + "description": "Exclusive UTC calendar day at the end of the query range. Defaults to the day after the current UTC date so current-day usage is included. The date range cannot exceed 90 days.", + "schema": { + "anyOf": [ + { + "format": "date", + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "End Date" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ToolCallUsageResponseV1" + } + } + } + } + } + } + }, "/v1/users": { "get": { "summary": "Lists users in the workspace", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/users \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/users \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/users\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'cursor': None, 'email': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/users\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'cursor': None, 'email': None}\n)\n\nprint(response.text)" } ], "description": "Returns the workspace's members. Only actual joined members are returned; service accounts, invited users, and pending join requests are excluded.", @@ -8643,11 +9083,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/users/me \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/users/me \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/users/me\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/users/me\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Returns info about the user making the request.", @@ -8672,11 +9112,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/users/{user_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/users/{user_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/users/{user_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/users/{user_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Returns info about a user in the caller's workspace.", @@ -8706,11 +9146,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/organizations/me \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/organizations/me \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/organizations/me\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/organizations/me\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Returns info about the organization of the user making the request.", @@ -8735,11 +9175,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/gateway/events \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/gateway/events \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/gateway/events\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'start_time': None, 'end_time': None, 'limit': None, 'cursor': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/gateway/events\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'start_time': None, 'end_time': None, 'limit': None, 'cursor': None}\n)\n\nprint(response.text)" } ], "parameters": [ @@ -8860,110 +9300,185 @@ } } }, - "/v1/gateway/endpoints": { + "/v1/explore/metadata": { "get": { - "summary": "Lists Gateway endpoints", + "summary": "Lists model metadata", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/gateway/endpoints \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/explore/metadata \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/gateway/endpoints\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/explore/metadata\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'cursor': None, 'provider': None, 'q': None}\n)\n\nprint(response.text)" } ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/EndpointsResponseV1" + "description": "Lists all live model metadata rows, e.g. for model pickers.", + "parameters": [ + { + "name": "cursor", + "in": "query", + "required": false, + "description": "Opaque cursor returned by a previous page. Omit to fetch the first page.", + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" } - } + ], + "default": null, + "title": "Cursor" } - } - } - }, - "post": { - "summary": "Creates a Gateway endpoint", - "x-codeSamples": [ + }, { - "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/gateway/endpoints \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"slug\": \"baseten/mymodel-4\",\n \"region\": \"UNRESTRICTED\",\n \"targets\": [\n {\n \"environment_name\": \"staging\",\n \"model_id\": \"3kZ9xqd\",\n \"provider\": \"BASETEN\",\n \"target_model\": \"custom/model-name\"\n }\n ]\n}'" + "name": "limit", + "in": "query", + "required": false, + "description": "Maximum number of items to return.", + "schema": { + "default": 100, + "maximum": 1000, + "minimum": 1, + "title": "Limit", + "type": "integer" + } }, { - "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/gateway/endpoints\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'slug': 'baseten/mymodel-4', 'region': 'UNRESTRICTED', 'targets': [{'environment_name': 'staging', 'model_id': '3kZ9xqd', 'provider': 'BASETEN', 'target_model': 'custom/model-name'}]}\n)\n\nprint(response.text)" - } - ], - "description": "Provisions an endpoint for the given slug and its upstream target. Exactly one target is supported at this time. The slug's prefix must be one your organization owns.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateEndpointRequestV1" - } + "name": "provider", + "in": "query", + "required": false, + "description": "Filter to a provider by slug prefix, e.g. 'anthropic'. Preserved by the cursor; if repeated, must match the original filter.", + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Provider" } }, - "required": true - }, + { + "name": "q", + "in": "query", + "required": false, + "description": "Case-insensitive substring search over metadata slugs. Preserved by the cursor; if repeated, must match the original filter.", + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Q" + } + } + ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/EndpointV1" + "$ref": "#/components/schemas/ExploreMetadataResponseV1" } } } } - } + }, + "x-stability": "unstable" } }, - "/v1/gateway/endpoints/{endpoint_id}": { - "delete": { - "summary": "Deletes a Gateway endpoint", + "/v1/routes": { + "get": { + "summary": "Lists routes", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/gateway/endpoints/{endpoint_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/routes \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/gateway/endpoints/{endpoint_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/routes\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'cursor': None, 'team_id': None, 'name': None}\n)\n\nprint(response.text)" } ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/EndpointTombstoneV1" - } - } + "description": "Lists routes you can invoke, newest first, optionally filtered by team and exact name.", + "parameters": [ + { + "name": "cursor", + "in": "query", + "required": false, + "description": "Opaque cursor returned by a previous page. Omit to fetch the first page.", + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Cursor" } - } - } - }, - "parameters": [ - { - "$ref": "#/components/parameters/endpoint_id" - } - ], - "get": { - "summary": "Gets a Gateway endpoint", - "x-codeSamples": [ + }, { - "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/gateway/endpoints/{endpoint_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "name": "limit", + "in": "query", + "required": false, + "description": "Maximum number of items to return.", + "schema": { + "default": 100, + "maximum": 1000, + "minimum": 1, + "title": "Limit", + "type": "integer" + } }, { - "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/gateway/endpoints/{endpoint_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "name": "team_id", + "in": "query", + "required": false, + "description": "Filter by owning team ID. Preserved by the cursor; if repeated, must match the original filter.", + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Team Id" + } + }, + { + "name": "name", + "in": "query", + "required": false, + "description": "Filter by exact route name. Preserved by the cursor; if repeated, must match the original filter.", + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Name" + } } ], "responses": { @@ -8972,31 +9487,32 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/EndpointV1" + "$ref": "#/components/schemas/RoutesResponseV1" } } } } - } + }, + "x-stability": "unstable" }, - "patch": { - "summary": "Updates a Gateway endpoint", + "post": { + "summary": "Creates a route", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/gateway/endpoints/{endpoint_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"targets\": [\n {\n \"environment_name\": \"staging\",\n \"model_id\": \"3kZ9xqd\",\n \"provider\": \"BASETEN\",\n \"target_model\": \"custom/model-name\"\n }\n ]\n}'" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/routes \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"team_id\": \"abc1234\",\n \"display_name\": \"Assistant\",\n \"target\": {\n \"model\": \"zai-org/GLM-5.3\",\n \"type\": \"BASETEN_MODEL_API\"\n },\n \"description\": \"Assistant for code review and debugging.\"\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/gateway/endpoints/{endpoint_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'targets': [{'environment_name': 'staging', 'model_id': '3kZ9xqd', 'provider': 'BASETEN', 'target_model': 'custom/model-name'}]}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/routes\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'team_id': 'abc1234', 'display_name': 'Assistant', 'target': {'model': 'zai-org/GLM-5.3', 'type': 'BASETEN_MODEL_API'}, 'description': 'Assistant for code review and debugging.'}\n)\n\nprint(response.text)" } ], - "description": "Updates the endpoint's provided mutable fields. If targets are provided, the full target list is replaced. Exactly one target is supported at this time.", + "description": "Creates and derives a name for the provided route configuration", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpdateEndpointRequestV1" + "$ref": "#/components/schemas/CreateRouteRequestV1" } } }, @@ -9008,25 +9524,150 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/EndpointV1" + "$ref": "#/components/schemas/RouteV1" } } } } - } + }, + "x-stability": "unstable" } }, - "/v1/gateway/groups": { + "/v1/routes/usage": { "get": { - "summary": "Lists groups", + "summary": "Gets daily route usage and estimated costs", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/gateway/groups \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/routes/usage \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/gateway/groups\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/routes/usage\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'cursor': None, 'start_date': None, 'end_date': None}\n)\n\nprint(response.text)" + } + ], + "description": "Buckets are UTC days, and days with no usage are included. Organization admins see all route usage in the organization. Other members, including viewers, see only usage from Routes keys they created, including keys that have since expired, been revoked, or been deleted. Usage is metered every 15 minutes, so the current hour can lag. Model API costs use your prices at the time of each request and include tool calls. xAI costs are the charges xAI reports. OpenAI and Anthropic costs are estimated from Baseten's reference prices and may differ from your provider's bill. Vertex and OpenAI-compatible usage is not included. Costs for OpenAI, Anthropic, and xAI estimate what you pay those providers; they are not Baseten charges. Usage is retained for 92 days.", + "parameters": [ + { + "name": "cursor", + "in": "query", + "required": false, + "description": "Opaque cursor returned by a previous page. Omit to fetch the first page.", + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Cursor" + } + }, + { + "name": "limit", + "in": "query", + "required": false, + "description": "Number of daily buckets to return. Defaults to 7; maximum 31.", + "schema": { + "default": 7, + "maximum": 31, + "minimum": 1, + "title": "Limit", + "type": "integer" + } + }, + { + "name": "start_date", + "in": "query", + "required": false, + "description": "Inclusive UTC calendar day at the start of the query range. Defaults to the previous UTC date, and is ignored when you pass a cursor.", + "schema": { + "anyOf": [ + { + "format": "date", + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Start Date" + } + }, + { + "name": "end_date", + "in": "query", + "required": false, + "description": "Exclusive UTC calendar day at the end of the query range. Defaults to the day after the current UTC date so current-day usage is included.", + "schema": { + "anyOf": [ + { + "format": "date", + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "End Date" + } + }, + { + "name": "group_by", + "in": "query", + "required": false, + "description": "Dimensions to break usage down by, repeated once per dimension: USER, MODEL, or PROVIDER. Each result represents one observed combination of the requested dimensions within that day, and results are sorted by those values. Combinations without usage are omitted, so result counts can differ between days. Defaults to MODEL.", + "schema": { + "items": { + "$ref": "#/components/schemas/RouteUsageDimensionV1" + }, + "title": "Group By", + "type": "array" + } + }, + { + "name": "user_ids", + "in": "query", + "required": false, + "description": "Return only usage from Routes keys created by these user IDs, repeated once per ID.", + "schema": { + "items": { + "type": "string" + }, + "title": "User Ids", + "type": "array" + } + }, + { + "name": "models", + "in": "query", + "required": false, + "description": "Return only usage for these exact model names, repeated once per model.", + "schema": { + "items": { + "type": "string" + }, + "title": "Models", + "type": "array" + } + }, + { + "name": "providers", + "in": "query", + "required": false, + "description": "Return only usage for these providers, repeated once per provider.", + "schema": { + "items": { + "$ref": "#/components/schemas/RouteProviderV1" + }, + "title": "Providers", + "type": "array" + } } ], "responses": { @@ -9035,61 +9676,57 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GroupsResponseV1" + "$ref": "#/components/schemas/RoutesUsageResponseV1" } } } } - } - }, - "post": { - "summary": "Creates a group", + }, + "x-stability": "unstable" + } + }, + "/v1/routes/{route_id}": { + "delete": { + "summary": "Deletes a route", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/gateway/groups \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"metadata\": {\n \"name\": \"Acme prod\",\n \"external_entity_id\": \"cust_42\"\n },\n \"models\": [\n {\n \"slug\": \"my-org/claude\"\n }\n ],\n \"hierarchy\": {\n \"limit_enforcement\": \"INDEPENDENT\",\n \"parent_group_id\": \"abc123\"\n }\n}'" + "source": "curl --request DELETE \\\n--url https://api.staging.baseten.co/v1/routes/{route_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/gateway/groups\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'metadata': {'name': 'Acme prod', 'external_entity_id': 'cust_42'}, 'models': [{'slug': 'my-org/claude'}], 'hierarchy': {'limit_enforcement': 'INDEPENDENT', 'parent_group_id': 'abc123'}}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/routes/{route_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Creates a group and its endpoint configuration.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateGroupRequestV1" - } - } - }, - "required": true - }, "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GroupV1" + "$ref": "#/components/schemas/RouteTombstoneV1" } } } } + }, + "x-stability": "unstable" + }, + "parameters": [ + { + "$ref": "#/components/parameters/route_id" } - } - }, - "/v1/gateway/groups/{group_id}": { + ], "get": { - "summary": "Gets a group", + "summary": "Gets a route", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/gateway/groups/{group_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/routes/{route_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/gateway/groups/{group_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/routes/{route_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "responses": { @@ -9098,36 +9735,32 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GroupV1" + "$ref": "#/components/schemas/RouteV1" } } } } - } + }, + "x-stability": "unstable" }, - "parameters": [ - { - "$ref": "#/components/parameters/group_id" - } - ], "patch": { - "summary": "Updates a group", + "summary": "Updates a route's display name or description", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/gateway/groups/{group_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"metadata\": {\n \"name\": \"Acme Prod\"\n },\n \"models\": null\n}'" + "source": "curl --request PATCH \\\n--url https://api.staging.baseten.co/v1/routes/{route_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"description\": \"Assistant for code review and debugging.\",\n \"display_name\": \"Assistant\"\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/gateway/groups/{group_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'metadata': {'name': 'Acme Prod'}, 'models': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/routes/{route_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'description': 'Assistant for code review and debugging.', 'display_name': 'Assistant'}\n)\n\nprint(response.text)" } ], - "description": "Updates the group's mutable fields.", + "description": "The route name, target, and owning team are immutable.", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpdateGroupRequestV1" + "$ref": "#/components/schemas/UpdateRouteRequestV1" } } }, @@ -9139,25 +9772,26 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GroupV1" + "$ref": "#/components/schemas/RouteV1" } } } } - } + }, + "x-stability": "unstable" } }, - "/v1/gateway/groups/{group_id}/api_keys": { + "/v1/gateway/endpoints": { "get": { - "summary": "Lists API keys for a group", + "summary": "Lists Gateway endpoints", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/gateway/groups/{group_id}/api_keys \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/gateway/endpoints \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/gateway/groups/{group_id}/api_keys\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/gateway/endpoints\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "responses": { @@ -9166,36 +9800,124 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/KeysForGroupResponseV1" + "$ref": "#/components/schemas/EndpointsResponseV1" } } } } } }, - "parameters": [ - { - "$ref": "#/components/parameters/group_id" + "post": { + "summary": "Creates a Gateway endpoint", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/gateway/endpoints \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"slug\": \"baseten/mymodel-4\",\n \"region\": \"UNRESTRICTED\",\n \"targets\": [\n {\n \"environment_name\": \"staging\",\n \"model_id\": \"3kZ9xqd\",\n \"provider\": \"BASETEN\",\n \"target_model\": \"custom/model-name\"\n }\n ]\n}'" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/gateway/endpoints\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'slug': 'baseten/mymodel-4', 'region': 'UNRESTRICTED', 'targets': [{'environment_name': 'staging', 'model_id': '3kZ9xqd', 'provider': 'BASETEN', 'target_model': 'custom/model-name'}]}\n)\n\nprint(response.text)" + } + ], + "description": "Provisions an endpoint for the given slug and its upstream target. Exactly one target is supported at this time. The slug's prefix must be one your organization owns.", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateEndpointRequestV1" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EndpointV1" + } + } + } + } + } + } + }, + "/v1/gateway/endpoints/{endpoint_id}": { + "delete": { + "summary": "Deletes a Gateway endpoint", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request DELETE \\\n--url https://api.staging.baseten.co/v1/gateway/endpoints/{endpoint_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/gateway/endpoints/{endpoint_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EndpointTombstoneV1" + } + } + } + } + } + }, + "parameters": [ + { + "$ref": "#/components/parameters/endpoint_id" } ], - "post": { - "summary": "Creates an API key for a group", + "get": { + "summary": "Gets a Gateway endpoint", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/gateway/groups/{group_id}/api_keys \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"name\": \"prod-key-1\"\n}'" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/gateway/endpoints/{endpoint_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/gateway/groups/{group_id}/api_keys\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'name': 'prod-key-1'}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/gateway/endpoints/{endpoint_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Creates a new API key for the given group.", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EndpointV1" + } + } + } + } + } + }, + "patch": { + "summary": "Updates a Gateway endpoint", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request PATCH \\\n--url https://api.staging.baseten.co/v1/gateway/endpoints/{endpoint_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"targets\": [\n {\n \"environment_name\": \"staging\",\n \"model_id\": \"3kZ9xqd\",\n \"provider\": \"BASETEN\",\n \"target_model\": \"custom/model-name\"\n }\n ]\n}'" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/gateway/endpoints/{endpoint_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'targets': [{'environment_name': 'staging', 'model_id': '3kZ9xqd', 'provider': 'BASETEN', 'target_model': 'custom/model-name'}]}\n)\n\nprint(response.text)" + } + ], + "description": "Updates the endpoint's provided mutable fields. If targets are provided, the full target list is replaced. Exactly one target is supported at this time.", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateApiKeyForGroupRequestV1" + "$ref": "#/components/schemas/UpdateEndpointRequestV1" } } }, @@ -9207,7 +9929,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateApiKeyForGroupResponseV1" + "$ref": "#/components/schemas/EndpointV1" } } } @@ -9215,25 +9937,50 @@ } } }, - "/v1/gateway/groups/{group_id}/api_keys/register": { + "/v1/gateway/groups": { + "get": { + "summary": "Lists groups", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/gateway/groups \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/gateway/groups\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GroupsResponseV1" + } + } + } + } + } + }, "post": { - "summary": "Registers an API key for a group", + "summary": "Creates a group", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.baseten.co/v1/gateway/groups/{group_id}/api_keys/register \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"name\": \"my-model-api-key\",\n \"key\": \"my-secure-api-key-value\"\n}'" + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/gateway/groups \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"metadata\": {\n \"name\": \"Acme prod\",\n \"external_entity_id\": \"cust_42\"\n },\n \"models\": [\n {\n \"slug\": \"my-org/claude\"\n }\n ],\n \"hierarchy\": {\n \"limit_enforcement\": \"INDEPENDENT\",\n \"parent_group_id\": \"abc123\"\n }\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/gateway/groups/{group_id}/api_keys/register\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'name': 'my-model-api-key', 'key': 'my-secure-api-key-value'}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/gateway/groups\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'metadata': {'name': 'Acme prod', 'external_entity_id': 'cust_42'}, 'models': [{'slug': 'my-org/claude'}], 'hierarchy': {'limit_enforcement': 'INDEPENDENT', 'parent_group_id': 'abc123'}}\n)\n\nprint(response.text)" } ], - "description": "Registers a Gateway API key with the provided value and name.", + "description": "Creates a group and its endpoint configuration.", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/RegisterAPIKeyRequestV1" + "$ref": "#/components/schemas/CreateGroupRequestV1" } } }, @@ -9245,7 +9992,34 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/RegisterAPIKeyResponseV1" + "$ref": "#/components/schemas/GroupV1" + } + } + } + } + } + } + }, + "/v1/gateway/groups/{group_id}": { + "get": { + "summary": "Gets a group", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/gateway/groups/{group_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/gateway/groups/{group_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GroupV1" } } } @@ -9256,19 +10030,55 @@ { "$ref": "#/components/parameters/group_id" } - ] + ], + "patch": { + "summary": "Updates a group", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request PATCH \\\n--url https://api.staging.baseten.co/v1/gateway/groups/{group_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"metadata\": {\n \"name\": \"Acme Prod\"\n },\n \"models\": null\n}'" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/gateway/groups/{group_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'metadata': {'name': 'Acme Prod'}, 'models': None}\n)\n\nprint(response.text)" + } + ], + "description": "Updates the group's mutable fields.", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateGroupRequestV1" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GroupV1" + } + } + } + } + } + } }, - "/v1/gateway/groups/{group_id}/api_keys/{api_key_prefix}": { + "/v1/gateway/groups/{group_id}/api_keys": { "get": { - "summary": "Gets an API key for a group", + "summary": "Lists API keys for a group", "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.baseten.co/v1/gateway/groups/{group_id}/api_keys/{api_key_prefix} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/gateway/groups/{group_id}/api_keys \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/gateway/groups/{group_id}/api_keys/{api_key_prefix}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/gateway/groups/{group_id}/api_keys\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "responses": { @@ -9277,7 +10087,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GatewayKeyInfoV1" + "$ref": "#/components/schemas/KeysForGroupResponseV1" } } } @@ -9287,1004 +10097,952 @@ "parameters": [ { "$ref": "#/components/parameters/group_id" - }, - { - "$ref": "#/components/parameters/api_key_prefix" } - ] - } - }, - "openapi": "3.1.0", - "components": { - "schemas": { - "PaginationResponseV1": { - "properties": { - "has_more": { - "description": "Whether more items exist after this page.", - "title": "Has More", - "type": "boolean" + ], + "post": { + "summary": "Creates an API key for a group", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/gateway/groups/{group_id}/api_keys \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"name\": \"prod-key-1\"\n}'" }, - "cursor": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "description": "Opaque cursor to pass into the next request. Null when there is no next page.", - "title": "Cursor" + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/gateway/groups/{group_id}/api_keys\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'name': 'prod-key-1'}\n)\n\nprint(response.text)" } - }, - "required": [ - "has_more" ], - "title": "PaginationResponseV1", - "type": "object" - }, - "VolumeTagV1": { - "properties": { - "name": { - "description": "Tag name. Tags are case-sensitive.", - "title": "Name", - "type": "string" + "description": "Creates a new API key for the given group.", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateApiKeyForGroupRequestV1" + } + } }, - "digest": { - "description": "Digest of the version the tag points at, as `b3:`.", - "title": "Digest", - "type": "string" - } + "required": true }, - "required": [ - "name", - "digest" + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateApiKeyForGroupResponseV1" + } + } + } + } + } + } + }, + "/v1/gateway/groups/{group_id}/api_keys/register": { + "post": { + "summary": "Registers an API key for a group", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/gateway/groups/{group_id}/api_keys/register \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"name\": \"my-model-api-key\",\n \"key\": \"my-secure-api-key-value\"\n}'" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/gateway/groups/{group_id}/api_keys/register\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'name': 'my-model-api-key', 'key': 'my-secure-api-key-value'}\n)\n\nprint(response.text)" + } ], - "title": "VolumeTagV1", - "type": "object" + "description": "Registers a Gateway API key with the provided value and name.", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RegisterAPIKeyRequestV1" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RegisterAPIKeyResponseV1" + } + } + } + } + } }, - "VolumeV1": { - "properties": { - "namespace": { - "description": "Namespace the volume belongs to, in lowercase.", - "title": "Namespace", - "type": "string" + "parameters": [ + { + "$ref": "#/components/parameters/group_id" + } + ] + }, + "/v1/gateway/groups/{group_id}/api_keys/{api_key_prefix}": { + "get": { + "summary": "Gets an API key for a group", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/gateway/groups/{group_id}/api_keys/{api_key_prefix} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, - "name": { - "description": "Name of the volume, in lowercase.", - "title": "Name", - "type": "string" + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/gateway/groups/{group_id}/api_keys/{api_key_prefix}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GatewayKeyInfoV1" + } + } + } + } + } + }, + "parameters": [ + { + "$ref": "#/components/parameters/group_id" + }, + { + "$ref": "#/components/parameters/api_key_prefix" + } + ] + }, + "/v1/sandboxes/instances": { + "get": { + "operationId": "ListSandboxes", + "summary": "List sandboxes", + "description": "Return a cursor-paginated page of sandboxes. Terminated sandboxes are hidden by default.", + "tags": [ + "Sandboxes" + ], + "parameters": [ + { + "$ref": "#/components/parameters/TeamId" }, - "version_ref": { - "description": "Full address of the volume, as `bdn:/`. Paste this into the `bdn.mounts` section of a config.yaml.", - "title": "Version Ref", - "type": "string" + { + "$ref": "#/components/parameters/TeamIdHeader" }, - "sequence": { - "description": "Revision counter for the volume, incremented on every commit and tag change. Use it to detect that a volume changed.", - "title": "Sequence", - "type": "integer" + { + "$ref": "#/components/parameters/Cursor" }, - "updated_at": { - "description": "When the volume last changed, in ISO 8601 format.", - "format": "date-time", - "title": "Updated At", - "type": "string" + { + "$ref": "#/components/parameters/Limit" }, - "head": { - "anyOf": [ - { - "$ref": "#/components/schemas/VolumeVersionSummaryV1" + { + "name": "q", + "in": "query", + "description": "Search indexed sandbox names and labels. Search is applied before pagination.", + "required": false, + "schema": { + "type": "string", + "example": "api-review" + } + }, + { + "name": "status", + "in": "query", + "description": "Deployment statuses. Repeat the query parameter for each status, for example status=DEPLOYED&status=FAILED. Unknown values are rejected. Cannot be combined with external_id.", + "required": false, + "style": "form", + "explode": true, + "schema": { + "type": "array", + "minItems": 1, + "items": { + "type": "string", + "minLength": 1 }, - { - "type": "null" + "example": [ + "DEPLOYED", + "FAILED" + ] + } + }, + { + "name": "external_id", + "in": "query", + "description": "Filter by a caller-owned external identifier. Cannot be combined with status.", + "required": false, + "schema": { + "type": "string", + "example": "api-review-20260916-001" + } + } + ], + "responses": { + "200": { + "description": "Successful operation.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ListSandboxesResponseV1" + }, + "examples": { + "page": { + "$ref": "#/components/examples/SandboxesPage" + }, + "last_page": { + "$ref": "#/components/examples/SandboxesLastPage" + } + } } - ], - "description": "Version that the reserved `head` tag points at, which a reference with no tag or digest resolves to. Null when the volume has no head, or when your API key cannot read it." + } }, - "tags": { - "description": "Tags on the volume that your API key can read.", - "items": { - "$ref": "#/components/schemas/VolumeTagV1" - }, - "title": "Tags", - "type": "array" + "400": { + "$ref": "#/components/responses/SandboxError400" }, - "tag_count": { - "description": "Total number of tags on the volume, which can exceed the length of `tags` when your API key cannot read all of them.", - "title": "Tag Count", - "type": "integer" + "401": { + "$ref": "#/components/responses/SandboxError401" }, - "versions_alive": { - "description": "Number of versions that have not been deleted.", - "title": "Versions Alive", - "type": "integer" + "403": { + "$ref": "#/components/responses/SandboxError403" }, - "versions_tombstoned": { - "description": "Number of versions that have been deleted.", - "title": "Versions Tombstoned", - "type": "integer" + "429": { + "$ref": "#/components/responses/SandboxError429" }, - "versions_untagged": { - "description": "Number of versions that no tag points at.", - "title": "Versions Untagged", - "type": "integer" + "500": { + "$ref": "#/components/responses/SandboxError500" } }, - "required": [ - "namespace", - "name", - "version_ref", - "sequence", - "updated_at", - "head", - "tags", - "tag_count", - "versions_alive", - "versions_tombstoned", - "versions_untagged" - ], - "title": "VolumeV1", - "type": "object" + "x-stability": "unstable" }, - "VolumeVersionSummaryV1": { - "properties": { - "digest": { - "description": "Content digest of the version, as `b3:`.", - "title": "Digest", - "type": "string" - }, - "total_size_bytes": { - "description": "Total size of the version's files in bytes.", - "title": "Total Size Bytes", - "type": "integer" + "post": { + "parameters": [ + { + "$ref": "#/components/parameters/TeamId" }, - "created_at": { - "description": "When the version was committed, in ISO 8601 format.", - "format": "date-time", - "title": "Created At", - "type": "string" + { + "$ref": "#/components/parameters/TeamIdHeader" } - }, - "required": [ - "digest", - "total_size_bytes", - "created_at" ], - "title": "VolumeVersionSummaryV1", - "type": "object" - }, - "ListVolumesResponseV1": { - "description": "A page of volumes in one namespace.", - "properties": { - "items": { - "description": "Items in this page.", - "items": { - "$ref": "#/components/schemas/VolumeV1" - }, - "title": "Items", - "type": "array" - }, - "pagination": { - "$ref": "#/components/schemas/PaginationResponseV1", - "description": "Pagination metadata for the page." - } - }, - "required": [ - "items", - "pagination" + "operationId": "CreateSandbox", + "summary": "Create a sandbox", + "description": "Create a sandbox with an optional client-provided name, generated by the server when omitted. The request waits briefly for deployment, then returns the created resource. Deployment may continue after the response; inspect status to determine readiness. Names belonging to failed or terminated sandboxes can be reused; an active sandbox reserves its name. To get started, set image to blaxel/base-image:latest, the built-in image with the sandbox execution API ready to use. It is available directly; no image build, push, or GET /v1/sandboxes/images is needed. Use the returned url to execute commands with the same Bearer API key.", + "tags": [ + "Sandboxes" ], - "title": "ListVolumesResponseV1", - "type": "object" - }, - "ListVolumesRequestV1": { - "properties": { - "cursor": { - "anyOf": [ - { - "type": "string" + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateSandboxRequestV1" }, - { - "type": "null" + "examples": { + "quickstart": { + "$ref": "#/components/examples/CreateSandboxQuickstart" + }, + "complete": { + "$ref": "#/components/examples/CreateSandbox" + } } - ], - "default": null, - "description": "Opaque cursor returned by a previous page. Omit to fetch the first page.", - "title": "Cursor" - }, - "limit": { - "default": 100, - "description": "Maximum number of volumes to return.", - "maximum": 1000, - "minimum": 1, - "title": "Limit", - "type": "integer" - }, - "namespace": { - "description": "Namespace to list volumes in. Required, because the volume service has no cross-namespace inventory.", - "title": "Namespace", - "type": "string" + } } }, - "required": [ - "namespace" - ], - "title": "ListVolumesRequestV1", - "type": "object" - }, - "VolumeTokenScopeV1": { - "description": "Capability a volume token grants.\n\n- ``PULL``: read volume data.\n- ``INSPECT``: read volume metadata without data access.\n- ``PUSH``: upload and commit volume versions.\n- ``TAG``: move or remove tags.", - "enum": [ - "PULL", - "INSPECT", - "PUSH", - "TAG" - ], - "title": "VolumeTokenScopeV1", - "type": "string" - }, - "CreateVolumeTokenRequestV1": { - "additionalProperties": false, - "properties": { - "scopes": { - "description": "Capabilities the token grants, at least one. Requesting PUSH or TAG requires organization-level model management permission.", - "items": { - "$ref": "#/components/schemas/VolumeTokenScopeV1" - }, - "minItems": 1, - "title": "Scopes", - "type": "array" + "responses": { + "201": { + "description": "Sandbox created.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SandboxV1" + }, + "examples": { + "complete": { + "$ref": "#/components/examples/SandboxReady" + } + } + } + } }, - "namespaces": { - "description": "Volume namespaces the token is limited to, lowercase ASCII, at least one. Pass only the namespaces the operation needs.", - "items": { - "type": "string" - }, - "minItems": 1, - "title": "Namespaces", - "type": "array" + "400": { + "$ref": "#/components/responses/SandboxError400" }, - "volumes": { - "description": "Volume names the token is limited to, lowercase ASCII, exact names only, at least one. The limit applies to every requested scope in every requested namespace.", - "items": { - "type": "string" - }, - "minItems": 1, - "title": "Volumes", - "type": "array" + "401": { + "$ref": "#/components/responses/SandboxError401" }, - "correlation_id": { - "anyOf": [ - { - "maxLength": 128, - "pattern": "^[\\x21-\\x7e]+$", - "type": "string" - }, - { - "type": "null" + "403": { + "$ref": "#/components/responses/SandboxError403" + }, + "409": { + "description": "An active sandbox with the requested name already exists. Returns a JSON error with code, message, and optional details.", + "content": { + "application/json": { + "example": { + "code": "ALREADY_EXISTS", + "message": "A sandbox with this name already exists.", + "details": { + "name": "baseten-api-review-0916" + } + } } - ], - "default": null, - "description": "Optional client-chosen identifier, at most 128 printable ASCII characters. Echoed into server logs to link the issued token to a client operation.", - "title": "Correlation Id" + } + }, + "429": { + "$ref": "#/components/responses/SandboxError429" + }, + "500": { + "$ref": "#/components/responses/SandboxError500" } }, - "required": [ - "scopes", - "namespaces", - "volumes" + "x-stability": "unstable" + } + }, + "/v1/sandboxes/instances/{sandbox_name}": { + "parameters": [ + { + "$ref": "#/components/parameters/SandboxName" + } + ], + "get": { + "operationId": "GetSandbox", + "summary": "Get a sandbox", + "description": "Return the sandbox configuration and current state.", + "tags": [ + "Sandboxes" ], - "title": "CreateVolumeTokenRequestV1", - "type": "object" - }, - "CreateVolumeTokenResponseV1": { - "properties": { - "token": { - "description": "Volume access token. Pass as a bearer token to the volume APIs.", - "title": "Token", - "type": "string" + "parameters": [ + { + "$ref": "#/components/parameters/TeamId" }, - "expires_at": { - "description": "Token expiry in ISO 8601 format. Tokens cannot be renewed; exchange again for a fresh token.", - "format": "date-time", - "title": "Expires At", - "type": "string" + { + "$ref": "#/components/parameters/TeamIdHeader" + } + ], + "responses": { + "200": { + "description": "Successful operation.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SandboxV1" + }, + "examples": { + "complete": { + "$ref": "#/components/examples/SandboxReady" + } + } + } + } }, - "scopes": { - "description": "Effective capabilities granted.", - "items": { - "$ref": "#/components/schemas/VolumeTokenScopeV1" - }, - "title": "Scopes", - "type": "array" + "401": { + "$ref": "#/components/responses/SandboxError401" }, - "namespaces": { - "description": "Effective namespaces granted, in canonical lowercase form.", - "items": { - "type": "string" - }, - "title": "Namespaces", - "type": "array" + "403": { + "$ref": "#/components/responses/SandboxError403" }, - "volumes": { - "description": "Effective volume names granted, in canonical lowercase form.", - "items": { - "type": "string" - }, - "title": "Volumes", - "type": "array" + "404": { + "$ref": "#/components/responses/SandboxError404" }, - "bdn_endpoint": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Base URL of the volume API this token authenticates against. Null when the environment does not expose a public volume API yet.", - "title": "Bdn Endpoint" + "429": { + "$ref": "#/components/responses/SandboxError429" + }, + "500": { + "$ref": "#/components/responses/SandboxError500" } }, - "required": [ - "token", - "expires_at", - "scopes", - "namespaces", - "volumes", - "bdn_endpoint" - ], - "title": "CreateVolumeTokenResponseV1", - "type": "object" + "x-stability": "unstable" }, - "ListVolumeNamespacesResponseV1": { - "description": "A page of namespaces the caller can read.", - "properties": { - "items": { - "description": "Items in this page.", - "items": { - "type": "string" - }, - "title": "Items", - "type": "array" + "patch": { + "parameters": [ + { + "$ref": "#/components/parameters/TeamId" }, - "pagination": { - "$ref": "#/components/schemas/PaginationResponseV1", - "description": "Pagination metadata for the page." + { + "$ref": "#/components/parameters/TeamIdHeader" } - }, - "required": [ - "items", - "pagination" ], - "title": "ListVolumeNamespacesResponseV1", - "type": "object" - }, - "ListVolumeNamespacesRequestV1": { - "properties": { - "cursor": { - "anyOf": [ - { - "type": "string" + "operationId": "UpdateSandbox", + "summary": "Update a sandbox", + "description": "Partially update configuration. Omitted fields remain unchanged; supplied arrays and maps replace their previous values. Structured objects update only supplied fields. Changes to image may reset running state. The name, memory, and network configuration are immutable after creation. Supplying memory or network returns 400, including unchanged, empty, or null values.", + "tags": [ + "Sandboxes" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateSandboxRequestV1" }, - { - "type": "null" + "examples": { + "complete": { + "$ref": "#/components/examples/UpdateSandbox" + } } - ], - "default": null, - "description": "Opaque cursor returned by a previous page. Omit to fetch the first page.", - "title": "Cursor" + } + } + }, + "responses": { + "200": { + "description": "Successful operation.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SandboxV1" + }, + "examples": { + "complete": { + "$ref": "#/components/examples/SandboxUpdated" + } + } + } + } }, - "limit": { - "default": 100, - "description": "Maximum number of namespaces to return.", - "maximum": 1000, - "minimum": 1, - "title": "Limit", - "type": "integer" + "400": { + "description": "Invalid request, including attempts to change memory or network configuration.", + "content": { + "application/json": { + "example": { + "code": "INVALID_REQUEST", + "message": "Memory and network configuration cannot be changed after creation." + } + } + } + }, + "401": { + "$ref": "#/components/responses/SandboxError401" + }, + "403": { + "$ref": "#/components/responses/SandboxError403" + }, + "404": { + "$ref": "#/components/responses/SandboxError404" + }, + "409": { + "$ref": "#/components/responses/SandboxError409" + }, + "429": { + "$ref": "#/components/responses/SandboxError429" + }, + "500": { + "$ref": "#/components/responses/SandboxError500" } }, - "title": "ListVolumeNamespacesRequestV1", - "type": "object" + "x-stability": "unstable" }, - "DeleteVolumeRequestV1": { - "properties": { - "expected_sequence": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null, - "description": "Revision the volume is expected to be at. When set, the delete fails with a conflict if the volume has changed since, so it cannot act on a volume someone else has pushed to. Take the value from a volume's sequence, or from volume_sequence.", - "title": "Expected Sequence" + "delete": { + "parameters": [ + { + "$ref": "#/components/parameters/TeamId" + }, + { + "$ref": "#/components/parameters/TeamIdHeader" } - }, - "title": "DeleteVolumeRequestV1", - "type": "object" - }, - "DeleteVolumeResponseV1": { - "properties": { - "namespace": { - "description": "Namespace the volume belongs to, in lowercase.", - "title": "Namespace", - "type": "string" + ], + "operationId": "DeleteSandbox", + "summary": "Delete a sandbox", + "description": "Permanently delete the sandbox and its local data asynchronously. The returned resource has status DELETING.", + "tags": [ + "Sandboxes" + ], + "responses": { + "202": { + "description": "Request accepted.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SandboxV1" + }, + "examples": { + "complete": { + "$ref": "#/components/examples/SandboxDeleting" + } + } + } + } }, - "name": { - "description": "Name of the volume, in lowercase.", - "title": "Name", - "type": "string" + "401": { + "$ref": "#/components/responses/SandboxError401" }, - "versions_deleted": { - "description": "Number of versions this request deleted. Zero when the volume had no live versions left, which is not an error.", - "title": "Versions Deleted", - "type": "integer" + "403": { + "$ref": "#/components/responses/SandboxError403" }, - "volume_sequence": { - "description": "Revision of the volume after the delete.", - "title": "Volume Sequence", - "type": "integer" + "404": { + "$ref": "#/components/responses/SandboxError404" + }, + "409": { + "$ref": "#/components/responses/SandboxError409" + }, + "429": { + "$ref": "#/components/responses/SandboxError429" + }, + "500": { + "$ref": "#/components/responses/SandboxError500" } }, - "required": [ - "namespace", - "name", - "versions_deleted", - "volume_sequence" + "x-stability": "unstable" + } + }, + "/v1/sandboxes/images": { + "get": { + "operationId": "ListImages", + "summary": "List sandbox images", + "description": "Return one cursor-paginated page of image repository summaries. Tags are listed separately. Pages can be empty when non-sandbox repositories are excluded; follow pagination.cursor while pagination.has_more is true. Prefix search forces ascending name order.", + "tags": [ + "Images" ], - "title": "DeleteVolumeResponseV1", - "type": "object" - }, - "VolumeVersionV1": { - "properties": { - "namespace": { - "description": "Namespace the volume belongs to, in lowercase.", - "title": "Namespace", - "type": "string" - }, - "volume": { - "description": "Name of the volume, in lowercase.", - "title": "Volume", - "type": "string" - }, - "version_ref": { - "description": "Full address of this version, as `bdn:/@`. Paste this into the `bdn.mounts` section of a config.yaml to pin to it.", - "title": "Version Ref", - "type": "string" + "parameters": [ + { + "$ref": "#/components/parameters/TeamId" }, - "digest": { - "description": "Content digest of the version, as `b3:`.", - "title": "Digest", - "type": "string" + { + "$ref": "#/components/parameters/TeamIdHeader" }, - "sequence": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Revision the version was committed at. Null for versions committed before the volume service recorded it.", - "title": "Sequence" + { + "$ref": "#/components/parameters/Cursor" }, - "lifecycle": { - "description": "Lifecycle state of the version, for example ALIVE or TOMBSTONED.", - "title": "Lifecycle", - "type": "string" + { + "$ref": "#/components/parameters/Limit" }, - "is_head": { - "description": "Whether the reserved `head` tag points at this version.", - "title": "Is Head", - "type": "boolean" + { + "name": "sort", + "in": "query", + "description": "Sort by repository name or creation time: name:asc, name:desc, createdAt:asc, or createdAt:desc. Keep the same sort when following a cursor.", + "schema": { + "type": "string", + "default": "createdAt:desc" + } }, - "tags": { - "description": "Tags pointing at this version that your API key can read.", - "items": { + { + "name": "q", + "in": "query", + "description": "Case-sensitive repository name prefix. Search is applied before pagination.", + "schema": { "type": "string" - }, - "title": "Tags", - "type": "array" - }, - "total_size_bytes": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" + } + } + ], + "responses": { + "200": { + "description": "Successful operation.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ListImagesResponseV1" + }, + "examples": { + "complete": { + "$ref": "#/components/examples/ImagesList" + } + } } - ], - "description": "Total size of the version's files in bytes. Null when not recorded.", - "title": "Total Size Bytes" + } }, - "created_at": { - "description": "When the version was committed, in ISO 8601 format.", - "format": "date-time", - "title": "Created At", - "type": "string" + "400": { + "$ref": "#/components/responses/SandboxError400" }, - "tombstoned_at": { - "anyOf": [ - { - "format": "date-time", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the version was deleted, in ISO 8601 format. Null unless the lifecycle is TOMBSTONED.", - "title": "Tombstoned At" + "401": { + "$ref": "#/components/responses/SandboxError401" }, - "delete_after": { - "anyOf": [ - { - "format": "date-time", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the version stops being restorable, in ISO 8601 format. Null unless the lifecycle is TOMBSTONED.", - "title": "Delete After" + "403": { + "$ref": "#/components/responses/SandboxError403" + }, + "429": { + "$ref": "#/components/responses/SandboxError429" + }, + "500": { + "$ref": "#/components/responses/SandboxError500" } }, - "required": [ - "namespace", - "volume", - "version_ref", - "digest", - "sequence", - "lifecycle", - "is_head", - "tags", - "total_size_bytes", - "created_at", - "tombstoned_at", - "delete_after" - ], - "title": "VolumeVersionV1", - "type": "object" + "x-stability": "unstable" }, - "ListVolumeVersionsResponseV1": { - "description": "Every version of a volume, newest first.\n\nUnpaginated: `limit` and `cursor` are absent rather than accepted and\nignored, so adding them once the volume service pages this listing is a\npurely additive change.", - "properties": { - "versions": { - "description": "Versions of the volume, newest first.", - "items": { - "$ref": "#/components/schemas/VolumeVersionV1" - }, - "title": "Versions", - "type": "array" + "post": { + "parameters": [ + { + "$ref": "#/components/parameters/TeamId" }, - "volume_sequence": { - "description": "Revision of the volume as a whole when the versions were read. Pass it as expected_sequence on a later delete to make that delete conditional on the volume not having changed since. Distinct from the per-version sequence, which is the revision a version was committed at.", - "title": "Volume Sequence", - "type": "integer" + { + "$ref": "#/components/parameters/TeamIdHeader" } - }, - "required": [ - "versions", - "volume_sequence" ], - "title": "ListVolumeVersionsResponseV1", - "type": "object" - }, - "ListVolumeVersionsRequestV1": { - "properties": { - "include_tombstoned": { - "default": false, - "description": "Whether to include deleted versions. A deleted version carries a TOMBSTONED lifecycle and stays restorable until its recovery deadline passes.", - "title": "Include Tombstoned", - "type": "boolean" - } - }, - "title": "ListVolumeVersionsRequestV1", - "type": "object" - }, - "DeleteVolumeVersionRequestV1": { - "properties": { - "expected_sequence": { - "anyOf": [ - { - "type": "integer" + "operationId": "PushImage", + "summary": "Push a sandbox image", + "description": "With image supplied, import the registry image asynchronously. Otherwise return an upload URL for a ZIP source archive containing its Dockerfile and build context. Processing starts after upload. No sandbox is created. Poll the image until BUILT or FAILED.", + "tags": [ + "Images" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PushImageRequestV1" }, - { - "type": "null" + "examples": { + "archive": { + "$ref": "#/components/examples/PushArchive" + }, + "registry": { + "$ref": "#/components/examples/PushRegistry" + } } - ], - "default": null, - "description": "Revision the volume is expected to be at. When set, the delete fails with a conflict if the volume has changed since, so a read followed by a delete cannot act on a version a tag has since been moved off. Take the value from volume_sequence.", - "title": "Expected Sequence" + } } }, - "title": "DeleteVolumeVersionRequestV1", - "type": "object" - }, - "DeleteVolumeVersionResponseV1": { - "properties": { - "namespace": { - "description": "Namespace the volume belongs to, in lowercase.", - "title": "Namespace", - "type": "string" - }, - "volume": { - "description": "Name of the volume, in lowercase.", - "title": "Volume", - "type": "string" + "responses": { + "202": { + "description": "Request accepted.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PushImageResponseV1" + }, + "examples": { + "archive": { + "$ref": "#/components/examples/PushArchiveAccepted" + }, + "registry": { + "$ref": "#/components/examples/PushRegistryAccepted" + } + } + } + } }, - "version_ref": { - "description": "Full address of the deleted version, as `bdn:/@`.", - "title": "Version Ref", - "type": "string" + "400": { + "$ref": "#/components/responses/SandboxError400" }, - "digest": { - "description": "Content digest of the deleted version, as `b3:`.", - "title": "Digest", - "type": "string" + "401": { + "$ref": "#/components/responses/SandboxError401" }, - "lifecycle": { - "description": "Lifecycle state of the version after the delete.", - "title": "Lifecycle", - "type": "string" + "403": { + "$ref": "#/components/responses/SandboxError403" }, - "delete_after": { - "description": "When the version stops being restorable, in ISO 8601 format. Until then it can be returned to service.", - "format": "date-time", - "title": "Delete After", - "type": "string" + "429": { + "$ref": "#/components/responses/SandboxError429" }, - "volume_sequence": { - "description": "Revision of the volume after the delete.", - "title": "Volume Sequence", - "type": "integer" + "500": { + "$ref": "#/components/responses/SandboxError500" } }, - "required": [ - "namespace", - "volume", - "version_ref", - "digest", - "lifecycle", - "delete_after", - "volume_sequence" - ], - "title": "DeleteVolumeVersionResponseV1", - "type": "object" - }, - "VolumeVersionDetailV1": { - "description": "One version, with the fields only a single-version read reports.", - "properties": { - "namespace": { - "description": "Namespace the volume belongs to, in lowercase.", - "title": "Namespace", - "type": "string" - }, - "volume": { - "description": "Name of the volume, in lowercase.", - "title": "Volume", - "type": "string" + "x-stability": "unstable" + } + }, + "/v1/sandboxes/cleanup_images": { + "post": { + "parameters": [ + { + "$ref": "#/components/parameters/TeamId" }, - "version_ref": { - "description": "Full address of this version, as `bdn:/@`. Paste this into the `bdn.mounts` section of a config.yaml to pin to it.", - "title": "Version Ref", - "type": "string" + { + "$ref": "#/components/parameters/TeamIdHeader" + } + ], + "operationId": "CleanupImages", + "summary": "Clean up unused images", + "description": "Remove unused sandbox image versions. Versions referenced by active deployments are preserved.", + "tags": [ + "Images" + ], + "responses": { + "200": { + "description": "Successful operation.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CleanupImagesResponseV1" + }, + "examples": { + "complete": { + "$ref": "#/components/examples/CleanupImages" + } + } + } + } }, - "digest": { - "description": "Content digest of the version, as `b3:`.", - "title": "Digest", - "type": "string" + "400": { + "$ref": "#/components/responses/SandboxError400" }, - "sequence": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Revision the version was committed at. Null for versions committed before the volume service recorded it.", - "title": "Sequence" + "401": { + "$ref": "#/components/responses/SandboxError401" }, - "lifecycle": { - "description": "Lifecycle state of the version, for example ALIVE or TOMBSTONED.", - "title": "Lifecycle", - "type": "string" + "403": { + "$ref": "#/components/responses/SandboxError403" }, - "is_head": { - "description": "Whether the reserved `head` tag points at this version.", - "title": "Is Head", - "type": "boolean" + "429": { + "$ref": "#/components/responses/SandboxError429" }, - "tags": { - "description": "Tags pointing at this version that your API key can read.", - "items": { - "type": "string" - }, - "title": "Tags", - "type": "array" + "500": { + "$ref": "#/components/responses/SandboxError500" + } + }, + "x-stability": "unstable" + } + }, + "/v1/sandboxes/images/{image_name}": { + "parameters": [ + { + "$ref": "#/components/parameters/ImageName" + } + ], + "get": { + "operationId": "GetImage", + "summary": "Get a sandbox image", + "description": "Return the repository summary and processing status. Use the tag listing endpoint for image versions.", + "tags": [ + "Images" + ], + "parameters": [ + { + "$ref": "#/components/parameters/TeamId" }, - "total_size_bytes": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" + { + "$ref": "#/components/parameters/TeamIdHeader" + } + ], + "responses": { + "200": { + "description": "Successful operation.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ImageV1" + }, + "examples": { + "complete": { + "$ref": "#/components/examples/ImageSummary" + } + } } - ], - "description": "Total size of the version's files in bytes. Null when not recorded.", - "title": "Total Size Bytes" + } }, - "created_at": { - "description": "When the version was committed, in ISO 8601 format.", - "format": "date-time", - "title": "Created At", - "type": "string" + "401": { + "$ref": "#/components/responses/SandboxError401" }, - "tombstoned_at": { - "anyOf": [ - { - "format": "date-time", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the version was deleted, in ISO 8601 format. Null unless the lifecycle is TOMBSTONED.", - "title": "Tombstoned At" + "403": { + "$ref": "#/components/responses/SandboxError403" }, - "delete_after": { - "anyOf": [ - { - "format": "date-time", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the version stops being restorable, in ISO 8601 format. Null unless the lifecycle is TOMBSTONED.", - "title": "Delete After" + "404": { + "$ref": "#/components/responses/SandboxError404" }, - "entry_count": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Number of files in the version. Null when not recorded.", - "title": "Entry Count" + "429": { + "$ref": "#/components/responses/SandboxError429" }, - "volume_sequence": { - "description": "Revision of the volume as a whole when this version was read. Pass it as expected_sequence on a later delete to make that delete conditional on the volume not having changed since.", - "title": "Volume Sequence", - "type": "integer" + "500": { + "$ref": "#/components/responses/SandboxError500" } }, - "required": [ - "namespace", - "volume", - "version_ref", - "digest", - "sequence", - "lifecycle", - "is_head", - "tags", - "total_size_bytes", - "created_at", - "tombstoned_at", - "delete_after", - "entry_count", - "volume_sequence" - ], - "title": "VolumeVersionDetailV1", - "type": "object" + "x-stability": "unstable" }, - "RestoreVolumeVersionRequestV1": { - "properties": { - "expected_sequence": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null, - "description": "Revision the volume is expected to be at. When set, the restore fails with a conflict if the volume has changed since. Take the value from volume_sequence.", - "title": "Expected Sequence" + "delete": { + "parameters": [ + { + "$ref": "#/components/parameters/TeamId" + }, + { + "$ref": "#/components/parameters/TeamIdHeader" } - }, - "title": "RestoreVolumeVersionRequestV1", - "type": "object" - }, - "RestoreVolumeVersionResponseV1": { - "properties": { - "namespace": { - "description": "Namespace the volume belongs to, in lowercase.", - "title": "Namespace", - "type": "string" + ], + "operationId": "DeleteImage", + "summary": "Delete a sandbox image", + "description": "Delete the image repository and all its tags. Reject deletion if any version is referenced by an active deployment. Return the deleted image.", + "tags": [ + "Images" + ], + "responses": { + "200": { + "description": "Successful operation.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ImageV1" + }, + "examples": { + "complete": { + "$ref": "#/components/examples/ImageReady" + } + } + } + } }, - "volume": { - "description": "Name of the volume, in lowercase.", - "title": "Volume", - "type": "string" + "401": { + "$ref": "#/components/responses/SandboxError401" }, - "version_ref": { - "description": "Full address of the restored version, as `bdn:/@`.", - "title": "Version Ref", - "type": "string" + "403": { + "$ref": "#/components/responses/SandboxError403" }, - "digest": { - "description": "Content digest of the restored version, as `b3:`.", - "title": "Digest", - "type": "string" + "404": { + "$ref": "#/components/responses/SandboxError404" }, - "lifecycle": { - "description": "Lifecycle state of the version after the restore.", - "title": "Lifecycle", - "type": "string" + "409": { + "$ref": "#/components/responses/SandboxError409" }, - "volume_sequence": { - "description": "Revision of the volume after the restore.", - "title": "Volume Sequence", - "type": "integer" + "429": { + "$ref": "#/components/responses/SandboxError429" + }, + "500": { + "$ref": "#/components/responses/SandboxError500" } }, - "required": [ - "namespace", - "volume", - "version_ref", - "digest", - "lifecycle", - "volume_sequence" + "x-stability": "unstable" + } + }, + "/v1/sandboxes/images/{image_name}/tags": { + "parameters": [ + { + "$ref": "#/components/parameters/ImageName" + } + ], + "get": { + "operationId": "ListImageTags", + "summary": "List image tags", + "description": "Return one cursor-paginated page of image versions.", + "tags": [ + "Images" ], - "title": "RestoreVolumeVersionResponseV1", - "type": "object" - }, - "SecretV1": { - "description": "A Baseten secret. Note that we do not support retrieving secret values.", - "properties": { - "id": { - "description": "Stable identifier for the secret. Unchanged across rotation.", - "examples": [ - "3kZ9xqd" - ], - "title": "Id", - "type": "string" + "parameters": [ + { + "$ref": "#/components/parameters/TeamId" }, - "created_at": { - "description": "Time the secret was created in ISO 8601 format", - "format": "date-time", - "title": "Created At", - "type": "string" + { + "$ref": "#/components/parameters/TeamIdHeader" }, - "name": { - "description": "Name of the secret", - "title": "Name", - "type": "string" + { + "$ref": "#/components/parameters/Cursor" }, - "team_name": { - "description": "Name of the team the secret belongs to", - "title": "Team Name", - "type": "string" + { + "$ref": "#/components/parameters/Limit" + }, + { + "name": "sort", + "in": "query", + "description": "Sort by tag name: name:asc or name:desc. Keep the same sort when following a cursor.", + "schema": { + "type": "string", + "default": "name:asc" + } + }, + { + "name": "q", + "in": "query", + "description": "Case-sensitive tag name prefix. Cannot be combined with name. Forces ascending name order.", + "schema": { + "type": "string" + } + }, + { + "name": "name", + "in": "query", + "description": "Exact tag name. Cannot be combined with q. Forces ascending name order.", + "schema": { + "type": "string" + } } - }, - "required": [ - "id", - "created_at", - "name", - "team_name" ], - "title": "SecretV1", - "type": "object" - }, - "SecretsV1": { - "description": "A list of Baseten secrets.", - "properties": { - "secrets": { - "items": { - "$ref": "#/components/schemas/SecretV1" - }, - "title": "Secrets", - "type": "array" + "responses": { + "200": { + "description": "Successful operation.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ListImageTagsResponseV1" + } + } + } + }, + "400": { + "$ref": "#/components/responses/SandboxError400" + }, + "401": { + "$ref": "#/components/responses/SandboxError401" + }, + "403": { + "$ref": "#/components/responses/SandboxError403" + }, + "404": { + "$ref": "#/components/responses/SandboxError404" + }, + "429": { + "$ref": "#/components/responses/SandboxError429" + }, + "500": { + "$ref": "#/components/responses/SandboxError500" } }, - "required": [ - "secrets" - ], - "title": "SecretsV1", - "type": "object" - }, - "UpsertSecretRequestV1": { - "description": "A request to create or update a Baseten secret by name.", - "properties": { - "name": { - "description": "Name of the new or existing secret", - "examples": [ - "my_secret" - ], - "title": "Name", - "type": "string" + "x-stability": "unstable" + } + }, + "/v1/sandboxes/images/{image_name}/tags/{tag_name}": { + "parameters": [ + { + "$ref": "#/components/parameters/ImageName" + }, + { + "$ref": "#/components/parameters/TagName" + } + ], + "delete": { + "parameters": [ + { + "$ref": "#/components/parameters/TeamId" }, - "value": { - "description": "Value of the secret", - "examples": [ - "my_secret_value" - ], - "title": "Value", - "type": "string" + { + "$ref": "#/components/parameters/TeamIdHeader" } - }, - "required": [ - "name", - "value" ], - "title": "UpsertSecretRequestV1", - "type": "object" - }, - "SecretTombstoneV1": { - "description": "A secret tombstone.", - "properties": { - "name": { - "description": "Name of the deleted secret", - "title": "Name", - "type": "string" - } - }, - "required": [ - "name" + "operationId": "DeleteImageTag", + "summary": "Delete an image tag", + "description": "Delete a specific image version. Reject deletion if the version is referenced by an active deployment. Return the updated image with its remaining tags, possibly empty.", + "tags": [ + "Images" ], - "title": "SecretTombstoneV1", - "type": "object" - }, - "EnvironmentGroupManageAccessV1": { - "description": "Who is allowed to manage an environment group.", - "properties": { - "is_restricted": { - "description": "Whether the environment is restricted to a specific set of users.", - "title": "Is Restricted", - "type": "boolean" + "responses": { + "200": { + "description": "Successful operation.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ImageV1" + }, + "examples": { + "complete": { + "$ref": "#/components/examples/ImageAfterTagDeletion" + } + } + } + } }, - "users": { - "description": "Users who can manage the environment while it is restricted, including organization and team admins who always have access. Empty when the environment is unrestricted.", - "items": { - "$ref": "#/components/schemas/EnvironmentGroupUserV1" - }, - "title": "Users", - "type": "array" + "401": { + "$ref": "#/components/responses/SandboxError401" + }, + "403": { + "$ref": "#/components/responses/SandboxError403" + }, + "404": { + "$ref": "#/components/responses/SandboxError404" + }, + "409": { + "$ref": "#/components/responses/SandboxError409" + }, + "429": { + "$ref": "#/components/responses/SandboxError429" + }, + "500": { + "$ref": "#/components/responses/SandboxError500" } }, - "required": [ - "is_restricted" - ], - "title": "EnvironmentGroupManageAccessV1", - "type": "object" - }, - "EnvironmentGroupUserV1": { - "description": "A user referenced by an environment group's manage access.", + "x-stability": "unstable" + } + } + }, + "openapi": "3.1.0", + "components": { + "schemas": { + "PaginationResponseV1": { "properties": { - "user_id": { - "description": "Unique identifier for the user.", - "title": "User Id", - "type": "string" + "has_more": { + "description": "Whether more items exist after this page.", + "title": "Has More", + "type": "boolean" }, - "email": { + "cursor": { "anyOf": [ { "type": "string" @@ -10294,185 +11052,221 @@ } ], "default": null, - "description": "Email address of the user.", - "title": "Email" - }, + "description": "Opaque cursor to pass into the next request. Null when there is no next page.", + "title": "Cursor" + } + }, + "required": [ + "has_more" + ], + "title": "PaginationResponseV1", + "type": "object" + }, + "VolumeTagV1": { + "properties": { "name": { + "description": "Tag name. Tags are case-sensitive.", + "title": "Name", + "type": "string" + }, + "digest": { + "description": "Digest of the version the tag points at, as `b3:`.", + "title": "Digest", + "type": "string" + }, + "expires_at": { "anyOf": [ { + "format": "date-time", "type": "string" }, { "type": "null" } ], - "default": null, - "description": "Display name of the user.", - "title": "Name" + "description": "When the tag stops resolving and leaves the volume, in ISO 8601 format. Null for a tag that never expires. The version it points at is not affected.", + "title": "Expires At" } }, "required": [ - "user_id" + "name", + "digest", + "expires_at" ], - "title": "EnvironmentGroupUserV1", + "title": "VolumeTagV1", "type": "object" }, - "EnvironmentGroupV1": { - "description": "A team-scoped grouping of same-named environments (e.g. \"production\", \"staging\").\n\nRestricting an environment group limits who can manage the environment of that name\nacross every model and chain in the team.", + "VolumeV1": { "properties": { + "namespace": { + "description": "Namespace the volume belongs to, in lowercase.", + "title": "Namespace", + "type": "string" + }, "name": { - "description": "Name of the environment group, matching the environment name it governs.", - "examples": [ - "staging" - ], + "description": "Name of the volume, in lowercase.", "title": "Name", "type": "string" }, - "team_id": { - "description": "Unique identifier of the team the environment group belongs to.", - "title": "Team Id", + "version_ref": { + "description": "Full address of the volume, as `bdn:/`. Paste this into the `bdn.mounts` section of a config.yaml.", + "title": "Version Ref", "type": "string" }, - "team_name": { - "description": "Name of the team the environment group belongs to.", - "title": "Team Name", + "sequence": { + "description": "Revision counter for the volume, incremented on every commit, tag change, delete, and restore. A tag or version that expires leaves without changing it; the next write then increments it once. Use it to detect that a volume was written to.", + "title": "Sequence", + "type": "integer" + }, + "updated_at": { + "description": "When the volume was last written to, in ISO 8601 format. An expiry does not update it.", + "format": "date-time", + "title": "Updated At", "type": "string" }, - "manage_access": { - "$ref": "#/components/schemas/EnvironmentGroupManageAccessV1", - "description": "Settings controlling who can manage this environment group." - } - }, - "required": [ - "name", - "team_id", - "team_name", - "manage_access" - ], - "title": "EnvironmentGroupV1", - "type": "object" - }, - "EnvironmentGroupsV1": { - "description": "A page of environment groups.", - "properties": { - "items": { - "description": "Items in this page.", - "items": { - "$ref": "#/components/schemas/EnvironmentGroupV1" - }, - "title": "Items", - "type": "array" + "expires_at": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the whole volume expires, in ISO 8601 format. At that instant every live version is deleted, every tag drops, and the volume leaves the volume listing; each version then stays restorable until its recovery deadline passes. Null for a volume that never expires.", + "title": "Expires At" }, - "pagination": { - "$ref": "#/components/schemas/PaginationResponseV1", - "description": "Pagination metadata for the page." - } - }, - "required": [ - "items", - "pagination" - ], - "title": "EnvironmentGroupsV1", - "type": "object" - }, - "UpdateEnvironmentGroupManageAccessV1": { - "description": "Manage-access settings to apply to an environment group.", - "properties": { - "is_restricted": { - "description": "Whether to restrict this environment to a specific set of users.", - "title": "Is Restricted", - "type": "boolean" + "head": { + "anyOf": [ + { + "$ref": "#/components/schemas/VolumeVersionSummaryV1" + }, + { + "type": "null" + } + ], + "description": "Version that the reserved `head` tag points at, which a reference with no tag or digest resolves to. Never an expiring version. Null when the volume has no head, or when your API key cannot read it." }, - "user_ids": { - "description": "IDs of users granted manage access while restricted. Only meaningful when is_restricted is true.", + "tags": { + "description": "Tags on the volume that your API key can read. A tag with `expires_at` leaves this list at that instant.", "items": { - "type": "string" + "$ref": "#/components/schemas/VolumeTagV1" }, - "title": "User Ids", + "title": "Tags", "type": "array" - } - }, - "required": [ - "is_restricted" - ], - "title": "UpdateEnvironmentGroupManageAccessV1", - "type": "object" - }, - "UpdateEnvironmentGroupRequestV1": { - "description": "A request to update an existing environment group.", - "properties": { - "manage_access": { + }, + "tag_count": { + "description": "Total number of tags on the volume, which can exceed the length of `tags` when your API key cannot read all of them. Counts only tags that have not expired.", + "title": "Tag Count", + "type": "integer" + }, + "versions_alive": { + "description": "Number of versions that have not been deleted or expired.", + "title": "Versions Alive", + "type": "integer" + }, + "versions_tombstoned": { + "description": "Number of versions that have been deleted or expired and are still within their recovery window.", + "title": "Versions Tombstoned", + "type": "integer" + }, + "versions_untagged": { + "description": "Number of live versions that no tag points at.", + "title": "Versions Untagged", + "type": "integer" + }, + "versions_expiring": { + "description": "Number of live versions with an expiry still ahead of them. A version that has already expired counts in `versions_tombstoned` instead.", + "title": "Versions Expiring", + "type": "integer" + }, + "versions_earliest_expires_at": { "anyOf": [ { - "$ref": "#/components/schemas/UpdateEnvironmentGroupManageAccessV1" + "format": "date-time", + "type": "string" }, { "type": "null" } ], - "default": null, - "description": "Manage-access settings to apply. Omit to leave manage access unchanged." + "description": "Earliest expiry among the live versions, in ISO 8601 format. Null when no live version is scheduled to expire.", + "title": "Versions Earliest Expires At" } }, - "title": "UpdateEnvironmentGroupRequestV1", + "required": [ + "namespace", + "name", + "version_ref", + "sequence", + "updated_at", + "expires_at", + "head", + "tags", + "tag_count", + "versions_alive", + "versions_tombstoned", + "versions_untagged", + "versions_expiring", + "versions_earliest_expires_at" + ], + "title": "VolumeV1", "type": "object" }, - "TeamV1": { - "description": "A team.", + "VolumeVersionSummaryV1": { "properties": { - "id": { - "description": "Unique identifier of the team", - "title": "Id", - "type": "string" - }, - "name": { - "description": "Name of the team", - "title": "Name", + "digest": { + "description": "Content digest of the version, as `b3:`.", + "title": "Digest", "type": "string" }, - "default": { - "type": "boolean", - "description": "Whether this is the default team for the organization", - "title": "Default" + "total_size_bytes": { + "description": "Total size of the version's files in bytes.", + "title": "Total Size Bytes", + "type": "integer" }, "created_at": { - "description": "Time the team was created in ISO 8601 format", + "description": "When the version was committed, in ISO 8601 format.", "format": "date-time", "title": "Created At", "type": "string" } }, "required": [ - "id", - "name", - "default", + "digest", + "total_size_bytes", "created_at" ], - "title": "TeamV1", + "title": "VolumeVersionSummaryV1", "type": "object" }, - "TeamsV1": { - "description": "A list of teams.", + "ListVolumesResponseV1": { + "description": "A page of volumes in one namespace.", "properties": { - "teams": { - "description": "A list of teams", + "items": { + "description": "Items in this page.", "items": { - "$ref": "#/components/schemas/TeamV1" + "$ref": "#/components/schemas/VolumeV1" }, - "title": "Teams", + "title": "Items", "type": "array" + }, + "pagination": { + "$ref": "#/components/schemas/PaginationResponseV1", + "description": "Pagination metadata for the page." } }, "required": [ - "teams" + "items", + "pagination" ], - "title": "TeamsV1", + "title": "ListVolumesResponseV1", "type": "object" }, - "TeamsRequestV1": { - "description": "Request parameters for listing teams.", + "ListVolumesRequestV1": { "properties": { - "name": { + "cursor": { "anyOf": [ { "type": "string" @@ -10482,86 +11276,132 @@ } ], "default": null, - "description": "When set, returns only the team with this exact name, if any.", - "title": "Name" - } - }, - "title": "TeamsRequestV1", - "type": "object" - }, - "RegionV1": { - "description": "A region that deployments can be placed in.", - "properties": { - "slug": { - "description": "Stable identifier for the region, used when selecting a deployment region.", - "examples": [ - "us" - ], - "title": "Slug", - "type": "string" + "description": "Opaque cursor returned by a previous page. Omit to fetch the first page.", + "title": "Cursor" }, - "display_name": { - "description": "Human-readable name of the region.", - "examples": [ - "United States" - ], - "title": "Display Name", + "limit": { + "default": 100, + "description": "Maximum number of volumes to return.", + "maximum": 1000, + "minimum": 1, + "title": "Limit", + "type": "integer" + }, + "namespace": { + "description": "Namespace to list volumes in. Required, because the volume service has no cross-namespace inventory.", + "title": "Namespace", "type": "string" } }, "required": [ - "slug", - "display_name" + "namespace" ], - "title": "RegionV1", + "title": "ListVolumesRequestV1", "type": "object" }, - "RegionsV1": { - "description": "A list of regions.", - "properties": { - "regions": { - "items": { - "$ref": "#/components/schemas/RegionV1" - }, - "title": "Regions", + "VolumeTokenScopeV1": { + "description": "Capability a volume token grants.\n\n- ``PULL``: read volume data.\n- ``INSPECT``: read volume metadata without data access.\n- ``PUSH``: upload and commit volume versions.\n- ``TAG``: move or remove tags.", + "enum": [ + "PULL", + "INSPECT", + "PUSH", + "TAG" + ], + "title": "VolumeTokenScopeV1", + "type": "string" + }, + "CreateVolumeTokenRequestV1": { + "additionalProperties": false, + "properties": { + "scopes": { + "description": "Capabilities the token grants, at least one. Requesting PUSH or TAG requires organization-level model management permission.", + "items": { + "$ref": "#/components/schemas/VolumeTokenScopeV1" + }, + "minItems": 1, + "title": "Scopes", + "type": "array" + }, + "namespaces": { + "description": "Volume namespaces the token is limited to, lowercase ASCII, at least one. Pass only the namespaces the operation needs.", + "items": { + "type": "string" + }, + "minItems": 1, + "title": "Namespaces", + "type": "array" + }, + "volumes": { + "description": "Volume names the token is limited to, lowercase ASCII, exact names only, at least one. The limit applies to every requested scope in every requested namespace.", + "items": { + "type": "string" + }, + "minItems": 1, + "title": "Volumes", "type": "array" + }, + "correlation_id": { + "anyOf": [ + { + "maxLength": 128, + "pattern": "^[\\x21-\\x7e]+$", + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Optional client-chosen identifier, at most 128 printable ASCII characters. Echoed into server logs to link the issued token to a client operation.", + "title": "Correlation Id" } }, "required": [ - "regions" + "scopes", + "namespaces", + "volumes" ], - "title": "RegionsV1", + "title": "CreateVolumeTokenRequestV1", "type": "object" }, - "InstanceTypeV1": { - "description": "An instance type.", + "CreateVolumeTokenResponseV1": { "properties": { - "id": { - "description": "Identifier string for the instance type", - "title": "Id", + "token": { + "description": "Volume access token. Pass as a bearer token to the volume APIs.", + "title": "Token", "type": "string" }, - "name": { - "description": "Display name of the instance type", - "title": "Name", + "expires_at": { + "description": "Token expiry in ISO 8601 format. Tokens cannot be renewed; exchange again for a fresh token.", + "format": "date-time", + "title": "Expires At", "type": "string" }, - "memory_limit_mib": { - "description": "Memory limit of the instance type in Mebibytes", - "title": "Memory Limit Mib", - "type": "integer" + "scopes": { + "description": "Effective capabilities granted.", + "items": { + "$ref": "#/components/schemas/VolumeTokenScopeV1" + }, + "title": "Scopes", + "type": "array" }, - "millicpu_limit": { - "description": "CPU limit of the instance type in millicpu", - "title": "Millicpu Limit", - "type": "integer" + "namespaces": { + "description": "Effective namespaces granted, in canonical lowercase form.", + "items": { + "type": "string" + }, + "title": "Namespaces", + "type": "array" }, - "gpu_count": { - "description": "Number of GPUs on the instance type", - "title": "Gpu Count", - "type": "integer" + "volumes": { + "description": "Effective volume names granted, in canonical lowercase form.", + "items": { + "type": "string" + }, + "title": "Volumes", + "type": "array" }, - "gpu_type": { + "bdn_endpoint": { "anyOf": [ { "type": "string" @@ -10570,233 +11410,209 @@ "type": "null" } ], - "description": "Type of GPU on the instance type", - "title": "Gpu Type" - }, - "gpu_memory_limit_mib": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Memory limit of the GPU on the instance type in Mebibytes", - "title": "Gpu Memory Limit Mib" + "description": "Base URL of the volume API this token authenticates against. Null when the environment does not expose a public volume API yet.", + "title": "Bdn Endpoint" } }, "required": [ - "id", - "name", - "memory_limit_mib", - "millicpu_limit", - "gpu_count", - "gpu_type", - "gpu_memory_limit_mib" + "token", + "expires_at", + "scopes", + "namespaces", + "volumes", + "bdn_endpoint" ], - "title": "InstanceTypeV1", + "title": "CreateVolumeTokenResponseV1", "type": "object" }, - "InstanceTypesV1": { - "description": "A list of instance types.", + "ListVolumeNamespacesResponseV1": { + "description": "A page of namespaces the caller can read.", "properties": { - "instance_types": { + "items": { + "description": "Items in this page.", "items": { - "$ref": "#/components/schemas/InstanceTypeV1" + "type": "string" }, - "title": "Instance Types", + "title": "Items", "type": "array" + }, + "pagination": { + "$ref": "#/components/schemas/PaginationResponseV1", + "description": "Pagination metadata for the page." } }, "required": [ - "instance_types" + "items", + "pagination" ], - "title": "InstanceTypesV1", + "title": "ListVolumeNamespacesResponseV1", "type": "object" }, - "LoopsUserConfigV1": { - "description": "The caller's Loops user-level config (accelerator priorities).", + "ListVolumeNamespacesRequestV1": { "properties": { - "trainer_accelerator_priority": { + "cursor": { "anyOf": [ { - "items": { - "type": "string" - }, - "type": "array" + "type": "string" }, { "type": "null" } ], - "description": "Ordered allowlist of GPU types for your Loops trainer deployments, highest priority first. Intersected with the org-level allowlist (org acts as a ceiling). Null means 'inherit the org-level allowlist'.", - "examples": [ - [ - "H100", - "H200" - ] - ], - "title": "Trainer Accelerator Priority" + "default": null, + "description": "Opaque cursor returned by a previous page. Omit to fetch the first page.", + "title": "Cursor" }, - "sampler_accelerator_priority": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "Ordered allowlist of GPU types for your Loops sampler deployments, highest priority first. Intersected with the org-level allowlist (org acts as a ceiling). Null means 'inherit the org-level allowlist'.", - "examples": [ - [ - "H100", - "H200" - ] - ], - "title": "Sampler Accelerator Priority" + "limit": { + "default": 100, + "description": "Maximum number of namespaces to return.", + "maximum": 1000, + "minimum": 1, + "title": "Limit", + "type": "integer" + } + }, + "title": "ListVolumeNamespacesRequestV1", + "type": "object" + }, + "VolumeSyncAuthenticationAWSAssumeRoleV1": { + "additionalProperties": false, + "description": "Authentication using an AWS IAM role assumed by Baseten.", + "properties": { + "role_arn": { + "description": "AWS IAM role ARN to assume.", + "minLength": 1, + "title": "Role Arn", + "type": "string" + }, + "region": { + "description": "AWS region for the assumed role session.", + "minLength": 1, + "title": "Region", + "type": "string" } }, "required": [ - "trainer_accelerator_priority", - "sampler_accelerator_priority" + "role_arn", + "region" ], - "title": "LoopsUserConfigV1", + "title": "VolumeSyncAuthenticationAWSAssumeRoleV1", "type": "object" }, - "GetLoopsUserConfigResponseV1": { - "description": "Response for ``GET /v1/loops/user_config``.", + "VolumeSyncAuthenticationAWSOIDCV1": { + "additionalProperties": false, + "description": "Authentication using an AWS IAM role and Baseten workload identity.", "properties": { - "user_config": { - "$ref": "#/components/schemas/LoopsUserConfigV1", - "description": "The caller's Loops user config." + "role_arn": { + "description": "AWS IAM role ARN to assume through OIDC.", + "minLength": 1, + "title": "Role Arn", + "type": "string" + }, + "region": { + "description": "AWS region for the OIDC role session.", + "minLength": 1, + "title": "Region", + "type": "string" } }, "required": [ - "user_config" + "role_arn", + "region" ], - "title": "GetLoopsUserConfigResponseV1", + "title": "VolumeSyncAuthenticationAWSOIDCV1", "type": "object" }, - "PatchLoopsUserConfigRequestV1": { - "description": "Request body for ``PATCH /v1/loops/user_config``.\n\nFollows JSON Merge Patch (RFC 7396) semantics per field: omit the field\nto leave it unchanged, send ``null`` to clear and inherit the org-level\nallowlist, send a list to set the allowlist. Empty lists are rejected\nbecause the storage layer normalizes ``null`` and ``[]`` identically, so\naccepting both would create two ways to spell the same intent.", + "VolumeSyncAuthenticationGCPOIDCV1": { + "additionalProperties": false, + "description": "Authentication using GCP Workload Identity Federation.", "properties": { - "trainer_accelerator_priority": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "default": null, - "description": "Ordered list of GPU types for trainer deployments, highest priority first. Send a list to set; send null to clear (inherit org allowlist); omit to leave unchanged. Empty list is rejected.", - "examples": [ - [ - "H100", - "H200" - ] - ], - "title": "Trainer Accelerator Priority", - "x-null-distinct": true + "service_account": { + "description": "GCP service account to impersonate through OIDC.", + "minLength": 1, + "title": "Service Account", + "type": "string" }, - "sampler_accelerator_priority": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "default": null, - "description": "Ordered list of GPU types for sampler deployments, highest priority first. Send a list to set; send null to clear (inherit org allowlist); omit to leave unchanged. Empty list is rejected.", - "examples": [ - [ - "H100", - "H200" - ] - ], - "title": "Sampler Accelerator Priority", - "x-null-distinct": true + "workload_identity_provider": { + "description": "Full resource name of the GCP workload identity provider.", + "minLength": 1, + "title": "Workload Identity Provider", + "type": "string" } }, - "title": "PatchLoopsUserConfigRequestV1", + "required": [ + "service_account", + "workload_identity_provider" + ], + "title": "VolumeSyncAuthenticationGCPOIDCV1", "type": "object" }, - "PatchLoopsUserConfigResponseV1": { - "description": "Response for ``PATCH /v1/loops/user_config``.", + "VolumeSyncDestinationV1": { + "additionalProperties": false, + "description": "BDN destination for a volume sync.", "properties": { - "user_config": { - "$ref": "#/components/schemas/LoopsUserConfigV1", - "description": "The updated Loops user config." + "ref": { + "description": "Destination as bdn:/ with an optional tag.", + "title": "Ref", + "type": "string" } }, "required": [ - "user_config" + "ref" ], - "title": "PatchLoopsUserConfigResponseV1", + "title": "VolumeSyncDestinationV1", "type": "object" }, - "InstanceTypeWithPriceV1": { + "VolumeSyncErrorV1": { + "description": "Public failure details for a volume sync.", "properties": { - "instance_type": { - "$ref": "#/components/schemas/InstanceTypeV1", - "description": "Instance type properties." + "code": { + "description": "Stable machine-readable failure classification.", + "title": "Code", + "type": "string" }, - "price": { - "description": "Usage price in USD / minute.", - "title": "Price", - "type": "number" + "message": { + "description": "Redacted user-facing failure message.", + "title": "Message", + "type": "string" } }, "required": [ - "instance_type", - "price" + "code", + "message" ], - "title": "InstanceTypeWithPriceV1", + "title": "VolumeSyncErrorV1", "type": "object" }, - "InstanceTypePricesV1": { - "description": "A list of instance types.", + "VolumeSyncSourceAzureV1": { + "additionalProperties": false, + "description": "Azure Blob Storage source.", "properties": { - "instance_types": { + "uri": { + "description": "Remote source URI to materialize into the destination volume.", + "title": "Uri", + "type": "string" + }, + "include": { + "description": "Glob patterns selecting files to include.", "items": { - "$ref": "#/components/schemas/InstanceTypeWithPriceV1" + "type": "string" }, - "title": "Instance Types", + "title": "Include", "type": "array" - } - }, - "required": [ - "instance_types" - ], - "title": "InstanceTypePricesV1", - "type": "object" - }, - "DeploymentArchivePayloadV1": { - "description": "Deployment-level fields for a model-archive push.\n\nShared by every endpoint that creates a deployment from an uploaded archive:\n`POST /v1/prepare_model_upload`, the `model_archive` source on `POST\n/v1/models`, and `POST /v1/models/{model_id}/deployments`.", - "properties": { - "config": { - "additionalProperties": true, - "description": "Parsed model config as a JSON object.", - "title": "Config", - "type": "object" }, - "raw_config": { + "exclude": { + "description": "Glob patterns selecting files to exclude.", + "items": { + "type": "string" + }, + "title": "Exclude", + "type": "array" + }, + "auth_secret_name": { "anyOf": [ { + "minLength": 1, "type": "string" }, { @@ -10804,26 +11620,91 @@ } ], "default": null, - "description": "Original config.yaml text, persisted as-is on the deployment. Best-effort: invalid raw configs are logged and dropped without failing the request.", - "title": "Raw Config" + "description": "Optional workspace secret containing credentials for this source.", + "title": "Auth Secret Name" }, - "user_env": { - "anyOf": [ - { - "additionalProperties": true, - "type": "object" - }, - { - "type": "null" - } - ], - "default": null, - "description": "Client environment metadata (e.g. client version, Python version). Validated server-side.", - "title": "User Env" + "type": { + "const": "AZURE", + "description": "Azure Blob Storage source type.", + "title": "Type", + "type": "string" + } + }, + "required": [ + "uri", + "type" + ], + "title": "VolumeSyncSourceAzureV1", + "type": "object" + }, + "VolumeSyncSourceBasetenTrainingV1": { + "additionalProperties": false, + "description": "Baseten training artifact source.", + "properties": { + "uri": { + "description": "Remote source URI to materialize into the destination volume.", + "title": "Uri", + "type": "string" }, - "environment_name": { + "include": { + "description": "Glob patterns selecting files to include.", + "items": { + "type": "string" + }, + "title": "Include", + "type": "array" + }, + "exclude": { + "description": "Glob patterns selecting files to exclude.", + "items": { + "type": "string" + }, + "title": "Exclude", + "type": "array" + }, + "type": { + "const": "BASETEN_TRAINING", + "description": "Baseten training artifact source type.", + "title": "Type", + "type": "string" + } + }, + "required": [ + "uri", + "type" + ], + "title": "VolumeSyncSourceBasetenTrainingV1", + "type": "object" + }, + "VolumeSyncSourceCoreWeaveV1": { + "additionalProperties": false, + "description": "CoreWeave object storage source.", + "properties": { + "uri": { + "description": "Remote source URI to materialize into the destination volume.", + "title": "Uri", + "type": "string" + }, + "include": { + "description": "Glob patterns selecting files to include.", + "items": { + "type": "string" + }, + "title": "Include", + "type": "array" + }, + "exclude": { + "description": "Glob patterns selecting files to exclude.", + "items": { + "type": "string" + }, + "title": "Exclude", + "type": "array" + }, + "auth_secret_name": { "anyOf": [ { + "minLength": 1, "type": "string" }, { @@ -10831,18 +11712,52 @@ } ], "default": null, - "description": "Stable environment to push to (e.g. `production`). If unset, the deployment is created without environment selection. Caller must have push permission for the named environment.", - "title": "Environment Name" + "description": "Optional workspace secret containing credentials for this source.", + "title": "Auth Secret Name" }, - "create_environment_if_missing": { - "default": true, - "description": "Create the environment named by `environment_name` if it does not exist yet. If false, a push to an environment that does not exist is rejected. Only meaningful when `environment_name` is set to something other than `production`, which always exists. This field currently defaults to true, but that default will change to false in a future release. Set it explicitly to avoid a behavior change.", - "title": "Create Environment If Missing", - "type": "boolean" + "type": { + "const": "COREWEAVE", + "description": "CoreWeave object storage source type.", + "title": "Type", + "type": "string" + } + }, + "required": [ + "uri", + "type" + ], + "title": "VolumeSyncSourceCoreWeaveV1", + "type": "object" + }, + "VolumeSyncSourceGCSV1": { + "additionalProperties": false, + "description": "Google Cloud Storage source.", + "properties": { + "uri": { + "description": "Remote source URI to materialize into the destination volume.", + "title": "Uri", + "type": "string" }, - "region": { + "include": { + "description": "Glob patterns selecting files to include.", + "items": { + "type": "string" + }, + "title": "Include", + "type": "array" + }, + "exclude": { + "description": "Glob patterns selecting files to exclude.", + "items": { + "type": "string" + }, + "title": "Exclude", + "type": "array" + }, + "auth_secret_name": { "anyOf": [ { + "minLength": 1, "type": "string" }, { @@ -10850,31 +11765,64 @@ } ], "default": null, - "description": "Region in which to deploy the model", - "title": "Region" + "description": "Optional workspace secret containing credentials for this source.", + "title": "Auth Secret Name" }, - "preserve_env_instance_type": { - "default": true, - "description": "Retain the target environment's current instance type rather than the one in `config`. Only meaningful when `environment_name` is set and that environment already exists.", - "title": "Preserve Env Instance Type", - "type": "boolean" + "type": { + "const": "GCS", + "description": "Google Cloud Storage source type.", + "title": "Type", + "type": "string" }, - "deploy_timeout_minutes": { + "gcp_oidc": { "anyOf": [ { - "type": "integer" + "$ref": "#/components/schemas/VolumeSyncAuthenticationGCPOIDCV1" }, { "type": "null" } ], "default": null, - "description": "Deploy timeout in minutes; allowed range 10 to 1440. Server default applies if unset.", - "title": "Deploy Timeout Minutes" + "description": "GCP OIDC authentication for this source. Cannot be combined with auth_secret_name." + } + }, + "required": [ + "uri", + "type" + ], + "title": "VolumeSyncSourceGCSV1", + "type": "object" + }, + "VolumeSyncSourceHuggingFaceV1": { + "additionalProperties": false, + "description": "Hugging Face source.", + "properties": { + "uri": { + "description": "Remote source URI to materialize into the destination volume.", + "title": "Uri", + "type": "string" }, - "deployment_name": { + "include": { + "description": "Glob patterns selecting files to include.", + "items": { + "type": "string" + }, + "title": "Include", + "type": "array" + }, + "exclude": { + "description": "Glob patterns selecting files to exclude.", + "items": { + "type": "string" + }, + "title": "Exclude", + "type": "array" + }, + "auth_secret_name": { "anyOf": [ { + "minLength": 1, "type": "string" }, { @@ -10882,46 +11830,105 @@ } ], "default": null, - "description": "Optional human-readable name for the deployment.", - "title": "Deployment Name" + "description": "Optional workspace secret containing credentials for this source.", + "title": "Auth Secret Name" }, - "labels": { - "anyOf": [ - { - "additionalProperties": true, - "type": "object" + "type": { + "const": "HUGGING_FACE", + "description": "Hugging Face source type.", + "title": "Type", + "type": "string" + } + }, + "required": [ + "uri", + "type" + ], + "title": "VolumeSyncSourceHuggingFaceV1", + "type": "object" + }, + "VolumeSyncSourceR2V1": { + "additionalProperties": false, + "description": "Cloudflare R2 source.", + "properties": { + "uri": { + "description": "Remote source URI to materialize into the destination volume.", + "title": "Uri", + "type": "string" + }, + "include": { + "description": "Glob patterns selecting files to include.", + "items": { + "type": "string" + }, + "title": "Include", + "type": "array" + }, + "exclude": { + "description": "Glob patterns selecting files to exclude.", + "items": { + "type": "string" + }, + "title": "Exclude", + "type": "array" + }, + "auth_secret_name": { + "anyOf": [ + { + "minLength": 1, + "type": "string" }, { "type": "null" } ], "default": null, - "description": "User-provided key-value labels for the deployment.", - "title": "Labels" + "description": "Optional workspace secret containing credentials for this source.", + "title": "Auth Secret Name" }, - "is_development": { - "default": false, - "description": "If true, push as a development deployment: the model's single mutable dev slot, created if absent and overwritten in place otherwise. The following fields must be left at their defaults: `environment_name`, `preserve_env_instance_type`, `deployment_name`.", - "title": "Is Development", - "type": "boolean" + "type": { + "const": "R2", + "description": "Cloudflare R2 source type.", + "title": "Type", + "type": "string" } }, "required": [ - "config" + "uri", + "type" ], - "title": "DeploymentArchivePayloadV1", + "title": "VolumeSyncSourceR2V1", "type": "object" }, - "PrepareModelUploadRequestV1": { - "description": "Body for `POST /v1/prepare_model_upload`.\n\nValidates the same payload the commit endpoint will validate, and on\n`dry_run=false` issues STS upload credentials. Exactly one of `name` or\n`model_id` is required: `name` validates the new-model path (`POST\n/v1/models`); `model_id` validates the add-deployment path (`POST\n/v1/models/{model_id}/deployments`).", + "VolumeSyncSourceS3V1": { + "additionalProperties": false, + "description": "Amazon S3 source.", "properties": { - "deployment": { - "$ref": "#/components/schemas/DeploymentArchivePayloadV1", - "description": "Deployment-level payload, identical to the payload sent at commit." + "uri": { + "description": "Remote source URI to materialize into the destination volume.", + "title": "Uri", + "type": "string" }, - "name": { + "include": { + "description": "Glob patterns selecting files to include.", + "items": { + "type": "string" + }, + "title": "Include", + "type": "array" + }, + "exclude": { + "description": "Glob patterns selecting files to exclude.", + "items": { + "type": "string" + }, + "title": "Exclude", + "type": "array" + }, + "auth_secret_name": { "anyOf": [ { + "minLength": 1, "type": "string" }, { @@ -10929,91 +11936,114 @@ } ], "default": null, - "description": "Set to validate a new-model push. Exactly one of `name` or `model_id` is required.", - "title": "Name" + "description": "Optional workspace secret containing credentials for this source.", + "title": "Auth Secret Name" }, - "team_id": { + "type": { + "const": "S3", + "description": "Amazon S3 source type.", + "title": "Type", + "type": "string" + }, + "aws_assume_role": { "anyOf": [ { - "type": "string" + "$ref": "#/components/schemas/VolumeSyncAuthenticationAWSAssumeRoleV1" }, { "type": "null" } ], "default": null, - "description": "Team the new model will belong to. Only valid when `name` is set; defaults to the organization's default team when omitted. Must not be set when `model_id` is set (the existing model already has a team).", - "title": "Team Id" + "description": "AWS AssumeRole authentication for this source. Cannot be combined with auth_secret_name." }, - "model_id": { + "aws_oidc": { "anyOf": [ { - "type": "string" + "$ref": "#/components/schemas/VolumeSyncAuthenticationAWSOIDCV1" }, { "type": "null" } ], "default": null, - "description": "Set to validate an add-deployment push to an existing model. Exactly one of `name` or `model_id` is required.", - "title": "Model Id" - }, - "dry_run": { - "default": false, - "description": "If true, validate the payload only and do not issue upload credentials. The response sets `creds`, `s3_bucket`, and `s3_key` to `null`.", - "title": "Dry Run", - "type": "boolean" + "description": "AWS OIDC authentication for this source. Cannot be combined with other authentication fields." } }, "required": [ - "deployment" + "uri", + "type" ], - "title": "PrepareModelUploadRequestV1", + "title": "VolumeSyncSourceS3V1", "type": "object" }, - "AWSCredentialsV1": { - "description": "AWS credentials", + "VolumeSyncStatusV1": { + "enum": [ + "PENDING", + "SYNCING", + "READY", + "FAILED", + "CANCELED" + ], + "title": "VolumeSyncStatusV1", + "type": "string" + }, + "VolumeSyncV1": { + "description": "Current state and result of a volume sync.", "properties": { - "aws_access_key_id": { - "description": "The AWS access key ID", - "title": "Aws Access Key Id", + "sync_id": { + "description": "Identifier of this sync operation.", + "title": "Sync Id", "type": "string" }, - "aws_secret_access_key": { - "description": "The AWS secret access key", - "title": "Aws Secret Access Key", - "type": "string" + "status": { + "$ref": "#/components/schemas/VolumeSyncStatusV1", + "description": "Current lifecycle state of the sync." }, - "aws_session_token": { - "description": "The AWS session token", - "title": "Aws Session Token", - "type": "string" - } - }, - "required": [ - "aws_access_key_id", - "aws_secret_access_key", - "aws_session_token" - ], - "title": "AWSCredentialsV1", - "type": "object" - }, - "PrepareModelUploadResponseV1": { - "description": "Response from `POST /v1/prepare_model_upload`.\n\nReturns STS upload credentials when the push requires an archive upload. All\nfour fields (`creds`, `s3_bucket`, `s3_key`, `s3_region`) are `null` when no\nupload is needed: either `dry_run=true` (validation only) or a model format\nthat is not built from an uploaded archive (for example, BIS-LLM, which is\nbuilt from its config alone).", - "properties": { - "creds": { - "anyOf": [ + "source": { + "description": "Remote source being synced.", + "discriminator": { + "mapping": { + "AZURE": "#/components/schemas/VolumeSyncSourceAzureV1", + "BASETEN_TRAINING": "#/components/schemas/VolumeSyncSourceBasetenTrainingV1", + "COREWEAVE": "#/components/schemas/VolumeSyncSourceCoreWeaveV1", + "GCS": "#/components/schemas/VolumeSyncSourceGCSV1", + "HUGGING_FACE": "#/components/schemas/VolumeSyncSourceHuggingFaceV1", + "R2": "#/components/schemas/VolumeSyncSourceR2V1", + "S3": "#/components/schemas/VolumeSyncSourceS3V1" + }, + "propertyName": "type" + }, + "oneOf": [ { - "$ref": "#/components/schemas/AWSCredentialsV1" + "$ref": "#/components/schemas/VolumeSyncSourceHuggingFaceV1" }, { - "type": "null" + "$ref": "#/components/schemas/VolumeSyncSourceS3V1" + }, + { + "$ref": "#/components/schemas/VolumeSyncSourceGCSV1" + }, + { + "$ref": "#/components/schemas/VolumeSyncSourceAzureV1" + }, + { + "$ref": "#/components/schemas/VolumeSyncSourceR2V1" + }, + { + "$ref": "#/components/schemas/VolumeSyncSourceCoreWeaveV1" + }, + { + "$ref": "#/components/schemas/VolumeSyncSourceBasetenTrainingV1" } ], - "default": null, - "description": "STS credentials to upload the model archive. Null when no archive upload is required." + "title": "Source" }, - "s3_bucket": { + "destination": { + "$ref": "#/components/schemas/VolumeSyncDestinationV1", + "description": "BDN volume being populated." + }, + "volume_version_id": { "anyOf": [ { "type": "string" @@ -11023,10 +12053,10 @@ } ], "default": null, - "description": "S3 bucket the credentials are scoped to. Null when no archive upload is required.", - "title": "S3 Bucket" + "description": "Produced artifact identifier; null until the sync is ready.", + "title": "Volume Version Id" }, - "s3_key": { + "version_ref": { "anyOf": [ { "type": "string" @@ -11036,10 +12066,10 @@ } ], "default": null, - "description": "S3 key the credentials are scoped to. Pass this to `POST /v1/models` (in the `model_archive` source) once the upload completes. Null when no archive upload is required.", - "title": "S3 Key" + "description": "Immutable BDN reference; null until the sync is ready.", + "title": "Version Ref" }, - "s3_region": { + "content_digest": { "anyOf": [ { "type": "string" @@ -11049,48 +12079,32 @@ } ], "default": null, - "description": "AWS region the S3 bucket resides in. Null when no archive upload is required.", - "title": "S3 Region" - } - }, - "title": "PrepareModelUploadResponseV1", - "type": "object" - }, - "AuditLogActorTypeV1": { - "description": "Kind of actor that performed an audited action.", - "enum": [ - "USER", - "API_KEY", - "BASETEN_USER", - "BASETEN_SYSTEM", - "TOMBSTONE_USER" - ], - "title": "AuditLogActorTypeV1", - "type": "string" - }, - "AuditLogActorV1": { - "description": "The actor that performed an audited action.", - "properties": { - "type": { - "$ref": "#/components/schemas/AuditLogActorTypeV1", - "description": "Kind of actor that performed the action." + "description": "BLAKE3 digest of the synced content; null until available.", + "title": "Content Digest" }, - "email": { + "total_size_bytes": { "anyOf": [ { - "type": "string" + "type": "integer" }, { "type": "null" } ], "default": null, - "description": "Email of the acting user, when the actor is a user.", - "title": "Email" + "description": "Total size of the synced content in bytes; null until available.", + "title": "Total Size Bytes" }, - "api_key_prefix": { + "created_at": { + "description": "Time at which the sync was created.", + "format": "date-time", + "title": "Created At", + "type": "string" + }, + "completed_at": { "anyOf": [ { + "format": "date-time", "type": "string" }, { @@ -11098,451 +12112,490 @@ } ], "default": null, - "description": "Prefix of the acting API key, when the actor is an API key.", - "title": "Api Key Prefix" + "description": "Time at which the sync reached a terminal state.", + "title": "Completed At" }, - "api_key_name": { + "error": { "anyOf": [ { - "type": "string" + "$ref": "#/components/schemas/VolumeSyncErrorV1" }, { "type": "null" } ], "default": null, - "description": "Display name of the acting API key, when the actor is an API key.", - "title": "Api Key Name" + "description": "Redacted failure details; null unless the sync failed." } }, "required": [ - "type" + "sync_id", + "status", + "source", + "destination", + "created_at" ], - "title": "AuditLogActorV1", + "title": "VolumeSyncV1", "type": "object" }, - "AuditLogApiKeyTypeV1": { - "description": "Type of API key recorded on an API-key event.", - "enum": [ - "PERSONAL", - "CREATOR_SERVICE_ACCOUNT", - "MANAGE_API_KEYS_SERVICE_ACCOUNT", - "INVOKE_ALL_MODELS_SERVICE_ACCOUNT", - "INVOKE_ALLOWED_MODELS_SERVICE_ACCOUNT", - "INVOKE_SCOPED_ENVS_AND_MODELS_SERVICE_ACCOUNT", - "EXPORT_METRICS_ALL_MODELS_SERVICE_ACCOUNT", - "EXPORT_METRICS_ALLOWED_MODELS_SERVICE_ACCOUNT", - "INVOKE_ALL_SHARED_ENDPOINTS_SERVICE_ACCOUNT", - "INVOKE_ALLOWED_SHARED_ENDPOINTS_SERVICE_ACCOUNT", - "INVOKE_ALL_ROUTES" + "VolumeSyncsV1": { + "description": "A page of volume syncs in the active workspace.", + "properties": { + "items": { + "description": "Items in this page.", + "items": { + "$ref": "#/components/schemas/VolumeSyncV1" + }, + "title": "Items", + "type": "array" + }, + "pagination": { + "$ref": "#/components/schemas/PaginationResponseV1", + "description": "Pagination metadata for the page." + } + }, + "required": [ + "items", + "pagination" ], - "title": "AuditLogApiKeyTypeV1", - "type": "string" + "title": "VolumeSyncsV1", + "type": "object" }, - "AuditLogEntryV1": { - "description": "A single audit-log entry.", + "VolumeSyncsRequestV1": { + "description": "Filters and pagination for listing volume syncs in the active workspace.", "properties": { - "id": { - "description": "Unique identifier of the audit-log entry.", - "title": "Id", - "type": "string" + "cursor": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Opaque cursor returned by a previous page. Omit to fetch the first page.", + "title": "Cursor" }, - "created": { - "description": "Time the action occurred, in ISO 8601 format.", - "format": "date-time", - "title": "Created", - "type": "string" - }, - "event_type": { - "$ref": "#/components/schemas/AuditLogEventTypeV1", - "description": "Type of action that was recorded." + "limit": { + "default": 100, + "description": "Maximum number of items to return.", + "maximum": 1000, + "minimum": 1, + "title": "Limit", + "type": "integer" }, - "event_data": { - "description": "Structured details of the action, discriminated by `event_type`.", + "ref": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Exact destination reference to match.", + "title": "Ref" + } + }, + "title": "VolumeSyncsRequestV1", + "type": "object" + }, + "CreateVolumeSyncRequestV1": { + "additionalProperties": false, + "description": "Request to start an asynchronous volume sync.", + "properties": { + "source": { + "description": "Remote source to sync from.", "discriminator": { "mapping": { - "API_KEY_CREATED": "#/components/schemas/AuditLogEventApiKeyCreatedV1", - "API_KEY_DELETED": "#/components/schemas/AuditLogEventApiKeyDeletedV1", - "CHAINLET_AUTOSCALING_SETTINGS_CHANGED": "#/components/schemas/AuditLogEventChainletAutoscalingSettingsChangedV1", - "CHAINLET_INSTANCE_TYPE_CHANGED": "#/components/schemas/AuditLogEventChainletInstanceTypeChangedV1", - "CHAIN_DELETED": "#/components/schemas/AuditLogEventChainDeletedV1", - "CHAIN_DEPLOYED": "#/components/schemas/AuditLogEventChainDeployedV1", - "CHAIN_DEPLOYMENT_ACTIVATED": "#/components/schemas/AuditLogEventChainDeploymentActivatedV1", - "CHAIN_DEPLOYMENT_DEACTIVATED": "#/components/schemas/AuditLogEventChainDeploymentDeactivatedV1", - "CHAIN_DEPLOYMENT_DELETED": "#/components/schemas/AuditLogEventChainDeploymentDeletedV1", - "CHAIN_DEPLOYMENT_PROMOTED": "#/components/schemas/AuditLogEventChainDeploymentPromotedV1", - "CHAIN_ENVIRONMENT_CREATED": "#/components/schemas/AuditLogEventChainEnvironmentCreatedV1", - "CHAIN_ENVIRONMENT_UPDATED": "#/components/schemas/AuditLogEventChainEnvironmentUpdatedV1", - "DIRECTORY_GROUP_ROLE_UPDATED": "#/components/schemas/AuditLogEventDirectoryGroupRoleUpdatedV1", - "ENVIRONMENT_CREATED": "#/components/schemas/AuditLogEventEnvironmentCreatedV1", - "ENVIRONMENT_DELETED": "#/components/schemas/AuditLogEventEnvironmentDeletedV1", - "ENVIRONMENT_UPDATED": "#/components/schemas/AuditLogEventEnvironmentUpdatedV1", - "GATEWAY_ENDPOINT_CREATED": "#/components/schemas/AuditLogEventGatewayEndpointCreatedV1", - "GATEWAY_ENDPOINT_DELETED": "#/components/schemas/AuditLogEventGatewayEndpointDeletedV1", - "GATEWAY_ENDPOINT_UPDATED": "#/components/schemas/AuditLogEventGatewayEndpointUpdatedV1", - "MODEL_DELETED": "#/components/schemas/AuditLogEventModelDeletedV1", - "MODEL_DEPLOYED": "#/components/schemas/AuditLogEventModelDeployedV1", - "MODEL_DEPLOYMENT_ACTIVATED": "#/components/schemas/AuditLogEventModelDeploymentActivatedV1", - "MODEL_DEPLOYMENT_AUTOSCALING_SETTINGS_CHANGED": "#/components/schemas/AuditLogEventModelDeploymentAutoscalingSettingsChangedV1", - "MODEL_DEPLOYMENT_DEACTIVATED": "#/components/schemas/AuditLogEventModelDeploymentDeactivatedV1", - "MODEL_DEPLOYMENT_DELETED": "#/components/schemas/AuditLogEventModelDeploymentDeletedV1", - "MODEL_DEPLOYMENT_INSTANCE_TYPE_CHANGED": "#/components/schemas/AuditLogEventModelDeploymentInstanceTypeChangedV1", - "MODEL_DEPLOYMENT_PROMOTED": "#/components/schemas/AuditLogEventModelDeploymentPromotedV1", - "MODEL_DEPLOYMENT_REQUEST_BACKPRESSURE_SETTINGS_CHANGED": "#/components/schemas/AuditLogEventModelDeploymentRequestBackpressureSettingsChangedV1", - "MODEL_DEPLOYMENT_RETRIED": "#/components/schemas/AuditLogEventModelDeploymentRetriedV1", - "MODEL_PROMOTION_CONTROL_ACTION": "#/components/schemas/AuditLogEventModelPromotionControlActionV1", - "REPLICA_TERMINATED": "#/components/schemas/AuditLogEventReplicaTerminatedV1", - "REQUIRE_GROUP_BASED_ADMINS_ENABLED": "#/components/schemas/AuditLogEventRequireGroupBasedAdminsEnabledV1", - "SECRET_DELETED": "#/components/schemas/AuditLogEventSecretDeletedV1", - "SECRET_UPDATED": "#/components/schemas/AuditLogEventSecretUpdatedV1", - "SSH_CERTIFICATE_SIGNED": "#/components/schemas/AuditLogEventSshCertificateSignedV1", - "USER_INVITED": "#/components/schemas/AuditLogEventUserInvitedV1", - "USER_JOINED_ORGANIZATION": "#/components/schemas/AuditLogEventUserJoinedOrganizationV1", - "USER_REMOVED": "#/components/schemas/AuditLogEventUserRemovedV1", - "USER_ROLE_UPDATED": "#/components/schemas/AuditLogEventUserRoleUpdatedV1", - "USER_TEAM_ROLE_UPDATED": "#/components/schemas/AuditLogEventUserTeamRoleUpdatedV1", - "VOLUME_DELETED": "#/components/schemas/AuditLogEventVolumeDeletedV1", - "VOLUME_VERSION_DELETED": "#/components/schemas/AuditLogEventVolumeVersionDeletedV1", - "VOLUME_VERSION_RESTORED": "#/components/schemas/AuditLogEventVolumeVersionRestoredV1", - "WEBHOOK_SIGNING_SECRET_CREATED": "#/components/schemas/AuditLogEventWebhookSigningSecretCreatedV1", - "WEBHOOK_SIGNING_SECRET_DELETED": "#/components/schemas/AuditLogEventWebhookSigningSecretDeletedV1", - "WEBHOOK_SIGNING_SECRET_ROTATED": "#/components/schemas/AuditLogEventWebhookSigningSecretRotatedV1" - }, - "propertyName": "event_type" + "AZURE": "#/components/schemas/VolumeSyncSourceAzureV1", + "BASETEN_TRAINING": "#/components/schemas/VolumeSyncSourceBasetenTrainingV1", + "COREWEAVE": "#/components/schemas/VolumeSyncSourceCoreWeaveV1", + "GCS": "#/components/schemas/VolumeSyncSourceGCSV1", + "HUGGING_FACE": "#/components/schemas/VolumeSyncSourceHuggingFaceV1", + "R2": "#/components/schemas/VolumeSyncSourceR2V1", + "S3": "#/components/schemas/VolumeSyncSourceS3V1" + }, + "propertyName": "type" }, "oneOf": [ { - "$ref": "#/components/schemas/AuditLogEventModelDeployedV1" - }, - { - "$ref": "#/components/schemas/AuditLogEventModelDeploymentActivatedV1" - }, - { - "$ref": "#/components/schemas/AuditLogEventModelDeploymentDeactivatedV1" + "$ref": "#/components/schemas/VolumeSyncSourceHuggingFaceV1" }, { - "$ref": "#/components/schemas/AuditLogEventModelDeploymentRetriedV1" + "$ref": "#/components/schemas/VolumeSyncSourceS3V1" }, { - "$ref": "#/components/schemas/AuditLogEventModelDeploymentPromotedV1" + "$ref": "#/components/schemas/VolumeSyncSourceGCSV1" }, { - "$ref": "#/components/schemas/AuditLogEventModelDeploymentAutoscalingSettingsChangedV1" + "$ref": "#/components/schemas/VolumeSyncSourceAzureV1" }, { - "$ref": "#/components/schemas/AuditLogEventModelDeploymentRequestBackpressureSettingsChangedV1" + "$ref": "#/components/schemas/VolumeSyncSourceR2V1" }, { - "$ref": "#/components/schemas/AuditLogEventModelDeploymentInstanceTypeChangedV1" + "$ref": "#/components/schemas/VolumeSyncSourceCoreWeaveV1" }, { - "$ref": "#/components/schemas/AuditLogEventModelDeploymentDeletedV1" - }, + "$ref": "#/components/schemas/VolumeSyncSourceBasetenTrainingV1" + } + ], + "title": "Source" + }, + "destination": { + "$ref": "#/components/schemas/VolumeSyncDestinationV1", + "description": "BDN volume to sync into." + } + }, + "required": [ + "source", + "destination" + ], + "title": "CreateVolumeSyncRequestV1", + "type": "object" + }, + "DeleteVolumeRequestV1": { + "properties": { + "expected_sequence": { + "anyOf": [ { - "$ref": "#/components/schemas/AuditLogEventModelDeletedV1" + "type": "integer" }, { - "$ref": "#/components/schemas/AuditLogEventChainDeployedV1" - }, + "type": "null" + } + ], + "default": null, + "description": "Revision the volume is expected to be at. When set, the delete fails with a conflict if the volume has changed since, so it cannot act on a volume someone else has pushed to. Take the value from a volume's sequence, or from volume_sequence.", + "title": "Expected Sequence" + } + }, + "title": "DeleteVolumeRequestV1", + "type": "object" + }, + "DeleteVolumeResponseV1": { + "properties": { + "namespace": { + "description": "Namespace the volume belongs to, in lowercase.", + "title": "Namespace", + "type": "string" + }, + "name": { + "description": "Name of the volume, in lowercase.", + "title": "Name", + "type": "string" + }, + "versions_deleted": { + "description": "Number of versions this request deleted. Zero when the volume had no live versions left, which is not an error.", + "title": "Versions Deleted", + "type": "integer" + }, + "volume_sequence": { + "description": "Revision of the volume after the delete.", + "title": "Volume Sequence", + "type": "integer" + } + }, + "required": [ + "namespace", + "name", + "versions_deleted", + "volume_sequence" + ], + "title": "DeleteVolumeResponseV1", + "type": "object" + }, + "VolumeVersionV1": { + "properties": { + "namespace": { + "description": "Namespace the volume belongs to, in lowercase.", + "title": "Namespace", + "type": "string" + }, + "volume": { + "description": "Name of the volume, in lowercase.", + "title": "Volume", + "type": "string" + }, + "version_ref": { + "description": "Full address of this version, as `bdn:/@`. Paste this into the `bdn.mounts` section of a config.yaml to pin to it.", + "title": "Version Ref", + "type": "string" + }, + "digest": { + "description": "Content digest of the version, as `b3:`.", + "title": "Digest", + "type": "string" + }, + "sequence": { + "anyOf": [ { - "$ref": "#/components/schemas/AuditLogEventChainDeploymentActivatedV1" + "type": "integer" }, { - "$ref": "#/components/schemas/AuditLogEventChainDeploymentDeactivatedV1" - }, + "type": "null" + } + ], + "description": "Revision the version was committed at. Null for versions committed before the volume service recorded it.", + "title": "Sequence" + }, + "lifecycle": { + "description": "Lifecycle state of the version: ALIVE, or TOMBSTONED once it has been deleted or has expired.", + "title": "Lifecycle", + "type": "string" + }, + "is_head": { + "description": "Whether the reserved `head` tag points at this version.", + "title": "Is Head", + "type": "boolean" + }, + "tags": { + "description": "Tags pointing at this version that your API key can read.", + "items": { + "type": "string" + }, + "title": "Tags", + "type": "array" + }, + "total_size_bytes": { + "anyOf": [ { - "$ref": "#/components/schemas/AuditLogEventChainDeploymentPromotedV1" + "type": "integer" }, { - "$ref": "#/components/schemas/AuditLogEventChainletAutoscalingSettingsChangedV1" - }, + "type": "null" + } + ], + "description": "Total size of the version's files in bytes. Null when not recorded.", + "title": "Total Size Bytes" + }, + "created_at": { + "description": "When the version was committed, in ISO 8601 format.", + "format": "date-time", + "title": "Created At", + "type": "string" + }, + "expires_at": { + "anyOf": [ { - "$ref": "#/components/schemas/AuditLogEventChainletInstanceTypeChangedV1" + "format": "date-time", + "type": "string" }, { - "$ref": "#/components/schemas/AuditLogEventChainDeploymentDeletedV1" - }, + "type": "null" + } + ], + "description": "When the version expires, in ISO 8601 format. At that instant it becomes TOMBSTONED with `tombstoned_at` set to this value, and every tag pointing at it drops. Null for a version that never expires, and null once the lifecycle is TOMBSTONED.", + "title": "Expires At" + }, + "tombstoned_at": { + "anyOf": [ { - "$ref": "#/components/schemas/AuditLogEventChainDeletedV1" + "format": "date-time", + "type": "string" }, { - "$ref": "#/components/schemas/AuditLogEventChainEnvironmentCreatedV1" - }, + "type": "null" + } + ], + "description": "When the version was deleted or expired, in ISO 8601 format. Null unless the lifecycle is TOMBSTONED.", + "title": "Tombstoned At" + }, + "delete_after": { + "anyOf": [ { - "$ref": "#/components/schemas/AuditLogEventChainEnvironmentUpdatedV1" - }, - { - "$ref": "#/components/schemas/AuditLogEventSecretUpdatedV1" - }, - { - "$ref": "#/components/schemas/AuditLogEventSecretDeletedV1" - }, - { - "$ref": "#/components/schemas/AuditLogEventApiKeyCreatedV1" - }, - { - "$ref": "#/components/schemas/AuditLogEventApiKeyDeletedV1" - }, - { - "$ref": "#/components/schemas/AuditLogEventGatewayEndpointCreatedV1" - }, - { - "$ref": "#/components/schemas/AuditLogEventGatewayEndpointUpdatedV1" - }, - { - "$ref": "#/components/schemas/AuditLogEventGatewayEndpointDeletedV1" - }, - { - "$ref": "#/components/schemas/AuditLogEventUserInvitedV1" - }, - { - "$ref": "#/components/schemas/AuditLogEventUserJoinedOrganizationV1" - }, - { - "$ref": "#/components/schemas/AuditLogEventWebhookSigningSecretCreatedV1" - }, - { - "$ref": "#/components/schemas/AuditLogEventWebhookSigningSecretRotatedV1" - }, - { - "$ref": "#/components/schemas/AuditLogEventWebhookSigningSecretDeletedV1" - }, - { - "$ref": "#/components/schemas/AuditLogEventUserRoleUpdatedV1" - }, - { - "$ref": "#/components/schemas/AuditLogEventUserTeamRoleUpdatedV1" - }, - { - "$ref": "#/components/schemas/AuditLogEventUserRemovedV1" - }, - { - "$ref": "#/components/schemas/AuditLogEventDirectoryGroupRoleUpdatedV1" - }, - { - "$ref": "#/components/schemas/AuditLogEventRequireGroupBasedAdminsEnabledV1" - }, - { - "$ref": "#/components/schemas/AuditLogEventEnvironmentCreatedV1" - }, - { - "$ref": "#/components/schemas/AuditLogEventEnvironmentUpdatedV1" - }, - { - "$ref": "#/components/schemas/AuditLogEventEnvironmentDeletedV1" - }, - { - "$ref": "#/components/schemas/AuditLogEventReplicaTerminatedV1" - }, - { - "$ref": "#/components/schemas/AuditLogEventModelPromotionControlActionV1" - }, - { - "$ref": "#/components/schemas/AuditLogEventSshCertificateSignedV1" - }, - { - "$ref": "#/components/schemas/AuditLogEventVolumeDeletedV1" - }, - { - "$ref": "#/components/schemas/AuditLogEventVolumeVersionDeletedV1" - }, - { - "$ref": "#/components/schemas/AuditLogEventVolumeVersionRestoredV1" - } - ], - "title": "Event Data" - }, - "source": { - "anyOf": [ - { - "$ref": "#/components/schemas/AuditLogSourceV1" - }, - { - "type": "null" - } - ], - "default": null, - "description": "Surface that issued the action, if known." - }, - "actor": { - "$ref": "#/components/schemas/AuditLogActorV1", - "description": "The actor that performed the action." - }, - "client_name": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "description": "Name of the client that issued the action, if known.", - "title": "Client Name" - }, - "client_version": { - "anyOf": [ - { - "type": "string" + "format": "date-time", + "type": "string" }, { "type": "null" } ], - "default": null, - "description": "Version of the client that issued the action, if known.", - "title": "Client Version" + "description": "When the version stops being restorable, in ISO 8601 format. Null unless the lifecycle is TOMBSTONED.", + "title": "Delete After" + } + }, + "required": [ + "namespace", + "volume", + "version_ref", + "digest", + "sequence", + "lifecycle", + "is_head", + "tags", + "total_size_bytes", + "created_at", + "expires_at", + "tombstoned_at", + "delete_after" + ], + "title": "VolumeVersionV1", + "type": "object" + }, + "ListVolumeVersionsResponseV1": { + "description": "Every version of a volume, newest first.\n\nUnpaginated: `limit` and `cursor` are absent rather than accepted and\nignored, so adding them once the volume service pages this listing is a\npurely additive change.", + "properties": { + "versions": { + "description": "Versions of the volume, newest first.", + "items": { + "$ref": "#/components/schemas/VolumeVersionV1" + }, + "title": "Versions", + "type": "array" }, - "client_session_id": { + "volume_sequence": { + "description": "Revision of the volume as a whole when the versions were read. Pass it as expected_sequence on a later delete to make that delete conditional on the volume not having changed since. Distinct from the per-version sequence, which is the revision a version was committed at.", + "title": "Volume Sequence", + "type": "integer" + } + }, + "required": [ + "versions", + "volume_sequence" + ], + "title": "ListVolumeVersionsResponseV1", + "type": "object" + }, + "ListVolumeVersionsRequestV1": { + "properties": { + "include_tombstoned": { + "default": false, + "description": "Whether to include deleted and expired versions. Such a version carries a TOMBSTONED lifecycle and stays restorable until its recovery deadline passes.", + "title": "Include Tombstoned", + "type": "boolean" + } + }, + "title": "ListVolumeVersionsRequestV1", + "type": "object" + }, + "DeleteVolumeVersionRequestV1": { + "properties": { + "expected_sequence": { "anyOf": [ { - "type": "string" + "type": "integer" }, { "type": "null" } ], "default": null, - "description": "Opaque identifier grouping actions from the same client session, if known.", - "title": "Client Session Id" + "description": "Revision the volume is expected to be at. When set, the delete fails with a conflict if the volume has changed since, so a read followed by a delete cannot act on a version a tag has since been moved off. Take the value from volume_sequence.", + "title": "Expected Sequence" } }, - "required": [ - "id", - "created", - "event_type", - "event_data", - "actor" - ], - "title": "AuditLogEntryV1", + "title": "DeleteVolumeVersionRequestV1", "type": "object" }, - "AuditLogEventApiKeyCreatedV1": { - "additionalProperties": false, - "description": "An API key was created.", + "DeleteVolumeVersionResponseV1": { "properties": { - "event_type": { - "const": "API_KEY_CREATED", - "title": "Event Type", + "namespace": { + "description": "Namespace the volume belongs to, in lowercase.", + "title": "Namespace", "type": "string" }, - "api_key_id": { - "title": "Api Key Id", + "volume": { + "description": "Name of the volume, in lowercase.", + "title": "Volume", "type": "string" }, - "api_key_type": { - "$ref": "#/components/schemas/AuditLogApiKeyTypeV1" + "version_ref": { + "description": "Full address of the deleted version, as `bdn:/@`.", + "title": "Version Ref", + "type": "string" }, - "prefix": { - "title": "Prefix", + "digest": { + "description": "Content digest of the deleted version, as `b3:`.", + "title": "Digest", + "type": "string" + }, + "lifecycle": { + "description": "Lifecycle state of the version after the delete.", + "title": "Lifecycle", "type": "string" + }, + "delete_after": { + "description": "When the version stops being restorable, in ISO 8601 format. Until then it can be returned to service.", + "format": "date-time", + "title": "Delete After", + "type": "string" + }, + "volume_sequence": { + "description": "Revision of the volume after the delete.", + "title": "Volume Sequence", + "type": "integer" } }, "required": [ - "event_type", - "api_key_id", - "api_key_type", - "prefix" + "namespace", + "volume", + "version_ref", + "digest", + "lifecycle", + "delete_after", + "volume_sequence" ], - "title": "AuditLogEventApiKeyCreatedV1", + "title": "DeleteVolumeVersionResponseV1", "type": "object" }, - "AuditLogEventApiKeyDeletedV1": { - "additionalProperties": false, - "description": "An API key was revoked.", + "VolumeVersionDetailV1": { + "description": "One version, with the fields only a single-version read reports.", "properties": { - "event_type": { - "const": "API_KEY_DELETED", - "title": "Event Type", + "namespace": { + "description": "Namespace the volume belongs to, in lowercase.", + "title": "Namespace", "type": "string" }, - "api_key_id": { - "title": "Api Key Id", + "volume": { + "description": "Name of the volume, in lowercase.", + "title": "Volume", "type": "string" }, - "api_key_type": { - "$ref": "#/components/schemas/AuditLogApiKeyTypeV1" - }, - "prefix": { - "title": "Prefix", + "version_ref": { + "description": "Full address of this version, as `bdn:/@`. Paste this into the `bdn.mounts` section of a config.yaml to pin to it.", + "title": "Version Ref", "type": "string" - } - }, - "required": [ - "event_type", - "api_key_id", - "api_key_type", - "prefix" - ], - "title": "AuditLogEventApiKeyDeletedV1", - "type": "object" - }, - "AuditLogEventAutoscalingScheduleActionV1": { - "description": "What an autoscaling change did to one schedule.", - "enum": [ - "CREATED", - "UPDATED", - "DELETED", - "UNCHANGED" - ], - "title": "AuditLogEventAutoscalingScheduleActionV1", - "type": "string" - }, - "AuditLogEventAutoscalingScheduleChangeV1": { - "additionalProperties": false, - "description": "What an autoscaling change did to one schedule, and the schedule on either side of it.\n`previous` is null on a create, `current` on a delete, and an unchanged schedule carries only\n`current`. Not itself a payload in the discriminated union.", - "properties": { - "action": { - "$ref": "#/components/schemas/AuditLogEventAutoscalingScheduleActionV1" }, - "schedule_id": { - "title": "Schedule Id", + "digest": { + "description": "Content digest of the version, as `b3:`.", + "title": "Digest", "type": "string" }, - "previous": { + "sequence": { "anyOf": [ { - "$ref": "#/components/schemas/AuditLogEventAutoscalingScheduleSettingsV1" + "type": "integer" }, { "type": "null" } - ] + ], + "description": "Revision the version was committed at. Null for versions committed before the volume service recorded it.", + "title": "Sequence" }, - "current": { - "anyOf": [ - { - "$ref": "#/components/schemas/AuditLogEventAutoscalingScheduleSettingsV1" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "action", - "schedule_id", - "previous", - "current" - ], - "title": "AuditLogEventAutoscalingScheduleChangeV1", - "type": "object" - }, - "AuditLogEventAutoscalingScheduleSettingsV1": { - "additionalProperties": false, - "description": "One autoscaling schedule's timing and autoscaling settings. Not itself a union payload.", - "properties": { - "min_replica": { - "title": "Min Replica", - "type": "integer" + "lifecycle": { + "description": "Lifecycle state of the version: ALIVE, or TOMBSTONED once it has been deleted or has expired.", + "title": "Lifecycle", + "type": "string" }, - "max_replica": { - "title": "Max Replica", - "type": "integer" + "is_head": { + "description": "Whether the reserved `head` tag points at this version.", + "title": "Is Head", + "type": "boolean" }, - "concurrency_target": { + "tags": { + "description": "Tags pointing at this version that your API key can read.", + "items": { + "type": "string" + }, + "title": "Tags", + "type": "array" + }, + "total_size_bytes": { "anyOf": [ { "type": "integer" @@ -11551,42 +12604,55 @@ "type": "null" } ], - "title": "Concurrency Target" + "description": "Total size of the version's files in bytes. Null when not recorded.", + "title": "Total Size Bytes" }, - "autoscaling_window": { + "created_at": { + "description": "When the version was committed, in ISO 8601 format.", + "format": "date-time", + "title": "Created At", + "type": "string" + }, + "expires_at": { "anyOf": [ { - "type": "integer" + "format": "date-time", + "type": "string" }, { "type": "null" } ], - "title": "Autoscaling Window" + "description": "When the version expires, in ISO 8601 format. At that instant it becomes TOMBSTONED with `tombstoned_at` set to this value, and every tag pointing at it drops. Null for a version that never expires, and null once the lifecycle is TOMBSTONED.", + "title": "Expires At" }, - "scale_down_delay": { + "tombstoned_at": { "anyOf": [ { - "type": "integer" + "format": "date-time", + "type": "string" }, { "type": "null" } ], - "title": "Scale Down Delay" + "description": "When the version was deleted or expired, in ISO 8601 format. Null unless the lifecycle is TOMBSTONED.", + "title": "Tombstoned At" }, - "target_utilization_percentage": { + "delete_after": { "anyOf": [ { - "type": "integer" + "format": "date-time", + "type": "string" }, { "type": "null" } ], - "title": "Target Utilization Percentage" + "description": "When the version stops being restorable, in ISO 8601 format. Null unless the lifecycle is TOMBSTONED.", + "title": "Delete After" }, - "target_in_flight_tokens": { + "entry_count": { "anyOf": [ { "type": "integer" @@ -11595,94 +12661,278 @@ "type": "null" } ], - "title": "Target In Flight Tokens" + "description": "Number of files in the version. Null when not recorded.", + "title": "Entry Count" }, - "max_scale_down_rate": { + "volume_sequence": { + "description": "Revision of the volume as a whole when this version was read. Pass it as expected_sequence on a later delete to make that delete conditional on the volume not having changed since.", + "title": "Volume Sequence", + "type": "integer" + } + }, + "required": [ + "namespace", + "volume", + "version_ref", + "digest", + "sequence", + "lifecycle", + "is_head", + "tags", + "total_size_bytes", + "created_at", + "expires_at", + "tombstoned_at", + "delete_after", + "entry_count", + "volume_sequence" + ], + "title": "VolumeVersionDetailV1", + "type": "object" + }, + "RestoreVolumeVersionRequestV1": { + "properties": { + "expected_sequence": { "anyOf": [ { - "type": "number" + "type": "integer" }, { "type": "null" } ], - "title": "Max Scale Down Rate" + "default": null, + "description": "Revision the volume is expected to be at. When set, the restore fails with a conflict if the volume has changed since. Take the value from volume_sequence.", + "title": "Expected Sequence" + } + }, + "title": "RestoreVolumeVersionRequestV1", + "type": "object" + }, + "RestoreVolumeVersionResponseV1": { + "properties": { + "namespace": { + "description": "Namespace the volume belongs to, in lowercase.", + "title": "Namespace", + "type": "string" }, - "schedule_name": { - "title": "Schedule Name", + "volume": { + "description": "Name of the volume, in lowercase.", + "title": "Volume", "type": "string" }, - "enabled": { - "title": "Enabled", - "type": "boolean" + "version_ref": { + "description": "Full address of the restored version, as `bdn:/@`.", + "title": "Version Ref", + "type": "string" }, - "cadence": { - "title": "Cadence", + "digest": { + "description": "Content digest of the restored version, as `b3:`.", + "title": "Digest", "type": "string" }, - "timezone": { - "title": "Timezone", + "lifecycle": { + "description": "Lifecycle state of the version after the restore.", + "title": "Lifecycle", "type": "string" }, - "weekdays": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } + "volume_sequence": { + "description": "Revision of the volume after the restore.", + "title": "Volume Sequence", + "type": "integer" + } + }, + "required": [ + "namespace", + "volume", + "version_ref", + "digest", + "lifecycle", + "volume_sequence" + ], + "title": "RestoreVolumeVersionResponseV1", + "type": "object" + }, + "TokenScopeV1": { + "description": "What a token minted by POST /v1/token grants access to.", + "enum": [ + "sandboxes" + ], + "title": "TokenScopeV1", + "type": "string" + }, + "CreateTokenRequestV1": { + "properties": { + "scopes": { + "description": "What the token should grant access to. Only `sandboxes` is supported today; the token then authenticates against the sandbox API.", + "examples": [ + [ + "sandboxes" + ] ], - "title": "Weekdays" - }, - "start_hour": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "title": "Start Hour" + "items": { + "$ref": "#/components/schemas/TokenScopeV1" + }, + "minItems": 1, + "title": "Scopes", + "type": "array" + } + }, + "required": [ + "scopes" + ], + "title": "CreateTokenRequestV1", + "type": "object" + }, + "TokenV1": { + "properties": { + "token": { + "description": "Short-lived bearer token for the sandbox API. Send it as Authorization: Bearer .", + "title": "Token", + "type": "string" }, - "start_minute": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } + "expires_at": { + "description": "Token expiry in ISO 8601 format. Tokens cannot be renewed; request a new one.", + "format": "date-time", + "title": "Expires At", + "type": "string" + } + }, + "required": [ + "token", + "expires_at" + ], + "title": "TokenV1", + "type": "object" + }, + "SecretV1": { + "description": "A Baseten secret. Note that we do not support retrieving secret values.", + "properties": { + "id": { + "description": "Stable identifier for the secret. Unchanged across rotation.", + "examples": [ + "3kZ9xqd" ], - "title": "Start Minute" + "title": "Id", + "type": "string" }, - "end_hour": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } + "created_at": { + "description": "Time the secret was created in ISO 8601 format", + "format": "date-time", + "title": "Created At", + "type": "string" + }, + "name": { + "description": "Name of the secret", + "title": "Name", + "type": "string" + }, + "team_name": { + "description": "Name of the team the secret belongs to", + "title": "Team Name", + "type": "string" + } + }, + "required": [ + "id", + "created_at", + "name", + "team_name" + ], + "title": "SecretV1", + "type": "object" + }, + "SecretsV1": { + "description": "A list of Baseten secrets.", + "properties": { + "secrets": { + "items": { + "$ref": "#/components/schemas/SecretV1" + }, + "title": "Secrets", + "type": "array" + } + }, + "required": [ + "secrets" + ], + "title": "SecretsV1", + "type": "object" + }, + "UpsertSecretRequestV1": { + "description": "A request to create or update a Baseten secret by name.", + "properties": { + "name": { + "description": "Name of the new or existing secret", + "examples": [ + "my_secret" ], - "title": "End Hour" + "title": "Name", + "type": "string" }, - "end_minute": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } + "value": { + "description": "Value of the secret", + "examples": [ + "my_secret_value" ], - "title": "End Minute" + "title": "Value", + "type": "string" + } + }, + "required": [ + "name", + "value" + ], + "title": "UpsertSecretRequestV1", + "type": "object" + }, + "SecretTombstoneV1": { + "description": "A secret tombstone.", + "properties": { + "name": { + "description": "Name of the deleted secret", + "title": "Name", + "type": "string" + } + }, + "required": [ + "name" + ], + "title": "SecretTombstoneV1", + "type": "object" + }, + "EnvironmentGroupManageAccessV1": { + "description": "Who is allowed to manage an environment group.", + "properties": { + "is_restricted": { + "description": "Whether the environment is restricted to a specific set of users.", + "title": "Is Restricted", + "type": "boolean" }, - "start_at": { + "users": { + "description": "Users who can manage the environment while it is restricted, including organization and team admins who always have access. Empty when the environment is unrestricted.", + "items": { + "$ref": "#/components/schemas/EnvironmentGroupUserV1" + }, + "title": "Users", + "type": "array" + } + }, + "required": [ + "is_restricted" + ], + "title": "EnvironmentGroupManageAccessV1", + "type": "object" + }, + "EnvironmentGroupUserV1": { + "description": "A user referenced by an environment group's manage access.", + "properties": { + "user_id": { + "description": "Unique identifier for the user.", + "title": "User Id", + "type": "string" + }, + "email": { "anyOf": [ { "type": "string" @@ -11692,9 +12942,10 @@ } ], "default": null, - "title": "Start At" + "description": "Email address of the user.", + "title": "Email" }, - "end_at": { + "name": { "anyOf": [ { "type": "string" @@ -11704,272 +12955,172 @@ } ], "default": null, - "title": "End At" + "description": "Display name of the user.", + "title": "Name" } }, "required": [ - "min_replica", - "max_replica", - "concurrency_target", - "autoscaling_window", - "scale_down_delay", - "target_utilization_percentage", - "target_in_flight_tokens", - "max_scale_down_rate", - "schedule_name", - "enabled", - "cadence", - "timezone", - "weekdays", - "start_hour", - "start_minute", - "end_hour", - "end_minute" + "user_id" ], - "title": "AuditLogEventAutoscalingScheduleSettingsV1", + "title": "EnvironmentGroupUserV1", "type": "object" }, - "AuditLogEventAutoscalingSettingsV1": { - "additionalProperties": false, - "description": "Autoscaling settings for a deployment or environment.", + "EnvironmentGroupV1": { + "description": "A team-scoped grouping of same-named environments (e.g. \"production\", \"staging\").\n\nRestricting an environment group limits who can manage the environment of that name\nacross every model and chain in the team.", "properties": { - "min_replica": { - "title": "Min Replica", - "type": "integer" - }, - "max_replica": { - "title": "Max Replica", - "type": "integer" - }, - "concurrency_target": { - "title": "Concurrency Target", - "type": "integer" - }, - "autoscaling_window": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } + "name": { + "description": "Name of the environment group, matching the environment name it governs.", + "examples": [ + "staging" ], - "title": "Autoscaling Window" + "title": "Name", + "type": "string" }, - "scale_down_delay": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "title": "Scale Down Delay" + "team_id": { + "description": "Unique identifier of the team the environment group belongs to.", + "title": "Team Id", + "type": "string" }, - "target_utilization_percentage": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "title": "Target Utilization Percentage" - }, - "target_in_flight_tokens": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "title": "Target In Flight Tokens" + "team_name": { + "description": "Name of the team the environment group belongs to.", + "title": "Team Name", + "type": "string" }, - "max_scale_down_rate": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "null" - } - ], - "title": "Max Scale Down Rate" + "manage_access": { + "$ref": "#/components/schemas/EnvironmentGroupManageAccessV1", + "description": "Settings controlling who can manage this environment group." } }, "required": [ - "min_replica", - "max_replica", - "concurrency_target", - "autoscaling_window", - "scale_down_delay", - "target_utilization_percentage", - "target_in_flight_tokens", - "max_scale_down_rate" + "name", + "team_id", + "team_name", + "manage_access" ], - "title": "AuditLogEventAutoscalingSettingsV1", + "title": "EnvironmentGroupV1", "type": "object" }, - "AuditLogEventChainDeletedV1": { - "additionalProperties": false, - "description": "A chain was deleted.", + "EnvironmentGroupsV1": { + "description": "A page of environment groups.", "properties": { - "event_type": { - "const": "CHAIN_DELETED", - "title": "Event Type", - "type": "string" - }, - "chain_id": { - "title": "Chain Id", - "type": "string" - }, - "chain_name": { - "title": "Chain Name", - "type": "string" + "items": { + "description": "Items in this page.", + "items": { + "$ref": "#/components/schemas/EnvironmentGroupV1" + }, + "title": "Items", + "type": "array" }, - "chain_deployment_name": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Chain Deployment Name" + "pagination": { + "$ref": "#/components/schemas/PaginationResponseV1", + "description": "Pagination metadata for the page." } }, "required": [ - "event_type", - "chain_id", - "chain_name", - "chain_deployment_name" + "items", + "pagination" ], - "title": "AuditLogEventChainDeletedV1", + "title": "EnvironmentGroupsV1", "type": "object" }, - "AuditLogEventChainDeployedV1": { - "additionalProperties": false, - "description": "A chain deployment was created.", + "UpdateEnvironmentGroupManageAccessV1": { + "description": "Manage-access settings to apply to an environment group.", "properties": { - "event_type": { - "const": "CHAIN_DEPLOYED", - "title": "Event Type", - "type": "string" - }, - "chain_id": { - "title": "Chain Id", - "type": "string" - }, - "chain_name": { - "title": "Chain Name", - "type": "string" - }, - "chain_deployment_id": { - "title": "Chain Deployment Id", - "type": "string" - }, - "chain_deployment_name": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Chain Deployment Name" - }, - "is_primary": { - "title": "Is Primary", + "is_restricted": { + "description": "Whether to restrict this environment to a specific set of users.", + "title": "Is Restricted", "type": "boolean" }, - "publish": { - "title": "Publish", - "type": "boolean" + "user_ids": { + "description": "IDs of users granted manage access while restricted. Only meaningful when is_restricted is true.", + "items": { + "type": "string" + }, + "title": "User Ids", + "type": "array" } }, "required": [ - "event_type", - "chain_id", - "chain_name", - "chain_deployment_id", - "chain_deployment_name", - "is_primary", - "publish" + "is_restricted" ], - "title": "AuditLogEventChainDeployedV1", + "title": "UpdateEnvironmentGroupManageAccessV1", "type": "object" }, - "AuditLogEventChainDeploymentActivatedV1": { - "additionalProperties": false, - "description": "A chain deployment was activated.", + "UpdateEnvironmentGroupRequestV1": { + "description": "A request to update an existing environment group.", "properties": { - "event_type": { - "const": "CHAIN_DEPLOYMENT_ACTIVATED", - "title": "Event Type", - "type": "string" - }, - "chain_id": { - "title": "Chain Id", - "type": "string" - }, - "chain_name": { - "title": "Chain Name", - "type": "string" - }, - "chain_deployment_id": { - "title": "Chain Deployment Id", - "type": "string" - }, - "chain_deployment_name": { + "manage_access": { "anyOf": [ { - "type": "string" + "$ref": "#/components/schemas/UpdateEnvironmentGroupManageAccessV1" }, { "type": "null" } ], - "title": "Chain Deployment Name" + "default": null, + "description": "Manage-access settings to apply. Omit to leave manage access unchanged." } }, - "required": [ - "event_type", - "chain_id", - "chain_name", - "chain_deployment_id", - "chain_deployment_name" - ], - "title": "AuditLogEventChainDeploymentActivatedV1", + "title": "UpdateEnvironmentGroupRequestV1", "type": "object" }, - "AuditLogEventChainDeploymentDeactivatedV1": { - "additionalProperties": false, - "description": "A chain deployment was deactivated.", + "TeamV1": { + "description": "A team.", "properties": { - "event_type": { - "const": "CHAIN_DEPLOYMENT_DEACTIVATED", - "title": "Event Type", + "id": { + "description": "Unique identifier of the team", + "title": "Id", "type": "string" }, - "chain_id": { - "title": "Chain Id", + "name": { + "description": "Name of the team", + "title": "Name", "type": "string" }, - "chain_name": { - "title": "Chain Name", - "type": "string" + "default": { + "type": "boolean", + "description": "Whether this is the default team for the organization", + "title": "Default" }, - "chain_deployment_id": { - "title": "Chain Deployment Id", + "created_at": { + "description": "Time the team was created in ISO 8601 format", + "format": "date-time", + "title": "Created At", "type": "string" - }, - "chain_deployment_name": { + } + }, + "required": [ + "id", + "name", + "default", + "created_at" + ], + "title": "TeamV1", + "type": "object" + }, + "TeamsV1": { + "description": "A list of teams.", + "properties": { + "teams": { + "description": "A list of teams", + "items": { + "$ref": "#/components/schemas/TeamV1" + }, + "title": "Teams", + "type": "array" + } + }, + "required": [ + "teams" + ], + "title": "TeamsV1", + "type": "object" + }, + "TeamsRequestV1": { + "description": "Request parameters for listing teams.", + "properties": { + "name": { "anyOf": [ { "type": "string" @@ -11978,95 +13129,87 @@ "type": "null" } ], - "title": "Chain Deployment Name" - } + "default": null, + "description": "When set, returns only the team with this exact name, if any.", + "title": "Name" + } }, - "required": [ - "event_type", - "chain_id", - "chain_name", - "chain_deployment_id", - "chain_deployment_name" - ], - "title": "AuditLogEventChainDeploymentDeactivatedV1", + "title": "TeamsRequestV1", "type": "object" }, - "AuditLogEventChainDeploymentDeletedV1": { - "additionalProperties": false, - "description": "A chain deployment was deleted.", + "RegionV1": { + "description": "A region that deployments can be placed in.", "properties": { - "event_type": { - "const": "CHAIN_DEPLOYMENT_DELETED", - "title": "Event Type", - "type": "string" - }, - "chain_id": { - "title": "Chain Id", - "type": "string" - }, - "chain_name": { - "title": "Chain Name", - "type": "string" - }, - "chain_deployment_id": { - "title": "Chain Deployment Id", + "slug": { + "description": "Stable identifier for the region, used when selecting a deployment region.", + "examples": [ + "us" + ], + "title": "Slug", "type": "string" }, - "deployment_name": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "display_name": { + "description": "Human-readable name of the region.", + "examples": [ + "United States" ], - "title": "Deployment Name" + "title": "Display Name", + "type": "string" } }, "required": [ - "event_type", - "chain_id", - "chain_name", - "chain_deployment_id", - "deployment_name" + "slug", + "display_name" ], - "title": "AuditLogEventChainDeploymentDeletedV1", + "title": "RegionV1", "type": "object" }, - "AuditLogEventChainDeploymentPromotedV1": { - "additionalProperties": false, - "description": "A chain deployment was promoted to an environment.", + "RegionsV1": { + "description": "A list of regions.", "properties": { - "event_type": { - "const": "CHAIN_DEPLOYMENT_PROMOTED", - "title": "Event Type", + "regions": { + "items": { + "$ref": "#/components/schemas/RegionV1" + }, + "title": "Regions", + "type": "array" + } + }, + "required": [ + "regions" + ], + "title": "RegionsV1", + "type": "object" + }, + "InstanceTypeV1": { + "description": "An instance type.", + "properties": { + "id": { + "description": "Identifier string for the instance type", + "title": "Id", "type": "string" }, - "chain_id": { - "title": "Chain Id", + "name": { + "description": "Display name of the instance type", + "title": "Name", "type": "string" }, - "chain_name": { - "title": "Chain Name", - "type": "string" + "memory_limit_mib": { + "description": "Memory limit of the instance type in Mebibytes", + "title": "Memory Limit Mib", + "type": "integer" }, - "chain_deployment_id": { - "title": "Chain Deployment Id", - "type": "string" + "millicpu_limit": { + "description": "CPU limit of the instance type in millicpu", + "title": "Millicpu Limit", + "type": "integer" }, - "chain_deployment_name": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Chain Deployment Name" + "gpu_count": { + "description": "Number of GPUs on the instance type", + "title": "Gpu Count", + "type": "integer" }, - "environment_name": { + "gpu_type": { "anyOf": [ { "type": "string" @@ -12075,255 +13218,309 @@ "type": "null" } ], - "title": "Environment Name" + "description": "Type of GPU on the instance type", + "title": "Gpu Type" }, - "environment_id": { + "gpu_memory_limit_mib": { "anyOf": [ { - "type": "string" + "type": "integer" }, { "type": "null" } ], - "title": "Environment Id" + "description": "Memory limit of the GPU on the instance type in Mebibytes", + "title": "Gpu Memory Limit Mib" } }, "required": [ - "event_type", - "chain_id", - "chain_name", - "chain_deployment_id", - "chain_deployment_name", - "environment_name", - "environment_id" + "id", + "name", + "memory_limit_mib", + "millicpu_limit", + "gpu_count", + "gpu_type", + "gpu_memory_limit_mib" ], - "title": "AuditLogEventChainDeploymentPromotedV1", + "title": "InstanceTypeV1", "type": "object" }, - "AuditLogEventChainEnvironmentCreatedV1": { - "additionalProperties": false, - "description": "A chain environment was created.", + "InstanceTypesV1": { + "description": "A list of instance types.", "properties": { - "event_type": { - "const": "CHAIN_ENVIRONMENT_CREATED", - "title": "Event Type", - "type": "string" - }, - "chain_id": { - "title": "Chain Id", - "type": "string" - }, - "chain_name": { - "title": "Chain Name", - "type": "string" - }, - "environment_name": { - "title": "Environment Name", - "type": "string" - }, - "redeploy_on_promotion": { + "instance_types": { + "items": { + "$ref": "#/components/schemas/InstanceTypeV1" + }, + "title": "Instance Types", + "type": "array" + } + }, + "required": [ + "instance_types" + ], + "title": "InstanceTypesV1", + "type": "object" + }, + "LoopsUserConfigV1": { + "description": "The caller's Loops user-level config (accelerator priorities).", + "properties": { + "trainer_accelerator_priority": { "anyOf": [ { - "type": "boolean" + "items": { + "type": "string" + }, + "type": "array" }, { "type": "null" } ], - "title": "Redeploy On Promotion" - }, - "ramp_up_while_promoting": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } + "description": "Ordered allowlist of GPU types for your Loops trainer deployments, highest priority first. Intersected with the org-level allowlist (org acts as a ceiling). Null means 'inherit the org-level allowlist'.", + "examples": [ + [ + "H100", + "H200" + ] ], - "title": "Ramp Up While Promoting" + "title": "Trainer Accelerator Priority" }, - "ramp_up_duration_seconds": { + "sampler_accelerator_priority": { "anyOf": [ { - "type": "integer" + "items": { + "type": "string" + }, + "type": "array" }, { "type": "null" } ], - "title": "Ramp Up Duration Seconds" + "description": "Ordered allowlist of GPU types for your Loops sampler deployments, highest priority first. Intersected with the org-level allowlist (org acts as a ceiling). Null means 'inherit the org-level allowlist'.", + "examples": [ + [ + "H100", + "H200" + ] + ], + "title": "Sampler Accelerator Priority" } }, "required": [ - "event_type", - "chain_id", - "chain_name", - "environment_name", - "redeploy_on_promotion", - "ramp_up_while_promoting", - "ramp_up_duration_seconds" + "trainer_accelerator_priority", + "sampler_accelerator_priority" ], - "title": "AuditLogEventChainEnvironmentCreatedV1", + "title": "LoopsUserConfigV1", "type": "object" }, - "AuditLogEventChainEnvironmentUpdatedV1": { - "additionalProperties": false, - "description": "A chain environment was updated.", + "GetLoopsUserConfigResponseV1": { + "description": "Response for ``GET /v1/loops/user_config``.", "properties": { - "event_type": { - "const": "CHAIN_ENVIRONMENT_UPDATED", - "title": "Event Type", - "type": "string" - }, - "chain_id": { - "title": "Chain Id", - "type": "string" - }, - "chain_name": { - "title": "Chain Name", - "type": "string" - }, - "environment_name": { - "title": "Environment Name", - "type": "string" - }, - "redeploy_on_promotion": { + "user_config": { + "$ref": "#/components/schemas/LoopsUserConfigV1", + "description": "The caller's Loops user config." + } + }, + "required": [ + "user_config" + ], + "title": "GetLoopsUserConfigResponseV1", + "type": "object" + }, + "PatchLoopsUserConfigRequestV1": { + "description": "Request body for ``PATCH /v1/loops/user_config``.\n\nFollows JSON Merge Patch (RFC 7396) semantics per field: omit the field\nto leave it unchanged, send ``null`` to clear and inherit the org-level\nallowlist, send a list to set the allowlist. Empty lists are rejected\nbecause the storage layer normalizes ``null`` and ``[]`` identically, so\naccepting both would create two ways to spell the same intent.", + "properties": { + "trainer_accelerator_priority": { "anyOf": [ { - "type": "boolean" + "items": { + "type": "string" + }, + "type": "array" }, { "type": "null" } ], - "title": "Redeploy On Promotion" - }, - "ramp_up_while_promoting": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } + "default": null, + "description": "Ordered list of GPU types for trainer deployments, highest priority first. Send a list to set; send null to clear (inherit org allowlist); omit to leave unchanged. Empty list is rejected.", + "examples": [ + [ + "H100", + "H200" + ] ], - "title": "Ramp Up While Promoting" + "title": "Trainer Accelerator Priority", + "x-null-distinct": true }, - "ramp_up_duration_seconds": { + "sampler_accelerator_priority": { "anyOf": [ { - "type": "integer" + "items": { + "type": "string" + }, + "type": "array" }, { "type": "null" } ], - "title": "Ramp Up Duration Seconds" + "default": null, + "description": "Ordered list of GPU types for sampler deployments, highest priority first. Send a list to set; send null to clear (inherit org allowlist); omit to leave unchanged. Empty list is rejected.", + "examples": [ + [ + "H100", + "H200" + ] + ], + "title": "Sampler Accelerator Priority", + "x-null-distinct": true + } + }, + "title": "PatchLoopsUserConfigRequestV1", + "type": "object" + }, + "PatchLoopsUserConfigResponseV1": { + "description": "Response for ``PATCH /v1/loops/user_config``.", + "properties": { + "user_config": { + "$ref": "#/components/schemas/LoopsUserConfigV1", + "description": "The updated Loops user config." } }, "required": [ - "event_type", - "chain_id", - "chain_name", - "environment_name", - "redeploy_on_promotion", - "ramp_up_while_promoting", - "ramp_up_duration_seconds" + "user_config" ], - "title": "AuditLogEventChainEnvironmentUpdatedV1", + "title": "PatchLoopsUserConfigResponseV1", "type": "object" }, - "AuditLogEventChainletAutoscalingSettingsChangedV1": { - "additionalProperties": false, - "description": "A chainlet's autoscaling settings were changed.", + "InstanceTypeWithPriceV1": { "properties": { - "min_replica": { - "title": "Min Replica", - "type": "integer" - }, - "max_replica": { - "title": "Max Replica", - "type": "integer" + "instance_type": { + "$ref": "#/components/schemas/InstanceTypeV1", + "description": "Instance type properties." }, - "concurrency_target": { - "title": "Concurrency Target", - "type": "integer" + "price": { + "description": "Usage price in USD / minute.", + "title": "Price", + "type": "number" + } + }, + "required": [ + "instance_type", + "price" + ], + "title": "InstanceTypeWithPriceV1", + "type": "object" + }, + "InstanceTypePricesV1": { + "description": "A list of instance types.", + "properties": { + "instance_types": { + "items": { + "$ref": "#/components/schemas/InstanceTypeWithPriceV1" + }, + "title": "Instance Types", + "type": "array" + } + }, + "required": [ + "instance_types" + ], + "title": "InstanceTypePricesV1", + "type": "object" + }, + "DeploymentArchivePayloadV1": { + "description": "Deployment-level fields for a model-archive push.\n\nShared by every endpoint that creates a deployment from an uploaded archive:\n`POST /v1/prepare_model_upload`, the `model_archive` source on `POST\n/v1/models`, and `POST /v1/models/{model_id}/deployments`.", + "properties": { + "config": { + "additionalProperties": true, + "description": "Parsed model config as a JSON object.", + "title": "Config", + "type": "object" }, - "autoscaling_window": { + "raw_config": { "anyOf": [ { - "type": "integer" + "type": "string" }, { "type": "null" } ], - "title": "Autoscaling Window" + "default": null, + "description": "Original config.yaml text, persisted as-is on the deployment. Best-effort: invalid raw configs are logged and dropped without failing the request.", + "title": "Raw Config" }, - "scale_down_delay": { + "user_env": { "anyOf": [ { - "type": "integer" + "additionalProperties": true, + "type": "object" }, { "type": "null" } ], - "title": "Scale Down Delay" + "default": null, + "description": "Client environment metadata (e.g. client version, Python version). Validated server-side.", + "title": "User Env" }, - "target_utilization_percentage": { + "environment_name": { "anyOf": [ { - "type": "integer" + "type": "string" }, { "type": "null" } ], - "title": "Target Utilization Percentage" + "default": null, + "description": "Stable environment to push to (e.g. `production`). If unset, the deployment is created without environment selection. Caller must have push permission for the named environment.", + "title": "Environment Name" }, - "target_in_flight_tokens": { + "create_environment_if_missing": { + "default": true, + "description": "Create the environment named by `environment_name` if it does not exist yet. If false, a push to an environment that does not exist is rejected. Only meaningful when `environment_name` is set to something other than `production`, which always exists. This field currently defaults to true, but that default will change to false in a future release. Set it explicitly to avoid a behavior change.", + "title": "Create Environment If Missing", + "type": "boolean" + }, + "region": { "anyOf": [ { - "type": "integer" + "type": "string" }, { "type": "null" } ], - "title": "Target In Flight Tokens" + "default": null, + "description": "Region in which to deploy the model", + "title": "Region" }, - "max_scale_down_rate": { + "preserve_env_instance_type": { + "default": true, + "description": "Retain the target environment's current instance type rather than the one in `config`. Only meaningful when `environment_name` is set and that environment already exists.", + "title": "Preserve Env Instance Type", + "type": "boolean" + }, + "deploy_timeout_minutes": { "anyOf": [ { - "type": "number" + "type": "integer" }, { "type": "null" } ], - "title": "Max Scale Down Rate" - }, - "event_type": { - "const": "CHAINLET_AUTOSCALING_SETTINGS_CHANGED", - "title": "Event Type", - "type": "string" - }, - "chain_id": { - "title": "Chain Id", - "type": "string" - }, - "chain_name": { - "title": "Chain Name", - "type": "string" - }, - "chain_deployment_id": { - "title": "Chain Deployment Id", - "type": "string" + "default": null, + "description": "Deploy timeout in minutes; allowed range 10 to 1440. Server default applies if unset.", + "title": "Deploy Timeout Minutes" }, - "chain_deployment_name": { + "deployment_name": { "anyOf": [ { "type": "string" @@ -12332,70 +13529,45 @@ "type": "null" } ], - "title": "Chain Deployment Name" - }, - "chainlet_name": { - "title": "Chainlet Name", - "type": "string" - }, - "chainlet_id": { - "title": "Chainlet Id", - "type": "string" + "default": null, + "description": "Optional human-readable name for the deployment.", + "title": "Deployment Name" }, - "previous_settings": { + "labels": { "anyOf": [ { - "$ref": "#/components/schemas/AuditLogEventAutoscalingSettingsV1" + "additionalProperties": true, + "type": "object" }, { "type": "null" } - ] + ], + "default": null, + "description": "User-provided key-value labels for the deployment.", + "title": "Labels" + }, + "is_development": { + "default": false, + "description": "If true, push as a development deployment: the model's single mutable dev slot, created if absent and overwritten in place otherwise. The following fields must be left at their defaults: `environment_name`, `preserve_env_instance_type`, `deployment_name`.", + "title": "Is Development", + "type": "boolean" } }, "required": [ - "min_replica", - "max_replica", - "concurrency_target", - "autoscaling_window", - "scale_down_delay", - "target_utilization_percentage", - "target_in_flight_tokens", - "max_scale_down_rate", - "event_type", - "chain_id", - "chain_name", - "chain_deployment_id", - "chain_deployment_name", - "chainlet_name", - "chainlet_id", - "previous_settings" + "config" ], - "title": "AuditLogEventChainletAutoscalingSettingsChangedV1", + "title": "DeploymentArchivePayloadV1", "type": "object" }, - "AuditLogEventChainletInstanceTypeChangedV1": { - "additionalProperties": false, - "description": "A chainlet's instance type was changed.", + "PrepareModelUploadRequestV1": { + "description": "Body for `POST /v1/prepare_model_upload`.\n\nValidates the same payload the commit endpoint will validate, and on\n`dry_run=false` issues STS upload credentials. Exactly one of `name` or\n`model_id` is required: `name` validates the new-model path (`POST\n/v1/models`); `model_id` validates the add-deployment path (`POST\n/v1/models/{model_id}/deployments`).", "properties": { - "event_type": { - "const": "CHAINLET_INSTANCE_TYPE_CHANGED", - "title": "Event Type", - "type": "string" - }, - "chain_id": { - "title": "Chain Id", - "type": "string" - }, - "chain_name": { - "title": "Chain Name", - "type": "string" - }, - "chain_deployment_id": { - "title": "Chain Deployment Id", - "type": "string" + "deployment": { + "$ref": "#/components/schemas/DeploymentArchivePayloadV1", + "description": "Deployment-level payload, identical to the payload sent at commit." }, - "chain_deployment_name": { + "name": { "anyOf": [ { "type": "string" @@ -12404,54 +13576,9 @@ "type": "null" } ], - "title": "Chain Deployment Name" - }, - "chainlet_name": { - "title": "Chainlet Name", - "type": "string" - }, - "chainlet_id": { - "title": "Chainlet Id", - "type": "string" - }, - "instance_type_name": { - "title": "Instance Type Name", - "type": "string" - } - }, - "required": [ - "event_type", - "chain_id", - "chain_name", - "chain_deployment_id", - "chain_deployment_name", - "chainlet_name", - "chainlet_id", - "instance_type_name" - ], - "title": "AuditLogEventChainletInstanceTypeChangedV1", - "type": "object" - }, - "AuditLogEventDirectoryGroupRoleUpdatedV1": { - "additionalProperties": false, - "description": "A directory group's role was updated.", - "properties": { - "event_type": { - "const": "DIRECTORY_GROUP_ROLE_UPDATED", - "title": "Event Type", - "type": "string" - }, - "directory_group_id": { - "title": "Directory Group Id", - "type": "string" - }, - "directory_group_name": { - "title": "Directory Group Name", - "type": "string" - }, - "new_role_name": { - "title": "New Role Name", - "type": "string" + "default": null, + "description": "Set to validate a new-model push. Exactly one of `name` or `model_id` is required.", + "title": "Name" }, "team_id": { "anyOf": [ @@ -12462,9 +13589,11 @@ "type": "null" } ], + "default": null, + "description": "Team the new model will belong to. Only valid when `name` is set; defaults to the organization's default team when omitted. Must not be set when `model_id` is set (the existing model already has a team).", "title": "Team Id" }, - "team_name": { + "model_id": { "anyOf": [ { "type": "string" @@ -12473,114 +13602,128 @@ "type": "null" } ], - "title": "Team Name" + "default": null, + "description": "Set to validate an add-deployment push to an existing model. Exactly one of `name` or `model_id` is required.", + "title": "Model Id" + }, + "dry_run": { + "default": false, + "description": "If true, validate the payload only and do not issue upload credentials. The response sets `creds`, `s3_bucket`, and `s3_key` to `null`.", + "title": "Dry Run", + "type": "boolean" } }, "required": [ - "event_type", - "directory_group_id", - "directory_group_name", - "new_role_name", - "team_id", - "team_name" + "deployment" ], - "title": "AuditLogEventDirectoryGroupRoleUpdatedV1", + "title": "PrepareModelUploadRequestV1", "type": "object" }, - "AuditLogEventEnvironmentCreatedV1": { - "additionalProperties": false, - "description": "A model environment was created.", + "AWSCredentialsV1": { + "description": "AWS credentials", "properties": { - "min_replica": { - "title": "Min Replica", - "type": "integer" - }, - "max_replica": { - "title": "Max Replica", - "type": "integer" - }, - "concurrency_target": { - "title": "Concurrency Target", - "type": "integer" - }, - "autoscaling_window": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "title": "Autoscaling Window" - }, - "scale_down_delay": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "title": "Scale Down Delay" + "aws_access_key_id": { + "description": "The AWS access key ID", + "title": "Aws Access Key Id", + "type": "string" }, - "target_utilization_percentage": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "title": "Target Utilization Percentage" + "aws_secret_access_key": { + "description": "The AWS secret access key", + "title": "Aws Secret Access Key", + "type": "string" }, - "target_in_flight_tokens": { + "aws_session_token": { + "description": "The AWS session token", + "title": "Aws Session Token", + "type": "string" + } + }, + "required": [ + "aws_access_key_id", + "aws_secret_access_key", + "aws_session_token" + ], + "title": "AWSCredentialsV1", + "type": "object" + }, + "PrepareModelUploadResponseV1": { + "description": "Response from `POST /v1/prepare_model_upload`.\n\nReturns STS upload credentials when the push requires an archive upload. All\nfour fields (`creds`, `s3_bucket`, `s3_key`, `s3_region`) are `null` when no\nupload is needed: either `dry_run=true` (validation only) or a model format\nthat is not built from an uploaded archive (for example, BIS-LLM, which is\nbuilt from its config alone).", + "properties": { + "creds": { "anyOf": [ { - "type": "integer" + "$ref": "#/components/schemas/AWSCredentialsV1" }, { "type": "null" } ], - "title": "Target In Flight Tokens" + "default": null, + "description": "STS credentials to upload the model archive. Null when no archive upload is required." }, - "max_scale_down_rate": { + "s3_bucket": { "anyOf": [ { - "type": "number" + "type": "string" }, { "type": "null" } ], - "title": "Max Scale Down Rate" + "default": null, + "description": "S3 bucket the credentials are scoped to. Null when no archive upload is required.", + "title": "S3 Bucket" }, - "redeploy_on_promotion": { + "s3_key": { "anyOf": [ { - "type": "boolean" + "type": "string" }, { "type": "null" } ], - "title": "Redeploy On Promotion" + "default": null, + "description": "S3 key the credentials are scoped to. Pass this to `POST /v1/models` (in the `model_archive` source) once the upload completes. Null when no archive upload is required.", + "title": "S3 Key" }, - "rolling_deploy": { + "s3_region": { "anyOf": [ { - "type": "boolean" + "type": "string" }, { "type": "null" } ], - "title": "Rolling Deploy" + "default": null, + "description": "AWS region the S3 bucket resides in. Null when no archive upload is required.", + "title": "S3 Region" + } + }, + "title": "PrepareModelUploadResponseV1", + "type": "object" + }, + "AuditLogActorTypeV1": { + "description": "Kind of actor that performed an audited action.", + "enum": [ + "USER", + "API_KEY", + "BASETEN_USER", + "BASETEN_SYSTEM", + "TOMBSTONE_USER" + ], + "title": "AuditLogActorTypeV1", + "type": "string" + }, + "AuditLogActorV1": { + "description": "The actor that performed an audited action.", + "properties": { + "type": { + "$ref": "#/components/schemas/AuditLogActorTypeV1", + "description": "Kind of actor that performed the action." }, - "rolling_deploy_strategy": { + "email": { "anyOf": [ { "type": "string" @@ -12589,390 +13732,333 @@ "type": "null" } ], - "title": "Rolling Deploy Strategy" + "default": null, + "description": "Email of the acting user, when the actor is a user.", + "title": "Email" }, - "max_unavailable_percent": { + "api_key_prefix": { "anyOf": [ { - "type": "integer" + "type": "string" }, { "type": "null" } ], - "title": "Max Unavailable Percent" + "default": null, + "description": "Prefix of the acting API key, when the actor is an API key.", + "title": "Api Key Prefix" }, - "max_surge_percent": { + "api_key_name": { "anyOf": [ { - "type": "integer" + "type": "string" }, { "type": "null" } ], - "title": "Max Surge Percent" - }, - "stabilization_time_seconds": { - "anyOf": [ + "default": null, + "description": "Display name of the acting API key, when the actor is an API key.", + "title": "Api Key Name" + } + }, + "required": [ + "type" + ], + "title": "AuditLogActorV1", + "type": "object" + }, + "AuditLogApiKeyTypeV1": { + "description": "Type of API key recorded on an API-key event.", + "enum": [ + "PERSONAL", + "CREATOR_SERVICE_ACCOUNT", + "MANAGE_API_KEYS_SERVICE_ACCOUNT", + "INVOKE_ALL_MODELS_SERVICE_ACCOUNT", + "INVOKE_ALLOWED_MODELS_SERVICE_ACCOUNT", + "INVOKE_SCOPED_ENVS_AND_MODELS_SERVICE_ACCOUNT", + "EXPORT_METRICS_ALL_MODELS_SERVICE_ACCOUNT", + "EXPORT_METRICS_ALLOWED_MODELS_SERVICE_ACCOUNT", + "INVOKE_ALL_SHARED_ENDPOINTS_SERVICE_ACCOUNT", + "INVOKE_ALLOWED_SHARED_ENDPOINTS_SERVICE_ACCOUNT", + "INVOKE_ALL_ROUTES" + ], + "title": "AuditLogApiKeyTypeV1", + "type": "string" + }, + "AuditLogEntryV1": { + "description": "A single audit-log entry.", + "properties": { + "id": { + "description": "Unique identifier of the audit-log entry.", + "title": "Id", + "type": "string" + }, + "created": { + "description": "Time the action occurred, in ISO 8601 format.", + "format": "date-time", + "title": "Created", + "type": "string" + }, + "event_type": { + "$ref": "#/components/schemas/AuditLogEventTypeV1", + "description": "Type of action that was recorded." + }, + "event_data": { + "description": "Structured details of the action, discriminated by `event_type`.", + "discriminator": { + "mapping": { + "API_KEY_CREATED": "#/components/schemas/AuditLogEventApiKeyCreatedV1", + "API_KEY_DELETED": "#/components/schemas/AuditLogEventApiKeyDeletedV1", + "CHAINLET_AUTOSCALING_SETTINGS_CHANGED": "#/components/schemas/AuditLogEventChainletAutoscalingSettingsChangedV1", + "CHAINLET_INSTANCE_TYPE_CHANGED": "#/components/schemas/AuditLogEventChainletInstanceTypeChangedV1", + "CHAIN_DELETED": "#/components/schemas/AuditLogEventChainDeletedV1", + "CHAIN_DEPLOYED": "#/components/schemas/AuditLogEventChainDeployedV1", + "CHAIN_DEPLOYMENT_ACTIVATED": "#/components/schemas/AuditLogEventChainDeploymentActivatedV1", + "CHAIN_DEPLOYMENT_DEACTIVATED": "#/components/schemas/AuditLogEventChainDeploymentDeactivatedV1", + "CHAIN_DEPLOYMENT_DELETED": "#/components/schemas/AuditLogEventChainDeploymentDeletedV1", + "CHAIN_DEPLOYMENT_PROMOTED": "#/components/schemas/AuditLogEventChainDeploymentPromotedV1", + "CHAIN_ENVIRONMENT_CREATED": "#/components/schemas/AuditLogEventChainEnvironmentCreatedV1", + "CHAIN_ENVIRONMENT_UPDATED": "#/components/schemas/AuditLogEventChainEnvironmentUpdatedV1", + "DIRECTORY_GROUP_ROLE_UPDATED": "#/components/schemas/AuditLogEventDirectoryGroupRoleUpdatedV1", + "ENVIRONMENT_CREATED": "#/components/schemas/AuditLogEventEnvironmentCreatedV1", + "ENVIRONMENT_DELETED": "#/components/schemas/AuditLogEventEnvironmentDeletedV1", + "ENVIRONMENT_UPDATED": "#/components/schemas/AuditLogEventEnvironmentUpdatedV1", + "GATEWAY_ENDPOINT_CREATED": "#/components/schemas/AuditLogEventGatewayEndpointCreatedV1", + "GATEWAY_ENDPOINT_DELETED": "#/components/schemas/AuditLogEventGatewayEndpointDeletedV1", + "GATEWAY_ENDPOINT_UPDATED": "#/components/schemas/AuditLogEventGatewayEndpointUpdatedV1", + "MODEL_DELETED": "#/components/schemas/AuditLogEventModelDeletedV1", + "MODEL_DEPLOYED": "#/components/schemas/AuditLogEventModelDeployedV1", + "MODEL_DEPLOYMENT_ACTIVATED": "#/components/schemas/AuditLogEventModelDeploymentActivatedV1", + "MODEL_DEPLOYMENT_AUTOSCALING_SETTINGS_CHANGED": "#/components/schemas/AuditLogEventModelDeploymentAutoscalingSettingsChangedV1", + "MODEL_DEPLOYMENT_DEACTIVATED": "#/components/schemas/AuditLogEventModelDeploymentDeactivatedV1", + "MODEL_DEPLOYMENT_DELETED": "#/components/schemas/AuditLogEventModelDeploymentDeletedV1", + "MODEL_DEPLOYMENT_INSTANCE_TYPE_CHANGED": "#/components/schemas/AuditLogEventModelDeploymentInstanceTypeChangedV1", + "MODEL_DEPLOYMENT_PROMOTED": "#/components/schemas/AuditLogEventModelDeploymentPromotedV1", + "MODEL_DEPLOYMENT_REQUEST_BACKPRESSURE_SETTINGS_CHANGED": "#/components/schemas/AuditLogEventModelDeploymentRequestBackpressureSettingsChangedV1", + "MODEL_DEPLOYMENT_RETRIED": "#/components/schemas/AuditLogEventModelDeploymentRetriedV1", + "MODEL_PROMOTION_CONTROL_ACTION": "#/components/schemas/AuditLogEventModelPromotionControlActionV1", + "MODEL_RENAMED": "#/components/schemas/AuditLogEventModelRenamedV1", + "PROVIDER_CONNECTION_CREATED": "#/components/schemas/AuditLogEventProviderConnectionCreatedV1", + "PROVIDER_CONNECTION_DELETED": "#/components/schemas/AuditLogEventProviderConnectionDeletedV1", + "PROVIDER_CONNECTION_UPDATED": "#/components/schemas/AuditLogEventProviderConnectionUpdatedV1", + "REPLICA_TERMINATED": "#/components/schemas/AuditLogEventReplicaTerminatedV1", + "REQUIRE_GROUP_BASED_ADMINS_ENABLED": "#/components/schemas/AuditLogEventRequireGroupBasedAdminsEnabledV1", + "SECRET_DELETED": "#/components/schemas/AuditLogEventSecretDeletedV1", + "SECRET_UPDATED": "#/components/schemas/AuditLogEventSecretUpdatedV1", + "SSH_CERTIFICATE_SIGNED": "#/components/schemas/AuditLogEventSshCertificateSignedV1", + "USER_INVITED": "#/components/schemas/AuditLogEventUserInvitedV1", + "USER_JOINED_ORGANIZATION": "#/components/schemas/AuditLogEventUserJoinedOrganizationV1", + "USER_REMOVED": "#/components/schemas/AuditLogEventUserRemovedV1", + "USER_ROLE_UPDATED": "#/components/schemas/AuditLogEventUserRoleUpdatedV1", + "USER_TEAM_ROLE_UPDATED": "#/components/schemas/AuditLogEventUserTeamRoleUpdatedV1", + "VOLUME_DELETED": "#/components/schemas/AuditLogEventVolumeDeletedV1", + "VOLUME_VERSION_DELETED": "#/components/schemas/AuditLogEventVolumeVersionDeletedV1", + "VOLUME_VERSION_RESTORED": "#/components/schemas/AuditLogEventVolumeVersionRestoredV1", + "WEBHOOK_SIGNING_SECRET_CREATED": "#/components/schemas/AuditLogEventWebhookSigningSecretCreatedV1", + "WEBHOOK_SIGNING_SECRET_DELETED": "#/components/schemas/AuditLogEventWebhookSigningSecretDeletedV1", + "WEBHOOK_SIGNING_SECRET_ROTATED": "#/components/schemas/AuditLogEventWebhookSigningSecretRotatedV1" + }, + "propertyName": "event_type" + }, + "oneOf": [ { - "type": "integer" + "$ref": "#/components/schemas/AuditLogEventModelDeployedV1" }, { - "type": "null" - } - ], - "title": "Stabilization Time Seconds" - }, - "replica_overhead_percent": { - "anyOf": [ + "$ref": "#/components/schemas/AuditLogEventModelDeploymentActivatedV1" + }, { - "type": "integer" + "$ref": "#/components/schemas/AuditLogEventModelDeploymentDeactivatedV1" }, { - "type": "null" - } - ], - "title": "Replica Overhead Percent" - }, - "promotion_cleanup_strategy": { - "anyOf": [ + "$ref": "#/components/schemas/AuditLogEventModelDeploymentRetriedV1" + }, { - "type": "string" + "$ref": "#/components/schemas/AuditLogEventModelDeploymentPromotedV1" }, { - "type": "null" - } - ], - "title": "Promotion Cleanup Strategy" - }, - "ramp_up_while_promoting": { - "anyOf": [ + "$ref": "#/components/schemas/AuditLogEventModelDeploymentAutoscalingSettingsChangedV1" + }, { - "type": "boolean" + "$ref": "#/components/schemas/AuditLogEventModelDeploymentRequestBackpressureSettingsChangedV1" }, { - "type": "null" - } - ], - "title": "Ramp Up While Promoting" - }, - "ramp_up_duration_seconds": { - "anyOf": [ + "$ref": "#/components/schemas/AuditLogEventModelDeploymentInstanceTypeChangedV1" + }, { - "type": "integer" + "$ref": "#/components/schemas/AuditLogEventModelDeploymentDeletedV1" }, { - "type": "null" - } - ], - "title": "Ramp Up Duration Seconds" - }, - "ramp_up_step_size": { - "anyOf": [ + "$ref": "#/components/schemas/AuditLogEventModelDeletedV1" + }, { - "type": "integer" + "$ref": "#/components/schemas/AuditLogEventModelRenamedV1" }, { - "type": "null" - } - ], - "title": "Ramp Up Step Size" - }, - "request_backpressure_policy": { - "anyOf": [ + "$ref": "#/components/schemas/AuditLogEventChainDeployedV1" + }, { - "type": "string" + "$ref": "#/components/schemas/AuditLogEventChainDeploymentActivatedV1" }, { - "type": "null" - } - ], - "default": null, - "title": "Request Backpressure Policy" - }, - "model_id": { - "title": "Model Id", - "type": "string" - }, - "model_name": { - "title": "Model Name", - "type": "string" - }, - "environment_name": { - "title": "Environment Name", - "type": "string" - }, - "deployment_type": { - "anyOf": [ + "$ref": "#/components/schemas/AuditLogEventChainDeploymentDeactivatedV1" + }, { - "type": "string" + "$ref": "#/components/schemas/AuditLogEventChainDeploymentPromotedV1" }, { - "type": "null" - } - ], - "title": "Deployment Type" - }, - "event_type": { - "const": "ENVIRONMENT_CREATED", - "title": "Event Type", - "type": "string" - } - }, - "required": [ - "min_replica", - "max_replica", - "concurrency_target", - "autoscaling_window", - "scale_down_delay", - "target_utilization_percentage", - "target_in_flight_tokens", - "max_scale_down_rate", - "redeploy_on_promotion", - "rolling_deploy", - "rolling_deploy_strategy", - "max_unavailable_percent", - "max_surge_percent", - "stabilization_time_seconds", - "replica_overhead_percent", - "promotion_cleanup_strategy", - "ramp_up_while_promoting", - "ramp_up_duration_seconds", - "ramp_up_step_size", - "model_id", - "model_name", - "environment_name", - "deployment_type", - "event_type" - ], - "title": "AuditLogEventEnvironmentCreatedV1", - "type": "object" - }, - "AuditLogEventEnvironmentDeletedV1": { - "additionalProperties": false, - "description": "A model environment was deleted.", - "properties": { - "event_type": { - "const": "ENVIRONMENT_DELETED", - "title": "Event Type", - "type": "string" - }, - "model_id": { - "title": "Model Id", - "type": "string" - }, - "model_name": { - "title": "Model Name", - "type": "string" - }, - "environment_name": { - "title": "Environment Name", - "type": "string" - } - }, - "required": [ - "event_type", - "model_id", - "model_name", - "environment_name" - ], - "title": "AuditLogEventEnvironmentDeletedV1", - "type": "object" - }, - "AuditLogEventEnvironmentSettingsV1": { - "additionalProperties": false, - "description": "Full environment settings (autoscaling + rolling promotion + deprecated canary);\nshared base for the environment events and the type of their previous_settings\nsnapshots. Not itself a payload in the discriminated union.", - "properties": { - "min_replica": { - "title": "Min Replica", - "type": "integer" - }, - "max_replica": { - "title": "Max Replica", - "type": "integer" - }, - "concurrency_target": { - "title": "Concurrency Target", - "type": "integer" - }, - "autoscaling_window": { - "anyOf": [ + "$ref": "#/components/schemas/AuditLogEventChainletAutoscalingSettingsChangedV1" + }, { - "type": "integer" + "$ref": "#/components/schemas/AuditLogEventChainletInstanceTypeChangedV1" }, { - "type": "null" - } - ], - "title": "Autoscaling Window" - }, - "scale_down_delay": { - "anyOf": [ + "$ref": "#/components/schemas/AuditLogEventChainDeploymentDeletedV1" + }, { - "type": "integer" + "$ref": "#/components/schemas/AuditLogEventChainDeletedV1" }, { - "type": "null" - } - ], - "title": "Scale Down Delay" - }, - "target_utilization_percentage": { - "anyOf": [ + "$ref": "#/components/schemas/AuditLogEventChainEnvironmentCreatedV1" + }, { - "type": "integer" + "$ref": "#/components/schemas/AuditLogEventChainEnvironmentUpdatedV1" }, { - "type": "null" - } - ], - "title": "Target Utilization Percentage" - }, - "target_in_flight_tokens": { - "anyOf": [ + "$ref": "#/components/schemas/AuditLogEventSecretUpdatedV1" + }, { - "type": "integer" + "$ref": "#/components/schemas/AuditLogEventSecretDeletedV1" }, { - "type": "null" - } - ], - "title": "Target In Flight Tokens" - }, - "max_scale_down_rate": { - "anyOf": [ + "$ref": "#/components/schemas/AuditLogEventApiKeyCreatedV1" + }, { - "type": "number" + "$ref": "#/components/schemas/AuditLogEventApiKeyDeletedV1" }, { - "type": "null" - } - ], - "title": "Max Scale Down Rate" - }, - "redeploy_on_promotion": { - "anyOf": [ + "$ref": "#/components/schemas/AuditLogEventGatewayEndpointCreatedV1" + }, { - "type": "boolean" + "$ref": "#/components/schemas/AuditLogEventGatewayEndpointUpdatedV1" }, { - "type": "null" - } - ], - "title": "Redeploy On Promotion" - }, - "rolling_deploy": { - "anyOf": [ + "$ref": "#/components/schemas/AuditLogEventGatewayEndpointDeletedV1" + }, { - "type": "boolean" + "$ref": "#/components/schemas/AuditLogEventProviderConnectionCreatedV1" }, { - "type": "null" - } - ], - "title": "Rolling Deploy" - }, - "rolling_deploy_strategy": { - "anyOf": [ + "$ref": "#/components/schemas/AuditLogEventProviderConnectionUpdatedV1" + }, { - "type": "string" + "$ref": "#/components/schemas/AuditLogEventProviderConnectionDeletedV1" }, { - "type": "null" - } - ], - "title": "Rolling Deploy Strategy" - }, - "max_unavailable_percent": { - "anyOf": [ + "$ref": "#/components/schemas/AuditLogEventUserInvitedV1" + }, { - "type": "integer" + "$ref": "#/components/schemas/AuditLogEventUserJoinedOrganizationV1" }, { - "type": "null" - } - ], - "title": "Max Unavailable Percent" - }, - "max_surge_percent": { - "anyOf": [ + "$ref": "#/components/schemas/AuditLogEventWebhookSigningSecretCreatedV1" + }, { - "type": "integer" + "$ref": "#/components/schemas/AuditLogEventWebhookSigningSecretRotatedV1" }, { - "type": "null" - } - ], - "title": "Max Surge Percent" - }, - "stabilization_time_seconds": { - "anyOf": [ + "$ref": "#/components/schemas/AuditLogEventWebhookSigningSecretDeletedV1" + }, { - "type": "integer" + "$ref": "#/components/schemas/AuditLogEventUserRoleUpdatedV1" }, { - "type": "null" - } - ], - "title": "Stabilization Time Seconds" - }, - "replica_overhead_percent": { - "anyOf": [ + "$ref": "#/components/schemas/AuditLogEventUserTeamRoleUpdatedV1" + }, { - "type": "integer" + "$ref": "#/components/schemas/AuditLogEventUserRemovedV1" }, { - "type": "null" - } - ], - "title": "Replica Overhead Percent" - }, - "promotion_cleanup_strategy": { - "anyOf": [ + "$ref": "#/components/schemas/AuditLogEventDirectoryGroupRoleUpdatedV1" + }, { - "type": "string" + "$ref": "#/components/schemas/AuditLogEventRequireGroupBasedAdminsEnabledV1" }, { - "type": "null" + "$ref": "#/components/schemas/AuditLogEventEnvironmentCreatedV1" + }, + { + "$ref": "#/components/schemas/AuditLogEventEnvironmentUpdatedV1" + }, + { + "$ref": "#/components/schemas/AuditLogEventEnvironmentDeletedV1" + }, + { + "$ref": "#/components/schemas/AuditLogEventReplicaTerminatedV1" + }, + { + "$ref": "#/components/schemas/AuditLogEventModelPromotionControlActionV1" + }, + { + "$ref": "#/components/schemas/AuditLogEventSshCertificateSignedV1" + }, + { + "$ref": "#/components/schemas/AuditLogEventVolumeDeletedV1" + }, + { + "$ref": "#/components/schemas/AuditLogEventVolumeVersionDeletedV1" + }, + { + "$ref": "#/components/schemas/AuditLogEventVolumeVersionRestoredV1" } ], - "title": "Promotion Cleanup Strategy" + "title": "Event Data" }, - "ramp_up_while_promoting": { + "source": { "anyOf": [ { - "type": "boolean" + "$ref": "#/components/schemas/AuditLogSourceV1" }, { "type": "null" } ], - "title": "Ramp Up While Promoting" + "default": null, + "description": "Surface that issued the action, if known." }, - "ramp_up_duration_seconds": { + "actor": { + "$ref": "#/components/schemas/AuditLogActorV1", + "description": "The actor that performed the action." + }, + "client_name": { "anyOf": [ { - "type": "integer" + "type": "string" }, { "type": "null" } ], - "title": "Ramp Up Duration Seconds" + "default": null, + "description": "Name of the client that issued the action, if known.", + "title": "Client Name" }, - "ramp_up_step_size": { + "client_version": { "anyOf": [ { - "type": "integer" + "type": "string" }, { "type": "null" } ], - "title": "Ramp Up Step Size" + "default": null, + "description": "Version of the client that issued the action, if known.", + "title": "Client Version" }, - "request_backpressure_policy": { + "client_session_id": { "anyOf": [ { "type": "string" @@ -12982,51 +14068,136 @@ } ], "default": null, - "title": "Request Backpressure Policy" + "description": "Opaque identifier grouping actions from the same client session, if known.", + "title": "Client Session Id" } }, "required": [ - "min_replica", - "max_replica", - "concurrency_target", - "autoscaling_window", - "scale_down_delay", - "target_utilization_percentage", - "target_in_flight_tokens", - "max_scale_down_rate", - "redeploy_on_promotion", - "rolling_deploy", - "rolling_deploy_strategy", - "max_unavailable_percent", - "max_surge_percent", - "stabilization_time_seconds", - "replica_overhead_percent", - "promotion_cleanup_strategy", - "ramp_up_while_promoting", - "ramp_up_duration_seconds", - "ramp_up_step_size" + "id", + "created", + "event_type", + "event_data", + "actor" ], - "title": "AuditLogEventEnvironmentSettingsV1", + "title": "AuditLogEntryV1", "type": "object" }, - "AuditLogEventEnvironmentUpdatedV1": { + "AuditLogEventApiKeyCreatedV1": { "additionalProperties": false, - "description": "A model environment's settings were updated.", + "description": "An API key was created.", "properties": { - "schedules": { - "anyOf": [ - { - "items": { - "$ref": "#/components/schemas/AuditLogEventAutoscalingScheduleChangeV1" - }, - "type": "array" - }, + "event_type": { + "const": "API_KEY_CREATED", + "title": "Event Type", + "type": "string" + }, + "api_key_id": { + "title": "Api Key Id", + "type": "string" + }, + "api_key_type": { + "$ref": "#/components/schemas/AuditLogApiKeyTypeV1" + }, + "prefix": { + "title": "Prefix", + "type": "string" + } + }, + "required": [ + "event_type", + "api_key_id", + "api_key_type", + "prefix" + ], + "title": "AuditLogEventApiKeyCreatedV1", + "type": "object" + }, + "AuditLogEventApiKeyDeletedV1": { + "additionalProperties": false, + "description": "An API key was revoked.", + "properties": { + "event_type": { + "const": "API_KEY_DELETED", + "title": "Event Type", + "type": "string" + }, + "api_key_id": { + "title": "Api Key Id", + "type": "string" + }, + "api_key_type": { + "$ref": "#/components/schemas/AuditLogApiKeyTypeV1" + }, + "prefix": { + "title": "Prefix", + "type": "string" + } + }, + "required": [ + "event_type", + "api_key_id", + "api_key_type", + "prefix" + ], + "title": "AuditLogEventApiKeyDeletedV1", + "type": "object" + }, + "AuditLogEventAutoscalingScheduleActionV1": { + "description": "What an autoscaling change did to one schedule.", + "enum": [ + "CREATED", + "UPDATED", + "DELETED", + "UNCHANGED" + ], + "title": "AuditLogEventAutoscalingScheduleActionV1", + "type": "string" + }, + "AuditLogEventAutoscalingScheduleChangeV1": { + "additionalProperties": false, + "description": "What an autoscaling change did to one schedule, and the schedule on either side of it.\n`previous` is null on a create, `current` on a delete, and an unchanged schedule carries only\n`current`. Not itself a payload in the discriminated union.", + "properties": { + "action": { + "$ref": "#/components/schemas/AuditLogEventAutoscalingScheduleActionV1" + }, + "schedule_id": { + "title": "Schedule Id", + "type": "string" + }, + "previous": { + "anyOf": [ + { + "$ref": "#/components/schemas/AuditLogEventAutoscalingScheduleSettingsV1" + }, { "type": "null" } - ], - "title": "Schedules" + ] }, + "current": { + "anyOf": [ + { + "$ref": "#/components/schemas/AuditLogEventAutoscalingScheduleSettingsV1" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "action", + "schedule_id", + "previous", + "current" + ], + "title": "AuditLogEventAutoscalingScheduleChangeV1", + "type": "object" + }, + "AuditLogEventAutoscalingScheduleSettingsV1": { + "additionalProperties": false, + "description": "One autoscaling schedule's timing and autoscaling settings. Not itself a union payload.", + "properties": { "min_replica": { "title": "Min Replica", "type": "integer" @@ -13036,8 +14207,15 @@ "type": "integer" }, "concurrency_target": { - "title": "Concurrency Target", - "type": "integer" + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Concurrency Target" }, "autoscaling_window": { "anyOf": [ @@ -13094,29 +14272,3146 @@ ], "title": "Max Scale Down Rate" }, - "redeploy_on_promotion": { + "schedule_name": { + "title": "Schedule Name", + "type": "string" + }, + "enabled": { + "title": "Enabled", + "type": "boolean" + }, + "cadence": { + "title": "Cadence", + "type": "string" + }, + "timezone": { + "title": "Timezone", + "type": "string" + }, + "weekdays": { "anyOf": [ { - "type": "boolean" + "items": { + "type": "string" + }, + "type": "array" }, { "type": "null" } ], - "title": "Redeploy On Promotion" + "title": "Weekdays" }, - "rolling_deploy": { + "start_hour": { "anyOf": [ { - "type": "boolean" + "type": "integer" }, { "type": "null" } ], - "title": "Rolling Deploy" + "title": "Start Hour" }, - "rolling_deploy_strategy": { + "start_minute": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Start Minute" + }, + "end_hour": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "End Hour" + }, + "end_minute": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "End Minute" + }, + "start_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Start At" + }, + "end_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "End At" + } + }, + "required": [ + "min_replica", + "max_replica", + "concurrency_target", + "autoscaling_window", + "scale_down_delay", + "target_utilization_percentage", + "target_in_flight_tokens", + "max_scale_down_rate", + "schedule_name", + "enabled", + "cadence", + "timezone", + "weekdays", + "start_hour", + "start_minute", + "end_hour", + "end_minute" + ], + "title": "AuditLogEventAutoscalingScheduleSettingsV1", + "type": "object" + }, + "AuditLogEventAutoscalingSettingsV1": { + "additionalProperties": false, + "description": "Autoscaling settings for a deployment or environment.", + "properties": { + "min_replica": { + "title": "Min Replica", + "type": "integer" + }, + "max_replica": { + "title": "Max Replica", + "type": "integer" + }, + "concurrency_target": { + "title": "Concurrency Target", + "type": "integer" + }, + "autoscaling_window": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Autoscaling Window" + }, + "scale_down_delay": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Scale Down Delay" + }, + "target_utilization_percentage": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Target Utilization Percentage" + }, + "target_in_flight_tokens": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Target In Flight Tokens" + }, + "max_scale_down_rate": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Max Scale Down Rate" + } + }, + "required": [ + "min_replica", + "max_replica", + "concurrency_target", + "autoscaling_window", + "scale_down_delay", + "target_utilization_percentage", + "target_in_flight_tokens", + "max_scale_down_rate" + ], + "title": "AuditLogEventAutoscalingSettingsV1", + "type": "object" + }, + "AuditLogEventChainDeletedV1": { + "additionalProperties": false, + "description": "A chain was deleted.", + "properties": { + "event_type": { + "const": "CHAIN_DELETED", + "title": "Event Type", + "type": "string" + }, + "chain_id": { + "title": "Chain Id", + "type": "string" + }, + "chain_name": { + "title": "Chain Name", + "type": "string" + }, + "chain_deployment_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Chain Deployment Name" + } + }, + "required": [ + "event_type", + "chain_id", + "chain_name", + "chain_deployment_name" + ], + "title": "AuditLogEventChainDeletedV1", + "type": "object" + }, + "AuditLogEventChainDeployedV1": { + "additionalProperties": false, + "description": "A chain deployment was created.", + "properties": { + "event_type": { + "const": "CHAIN_DEPLOYED", + "title": "Event Type", + "type": "string" + }, + "chain_id": { + "title": "Chain Id", + "type": "string" + }, + "chain_name": { + "title": "Chain Name", + "type": "string" + }, + "chain_deployment_id": { + "title": "Chain Deployment Id", + "type": "string" + }, + "chain_deployment_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Chain Deployment Name" + }, + "is_primary": { + "title": "Is Primary", + "type": "boolean" + }, + "publish": { + "title": "Publish", + "type": "boolean" + } + }, + "required": [ + "event_type", + "chain_id", + "chain_name", + "chain_deployment_id", + "chain_deployment_name", + "is_primary", + "publish" + ], + "title": "AuditLogEventChainDeployedV1", + "type": "object" + }, + "AuditLogEventChainDeploymentActivatedV1": { + "additionalProperties": false, + "description": "A chain deployment was activated.", + "properties": { + "event_type": { + "const": "CHAIN_DEPLOYMENT_ACTIVATED", + "title": "Event Type", + "type": "string" + }, + "chain_id": { + "title": "Chain Id", + "type": "string" + }, + "chain_name": { + "title": "Chain Name", + "type": "string" + }, + "chain_deployment_id": { + "title": "Chain Deployment Id", + "type": "string" + }, + "chain_deployment_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Chain Deployment Name" + } + }, + "required": [ + "event_type", + "chain_id", + "chain_name", + "chain_deployment_id", + "chain_deployment_name" + ], + "title": "AuditLogEventChainDeploymentActivatedV1", + "type": "object" + }, + "AuditLogEventChainDeploymentDeactivatedV1": { + "additionalProperties": false, + "description": "A chain deployment was deactivated.", + "properties": { + "event_type": { + "const": "CHAIN_DEPLOYMENT_DEACTIVATED", + "title": "Event Type", + "type": "string" + }, + "chain_id": { + "title": "Chain Id", + "type": "string" + }, + "chain_name": { + "title": "Chain Name", + "type": "string" + }, + "chain_deployment_id": { + "title": "Chain Deployment Id", + "type": "string" + }, + "chain_deployment_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Chain Deployment Name" + } + }, + "required": [ + "event_type", + "chain_id", + "chain_name", + "chain_deployment_id", + "chain_deployment_name" + ], + "title": "AuditLogEventChainDeploymentDeactivatedV1", + "type": "object" + }, + "AuditLogEventChainDeploymentDeletedV1": { + "additionalProperties": false, + "description": "A chain deployment was deleted.", + "properties": { + "event_type": { + "const": "CHAIN_DEPLOYMENT_DELETED", + "title": "Event Type", + "type": "string" + }, + "chain_id": { + "title": "Chain Id", + "type": "string" + }, + "chain_name": { + "title": "Chain Name", + "type": "string" + }, + "chain_deployment_id": { + "title": "Chain Deployment Id", + "type": "string" + }, + "deployment_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Deployment Name" + } + }, + "required": [ + "event_type", + "chain_id", + "chain_name", + "chain_deployment_id", + "deployment_name" + ], + "title": "AuditLogEventChainDeploymentDeletedV1", + "type": "object" + }, + "AuditLogEventChainDeploymentPromotedV1": { + "additionalProperties": false, + "description": "A chain deployment was promoted to an environment.", + "properties": { + "event_type": { + "const": "CHAIN_DEPLOYMENT_PROMOTED", + "title": "Event Type", + "type": "string" + }, + "chain_id": { + "title": "Chain Id", + "type": "string" + }, + "chain_name": { + "title": "Chain Name", + "type": "string" + }, + "chain_deployment_id": { + "title": "Chain Deployment Id", + "type": "string" + }, + "chain_deployment_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Chain Deployment Name" + }, + "environment_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Environment Name" + }, + "environment_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Environment Id" + } + }, + "required": [ + "event_type", + "chain_id", + "chain_name", + "chain_deployment_id", + "chain_deployment_name", + "environment_name", + "environment_id" + ], + "title": "AuditLogEventChainDeploymentPromotedV1", + "type": "object" + }, + "AuditLogEventChainEnvironmentCreatedV1": { + "additionalProperties": false, + "description": "A chain environment was created.", + "properties": { + "event_type": { + "const": "CHAIN_ENVIRONMENT_CREATED", + "title": "Event Type", + "type": "string" + }, + "chain_id": { + "title": "Chain Id", + "type": "string" + }, + "chain_name": { + "title": "Chain Name", + "type": "string" + }, + "environment_name": { + "title": "Environment Name", + "type": "string" + }, + "redeploy_on_promotion": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Redeploy On Promotion" + }, + "ramp_up_while_promoting": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Ramp Up While Promoting" + }, + "ramp_up_duration_seconds": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Ramp Up Duration Seconds" + } + }, + "required": [ + "event_type", + "chain_id", + "chain_name", + "environment_name", + "redeploy_on_promotion", + "ramp_up_while_promoting", + "ramp_up_duration_seconds" + ], + "title": "AuditLogEventChainEnvironmentCreatedV1", + "type": "object" + }, + "AuditLogEventChainEnvironmentUpdatedV1": { + "additionalProperties": false, + "description": "A chain environment was updated.", + "properties": { + "event_type": { + "const": "CHAIN_ENVIRONMENT_UPDATED", + "title": "Event Type", + "type": "string" + }, + "chain_id": { + "title": "Chain Id", + "type": "string" + }, + "chain_name": { + "title": "Chain Name", + "type": "string" + }, + "environment_name": { + "title": "Environment Name", + "type": "string" + }, + "redeploy_on_promotion": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Redeploy On Promotion" + }, + "ramp_up_while_promoting": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Ramp Up While Promoting" + }, + "ramp_up_duration_seconds": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Ramp Up Duration Seconds" + } + }, + "required": [ + "event_type", + "chain_id", + "chain_name", + "environment_name", + "redeploy_on_promotion", + "ramp_up_while_promoting", + "ramp_up_duration_seconds" + ], + "title": "AuditLogEventChainEnvironmentUpdatedV1", + "type": "object" + }, + "AuditLogEventChainletAutoscalingSettingsChangedV1": { + "additionalProperties": false, + "description": "A chainlet's autoscaling settings were changed.", + "properties": { + "min_replica": { + "title": "Min Replica", + "type": "integer" + }, + "max_replica": { + "title": "Max Replica", + "type": "integer" + }, + "concurrency_target": { + "title": "Concurrency Target", + "type": "integer" + }, + "autoscaling_window": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Autoscaling Window" + }, + "scale_down_delay": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Scale Down Delay" + }, + "target_utilization_percentage": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Target Utilization Percentage" + }, + "target_in_flight_tokens": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Target In Flight Tokens" + }, + "max_scale_down_rate": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Max Scale Down Rate" + }, + "event_type": { + "const": "CHAINLET_AUTOSCALING_SETTINGS_CHANGED", + "title": "Event Type", + "type": "string" + }, + "chain_id": { + "title": "Chain Id", + "type": "string" + }, + "chain_name": { + "title": "Chain Name", + "type": "string" + }, + "chain_deployment_id": { + "title": "Chain Deployment Id", + "type": "string" + }, + "chain_deployment_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Chain Deployment Name" + }, + "chainlet_name": { + "title": "Chainlet Name", + "type": "string" + }, + "chainlet_id": { + "title": "Chainlet Id", + "type": "string" + }, + "previous_settings": { + "anyOf": [ + { + "$ref": "#/components/schemas/AuditLogEventAutoscalingSettingsV1" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "min_replica", + "max_replica", + "concurrency_target", + "autoscaling_window", + "scale_down_delay", + "target_utilization_percentage", + "target_in_flight_tokens", + "max_scale_down_rate", + "event_type", + "chain_id", + "chain_name", + "chain_deployment_id", + "chain_deployment_name", + "chainlet_name", + "chainlet_id", + "previous_settings" + ], + "title": "AuditLogEventChainletAutoscalingSettingsChangedV1", + "type": "object" + }, + "AuditLogEventChainletInstanceTypeChangedV1": { + "additionalProperties": false, + "description": "A chainlet's instance type was changed.", + "properties": { + "event_type": { + "const": "CHAINLET_INSTANCE_TYPE_CHANGED", + "title": "Event Type", + "type": "string" + }, + "chain_id": { + "title": "Chain Id", + "type": "string" + }, + "chain_name": { + "title": "Chain Name", + "type": "string" + }, + "chain_deployment_id": { + "title": "Chain Deployment Id", + "type": "string" + }, + "chain_deployment_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Chain Deployment Name" + }, + "chainlet_name": { + "title": "Chainlet Name", + "type": "string" + }, + "chainlet_id": { + "title": "Chainlet Id", + "type": "string" + }, + "instance_type_name": { + "title": "Instance Type Name", + "type": "string" + } + }, + "required": [ + "event_type", + "chain_id", + "chain_name", + "chain_deployment_id", + "chain_deployment_name", + "chainlet_name", + "chainlet_id", + "instance_type_name" + ], + "title": "AuditLogEventChainletInstanceTypeChangedV1", + "type": "object" + }, + "AuditLogEventDirectoryGroupRoleUpdatedV1": { + "additionalProperties": false, + "description": "A directory group's role was updated.", + "properties": { + "event_type": { + "const": "DIRECTORY_GROUP_ROLE_UPDATED", + "title": "Event Type", + "type": "string" + }, + "directory_group_id": { + "title": "Directory Group Id", + "type": "string" + }, + "directory_group_name": { + "title": "Directory Group Name", + "type": "string" + }, + "new_role_name": { + "title": "New Role Name", + "type": "string" + }, + "team_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Team Id" + }, + "team_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Team Name" + } + }, + "required": [ + "event_type", + "directory_group_id", + "directory_group_name", + "new_role_name", + "team_id", + "team_name" + ], + "title": "AuditLogEventDirectoryGroupRoleUpdatedV1", + "type": "object" + }, + "AuditLogEventEnvironmentCreatedV1": { + "additionalProperties": false, + "description": "A model environment was created.", + "properties": { + "min_replica": { + "title": "Min Replica", + "type": "integer" + }, + "max_replica": { + "title": "Max Replica", + "type": "integer" + }, + "concurrency_target": { + "title": "Concurrency Target", + "type": "integer" + }, + "autoscaling_window": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Autoscaling Window" + }, + "scale_down_delay": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Scale Down Delay" + }, + "target_utilization_percentage": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Target Utilization Percentage" + }, + "target_in_flight_tokens": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Target In Flight Tokens" + }, + "max_scale_down_rate": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Max Scale Down Rate" + }, + "redeploy_on_promotion": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Redeploy On Promotion" + }, + "rolling_deploy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Rolling Deploy" + }, + "rolling_deploy_strategy": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Rolling Deploy Strategy" + }, + "max_unavailable_percent": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Max Unavailable Percent" + }, + "max_surge_percent": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Max Surge Percent" + }, + "stabilization_time_seconds": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Stabilization Time Seconds" + }, + "replica_overhead_percent": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Replica Overhead Percent" + }, + "promotion_cleanup_strategy": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Promotion Cleanup Strategy" + }, + "ramp_up_while_promoting": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Ramp Up While Promoting" + }, + "ramp_up_duration_seconds": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Ramp Up Duration Seconds" + }, + "ramp_up_step_size": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Ramp Up Step Size" + }, + "request_backpressure_policy": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Request Backpressure Policy" + }, + "model_id": { + "title": "Model Id", + "type": "string" + }, + "model_name": { + "title": "Model Name", + "type": "string" + }, + "environment_name": { + "title": "Environment Name", + "type": "string" + }, + "deployment_type": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Deployment Type" + }, + "event_type": { + "const": "ENVIRONMENT_CREATED", + "title": "Event Type", + "type": "string" + } + }, + "required": [ + "min_replica", + "max_replica", + "concurrency_target", + "autoscaling_window", + "scale_down_delay", + "target_utilization_percentage", + "target_in_flight_tokens", + "max_scale_down_rate", + "redeploy_on_promotion", + "rolling_deploy", + "rolling_deploy_strategy", + "max_unavailable_percent", + "max_surge_percent", + "stabilization_time_seconds", + "replica_overhead_percent", + "promotion_cleanup_strategy", + "ramp_up_while_promoting", + "ramp_up_duration_seconds", + "ramp_up_step_size", + "model_id", + "model_name", + "environment_name", + "deployment_type", + "event_type" + ], + "title": "AuditLogEventEnvironmentCreatedV1", + "type": "object" + }, + "AuditLogEventEnvironmentDeletedV1": { + "additionalProperties": false, + "description": "A model environment was deleted.", + "properties": { + "event_type": { + "const": "ENVIRONMENT_DELETED", + "title": "Event Type", + "type": "string" + }, + "model_id": { + "title": "Model Id", + "type": "string" + }, + "model_name": { + "title": "Model Name", + "type": "string" + }, + "environment_name": { + "title": "Environment Name", + "type": "string" + } + }, + "required": [ + "event_type", + "model_id", + "model_name", + "environment_name" + ], + "title": "AuditLogEventEnvironmentDeletedV1", + "type": "object" + }, + "AuditLogEventEnvironmentSettingsV1": { + "additionalProperties": false, + "description": "Full environment settings (autoscaling + rolling promotion + deprecated canary);\nshared base for the environment events and the type of their previous_settings\nsnapshots. Not itself a payload in the discriminated union.", + "properties": { + "min_replica": { + "title": "Min Replica", + "type": "integer" + }, + "max_replica": { + "title": "Max Replica", + "type": "integer" + }, + "concurrency_target": { + "title": "Concurrency Target", + "type": "integer" + }, + "autoscaling_window": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Autoscaling Window" + }, + "scale_down_delay": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Scale Down Delay" + }, + "target_utilization_percentage": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Target Utilization Percentage" + }, + "target_in_flight_tokens": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Target In Flight Tokens" + }, + "max_scale_down_rate": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Max Scale Down Rate" + }, + "redeploy_on_promotion": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Redeploy On Promotion" + }, + "rolling_deploy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Rolling Deploy" + }, + "rolling_deploy_strategy": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Rolling Deploy Strategy" + }, + "max_unavailable_percent": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Max Unavailable Percent" + }, + "max_surge_percent": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Max Surge Percent" + }, + "stabilization_time_seconds": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Stabilization Time Seconds" + }, + "replica_overhead_percent": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Replica Overhead Percent" + }, + "promotion_cleanup_strategy": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Promotion Cleanup Strategy" + }, + "ramp_up_while_promoting": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Ramp Up While Promoting" + }, + "ramp_up_duration_seconds": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Ramp Up Duration Seconds" + }, + "ramp_up_step_size": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Ramp Up Step Size" + }, + "request_backpressure_policy": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Request Backpressure Policy" + } + }, + "required": [ + "min_replica", + "max_replica", + "concurrency_target", + "autoscaling_window", + "scale_down_delay", + "target_utilization_percentage", + "target_in_flight_tokens", + "max_scale_down_rate", + "redeploy_on_promotion", + "rolling_deploy", + "rolling_deploy_strategy", + "max_unavailable_percent", + "max_surge_percent", + "stabilization_time_seconds", + "replica_overhead_percent", + "promotion_cleanup_strategy", + "ramp_up_while_promoting", + "ramp_up_duration_seconds", + "ramp_up_step_size" + ], + "title": "AuditLogEventEnvironmentSettingsV1", + "type": "object" + }, + "AuditLogEventEnvironmentUpdatedV1": { + "additionalProperties": false, + "description": "A model environment's settings were updated.", + "properties": { + "schedules": { + "anyOf": [ + { + "items": { + "$ref": "#/components/schemas/AuditLogEventAutoscalingScheduleChangeV1" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Schedules" + }, + "min_replica": { + "title": "Min Replica", + "type": "integer" + }, + "max_replica": { + "title": "Max Replica", + "type": "integer" + }, + "concurrency_target": { + "title": "Concurrency Target", + "type": "integer" + }, + "autoscaling_window": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Autoscaling Window" + }, + "scale_down_delay": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Scale Down Delay" + }, + "target_utilization_percentage": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Target Utilization Percentage" + }, + "target_in_flight_tokens": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Target In Flight Tokens" + }, + "max_scale_down_rate": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Max Scale Down Rate" + }, + "redeploy_on_promotion": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Redeploy On Promotion" + }, + "rolling_deploy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Rolling Deploy" + }, + "rolling_deploy_strategy": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Rolling Deploy Strategy" + }, + "max_unavailable_percent": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Max Unavailable Percent" + }, + "max_surge_percent": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Max Surge Percent" + }, + "stabilization_time_seconds": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Stabilization Time Seconds" + }, + "replica_overhead_percent": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Replica Overhead Percent" + }, + "promotion_cleanup_strategy": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Promotion Cleanup Strategy" + }, + "ramp_up_while_promoting": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Ramp Up While Promoting" + }, + "ramp_up_duration_seconds": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Ramp Up Duration Seconds" + }, + "ramp_up_step_size": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Ramp Up Step Size" + }, + "request_backpressure_policy": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Request Backpressure Policy" + }, + "model_id": { + "title": "Model Id", + "type": "string" + }, + "model_name": { + "title": "Model Name", + "type": "string" + }, + "environment_name": { + "title": "Environment Name", + "type": "string" + }, + "deployment_type": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Deployment Type" + }, + "event_type": { + "const": "ENVIRONMENT_UPDATED", + "title": "Event Type", + "type": "string" + }, + "previous_settings": { + "anyOf": [ + { + "$ref": "#/components/schemas/AuditLogEventEnvironmentSettingsV1" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "schedules", + "min_replica", + "max_replica", + "concurrency_target", + "autoscaling_window", + "scale_down_delay", + "target_utilization_percentage", + "target_in_flight_tokens", + "max_scale_down_rate", + "redeploy_on_promotion", + "rolling_deploy", + "rolling_deploy_strategy", + "max_unavailable_percent", + "max_surge_percent", + "stabilization_time_seconds", + "replica_overhead_percent", + "promotion_cleanup_strategy", + "ramp_up_while_promoting", + "ramp_up_duration_seconds", + "ramp_up_step_size", + "model_id", + "model_name", + "environment_name", + "deployment_type", + "event_type", + "previous_settings" + ], + "title": "AuditLogEventEnvironmentUpdatedV1", + "type": "object" + }, + "AuditLogEventGatewayEndpointCreatedV1": { + "additionalProperties": false, + "description": "A Frontier Gateway endpoint was created.", + "properties": { + "event_type": { + "const": "GATEWAY_ENDPOINT_CREATED", + "title": "Event Type", + "type": "string" + }, + "gateway_endpoint_id": { + "title": "Gateway Endpoint Id", + "type": "string" + }, + "slug": { + "title": "Slug", + "type": "string" + } + }, + "required": [ + "event_type", + "gateway_endpoint_id", + "slug" + ], + "title": "AuditLogEventGatewayEndpointCreatedV1", + "type": "object" + }, + "AuditLogEventGatewayEndpointDeletedV1": { + "additionalProperties": false, + "description": "A Frontier Gateway endpoint was deleted.", + "properties": { + "event_type": { + "const": "GATEWAY_ENDPOINT_DELETED", + "title": "Event Type", + "type": "string" + }, + "gateway_endpoint_id": { + "title": "Gateway Endpoint Id", + "type": "string" + }, + "slug": { + "title": "Slug", + "type": "string" + } + }, + "required": [ + "event_type", + "gateway_endpoint_id", + "slug" + ], + "title": "AuditLogEventGatewayEndpointDeletedV1", + "type": "object" + }, + "AuditLogEventGatewayEndpointUpdatedV1": { + "additionalProperties": false, + "description": "A Frontier Gateway endpoint was updated.", + "properties": { + "event_type": { + "const": "GATEWAY_ENDPOINT_UPDATED", + "title": "Event Type", + "type": "string" + }, + "gateway_endpoint_id": { + "title": "Gateway Endpoint Id", + "type": "string" + }, + "slug": { + "title": "Slug", + "type": "string" + }, + "previous_slug": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Previous Slug" + } + }, + "required": [ + "event_type", + "gateway_endpoint_id", + "slug", + "previous_slug" + ], + "title": "AuditLogEventGatewayEndpointUpdatedV1", + "type": "object" + }, + "AuditLogEventModelDeletedV1": { + "additionalProperties": false, + "description": "A model was deleted.", + "properties": { + "event_type": { + "const": "MODEL_DELETED", + "title": "Event Type", + "type": "string" + }, + "model_id": { + "title": "Model Id", + "type": "string" + }, + "model_name": { + "title": "Model Name", + "type": "string" + } + }, + "required": [ + "event_type", + "model_id", + "model_name" + ], + "title": "AuditLogEventModelDeletedV1", + "type": "object" + }, + "AuditLogEventModelDeployedV1": { + "additionalProperties": false, + "description": "A model deployment was created.", + "properties": { + "event_type": { + "const": "MODEL_DEPLOYED", + "title": "Event Type", + "type": "string" + }, + "model_id": { + "title": "Model Id", + "type": "string" + }, + "model_name": { + "title": "Model Name", + "type": "string" + }, + "deployment_id": { + "title": "Deployment Id", + "type": "string" + }, + "deployment_name": { + "title": "Deployment Name", + "type": "string" + }, + "scale_previous_to_zero": { + "title": "Scale Previous To Zero", + "type": "boolean" + }, + "trusted": { + "title": "Trusted", + "type": "boolean" + }, + "publish": { + "title": "Publish", + "type": "boolean" + }, + "environment_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Environment Name" + } + }, + "required": [ + "event_type", + "model_id", + "model_name", + "deployment_id", + "deployment_name", + "scale_previous_to_zero", + "trusted", + "publish", + "environment_name" + ], + "title": "AuditLogEventModelDeployedV1", + "type": "object" + }, + "AuditLogEventModelDeploymentActivatedV1": { + "additionalProperties": false, + "description": "A model deployment was activated.", + "properties": { + "event_type": { + "const": "MODEL_DEPLOYMENT_ACTIVATED", + "title": "Event Type", + "type": "string" + }, + "model_id": { + "title": "Model Id", + "type": "string" + }, + "model_name": { + "title": "Model Name", + "type": "string" + }, + "deployment_id": { + "title": "Deployment Id", + "type": "string" + }, + "deployment_name": { + "title": "Deployment Name", + "type": "string" + } + }, + "required": [ + "event_type", + "model_id", + "model_name", + "deployment_id", + "deployment_name" + ], + "title": "AuditLogEventModelDeploymentActivatedV1", + "type": "object" + }, + "AuditLogEventModelDeploymentAutoscalingSettingsChangedV1": { + "additionalProperties": false, + "description": "A model deployment's autoscaling settings were changed.", + "properties": { + "schedules": { + "anyOf": [ + { + "items": { + "$ref": "#/components/schemas/AuditLogEventAutoscalingScheduleChangeV1" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Schedules" + }, + "min_replica": { + "title": "Min Replica", + "type": "integer" + }, + "max_replica": { + "title": "Max Replica", + "type": "integer" + }, + "concurrency_target": { + "title": "Concurrency Target", + "type": "integer" + }, + "autoscaling_window": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Autoscaling Window" + }, + "scale_down_delay": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Scale Down Delay" + }, + "target_utilization_percentage": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Target Utilization Percentage" + }, + "target_in_flight_tokens": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Target In Flight Tokens" + }, + "max_scale_down_rate": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Max Scale Down Rate" + }, + "event_type": { + "const": "MODEL_DEPLOYMENT_AUTOSCALING_SETTINGS_CHANGED", + "title": "Event Type", + "type": "string" + }, + "model_id": { + "title": "Model Id", + "type": "string" + }, + "model_name": { + "title": "Model Name", + "type": "string" + }, + "deployment_id": { + "title": "Deployment Id", + "type": "string" + }, + "deployment_name": { + "title": "Deployment Name", + "type": "string" + }, + "deployment_type": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Deployment Type" + }, + "previous_settings": { + "anyOf": [ + { + "$ref": "#/components/schemas/AuditLogEventAutoscalingSettingsV1" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "schedules", + "min_replica", + "max_replica", + "concurrency_target", + "autoscaling_window", + "scale_down_delay", + "target_utilization_percentage", + "target_in_flight_tokens", + "max_scale_down_rate", + "event_type", + "model_id", + "model_name", + "deployment_id", + "deployment_name", + "deployment_type", + "previous_settings" + ], + "title": "AuditLogEventModelDeploymentAutoscalingSettingsChangedV1", + "type": "object" + }, + "AuditLogEventModelDeploymentDeactivatedV1": { + "additionalProperties": false, + "description": "A model deployment was deactivated.", + "properties": { + "event_type": { + "const": "MODEL_DEPLOYMENT_DEACTIVATED", + "title": "Event Type", + "type": "string" + }, + "model_id": { + "title": "Model Id", + "type": "string" + }, + "model_name": { + "title": "Model Name", + "type": "string" + }, + "deployment_id": { + "title": "Deployment Id", + "type": "string" + }, + "deployment_name": { + "title": "Deployment Name", + "type": "string" + } + }, + "required": [ + "event_type", + "model_id", + "model_name", + "deployment_id", + "deployment_name" + ], + "title": "AuditLogEventModelDeploymentDeactivatedV1", + "type": "object" + }, + "AuditLogEventModelDeploymentDeletedV1": { + "additionalProperties": false, + "description": "A model deployment was deleted.", + "properties": { + "event_type": { + "const": "MODEL_DEPLOYMENT_DELETED", + "title": "Event Type", + "type": "string" + }, + "model_id": { + "title": "Model Id", + "type": "string" + }, + "model_name": { + "title": "Model Name", + "type": "string" + }, + "deployment_id": { + "title": "Deployment Id", + "type": "string" + }, + "deployment_name": { + "title": "Deployment Name", + "type": "string" + } + }, + "required": [ + "event_type", + "model_id", + "model_name", + "deployment_id", + "deployment_name" + ], + "title": "AuditLogEventModelDeploymentDeletedV1", + "type": "object" + }, + "AuditLogEventModelDeploymentInstanceTypeChangedV1": { + "additionalProperties": false, + "description": "A model deployment's instance type was changed.", + "properties": { + "event_type": { + "const": "MODEL_DEPLOYMENT_INSTANCE_TYPE_CHANGED", + "title": "Event Type", + "type": "string" + }, + "model_id": { + "title": "Model Id", + "type": "string" + }, + "model_name": { + "title": "Model Name", + "type": "string" + }, + "deployment_id": { + "title": "Deployment Id", + "type": "string" + }, + "deployment_name": { + "title": "Deployment Name", + "type": "string" + }, + "instance_type_name": { + "title": "Instance Type Name", + "type": "string" + } + }, + "required": [ + "event_type", + "model_id", + "model_name", + "deployment_id", + "deployment_name", + "instance_type_name" + ], + "title": "AuditLogEventModelDeploymentInstanceTypeChangedV1", + "type": "object" + }, + "AuditLogEventModelDeploymentPromotedV1": { + "additionalProperties": false, + "description": "A model deployment was promoted to an environment.", + "properties": { + "event_type": { + "const": "MODEL_DEPLOYMENT_PROMOTED", + "title": "Event Type", + "type": "string" + }, + "model_id": { + "title": "Model Id", + "type": "string" + }, + "model_name": { + "title": "Model Name", + "type": "string" + }, + "deployment_id": { + "title": "Deployment Id", + "type": "string" + }, + "deployment_name": { + "title": "Deployment Name", + "type": "string" + }, + "environment_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Environment Name" + }, + "environment_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Environment Id" + } + }, + "required": [ + "event_type", + "model_id", + "model_name", + "deployment_id", + "deployment_name", + "environment_name", + "environment_id" + ], + "title": "AuditLogEventModelDeploymentPromotedV1", + "type": "object" + }, + "AuditLogEventModelDeploymentRequestBackpressureSettingsChangedV1": { + "additionalProperties": false, + "description": "A model deployment's request backpressure settings were changed.", + "properties": { + "event_type": { + "const": "MODEL_DEPLOYMENT_REQUEST_BACKPRESSURE_SETTINGS_CHANGED", + "title": "Event Type", + "type": "string" + }, + "model_id": { + "title": "Model Id", + "type": "string" + }, + "model_name": { + "title": "Model Name", + "type": "string" + }, + "deployment_id": { + "title": "Deployment Id", + "type": "string" + }, + "deployment_name": { + "title": "Deployment Name", + "type": "string" + }, + "policy": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Policy" + }, + "previous_policy": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Previous Policy" + } + }, + "required": [ + "event_type", + "model_id", + "model_name", + "deployment_id", + "deployment_name" + ], + "title": "AuditLogEventModelDeploymentRequestBackpressureSettingsChangedV1", + "type": "object" + }, + "AuditLogEventModelDeploymentRetriedV1": { + "additionalProperties": false, + "description": "A model deployment build was retried.", + "properties": { + "event_type": { + "const": "MODEL_DEPLOYMENT_RETRIED", + "title": "Event Type", + "type": "string" + }, + "model_id": { + "title": "Model Id", + "type": "string" + }, + "model_name": { + "title": "Model Name", + "type": "string" + }, + "deployment_id": { + "title": "Deployment Id", + "type": "string" + }, + "deployment_name": { + "title": "Deployment Name", + "type": "string" + }, + "retried": { + "title": "Retried", + "type": "boolean" + } + }, + "required": [ + "event_type", + "model_id", + "model_name", + "deployment_id", + "deployment_name", + "retried" + ], + "title": "AuditLogEventModelDeploymentRetriedV1", + "type": "object" + }, + "AuditLogEventModelPromotionControlActionV1": { + "additionalProperties": false, + "description": "A user-initiated promotion control signal was sent to a rolling promotion.", + "properties": { + "event_type": { + "const": "MODEL_PROMOTION_CONTROL_ACTION", + "title": "Event Type", + "type": "string" + }, + "model_id": { + "title": "Model Id", + "type": "string" + }, + "model_name": { + "title": "Model Name", + "type": "string" + }, + "deployment_id": { + "title": "Deployment Id", + "type": "string" + }, + "deployment_name": { + "title": "Deployment Name", + "type": "string" + }, + "environment_name": { + "title": "Environment Name", + "type": "string" + }, + "environment_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Environment Id" + }, + "action": { + "$ref": "#/components/schemas/AuditLogPromotionControlActionV1" + } + }, + "required": [ + "event_type", + "model_id", + "model_name", + "deployment_id", + "deployment_name", + "environment_name", + "environment_id", + "action" + ], + "title": "AuditLogEventModelPromotionControlActionV1", + "type": "object" + }, + "AuditLogEventModelRenamedV1": { + "additionalProperties": false, + "description": "A model was renamed. `model_name` is the new name.", + "properties": { + "event_type": { + "const": "MODEL_RENAMED", + "title": "Event Type", + "type": "string" + }, + "model_id": { + "title": "Model Id", + "type": "string" + }, + "model_name": { + "title": "Model Name", + "type": "string" + }, + "previous_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Previous Name" + } + }, + "required": [ + "event_type", + "model_id", + "model_name", + "previous_name" + ], + "title": "AuditLogEventModelRenamedV1", + "type": "object" + }, + "AuditLogEventProviderConnectionCreatedV1": { + "additionalProperties": false, + "properties": { + "event_type": { + "const": "PROVIDER_CONNECTION_CREATED", + "title": "Event Type", + "type": "string" + }, + "provider_connection_id": { + "title": "Provider Connection Id", + "type": "string" + }, + "provider": { + "title": "Provider", + "type": "string" + }, + "secret_name": { + "title": "Secret Name", + "type": "string" + } + }, + "required": [ + "event_type", + "provider_connection_id", + "provider", + "secret_name" + ], + "title": "AuditLogEventProviderConnectionCreatedV1", + "type": "object" + }, + "AuditLogEventProviderConnectionDeletedV1": { + "additionalProperties": false, + "properties": { + "event_type": { + "const": "PROVIDER_CONNECTION_DELETED", + "title": "Event Type", + "type": "string" + }, + "provider_connection_id": { + "title": "Provider Connection Id", + "type": "string" + }, + "provider": { + "title": "Provider", + "type": "string" + }, + "secret_name": { + "title": "Secret Name", + "type": "string" + } + }, + "required": [ + "event_type", + "provider_connection_id", + "provider", + "secret_name" + ], + "title": "AuditLogEventProviderConnectionDeletedV1", + "type": "object" + }, + "AuditLogEventProviderConnectionUpdatedV1": { + "additionalProperties": false, + "properties": { + "event_type": { + "const": "PROVIDER_CONNECTION_UPDATED", + "title": "Event Type", + "type": "string" + }, + "provider_connection_id": { + "title": "Provider Connection Id", + "type": "string" + }, + "provider": { + "title": "Provider", + "type": "string" + }, + "secret_name": { + "title": "Secret Name", + "type": "string" + } + }, + "required": [ + "event_type", + "provider_connection_id", + "provider", + "secret_name" + ], + "title": "AuditLogEventProviderConnectionUpdatedV1", + "type": "object" + }, + "AuditLogEventReplicaTerminatedV1": { + "additionalProperties": false, + "description": "A replica of a model deployment was terminated.", + "properties": { + "event_type": { + "const": "REPLICA_TERMINATED", + "title": "Event Type", + "type": "string" + }, + "model_id": { + "title": "Model Id", + "type": "string" + }, + "model_name": { + "title": "Model Name", + "type": "string" + }, + "deployment_id": { + "title": "Deployment Id", + "type": "string" + }, + "deployment_name": { + "title": "Deployment Name", + "type": "string" + }, + "replica_id": { + "title": "Replica Id", + "type": "string" + } + }, + "required": [ + "event_type", + "model_id", + "model_name", + "deployment_id", + "deployment_name", + "replica_id" + ], + "title": "AuditLogEventReplicaTerminatedV1", + "type": "object" + }, + "AuditLogEventRequireGroupBasedAdminsEnabledV1": { + "additionalProperties": false, + "description": "Group-based admin enforcement was enabled for the organization.", + "properties": { + "event_type": { + "const": "REQUIRE_GROUP_BASED_ADMINS_ENABLED", + "title": "Event Type", + "type": "string" + }, + "organization_id": { + "title": "Organization Id", + "type": "string" + } + }, + "required": [ + "event_type", + "organization_id" + ], + "title": "AuditLogEventRequireGroupBasedAdminsEnabledV1", + "type": "object" + }, + "AuditLogEventSecretDeletedV1": { + "additionalProperties": false, + "description": "A secret was deleted.", + "properties": { + "event_type": { + "const": "SECRET_DELETED", + "title": "Event Type", + "type": "string" + }, + "secret_id": { + "title": "Secret Id", + "type": "string" + }, + "secret_name": { + "title": "Secret Name", + "type": "string" + } + }, + "required": [ + "event_type", + "secret_id", + "secret_name" + ], + "title": "AuditLogEventSecretDeletedV1", + "type": "object" + }, + "AuditLogEventSecretUpdatedV1": { + "additionalProperties": false, + "description": "A secret was created or updated.", + "properties": { + "event_type": { + "const": "SECRET_UPDATED", + "title": "Event Type", + "type": "string" + }, + "secret_id": { + "title": "Secret Id", + "type": "string" + }, + "secret_name": { + "title": "Secret Name", + "type": "string" + } + }, + "required": [ + "event_type", + "secret_id", + "secret_name" + ], + "title": "AuditLogEventSecretUpdatedV1", + "type": "object" + }, + "AuditLogEventSshCertificateSignedV1": { + "additionalProperties": false, + "description": "An SSH certificate was signed for a workload.", + "properties": { + "event_type": { + "const": "SSH_CERTIFICATE_SIGNED", + "title": "Event Type", + "type": "string" + }, + "workload_type": { + "title": "Workload Type", + "type": "string" + }, + "workload_id": { + "title": "Workload Id", + "type": "string" + }, + "project_id": { + "title": "Project Id", + "type": "string" + }, + "replica_id": { + "title": "Replica Id", + "type": "string" + }, + "proxy_address": { + "title": "Proxy Address", + "type": "string" + }, + "expires_at": { + "title": "Expires At", + "type": "string" + } + }, + "required": [ + "event_type", + "workload_type", + "workload_id", + "project_id", + "replica_id", + "proxy_address", + "expires_at" + ], + "title": "AuditLogEventSshCertificateSignedV1", + "type": "object" + }, + "AuditLogEventTypeV1": { + "description": "Type of action recorded by an audit-log entry.", + "enum": [ + "MODEL_DEPLOYED", + "MODEL_DEPLOYMENT_ACTIVATED", + "MODEL_DEPLOYMENT_DEACTIVATED", + "MODEL_DEPLOYMENT_RETRIED", + "MODEL_DEPLOYMENT_PROMOTED", + "MODEL_DEPLOYMENT_AUTOSCALING_SETTINGS_CHANGED", + "MODEL_DEPLOYMENT_REQUEST_BACKPRESSURE_SETTINGS_CHANGED", + "MODEL_DEPLOYMENT_INSTANCE_TYPE_CHANGED", + "MODEL_DEPLOYMENT_DELETED", + "MODEL_DELETED", + "MODEL_RENAMED", + "CHAIN_DEPLOYED", + "CHAIN_DEPLOYMENT_ACTIVATED", + "CHAIN_DEPLOYMENT_DEACTIVATED", + "CHAIN_DEPLOYMENT_PROMOTED", + "CHAINLET_AUTOSCALING_SETTINGS_CHANGED", + "CHAINLET_INSTANCE_TYPE_CHANGED", + "CHAIN_DEPLOYMENT_DELETED", + "CHAIN_DELETED", + "CHAIN_ENVIRONMENT_CREATED", + "CHAIN_ENVIRONMENT_UPDATED", + "SECRET_UPDATED", + "SECRET_DELETED", + "API_KEY_CREATED", + "API_KEY_DELETED", + "GATEWAY_ENDPOINT_CREATED", + "GATEWAY_ENDPOINT_UPDATED", + "GATEWAY_ENDPOINT_DELETED", + "PROVIDER_CONNECTION_CREATED", + "PROVIDER_CONNECTION_UPDATED", + "PROVIDER_CONNECTION_DELETED", + "USER_INVITED", + "USER_JOINED_ORGANIZATION", + "WEBHOOK_SIGNING_SECRET_CREATED", + "WEBHOOK_SIGNING_SECRET_ROTATED", + "WEBHOOK_SIGNING_SECRET_DELETED", + "USER_ROLE_UPDATED", + "USER_TEAM_ROLE_UPDATED", + "USER_REMOVED", + "DIRECTORY_GROUP_ROLE_UPDATED", + "REQUIRE_GROUP_BASED_ADMINS_ENABLED", + "ENVIRONMENT_CREATED", + "ENVIRONMENT_UPDATED", + "ENVIRONMENT_DELETED", + "REPLICA_TERMINATED", + "MODEL_PROMOTION_CONTROL_ACTION", + "SSH_CERTIFICATE_SIGNED", + "VOLUME_DELETED", + "VOLUME_VERSION_DELETED", + "VOLUME_VERSION_RESTORED" + ], + "title": "AuditLogEventTypeV1", + "type": "string" + }, + "AuditLogEventUserInvitedV1": { + "additionalProperties": false, + "description": "A user was invited to the organization.", + "properties": { + "event_type": { + "const": "USER_INVITED", + "title": "Event Type", + "type": "string" + }, + "invited_user_email": { + "title": "Invited User Email", + "type": "string" + }, + "role_name": { + "title": "Role Name", + "type": "string" + } + }, + "required": [ + "event_type", + "invited_user_email", + "role_name" + ], + "title": "AuditLogEventUserInvitedV1", + "type": "object" + }, + "AuditLogEventUserJoinedOrganizationV1": { + "additionalProperties": false, + "description": "A user joined the organization.", + "properties": { + "event_type": { + "const": "USER_JOINED_ORGANIZATION", + "title": "Event Type", + "type": "string" + }, + "new_user_email": { + "title": "New User Email", + "type": "string" + }, + "user_id": { + "title": "User Id", + "type": "string" + } + }, + "required": [ + "event_type", + "new_user_email", + "user_id" + ], + "title": "AuditLogEventUserJoinedOrganizationV1", + "type": "object" + }, + "AuditLogEventUserRemovedV1": { + "additionalProperties": false, + "description": "A user was removed from the organization.", + "properties": { + "event_type": { + "const": "USER_REMOVED", + "title": "Event Type", + "type": "string" + }, + "removed_user_email": { + "title": "Removed User Email", + "type": "string" + } + }, + "required": [ + "event_type", + "removed_user_email" + ], + "title": "AuditLogEventUserRemovedV1", + "type": "object" + }, + "AuditLogEventUserRoleUpdatedV1": { + "additionalProperties": false, + "description": "A user's organization role was updated.", + "properties": { + "event_type": { + "const": "USER_ROLE_UPDATED", + "title": "Event Type", + "type": "string" + }, + "user_id": { + "title": "User Id", + "type": "string" + }, + "user_email": { + "title": "User Email", + "type": "string" + }, + "new_role_name": { + "title": "New Role Name", + "type": "string" + } + }, + "required": [ + "event_type", + "user_id", + "user_email", + "new_role_name" + ], + "title": "AuditLogEventUserRoleUpdatedV1", + "type": "object" + }, + "AuditLogEventUserTeamRoleUpdatedV1": { + "additionalProperties": false, + "description": "A user's team role was updated.", + "properties": { + "event_type": { + "const": "USER_TEAM_ROLE_UPDATED", + "title": "Event Type", + "type": "string" + }, + "user_id": { + "title": "User Id", + "type": "string" + }, + "user_email": { + "title": "User Email", + "type": "string" + }, + "team_id": { + "title": "Team Id", + "type": "string" + }, + "team_name": { + "title": "Team Name", + "type": "string" + }, + "new_role_name": { + "title": "New Role Name", + "type": "string" + } + }, + "required": [ + "event_type", + "user_id", + "user_email", + "team_id", + "team_name", + "new_role_name" + ], + "title": "AuditLogEventUserTeamRoleUpdatedV1", + "type": "object" + }, + "AuditLogEventVolumeDeletedV1": { + "additionalProperties": false, + "description": "A volume was deleted, tombstoning every version it still held.", + "properties": { + "event_type": { + "const": "VOLUME_DELETED", + "title": "Event Type", + "type": "string" + }, + "volume_ref": { + "title": "Volume Ref", + "type": "string" + }, + "namespace": { + "title": "Namespace", + "type": "string" + }, + "volume_name": { + "title": "Volume Name", + "type": "string" + }, + "versions_deleted": { + "title": "Versions Deleted", + "type": "integer" + } + }, + "required": [ + "event_type", + "volume_ref", + "namespace", + "volume_name", + "versions_deleted" + ], + "title": "AuditLogEventVolumeDeletedV1", + "type": "object" + }, + "AuditLogEventVolumeVersionDeletedV1": { + "additionalProperties": false, + "description": "One version of a volume was deleted.", + "properties": { + "event_type": { + "const": "VOLUME_VERSION_DELETED", + "title": "Event Type", + "type": "string" + }, + "volume_ref": { + "title": "Volume Ref", + "type": "string" + }, + "namespace": { + "title": "Namespace", + "type": "string" + }, + "volume_name": { + "title": "Volume Name", + "type": "string" + }, + "version": { + "title": "Version", + "type": "string" + }, + "digest": { + "title": "Digest", + "type": "string" + } + }, + "required": [ + "event_type", + "volume_ref", + "namespace", + "volume_name", + "version", + "digest" + ], + "title": "AuditLogEventVolumeVersionDeletedV1", + "type": "object" + }, + "AuditLogEventVolumeVersionRestoredV1": { + "additionalProperties": false, + "description": "A deleted version of a volume was restored.", + "properties": { + "event_type": { + "const": "VOLUME_VERSION_RESTORED", + "title": "Event Type", + "type": "string" + }, + "volume_ref": { + "title": "Volume Ref", + "type": "string" + }, + "namespace": { + "title": "Namespace", + "type": "string" + }, + "volume_name": { + "title": "Volume Name", + "type": "string" + }, + "version": { + "title": "Version", + "type": "string" + }, + "digest": { + "title": "Digest", + "type": "string" + } + }, + "required": [ + "event_type", + "volume_ref", + "namespace", + "volume_name", + "version", + "digest" + ], + "title": "AuditLogEventVolumeVersionRestoredV1", + "type": "object" + }, + "AuditLogEventWebhookSigningSecretCreatedV1": { + "additionalProperties": false, + "description": "A webhook signing secret was created.", + "properties": { + "event_type": { + "const": "WEBHOOK_SIGNING_SECRET_CREATED", + "title": "Event Type", + "type": "string" + }, + "webhook_signing_secret_id": { + "title": "Webhook Signing Secret Id", + "type": "string" + } + }, + "required": [ + "event_type", + "webhook_signing_secret_id" + ], + "title": "AuditLogEventWebhookSigningSecretCreatedV1", + "type": "object" + }, + "AuditLogEventWebhookSigningSecretDeletedV1": { + "additionalProperties": false, + "description": "A webhook signing secret was deleted.", + "properties": { + "event_type": { + "const": "WEBHOOK_SIGNING_SECRET_DELETED", + "title": "Event Type", + "type": "string" + }, + "webhook_signing_secret_id": { + "title": "Webhook Signing Secret Id", + "type": "string" + } + }, + "required": [ + "event_type", + "webhook_signing_secret_id" + ], + "title": "AuditLogEventWebhookSigningSecretDeletedV1", + "type": "object" + }, + "AuditLogEventWebhookSigningSecretRotatedV1": { + "additionalProperties": false, + "description": "A webhook signing secret was rotated.", + "properties": { + "event_type": { + "const": "WEBHOOK_SIGNING_SECRET_ROTATED", + "title": "Event Type", + "type": "string" + }, + "webhook_signing_secret_id": { + "title": "Webhook Signing Secret Id", + "type": "string" + } + }, + "required": [ + "event_type", + "webhook_signing_secret_id" + ], + "title": "AuditLogEventWebhookSigningSecretRotatedV1", + "type": "object" + }, + "AuditLogPromotionControlActionV1": { + "description": "User-initiated promotion control signal recorded on a promotion-control event.", + "enum": [ + "PAUSE", + "RESUME", + "FORCE_CANCEL", + "FORCE_ROLL_FORWARD", + "GRACEFUL_CANCEL" + ], + "title": "AuditLogPromotionControlActionV1", + "type": "string" + }, + "AuditLogSourceV1": { + "description": "Surface that issued the audited action.", + "enum": [ + "UI", + "API", + "MCP", + "SYSTEM", + "OTHER" + ], + "title": "AuditLogSourceV1", + "type": "string" + }, + "ListAuditLogsResponseV1": { + "description": "A page of audit-log entries, newest first by default.", + "properties": { + "items": { + "description": "Items in this page.", + "items": { + "$ref": "#/components/schemas/AuditLogEntryV1" + }, + "title": "Items", + "type": "array" + }, + "pagination": { + "$ref": "#/components/schemas/PaginationResponseV1", + "description": "Pagination metadata for the page." + } + }, + "required": [ + "items", + "pagination" + ], + "title": "ListAuditLogsResponseV1", + "type": "object" + }, + "AuditLogEventTypeGroupV1": { + "description": "Coarse grouping of event types, used to filter the audit log.", + "enum": [ + "DEPLOYED", + "PROMOTED", + "ACTIVATED_DEACTIVATED", + "AUTOSCALING_SETTINGS", + "REQUEST_BACKPRESSURE_SETTINGS", + "INSTANCE_TYPE_CHANGED", + "ENVIRONMENT_SETTINGS", + "REPLICA_TERMINATED", + "DELETED", + "METADATA", + "SECRETS", + "API_KEYS", + "GATEWAY", + "CODE", + "WEBHOOK_SIGNING_SECRETS", + "USER_MANAGEMENT", + "DIRECTORY_GROUP_MANAGEMENT", + "SSH" + ], + "title": "AuditLogEventTypeGroupV1", + "type": "string" + }, + "AuditLogSortDirectionV1": { + "description": "Sort order of returned entries, by creation time.", + "enum": [ + "DESC", + "ASC" + ], + "title": "AuditLogSortDirectionV1", + "type": "string" + }, + "ListAuditLogsRequestV1": { + "description": "Query params for listing audit-log entries.", + "properties": { + "cursor": { "anyOf": [ { "type": "string" @@ -13125,53 +17420,24 @@ "type": "null" } ], - "title": "Rolling Deploy Strategy" - }, - "max_unavailable_percent": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "title": "Max Unavailable Percent" - }, - "max_surge_percent": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "title": "Max Surge Percent" + "default": null, + "description": "Opaque cursor returned by a previous page. Omit to fetch the first page.", + "title": "Cursor" }, - "stabilization_time_seconds": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "title": "Stabilization Time Seconds" + "limit": { + "default": 20, + "description": "Maximum number of entries to return per page. Defaults to 20, and must be between 1 and 200.", + "maximum": 200, + "minimum": 1, + "title": "Limit", + "type": "integer" }, - "replica_overhead_percent": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "title": "Replica Overhead Percent" + "direction": { + "$ref": "#/components/schemas/AuditLogSortDirectionV1", + "default": "DESC", + "description": "Sort order by the time the action occurred. Defaults to DESC (newest first). Ignored when paginating with a cursor." }, - "promotion_cleanup_strategy": { + "search": { "anyOf": [ { "type": "string" @@ -13180,193 +17446,113 @@ "type": "null" } ], - "title": "Promotion Cleanup Strategy" - }, - "ramp_up_while_promoting": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } - ], - "title": "Ramp Up While Promoting" + "default": null, + "description": "Case-insensitive substring matched against resource names and IDs in the entry.", + "title": "Search" }, - "ramp_up_duration_seconds": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "title": "Ramp Up Duration Seconds" + "event_type_groups": { + "description": "When set, returns only entries whose event type falls in one of these groups.", + "items": { + "$ref": "#/components/schemas/AuditLogEventTypeGroupV1" + }, + "title": "Event Type Groups", + "type": "array" }, - "ramp_up_step_size": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "title": "Ramp Up Step Size" + "user_ids": { + "description": "When set, returns only entries whose acting user is one of these IDs.", + "items": { + "type": "string" + }, + "title": "User Ids", + "type": "array" }, - "request_backpressure_policy": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Request Backpressure Policy" + "deployment_ids": { + "description": "When set, returns only entries referencing one of these model deployment IDs.", + "items": { + "type": "string" + }, + "title": "Deployment Ids", + "type": "array" }, - "model_id": { - "title": "Model Id", - "type": "string" + "chain_deployment_ids": { + "description": "When set, returns only entries referencing one of these chain deployment IDs.", + "items": { + "type": "string" + }, + "title": "Chain Deployment Ids", + "type": "array" }, - "model_name": { - "title": "Model Name", - "type": "string" + "environment_names": { + "description": "When set, returns only entries for one of these environments.", + "items": { + "type": "string" + }, + "title": "Environment Names", + "type": "array" }, - "environment_name": { - "title": "Environment Name", - "type": "string" + "sources": { + "description": "When set, returns only entries issued from one of these surfaces.", + "items": { + "$ref": "#/components/schemas/AuditLogSourceV1" + }, + "title": "Sources", + "type": "array" }, - "deployment_type": { + "start_epoch_millis": { "anyOf": [ { - "type": "string" + "type": "integer" }, { "type": "null" } ], - "title": "Deployment Type" - }, - "event_type": { - "const": "ENVIRONMENT_UPDATED", - "title": "Event Type", - "type": "string" + "default": null, + "description": "Epoch milliseconds for the start of the window. Defaults to the beginning of the audit-log history.", + "title": "Start Epoch Millis" }, - "previous_settings": { + "end_epoch_millis": { "anyOf": [ { - "$ref": "#/components/schemas/AuditLogEventEnvironmentSettingsV1" + "type": "integer" }, { "type": "null" } - ] - } - }, - "required": [ - "schedules", - "min_replica", - "max_replica", - "concurrency_target", - "autoscaling_window", - "scale_down_delay", - "target_utilization_percentage", - "target_in_flight_tokens", - "max_scale_down_rate", - "redeploy_on_promotion", - "rolling_deploy", - "rolling_deploy_strategy", - "max_unavailable_percent", - "max_surge_percent", - "stabilization_time_seconds", - "replica_overhead_percent", - "promotion_cleanup_strategy", - "ramp_up_while_promoting", - "ramp_up_duration_seconds", - "ramp_up_step_size", - "model_id", - "model_name", - "environment_name", - "deployment_type", - "event_type", - "previous_settings" - ], - "title": "AuditLogEventEnvironmentUpdatedV1", - "type": "object" - }, - "AuditLogEventGatewayEndpointCreatedV1": { - "additionalProperties": false, - "description": "A Frontier Gateway endpoint was created.", - "properties": { - "event_type": { - "const": "GATEWAY_ENDPOINT_CREATED", - "title": "Event Type", - "type": "string" - }, - "gateway_endpoint_id": { - "title": "Gateway Endpoint Id", - "type": "string" - }, - "slug": { - "title": "Slug", - "type": "string" - } - }, - "required": [ - "event_type", - "gateway_endpoint_id", - "slug" - ], - "title": "AuditLogEventGatewayEndpointCreatedV1", - "type": "object" - }, - "AuditLogEventGatewayEndpointDeletedV1": { - "additionalProperties": false, - "description": "A Frontier Gateway endpoint was deleted.", - "properties": { - "event_type": { - "const": "GATEWAY_ENDPOINT_DELETED", - "title": "Event Type", - "type": "string" - }, - "gateway_endpoint_id": { - "title": "Gateway Endpoint Id", - "type": "string" - }, - "slug": { - "title": "Slug", - "type": "string" + ], + "default": null, + "description": "Epoch milliseconds for the end of the window. Defaults to the current time.", + "title": "End Epoch Millis" } }, - "required": [ - "event_type", - "gateway_endpoint_id", - "slug" - ], - "title": "AuditLogEventGatewayEndpointDeletedV1", + "title": "ListAuditLogsRequestV1", "type": "object" }, - "AuditLogEventGatewayEndpointUpdatedV1": { - "additionalProperties": false, - "description": "A Frontier Gateway endpoint was updated.", + "ModelV1": { + "description": "A model.", "properties": { - "event_type": { - "const": "GATEWAY_ENDPOINT_UPDATED", - "title": "Event Type", + "id": { + "description": "Unique identifier of the model", + "title": "Id", "type": "string" }, - "gateway_endpoint_id": { - "title": "Gateway Endpoint Id", + "created_at": { + "description": "Time the model was created in ISO 8601 format", + "format": "date-time", + "title": "Created At", "type": "string" }, - "slug": { - "title": "Slug", + "name": { + "description": "Name of the model", + "title": "Name", "type": "string" }, - "previous_slug": { + "deployments_count": { + "description": "Number of deployments of the model", + "title": "Deployments Count", + "type": "integer" + }, + "production_deployment_id": { "anyOf": [ { "type": "string" @@ -13375,82 +17561,102 @@ "type": "null" } ], - "title": "Previous Slug" + "description": "Unique identifier of the production deployment of the model", + "title": "Production Deployment Id" + }, + "development_deployment_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Unique identifier of the development deployment of the model", + "title": "Development Deployment Id" + }, + "instance_type_name": { + "description": "Name of the instance type for the production deployment of the model", + "title": "Instance Type Name", + "type": "string" + }, + "team_name": { + "description": "Name of the team associated with the model.", + "title": "Team Name", + "type": "string" } }, "required": [ - "event_type", - "gateway_endpoint_id", - "slug", - "previous_slug" + "id", + "created_at", + "name", + "deployments_count", + "production_deployment_id", + "development_deployment_id", + "instance_type_name", + "team_name" ], - "title": "AuditLogEventGatewayEndpointUpdatedV1", + "title": "ModelV1", "type": "object" }, - "AuditLogEventModelDeletedV1": { - "additionalProperties": false, - "description": "A model was deleted.", + "ModelsV1": { + "description": "A list of models.", "properties": { - "event_type": { - "const": "MODEL_DELETED", - "title": "Event Type", - "type": "string" - }, - "model_id": { - "title": "Model Id", - "type": "string" - }, - "model_name": { - "title": "Model Name", - "type": "string" + "models": { + "items": { + "$ref": "#/components/schemas/ModelV1" + }, + "title": "Models", + "type": "array" } }, "required": [ - "event_type", - "model_id", - "model_name" + "models" ], - "title": "AuditLogEventModelDeletedV1", + "title": "ModelsV1", "type": "object" }, - "AuditLogEventModelDeployedV1": { - "additionalProperties": false, - "description": "A model deployment was created.", + "ModelsRequestV1": { + "description": "Request parameters for listing models.", "properties": { - "event_type": { - "const": "MODEL_DEPLOYED", - "title": "Event Type", - "type": "string" - }, - "model_id": { - "title": "Model Id", - "type": "string" - }, - "model_name": { - "title": "Model Name", + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "When set, returns only models with this exact name, if any. On a team-scoped route this matches at most one model; on the org-wide route it may match models in multiple teams, since names are unique only within a team.", + "title": "Name" + } + }, + "title": "ModelsRequestV1", + "type": "object" + }, + "LibraryListingSourceV1": { + "description": "Create a model by forking a library listing accessible to the caller's organization.", + "properties": { + "kind": { + "const": "library_listing", + "default": "library_listing", + "title": "Kind", "type": "string" }, - "deployment_id": { - "title": "Deployment Id", + "lab_display_name": { + "description": "Identifier of the publishing organization, as returned by `GET /v1/library_models`.", + "title": "Lab Display Name", "type": "string" }, - "deployment_name": { - "title": "Deployment Name", + "user_defined_listing_id": { + "description": "Listing identifier within the publishing organization.", + "title": "User Defined Listing Id", "type": "string" }, - "scale_previous_to_zero": { - "title": "Scale Previous To Zero", - "type": "boolean" - }, - "trusted": { - "title": "Trusted", - "type": "boolean" - }, - "publish": { - "title": "Publish", - "type": "boolean" - }, - "environment_name": { + "deployed_model_name": { "anyOf": [ { "type": "string" @@ -13459,89 +17665,105 @@ "type": "null" } ], - "title": "Environment Name" + "default": null, + "description": "Optional name for the new deployed model. Defaults to the listing's configured name.", + "title": "Deployed Model Name" } }, "required": [ - "event_type", - "model_id", - "model_name", - "deployment_id", - "deployment_name", - "scale_previous_to_zero", - "trusted", - "publish", - "environment_name" + "lab_display_name", + "user_defined_listing_id" ], - "title": "AuditLogEventModelDeployedV1", + "title": "LibraryListingSourceV1", "type": "object" }, - "AuditLogEventModelDeploymentActivatedV1": { - "additionalProperties": false, - "description": "A model deployment was activated.", + "ModelArchiveSourceV1": { + "description": "Create a model from an archive previously uploaded via the credentials\nissued by `POST /v1/prepare_model_upload`.", "properties": { - "event_type": { - "const": "MODEL_DEPLOYMENT_ACTIVATED", - "title": "Event Type", + "kind": { + "const": "model_archive", + "default": "model_archive", + "title": "Kind", "type": "string" }, - "model_id": { - "title": "Model Id", + "name": { + "description": "Name of the new model.", + "title": "Name", "type": "string" }, - "model_name": { - "title": "Model Name", - "type": "string" + "deployment": { + "$ref": "#/components/schemas/DeploymentArchivePayloadV1", + "description": "Deployment-level configuration for the model's first deployment." }, - "deployment_id": { - "title": "Deployment Id", - "type": "string" + "s3_key": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "S3 key of the uploaded archive, from the credentials returned by `POST /v1/prepare_model_upload`. Omit for model formats that are not built from an archive (for example, BIS-LLM), where prepare issues no upload target.", + "title": "S3 Key" }, - "deployment_name": { - "title": "Deployment Name", - "type": "string" + "disable_archive_download": { + "default": false, + "description": "If true, the uploaded archive is not downloadable after creation. Locked at model creation; cannot be changed by subsequent deployments.", + "title": "Disable Archive Download", + "type": "boolean" } }, "required": [ - "event_type", - "model_id", - "model_name", - "deployment_id", - "deployment_name" + "name", + "deployment" ], - "title": "AuditLogEventModelDeploymentActivatedV1", + "title": "ModelArchiveSourceV1", "type": "object" }, - "AuditLogEventModelDeploymentAutoscalingSettingsChangedV1": { - "additionalProperties": false, - "description": "A model deployment's autoscaling settings were changed.", + "CreateModelRequestV1": { + "description": "Body for creating a model via `POST /v1/models`.", "properties": { - "schedules": { - "anyOf": [ + "source": { + "description": "Where the new model is created from.", + "discriminator": { + "mapping": { + "library_listing": "#/components/schemas/LibraryListingSourceV1", + "model_archive": "#/components/schemas/ModelArchiveSourceV1" + }, + "propertyName": "kind" + }, + "oneOf": [ { - "items": { - "$ref": "#/components/schemas/AuditLogEventAutoscalingScheduleChangeV1" - }, - "type": "array" + "$ref": "#/components/schemas/LibraryListingSourceV1" }, { - "type": "null" + "$ref": "#/components/schemas/ModelArchiveSourceV1" } ], - "title": "Schedules" - }, + "title": "Source" + } + }, + "required": [ + "source" + ], + "title": "CreateModelRequestV1", + "type": "object" + }, + "AutoscalingSettingsV1": { + "description": "Autoscaling settings for a deployment.", + "properties": { "min_replica": { + "description": "Minimum number of replicas", "title": "Min Replica", "type": "integer" }, "max_replica": { + "description": "Maximum number of replicas", "title": "Max Replica", "type": "integer" }, - "concurrency_target": { - "title": "Concurrency Target", - "type": "integer" - }, "autoscaling_window": { "anyOf": [ { @@ -13551,6 +17773,7 @@ "type": "null" } ], + "description": "Timeframe of traffic considered for autoscaling decisions", "title": "Autoscaling Window" }, "scale_down_delay": { @@ -13562,8 +17785,14 @@ "type": "null" } ], + "description": "Waiting period before scaling down any active replica", "title": "Scale Down Delay" }, + "concurrency_target": { + "description": "Number of requests per replica before scaling up", + "title": "Concurrency Target", + "type": "integer" + }, "target_utilization_percentage": { "anyOf": [ { @@ -13573,6 +17802,7 @@ "type": "null" } ], + "description": "Target utilization percentage for scaling up/down.", "title": "Target Utilization Percentage" }, "target_in_flight_tokens": { @@ -13584,222 +17814,111 @@ "type": "null" } ], + "default": null, + "description": "Target number of in-flight tokens for autoscaling decisions. Early access only.", "title": "Target In Flight Tokens" }, "max_scale_down_rate": { "anyOf": [ { - "type": "number" + "type": "integer" }, { "type": "null" } ], + "default": null, + "description": "Maximum percentage of replicas that can be removed per autoscaling window (1\u201350). E.g. 20 means at most 20% of replicas are removed per window.", "title": "Max Scale Down Rate" - }, - "event_type": { - "const": "MODEL_DEPLOYMENT_AUTOSCALING_SETTINGS_CHANGED", - "title": "Event Type", - "type": "string" - }, - "model_id": { - "title": "Model Id", - "type": "string" - }, - "model_name": { - "title": "Model Name", - "type": "string" - }, - "deployment_id": { - "title": "Deployment Id", - "type": "string" - }, - "deployment_name": { - "title": "Deployment Name", - "type": "string" - }, - "deployment_type": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Deployment Type" - }, - "previous_settings": { - "anyOf": [ - { - "$ref": "#/components/schemas/AuditLogEventAutoscalingSettingsV1" - }, - { - "type": "null" - } - ] } }, "required": [ - "schedules", "min_replica", "max_replica", - "concurrency_target", "autoscaling_window", "scale_down_delay", - "target_utilization_percentage", - "target_in_flight_tokens", - "max_scale_down_rate", - "event_type", - "model_id", - "model_name", - "deployment_id", - "deployment_name", - "deployment_type", - "previous_settings" + "concurrency_target", + "target_utilization_percentage" ], - "title": "AuditLogEventModelDeploymentAutoscalingSettingsChangedV1", + "title": "AutoscalingSettingsV1", "type": "object" }, - "AuditLogEventModelDeploymentDeactivatedV1": { - "additionalProperties": false, - "description": "A model deployment was deactivated.", - "properties": { - "event_type": { - "const": "MODEL_DEPLOYMENT_DEACTIVATED", - "title": "Event Type", - "type": "string" - }, - "model_id": { - "title": "Model Id", - "type": "string" - }, - "model_name": { - "title": "Model Name", - "type": "string" - }, - "deployment_id": { - "title": "Deployment Id", - "type": "string" - }, - "deployment_name": { - "title": "Deployment Name", - "type": "string" - } - }, - "required": [ - "event_type", - "model_id", - "model_name", - "deployment_id", - "deployment_name" + "DeploymentStatusV1": { + "description": "The status of a deployment.", + "enum": [ + "BUILDING", + "DEPLOYING", + "DEPLOY_FAILED", + "LOADING_MODEL", + "ACTIVE", + "UNHEALTHY", + "BUILD_FAILED", + "BUILD_STOPPED", + "DEACTIVATING", + "INACTIVE", + "FAILED", + "UPDATING", + "SCALED_TO_ZERO", + "WAKING_UP" ], - "title": "AuditLogEventModelDeploymentDeactivatedV1", - "type": "object" + "title": "DeploymentStatusV1", + "type": "string" }, - "AuditLogEventModelDeploymentDeletedV1": { - "additionalProperties": false, - "description": "A model deployment was deleted.", + "DeploymentV1": { + "description": "A deployment of a model.", "properties": { - "event_type": { - "const": "MODEL_DEPLOYMENT_DELETED", - "title": "Event Type", - "type": "string" - }, - "model_id": { - "title": "Model Id", - "type": "string" - }, - "model_name": { - "title": "Model Name", + "id": { + "description": "Unique identifier of the deployment", + "title": "Id", "type": "string" }, - "deployment_id": { - "title": "Deployment Id", + "created_at": { + "description": "Time the deployment was created in ISO 8601 format", + "format": "date-time", + "title": "Created At", "type": "string" }, - "deployment_name": { - "title": "Deployment Name", - "type": "string" - } - }, - "required": [ - "event_type", - "model_id", - "model_name", - "deployment_id", - "deployment_name" - ], - "title": "AuditLogEventModelDeploymentDeletedV1", - "type": "object" - }, - "AuditLogEventModelDeploymentInstanceTypeChangedV1": { - "additionalProperties": false, - "description": "A model deployment's instance type was changed.", - "properties": { - "event_type": { - "const": "MODEL_DEPLOYMENT_INSTANCE_TYPE_CHANGED", - "title": "Event Type", + "name": { + "description": "Name of the deployment", + "title": "Name", "type": "string" }, "model_id": { + "description": "Unique identifier of the model", "title": "Model Id", "type": "string" }, - "model_name": { - "title": "Model Name", - "type": "string" - }, - "deployment_id": { - "title": "Deployment Id", - "type": "string" - }, - "deployment_name": { - "title": "Deployment Name", - "type": "string" - }, - "instance_type_name": { - "title": "Instance Type Name", - "type": "string" - } - }, - "required": [ - "event_type", - "model_id", - "model_name", - "deployment_id", - "deployment_name", - "instance_type_name" - ], - "title": "AuditLogEventModelDeploymentInstanceTypeChangedV1", - "type": "object" - }, - "AuditLogEventModelDeploymentPromotedV1": { - "additionalProperties": false, - "description": "A model deployment was promoted to an environment.", - "properties": { - "event_type": { - "const": "MODEL_DEPLOYMENT_PROMOTED", - "title": "Event Type", - "type": "string" + "is_production": { + "description": "Whether the deployment is the production deployment of the model", + "title": "Is Production", + "type": "boolean" }, - "model_id": { - "title": "Model Id", - "type": "string" + "is_development": { + "description": "Whether the deployment is the development deployment of the model", + "title": "Is Development", + "type": "boolean" }, - "model_name": { - "title": "Model Name", - "type": "string" + "status": { + "$ref": "#/components/schemas/DeploymentStatusV1", + "description": "Status of the deployment" }, - "deployment_id": { - "title": "Deployment Id", - "type": "string" + "active_replica_count": { + "description": "Number of active replicas", + "title": "Active Replica Count", + "type": "integer" }, - "deployment_name": { - "title": "Deployment Name", - "type": "string" + "autoscaling_settings": { + "anyOf": [ + { + "$ref": "#/components/schemas/AutoscalingSettingsV1" + }, + { + "type": "null" + } + ], + "description": "Autoscaling settings for the deployment. If null, the model has not finished deploying" }, - "environment_name": { + "instance_type_name": { "anyOf": [ { "type": "string" @@ -13808,9 +17927,10 @@ "type": "null" } ], - "title": "Environment Name" + "description": "Name of the instance type the model deployment is running on", + "title": "Instance Type Name" }, - "environment_id": { + "environment": { "anyOf": [ { "type": "string" @@ -13819,152 +17939,172 @@ "type": "null" } ], - "title": "Environment Id" - } - }, - "required": [ - "event_type", - "model_id", - "model_name", - "deployment_id", - "deployment_name", - "environment_name", - "environment_id" - ], - "title": "AuditLogEventModelDeploymentPromotedV1", - "type": "object" - }, - "AuditLogEventModelDeploymentRequestBackpressureSettingsChangedV1": { - "additionalProperties": false, - "description": "A model deployment's request backpressure settings were changed.", - "properties": { - "event_type": { - "const": "MODEL_DEPLOYMENT_REQUEST_BACKPRESSURE_SETTINGS_CHANGED", - "title": "Event Type", - "type": "string" - }, - "model_id": { - "title": "Model Id", - "type": "string" - }, - "model_name": { - "title": "Model Name", - "type": "string" - }, - "deployment_id": { - "title": "Deployment Id", - "type": "string" - }, - "deployment_name": { - "title": "Deployment Name", - "type": "string" + "description": "The environment associated with the deployment", + "title": "Environment" }, - "policy": { + "labels": { "anyOf": [ { - "type": "string" + "additionalProperties": true, + "type": "object" }, { "type": "null" } ], "default": null, - "title": "Policy" + "description": "User-provided key-value labels for the deployment", + "title": "Labels" }, - "previous_policy": { + "region": { "anyOf": [ { - "type": "string" + "$ref": "#/components/schemas/RegionV1" }, { "type": "null" } ], "default": null, - "title": "Previous Policy" + "description": "The selected region for the deployment, if any" + }, + "request_backpressure_settings": { + "$ref": "#/components/schemas/RequestBackpressureSettingsV1", + "description": "Effective request backpressure settings for the deployment." } }, "required": [ - "event_type", + "id", + "created_at", + "name", "model_id", - "model_name", - "deployment_id", - "deployment_name" + "is_production", + "is_development", + "status", + "active_replica_count", + "autoscaling_settings", + "instance_type_name", + "environment", + "request_backpressure_settings" ], - "title": "AuditLogEventModelDeploymentRequestBackpressureSettingsChangedV1", + "title": "DeploymentV1", "type": "object" }, - "AuditLogEventModelDeploymentRetriedV1": { - "additionalProperties": false, - "description": "A model deployment build was retried.", + "RequestBackpressurePolicyV1": { + "enum": [ + "QUEUE_ON_FULL", + "REJECT_ON_FULL" + ], + "title": "RequestBackpressurePolicyV1", + "type": "string" + }, + "RequestBackpressureSettingsV1": { + "description": "Request backpressure settings for a deployment or environment.", "properties": { - "event_type": { - "const": "MODEL_DEPLOYMENT_RETRIED", - "title": "Event Type", - "type": "string" - }, - "model_id": { - "title": "Model Id", - "type": "string" - }, - "model_name": { - "title": "Model Name", - "type": "string" - }, - "deployment_id": { - "title": "Deployment Id", - "type": "string" + "policy": { + "anyOf": [ + { + "$ref": "#/components/schemas/RequestBackpressurePolicyV1" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Backpressure policy. Null when no policy is set." + } + }, + "title": "RequestBackpressureSettingsV1", + "type": "object" + }, + "CreatedModelDeploymentV1": { + "description": "A newly created deployment and its model.", + "properties": { + "model": { + "$ref": "#/components/schemas/ModelV1", + "description": "The model the deployment belongs to. May have been created by this call." }, - "deployment_name": { - "title": "Deployment Name", + "deployment": { + "$ref": "#/components/schemas/DeploymentV1", + "description": "The newly created deployment." + } + }, + "required": [ + "model", + "deployment" + ], + "title": "CreatedModelDeploymentV1", + "type": "object" + }, + "ModelTombstoneV1": { + "description": "A model tombstone.", + "properties": { + "id": { + "description": "Unique identifier of the model", + "title": "Id", "type": "string" }, - "retried": { - "title": "Retried", + "deleted": { + "description": "Whether the model was deleted", + "title": "Deleted", "type": "boolean" } }, "required": [ - "event_type", - "model_id", - "model_name", - "deployment_id", - "deployment_name", - "retried" + "id", + "deleted" ], - "title": "AuditLogEventModelDeploymentRetriedV1", + "title": "ModelTombstoneV1", "type": "object" }, - "AuditLogEventModelPromotionControlActionV1": { + "UpdateModelRequestV1": { "additionalProperties": false, - "description": "A user-initiated promotion control signal was sent to a rolling promotion.", + "description": "A request to update a model.", "properties": { - "event_type": { - "const": "MODEL_PROMOTION_CONTROL_ACTION", - "title": "Event Type", - "type": "string" - }, - "model_id": { - "title": "Model Id", - "type": "string" - }, - "model_name": { - "title": "Model Name", - "type": "string" - }, - "deployment_id": { - "title": "Deployment Id", - "type": "string" - }, - "deployment_name": { - "title": "Deployment Name", - "type": "string" - }, - "environment_name": { - "title": "Environment Name", - "type": "string" - }, - "environment_id": { + "name": { + "anyOf": [ + { + "maxLength": 255, + "minLength": 1, + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "New name for the model, unique within its team. Renaming does not change the model ID, endpoints, or deployments. Pushes that still use the old model_name create another model or target a model that now uses that name, so update config.yaml after renaming.", + "examples": [ + "my-model" + ], + "title": "Name" + } + }, + "title": "UpdateModelRequestV1", + "type": "object" + }, + "DeploymentsV1": { + "description": "A list of deployments of a model.", + "properties": { + "deployments": { + "description": "A list of deployments of a model", + "items": { + "$ref": "#/components/schemas/DeploymentV1" + }, + "title": "Deployments", + "type": "array" + } + }, + "required": [ + "deployments" + ], + "title": "DeploymentsV1", + "type": "object" + }, + "DeploymentsRequestV1": { + "description": "Request parameters for listing a model's deployments.", + "properties": { + "name": { "anyOf": [ { "type": "string" @@ -13973,856 +18113,781 @@ "type": "null" } ], - "title": "Environment Id" - }, - "action": { - "$ref": "#/components/schemas/AuditLogPromotionControlActionV1" + "default": null, + "description": "When set, returns only the deployment with this exact name, if any.", + "title": "Name" } }, - "required": [ - "event_type", - "model_id", - "model_name", - "deployment_id", - "deployment_name", - "environment_name", - "environment_id", - "action" - ], - "title": "AuditLogEventModelPromotionControlActionV1", + "title": "DeploymentsRequestV1", "type": "object" }, - "AuditLogEventReplicaTerminatedV1": { - "additionalProperties": false, - "description": "A replica of a model deployment was terminated.", + "DeploymentArchiveSourceV1": { + "description": "Add a deployment from an archive previously uploaded via the credentials\nissued by `POST /v1/prepare_model_upload`.", "properties": { - "event_type": { - "const": "REPLICA_TERMINATED", - "title": "Event Type", - "type": "string" - }, - "model_id": { - "title": "Model Id", - "type": "string" - }, - "model_name": { - "title": "Model Name", - "type": "string" - }, - "deployment_id": { - "title": "Deployment Id", + "kind": { + "const": "model_archive", + "default": "model_archive", + "title": "Kind", "type": "string" }, - "deployment_name": { - "title": "Deployment Name", - "type": "string" + "deployment": { + "$ref": "#/components/schemas/DeploymentArchivePayloadV1", + "description": "Deployment-level configuration." }, - "replica_id": { - "title": "Replica Id", - "type": "string" + "s3_key": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "S3 key of the uploaded archive, from the credentials returned by `POST /v1/prepare_model_upload`. Omit for model formats that are not built from an archive (for example, BIS-LLM), where prepare issues no upload target.", + "title": "S3 Key" } }, "required": [ - "event_type", - "model_id", - "model_name", - "deployment_id", - "deployment_name", - "replica_id" + "deployment" ], - "title": "AuditLogEventReplicaTerminatedV1", + "title": "DeploymentArchiveSourceV1", "type": "object" }, - "AuditLogEventRequireGroupBasedAdminsEnabledV1": { - "additionalProperties": false, - "description": "Group-based admin enforcement was enabled for the organization.", + "CreateModelDeploymentRequestV1": { + "description": "Body for adding a deployment to an existing model via\n`POST /v1/models/{model_id}/deployments`.", "properties": { - "event_type": { - "const": "REQUIRE_GROUP_BASED_ADMINS_ENABLED", - "title": "Event Type", - "type": "string" - }, - "organization_id": { - "title": "Organization Id", - "type": "string" + "source": { + "description": "Where the new deployment is created from.", + "discriminator": { + "mapping": { + "model_archive": "#/components/schemas/DeploymentArchiveSourceV1" + }, + "propertyName": "kind" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/DeploymentArchiveSourceV1" + } + ], + "title": "Source" } }, "required": [ - "event_type", - "organization_id" + "source" ], - "title": "AuditLogEventRequireGroupBasedAdminsEnabledV1", + "title": "CreateModelDeploymentRequestV1", "type": "object" }, - "AuditLogEventSecretDeletedV1": { - "additionalProperties": false, - "description": "A secret was deleted.", + "DeploymentTombstoneV1": { + "description": "A model deployment tombstone.", "properties": { - "event_type": { - "const": "SECRET_DELETED", - "title": "Event Type", + "id": { + "description": "Unique identifier of the deployment", + "title": "Id", "type": "string" }, - "secret_id": { - "title": "Secret Id", - "type": "string" + "deleted": { + "description": "Whether the deployment was deleted", + "title": "Deleted", + "type": "boolean" }, - "secret_name": { - "title": "Secret Name", + "model_id": { + "description": "Unique identifier of the model", + "title": "Model Id", "type": "string" } }, "required": [ - "event_type", - "secret_id", - "secret_name" + "id", + "deleted", + "model_id" ], - "title": "AuditLogEventSecretDeletedV1", + "title": "DeploymentTombstoneV1", "type": "object" }, - "AuditLogEventSecretUpdatedV1": { + "UpdateDeploymentRequestV1": { "additionalProperties": false, - "description": "A secret was created or updated.", + "description": "A request to update a deployment.", "properties": { - "event_type": { - "const": "SECRET_UPDATED", - "title": "Event Type", - "type": "string" - }, - "secret_id": { - "title": "Secret Id", - "type": "string" - }, - "secret_name": { - "title": "Secret Name", - "type": "string" + "name": { + "anyOf": [ + { + "maxLength": 255, + "minLength": 1, + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "New name for the deployment, unique among the model's deployments. Only alphanumeric characters, hyphens, underscores, and periods are allowed.", + "examples": [ + "my-deployment" + ], + "title": "Name" } }, - "required": [ - "event_type", - "secret_id", - "secret_name" - ], - "title": "AuditLogEventSecretUpdatedV1", + "title": "UpdateDeploymentRequestV1", "type": "object" }, - "AuditLogEventSshCertificateSignedV1": { + "UpdateAutoscalingSettingsV1": { "additionalProperties": false, - "description": "An SSH certificate was signed for a workload.", + "description": "A request to update autoscaling settings for a deployment. All fields are optional, and we only update ones passed in.", "properties": { - "event_type": { - "const": "SSH_CERTIFICATE_SIGNED", - "title": "Event Type", - "type": "string" + "min_replica": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Minimum number of replicas", + "examples": [ + 0 + ], + "title": "Min Replica" }, - "workload_type": { - "title": "Workload Type", - "type": "string" + "max_replica": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Maximum number of replicas", + "examples": [ + 7 + ], + "title": "Max Replica" }, - "workload_id": { - "title": "Workload Id", - "type": "string" + "autoscaling_window": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Timeframe of traffic considered for autoscaling decisions", + "examples": [ + 600 + ], + "title": "Autoscaling Window" + }, + "scale_down_delay": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Waiting period before scaling down any active replica", + "examples": [ + 120 + ], + "title": "Scale Down Delay" }, - "project_id": { - "title": "Project Id", - "type": "string" + "concurrency_target": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Number of requests per replica before scaling up", + "examples": [ + 2 + ], + "title": "Concurrency Target" }, - "replica_id": { - "title": "Replica Id", - "type": "string" + "target_utilization_percentage": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Target utilization percentage for scaling up/down.", + "examples": [ + 70 + ], + "title": "Target Utilization Percentage" }, - "proxy_address": { - "title": "Proxy Address", - "type": "string" + "target_in_flight_tokens": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Target number of in-flight tokens for autoscaling decisions. Early access only.", + "examples": [ + 40000 + ], + "title": "Target In Flight Tokens" }, - "expires_at": { - "title": "Expires At", - "type": "string" + "max_scale_down_rate": { + "anyOf": [ + { + "maximum": 50, + "minimum": 1, + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Maximum percentage of replicas that can be removed per autoscaling window (1\u201350). E.g. 20 means at most 20% of replicas are removed per window.", + "examples": [ + 20 + ], + "title": "Max Scale Down Rate" } }, - "required": [ - "event_type", - "workload_type", - "workload_id", - "project_id", - "replica_id", - "proxy_address", - "expires_at" - ], - "title": "AuditLogEventSshCertificateSignedV1", + "title": "UpdateAutoscalingSettingsV1", "type": "object" }, - "AuditLogEventTypeV1": { - "description": "Type of action recorded by an audit-log entry.", + "UpdateAutoscalingSettingsStatusV1": { + "description": "The status of a request to update autoscaling settings.", "enum": [ - "MODEL_DEPLOYED", - "MODEL_DEPLOYMENT_ACTIVATED", - "MODEL_DEPLOYMENT_DEACTIVATED", - "MODEL_DEPLOYMENT_RETRIED", - "MODEL_DEPLOYMENT_PROMOTED", - "MODEL_DEPLOYMENT_AUTOSCALING_SETTINGS_CHANGED", - "MODEL_DEPLOYMENT_REQUEST_BACKPRESSURE_SETTINGS_CHANGED", - "MODEL_DEPLOYMENT_INSTANCE_TYPE_CHANGED", - "MODEL_DEPLOYMENT_DELETED", - "MODEL_DELETED", - "CHAIN_DEPLOYED", - "CHAIN_DEPLOYMENT_ACTIVATED", - "CHAIN_DEPLOYMENT_DEACTIVATED", - "CHAIN_DEPLOYMENT_PROMOTED", - "CHAINLET_AUTOSCALING_SETTINGS_CHANGED", - "CHAINLET_INSTANCE_TYPE_CHANGED", - "CHAIN_DEPLOYMENT_DELETED", - "CHAIN_DELETED", - "CHAIN_ENVIRONMENT_CREATED", - "CHAIN_ENVIRONMENT_UPDATED", - "SECRET_UPDATED", - "SECRET_DELETED", - "API_KEY_CREATED", - "API_KEY_DELETED", - "GATEWAY_ENDPOINT_CREATED", - "GATEWAY_ENDPOINT_UPDATED", - "GATEWAY_ENDPOINT_DELETED", - "USER_INVITED", - "USER_JOINED_ORGANIZATION", - "WEBHOOK_SIGNING_SECRET_CREATED", - "WEBHOOK_SIGNING_SECRET_ROTATED", - "WEBHOOK_SIGNING_SECRET_DELETED", - "USER_ROLE_UPDATED", - "USER_TEAM_ROLE_UPDATED", - "USER_REMOVED", - "DIRECTORY_GROUP_ROLE_UPDATED", - "REQUIRE_GROUP_BASED_ADMINS_ENABLED", - "ENVIRONMENT_CREATED", - "ENVIRONMENT_UPDATED", - "ENVIRONMENT_DELETED", - "REPLICA_TERMINATED", - "MODEL_PROMOTION_CONTROL_ACTION", - "SSH_CERTIFICATE_SIGNED", - "VOLUME_DELETED", - "VOLUME_VERSION_DELETED", - "VOLUME_VERSION_RESTORED" + "ACCEPTED", + "QUEUED", + "UNCHANGED" ], - "title": "AuditLogEventTypeV1", + "title": "UpdateAutoscalingSettingsStatusV1", "type": "string" }, - "AuditLogEventUserInvitedV1": { - "additionalProperties": false, - "description": "A user was invited to the organization.", - "properties": { - "event_type": { - "const": "USER_INVITED", - "title": "Event Type", - "type": "string" - }, - "invited_user_email": { - "title": "Invited User Email", - "type": "string" - }, - "role_name": { - "title": "Role Name", - "type": "string" - } - }, - "required": [ - "event_type", - "invited_user_email", - "role_name" - ], - "title": "AuditLogEventUserInvitedV1", - "type": "object" - }, - "AuditLogEventUserJoinedOrganizationV1": { - "additionalProperties": false, - "description": "A user joined the organization.", + "UpdateAutoscalingSettingsResponseV1": { + "description": "The response to a request to update autoscaling settings.", "properties": { - "event_type": { - "const": "USER_JOINED_ORGANIZATION", - "title": "Event Type", - "type": "string" - }, - "new_user_email": { - "title": "New User Email", - "type": "string" + "status": { + "$ref": "#/components/schemas/UpdateAutoscalingSettingsStatusV1", + "description": "Status of the request to update autoscaling settings" }, - "user_id": { - "title": "User Id", + "message": { + "description": "A message describing the status of the request to update autoscaling settings", + "title": "Message", "type": "string" } }, "required": [ - "event_type", - "new_user_email", - "user_id" + "status", + "message" ], - "title": "AuditLogEventUserJoinedOrganizationV1", + "title": "UpdateAutoscalingSettingsResponseV1", "type": "object" }, - "AuditLogEventUserRemovedV1": { + "UpdateRequestBackpressureSettingsV1": { "additionalProperties": false, - "description": "A user was removed from the organization.", + "description": "A request to update request backpressure settings.", "properties": { - "event_type": { - "const": "USER_REMOVED", - "title": "Event Type", - "type": "string" - }, - "removed_user_email": { - "title": "Removed User Email", - "type": "string" + "policy": { + "anyOf": [ + { + "$ref": "#/components/schemas/RequestBackpressurePolicyV1" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Backpressure policy to apply. Null indicates no policy (on update, clears an existing one).", + "examples": [ + "REJECT_ON_FULL" + ], + "x-null-distinct": true } }, - "required": [ - "event_type", - "removed_user_email" - ], - "title": "AuditLogEventUserRemovedV1", + "title": "UpdateRequestBackpressureSettingsV1", "type": "object" }, - "AuditLogEventUserRoleUpdatedV1": { - "additionalProperties": false, - "description": "A user's organization role was updated.", + "PromoteRequestV1": { + "description": "A request to promote a deployment to production.", "properties": { - "event_type": { - "const": "USER_ROLE_UPDATED", - "title": "Event Type", - "type": "string" - }, - "user_id": { - "title": "User Id", - "type": "string" - }, - "user_email": { - "title": "User Email", - "type": "string" + "scale_down_previous_production": { + "default": true, + "description": "Whether to scale down the previous production deployment after promoting", + "examples": [ + true + ], + "title": "Scale Down Previous Production", + "type": "boolean" }, - "new_role_name": { - "title": "New Role Name", - "type": "string" + "preserve_env_instance_type": { + "default": true, + "description": "Whether to use the promoting deployment's instance type or preserve target environment's instance type", + "examples": [ + true + ], + "title": "Preserve Env Instance Type", + "type": "boolean" } }, - "required": [ - "event_type", - "user_id", - "user_email", - "new_role_name" - ], - "title": "AuditLogEventUserRoleUpdatedV1", + "title": "PromoteRequestV1", "type": "object" }, - "AuditLogEventUserTeamRoleUpdatedV1": { - "additionalProperties": false, - "description": "A user's team role was updated.", + "ActivateResponseV1": { + "description": "The response to a request to activate a deployment.", "properties": { - "event_type": { - "const": "USER_TEAM_ROLE_UPDATED", - "title": "Event Type", - "type": "string" - }, - "user_id": { - "title": "User Id", - "type": "string" - }, - "user_email": { - "title": "User Email", - "type": "string" - }, - "team_id": { - "title": "Team Id", - "type": "string" - }, - "team_name": { - "title": "Team Name", - "type": "string" + "success": { + "default": true, + "description": "Whether the deployment was successfully activated", + "title": "Success", + "type": "boolean" }, - "new_role_name": { - "title": "New Role Name", - "type": "string" + "no_op": { + "default": false, + "description": "Whether the request did nothing because the deployment was already active or on its way to becoming active", + "title": "No Op", + "type": "boolean" } }, - "required": [ - "event_type", - "user_id", - "user_email", - "team_id", - "team_name", - "new_role_name" - ], - "title": "AuditLogEventUserTeamRoleUpdatedV1", + "title": "ActivateResponseV1", "type": "object" }, - "AuditLogEventVolumeDeletedV1": { - "additionalProperties": false, - "description": "A volume was deleted, tombstoning every version it still held.", + "DeactivateResponseV1": { + "description": "The response to a request to deactivate a deployment.", "properties": { - "event_type": { - "const": "VOLUME_DELETED", - "title": "Event Type", - "type": "string" - }, - "volume_ref": { - "title": "Volume Ref", - "type": "string" - }, - "namespace": { - "title": "Namespace", - "type": "string" - }, - "volume_name": { - "title": "Volume Name", - "type": "string" + "success": { + "default": true, + "description": "Whether the deployment was successfully deactivated", + "title": "Success", + "type": "boolean" }, - "versions_deleted": { - "title": "Versions Deleted", - "type": "integer" + "no_op": { + "default": false, + "description": "Whether the request did nothing because the deployment was already inactive", + "title": "No Op", + "type": "boolean" } }, - "required": [ - "event_type", - "volume_ref", - "namespace", - "volume_name", - "versions_deleted" - ], - "title": "AuditLogEventVolumeDeletedV1", + "title": "DeactivateResponseV1", "type": "object" }, - "AuditLogEventVolumeVersionDeletedV1": { - "additionalProperties": false, - "description": "One version of a volume was deleted.", + "RetryDeploymentResponseV1": { + "description": "The response to a request to retry a deployment.", "properties": { - "event_type": { - "const": "VOLUME_VERSION_DELETED", - "title": "Event Type", - "type": "string" - }, - "volume_ref": { - "title": "Volume Ref", - "type": "string" - }, - "namespace": { - "title": "Namespace", - "type": "string" - }, - "volume_name": { - "title": "Volume Name", - "type": "string" + "retried": { + "description": "Whether the retry was successfully initiated", + "title": "Retried", + "type": "boolean" }, - "version": { - "title": "Version", - "type": "string" + "reason": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Explanation of the result. Provided when retried is false to explain why retry was not possible.", + "title": "Reason" }, - "digest": { - "title": "Digest", - "type": "string" + "deployment": { + "$ref": "#/components/schemas/DeploymentV1", + "description": "The deployment that was retried" } }, "required": [ - "event_type", - "volume_ref", - "namespace", - "volume_name", - "version", - "digest" + "retried", + "deployment" ], - "title": "AuditLogEventVolumeVersionDeletedV1", + "title": "RetryDeploymentResponseV1", "type": "object" }, - "AuditLogEventVolumeVersionRestoredV1": { - "additionalProperties": false, - "description": "A deleted version of a volume was restored.", + "DownloadDeploymentResponseV1": { + "description": "The response to a request to download a deployment's truss.", "properties": { - "event_type": { - "const": "VOLUME_VERSION_RESTORED", - "title": "Event Type", - "type": "string" - }, - "volume_ref": { - "title": "Volume Ref", - "type": "string" - }, - "namespace": { - "title": "Namespace", - "type": "string" - }, - "volume_name": { - "title": "Volume Name", - "type": "string" - }, - "version": { - "title": "Version", - "type": "string" - }, - "digest": { - "title": "Digest", + "download_url": { + "description": "Presigned URL to download the truss tar file", + "title": "Download Url", "type": "string" } }, "required": [ - "event_type", - "volume_ref", - "namespace", - "volume_name", - "version", - "digest" + "download_url" ], - "title": "AuditLogEventVolumeVersionRestoredV1", + "title": "DownloadDeploymentResponseV1", "type": "object" }, - "AuditLogEventWebhookSigningSecretCreatedV1": { - "additionalProperties": false, - "description": "A webhook signing secret was created.", + "DeploymentConfigResponseV1": { + "description": "The config of a deployment. Fields are populated per `output_format`.", "properties": { - "event_type": { - "const": "WEBHOOK_SIGNING_SECRET_CREATED", - "title": "Event Type", - "type": "string" + "config": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "description": "The parsed config of the deployment.", + "title": "Config" }, - "webhook_signing_secret_id": { - "title": "Webhook Signing Secret Id", - "type": "string" + "raw_config": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "The original config.yaml text \u2014 preserves comments, ordering, formatting.", + "title": "Raw Config" } }, - "required": [ - "event_type", - "webhook_signing_secret_id" - ], - "title": "AuditLogEventWebhookSigningSecretCreatedV1", + "title": "DeploymentConfigResponseV1", "type": "object" }, - "AuditLogEventWebhookSigningSecretDeletedV1": { - "additionalProperties": false, - "description": "A webhook signing secret was deleted.", + "DeploymentConfigOutputFormat": { + "enum": [ + "raw", + "parsed", + "both" + ], + "title": "DeploymentConfigOutputFormat", + "type": "string" + }, + "GetDeploymentConfigRequestV1": { + "description": "Query params for ``GET /v1/models/.../deployments/.../config``.", "properties": { - "event_type": { - "const": "WEBHOOK_SIGNING_SECRET_DELETED", - "title": "Event Type", - "type": "string" - }, - "webhook_signing_secret_id": { - "title": "Webhook Signing Secret Id", - "type": "string" + "output_format": { + "$ref": "#/components/schemas/DeploymentConfigOutputFormat", + "default": "both", + "description": "'raw': verbatim config.yaml with comments (not available for deployments created before 2026-04-30). 'parsed': dict with server-side defaults applied (always available). 'both': both fields populated." } }, - "required": [ - "event_type", - "webhook_signing_secret_id" - ], - "title": "AuditLogEventWebhookSigningSecretDeletedV1", + "title": "GetDeploymentConfigRequestV1", "type": "object" }, - "AuditLogEventWebhookSigningSecretRotatedV1": { - "additionalProperties": false, - "description": "A webhook signing secret was rotated.", + "LogLevelV1": { + "description": "A log severity level.", + "enum": [ + "DEBUG", + "INFO", + "WARNING", + "ERROR" + ], + "title": "LogLevelV1", + "type": "string" + }, + "LogV1": { "properties": { - "event_type": { - "const": "WEBHOOK_SIGNING_SECRET_ROTATED", - "title": "Event Type", + "timestamp": { + "description": "Epoch nanosecond timestamp of the log message.", + "title": "Timestamp", "type": "string" }, - "webhook_signing_secret_id": { - "title": "Webhook Signing Secret Id", + "message": { + "description": "The contents of the log message. When the logger captured an exception, the traceback is appended after the message.", + "title": "Message", "type": "string" + }, + "replica": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The replica the log line was emitted from.", + "title": "Replica" + }, + "request_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "The request ID associated with an inference request.", + "title": "Request Id" + }, + "level": { + "anyOf": [ + { + "$ref": "#/components/schemas/LogLevelV1" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Severity of the log line, if one was detected. null when unknown." } }, "required": [ - "event_type", - "webhook_signing_secret_id" + "timestamp", + "message", + "replica" ], - "title": "AuditLogEventWebhookSigningSecretRotatedV1", + "title": "LogV1", "type": "object" }, - "AuditLogPromotionControlActionV1": { - "description": "User-initiated promotion control signal recorded on a promotion-control event.", - "enum": [ - "PAUSE", - "RESUME", - "FORCE_CANCEL", - "FORCE_ROLL_FORWARD", - "GRACEFUL_CANCEL" - ], - "title": "AuditLogPromotionControlActionV1", - "type": "string" - }, - "AuditLogSourceV1": { - "description": "Surface that issued the audited action.", - "enum": [ - "UI", - "API", - "MCP", - "SYSTEM", - "OTHER" - ], - "title": "AuditLogSourceV1", - "type": "string" - }, - "ListAuditLogsResponseV1": { - "description": "A page of audit-log entries, newest first by default.", + "GetLogsResponseV1": { + "description": "A response to querying logs.", "properties": { - "items": { - "description": "Items in this page.", + "logs": { + "description": "Logs for a specific entity.", "items": { - "$ref": "#/components/schemas/AuditLogEntryV1" + "$ref": "#/components/schemas/LogV1" }, - "title": "Items", + "title": "Logs", "type": "array" - }, - "pagination": { - "$ref": "#/components/schemas/PaginationResponseV1", - "description": "Pagination metadata for the page." } }, "required": [ - "items", - "pagination" + "logs" ], - "title": "ListAuditLogsResponseV1", + "title": "GetLogsResponseV1", "type": "object" }, - "AuditLogEventTypeGroupV1": { - "description": "Coarse grouping of event types, used to filter the audit log.", - "enum": [ - "DEPLOYED", - "PROMOTED", - "ACTIVATED_DEACTIVATED", - "AUTOSCALING_SETTINGS", - "REQUEST_BACKPRESSURE_SETTINGS", - "INSTANCE_TYPE_CHANGED", - "ENVIRONMENT_SETTINGS", - "REPLICA_TERMINATED", - "DELETED", - "SECRETS", - "API_KEYS", - "GATEWAY", - "WEBHOOK_SIGNING_SECRETS", - "USER_MANAGEMENT", - "DIRECTORY_GROUP_MANAGEMENT", - "SSH" - ], - "title": "AuditLogEventTypeGroupV1", - "type": "string" - }, - "AuditLogSortDirectionV1": { - "description": "Sort order of returned entries, by creation time.", + "SortOrderV1": { "enum": [ - "DESC", - "ASC" + "asc", + "desc" ], - "title": "AuditLogSortDirectionV1", + "title": "SortOrderV1", "type": "string" }, - "ListAuditLogsRequestV1": { - "description": "Query params for listing audit-log entries.", + "GetDeploymentLogsRequestV1": { + "description": "A request to fetch deployment logs.", "properties": { - "cursor": { + "start_epoch_millis": { "anyOf": [ { - "type": "string" + "type": "integer" }, { "type": "null" } ], "default": null, - "description": "Opaque cursor returned by a previous page. Omit to fetch the first page.", - "title": "Cursor" - }, - "limit": { - "default": 20, - "description": "Maximum number of entries to return per page. Defaults to 20, and must be between 1 and 200.", - "maximum": 200, - "minimum": 1, - "title": "Limit", - "type": "integer" - }, - "direction": { - "$ref": "#/components/schemas/AuditLogSortDirectionV1", - "default": "DESC", - "description": "Sort order by the time the action occurred. Defaults to DESC (newest first). Ignored when paginating with a cursor." + "description": "Epoch milliseconds at which to start fetching logs. Defaults to 30 minutes before the end. The window from start to end must not exceed 7 days.", + "title": "Start Epoch Millis" }, - "search": { + "end_epoch_millis": { "anyOf": [ { - "type": "string" + "type": "integer" }, { "type": "null" } ], "default": null, - "description": "Case-insensitive substring matched against resource names and IDs in the entry.", - "title": "Search" - }, - "event_type_groups": { - "description": "When set, returns only entries whose event type falls in one of these groups.", - "items": { - "$ref": "#/components/schemas/AuditLogEventTypeGroupV1" - }, - "title": "Event Type Groups", - "type": "array" - }, - "user_ids": { - "description": "When set, returns only entries whose acting user is one of these IDs.", - "items": { - "type": "string" - }, - "title": "User Ids", - "type": "array" - }, - "deployment_ids": { - "description": "When set, returns only entries referencing one of these model deployment IDs.", - "items": { - "type": "string" - }, - "title": "Deployment Ids", - "type": "array" - }, - "chain_deployment_ids": { - "description": "When set, returns only entries referencing one of these chain deployment IDs.", - "items": { - "type": "string" - }, - "title": "Chain Deployment Ids", - "type": "array" - }, - "environment_names": { - "description": "When set, returns only entries for one of these environments.", - "items": { - "type": "string" - }, - "title": "Environment Names", - "type": "array" + "description": "Epoch milliseconds at which to stop fetching logs. Defaults to the current time.", + "title": "End Epoch Millis" }, - "sources": { - "description": "When set, returns only entries issued from one of these surfaces.", - "items": { - "$ref": "#/components/schemas/AuditLogSourceV1" - }, - "title": "Sources", - "type": "array" + "direction": { + "anyOf": [ + { + "$ref": "#/components/schemas/SortOrderV1" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Sort order for logs" }, - "start_epoch_millis": { + "limit": { "anyOf": [ { + "maximum": 1000, + "minimum": 1, "type": "integer" }, { "type": "null" } ], - "default": null, - "description": "Epoch milliseconds for the start of the window. Defaults to the beginning of the audit-log history.", - "title": "Start Epoch Millis" + "default": 500, + "description": "Limit of logs to fetch in a single request", + "title": "Limit" }, - "end_epoch_millis": { + "min_level": { "anyOf": [ { - "type": "integer" + "$ref": "#/components/schemas/LogLevelV1" }, { "type": "null" } ], "default": null, - "description": "Epoch milliseconds for the end of the window. Defaults to the current time.", - "title": "End Epoch Millis" - } - }, - "title": "ListAuditLogsRequestV1", - "type": "object" - }, - "ModelV1": { - "description": "A model.", - "properties": { - "id": { - "description": "Unique identifier of the model", - "title": "Id", - "type": "string" - }, - "created_at": { - "description": "Time the model was created in ISO 8601 format", - "format": "date-time", - "title": "Created At", - "type": "string" + "description": "Minimum log severity to include. Omit to return all log lines, including lines that have no level. Any explicit value returns lines at or above that severity and drops lines without a level." }, - "name": { - "description": "Name of the model", - "title": "Name", - "type": "string" + "replica": { + "anyOf": [ + { + "maxLength": 256, + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Only return logs emitted by this replica (5-char short ID).", + "title": "Replica" }, - "deployments_count": { - "description": "Number of deployments of the model", - "title": "Deployments Count", - "type": "integer" + "request_id": { + "anyOf": [ + { + "maxLength": 256, + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Only return logs tagged with this inference request ID.", + "title": "Request Id" }, - "production_deployment_id": { + "component": { "anyOf": [ { + "maxLength": 256, "type": "string" }, { "type": "null" } ], - "description": "Unique identifier of the production deployment of the model", - "title": "Production Deployment Id" + "default": null, + "description": "Only return logs from this component.", + "title": "Component" }, - "development_deployment_id": { + "search_pattern": { "anyOf": [ { + "maxLength": 256, "type": "string" }, { "type": "null" } ], - "description": "Unique identifier of the development deployment of the model", - "title": "Development Deployment Id" + "default": null, + "description": "RE2 regular expression matched against the log message. Prefer `includes` and `excludes` for plain substring matches.", + "title": "Search Pattern" }, - "instance_type_name": { - "description": "Name of the instance type for the production deployment of the model", - "title": "Instance Type Name", - "type": "string" + "includes": { + "description": "Case-sensitive substrings that must all appear in the log message.", + "items": { + "type": "string" + }, + "maxItems": 8, + "title": "Includes", + "type": "array" }, - "team_name": { - "description": "Name of the team associated with the model.", - "title": "Team Name", - "type": "string" + "excludes": { + "description": "Case-sensitive substrings; lines containing any of these are dropped.", + "items": { + "type": "string" + }, + "maxItems": 8, + "title": "Excludes", + "type": "array" } }, - "required": [ - "id", - "created_at", - "name", - "deployments_count", - "production_deployment_id", - "development_deployment_id", - "instance_type_name", - "team_name" - ], - "title": "ModelV1", + "title": "GetDeploymentLogsRequestV1", "type": "object" }, - "ModelsV1": { - "description": "A list of models.", + "DeploymentPatchActionV1": { + "description": "How a patch op changes its target.", + "enum": [ + "ADD", + "UPDATE", + "REMOVE" + ], + "title": "DeploymentPatchActionV1", + "type": "string" + }, + "DeploymentPatchOpConfigV1": { + "description": "Replace the config when config.yaml changes.\n\nConfig has no action: it is always a full replacement of the parsed config.\nDerived changes (environment variables, external data, requirements) are\nemitted as their own ops alongside this one.", "properties": { - "models": { - "items": { - "$ref": "#/components/schemas/ModelV1" - }, - "title": "Models", - "type": "array" + "type": { + "const": "config", + "default": "config", + "title": "Type", + "type": "string" + }, + "config": { + "additionalProperties": true, + "description": "The full parsed config as a JSON object.", + "title": "Config", + "type": "object" + }, + "path": { + "default": "config.yaml", + "description": "Config file path within the source.", + "title": "Path", + "type": "string" } }, "required": [ - "models" + "config" ], - "title": "ModelsV1", + "title": "DeploymentPatchOpConfigV1", "type": "object" }, - "ModelsRequestV1": { - "description": "Request parameters for listing models.", + "DeploymentPatchOpEnvVarV1": { + "description": "Add, update, or remove a single environment variable.", "properties": { + "type": { + "const": "environment_variable", + "default": "environment_variable", + "title": "Type", + "type": "string" + }, + "action": { + "$ref": "#/components/schemas/DeploymentPatchActionV1", + "description": "How this op changes the variable." + }, "name": { + "description": "The environment variable name.", + "title": "Name", + "type": "string" + }, + "value": { "anyOf": [ { "type": "string" @@ -14832,33 +18897,78 @@ } ], "default": null, - "description": "When set, returns only models with this exact name, if any. On a team-scoped route this matches at most one model; on the org-wide route it may match models in multiple teams, since names are unique only within a team.", - "title": "Name" + "description": "The environment variable value. Required for add and update.", + "title": "Value" } }, - "title": "ModelsRequestV1", + "required": [ + "action", + "name" + ], + "title": "DeploymentPatchOpEnvVarV1", "type": "object" }, - "LibraryListingSourceV1": { - "description": "Create a model by forking a library listing accessible to the caller's organization.", + "DeploymentPatchOpExternalDataV1": { + "description": "Add, update, or remove a single external data item.\n\nExternal data is referenced by config, not stored in the source. The backend\nonly adds or removes it, where adding re-downloads (overwriting any existing\nfile), so `update` is accepted and treated identically to `add`.", "properties": { - "kind": { - "const": "library_listing", - "default": "library_listing", - "title": "Kind", + "type": { + "const": "external_data", + "default": "external_data", + "title": "Type", "type": "string" }, - "lab_display_name": { - "description": "Identifier of the publishing organization, as returned by `GET /v1/library_models`.", - "title": "Lab Display Name", + "action": { + "$ref": "#/components/schemas/DeploymentPatchActionV1", + "description": "How this op changes the item. `UPDATE` is treated identically to `ADD`." + }, + "item": { + "additionalProperties": { + "type": "string" + }, + "description": "The single external data item descriptor.", + "title": "Item", + "type": "object" + } + }, + "required": [ + "action", + "item" + ], + "title": "DeploymentPatchOpExternalDataV1", + "type": "object" + }, + "DeploymentPatchOpModelCodeV1": { + "description": "Add, update, or remove a file under the model code directory.", + "properties": { + "type": { + "const": "model_code", + "default": "model_code", + "title": "Type", "type": "string" }, - "user_defined_listing_id": { - "description": "Listing identifier within the publishing organization.", - "title": "User Defined Listing Id", + "action": { + "$ref": "#/components/schemas/DeploymentPatchActionV1", + "description": "How this op changes the file." + }, + "path": { + "description": "File path relative to the model code directory.", + "title": "Path", "type": "string" }, - "deployed_model_name": { + "content": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "UTF-8 file content. Null for removals and binary files.", + "title": "Content" + }, + "content_bytes": { "anyOf": [ { "type": "string" @@ -14868,36 +18978,42 @@ } ], "default": null, - "description": "Optional name for the new deployed model. Defaults to the listing's configured name.", - "title": "Deployed Model Name" + "description": "Base64-encoded content for binary files.", + "title": "Content Bytes" + }, + "hot_reload": { + "default": false, + "description": "Whether the running server can pick up this change without a restart.", + "title": "Hot Reload", + "type": "boolean" } }, "required": [ - "lab_display_name", - "user_defined_listing_id" + "action", + "path" ], - "title": "LibraryListingSourceV1", + "title": "DeploymentPatchOpModelCodeV1", "type": "object" }, - "ModelArchiveSourceV1": { - "description": "Create a model from an archive previously uploaded via the credentials\nissued by `POST /v1/prepare_model_upload`.", + "DeploymentPatchOpPackageV1": { + "description": "Add, update, or remove a file under the bundled packages directory.", "properties": { - "kind": { - "const": "model_archive", - "default": "model_archive", - "title": "Kind", + "type": { + "const": "package", + "default": "package", + "title": "Type", "type": "string" }, - "name": { - "description": "Name of the new model.", - "title": "Name", - "type": "string" + "action": { + "$ref": "#/components/schemas/DeploymentPatchActionV1", + "description": "How this op changes the file." }, - "deployment": { - "$ref": "#/components/schemas/DeploymentArchivePayloadV1", - "description": "Deployment-level configuration for the model's first deployment." + "path": { + "description": "File path relative to the bundled packages directory.", + "title": "Path", + "type": "string" }, - "s3_key": { + "content": { "anyOf": [ { "type": "string" @@ -14907,512 +19023,573 @@ } ], "default": null, - "description": "S3 key of the uploaded archive, from the credentials returned by `POST /v1/prepare_model_upload`. Omit for model formats that are not built from an archive (for example, BIS-LLM), where prepare issues no upload target.", - "title": "S3 Key" + "description": "UTF-8 file content. Null for removals and binary files.", + "title": "Content" }, - "disable_archive_download": { - "default": false, - "description": "If true, the uploaded archive is not downloadable after creation. Locked at model creation; cannot be changed by subsequent deployments.", - "title": "Disable Archive Download", - "type": "boolean" - } - }, - "required": [ - "name", - "deployment" - ], - "title": "ModelArchiveSourceV1", - "type": "object" - }, - "CreateModelRequestV1": { - "description": "Body for creating a model via `POST /v1/models`.", - "properties": { - "source": { - "description": "Where the new model is created from.", - "discriminator": { - "mapping": { - "library_listing": "#/components/schemas/LibraryListingSourceV1", - "model_archive": "#/components/schemas/ModelArchiveSourceV1" - }, - "propertyName": "kind" - }, - "oneOf": [ + "content_bytes": { + "anyOf": [ { - "$ref": "#/components/schemas/LibraryListingSourceV1" + "type": "string" }, { - "$ref": "#/components/schemas/ModelArchiveSourceV1" + "type": "null" } ], - "title": "Source" + "default": null, + "description": "Base64-encoded content for binary files.", + "title": "Content Bytes" } }, "required": [ - "source" + "action", + "path" ], - "title": "CreateModelRequestV1", + "title": "DeploymentPatchOpPackageV1", "type": "object" }, - "AutoscalingSettingsV1": { - "description": "Autoscaling settings for a deployment.", + "DeploymentPatchOpPythonRequirementV1": { + "description": "Add, update, or remove a single Python requirement.", "properties": { - "min_replica": { - "description": "Minimum number of replicas", - "title": "Min Replica", - "type": "integer" - }, - "max_replica": { - "description": "Maximum number of replicas", - "title": "Max Replica", - "type": "integer" + "type": { + "const": "python_requirement", + "default": "python_requirement", + "title": "Type", + "type": "string" }, - "autoscaling_window": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Timeframe of traffic considered for autoscaling decisions", - "title": "Autoscaling Window" + "action": { + "$ref": "#/components/schemas/DeploymentPatchActionV1", + "description": "How this op changes the requirement." }, - "scale_down_delay": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Waiting period before scaling down any active replica", - "title": "Scale Down Delay" + "requirement": { + "description": "The requirement to apply. For removals this is the package name; otherwise the full requirements.txt-style line.", + "title": "Requirement", + "type": "string" + } + }, + "required": [ + "action", + "requirement" + ], + "title": "DeploymentPatchOpPythonRequirementV1", + "type": "object" + }, + "DeploymentPatchPointV1": { + "description": "A patch point: the source state the next patch is computed against.\n\nThe content hash that identifies a point is derived from this state (see\n`DeploymentPatchPointWithHashV1.hash`), so a request only sends the state and\nthe server stamps the hash. A previous point's hash plus the current local\nsource is enough to compute the next patch, so the watch client reads the\npoint it is patching off of.", + "properties": { + "content_hashes": { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "description": "Map of every non-ignored source path, relative and forward-slash, to its content hash: files map to the hex blake3 digest of their bytes, directories map to null. This is the full signature of the source tree and what the content hash is derived from.", + "title": "Content Hashes", + "type": "object" }, - "concurrency_target": { - "description": "Number of requests per replica before scaling up", - "title": "Concurrency Target", - "type": "integer" + "config": { + "description": "The verbatim config.yaml text for this source state.", + "title": "Config", + "type": "string" }, - "target_utilization_percentage": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Target utilization percentage for scaling up/down.", - "title": "Target Utilization Percentage" + "requirements": { + "description": "Requirements resolved from the config's requirements file, when it points at one. Empty when requirements are declared inline in the config.", + "items": { + "type": "string" + }, + "title": "Requirements", + "type": "array" + } + }, + "required": [ + "content_hashes", + "config" + ], + "title": "DeploymentPatchPointV1", + "type": "object" + }, + "CreateDeploymentPatchRequestV1": { + "description": "A patch to stage against the development deployment.\n\nStaging is durable on its own: the patch is persisted independently of the\nlater sync, so a failed sync does not lose it.", + "properties": { + "prev_patch_hash": { + "description": "Content hash of the patch point this patch is applied on - the link the staged patch must build on. A stale value (the base moved underneath the client) is rejected with a conflict.", + "title": "Prev Patch Hash", + "type": "string" }, - "target_in_flight_tokens": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null, - "description": "Target number of in-flight tokens for autoscaling decisions. Early access only.", - "title": "Target In Flight Tokens" + "next_patch_point": { + "$ref": "#/components/schemas/DeploymentPatchPointV1", + "description": "The source state after this patch. The server derives its content hash from `content_hashes`." }, - "max_scale_down_rate": { - "anyOf": [ - { - "type": "integer" + "patch_ops": { + "description": "The ordered ops that make up this patch. At least one op is required; a patch that changes nothing is not a valid request. There is no op for a directory: a directory comes into existence when the first file under it is added, and is removed when its last file is removed, so directory creation and deletion happen implicitly through the file ops. Adding or removing an otherwise empty directory therefore produces no ops even though it changes the source hash; do not send a patch request for such a change.", + "items": { + "discriminator": { + "mapping": { + "config": "#/components/schemas/DeploymentPatchOpConfigV1", + "environment_variable": "#/components/schemas/DeploymentPatchOpEnvVarV1", + "external_data": "#/components/schemas/DeploymentPatchOpExternalDataV1", + "model_code": "#/components/schemas/DeploymentPatchOpModelCodeV1", + "package": "#/components/schemas/DeploymentPatchOpPackageV1", + "python_requirement": "#/components/schemas/DeploymentPatchOpPythonRequirementV1" + }, + "propertyName": "type" }, - { - "type": "null" - } - ], - "default": null, - "description": "Maximum percentage of replicas that can be removed per autoscaling window (1\u201350). E.g. 20 means at most 20% of replicas are removed per window.", - "title": "Max Scale Down Rate" + "oneOf": [ + { + "$ref": "#/components/schemas/DeploymentPatchOpModelCodeV1" + }, + { + "$ref": "#/components/schemas/DeploymentPatchOpPackageV1" + }, + { + "$ref": "#/components/schemas/DeploymentPatchOpConfigV1" + }, + { + "$ref": "#/components/schemas/DeploymentPatchOpPythonRequirementV1" + }, + { + "$ref": "#/components/schemas/DeploymentPatchOpEnvVarV1" + }, + { + "$ref": "#/components/schemas/DeploymentPatchOpExternalDataV1" + } + ] + }, + "minItems": 1, + "title": "Patch Ops", + "type": "array" } }, "required": [ - "min_replica", - "max_replica", - "autoscaling_window", - "scale_down_delay", - "concurrency_target", - "target_utilization_percentage" + "prev_patch_hash", + "next_patch_point", + "patch_ops" ], - "title": "AutoscalingSettingsV1", + "title": "CreateDeploymentPatchRequestV1", "type": "object" }, - "DeploymentStatusV1": { - "description": "The status of a deployment.", - "enum": [ - "BUILDING", - "DEPLOYING", - "DEPLOY_FAILED", - "LOADING_MODEL", - "ACTIVE", - "UNHEALTHY", - "BUILD_FAILED", - "BUILD_STOPPED", - "DEACTIVATING", - "INACTIVE", - "FAILED", - "UPDATING", - "SCALED_TO_ZERO", - "WAKING_UP" - ], - "title": "DeploymentStatusV1", - "type": "string" - }, - "DeploymentV1": { - "description": "A deployment of a model.", + "DeploymentPatchPointWithHashV1": { + "description": "A patch point plus its server-assigned content hash, returned in responses.\n\nRequests omit the hash (the server derives it from the source state); responses\ninclude it so the watch client can echo it back as the next patch's\n`prev_patch_hash` without having to recompute the fold itself.", "properties": { - "id": { - "description": "Unique identifier of the deployment", - "title": "Id", - "type": "string" + "content_hashes": { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "description": "Map of every non-ignored source path, relative and forward-slash, to its content hash: files map to the hex blake3 digest of their bytes, directories map to null. This is the full signature of the source tree and what the content hash is derived from.", + "title": "Content Hashes", + "type": "object" }, - "created_at": { - "description": "Time the deployment was created in ISO 8601 format", - "format": "date-time", - "title": "Created At", + "config": { + "description": "The verbatim config.yaml text for this source state.", + "title": "Config", "type": "string" }, - "name": { - "description": "Name of the deployment", - "title": "Name", - "type": "string" + "requirements": { + "description": "Requirements resolved from the config's requirements file, when it points at one. Empty when requirements are declared inline in the config.", + "items": { + "type": "string" + }, + "title": "Requirements", + "type": "array" }, - "model_id": { - "description": "Unique identifier of the model", - "title": "Model Id", + "hash": { + "description": "Content hash identifying this exact source state, and the link patches build on. It is derived deterministically from `content_hashes`, so a request need not send it - the server derives it. It is derived by sorting the `content_hashes` keys as paths, splitting each key on '/' into its path components and ordering the keys by comparing those component lists element by element, each component compared by Unicode code point (equivalently UTF-8 byte order). Treating '/' as a path separator this way, rather than as the ordinary character U+002F, means a key that is an ancestor path sorts before a sibling whose name extends the first differing component (so e.g. 'a/b' sorts before 'a.b'). A blake3 hasher is then built, and for each key in that order updated with the blake3 digest (32 raw bytes) of the key encoded as UTF-8, then, when the entry is a file (non-null value), with that file's digest as 32 raw bytes. The stream uses raw digest bytes, but the values in `content_hashes` are those digests hex-encoded (64 hex chars), so decode each value from hex first. Directory entries (null value) contribute only their key digest. The result is the hasher's own hex digest.", + "title": "Hash", "type": "string" + } + }, + "required": [ + "content_hashes", + "config", + "hash" + ], + "title": "DeploymentPatchPointWithHashV1", + "type": "object" + }, + "CreateDeploymentPatchResponseV1": { + "description": "The created patch, represented by the patch point it produced.", + "properties": { + "patch_point": { + "$ref": "#/components/schemas/DeploymentPatchPointWithHashV1", + "description": "The resulting patch point the staged patch produced; matches the pending point a subsequent state read returns." + } + }, + "required": [ + "patch_point" + ], + "title": "CreateDeploymentPatchResponseV1", + "type": "object" + }, + "GetDeploymentPatchesStateResponseV1": { + "description": "The patch state of the development deployment.\n\nThe watch client computes its next patch off `pending_patch_point` when present,\nelse `running_patch_point`.", + "properties": { + "running_patch_point": { + "$ref": "#/components/schemas/DeploymentPatchPointWithHashV1", + "description": "The patch point the deployment is recorded as running." }, - "is_production": { - "description": "Whether the deployment is the production deployment of the model", - "title": "Is Production", - "type": "boolean" - }, - "is_development": { - "description": "Whether the deployment is the development deployment of the model", - "title": "Is Development", - "type": "boolean" - }, - "status": { - "$ref": "#/components/schemas/DeploymentStatusV1", - "description": "Status of the deployment" - }, - "active_replica_count": { - "description": "Number of active replicas", - "title": "Active Replica Count", - "type": "integer" - }, - "autoscaling_settings": { - "anyOf": [ - { - "$ref": "#/components/schemas/AutoscalingSettingsV1" - }, - { - "type": "null" - } - ], - "description": "Autoscaling settings for the deployment. If null, the model has not finished deploying" - }, - "instance_type_name": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Name of the instance type the model deployment is running on", - "title": "Instance Type Name" - }, - "environment": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "The environment associated with the deployment", - "title": "Environment" - }, - "labels": { - "anyOf": [ - { - "additionalProperties": true, - "type": "object" - }, - { - "type": "null" - } - ], - "default": null, - "description": "User-provided key-value labels for the deployment", - "title": "Labels" - }, - "region": { + "pending_patch_point": { "anyOf": [ { - "$ref": "#/components/schemas/RegionV1" + "$ref": "#/components/schemas/DeploymentPatchPointWithHashV1" }, { "type": "null" } ], "default": null, - "description": "The selected region for the deployment, if any" - }, - "request_backpressure_settings": { - "$ref": "#/components/schemas/RequestBackpressureSettingsV1", - "description": "Effective request backpressure settings for the deployment." + "description": "The latest staged-but-unsynced patch point, or null when the deployment is recorded as caught up." } }, "required": [ - "id", - "created_at", - "name", - "model_id", - "is_production", - "is_development", - "status", - "active_replica_count", - "autoscaling_settings", - "instance_type_name", - "environment", - "request_backpressure_settings" + "running_patch_point" ], - "title": "DeploymentV1", + "title": "GetDeploymentPatchesStateResponseV1", "type": "object" }, - "RequestBackpressurePolicyV1": { - "enum": [ - "QUEUE_ON_FULL", - "REJECT_ON_FULL" - ], - "title": "RequestBackpressurePolicyV1", - "type": "string" + "SyncDeploymentPatchesRequestV1": { + "description": "Triggers a sync of any staged patches to the running deployment. Takes no\nfields: the deployment and its staged patches fully determine the sync.", + "properties": {}, + "title": "SyncDeploymentPatchesRequestV1", + "type": "object" }, - "RequestBackpressureSettingsV1": { - "description": "Request backpressure settings for a deployment or environment.", + "SyncDeploymentPatchesResponseV1": { + "description": "The outcome of a sync that ran.\n\nOperational failures (a transient patch failure, an invalid patch sequence)\nare surfaced as HTTP errors rather than fields here, so a 2xx means the sync\nreached a verdict.", "properties": { - "policy": { + "needs_full_deploy_reason": { "anyOf": [ { - "$ref": "#/components/schemas/RequestBackpressurePolicyV1" + "type": "string" }, { "type": "null" } - ], - "default": null, - "description": "Backpressure policy. Null when no policy is set." - } - }, - "title": "RequestBackpressureSettingsV1", - "type": "object" - }, - "CreatedModelDeploymentV1": { - "description": "A newly created deployment and its model.", - "properties": { - "model": { - "$ref": "#/components/schemas/ModelV1", - "description": "The model the deployment belongs to. May have been created by this call." - }, - "deployment": { - "$ref": "#/components/schemas/DeploymentV1", - "description": "The newly created deployment." + ], + "default": null, + "description": "If set, the change cannot be patched and a full push is required; the value explains why. If null, the deployment is now in sync.", + "title": "Needs Full Deploy Reason" } }, - "required": [ - "model", - "deployment" - ], - "title": "CreatedModelDeploymentV1", + "title": "SyncDeploymentPatchesResponseV1", "type": "object" }, - "ModelTombstoneV1": { - "description": "A model tombstone.", + "ModelMetricDescriptorV1": { + "description": "Describes one metric. Its position in the response ``metric_descriptors``\nlist is the index used to read that metric out of each value set's ``values``.\n\nA metric may break down into multiple labeled series (e.g. latency quantiles,\nor volume by status). ``label_sets`` enumerates those series in order; each\nvalue set's value for this metric is a list aligned to that order.", "properties": { - "id": { - "description": "Unique identifier of the model", - "title": "Id", + "name": { + "description": "Canonical metric name.", + "title": "Name", "type": "string" }, - "deleted": { - "description": "Whether the model was deleted", - "title": "Deleted", - "type": "boolean" + "unit_hint": { + "$ref": "#/components/schemas/ModelMetricUnitHintV1", + "description": "Advisory unit of the metric's values." + }, + "kind": { + "$ref": "#/components/schemas/ModelMetricKindV1", + "description": "Semantic hint for how the metric behaves (GAUGE, COUNTER, HISTOGRAM)." + }, + "label_sets": { + "description": "The metric's series, in order. Each entry is the set of labels identifying one series; the value at the same index in each value set's ``values`` is that series' value. A plain metric has a single entry with no labels (`{}`). A histogram has one entry per quantile plus an average, e.g. {'quantile': '0.5'} \u2026 {'quantile': '0.99'}, {'stat': 'avg'}. A by-status metric has one entry per status, e.g. {'status': '2xx'}.", + "items": { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + "title": "Label Sets", + "type": "array" } }, "required": [ - "id", - "deleted" + "name", + "unit_hint", + "kind", + "label_sets" ], - "title": "ModelTombstoneV1", + "title": "ModelMetricDescriptorV1", "type": "object" }, - "DeploymentsV1": { - "description": "A list of deployments of a model.", + "ModelMetricKindV1": { + "description": "Semantic hint for how a metric behaves, to aid client rendering and\naggregation. It does not describe the value's shape (that is carried by the\ndescriptor's ``label_sets``; a metric may break down into multiple series).\n\n- ``GAUGE``: an instantaneous value (e.g. queue size, running requests).\n- ``COUNTER``: a cumulative total over the step (e.g. tokens, restarts).\n- ``HISTOGRAM``: a distribution, exposed as quantile/average series.", + "enum": [ + "GAUGE", + "COUNTER", + "HISTOGRAM" + ], + "title": "ModelMetricKindV1", + "type": "string" + }, + "ModelMetricModeV1": { + "description": "How metric values are aggregated over the request.", + "enum": [ + "CURRENT", + "SUMMARY", + "SERIES" + ], + "title": "ModelMetricModeV1", + "type": "string" + }, + "ModelMetricUnitHintV1": { + "description": "Advisory unit of a metric's values. Values are reported as scraped, so the\nhint describes the raw value (e.g. GPU memory is reported in mebibytes).\n\n- ``PER_SECOND``: a rate per second.\n- ``SECONDS``: a duration in seconds.\n- ``BYTES``: a size in bytes.\n- ``MEBIBYTES``: a size in mebibytes (MiB).\n- ``COUNT``: a dimensionless tally of discrete things.\n- ``RATIO``: a dimensionless ratio. Usually in ``[0, 1]`` but may exceed 1\n (e.g. CPU usage in cores = cpu-seconds/second).", + "enum": [ + "PER_SECOND", + "SECONDS", + "BYTES", + "MEBIBYTES", + "COUNT", + "RATIO" + ], + "title": "ModelMetricUnitHintV1", + "type": "string" + }, + "ModelMetricValueSetV1": { + "description": "The metric values for one time step. ``values`` is aligned by index to the\nresponse ``metric_descriptors`` list.", "properties": { - "deployments": { - "description": "A list of deployments of a model", + "start_epoch_millis": { + "description": "Start of the step. The step spans until the next value set's start, or the window end for the last one; a summary has a single value set starting at the window start.", + "title": "Start Epoch Millis", + "type": "integer" + }, + "values": { + "description": "Metric values aligned to the ``metric_descriptors`` index. Each entry is a list aligned to that descriptor's ``label_sets`` (a single-element list for a plain metric). A series with no data in this step is null.", "items": { - "$ref": "#/components/schemas/DeploymentV1" + "items": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ] + }, + "type": "array" }, - "title": "Deployments", + "title": "Values", "type": "array" } }, "required": [ - "deployments" + "start_epoch_millis", + "values" ], - "title": "DeploymentsV1", + "title": "ModelMetricValueSetV1", "type": "object" }, - "DeploymentsRequestV1": { - "description": "Request parameters for listing a model's deployments.", + "GetModelMetricsResponseV1": { + "description": "Model metrics over a time window, index-mapped: metric descriptors appear once\nin ``metric_descriptors``; each value set's ``values`` are aligned to that order.", "properties": { - "name": { + "start_epoch_millis": { + "description": "Start of the returned window.", + "title": "Start Epoch Millis", + "type": "integer" + }, + "end_epoch_millis": { + "description": "End of the returned window.", + "title": "End Epoch Millis", + "type": "integer" + }, + "mode": { + "$ref": "#/components/schemas/ModelMetricModeV1", + "description": "The aggregation mode used." + }, + "step_seconds": { "anyOf": [ { - "type": "string" + "type": "integer" }, { "type": "null" } ], - "default": null, - "description": "When set, returns only the deployment with this exact name, if any.", - "title": "Name" + "description": "Seconds per step; populated only in SERIES mode, null otherwise.", + "title": "Step Seconds" + }, + "metric_descriptors": { + "description": "Descriptors for each metric; position defines the values index.", + "items": { + "$ref": "#/components/schemas/ModelMetricDescriptorV1" + }, + "title": "Metric Descriptors", + "type": "array" + }, + "metric_values": { + "description": "Metric values per time step covering the window. In summary mode this always contains exactly one value set spanning the whole window.", + "items": { + "$ref": "#/components/schemas/ModelMetricValueSetV1" + }, + "title": "Metric Values", + "type": "array" } }, - "title": "DeploymentsRequestV1", + "required": [ + "start_epoch_millis", + "end_epoch_millis", + "mode", + "step_seconds", + "metric_descriptors", + "metric_values" + ], + "title": "GetModelMetricsResponseV1", "type": "object" }, - "DeploymentArchiveSourceV1": { - "description": "Add a deployment from an archive previously uploaded via the credentials\nissued by `POST /v1/prepare_model_upload`.", + "GetDeploymentMetricsRequestV1": { + "description": "Query params for ``GET /v1/models/.../deployments/.../metrics``.", "properties": { - "kind": { - "const": "model_archive", - "default": "model_archive", - "title": "Kind", - "type": "string" + "mode": { + "$ref": "#/components/schemas/ModelMetricModeV1", + "default": "CURRENT", + "description": "'CURRENT': a single instantaneous snapshot at now; start/end must be omitted. 'SUMMARY': a single value set aggregating the whole window. 'SERIES': evenly-spaced value sets across the window, with the step derived from the window duration." }, - "deployment": { - "$ref": "#/components/schemas/DeploymentArchivePayloadV1", - "description": "Deployment-level configuration." + "start_epoch_millis": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Epoch millis timestamp to start fetching metrics. Defaults to one hour before the end.", + "title": "Start Epoch Millis" }, - "s3_key": { + "end_epoch_millis": { "anyOf": [ { - "type": "string" + "type": "integer" }, { "type": "null" } ], "default": null, - "description": "S3 key of the uploaded archive, from the credentials returned by `POST /v1/prepare_model_upload`. Omit for model formats that are not built from an archive (for example, BIS-LLM), where prepare issues no upload target.", - "title": "S3 Key" + "description": "Epoch millis timestamp to end fetching metrics. Defaults to the current time. The window between start and end must not exceed 7 days.", + "title": "End Epoch Millis" + }, + "metrics": { + "description": "Names of the metrics to return; see https://docs.baseten.co/observability/export-metrics/supported-metrics for the available names. When omitted, a default set is returned: baseten_replicas_active, baseten_inference_requests_total, and baseten_end_to_end_response_time_seconds. Unknown names are rejected; valid names that do not apply are omitted from the response.", + "items": { + "type": "string" + }, + "title": "Metrics", + "type": "array" } }, - "required": [ - "deployment" - ], - "title": "DeploymentArchiveSourceV1", + "title": "GetDeploymentMetricsRequestV1", "type": "object" }, - "CreateModelDeploymentRequestV1": { - "description": "Body for adding a deployment to an existing model via\n`POST /v1/models/{model_id}/deployments`.", + "TerminateReplicaResponseV1": { + "description": "The response to a request to terminate a replica in a deployment.", "properties": { - "source": { - "description": "Where the new deployment is created from.", - "discriminator": { - "mapping": { - "model_archive": "#/components/schemas/DeploymentArchiveSourceV1" + "success": { + "default": true, + "description": "Whether the replica was successfully terminated", + "title": "Success", + "type": "boolean" + } + }, + "title": "TerminateReplicaResponseV1", + "type": "object" + }, + "SignSSHCertificateRequestV1": { + "description": "Request to sign an SSH certificate for accessing a workload pod.", + "properties": { + "public_key": { + "description": "The user's SSH public key (e.g., 'ssh-ed25519 AAAA... user@host').", + "title": "Public Key", + "type": "string" + }, + "replica_id": { + "anyOf": [ + { + "type": "string" }, - "propertyName": "kind" - }, - "oneOf": [ { - "$ref": "#/components/schemas/DeploymentArchiveSourceV1" + "type": "null" } ], - "title": "Source" + "default": null, + "description": "The replica to connect to. Required for training jobs (e.g. '0'). Optional for inference (server picks a running replica if omitted).", + "title": "Replica Id" } }, "required": [ - "source" + "public_key" ], - "title": "CreateModelDeploymentRequestV1", + "title": "SignSSHCertificateRequestV1", "type": "object" }, - "DeploymentTombstoneV1": { - "description": "A model deployment tombstone.", + "SignSSHCertificateResponseV1": { + "description": "Response containing a signed SSH certificate for proxy authentication.", "properties": { - "id": { - "description": "Unique identifier of the deployment", - "title": "Id", + "ssh_certificate": { + "description": "The signed SSH certificate in OpenSSH format.", + "title": "Ssh Certificate", "type": "string" }, - "deleted": { - "description": "Whether the deployment was deleted", - "title": "Deleted", - "type": "boolean" + "jwt": { + "description": "Signed JWT (ES256) for SSH proxy authorization.", + "title": "Jwt", + "type": "string" }, - "model_id": { - "description": "Unique identifier of the model", - "title": "Model Id", + "proxy_address": { + "description": "Address of the SSH proxy to connect to (host:port).", + "title": "Proxy Address", + "type": "string" + }, + "ssh_cert_expires_at": { + "description": "When the certificate expires, in ISO 8601 format.", + "format": "date-time", + "title": "Ssh Cert Expires At", "type": "string" } }, "required": [ - "id", - "deleted", - "model_id" + "ssh_certificate", + "jwt", + "proxy_address", + "ssh_cert_expires_at" ], - "title": "DeploymentTombstoneV1", + "title": "SignSSHCertificateResponseV1", "type": "object" }, - "UpdateDeploymentRequestV1": { - "additionalProperties": false, - "description": "A request to update a deployment.", + "AutoscalingScheduleSettingsV1": { "properties": { - "name": { + "min_replica": { + "description": "Minimum number of replicas", + "title": "Min Replica", + "type": "integer" + }, + "max_replica": { + "description": "Maximum number of replicas", + "title": "Max Replica", + "type": "integer" + }, + "autoscaling_window": { "anyOf": [ { - "maxLength": 255, - "minLength": 1, - "type": "string" + "type": "integer" }, { "type": "null" } ], - "default": null, - "description": "New name for the deployment, unique among the model's deployments. Only alphanumeric characters, hyphens, underscores, and periods are allowed.", - "examples": [ - "my-deployment" - ], - "title": "Name" - } - }, - "title": "UpdateDeploymentRequestV1", - "type": "object" - }, - "UpdateAutoscalingSettingsV1": { - "additionalProperties": false, - "description": "A request to update autoscaling settings for a deployment. All fields are optional, and we only update ones passed in.", - "properties": { - "min_replica": { + "description": "Timeframe of traffic considered for autoscaling decisions. Null inherits the environment value.", + "title": "Autoscaling Window" + }, + "scale_down_delay": { "anyOf": [ { "type": "integer" @@ -15421,14 +19598,10 @@ "type": "null" } ], - "default": null, - "description": "Minimum number of replicas", - "examples": [ - 0 - ], - "title": "Min Replica" + "description": "Waiting period before scaling down any active replica. Null inherits the environment value.", + "title": "Scale Down Delay" }, - "max_replica": { + "concurrency_target": { "anyOf": [ { "type": "integer" @@ -15437,14 +19610,10 @@ "type": "null" } ], - "default": null, - "description": "Maximum number of replicas", - "examples": [ - 7 - ], - "title": "Max Replica" + "description": "Number of requests per replica before scaling up. Null inherits the environment value.", + "title": "Concurrency Target" }, - "autoscaling_window": { + "target_utilization_percentage": { "anyOf": [ { "type": "integer" @@ -15453,14 +19622,22 @@ "type": "null" } ], - "default": null, - "description": "Timeframe of traffic considered for autoscaling decisions", - "examples": [ - 600 + "description": "Target utilization percentage for scaling up/down. Null inherits the environment value.", + "title": "Target Utilization Percentage" + }, + "target_in_flight_tokens": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } ], - "title": "Autoscaling Window" + "description": "Target number of in-flight tokens for autoscaling decisions. Null inherits the environment value. Early access only.", + "title": "Target In Flight Tokens" }, - "scale_down_delay": { + "max_scale_down_rate": { "anyOf": [ { "type": "integer" @@ -15469,14 +19646,88 @@ "type": "null" } ], - "default": null, - "description": "Waiting period before scaling down any active replica", - "examples": [ - 120 + "description": "Maximum percentage of replicas that can be removed per autoscaling window. Null inherits the environment value.", + "title": "Max Scale Down Rate" + } + }, + "required": [ + "min_replica", + "max_replica", + "autoscaling_window", + "scale_down_delay", + "concurrency_target", + "target_utilization_percentage", + "target_in_flight_tokens", + "max_scale_down_rate" + ], + "title": "AutoscalingScheduleSettingsV1", + "type": "object" + }, + "AutoscalingScheduleStateV1": { + "properties": { + "schedule_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } ], - "title": "Scale Down Delay" + "description": "Stable schedule identifier, or null when the baseline settings apply", + "title": "Schedule Id" }, - "concurrency_target": { + "autoscaling_settings": { + "$ref": "#/components/schemas/AutoscalingSettingsV1", + "description": "Autoscaling settings on the current serving deployment. In a PATCH response, this snapshot can precede asynchronous schedule reconciliation; poll the GET endpoint for the applied state." + } + }, + "required": [ + "schedule_id", + "autoscaling_settings" + ], + "title": "AutoscalingScheduleStateV1", + "type": "object" + }, + "AutoscalingScheduleV1": { + "properties": { + "id": { + "description": "Stable unique identifier of the schedule", + "title": "Id", + "type": "string" + }, + "name": { + "description": "Name of the schedule", + "title": "Name", + "type": "string" + }, + "enabled": { + "description": "Whether the schedule is enabled", + "title": "Enabled", + "type": "boolean" + }, + "autoscaling_settings": { + "$ref": "#/components/schemas/AutoscalingScheduleSettingsV1", + "description": "Raw autoscaling overrides applied during the schedule window" + }, + "cadence": { + "description": "Cadence of the schedule. DAILY runs once per selected weekday; HOURLY repeats the minute window every hour on selected weekdays.", + "enum": [ + "DAILY", + "HOURLY" + ], + "title": "Cadence", + "type": "string" + }, + "weekdays": { + "description": "Weekdays on which the schedule runs", + "items": { + "$ref": "#/components/schemas/AutoscalingScheduleWeekdayV1" + }, + "title": "Weekdays", + "type": "array" + }, + "start_hour": { "anyOf": [ { "type": "integer" @@ -15486,13 +19737,15 @@ } ], "default": null, - "description": "Number of requests per replica before scaling up", - "examples": [ - 2 - ], - "title": "Concurrency Target" + "description": "Start hour in the environment schedule timezone. Omitted for unrestricted HOURLY schedules.", + "title": "Start Hour" }, - "target_utilization_percentage": { + "start_minute": { + "description": "Start minute of the schedule window", + "title": "Start Minute", + "type": "integer" + }, + "end_hour": { "anyOf": [ { "type": "integer" @@ -15502,306 +19755,220 @@ } ], "default": null, - "description": "Target utilization percentage for scaling up/down.", - "examples": [ - 70 - ], - "title": "Target Utilization Percentage" + "description": "End hour in the environment schedule timezone. Omitted for unrestricted HOURLY schedules.", + "title": "End Hour" }, - "target_in_flight_tokens": { + "end_minute": { + "description": "End minute of the schedule window", + "title": "End Minute", + "type": "integer" + } + }, + "required": [ + "id", + "name", + "enabled", + "autoscaling_settings", + "cadence", + "weekdays", + "start_minute", + "end_minute" + ], + "title": "AutoscalingScheduleV1", + "type": "object" + }, + "AutoscalingScheduleWeekdayV1": { + "enum": [ + "SUNDAY", + "MONDAY", + "TUESDAY", + "WEDNESDAY", + "THURSDAY", + "FRIDAY", + "SATURDAY" + ], + "title": "AutoscalingScheduleWeekdayV1", + "type": "string" + }, + "EnvironmentAutoscalingSchedulesV1": { + "properties": { + "timezone": { "anyOf": [ { - "type": "integer" + "type": "string" }, { "type": "null" } ], "default": null, - "description": "Target number of in-flight tokens for autoscaling decisions. Early access only.", - "examples": [ - 40000 - ], - "title": "Target In Flight Tokens" + "description": "IANA timezone shared by all schedules. Omitted when no schedules exist.", + "title": "Timezone" }, - "max_scale_down_rate": { + "schedules": { + "description": "Autoscaling schedules ordered by creation time and stable identifier", + "items": { + "discriminator": { + "mapping": { + "DAILY": "#/components/schemas/AutoscalingScheduleV1", + "HOURLY": "#/components/schemas/AutoscalingScheduleV1", + "ONE_TIME": "#/components/schemas/OneTimeAutoscalingScheduleV1" + }, + "propertyName": "cadence" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/AutoscalingScheduleV1" + }, + { + "$ref": "#/components/schemas/OneTimeAutoscalingScheduleV1" + } + ] + }, + "title": "Schedules", + "type": "array" + }, + "applied_state": { "anyOf": [ { - "maximum": 50, - "minimum": 1, - "type": "integer" + "$ref": "#/components/schemas/AutoscalingScheduleStateV1" }, { "type": "null" } ], - "default": null, - "description": "Maximum percentage of replicas that can be removed per autoscaling window (1\u201350). E.g. 20 means at most 20% of replicas are removed per window.", - "examples": [ - 20 - ], - "title": "Max Scale Down Rate" - } - }, - "title": "UpdateAutoscalingSettingsV1", - "type": "object" - }, - "UpdateAutoscalingSettingsStatusV1": { - "description": "The status of a request to update autoscaling settings.", - "enum": [ - "ACCEPTED", - "QUEUED", - "UNCHANGED" - ], - "title": "UpdateAutoscalingSettingsStatusV1", - "type": "string" - }, - "UpdateAutoscalingSettingsResponseV1": { - "description": "The response to a request to update autoscaling settings.", - "properties": { - "status": { - "$ref": "#/components/schemas/UpdateAutoscalingSettingsStatusV1", - "description": "Status of the request to update autoscaling settings" - }, - "message": { - "description": "A message describing the status of the request to update autoscaling settings", - "title": "Message", - "type": "string" + "description": "Autoscaling state on the current serving deployment, or null when no deployment exists" } }, "required": [ - "status", - "message" + "schedules", + "applied_state" ], - "title": "UpdateAutoscalingSettingsResponseV1", + "title": "EnvironmentAutoscalingSchedulesV1", "type": "object" }, - "UpdateRequestBackpressureSettingsV1": { - "additionalProperties": false, - "description": "A request to update request backpressure settings.", + "EnvironmentV1": { + "description": "Environment for oracles.", "properties": { - "policy": { + "name": { + "description": "Name of the environment", + "title": "Name", + "type": "string" + }, + "created_at": { + "description": "Time the environment was created in ISO 8601 format", + "format": "date-time", + "title": "Created At", + "type": "string" + }, + "model_id": { + "description": "Unique identifier of the model", + "title": "Model Id", + "type": "string" + }, + "current_deployment": { "anyOf": [ { - "$ref": "#/components/schemas/RequestBackpressurePolicyV1" + "$ref": "#/components/schemas/DeploymentV1" }, { "type": "null" } ], - "default": null, - "description": "Backpressure policy to apply. Null indicates no policy (on update, clears an existing one).", - "examples": [ - "REJECT_ON_FULL" - ], - "x-null-distinct": true - } - }, - "title": "UpdateRequestBackpressureSettingsV1", - "type": "object" - }, - "PromoteRequestV1": { - "description": "A request to promote a deployment to production.", - "properties": { - "scale_down_previous_production": { - "default": true, - "description": "Whether to scale down the previous production deployment after promoting", - "examples": [ - true - ], - "title": "Scale Down Previous Production", - "type": "boolean" - }, - "preserve_env_instance_type": { - "default": true, - "description": "Whether to use the promoting deployment's instance type or preserve target environment's instance type", - "examples": [ - true - ], - "title": "Preserve Env Instance Type", - "type": "boolean" - } - }, - "title": "PromoteRequestV1", - "type": "object" - }, - "ActivateResponseV1": { - "description": "The response to a request to activate a deployment.", - "properties": { - "success": { - "default": true, - "description": "Whether the deployment was successfully activated", - "title": "Success", - "type": "boolean" - }, - "no_op": { - "default": false, - "description": "Whether the request did nothing because the deployment was already active or on its way to becoming active", - "title": "No Op", - "type": "boolean" - } - }, - "title": "ActivateResponseV1", - "type": "object" - }, - "DeactivateResponseV1": { - "description": "The response to a request to deactivate a deployment.", - "properties": { - "success": { - "default": true, - "description": "Whether the deployment was successfully deactivated", - "title": "Success", - "type": "boolean" - }, - "no_op": { - "default": false, - "description": "Whether the request did nothing because the deployment was already inactive", - "title": "No Op", - "type": "boolean" - } - }, - "title": "DeactivateResponseV1", - "type": "object" - }, - "RetryDeploymentResponseV1": { - "description": "The response to a request to retry a deployment.", - "properties": { - "retried": { - "description": "Whether the retry was successfully initiated", - "title": "Retried", - "type": "boolean" + "description": "Current deployment of the environment" }, - "reason": { + "candidate_deployment": { "anyOf": [ { - "type": "string" + "$ref": "#/components/schemas/DeploymentV1" }, { "type": "null" } ], "default": null, - "description": "Explanation of the result. Provided when retried is false to explain why retry was not possible.", - "title": "Reason" + "description": "Candidate deployment being promoted to the environment, if a promotion is in progress" }, - "deployment": { - "$ref": "#/components/schemas/DeploymentV1", - "description": "The deployment that was retried" - } - }, - "required": [ - "retried", - "deployment" - ], - "title": "RetryDeploymentResponseV1", - "type": "object" - }, - "DownloadDeploymentResponseV1": { - "description": "The response to a request to download a deployment's truss.", - "properties": { - "download_url": { - "description": "Presigned URL to download the truss tar file", - "title": "Download Url", - "type": "string" - } - }, - "required": [ - "download_url" - ], - "title": "DownloadDeploymentResponseV1", - "type": "object" - }, - "DeploymentConfigResponseV1": { - "description": "The config of a deployment. Fields are populated per `output_format`.", - "properties": { - "config": { + "in_progress_promotion": { "anyOf": [ { - "additionalProperties": true, - "type": "object" + "$ref": "#/components/schemas/InProgressPromotionV1" }, { "type": "null" } ], "default": null, - "description": "The parsed config of the deployment.", - "title": "Config" + "description": "Details of the in-progress promotion, if any" + }, + "autoscaling_settings": { + "$ref": "#/components/schemas/AutoscalingSettingsV1", + "description": "Autoscaling settings for the environment" + }, + "promotion_settings": { + "$ref": "#/components/schemas/PromotionSettingsV1", + "description": "Promotion settings for the environment" + }, + "instance_type": { + "$ref": "#/components/schemas/InstanceTypeV1", + "description": "Instance type for the environment" + }, + "request_backpressure_settings": { + "$ref": "#/components/schemas/RequestBackpressureSettingsV1", + "description": "Request backpressure settings for the environment." }, - "raw_config": { + "autoscaling_schedules": { "anyOf": [ { - "type": "string" + "$ref": "#/components/schemas/EnvironmentAutoscalingSchedulesV1" }, { "type": "null" } ], "default": null, - "description": "The original config.yaml text \u2014 preserves comments, ordering, formatting.", - "title": "Raw Config" + "description": "Autoscaling schedules and their evaluated state" } }, - "title": "DeploymentConfigResponseV1", - "type": "object" - }, - "DeploymentConfigOutputFormat": { - "enum": [ - "raw", - "parsed", - "both" + "required": [ + "name", + "created_at", + "model_id", + "current_deployment", + "autoscaling_settings", + "promotion_settings", + "instance_type", + "request_backpressure_settings" ], - "title": "DeploymentConfigOutputFormat", - "type": "string" - }, - "GetDeploymentConfigRequestV1": { - "description": "Query params for ``GET /v1/models/.../deployments/.../config``.", - "properties": { - "output_format": { - "$ref": "#/components/schemas/DeploymentConfigOutputFormat", - "default": "both", - "description": "'raw': verbatim config.yaml with comments (not available for deployments created before 2026-04-30). 'parsed': dict with server-side defaults applied (always available). 'both': both fields populated." - } - }, - "title": "GetDeploymentConfigRequestV1", + "title": "EnvironmentV1", "type": "object" }, - "LogLevelV1": { - "description": "A log severity level.", + "InProgressPromotionStatusV1": { "enum": [ - "DEBUG", - "INFO", - "WARNING", - "ERROR" + "RELEASING", + "RAMPING_UP", + "RAMPING_DOWN", + "PAUSED", + "SUCCEEDED", + "FAILED", + "CANCELED" ], - "title": "LogLevelV1", + "title": "InProgressPromotionStatusV1", "type": "string" }, - "LogV1": { + "InProgressPromotionV1": { + "description": "Details of an in-progress promotion.", "properties": { - "timestamp": { - "description": "Epoch nanosecond timestamp of the log message.", - "title": "Timestamp", - "type": "string" - }, - "message": { - "description": "The contents of the log message. When the logger captured an exception, the traceback is appended after the message.", - "title": "Message", - "type": "string" + "status": { + "$ref": "#/components/schemas/InProgressPromotionStatusV1", + "description": "Status of the promotion" }, - "replica": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "description": "The replica the log line was emitted from.", - "title": "Replica" + "percent_traffic_to_new_version": { + "description": "Percentage of traffic routed to the candidate deployment", + "title": "Percent Traffic To New Version", + "type": "integer" }, - "request_id": { + "error_message": { "anyOf": [ { "type": "string" @@ -15811,824 +19978,704 @@ } ], "default": null, - "description": "The request ID associated with an inference request.", - "title": "Request Id" + "description": "Error message if promotion failed", + "title": "Error Message" }, - "level": { + "rolling_deploy": { "anyOf": [ { - "$ref": "#/components/schemas/LogLevelV1" + "type": "boolean" }, { "type": "null" } ], "default": null, - "description": "Severity of the log line, if one was detected. null when unknown." + "description": "Whether this is a rolling deploy", + "title": "Rolling Deploy" } }, "required": [ - "timestamp", - "message", - "replica" + "status", + "percent_traffic_to_new_version" ], - "title": "LogV1", + "title": "InProgressPromotionV1", "type": "object" }, - "GetLogsResponseV1": { - "description": "A response to querying logs.", + "OneTimeAutoscalingScheduleV1": { "properties": { - "logs": { - "description": "Logs for a specific entity.", - "items": { - "$ref": "#/components/schemas/LogV1" - }, - "title": "Logs", - "type": "array" + "id": { + "description": "Stable unique identifier of the schedule", + "title": "Id", + "type": "string" + }, + "name": { + "description": "Name of the schedule", + "title": "Name", + "type": "string" + }, + "enabled": { + "description": "Whether the schedule is enabled", + "title": "Enabled", + "type": "boolean" + }, + "autoscaling_settings": { + "$ref": "#/components/schemas/AutoscalingScheduleSettingsV1", + "description": "Raw autoscaling overrides applied during the schedule window" + }, + "cadence": { + "const": "ONE_TIME", + "description": "One-time schedule cadence", + "title": "Cadence", + "type": "string" + }, + "start_at": { + "description": "Inclusive start of the schedule window", + "format": "date-time", + "title": "Start At", + "type": "string" + }, + "end_at": { + "description": "Exclusive end of the schedule window", + "format": "date-time", + "title": "End At", + "type": "string" } }, "required": [ - "logs" + "id", + "name", + "enabled", + "autoscaling_settings", + "cadence", + "start_at", + "end_at" ], - "title": "GetLogsResponseV1", + "title": "OneTimeAutoscalingScheduleV1", "type": "object" }, - "SortOrderV1": { + "PromotionCleanupStrategyV1": { + "description": "The promotion cleanup strategy.", "enum": [ - "asc", - "desc" + "KEEP", + "SCALE_TO_ZERO", + "DEACTIVATE" ], - "title": "SortOrderV1", + "title": "PromotionCleanupStrategyV1", "type": "string" }, - "GetDeploymentLogsRequestV1": { - "description": "A request to fetch deployment logs.", + "PromotionSettingsV1": { + "description": "Promotion settings for promoting chains and oracles", "properties": { - "start_epoch_millis": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null, - "description": "Epoch milliseconds at which to start fetching logs. Defaults to 30 minutes before the end. The window from start to end must not exceed 7 days.", - "title": "Start Epoch Millis" - }, - "end_epoch_millis": { + "redeploy_on_promotion": { "anyOf": [ { - "type": "integer" + "type": "boolean" }, { "type": "null" } ], - "default": null, - "description": "Epoch milliseconds at which to stop fetching logs. Defaults to the current time.", - "title": "End Epoch Millis" - }, - "direction": { - "anyOf": [ - { - "$ref": "#/components/schemas/SortOrderV1" - }, - { - "type": "null" - } + "default": false, + "description": "Whether to deploy on all promotions. Enabling this flag allows model code to safely handle environment-specific logic. When a deployment is promoted, a new deployment will be created with a copy of the image.", + "examples": [ + true ], - "default": null, - "description": "Sort order for logs" + "title": "Redeploy On Promotion" }, - "limit": { + "rolling_deploy": { "anyOf": [ { - "maximum": 1000, - "minimum": 1, - "type": "integer" + "type": "boolean" }, { "type": "null" } ], - "default": 500, - "description": "Limit of logs to fetch in a single request", - "title": "Limit" - }, - "min_level": { - "anyOf": [ - { - "$ref": "#/components/schemas/LogLevelV1" - }, - { - "type": "null" - } + "default": false, + "description": "Whether the environment should rely on rolling deploy orchestration.", + "examples": [ + true ], - "default": null, - "description": "Minimum log severity to include. Omit to return all log lines, including lines that have no level. Any explicit value returns lines at or above that severity and drops lines without a level." + "title": "Rolling Deploy" }, - "replica": { + "promotion_cleanup_strategy": { "anyOf": [ { - "maxLength": 256, - "type": "string" + "$ref": "#/components/schemas/PromotionCleanupStrategyV1" }, { "type": "null" } ], - "default": null, - "description": "Only return logs emitted by this replica (5-char short ID).", - "title": "Replica" + "default": "SCALE_TO_ZERO", + "description": "The cleanup strategy to use after a promotion completes.", + "examples": [ + "SCALE_TO_ZERO" + ] }, - "request_id": { + "rolling_deploy_config": { "anyOf": [ { - "maxLength": 256, - "type": "string" + "$ref": "#/components/schemas/RollingDeployConfigV1" }, { "type": "null" } ], "default": null, - "description": "Only return logs tagged with this inference request ID.", - "title": "Request Id" + "description": "Rolling deploy configuration for promotions" }, - "component": { + "ramp_up_while_promoting": { "anyOf": [ { - "maxLength": 256, - "type": "string" + "type": "boolean" }, { "type": "null" } ], - "default": null, - "description": "Only return logs from this component.", - "title": "Component" + "default": false, + "description": "Whether to ramp up traffic while promoting", + "examples": [ + true + ], + "title": "Ramp Up While Promoting" }, - "search_pattern": { + "ramp_up_duration_seconds": { "anyOf": [ { - "maxLength": 256, - "type": "string" + "type": "integer" }, { "type": "null" } ], - "default": null, - "description": "RE2 regular expression matched against the log message. Prefer `includes` and `excludes` for plain substring matches.", - "title": "Search Pattern" + "default": 600, + "description": "Duration of the ramp up in seconds", + "examples": [ + 600 + ], + "title": "Ramp Up Duration Seconds" + } + }, + "title": "PromotionSettingsV1", + "type": "object" + }, + "RollingDeployConfigV1": { + "description": "Rolling deploy config for promoting chains and oracles", + "properties": { + "rolling_deploy_strategy": { + "$ref": "#/components/schemas/RollingDeployStrategyV1", + "default": "REPLICA", + "description": "The rolling deploy strategy to use for promotions.", + "examples": [ + "REPLICA" + ] }, - "includes": { - "description": "Case-sensitive substrings that must all appear in the log message.", - "items": { - "type": "string" - }, - "maxItems": 8, - "title": "Includes", - "type": "array" + "max_surge_percent": { + "default": 25, + "description": "The maximum surge percentage for rolling deploys.", + "examples": [ + 25 + ], + "title": "Max Surge Percent", + "type": "integer" }, - "excludes": { - "description": "Case-sensitive substrings; lines containing any of these are dropped.", - "items": { - "type": "string" - }, - "maxItems": 8, - "title": "Excludes", - "type": "array" + "max_unavailable_percent": { + "default": 0, + "description": "The maximum unavailable percentage for rolling deploys.", + "examples": [ + 10 + ], + "title": "Max Unavailable Percent", + "type": "integer" + }, + "stabilization_time_seconds": { + "default": 0, + "description": "The stabilization time in seconds for rolling deploys.", + "examples": [ + 300 + ], + "title": "Stabilization Time Seconds", + "type": "integer" + }, + "replica_overhead_percent": { + "default": 0, + "description": "The replica overhead percentage for rolling deploys.", + "examples": [ + 0 + ], + "title": "Replica Overhead Percent", + "type": "integer" } }, - "title": "GetDeploymentLogsRequestV1", + "title": "RollingDeployConfigV1", "type": "object" }, - "DeploymentPatchActionV1": { - "description": "How a patch op changes its target.", + "RollingDeployStrategyV1": { + "description": "The rolling deploy strategy.", "enum": [ - "ADD", - "UPDATE", - "REMOVE" + "REPLICA" ], - "title": "DeploymentPatchActionV1", + "title": "RollingDeployStrategyV1", "type": "string" }, - "DeploymentPatchOpConfigV1": { - "description": "Replace the config when config.yaml changes.\n\nConfig has no action: it is always a full replacement of the parsed config.\nDerived changes (environment variables, external data, requirements) are\nemitted as their own ops alongside this one.", + "EnvironmentsV1": { + "description": "list of environments", "properties": { - "type": { - "const": "config", - "default": "config", - "title": "Type", - "type": "string" - }, - "config": { - "additionalProperties": true, - "description": "The full parsed config as a JSON object.", - "title": "Config", - "type": "object" - }, - "path": { - "default": "config.yaml", - "description": "Config file path within the source.", - "title": "Path", - "type": "string" + "environments": { + "items": { + "$ref": "#/components/schemas/EnvironmentV1" + }, + "title": "Environments", + "type": "array" } }, "required": [ - "config" + "environments" ], - "title": "DeploymentPatchOpConfigV1", + "title": "EnvironmentsV1", "type": "object" }, - "DeploymentPatchOpEnvVarV1": { - "description": "Add, update, or remove a single environment variable.", + "UpdatePromotionSettingsV1": { + "description": "Promotion settings for model promotion", "properties": { - "type": { - "const": "environment_variable", - "default": "environment_variable", - "title": "Type", - "type": "string" - }, - "action": { - "$ref": "#/components/schemas/DeploymentPatchActionV1", - "description": "How this op changes the variable." - }, - "name": { - "description": "The environment variable name.", - "title": "Name", - "type": "string" - }, - "value": { + "redeploy_on_promotion": { "anyOf": [ { - "type": "string" + "type": "boolean" }, { "type": "null" } ], "default": null, - "description": "The environment variable value. Required for add and update.", - "title": "Value" - } - }, - "required": [ - "action", - "name" - ], - "title": "DeploymentPatchOpEnvVarV1", - "type": "object" - }, - "DeploymentPatchOpExternalDataV1": { - "description": "Add, update, or remove a single external data item.\n\nExternal data is referenced by config, not stored in the source. The backend\nonly adds or removes it, where adding re-downloads (overwriting any existing\nfile), so `update` is accepted and treated identically to `add`.", - "properties": { - "type": { - "const": "external_data", - "default": "external_data", - "title": "Type", - "type": "string" - }, - "action": { - "$ref": "#/components/schemas/DeploymentPatchActionV1", - "description": "How this op changes the item. `UPDATE` is treated identically to `ADD`." + "description": "Whether to deploy on all promotions. Enabling this flag allows model code to safely handle environment-specific logic. When a deployment is promoted, a new deployment will be created with a copy of the image.", + "examples": [ + true + ], + "title": "Redeploy On Promotion" }, - "item": { - "additionalProperties": { - "type": "string" - }, - "description": "The single external data item descriptor.", - "title": "Item", - "type": "object" - } - }, - "required": [ - "action", - "item" - ], - "title": "DeploymentPatchOpExternalDataV1", - "type": "object" - }, - "DeploymentPatchOpModelCodeV1": { - "description": "Add, update, or remove a file under the model code directory.", - "properties": { - "type": { - "const": "model_code", - "default": "model_code", - "title": "Type", - "type": "string" + "rolling_deploy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Whether the environment should rely on rolling deploy orchestration.", + "examples": [ + true + ], + "title": "Rolling Deploy" }, - "action": { - "$ref": "#/components/schemas/DeploymentPatchActionV1", - "description": "How this op changes the file." + "promotion_cleanup_strategy": { + "anyOf": [ + { + "$ref": "#/components/schemas/PromotionCleanupStrategyV1" + }, + { + "type": "null" + } + ], + "default": null, + "description": "The cleanup strategy to use after a promotion completes.", + "examples": [ + "SCALE_TO_ZERO" + ] }, - "path": { - "description": "File path relative to the model code directory.", - "title": "Path", - "type": "string" + "rolling_deploy_config": { + "anyOf": [ + { + "$ref": "#/components/schemas/UpdateRollingDeployConfigV1" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Rolling deploy configuration for promotions" }, - "content": { + "ramp_up_while_promoting": { "anyOf": [ { - "type": "string" + "type": "boolean" }, { "type": "null" } ], "default": null, - "description": "UTF-8 file content. Null for removals and binary files.", - "title": "Content" + "description": "Whether to ramp up traffic while promoting", + "examples": [ + true + ], + "title": "Ramp Up While Promoting" }, - "content_bytes": { + "ramp_up_duration_seconds": { "anyOf": [ { - "type": "string" + "type": "integer" }, { "type": "null" } ], "default": null, - "description": "Base64-encoded content for binary files.", - "title": "Content Bytes" - }, - "hot_reload": { - "default": false, - "description": "Whether the running server can pick up this change without a restart.", - "title": "Hot Reload", - "type": "boolean" + "description": "Duration of the ramp up in seconds", + "examples": [ + 600 + ], + "title": "Ramp Up Duration Seconds" } }, - "required": [ - "action", - "path" - ], - "title": "DeploymentPatchOpModelCodeV1", + "title": "UpdatePromotionSettingsV1", "type": "object" }, - "DeploymentPatchOpPackageV1": { - "description": "Add, update, or remove a file under the bundled packages directory.", + "UpdateRollingDeployConfigV1": { + "description": "Rolling deploy config for promoting chains and oracles", "properties": { - "type": { - "const": "package", - "default": "package", - "title": "Type", - "type": "string" - }, - "action": { - "$ref": "#/components/schemas/DeploymentPatchActionV1", - "description": "How this op changes the file." - }, - "path": { - "description": "File path relative to the bundled packages directory.", - "title": "Path", - "type": "string" - }, - "content": { + "rolling_deploy_strategy": { "anyOf": [ { - "type": "string" + "$ref": "#/components/schemas/RollingDeployStrategyV1" }, { "type": "null" } ], "default": null, - "description": "UTF-8 file content. Null for removals and binary files.", - "title": "Content" + "description": "The rolling deploy strategy to use for promotions.", + "examples": [ + "REPLICA" + ] }, - "content_bytes": { + "max_surge_percent": { "anyOf": [ { - "type": "string" + "type": "integer" }, { "type": "null" } ], "default": null, - "description": "Base64-encoded content for binary files.", - "title": "Content Bytes" - } - }, - "required": [ - "action", - "path" - ], - "title": "DeploymentPatchOpPackageV1", - "type": "object" - }, - "DeploymentPatchOpPythonRequirementV1": { - "description": "Add, update, or remove a single Python requirement.", - "properties": { - "type": { - "const": "python_requirement", - "default": "python_requirement", - "title": "Type", - "type": "string" - }, - "action": { - "$ref": "#/components/schemas/DeploymentPatchActionV1", - "description": "How this op changes the requirement." - }, - "requirement": { - "description": "The requirement to apply. For removals this is the package name; otherwise the full requirements.txt-style line.", - "title": "Requirement", - "type": "string" - } - }, - "required": [ - "action", - "requirement" - ], - "title": "DeploymentPatchOpPythonRequirementV1", - "type": "object" - }, - "DeploymentPatchPointV1": { - "description": "A patch point: the source state the next patch is computed against.\n\nThe content hash that identifies a point is derived from this state (see\n`DeploymentPatchPointWithHashV1.hash`), so a request only sends the state and\nthe server stamps the hash. A previous point's hash plus the current local\nsource is enough to compute the next patch, so the watch client reads the\npoint it is patching off of.", - "properties": { - "content_hashes": { - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ] - }, - "description": "Map of every non-ignored source path, relative and forward-slash, to its content hash: files map to the hex blake3 digest of their bytes, directories map to null. This is the full signature of the source tree and what the content hash is derived from.", - "title": "Content Hashes", - "type": "object" - }, - "config": { - "description": "The verbatim config.yaml text for this source state.", - "title": "Config", - "type": "string" - }, - "requirements": { - "description": "Requirements resolved from the config's requirements file, when it points at one. Empty when requirements are declared inline in the config.", - "items": { - "type": "string" - }, - "title": "Requirements", - "type": "array" - } - }, - "required": [ - "content_hashes", - "config" - ], - "title": "DeploymentPatchPointV1", - "type": "object" - }, - "CreateDeploymentPatchRequestV1": { - "description": "A patch to stage against the development deployment.\n\nStaging is durable on its own: the patch is persisted independently of the\nlater sync, so a failed sync does not lose it.", - "properties": { - "prev_patch_hash": { - "description": "Content hash of the patch point this patch is applied on - the link the staged patch must build on. A stale value (the base moved underneath the client) is rejected with a conflict.", - "title": "Prev Patch Hash", - "type": "string" - }, - "next_patch_point": { - "$ref": "#/components/schemas/DeploymentPatchPointV1", - "description": "The source state after this patch. The server derives its content hash from `content_hashes`." + "description": "The maximum surge percentage for rolling deploys.", + "examples": [ + 25 + ], + "title": "Max Surge Percent" }, - "patch_ops": { - "description": "The ordered ops that make up this patch. At least one op is required; a patch that changes nothing is not a valid request. There is no op for a directory: a directory comes into existence when the first file under it is added, and is removed when its last file is removed, so directory creation and deletion happen implicitly through the file ops. Adding or removing an otherwise empty directory therefore produces no ops even though it changes the source hash; do not send a patch request for such a change.", - "items": { - "discriminator": { - "mapping": { - "config": "#/components/schemas/DeploymentPatchOpConfigV1", - "environment_variable": "#/components/schemas/DeploymentPatchOpEnvVarV1", - "external_data": "#/components/schemas/DeploymentPatchOpExternalDataV1", - "model_code": "#/components/schemas/DeploymentPatchOpModelCodeV1", - "package": "#/components/schemas/DeploymentPatchOpPackageV1", - "python_requirement": "#/components/schemas/DeploymentPatchOpPythonRequirementV1" - }, - "propertyName": "type" + "max_unavailable_percent": { + "anyOf": [ + { + "type": "integer" }, - "oneOf": [ - { - "$ref": "#/components/schemas/DeploymentPatchOpModelCodeV1" - }, - { - "$ref": "#/components/schemas/DeploymentPatchOpPackageV1" - }, - { - "$ref": "#/components/schemas/DeploymentPatchOpConfigV1" - }, - { - "$ref": "#/components/schemas/DeploymentPatchOpPythonRequirementV1" - }, - { - "$ref": "#/components/schemas/DeploymentPatchOpEnvVarV1" - }, - { - "$ref": "#/components/schemas/DeploymentPatchOpExternalDataV1" - } - ] - }, - "minItems": 1, - "title": "Patch Ops", - "type": "array" - } - }, - "required": [ - "prev_patch_hash", - "next_patch_point", - "patch_ops" - ], - "title": "CreateDeploymentPatchRequestV1", - "type": "object" - }, - "DeploymentPatchPointWithHashV1": { - "description": "A patch point plus its server-assigned content hash, returned in responses.\n\nRequests omit the hash (the server derives it from the source state); responses\ninclude it so the watch client can echo it back as the next patch's\n`prev_patch_hash` without having to recompute the fold itself.", - "properties": { - "content_hashes": { - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ] - }, - "description": "Map of every non-ignored source path, relative and forward-slash, to its content hash: files map to the hex blake3 digest of their bytes, directories map to null. This is the full signature of the source tree and what the content hash is derived from.", - "title": "Content Hashes", - "type": "object" - }, - "config": { - "description": "The verbatim config.yaml text for this source state.", - "title": "Config", - "type": "string" + { + "type": "null" + } + ], + "default": null, + "description": "The maximum unavailable percentage for rolling deploys.", + "examples": [ + 10 + ], + "title": "Max Unavailable Percent" }, - "requirements": { - "description": "Requirements resolved from the config's requirements file, when it points at one. Empty when requirements are declared inline in the config.", - "items": { - "type": "string" - }, - "title": "Requirements", - "type": "array" + "stabilization_time_seconds": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "The stabilization time in seconds for rolling deploys.", + "examples": [ + 300 + ], + "title": "Stabilization Time Seconds" }, - "hash": { - "description": "Content hash identifying this exact source state, and the link patches build on. It is derived deterministically from `content_hashes`, so a request need not send it - the server derives it. It is derived by sorting the `content_hashes` keys as paths, splitting each key on '/' into its path components and ordering the keys by comparing those component lists element by element, each component compared by Unicode code point (equivalently UTF-8 byte order). Treating '/' as a path separator this way, rather than as the ordinary character U+002F, means a key that is an ancestor path sorts before a sibling whose name extends the first differing component (so e.g. 'a/b' sorts before 'a.b'). A blake3 hasher is then built, and for each key in that order updated with the blake3 digest (32 raw bytes) of the key encoded as UTF-8, then, when the entry is a file (non-null value), with that file's digest as 32 raw bytes. The stream uses raw digest bytes, but the values in `content_hashes` are those digests hex-encoded (64 hex chars), so decode each value from hex first. Directory entries (null value) contribute only their key digest. The result is the hasher's own hex digest.", - "title": "Hash", - "type": "string" - } - }, - "required": [ - "content_hashes", - "config", - "hash" - ], - "title": "DeploymentPatchPointWithHashV1", - "type": "object" - }, - "CreateDeploymentPatchResponseV1": { - "description": "The created patch, represented by the patch point it produced.", - "properties": { - "patch_point": { - "$ref": "#/components/schemas/DeploymentPatchPointWithHashV1", - "description": "The resulting patch point the staged patch produced; matches the pending point a subsequent state read returns." + "replica_overhead_percent": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "The replica overhead percentage for rolling deploys.", + "examples": [ + 0 + ], + "title": "Replica Overhead Percent" } }, - "required": [ - "patch_point" - ], - "title": "CreateDeploymentPatchResponseV1", + "title": "UpdateRollingDeployConfigV1", "type": "object" }, - "GetDeploymentPatchesStateResponseV1": { - "description": "The patch state of the development deployment.\n\nThe watch client computes its next patch off `pending_patch_point` when present,\nelse `running_patch_point`.", + "CreateEnvironmentRequestV1": { + "description": "A request to create an environment.", "properties": { - "running_patch_point": { - "$ref": "#/components/schemas/DeploymentPatchPointWithHashV1", - "description": "The patch point the deployment is recorded as running." + "name": { + "description": "Name of the environment", + "examples": [ + "staging" + ], + "title": "Name", + "type": "string" }, - "pending_patch_point": { + "autoscaling_settings": { "anyOf": [ { - "$ref": "#/components/schemas/DeploymentPatchPointWithHashV1" + "$ref": "#/components/schemas/UpdateAutoscalingSettingsV1" }, { "type": "null" } ], "default": null, - "description": "The latest staged-but-unsynced patch point, or null when the deployment is recorded as caught up." - } - }, - "required": [ - "running_patch_point" - ], - "title": "GetDeploymentPatchesStateResponseV1", - "type": "object" - }, - "SyncDeploymentPatchesRequestV1": { - "description": "Triggers a sync of any staged patches to the running deployment. Takes no\nfields: the deployment and its staged patches fully determine the sync.", - "properties": {}, - "title": "SyncDeploymentPatchesRequestV1", - "type": "object" - }, - "SyncDeploymentPatchesResponseV1": { - "description": "The outcome of a sync that ran.\n\nOperational failures (a transient patch failure, an invalid patch sequence)\nare surfaced as HTTP errors rather than fields here, so a 2xx means the sync\nreached a verdict.", - "properties": { - "needs_full_deploy_reason": { + "description": "Autoscaling settings for the environment", + "examples": [ + { + "autoscaling_window": 800, + "concurrency_target": 3, + "max_replica": 2, + "max_scale_down_rate": null, + "min_replica": 1, + "scale_down_delay": 60, + "target_in_flight_tokens": null, + "target_utilization_percentage": null + } + ] + }, + "promotion_settings": { "anyOf": [ { - "type": "string" + "$ref": "#/components/schemas/UpdatePromotionSettingsV1" }, { "type": "null" } ], "default": null, - "description": "If set, the change cannot be patched and a full push is required; the value explains why. If null, the deployment is now in sync.", - "title": "Needs Full Deploy Reason" + "description": "Promotion settings for the environment. New Model environments use rolling promotions by default. Set `rolling_deploy` to `false` to opt out.", + "examples": [ + { + "promotion_cleanup_strategy": null, + "ramp_up_duration_seconds": 600, + "ramp_up_while_promoting": true, + "redeploy_on_promotion": true, + "rolling_deploy": false, + "rolling_deploy_config": null + } + ] + }, + "request_backpressure_settings": { + "anyOf": [ + { + "$ref": "#/components/schemas/UpdateRequestBackpressureSettingsV1" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Request backpressure settings for the environment." } }, - "title": "SyncDeploymentPatchesResponseV1", + "required": [ + "name" + ], + "title": "CreateEnvironmentRequestV1", "type": "object" }, - "ModelMetricDescriptorV1": { - "description": "Describes one metric. Its position in the response ``metric_descriptors``\nlist is the index used to read that metric out of each value set's ``values``.\n\nA metric may break down into multiple labeled series (e.g. latency quantiles,\nor volume by status). ``label_sets`` enumerates those series in order; each\nvalue set's value for this metric is a list aligned to that order.", + "EnvironmentTombstoneV1": { + "description": "An environment tombstone.", "properties": { "name": { - "description": "Canonical metric name.", + "description": "Name of the environment", "title": "Name", "type": "string" }, - "unit_hint": { - "$ref": "#/components/schemas/ModelMetricUnitHintV1", - "description": "Advisory unit of the metric's values." - }, - "kind": { - "$ref": "#/components/schemas/ModelMetricKindV1", - "description": "Semantic hint for how the metric behaves (GAUGE, COUNTER, HISTOGRAM)." + "model_id": { + "description": "Unique identifier of the model", + "title": "Model Id", + "type": "string" }, - "label_sets": { - "description": "The metric's series, in order. Each entry is the set of labels identifying one series; the value at the same index in each value set's ``values`` is that series' value. A plain metric has a single entry with no labels (`{}`). A histogram has one entry per quantile plus an average, e.g. {'quantile': '0.5'} \u2026 {'quantile': '0.99'}, {'stat': 'avg'}. A by-status metric has one entry per status, e.g. {'status': '2xx'}.", - "items": { - "additionalProperties": { - "type": "string" - }, - "type": "object" - }, - "title": "Label Sets", - "type": "array" + "deleted": { + "description": "Whether the environment was deleted", + "title": "Deleted", + "type": "boolean" } }, "required": [ "name", - "unit_hint", - "kind", - "label_sets" + "model_id", + "deleted" ], - "title": "ModelMetricDescriptorV1", + "title": "EnvironmentTombstoneV1", "type": "object" }, - "ModelMetricKindV1": { - "description": "Semantic hint for how a metric behaves, to aid client rendering and\naggregation. It does not describe the value's shape (that is carried by the\ndescriptor's ``label_sets``; a metric may break down into multiple series).\n\n- ``GAUGE``: an instantaneous value (e.g. queue size, running requests).\n- ``COUNTER``: a cumulative total over the step (e.g. tokens, restarts).\n- ``HISTOGRAM``: a distribution, exposed as quantile/average series.", - "enum": [ - "GAUGE", - "COUNTER", - "HISTOGRAM" - ], - "title": "ModelMetricKindV1", - "type": "string" - }, - "ModelMetricModeV1": { - "description": "How metric values are aggregated over the request.", - "enum": [ - "CURRENT", - "SUMMARY", - "SERIES" - ], - "title": "ModelMetricModeV1", - "type": "string" - }, - "ModelMetricUnitHintV1": { - "description": "Advisory unit of a metric's values. Values are reported as scraped, so the\nhint describes the raw value (e.g. GPU memory is reported in mebibytes).\n\n- ``PER_SECOND``: a rate per second.\n- ``SECONDS``: a duration in seconds.\n- ``BYTES``: a size in bytes.\n- ``MEBIBYTES``: a size in mebibytes (MiB).\n- ``COUNT``: a dimensionless tally of discrete things.\n- ``RATIO``: a dimensionless ratio. Usually in ``[0, 1]`` but may exceed 1\n (e.g. CPU usage in cores = cpu-seconds/second).", - "enum": [ - "PER_SECOND", - "SECONDS", - "BYTES", - "MEBIBYTES", - "COUNT", - "RATIO" - ], - "title": "ModelMetricUnitHintV1", - "type": "string" - }, - "ModelMetricValueSetV1": { - "description": "The metric values for one time step. ``values`` is aligned by index to the\nresponse ``metric_descriptors`` list.", + "AutoscalingScheduleSettingsRequestV1": { + "additionalProperties": false, + "description": "A complete set of raw autoscaling overrides for a schedule.", "properties": { - "start_epoch_millis": { - "description": "Start of the step. The step spans until the next value set's start, or the window end for the last one; a summary has a single value set starting at the window start.", - "title": "Start Epoch Millis", + "min_replica": { + "description": "Minimum number of replicas", + "title": "Min Replica", + "type": "integer" + }, + "max_replica": { + "description": "Maximum number of replicas", + "title": "Max Replica", "type": "integer" }, - "values": { - "description": "Metric values aligned to the ``metric_descriptors`` index. Each entry is a list aligned to that descriptor's ``label_sets`` (a single-element list for a plain metric). A series with no data in this step is null.", - "items": { - "items": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "null" - } - ] + "autoscaling_window": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Timeframe of traffic considered for autoscaling decisions. Null stores no schedule override and follows the current environment value.", + "title": "Autoscaling Window" + }, + "scale_down_delay": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Waiting period before scaling down any active replica. Null stores no schedule override and follows the current environment value.", + "title": "Scale Down Delay" + }, + "concurrency_target": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Number of requests per replica before scaling up. Null stores no schedule override and follows the current environment value.", + "title": "Concurrency Target" + }, + "target_utilization_percentage": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Target utilization percentage for scaling up/down. Null stores no schedule override and follows the current environment value.", + "title": "Target Utilization Percentage" + }, + "target_in_flight_tokens": { + "anyOf": [ + { + "type": "integer" }, - "type": "array" - }, - "title": "Values", - "type": "array" + { + "type": "null" + } + ], + "description": "Target number of in-flight tokens for autoscaling decisions. Null stores no schedule override and follows the current environment value. Early access only.", + "title": "Target In Flight Tokens" + }, + "max_scale_down_rate": { + "anyOf": [ + { + "maximum": 50, + "minimum": 1, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Maximum percentage of replicas that can be removed per autoscaling window. Null stores no schedule override and follows the current environment value.", + "title": "Max Scale Down Rate" } }, "required": [ - "start_epoch_millis", - "values" + "min_replica", + "max_replica", + "autoscaling_window", + "scale_down_delay", + "concurrency_target", + "target_utilization_percentage", + "target_in_flight_tokens", + "max_scale_down_rate" ], - "title": "ModelMetricValueSetV1", + "title": "AutoscalingScheduleSettingsRequestV1", "type": "object" }, - "GetModelMetricsResponseV1": { - "description": "Model metrics over a time window, index-mapped: metric descriptors appear once\nin ``metric_descriptors``; each value set's ``values`` are aligned to that order.", + "AutoscalingScheduleUpsertV1": { + "additionalProperties": false, + "description": "A complete recurring schedule submitted for create or replacement.", "properties": { - "start_epoch_millis": { - "description": "Start of the returned window.", - "title": "Start Epoch Millis", - "type": "integer" - }, - "end_epoch_millis": { - "description": "End of the returned window.", - "title": "End Epoch Millis", - "type": "integer" - }, - "mode": { - "$ref": "#/components/schemas/ModelMetricModeV1", - "description": "The aggregation mode used." - }, - "step_seconds": { + "id": { "anyOf": [ { - "type": "integer" + "type": "string" }, { "type": "null" } ], - "description": "Seconds per step; populated only in SERIES mode, null otherwise.", - "title": "Step Seconds" + "default": null, + "description": "Stable schedule identifier. Omit this field to create a schedule.", + "title": "Id" }, - "metric_descriptors": { - "description": "Descriptors for each metric; position defines the values index.", - "items": { - "$ref": "#/components/schemas/ModelMetricDescriptorV1" - }, - "title": "Metric Descriptors", - "type": "array" + "name": { + "description": "Name of the schedule", + "title": "Name", + "type": "string" }, - "metric_values": { - "description": "Metric values per time step covering the window. In summary mode this always contains exactly one value set spanning the whole window.", + "enabled": { + "description": "Whether the schedule is enabled", + "title": "Enabled", + "type": "boolean" + }, + "autoscaling_settings": { + "$ref": "#/components/schemas/AutoscalingScheduleSettingsRequestV1", + "description": "Complete raw autoscaling overrides for the schedule. Every field is required; nullable fields store no schedule override and follow the current environment value." + }, + "cadence": { + "description": "Recurring schedule cadence", + "enum": [ + "DAILY", + "HOURLY" + ], + "title": "Cadence", + "type": "string" + }, + "weekdays": { + "description": "Weekdays on which the schedule runs", "items": { - "$ref": "#/components/schemas/ModelMetricValueSetV1" + "$ref": "#/components/schemas/AutoscalingScheduleWeekdayV1" }, - "title": "Metric Values", + "title": "Weekdays", "type": "array" - } - }, - "required": [ - "start_epoch_millis", - "end_epoch_millis", - "mode", - "step_seconds", - "metric_descriptors", - "metric_values" - ], - "title": "GetModelMetricsResponseV1", - "type": "object" - }, - "GetDeploymentMetricsRequestV1": { - "description": "Query params for ``GET /v1/models/.../deployments/.../metrics``.", - "properties": { - "mode": { - "$ref": "#/components/schemas/ModelMetricModeV1", - "default": "CURRENT", - "description": "'CURRENT': a single instantaneous snapshot at now; start/end must be omitted. 'SUMMARY': a single value set aggregating the whole window. 'SERIES': evenly-spaced value sets across the window, with the step derived from the window duration." }, - "start_epoch_millis": { + "start_hour": { "anyOf": [ { "type": "integer" @@ -16638,10 +20685,15 @@ } ], "default": null, - "description": "Epoch millis timestamp to start fetching metrics. Defaults to one hour before the end.", - "title": "Start Epoch Millis" + "description": "Start hour in the environment schedule timezone. Omit for unrestricted HOURLY schedules.", + "title": "Start Hour" }, - "end_epoch_millis": { + "start_minute": { + "description": "Start minute of the schedule window", + "title": "Start Minute", + "type": "integer" + }, + "end_hour": { "anyOf": [ { "type": "integer" @@ -16651,43 +20703,32 @@ } ], "default": null, - "description": "Epoch millis timestamp to end fetching metrics. Defaults to the current time. The window between start and end must not exceed 7 days.", - "title": "End Epoch Millis" + "description": "End hour in the environment schedule timezone. Omit for unrestricted HOURLY schedules.", + "title": "End Hour" }, - "metrics": { - "description": "Names of the metrics to return; see https://docs.baseten.co/observability/export-metrics/supported-metrics for the available names. When omitted, a default set is returned: baseten_replicas_active, baseten_inference_requests_total, and baseten_end_to_end_response_time_seconds. Unknown names are rejected; valid names that do not apply are omitted from the response.", - "items": { - "type": "string" - }, - "title": "Metrics", - "type": "array" - } - }, - "title": "GetDeploymentMetricsRequestV1", - "type": "object" - }, - "TerminateReplicaResponseV1": { - "description": "The response to a request to terminate a replica in a deployment.", - "properties": { - "success": { - "default": true, - "description": "Whether the replica was successfully terminated", - "title": "Success", - "type": "boolean" + "end_minute": { + "description": "End minute of the schedule window", + "title": "End Minute", + "type": "integer" } }, - "title": "TerminateReplicaResponseV1", + "required": [ + "name", + "enabled", + "autoscaling_settings", + "cadence", + "weekdays", + "start_minute", + "end_minute" + ], + "title": "AutoscalingScheduleUpsertV1", "type": "object" }, - "SignSSHCertificateRequestV1": { - "description": "Request to sign an SSH certificate for accessing a workload pod.", + "OneTimeAutoscalingScheduleUpsertV1": { + "additionalProperties": false, + "description": "A complete one-time schedule submitted for create or replacement.", "properties": { - "public_key": { - "description": "The user's SSH public key (e.g., 'ssh-ed25519 AAAA... user@host').", - "title": "Public Key", - "type": "string" - }, - "replica_id": { + "id": { "anyOf": [ { "type": "string" @@ -16697,213 +20738,258 @@ } ], "default": null, - "description": "The replica to connect to. Required for training jobs (e.g. '0'). Optional for inference (server picks a running replica if omitted).", - "title": "Replica Id" - } - }, - "required": [ - "public_key" - ], - "title": "SignSSHCertificateRequestV1", - "type": "object" - }, - "SignSSHCertificateResponseV1": { - "description": "Response containing a signed SSH certificate for proxy authentication.", - "properties": { - "ssh_certificate": { - "description": "The signed SSH certificate in OpenSSH format.", - "title": "Ssh Certificate", + "description": "Stable schedule identifier. Omit this field to create a schedule.", + "title": "Id" + }, + "name": { + "description": "Name of the schedule", + "title": "Name", "type": "string" }, - "jwt": { - "description": "Signed JWT (ES256) for SSH proxy authorization.", - "title": "Jwt", + "enabled": { + "description": "Whether the schedule is enabled", + "title": "Enabled", + "type": "boolean" + }, + "autoscaling_settings": { + "$ref": "#/components/schemas/AutoscalingScheduleSettingsRequestV1", + "description": "Complete raw autoscaling overrides for the schedule. Every field is required; nullable fields store no schedule override and follow the current environment value." + }, + "cadence": { + "const": "ONE_TIME", + "description": "One-time schedule cadence", + "title": "Cadence", "type": "string" }, - "proxy_address": { - "description": "Address of the SSH proxy to connect to (host:port).", - "title": "Proxy Address", + "start_at": { + "description": "Inclusive start of the schedule window in ISO 8601 format. New schedules must start in the future.", + "format": "date-time", + "title": "Start At", "type": "string" }, - "ssh_cert_expires_at": { - "description": "When the certificate expires, in ISO 8601 format.", + "end_at": { + "description": "Exclusive end of the schedule window in ISO 8601 format", "format": "date-time", - "title": "Ssh Cert Expires At", + "title": "End At", "type": "string" } }, "required": [ - "ssh_certificate", - "jwt", - "proxy_address", - "ssh_cert_expires_at" + "name", + "enabled", + "autoscaling_settings", + "cadence", + "start_at", + "end_at" ], - "title": "SignSSHCertificateResponseV1", + "title": "OneTimeAutoscalingScheduleUpsertV1", "type": "object" }, - "AutoscalingScheduleSettingsV1": { + "UpdateAutoscalingScheduleSettingsV1": { + "additionalProperties": false, + "description": "Partial mutation of an environment's autoscaling schedule collection.", "properties": { - "min_replica": { - "description": "Minimum number of replicas", - "title": "Min Replica", - "type": "integer" - }, - "max_replica": { - "description": "Maximum number of replicas", - "title": "Max Replica", - "type": "integer" - }, - "autoscaling_window": { + "timezone": { "anyOf": [ { - "type": "integer" + "type": "string" }, { "type": "null" } ], - "description": "Timeframe of traffic considered for autoscaling decisions. Null inherits the environment value.", - "title": "Autoscaling Window" + "default": null, + "description": "IANA timezone shared by the resulting collection. Omission preserves the current timezone; null is allowed only when deleting every schedule.", + "title": "Timezone", + "x-null-distinct": true }, - "scale_down_delay": { + "schedules": { + "description": "Complete schedules to create or replace. Existing schedules omitted from this list are unchanged.", + "items": { + "discriminator": { + "mapping": { + "DAILY": "#/components/schemas/AutoscalingScheduleUpsertV1", + "HOURLY": "#/components/schemas/AutoscalingScheduleUpsertV1", + "ONE_TIME": "#/components/schemas/OneTimeAutoscalingScheduleUpsertV1" + }, + "propertyName": "cadence" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/AutoscalingScheduleUpsertV1" + }, + { + "$ref": "#/components/schemas/OneTimeAutoscalingScheduleUpsertV1" + } + ] + }, + "title": "Schedules", + "type": "array" + }, + "delete_schedules": { + "description": "Stable identifiers of schedules to delete. To clear all schedules, include every existing schedule identifier.", + "items": { + "type": "string" + }, + "title": "Delete Schedules", + "type": "array" + } + }, + "title": "UpdateAutoscalingScheduleSettingsV1", + "type": "object" + }, + "UpdateEnvironmentRequestV1": { + "additionalProperties": false, + "description": "A request to update an environment.", + "properties": { + "autoscaling_settings": { "anyOf": [ { - "type": "integer" + "$ref": "#/components/schemas/UpdateAutoscalingSettingsV1" }, { "type": "null" } ], - "description": "Waiting period before scaling down any active replica. Null inherits the environment value.", - "title": "Scale Down Delay" + "default": null, + "description": "Autoscaling settings for the environment", + "examples": [ + { + "autoscaling_window": 800, + "concurrency_target": 3, + "max_replica": 2, + "max_scale_down_rate": null, + "min_replica": 1, + "scale_down_delay": 60, + "target_in_flight_tokens": null, + "target_utilization_percentage": null + } + ] }, - "concurrency_target": { + "promotion_settings": { "anyOf": [ { - "type": "integer" + "$ref": "#/components/schemas/UpdatePromotionSettingsV1" }, { "type": "null" } ], - "description": "Number of requests per replica before scaling up. Null inherits the environment value.", - "title": "Concurrency Target" + "default": null, + "description": "Promotion settings for the environment", + "examples": [ + { + "promotion_cleanup_strategy": null, + "ramp_up_duration_seconds": 600, + "ramp_up_while_promoting": true, + "redeploy_on_promotion": true, + "rolling_deploy": null, + "rolling_deploy_config": null + } + ] }, - "target_utilization_percentage": { + "autoscaling_schedule_settings": { "anyOf": [ { - "type": "integer" + "$ref": "#/components/schemas/UpdateAutoscalingScheduleSettingsV1" }, { "type": "null" } ], - "description": "Target utilization percentage for scaling up/down. Null inherits the environment value.", - "title": "Target Utilization Percentage" - }, - "target_in_flight_tokens": { - "anyOf": [ + "default": null, + "description": "Partial autoscaling schedule collection update. Omitted collection fields and existing schedules are unchanged; each submitted schedule is a complete create or replacement.", + "examples": [ { - "type": "integer" + "schedules": [ + { + "autoscaling_settings": { + "autoscaling_window": null, + "concurrency_target": null, + "max_replica": 8, + "max_scale_down_rate": null, + "min_replica": 2, + "scale_down_delay": null, + "target_in_flight_tokens": null, + "target_utilization_percentage": null + }, + "cadence": "DAILY", + "enabled": true, + "end_hour": 10, + "end_minute": 0, + "name": "weekday-peak", + "start_hour": 8, + "start_minute": 0, + "weekdays": [ + "MONDAY", + "TUESDAY", + "WEDNESDAY", + "THURSDAY", + "FRIDAY" + ] + } + ], + "timezone": "America/Los_Angeles" }, { - "type": "null" + "delete_schedules": [ + "schedule-id" + ] } - ], - "description": "Target number of in-flight tokens for autoscaling decisions. Null inherits the environment value. Early access only.", - "title": "Target In Flight Tokens" + ] }, - "max_scale_down_rate": { + "request_backpressure_settings": { "anyOf": [ { - "type": "integer" + "$ref": "#/components/schemas/UpdateRequestBackpressureSettingsV1" }, { "type": "null" } ], - "description": "Maximum percentage of replicas that can be removed per autoscaling window. Null inherits the environment value.", - "title": "Max Scale Down Rate" - } - }, - "required": [ - "min_replica", - "max_replica", - "autoscaling_window", - "scale_down_delay", - "concurrency_target", - "target_utilization_percentage", - "target_in_flight_tokens", - "max_scale_down_rate" - ], - "title": "AutoscalingScheduleSettingsV1", - "type": "object" - }, - "AutoscalingScheduleStateV1": { - "properties": { - "schedule_id": { - "anyOf": [ - { - "type": "string" - }, + "default": null, + "description": "Request backpressure settings for the environment.", + "examples": [ { - "type": "null" + "policy": "REJECT_ON_FULL" } - ], - "description": "Stable schedule identifier, or null when the baseline settings apply", - "title": "Schedule Id" - }, - "autoscaling_settings": { - "$ref": "#/components/schemas/AutoscalingSettingsV1", - "description": "Autoscaling settings on the current serving deployment. In a PATCH response, this snapshot can precede asynchronous schedule reconciliation; poll the GET endpoint for the applied state." + ] } }, - "required": [ - "schedule_id", - "autoscaling_settings" - ], - "title": "AutoscalingScheduleStateV1", + "title": "UpdateEnvironmentRequestV1", "type": "object" }, - "AutoscalingScheduleV1": { + "UpdateEnvironmentResponseV1": { + "description": "The response to a request to update an environment's settings.", "properties": { - "id": { - "description": "Stable unique identifier of the schedule", - "title": "Id", - "type": "string" - }, - "name": { - "description": "Name of the schedule", - "title": "Name", - "type": "string" - }, - "enabled": { - "description": "Whether the schedule is enabled", - "title": "Enabled", - "type": "boolean" - }, - "autoscaling_settings": { - "$ref": "#/components/schemas/AutoscalingScheduleSettingsV1", - "description": "Raw autoscaling overrides applied during the schedule window" - }, - "cadence": { - "description": "Cadence of the schedule. DAILY runs once per selected weekday; HOURLY repeats the minute window every hour on selected weekdays.", - "enum": [ - "DAILY", - "HOURLY" - ], - "title": "Cadence", - "type": "string" - }, - "weekdays": { - "description": "Weekdays on which the schedule runs", - "items": { - "$ref": "#/components/schemas/AutoscalingScheduleWeekdayV1" - }, - "title": "Weekdays", - "type": "array" + "environment": { + "$ref": "#/components/schemas/EnvironmentV1", + "description": "The environment after the update, matching the shape returned by GET." }, - "start_hour": { + "status": { + "$ref": "#/components/schemas/UpdateAutoscalingSettingsStatusV1", + "deprecated": true, + "description": "Deprecated. Kept for legacy autoscaling-only update operation behavior." + }, + "message": { + "deprecated": true, + "description": "Deprecated. Kept for legacy autoscaling-only update operation behavior.", + "title": "Message", + "type": "string" + } + }, + "required": [ + "environment", + "status", + "message" + ], + "title": "UpdateEnvironmentResponseV1", + "type": "object" + }, + "GetEnvironmentLogsRequestV1": { + "description": "A request to fetch logs for a model environment.\n\nReturns logs from every deployment that was active on the environment over\nthe requested time range, merged in timestamp order.", + "properties": { + "start_epoch_millis": { "anyOf": [ { "type": "integer" @@ -16913,15 +20999,10 @@ } ], "default": null, - "description": "Start hour in the environment schedule timezone. Omitted for unrestricted HOURLY schedules.", - "title": "Start Hour" - }, - "start_minute": { - "description": "Start minute of the schedule window", - "title": "Start Minute", - "type": "integer" + "description": "Epoch milliseconds at which to start fetching logs. Defaults to 30 minutes before the end. The window from start to end must not exceed 7 days.", + "title": "Start Epoch Millis" }, - "end_hour": { + "end_epoch_millis": { "anyOf": [ { "type": "integer" @@ -16931,695 +21012,811 @@ } ], "default": null, - "description": "End hour in the environment schedule timezone. Omitted for unrestricted HOURLY schedules.", - "title": "End Hour" + "description": "Epoch milliseconds at which to stop fetching logs. Defaults to the current time.", + "title": "End Epoch Millis" }, - "end_minute": { - "description": "End minute of the schedule window", - "title": "End Minute", - "type": "integer" - } - }, - "required": [ - "id", - "name", - "enabled", - "autoscaling_settings", - "cadence", - "weekdays", - "start_minute", - "end_minute" - ], - "title": "AutoscalingScheduleV1", - "type": "object" - }, - "AutoscalingScheduleWeekdayV1": { - "enum": [ - "SUNDAY", - "MONDAY", - "TUESDAY", - "WEDNESDAY", - "THURSDAY", - "FRIDAY", - "SATURDAY" - ], - "title": "AutoscalingScheduleWeekdayV1", - "type": "string" - }, - "EnvironmentAutoscalingSchedulesV1": { - "properties": { - "timezone": { + "direction": { "anyOf": [ { - "type": "string" + "$ref": "#/components/schemas/SortOrderV1" }, { "type": "null" } ], "default": null, - "description": "IANA timezone shared by all schedules. Omitted when no schedules exist.", - "title": "Timezone" + "description": "Sort order for logs" }, - "schedules": { - "description": "Autoscaling schedules ordered by creation time and stable identifier", - "items": { - "discriminator": { - "mapping": { - "DAILY": "#/components/schemas/AutoscalingScheduleV1", - "HOURLY": "#/components/schemas/AutoscalingScheduleV1", - "ONE_TIME": "#/components/schemas/OneTimeAutoscalingScheduleV1" - }, - "propertyName": "cadence" + "limit": { + "anyOf": [ + { + "maximum": 1000, + "minimum": 1, + "type": "integer" }, - "oneOf": [ - { - "$ref": "#/components/schemas/AutoscalingScheduleV1" - }, - { - "$ref": "#/components/schemas/OneTimeAutoscalingScheduleV1" - } - ] - }, - "title": "Schedules", - "type": "array" + { + "type": "null" + } + ], + "default": 500, + "description": "Limit of logs to fetch in a single request", + "title": "Limit" }, - "applied_state": { + "min_level": { "anyOf": [ { - "$ref": "#/components/schemas/AutoscalingScheduleStateV1" + "$ref": "#/components/schemas/LogLevelV1" }, { "type": "null" } ], - "description": "Autoscaling state on the current serving deployment, or null when no deployment exists" - } - }, - "required": [ - "schedules", - "applied_state" - ], - "title": "EnvironmentAutoscalingSchedulesV1", - "type": "object" - }, - "EnvironmentV1": { - "description": "Environment for oracles.", - "properties": { - "name": { - "description": "Name of the environment", - "title": "Name", - "type": "string" - }, - "created_at": { - "description": "Time the environment was created in ISO 8601 format", - "format": "date-time", - "title": "Created At", - "type": "string" - }, - "model_id": { - "description": "Unique identifier of the model", - "title": "Model Id", - "type": "string" + "default": null, + "description": "Minimum log severity to include. Omit to return all log lines, including lines that have no level. Any explicit value returns lines at or above that severity and drops lines without a level." }, - "current_deployment": { + "replica": { "anyOf": [ { - "$ref": "#/components/schemas/DeploymentV1" + "maxLength": 256, + "type": "string" }, { "type": "null" } ], - "description": "Current deployment of the environment" + "default": null, + "description": "Only return logs emitted by this replica (5-char short ID).", + "title": "Replica" }, - "candidate_deployment": { + "request_id": { "anyOf": [ { - "$ref": "#/components/schemas/DeploymentV1" + "maxLength": 256, + "type": "string" }, { "type": "null" } ], "default": null, - "description": "Candidate deployment being promoted to the environment, if a promotion is in progress" + "description": "Only return logs tagged with this inference request ID.", + "title": "Request Id" }, - "in_progress_promotion": { + "component": { "anyOf": [ { - "$ref": "#/components/schemas/InProgressPromotionV1" + "maxLength": 256, + "type": "string" }, { "type": "null" } ], "default": null, - "description": "Details of the in-progress promotion, if any" - }, - "autoscaling_settings": { - "$ref": "#/components/schemas/AutoscalingSettingsV1", - "description": "Autoscaling settings for the environment" - }, - "promotion_settings": { - "$ref": "#/components/schemas/PromotionSettingsV1", - "description": "Promotion settings for the environment" - }, - "instance_type": { - "$ref": "#/components/schemas/InstanceTypeV1", - "description": "Instance type for the environment" - }, - "request_backpressure_settings": { - "$ref": "#/components/schemas/RequestBackpressureSettingsV1", - "description": "Request backpressure settings for the environment." + "description": "Only return logs from this component.", + "title": "Component" }, - "autoscaling_schedules": { + "search_pattern": { "anyOf": [ { - "$ref": "#/components/schemas/EnvironmentAutoscalingSchedulesV1" + "maxLength": 256, + "type": "string" }, { "type": "null" } ], "default": null, - "description": "Autoscaling schedules and their evaluated state" + "description": "RE2 regular expression matched against the log message. Prefer `includes` and `excludes` for plain substring matches.", + "title": "Search Pattern" + }, + "includes": { + "description": "Case-sensitive substrings that must all appear in the log message.", + "items": { + "type": "string" + }, + "maxItems": 8, + "title": "Includes", + "type": "array" + }, + "excludes": { + "description": "Case-sensitive substrings; lines containing any of these are dropped.", + "items": { + "type": "string" + }, + "maxItems": 8, + "title": "Excludes", + "type": "array" } }, - "required": [ - "name", - "created_at", - "model_id", - "current_deployment", - "autoscaling_settings", - "promotion_settings", - "instance_type", - "request_backpressure_settings" - ], - "title": "EnvironmentV1", - "type": "object" - }, - "InProgressPromotionStatusV1": { - "enum": [ - "RELEASING", - "RAMPING_UP", - "RAMPING_DOWN", - "PAUSED", - "SUCCEEDED", - "FAILED", - "CANCELED" - ], - "title": "InProgressPromotionStatusV1", - "type": "string" - }, - "InProgressPromotionV1": { - "description": "Details of an in-progress promotion.", - "properties": { - "status": { - "$ref": "#/components/schemas/InProgressPromotionStatusV1", - "description": "Status of the promotion" - }, - "percent_traffic_to_new_version": { - "description": "Percentage of traffic routed to the candidate deployment", - "title": "Percent Traffic To New Version", - "type": "integer" + "title": "GetEnvironmentLogsRequestV1", + "type": "object" + }, + "GetEnvironmentMetricsRequestV1": { + "description": "Query params for ``GET /v1/models/.../environments/.../metrics``.", + "properties": { + "mode": { + "$ref": "#/components/schemas/ModelMetricModeV1", + "default": "CURRENT", + "description": "'CURRENT': a single instantaneous snapshot at now; start/end must be omitted. 'SUMMARY': a single value set aggregating the whole window. 'SERIES': evenly-spaced value sets across the window, with the step derived from the window duration." }, - "error_message": { + "start_epoch_millis": { "anyOf": [ { - "type": "string" + "type": "integer" }, { "type": "null" } ], "default": null, - "description": "Error message if promotion failed", - "title": "Error Message" + "description": "Epoch millis timestamp to start fetching metrics. Defaults to one hour before the end.", + "title": "Start Epoch Millis" }, - "rolling_deploy": { + "end_epoch_millis": { "anyOf": [ { - "type": "boolean" + "type": "integer" }, { "type": "null" } ], "default": null, - "description": "Whether this is a rolling deploy", - "title": "Rolling Deploy" + "description": "Epoch millis timestamp to end fetching metrics. Defaults to the current time. The window between start and end must not exceed 7 days.", + "title": "End Epoch Millis" + }, + "metrics": { + "description": "Names of the metrics to return; see https://docs.baseten.co/observability/export-metrics/supported-metrics for the available names. When omitted, a default set is returned: baseten_replicas_active, baseten_inference_requests_total, and baseten_end_to_end_response_time_seconds. Unknown names are rejected; valid names that do not apply are omitted from the response.", + "items": { + "type": "string" + }, + "title": "Metrics", + "type": "array" + } + }, + "title": "GetEnvironmentMetricsRequestV1", + "type": "object" + }, + "PromoteToEnvironmentRequestV1": { + "description": "A request to promote a deployment to a environment.", + "properties": { + "scale_down_previous_deployment": { + "default": true, + "description": "Whether to scale down the previous deployment after promoting", + "examples": [ + true + ], + "title": "Scale Down Previous Deployment", + "type": "boolean" + }, + "deployment_id": { + "description": "The id of the deployment to promote", + "title": "Deployment Id", + "type": "string" + }, + "preserve_env_instance_type": { + "default": true, + "description": "Whether to use the promoting deployment's instance type or preserve target environment's instance type", + "examples": [ + true + ], + "title": "Preserve Env Instance Type", + "type": "boolean" + } + }, + "required": [ + "deployment_id" + ], + "title": "PromoteToEnvironmentRequestV1", + "type": "object" + }, + "CancelPromotionStatusV1": { + "description": "The status of a request to cancel a promotion.", + "enum": [ + "CANCELED", + "RAMPING_DOWN" + ], + "title": "CancelPromotionStatusV1", + "type": "string" + }, + "CancelPromotionResponseV1": { + "description": "The response to a request to cancel a promotion.", + "properties": { + "status": { + "$ref": "#/components/schemas/CancelPromotionStatusV1", + "description": "Status of the request to cancel a promotion. Can be CANCELED or RAMPING_DOWN." + }, + "message": { + "description": "A message describing the status of the request to cancel a promotion", + "title": "Message", + "type": "string" } }, "required": [ "status", - "percent_traffic_to_new_version" + "message" ], - "title": "InProgressPromotionV1", + "title": "CancelPromotionResponseV1", "type": "object" }, - "OneTimeAutoscalingScheduleV1": { + "SignalPromotionResponseV1": { + "description": "The response to a request to signal a rolling promotion.", + "properties": { + "success": { + "description": "Whether the signal was successfully sent", + "title": "Success", + "type": "boolean" + } + }, + "required": [ + "success" + ], + "title": "SignalPromotionResponseV1", + "type": "object" + }, + "ChainV1": { + "description": "A chain.", "properties": { "id": { - "description": "Stable unique identifier of the schedule", + "description": "Unique identifier of the chain", "title": "Id", "type": "string" }, - "name": { - "description": "Name of the schedule", - "title": "Name", + "created_at": { + "description": "Time the chain was created in ISO 8601 format", + "format": "date-time", + "title": "Created At", "type": "string" }, - "enabled": { - "description": "Whether the schedule is enabled", - "title": "Enabled", - "type": "boolean" - }, - "autoscaling_settings": { - "$ref": "#/components/schemas/AutoscalingScheduleSettingsV1", - "description": "Raw autoscaling overrides applied during the schedule window" - }, - "cadence": { - "const": "ONE_TIME", - "description": "One-time schedule cadence", - "title": "Cadence", + "name": { + "description": "Name of the chain", + "title": "Name", "type": "string" }, - "start_at": { - "description": "Inclusive start of the schedule window", - "format": "date-time", - "title": "Start At", - "type": "string" + "deployments_count": { + "description": "Number of deployments of the chain", + "title": "Deployments Count", + "type": "integer" }, - "end_at": { - "description": "Exclusive end of the schedule window", - "format": "date-time", - "title": "End At", + "team_name": { + "description": "Name of the team associated with the chain", + "title": "Team Name", "type": "string" } }, "required": [ "id", + "created_at", "name", - "enabled", - "autoscaling_settings", - "cadence", - "start_at", - "end_at" + "deployments_count", + "team_name" ], - "title": "OneTimeAutoscalingScheduleV1", + "title": "ChainV1", "type": "object" }, - "PromotionCleanupStrategyV1": { - "description": "The promotion cleanup strategy.", - "enum": [ - "KEEP", - "SCALE_TO_ZERO", - "DEACTIVATE" + "ChainsV1": { + "description": "A list of chains.", + "properties": { + "chains": { + "items": { + "$ref": "#/components/schemas/ChainV1" + }, + "title": "Chains", + "type": "array" + } + }, + "required": [ + "chains" ], - "title": "PromotionCleanupStrategyV1", - "type": "string" + "title": "ChainsV1", + "type": "object" }, - "PromotionSettingsV1": { - "description": "Promotion settings for promoting chains and oracles", + "ChainTombstoneV1": { + "description": "A chain tombstone.", "properties": { - "redeploy_on_promotion": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } - ], - "default": false, - "description": "Whether to deploy on all promotions. Enabling this flag allows model code to safely handle environment-specific logic. When a deployment is promoted, a new deployment will be created with a copy of the image.", - "examples": [ - true - ], - "title": "Redeploy On Promotion" + "id": { + "description": "Unique identifier of the chain", + "title": "Id", + "type": "string" }, - "rolling_deploy": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } - ], - "default": false, - "description": "Whether the environment should rely on rolling deploy orchestration.", - "examples": [ - true - ], - "title": "Rolling Deploy" + "deleted": { + "description": "Whether the chain was deleted", + "title": "Deleted", + "type": "boolean" + } + }, + "required": [ + "id", + "deleted" + ], + "title": "ChainTombstoneV1", + "type": "object" + }, + "ChainDeploymentV1": { + "description": "A deployment of a chain.", + "properties": { + "id": { + "description": "Unique identifier of the chain deployment", + "title": "Id", + "type": "string" + }, + "created_at": { + "description": "Time the chain deployment was created in ISO 8601 format", + "format": "date-time", + "title": "Created At", + "type": "string" + }, + "chain_id": { + "description": "Unique identifier of the chain", + "title": "Chain Id", + "type": "string" }, - "promotion_cleanup_strategy": { + "environment": { "anyOf": [ { - "$ref": "#/components/schemas/PromotionCleanupStrategyV1" + "type": "string" }, { "type": "null" } ], - "default": "SCALE_TO_ZERO", - "description": "The cleanup strategy to use after a promotion completes.", - "examples": [ - "SCALE_TO_ZERO" - ] + "description": "Environment the chain deployment is deployed in", + "title": "Environment" }, - "rolling_deploy_config": { - "anyOf": [ - { - "$ref": "#/components/schemas/RollingDeployConfigV1" - }, - { - "type": "null" - } - ], - "default": null, - "description": "Rolling deploy configuration for promotions" + "chainlets": { + "description": "Chainlets in the chain deployment", + "items": { + "$ref": "#/components/schemas/ChainletV1" + }, + "title": "Chainlets", + "type": "array" }, - "ramp_up_while_promoting": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } - ], - "default": false, - "description": "Whether to ramp up traffic while promoting", - "examples": [ - true - ], - "title": "Ramp Up While Promoting" + "status": { + "$ref": "#/components/schemas/DeploymentStatusV1", + "description": "Status of the chain deployment" + } + }, + "required": [ + "id", + "created_at", + "chain_id", + "environment", + "chainlets", + "status" + ], + "title": "ChainDeploymentV1", + "type": "object" + }, + "ChainletV1": { + "description": "A chainlet in a chain deployment.", + "properties": { + "id": { + "description": "Unique identifier of the chainlet", + "title": "Id", + "type": "string" }, - "ramp_up_duration_seconds": { + "name": { + "description": "Name of the chainlet", + "title": "Name", + "type": "string" + }, + "autoscaling_settings": { "anyOf": [ { - "type": "integer" + "$ref": "#/components/schemas/AutoscalingSettingsV1" }, { "type": "null" } ], - "default": 600, - "description": "Duration of the ramp up in seconds", - "examples": [ - 600 - ], - "title": "Ramp Up Duration Seconds" - } - }, - "title": "PromotionSettingsV1", - "type": "object" - }, - "RollingDeployConfigV1": { - "description": "Rolling deploy config for promoting chains and oracles", - "properties": { - "rolling_deploy_strategy": { - "$ref": "#/components/schemas/RollingDeployStrategyV1", - "default": "REPLICA", - "description": "The rolling deploy strategy to use for promotions.", - "examples": [ - "REPLICA" - ] - }, - "max_surge_percent": { - "default": 25, - "description": "The maximum surge percentage for rolling deploys.", - "examples": [ - 25 - ], - "title": "Max Surge Percent", - "type": "integer" + "description": "Autoscaling settings for the chainlet. If null, it has not finished deploying" }, - "max_unavailable_percent": { - "default": 0, - "description": "The maximum unavailable percentage for rolling deploys.", - "examples": [ - 10 - ], - "title": "Max Unavailable Percent", - "type": "integer" + "instance_type_name": { + "description": "Name of the instance type the chainlet is deployed on", + "title": "Instance Type Name", + "type": "string" }, - "stabilization_time_seconds": { - "default": 0, - "description": "The stabilization time in seconds for rolling deploys.", - "examples": [ - 300 - ], - "title": "Stabilization Time Seconds", + "active_replica_count": { + "description": "Number of active replicas", + "title": "Active Replica Count", "type": "integer" }, - "replica_overhead_percent": { - "default": 0, - "description": "The replica overhead percentage for rolling deploys.", - "examples": [ - 0 - ], - "title": "Replica Overhead Percent", - "type": "integer" + "status": { + "$ref": "#/components/schemas/DeploymentStatusV1", + "description": "Status of the chainlet" } }, - "title": "RollingDeployConfigV1", - "type": "object" - }, - "RollingDeployStrategyV1": { - "description": "The rolling deploy strategy.", - "enum": [ - "REPLICA" + "required": [ + "id", + "name", + "autoscaling_settings", + "instance_type_name", + "active_replica_count", + "status" ], - "title": "RollingDeployStrategyV1", - "type": "string" + "title": "ChainletV1", + "type": "object" }, - "EnvironmentsV1": { - "description": "list of environments", + "ChainDeploymentsV1": { + "description": "A list of chain deployments.", "properties": { - "environments": { + "deployments": { + "description": "A list of chain deployments", "items": { - "$ref": "#/components/schemas/EnvironmentV1" + "$ref": "#/components/schemas/ChainDeploymentV1" }, - "title": "Environments", + "title": "Deployments", "type": "array" } }, "required": [ - "environments" + "deployments" ], - "title": "EnvironmentsV1", + "title": "ChainDeploymentsV1", "type": "object" }, - "UpdatePromotionSettingsV1": { - "description": "Promotion settings for model promotion", + "ChainDeploymentTombstoneV1": { + "description": "A chain deployment tombstone.", "properties": { - "redeploy_on_promotion": { + "id": { + "description": "Unique identifier of the chain deployment", + "title": "Id", + "type": "string" + }, + "deleted": { + "description": "Whether the chain deployment was deleted", + "title": "Deleted", + "type": "boolean" + }, + "chain_id": { + "description": "Unique identifier of the chain", + "title": "Chain Id", + "type": "string" + } + }, + "required": [ + "id", + "deleted", + "chain_id" + ], + "title": "ChainDeploymentTombstoneV1", + "type": "object" + }, + "ChainletEnvironmentSettingsRequestV1": { + "description": "Request to create environment settings for a chainlet.", + "properties": { + "chainlet_name": { + "description": "Name of the chainlet", + "examples": [ + "HelloWorld" + ], + "title": "Chainlet Name", + "type": "string" + }, + "autoscaling_settings": { "anyOf": [ { - "type": "boolean" + "$ref": "#/components/schemas/UpdateAutoscalingSettingsV1" }, { "type": "null" } ], "default": null, - "description": "Whether to deploy on all promotions. Enabling this flag allows model code to safely handle environment-specific logic. When a deployment is promoted, a new deployment will be created with a copy of the image.", + "description": "Autoscaling settings for the chainlet", "examples": [ - true - ], - "title": "Redeploy On Promotion" - }, - "rolling_deploy": { - "anyOf": [ { - "type": "boolean" - }, - { - "type": "null" + "autoscaling_window": 60, + "concurrency_target": 1, + "max_replica": 1, + "max_scale_down_rate": null, + "min_replica": 0, + "scale_down_delay": 900, + "target_in_flight_tokens": null, + "target_utilization_percentage": 70 } + ] + }, + "instance_type_id": { + "default": "1x2", + "description": "ID of the instance type to use for the chainlet", + "examples": [ + "1x4", + "2x8", + "A10G:2x24x96", + "H100:2x52x468" ], - "default": null, - "description": "Whether the environment should rely on rolling deploy orchestration.", + "title": "Instance Type Id", + "type": "string" + } + }, + "required": [ + "chainlet_name" + ], + "title": "ChainletEnvironmentSettingsRequestV1", + "type": "object" + }, + "CreateChainEnvironmentRequestV1": { + "description": "A request to create a custom environment for a chain.", + "properties": { + "name": { + "description": "Name of the environment", "examples": [ - true + "staging" ], - "title": "Rolling Deploy" + "title": "Name", + "type": "string" }, - "promotion_cleanup_strategy": { + "promotion_settings": { "anyOf": [ { - "$ref": "#/components/schemas/PromotionCleanupStrategyV1" + "$ref": "#/components/schemas/UpdatePromotionSettingsV1" }, { "type": "null" } ], "default": null, - "description": "The cleanup strategy to use after a promotion completes.", + "description": "Promotion settings for the environment", "examples": [ - "SCALE_TO_ZERO" - ] - }, - "rolling_deploy_config": { - "anyOf": [ - { - "$ref": "#/components/schemas/UpdateRollingDeployConfigV1" - }, { - "type": "null" + "promotion_cleanup_strategy": null, + "ramp_up_duration_seconds": 600, + "ramp_up_while_promoting": true, + "redeploy_on_promotion": true, + "rolling_deploy": null, + "rolling_deploy_config": null } - ], - "default": null, - "description": "Rolling deploy configuration for promotions" + ] }, - "ramp_up_while_promoting": { + "chainlet_settings": { "anyOf": [ { - "type": "boolean" + "items": { + "$ref": "#/components/schemas/ChainletEnvironmentSettingsRequestV1" + }, + "type": "array" }, { "type": "null" } ], "default": null, - "description": "Whether to ramp up traffic while promoting", + "description": "Mapping of chainlet name to the desired chainlet environment settings", "examples": [ - true + [ + { + "autoscaling_settings": { + "autoscaling_window": 800, + "concurrency_target": 4, + "max_replica": 3, + "max_scale_down_rate": null, + "min_replica": 2, + "scale_down_delay": 63, + "target_in_flight_tokens": null, + "target_utilization_percentage": null + }, + "chainlet_name": "HelloWorld", + "instance_type_id": "2x8" + }, + { + "autoscaling_settings": { + "autoscaling_window": null, + "concurrency_target": null, + "max_replica": 3, + "max_scale_down_rate": null, + "min_replica": 3, + "scale_down_delay": null, + "target_in_flight_tokens": null, + "target_utilization_percentage": null + }, + "chainlet_name": "RandInt", + "instance_type_id": "A10Gx8x32" + } + ] ], - "title": "Ramp Up While Promoting" + "title": "Chainlet Settings" + } + }, + "required": [ + "name" + ], + "title": "CreateChainEnvironmentRequestV1", + "type": "object" + }, + "ChainletEnvironmentSettingsV1": { + "description": "Environment settings for a chainlet.", + "properties": { + "chainlet_name": { + "description": "Name of the chainlet", + "title": "Chainlet Name", + "type": "string" }, - "ramp_up_duration_seconds": { + "autoscaling_settings": { "anyOf": [ { - "type": "integer" + "$ref": "#/components/schemas/AutoscalingSettingsV1" }, { "type": "null" } ], - "default": null, - "description": "Duration of the ramp up in seconds", - "examples": [ - 600 - ], - "title": "Ramp Up Duration Seconds" + "description": "Autoscaling settings for the chainlet. If null, it has not finished deploying" + }, + "instance_type": { + "$ref": "#/components/schemas/InstanceTypeV1", + "description": "Instance type for the chainlet" } }, - "title": "UpdatePromotionSettingsV1", + "required": [ + "chainlet_name", + "autoscaling_settings", + "instance_type" + ], + "title": "ChainletEnvironmentSettingsV1", "type": "object" }, - "UpdateRollingDeployConfigV1": { - "description": "Rolling deploy config for promoting chains and oracles", + "ChainEnvironmentV1": { + "description": "Environment for oracles.", "properties": { - "rolling_deploy_strategy": { + "name": { + "description": "Name of the environment", + "title": "Name", + "type": "string" + }, + "created_at": { + "description": "Time the environment was created in ISO 8601 format", + "format": "date-time", + "title": "Created At", + "type": "string" + }, + "chain_id": { + "description": "Unique identifier of the chain", + "title": "Chain Id", + "type": "string" + }, + "promotion_settings": { + "$ref": "#/components/schemas/PromotionSettingsV1", + "description": "Promotion settings for the environment" + }, + "chainlet_settings": { + "description": "Environment settings for the chainlets", + "items": { + "$ref": "#/components/schemas/ChainletEnvironmentSettingsV1" + }, + "title": "Chainlet Settings", + "type": "array" + }, + "current_deployment": { "anyOf": [ { - "$ref": "#/components/schemas/RollingDeployStrategyV1" + "$ref": "#/components/schemas/ChainDeploymentV1" }, { "type": "null" } ], - "default": null, - "description": "The rolling deploy strategy to use for promotions.", - "examples": [ - "REPLICA" - ] + "description": "Current chain deployment of the environment" }, - "max_surge_percent": { + "candidate_deployment": { "anyOf": [ { - "type": "integer" + "$ref": "#/components/schemas/ChainDeploymentV1" }, { "type": "null" } ], "default": null, - "description": "The maximum surge percentage for rolling deploys.", - "examples": [ - 25 - ], - "title": "Max Surge Percent" + "description": "Candidate chain deployment being promoted to the environment, if a promotion is in progress" }, - "max_unavailable_percent": { + "in_progress_promotion": { "anyOf": [ { - "type": "integer" + "$ref": "#/components/schemas/InProgressPromotionV1" }, { "type": "null" } ], "default": null, - "description": "The maximum unavailable percentage for rolling deploys.", - "examples": [ - 10 - ], - "title": "Max Unavailable Percent" - }, - "stabilization_time_seconds": { + "description": "Details of the in-progress promotion, if any" + } + }, + "required": [ + "name", + "created_at", + "chain_id", + "promotion_settings", + "chainlet_settings", + "current_deployment" + ], + "title": "ChainEnvironmentV1", + "type": "object" + }, + "UpdateChainEnvironmentRequestV1": { + "description": "A request to update a chain environment.", + "properties": { + "promotion_settings": { "anyOf": [ { - "type": "integer" + "$ref": "#/components/schemas/UpdatePromotionSettingsV1" }, { "type": "null" } ], "default": null, - "description": "The stabilization time in seconds for rolling deploys.", + "description": "Promotion settings for the environment", "examples": [ - 300 - ], - "title": "Stabilization Time Seconds" - }, - "replica_overhead_percent": { - "anyOf": [ - { - "type": "integer" - }, { - "type": "null" + "promotion_cleanup_strategy": null, + "ramp_up_duration_seconds": 600, + "ramp_up_while_promoting": true, + "redeploy_on_promotion": null, + "rolling_deploy": null, + "rolling_deploy_config": null } - ], - "default": null, - "description": "The replica overhead percentage for rolling deploys.", + ] + } + }, + "title": "UpdateChainEnvironmentRequestV1", + "type": "object" + }, + "UpdateChainEnvironmentResponseV1": { + "description": "A response to update a chain environment.", + "properties": { + "ok": { + "description": "Whether the update was successful", + "title": "Ok", + "type": "boolean" + } + }, + "required": [ + "ok" + ], + "title": "UpdateChainEnvironmentResponseV1", + "type": "object" + }, + "PromoteToChainEnvironmentRequestV1": { + "description": "A request to promote a deployment to a environment.", + "properties": { + "scale_down_previous_deployment": { + "default": true, + "description": "Whether to scale down the previous deployment after promoting", "examples": [ - 0 + true ], - "title": "Replica Overhead Percent" + "title": "Scale Down Previous Deployment", + "type": "boolean" + }, + "deployment_id": { + "description": "The id of the chain deployment to promote", + "title": "Deployment Id", + "type": "string" } }, - "title": "UpdateRollingDeployConfigV1", + "required": [ + "deployment_id" + ], + "title": "PromoteToChainEnvironmentRequestV1", "type": "object" }, - "CreateEnvironmentRequestV1": { - "description": "A request to create an environment.", + "ChainletEnvironmentAutoscalingSettingsUpdateV1": { + "description": "The request to update the autoscaling settings for a chainlet.", "properties": { - "name": { - "description": "Name of the environment", + "chainlet_name": { + "description": "Name of the chainlet", "examples": [ - "staging" + "HelloWorld" ], - "title": "Name", + "title": "Chainlet Name", "type": "string" }, "autoscaling_settings": { - "anyOf": [ - { - "$ref": "#/components/schemas/UpdateAutoscalingSettingsV1" - }, - { - "type": "null" - } - ], - "default": null, - "description": "Autoscaling settings for the environment", + "$ref": "#/components/schemas/UpdateAutoscalingSettingsV1", + "description": "Autoscaling settings for the chainlet", "examples": [ { "autoscaling_window": 800, @@ -17632,279 +21829,233 @@ "target_utilization_percentage": null } ] - }, - "promotion_settings": { - "anyOf": [ - { - "$ref": "#/components/schemas/UpdatePromotionSettingsV1" - }, - { - "type": "null" - } - ], - "default": null, - "description": "Promotion settings for the environment", + } + }, + "required": [ + "chainlet_name", + "autoscaling_settings" + ], + "title": "ChainletEnvironmentAutoscalingSettingsUpdateV1", + "type": "object" + }, + "UpdateChainletEnvironmentAutoscalingSettingsRequestV1": { + "description": "A request to update the autoscaling settings for a multiple chainlets in an environment.\nIf a chainlet name doesn't exist, an error is returned.", + "properties": { + "updates": { + "description": "Mapping of chainlet name to the desired chainlet autoscaling settings. If the chainlet name doesn't exist, an error is returned.", "examples": [ - { - "promotion_cleanup_strategy": null, - "ramp_up_duration_seconds": 600, - "ramp_up_while_promoting": true, - "redeploy_on_promotion": true, - "rolling_deploy": true, - "rolling_deploy_config": null - } - ] - }, - "request_backpressure_settings": { - "anyOf": [ - { - "$ref": "#/components/schemas/UpdateRequestBackpressureSettingsV1" - }, - { - "type": "null" - } + [ + { + "autoscaling_settings": { + "autoscaling_window": 800, + "concurrency_target": 4, + "max_replica": 3, + "max_scale_down_rate": null, + "min_replica": 2, + "scale_down_delay": 63, + "target_in_flight_tokens": null, + "target_utilization_percentage": null + }, + "chainlet_name": "HelloWorld" + } + ], + [ + { + "autoscaling_settings": { + "autoscaling_window": null, + "concurrency_target": null, + "max_replica": null, + "max_scale_down_rate": null, + "min_replica": 0, + "scale_down_delay": null, + "target_in_flight_tokens": null, + "target_utilization_percentage": null + }, + "chainlet_name": "HelloWorld" + }, + { + "autoscaling_settings": { + "autoscaling_window": null, + "concurrency_target": null, + "max_replica": null, + "max_scale_down_rate": null, + "min_replica": 0, + "scale_down_delay": null, + "target_in_flight_tokens": null, + "target_utilization_percentage": null + }, + "chainlet_name": "RandInt" + } + ] ], - "default": null, - "description": "Request backpressure settings for the environment." + "items": { + "$ref": "#/components/schemas/ChainletEnvironmentAutoscalingSettingsUpdateV1" + }, + "title": "Updates", + "type": "array" } }, "required": [ - "name" + "updates" ], - "title": "CreateEnvironmentRequestV1", + "title": "UpdateChainletEnvironmentAutoscalingSettingsRequestV1", "type": "object" }, - "EnvironmentTombstoneV1": { - "description": "An environment tombstone.", + "ChainletEnvironmentInstanceTypeUpdateV1": { + "description": "A request to update the environment settings for a chainlet.", "properties": { - "name": { - "description": "Name of the environment", - "title": "Name", + "chainlet_name": { + "description": "Name of the chainlet", + "examples": [ + "HelloWorld" + ], + "title": "Chainlet Name", "type": "string" }, - "model_id": { - "description": "Unique identifier of the model", - "title": "Model Id", + "instance_type_id": { + "description": "Key of the instance type to use for the chainlet", + "examples": [ + "1x4", + "2x8", + "A10G:2x24x96" + ], + "title": "Instance Type Id", "type": "string" - }, - "deleted": { - "description": "Whether the environment was deleted", - "title": "Deleted", - "type": "boolean" } }, "required": [ - "name", - "model_id", - "deleted" + "chainlet_name", + "instance_type_id" ], - "title": "EnvironmentTombstoneV1", + "title": "ChainletEnvironmentInstanceTypeUpdateV1", "type": "object" }, - "AutoscalingScheduleSettingsRequestV1": { - "additionalProperties": false, - "description": "A complete set of raw autoscaling overrides for a schedule.", + "UpdateChainletEnvironmentInstanceTypeRequestV1": { + "description": "A request to update the instance types for chainlets in an environment. Multiples\nupdates can be made in one request. The updates will be processed in batch and a new deployment\nwill be created, deployed and promoted into the environment.", "properties": { - "min_replica": { - "description": "Minimum number of replicas", - "title": "Min Replica", - "type": "integer" - }, - "max_replica": { - "description": "Maximum number of replicas", - "title": "Max Replica", - "type": "integer" - }, - "autoscaling_window": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Timeframe of traffic considered for autoscaling decisions. Null stores no schedule override and follows the current environment value.", - "title": "Autoscaling Window" - }, - "scale_down_delay": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Waiting period before scaling down any active replica. Null stores no schedule override and follows the current environment value.", - "title": "Scale Down Delay" - }, - "concurrency_target": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Number of requests per replica before scaling up. Null stores no schedule override and follows the current environment value.", - "title": "Concurrency Target" - }, - "target_utilization_percentage": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Target utilization percentage for scaling up/down. Null stores no schedule override and follows the current environment value.", - "title": "Target Utilization Percentage" - }, - "target_in_flight_tokens": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Target number of in-flight tokens for autoscaling decisions. Null stores no schedule override and follows the current environment value. Early access only.", - "title": "Target In Flight Tokens" - }, - "max_scale_down_rate": { - "anyOf": [ - { - "maximum": 50, - "minimum": 1, - "type": "integer" - }, - { - "type": "null" - } + "updates": { + "description": "Mapping of chainlet name to the desired chainlet instance type. If the chainlet name doesn't exist, an error is returned.", + "examples": [ + [ + { + "chainlet_name": "HelloWorld", + "instance_type_id": "1x4" + }, + { + "chainlet_name": "RandInt", + "instance_type_id": "A10G:2x24x96" + } + ] ], - "description": "Maximum percentage of replicas that can be removed per autoscaling window. Null stores no schedule override and follows the current environment value.", - "title": "Max Scale Down Rate" + "items": { + "$ref": "#/components/schemas/ChainletEnvironmentInstanceTypeUpdateV1" + }, + "title": "Updates", + "type": "array" } }, "required": [ - "min_replica", - "max_replica", - "autoscaling_window", - "scale_down_delay", - "concurrency_target", - "target_utilization_percentage", - "target_in_flight_tokens", - "max_scale_down_rate" + "updates" ], - "title": "AutoscalingScheduleSettingsRequestV1", + "title": "UpdateChainletEnvironmentInstanceTypeRequestV1", "type": "object" }, - "AutoscalingScheduleUpsertV1": { - "additionalProperties": false, - "description": "A complete recurring schedule submitted for create or replacement.", + "UpdateChainletEnvironmentInstanceTypeResponseV1": { + "description": "A response to update the environment settings for a chainlet. If updating the instance type\nresulted in a re-deployment, `requires_redeployment` will be True and the resulting deployment\nwill be returned in the `chain_deployment` field.", "properties": { - "id": { + "requires_redeployment": { + "description": "Whether the resource update requires a re-deployment to update the instance type.", + "title": "Requires Redeployment", + "type": "boolean" + }, + "chain_deployment": { "anyOf": [ { - "type": "string" + "$ref": "#/components/schemas/ChainDeploymentV1" }, { "type": "null" } ], - "default": null, - "description": "Stable schedule identifier. Omit this field to create a schedule.", - "title": "Id" - }, - "name": { - "description": "Name of the schedule", - "title": "Name", - "type": "string" - }, - "enabled": { - "description": "Whether the schedule is enabled", - "title": "Enabled", - "type": "boolean" - }, - "autoscaling_settings": { - "$ref": "#/components/schemas/AutoscalingScheduleSettingsRequestV1", - "description": "Complete raw autoscaling overrides for the schedule. Every field is required; nullable fields store no schedule override and follow the current environment value." - }, - "cadence": { - "description": "Recurring schedule cadence", - "enum": [ - "DAILY", - "HOURLY" - ], - "title": "Cadence", - "type": "string" + "description": "The chain deployment resulting from the resource update, if any." }, - "weekdays": { - "description": "Weekdays on which the schedule runs", + "chainlet_environment_settings": { + "description": "The updated chainlet environment settings", "items": { - "$ref": "#/components/schemas/AutoscalingScheduleWeekdayV1" + "$ref": "#/components/schemas/ChainletEnvironmentSettingsV1" }, - "title": "Weekdays", + "title": "Chainlet Environment Settings", "type": "array" - }, - "start_hour": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null, - "description": "Start hour in the environment schedule timezone. Omit for unrestricted HOURLY schedules.", - "title": "Start Hour" - }, - "start_minute": { - "description": "Start minute of the schedule window", - "title": "Start Minute", - "type": "integer" - }, - "end_hour": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } + } + }, + "required": [ + "requires_redeployment", + "chain_deployment", + "chainlet_environment_settings" + ], + "title": "UpdateChainletEnvironmentInstanceTypeResponseV1", + "type": "object" + }, + "UpsertTrainingProjectV1": { + "description": "Fields that can be upserted on a training project.", + "properties": { + "name": { + "description": "Name of the training project.", + "examples": [ + "My Training Project" ], - "default": null, - "description": "End hour in the environment schedule timezone. Omit for unrestricted HOURLY schedules.", - "title": "End Hour" - }, - "end_minute": { - "description": "End minute of the schedule window", - "title": "End Minute", - "type": "integer" + "title": "Name", + "type": "string" } }, "required": [ - "name", - "enabled", - "autoscaling_settings", - "cadence", - "weekdays", - "start_minute", - "end_minute" + "name" ], - "title": "AutoscalingScheduleUpsertV1", + "title": "UpsertTrainingProjectV1", "type": "object" }, - "OneTimeAutoscalingScheduleUpsertV1": { - "additionalProperties": false, - "description": "A complete one-time schedule submitted for create or replacement.", + "UpsertTrainingProjectRequestV1": { + "description": "A request to upsert a training project.", + "properties": { + "training_project": { + "$ref": "#/components/schemas/UpsertTrainingProjectV1", + "description": "The training project to upsert." + } + }, + "required": [ + "training_project" + ], + "title": "UpsertTrainingProjectRequestV1", + "type": "object" + }, + "CheckpointSyncStatus": { + "description": "Lifecycle state for the checkpoint uploader.", + "enum": [ + "SYNCING", + "COMPLETED" + ], + "title": "CheckpointSyncStatus", + "type": "string" + }, + "TrainingJobV1": { "properties": { "id": { + "description": "Unique identifier of the training job.", + "title": "Id", + "type": "string" + }, + "created_at": { + "description": "Time the job was created in ISO 8601 format.", + "format": "date-time", + "title": "Created At", + "type": "string" + }, + "current_status": { + "description": "Current status of the training job.", + "title": "Current Status", + "type": "string" + }, + "error_message": { "anyOf": [ { "type": "string" @@ -17914,368 +22065,493 @@ } ], "default": null, - "description": "Stable schedule identifier. Omit this field to create a schedule.", - "title": "Id" - }, - "name": { - "description": "Name of the schedule", - "title": "Name", - "type": "string" - }, - "enabled": { - "description": "Whether the schedule is enabled", - "title": "Enabled", - "type": "boolean" + "description": "Error message if the training job failed.", + "title": "Error Message" }, - "autoscaling_settings": { - "$ref": "#/components/schemas/AutoscalingScheduleSettingsRequestV1", - "description": "Complete raw autoscaling overrides for the schedule. Every field is required; nullable fields store no schedule override and follow the current environment value." + "instance_type": { + "$ref": "#/components/schemas/InstanceTypeV1", + "description": "Instance type of the training job." }, - "cadence": { - "const": "ONE_TIME", - "description": "One-time schedule cadence", - "title": "Cadence", - "type": "string" + "node_count": { + "default": 1, + "description": "Number of nodes the job runs on. The instance type describes a single node, so the job's total GPU count is gpu_count multiplied by node_count.", + "examples": [ + 2 + ], + "minimum": 1, + "title": "Node Count", + "type": "integer" }, - "start_at": { - "description": "Inclusive start of the schedule window in ISO 8601 format. New schedules must start in the future.", + "updated_at": { + "description": "Time the job was updated in ISO 8601 format.", "format": "date-time", - "title": "Start At", + "title": "Updated At", "type": "string" }, - "end_at": { - "description": "Exclusive end of the schedule window in ISO 8601 format", - "format": "date-time", - "title": "End At", + "training_project_id": { + "description": "ID of the training project.", + "title": "Training Project Id", "type": "string" - } - }, - "required": [ - "name", - "enabled", - "autoscaling_settings", - "cadence", - "start_at", - "end_at" - ], - "title": "OneTimeAutoscalingScheduleUpsertV1", - "type": "object" - }, - "UpdateAutoscalingScheduleSettingsV1": { - "additionalProperties": false, - "description": "Partial mutation of an environment's autoscaling schedule collection.", - "properties": { - "timezone": { + }, + "training_project": { + "$ref": "#/components/schemas/TrainingProjectSummaryV1", + "description": "Summary of the training project." + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Name of the training job.", + "examples": [ + "gpt-oss-job" + ], + "title": "Name" + }, + "checkpoint_sync_status": { "anyOf": [ { - "type": "string" + "$ref": "#/components/schemas/CheckpointSyncStatus" }, { "type": "null" } ], "default": null, - "description": "IANA timezone shared by the resulting collection. Omission preserves the current timezone; null is allowed only when deleting every schedule.", - "title": "Timezone", - "x-null-distinct": true + "description": "Checkpoint sync status of the training job." }, - "schedules": { - "description": "Complete schedules to create or replace. Existing schedules omitted from this list are unchanged.", - "items": { - "discriminator": { - "mapping": { - "DAILY": "#/components/schemas/AutoscalingScheduleUpsertV1", - "HOURLY": "#/components/schemas/AutoscalingScheduleUpsertV1", - "ONE_TIME": "#/components/schemas/OneTimeAutoscalingScheduleUpsertV1" - }, - "propertyName": "cadence" + "priority": { + "default": 0, + "description": "Queue priority. Higher values are dequeued first. NULL is treated as 0.", + "title": "Priority", + "type": "integer" + }, + "availability_model": { + "$ref": "#/components/schemas/V1AvailabilityModel", + "default": "dedicated", + "description": "Capacity guarantee for the job. 'dedicated' is non-preemptible on-demand capacity; 'spot' is interruptible." + }, + "user": { + "anyOf": [ + { + "$ref": "#/components/schemas/UserV1" }, - "oneOf": [ - { - "$ref": "#/components/schemas/AutoscalingScheduleUpsertV1" - }, - { - "$ref": "#/components/schemas/OneTimeAutoscalingScheduleUpsertV1" - } - ] - }, - "title": "Schedules", - "type": "array" + { + "type": "null" + } + ], + "default": null, + "description": "The user who created the training job." + } + }, + "required": [ + "id", + "created_at", + "current_status", + "instance_type", + "updated_at", + "training_project_id", + "training_project" + ], + "title": "TrainingJobV1", + "type": "object" + }, + "TrainingProjectSummaryV1": { + "description": "A summary of a training project.", + "properties": { + "id": { + "description": "Unique identifier of the training project.", + "title": "Id", + "type": "string" }, - "delete_schedules": { - "description": "Stable identifiers of schedules to delete. To clear all schedules, include every existing schedule identifier.", - "items": { - "type": "string" - }, - "title": "Delete Schedules", - "type": "array" + "name": { + "description": "Name of the training project.", + "title": "Name", + "type": "string" } }, - "title": "UpdateAutoscalingScheduleSettingsV1", + "required": [ + "id", + "name" + ], + "title": "TrainingProjectSummaryV1", "type": "object" }, - "UpdateEnvironmentRequestV1": { - "additionalProperties": false, - "description": "A request to update an environment.", + "TrainingProjectV1": { "properties": { - "autoscaling_settings": { + "id": { + "description": "Unique identifier of the training project", + "title": "Id", + "type": "string" + }, + "name": { + "description": "Name of the training project.", + "title": "Name", + "type": "string" + }, + "created_at": { + "description": "Time the training project was created in ISO 8601 format.", + "format": "date-time", + "title": "Created At", + "type": "string" + }, + "updated_at": { + "description": "Time the training project was updated in ISO 8601 format.", + "format": "date-time", + "title": "Updated At", + "type": "string" + }, + "team_name": { "anyOf": [ { - "$ref": "#/components/schemas/UpdateAutoscalingSettingsV1" + "type": "string" }, { "type": "null" } ], "default": null, - "description": "Autoscaling settings for the environment", - "examples": [ - { - "autoscaling_window": 800, - "concurrency_target": 3, - "max_replica": 2, - "max_scale_down_rate": null, - "min_replica": 1, - "scale_down_delay": 60, - "target_in_flight_tokens": null, - "target_utilization_percentage": null - } - ] + "description": "Name of the team associated with the training project.", + "title": "Team Name" }, - "promotion_settings": { + "latest_job": { "anyOf": [ { - "$ref": "#/components/schemas/UpdatePromotionSettingsV1" + "$ref": "#/components/schemas/TrainingJobV1" }, { "type": "null" } ], - "default": null, - "description": "Promotion settings for the environment", - "examples": [ - { - "promotion_cleanup_strategy": null, - "ramp_up_duration_seconds": 600, - "ramp_up_while_promoting": true, - "redeploy_on_promotion": true, - "rolling_deploy": null, - "rolling_deploy_config": null - } - ] - }, - "autoscaling_schedule_settings": { + "description": "Most recently created training job for the training project." + } + }, + "required": [ + "id", + "name", + "created_at", + "updated_at", + "latest_job" + ], + "title": "TrainingProjectV1", + "type": "object" + }, + "UserV1": { + "description": "A user.", + "properties": { + "email": { "anyOf": [ { - "$ref": "#/components/schemas/UpdateAutoscalingScheduleSettingsV1" + "type": "string" }, { "type": "null" } ], "default": null, - "description": "Partial autoscaling schedule collection update. Omitted collection fields and existing schedules are unchanged; each submitted schedule is a complete create or replacement.", - "examples": [ - { - "schedules": [ - { - "autoscaling_settings": { - "autoscaling_window": null, - "concurrency_target": null, - "max_replica": 8, - "max_scale_down_rate": null, - "min_replica": 2, - "scale_down_delay": null, - "target_in_flight_tokens": null, - "target_utilization_percentage": null - }, - "cadence": "DAILY", - "enabled": true, - "end_hour": 10, - "end_minute": 0, - "name": "weekday-peak", - "start_hour": 8, - "start_minute": 0, - "weekdays": [ - "MONDAY", - "TUESDAY", - "WEDNESDAY", - "THURSDAY", - "FRIDAY" - ] - } - ], - "timezone": "America/Los_Angeles" - }, - { - "delete_schedules": [ - "schedule-id" - ] - } - ] + "description": "Email of the user.", + "title": "Email" + } + }, + "title": "UserV1", + "type": "object" + }, + "V1AvailabilityModel": { + "description": "Capacity guarantee under which a training job is scheduled.\n\n``DEDICATED`` is on-demand capacity that is not preempted (the default). ``SPOT`` is\ninterruptible capacity that may be preempted; the user is responsible for checkpointing\ntheir own progress. A managed/resumable model where the platform handles\ncheckpoint/resume on its own is intentionally not defined yet; it is planned for a\nfuture milestone.", + "enum": [ + "dedicated", + "spot" + ], + "title": "V1AvailabilityModel", + "type": "string" + }, + "UpsertTrainingProjectResponseV1": { + "description": "A response to upserting a training project.", + "properties": { + "training_project": { + "$ref": "#/components/schemas/TrainingProjectV1", + "description": "The upserted training project." + } + }, + "required": [ + "training_project" + ], + "title": "UpsertTrainingProjectResponseV1", + "type": "object" + }, + "ListTrainingProjectsResponseV1": { + "description": "A response to list training projects.", + "properties": { + "training_projects": { + "description": "List of training projects.", + "items": { + "$ref": "#/components/schemas/TrainingProjectV1" + }, + "title": "Training Projects", + "type": "array" + } + }, + "required": [ + "training_projects" + ], + "title": "ListTrainingProjectsResponseV1", + "type": "object" + }, + "ListTrainingJobsResponseV1": { + "description": "A response to list training jobs.", + "properties": { + "training_project": { + "$ref": "#/components/schemas/TrainingProjectV1", + "description": "The training project." }, - "request_backpressure_settings": { - "anyOf": [ - { - "$ref": "#/components/schemas/UpdateRequestBackpressureSettingsV1" - }, - { - "type": "null" - } - ], - "default": null, - "description": "Request backpressure settings for the environment.", - "examples": [ - { - "policy": "REJECT_ON_FULL" - } - ] + "training_jobs": { + "description": "List of training jobs.", + "items": { + "$ref": "#/components/schemas/TrainingJobV1" + }, + "title": "Training Jobs", + "type": "array" } }, - "title": "UpdateEnvironmentRequestV1", + "required": [ + "training_project", + "training_jobs" + ], + "title": "ListTrainingJobsResponseV1", "type": "object" }, - "UpdateEnvironmentResponseV1": { - "description": "The response to a request to update an environment's settings.", + "AuthMethod": { + "enum": [ + "CUSTOM_SECRET", + "AWS_OIDC", + "GCP_OIDC", + "AWS_ASSUME_ROLE" + ], + "title": "AuthMethod", + "type": "string" + }, + "AwsAssumeRoleDockerAuthV1": { + "description": "AWS assume-role details for the registry.", "properties": { - "environment": { - "$ref": "#/components/schemas/EnvironmentV1", - "description": "The environment after the update, matching the shape returned by GET." + "role_arn": { + "description": "AWS IAM role ARN that Baseten assumes to pull from the registry. The role's trust policy must allow Baseten's AWS principal with your Baseten-provided external ID.", + "title": "Role Arn", + "type": "string" }, - "status": { - "$ref": "#/components/schemas/UpdateAutoscalingSettingsStatusV1", - "deprecated": true, - "description": "Deprecated. Kept for legacy autoscaling-only update operation behavior." + "region": { + "description": "AWS region of the registry", + "title": "Region", + "type": "string" + } + }, + "required": [ + "role_arn", + "region" + ], + "title": "AwsAssumeRoleDockerAuthV1", + "type": "object" + }, + "AwsIamDockerAuthV1": { + "description": "AWS details for the registry.", + "properties": { + "access_key_secret_ref": { + "$ref": "#/components/schemas/SecretReferenceV1", + "description": "Name of the access key secret" }, - "message": { - "deprecated": true, - "description": "Deprecated. Kept for legacy autoscaling-only update operation behavior.", - "title": "Message", + "secret_access_key_secret_ref": { + "$ref": "#/components/schemas/SecretReferenceV1", + "description": "Name of the secret key secret" + } + }, + "required": [ + "access_key_secret_ref", + "secret_access_key_secret_ref" + ], + "title": "AwsIamDockerAuthV1", + "type": "object" + }, + "AwsOidcDockerAuthV1": { + "description": "AWS OIDC details for the registry.", + "properties": { + "role_arn": { + "description": "AWS IAM role ARN for OIDC authentication", + "title": "Role Arn", + "type": "string" + }, + "region": { + "description": "AWS region for OIDC authentication", + "title": "Region", "type": "string" } }, "required": [ - "environment", - "status", - "message" + "role_arn", + "region" ], - "title": "UpdateEnvironmentResponseV1", + "title": "AwsOidcDockerAuthV1", "type": "object" }, - "GetEnvironmentLogsRequestV1": { - "description": "A request to fetch logs for a model environment.\n\nReturns logs from every deployment that was active on the environment over\nthe requested time range, merged in timestamp order.", + "BasetenLatestCheckpointConfig": { "properties": { - "start_epoch_millis": { + "project_name": { "anyOf": [ { - "type": "integer" + "type": "string" }, { "type": "null" } ], "default": null, - "description": "Epoch milliseconds at which to start fetching logs. Defaults to 30 minutes before the end. The window from start to end must not exceed 7 days.", - "title": "Start Epoch Millis" + "description": "Name of the project to load the checkpoint from", + "title": "Project Name" }, - "end_epoch_millis": { + "job_id": { "anyOf": [ { - "type": "integer" + "type": "string" }, { "type": "null" } ], "default": null, - "description": "Epoch milliseconds at which to stop fetching logs. Defaults to the current time.", - "title": "End Epoch Millis" + "description": "ID of the job to load the checkpoint from", + "title": "Job Id" }, - "direction": { + "typ": { + "const": "baseten_latest_checkpoint", + "default": "baseten_latest_checkpoint", + "title": "Typ", + "type": "string" + } + }, + "title": "BasetenLatestCheckpointConfig", + "type": "object" + }, + "BasetenNamedCheckpointConfig": { + "properties": { + "checkpoint_name": { + "description": "Name of the checkpoint to load from", + "title": "Checkpoint Name", + "type": "string" + }, + "project_name": { "anyOf": [ { - "$ref": "#/components/schemas/SortOrderV1" + "type": "string" }, { "type": "null" } ], "default": null, - "description": "Sort order for logs" + "description": "Name of the project to load the checkpoint from", + "title": "Project Name" }, - "limit": { + "job_id": { "anyOf": [ { - "maximum": 1000, - "minimum": 1, - "type": "integer" + "type": "string" }, { "type": "null" } ], - "default": 500, - "description": "Limit of logs to fetch in a single request", - "title": "Limit" + "default": null, + "description": "ID of the job to load the checkpoint from", + "title": "Job Id" }, - "min_level": { - "anyOf": [ - { - "$ref": "#/components/schemas/LogLevelV1" - }, - { - "type": "null" - } + "typ": { + "const": "baseten_named_checkpoint", + "default": "baseten_named_checkpoint", + "title": "Typ", + "type": "string" + } + }, + "required": [ + "checkpoint_name" + ], + "title": "BasetenNamedCheckpointConfig", + "type": "object" + }, + "CreateJobWeightConfigV1": { + "description": "Weight source configuration for MDN (Model Distribution Network).\n\nEnables training jobs to mount external model weights from HuggingFace, S3, GCS, R2,\nor CoreWeave via MDN's caching and CSI mounting infrastructure. Weights are mirrored\nonce and deduplicated across training jobs.", + "properties": { + "source": { + "description": "Weight source URI. Supported formats: hf://, s3://, gs://, r2://, cw://", + "examples": [ + "hf://meta-llama/Llama-3-8B@main", + "s3://my-bucket/models/llama", + "gs://my-bucket/models/llama", + "r2://account_id.bucket/models/llama", + "r2://account_id.eu.bucket/models/llama", + "cw://my-bucket/models/llama" ], - "default": null, - "description": "Minimum log severity to include. Omit to return all log lines, including lines that have no level. Any explicit value returns lines at or above that severity and drops lines without a level." + "title": "Source", + "type": "string" }, - "replica": { - "anyOf": [ - { - "maxLength": 256, - "type": "string" - }, - { - "type": "null" - } + "mount_location": { + "description": "Path where weights will be mounted in the container", + "examples": [ + "/app/models/base", + "/models/llama" ], - "default": null, - "description": "Only return logs emitted by this replica (5-char short ID).", - "title": "Replica" + "title": "Mount Location", + "type": "string" }, - "request_id": { + "allow_patterns": { "anyOf": [ { - "maxLength": 256, - "type": "string" + "items": { + "type": "string" + }, + "type": "array" }, { "type": "null" } ], "default": null, - "description": "Only return logs tagged with this inference request ID.", - "title": "Request Id" + "description": "File patterns to include (Unix-style shell patterns)", + "examples": [ + [ + "*.safetensors", + "config.json" + ] + ], + "title": "Allow Patterns" }, - "component": { + "ignore_patterns": { "anyOf": [ { - "maxLength": 256, - "type": "string" + "items": { + "type": "string" + }, + "type": "array" }, { "type": "null" } ], "default": null, - "description": "Only return logs from this component.", - "title": "Component" + "description": "File patterns to exclude (Unix-style shell patterns)", + "examples": [ + [ + "*.bin", + "*.h5" + ] + ], + "title": "Ignore Patterns" }, - "search_pattern": { + "auth_secret_name": { "anyOf": [ { - "maxLength": 256, "type": "string" }, { @@ -18283,890 +22559,863 @@ } ], "default": null, - "description": "RE2 regular expression matched against the log message. Prefer `includes` and `excludes` for plain substring matches.", - "title": "Search Pattern" - }, - "includes": { - "description": "Case-sensitive substrings that must all appear in the log message.", - "items": { - "type": "string" - }, - "maxItems": 8, - "title": "Includes", - "type": "array" - }, - "excludes": { - "description": "Case-sensitive substrings; lines containing any of these are dropped.", - "items": { - "type": "string" - }, - "maxItems": 8, - "title": "Excludes", - "type": "array" - } - }, - "title": "GetEnvironmentLogsRequestV1", - "type": "object" - }, - "GetEnvironmentMetricsRequestV1": { - "description": "Query params for ``GET /v1/models/.../environments/.../metrics``.", - "properties": { - "mode": { - "$ref": "#/components/schemas/ModelMetricModeV1", - "default": "CURRENT", - "description": "'CURRENT': a single instantaneous snapshot at now; start/end must be omitted. 'SUMMARY': a single value set aggregating the whole window. 'SERIES': evenly-spaced value sets across the window, with the step derived from the window duration." + "description": "Name of the workspace secret for authentication (e.g., HuggingFace token)", + "examples": [ + "hf_token", + "aws_credentials" + ], + "title": "Auth Secret Name" }, - "start_epoch_millis": { + "auth": { "anyOf": [ { - "type": "integer" + "$ref": "#/components/schemas/TrainingWeightAuthV1" }, { "type": "null" } ], "default": null, - "description": "Epoch millis timestamp to start fetching metrics. Defaults to one hour before the end.", - "title": "Start Epoch Millis" - }, - "end_epoch_millis": { - "anyOf": [ + "description": "Authentication configuration for the weight source.", + "examples": [ { - "type": "integer" + "auth_method": "CUSTOM_SECRET", + "auth_secret_name": "hf_token" }, { - "type": "null" + "auth_method": "AWS_OIDC", + "aws_oidc_region": "us-east-1", + "aws_oidc_role_arn": "arn:aws:iam::123456789012:role/weights-access" + }, + { + "auth_method": "GCP_OIDC", + "gcp_oidc_service_account": "weights-reader@example.iam.gserviceaccount.com", + "gcp_oidc_workload_id_provider": "projects/123456789/locations/global/workloadIdentityPools/baseten/providers/baseten" + }, + { + "auth_method": "AWS_ASSUME_ROLE", + "aws_assume_role_arn": "arn:aws:iam::123456789012:role/baseten-customer-access", + "aws_assume_role_region": "us-east-1" } - ], - "default": null, - "description": "Epoch millis timestamp to end fetching metrics. Defaults to the current time. The window between start and end must not exceed 7 days.", - "title": "End Epoch Millis" - }, - "metrics": { - "description": "Names of the metrics to return; see https://docs.baseten.co/observability/export-metrics/supported-metrics for the available names. When omitted, a default set is returned: baseten_replicas_active, baseten_inference_requests_total, and baseten_end_to_end_response_time_seconds. Unknown names are rejected; valid names that do not apply are omitted from the response.", - "items": { - "type": "string" - }, - "title": "Metrics", - "type": "array" + ] } }, - "title": "GetEnvironmentMetricsRequestV1", + "required": [ + "source", + "mount_location" + ], + "title": "CreateJobWeightConfigV1", "type": "object" }, - "PromoteToEnvironmentRequestV1": { - "description": "A request to promote a deployment to a environment.", + "CreateTrainingJobAcceleratorV1": { "properties": { - "scale_down_previous_deployment": { - "default": true, - "description": "Whether to scale down the previous deployment after promoting", + "accelerator": { + "description": "GPU type for the training job.", "examples": [ - true + "H100" ], - "title": "Scale Down Previous Deployment", - "type": "boolean" - }, - "deployment_id": { - "description": "The id of the deployment to promote", - "title": "Deployment Id", + "title": "Accelerator", "type": "string" }, - "preserve_env_instance_type": { - "default": true, - "description": "Whether to use the promoting deployment's instance type or preserve target environment's instance type", + "count": { + "description": "GPUs needed for the training job.", "examples": [ - true + 2 ], - "title": "Preserve Env Instance Type", - "type": "boolean" + "title": "Count", + "type": "integer" } }, "required": [ - "deployment_id" + "accelerator", + "count" ], - "title": "PromoteToEnvironmentRequestV1", + "title": "CreateTrainingJobAcceleratorV1", "type": "object" }, - "CancelPromotionStatusV1": { - "description": "The status of a request to cancel a promotion.", - "enum": [ - "CANCELED", - "RAMPING_DOWN" - ], - "title": "CancelPromotionStatusV1", - "type": "string" - }, - "CancelPromotionResponseV1": { - "description": "The response to a request to cancel a promotion.", + "CreateTrainingJobCacheConfig": { "properties": { - "status": { - "$ref": "#/components/schemas/CancelPromotionStatusV1", - "description": "Status of the request to cancel a promotion. Can be CANCELED or RAMPING_DOWN." + "enable_legacy_hf_mount": { + "default": false, + "description": "Whether to enable the legacy Hugging Face cache.", + "examples": [ + true + ], + "title": "Enable Legacy Hf Mount", + "type": "boolean" }, - "message": { - "description": "A message describing the status of the request to cancel a promotion", - "title": "Message", + "enabled": { + "default": false, + "description": "Whether to enable the read-write cache.", + "examples": [ + true + ], + "title": "Enabled", + "type": "boolean" + }, + "require_cache_affinity": { + "default": true, + "description": "Whether to require region affinity for the read-write cache. If False, the resulting job is not guaranteed to be deployed alongside the previous cache.", + "examples": [ + true, + false + ], + "title": "Require Cache Affinity", + "type": "boolean" + }, + "mount_base_path": { + "default": "/root/.cache", + "description": "Mount base path for the cache directory. The project cache and team cache will be mounted under this path.", + "examples": [ + "/workspace/.cache", + "/root/.cache" + ], + "title": "Mount Base Path", "type": "string" } }, - "required": [ - "status", - "message" - ], - "title": "CancelPromotionResponseV1", + "title": "CreateTrainingJobCacheConfig", "type": "object" }, - "SignalPromotionResponseV1": { - "description": "The response to a request to signal a rolling promotion.", + "CreateTrainingJobCheckpointingConfig": { "properties": { - "success": { - "description": "Whether the signal was successfully sent", - "title": "Success", + "enabled": { + "default": false, + "description": "Whether checkpointing is enabled.", + "examples": [ + true + ], + "title": "Enabled", "type": "boolean" - } - }, - "required": [ - "success" - ], - "title": "SignalPromotionResponseV1", - "type": "object" - }, - "ChainV1": { - "description": "A chain.", - "properties": { - "id": { - "description": "Unique identifier of the chain", - "title": "Id", - "type": "string" - }, - "created_at": { - "description": "Time the chain was created in ISO 8601 format", - "format": "date-time", - "title": "Created At", - "type": "string" - }, - "name": { - "description": "Name of the chain", - "title": "Name", - "type": "string" }, - "deployments_count": { - "description": "Number of deployments of the chain", - "title": "Deployments Count", - "type": "integer" - }, - "team_name": { - "description": "Name of the team associated with the chain", - "title": "Team Name", - "type": "string" + "checkpoint_path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "path where checkpoints will be saved.", + "examples": [ + "/mnt/ckpts" + ], + "title": "Checkpoint Path" + }, + "volume_size_gib": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Size of the volume in gibibytes. If not provided, the default size will be used", + "examples": [ + 10 + ], + "title": "Volume Size Gib" } }, - "required": [ - "id", - "created_at", - "name", - "deployments_count", - "team_name" - ], - "title": "ChainV1", + "title": "CreateTrainingJobCheckpointingConfig", "type": "object" }, - "ChainsV1": { - "description": "A list of chains.", + "CreateTrainingJobComputeV1": { + "description": "Configuration to specify the compute for a training job.", "properties": { - "chains": { - "items": { - "$ref": "#/components/schemas/ChainV1" - }, - "title": "Chains", - "type": "array" + "node_count": { + "default": 1, + "description": "Number of nodes for the training job.", + "examples": [ + 1 + ], + "title": "Node Count", + "type": "integer" + }, + "cpu_count": { + "default": 1, + "description": "Number of cpus for the training job.", + "examples": [ + 1 + ], + "title": "Cpu Count", + "type": "integer" + }, + "memory": { + "default": "2Gi", + "description": "Memory for the training job.", + "examples": [ + "2Gi" + ], + "title": "Memory", + "type": "string" + }, + "accelerator": { + "anyOf": [ + { + "$ref": "#/components/schemas/CreateTrainingJobAcceleratorV1" + }, + { + "type": "null" + } + ], + "default": null, + "description": "GPU specification for the training job", + "examples": [ + { + "accelerator": "H100", + "count": 2 + } + ] + }, + "availability_model": { + "$ref": "#/components/schemas/V1AvailabilityModel", + "default": "dedicated", + "description": "Capacity guarantee for the job. 'dedicated' (the default) runs on on-demand capacity that is not preempted. 'spot' runs on interruptible capacity that may be preempted; the user is responsible for checkpointing their own progress.", + "examples": [ + "spot" + ] } }, - "required": [ - "chains" - ], - "title": "ChainsV1", + "title": "CreateTrainingJobComputeV1", "type": "object" }, - "ChainTombstoneV1": { - "description": "A chain tombstone.", + "CreateTrainingJobImageV1": { + "description": "Configuration to create a training job image.", "properties": { - "id": { - "description": "Unique identifier of the chain", - "title": "Id", + "base_image": { + "description": "Base image for the training job.", + "examples": [ + "hello-world" + ], + "title": "Base Image", "type": "string" }, - "deleted": { - "description": "Whether the chain was deleted", - "title": "Deleted", - "type": "boolean" + "docker_auth": { + "anyOf": [ + { + "$ref": "#/components/schemas/DockerAuthV1" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Docker authentication credentials" } }, "required": [ - "id", - "deleted" + "base_image" ], - "title": "ChainTombstoneV1", + "title": "CreateTrainingJobImageV1", "type": "object" }, - "ChainDeploymentV1": { - "description": "A deployment of a chain.", + "CreateTrainingJobRuntimeV1": { + "description": "Configuration to specify the runtime environment for a training job.", "properties": { - "id": { - "description": "Unique identifier of the chain deployment", - "title": "Id", - "type": "string" + "start_commands": { + "description": "Commands to execute when starting the runtime.", + "examples": [ + [ + "python main.py" + ] + ], + "items": { + "type": "string" + }, + "title": "Start Commands", + "type": "array" }, - "created_at": { - "description": "Time the chain deployment was created in ISO 8601 format", - "format": "date-time", - "title": "Created At", - "type": "string" + "environment_variables": { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/components/schemas/SecretReferenceV1" + } + ] + }, + "description": "Environment variables to set in the runtime.", + "examples": [ + { + "API_KEY": "your_api_key_here", + "PATH": "/usr/bin" + } + ], + "title": "Environment Variables", + "type": "object" }, - "chain_id": { - "description": "Unique identifier of the chain", - "title": "Chain Id", - "type": "string" + "artifacts": { + "description": "Runtime artifacts for the training job.", + "items": { + "$ref": "#/components/schemas/CreateTrainingJobS3Artifact" + }, + "title": "Artifacts", + "type": "array" }, - "environment": { + "enable_cache": { "anyOf": [ { - "type": "string" + "type": "boolean" }, { "type": "null" } ], - "description": "Environment the chain deployment is deployed in", - "title": "Environment" - }, - "chainlets": { - "description": "Chainlets in the chain deployment", - "items": { - "$ref": "#/components/schemas/ChainletV1" - }, - "title": "Chainlets", - "type": "array" + "default": null, + "description": "Deprecated. Use cache_config instead.", + "examples": [ + true + ], + "title": "Enable Cache" }, - "status": { - "$ref": "#/components/schemas/DeploymentStatusV1", - "description": "Status of the chain deployment" - } - }, - "required": [ - "id", - "created_at", - "chain_id", - "environment", - "chainlets", - "status" - ], - "title": "ChainDeploymentV1", - "type": "object" - }, - "ChainletV1": { - "description": "A chainlet in a chain deployment.", - "properties": { - "id": { - "description": "Unique identifier of the chainlet", - "title": "Id", - "type": "string" + "cache_config": { + "anyOf": [ + { + "$ref": "#/components/schemas/CreateTrainingJobCacheConfig" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Configuration for the read-write cache.", + "examples": [ + { + "enable_legacy_hf_mount": true, + "enabled": true, + "mount_base_path": "/root/.cache", + "require_cache_affinity": true + } + ] }, - "name": { - "description": "Name of the chainlet", - "title": "Name", - "type": "string" + "checkpointing_config": { + "$ref": "#/components/schemas/CreateTrainingJobCheckpointingConfig", + "description": "Configuration for checkpointing.", + "examples": [ + { + "checkpoint_path": "/mnt/ckpts", + "enabled": true, + "volume_size_gib": null + } + ] }, - "autoscaling_settings": { + "load_checkpoint_config": { "anyOf": [ { - "$ref": "#/components/schemas/AutoscalingSettingsV1" + "$ref": "#/components/schemas/LoadCheckpointConfig" }, { "type": "null" } ], - "description": "Autoscaling settings for the chainlet. If null, it has not finished deploying" - }, - "instance_type_name": { - "description": "Name of the instance type the chainlet is deployed on", - "title": "Instance Type Name", - "type": "string" - }, - "active_replica_count": { - "description": "Number of active replicas", - "title": "Active Replica Count", - "type": "integer" - }, - "status": { - "$ref": "#/components/schemas/DeploymentStatusV1", - "description": "Status of the chainlet" - } - }, - "required": [ - "id", - "name", - "autoscaling_settings", - "instance_type_name", - "active_replica_count", - "status" - ], - "title": "ChainletV1", - "type": "object" - }, - "ChainDeploymentsV1": { - "description": "A list of chain deployments.", - "properties": { - "deployments": { - "description": "A list of chain deployments", - "items": { - "$ref": "#/components/schemas/ChainDeploymentV1" - }, - "title": "Deployments", - "type": "array" + "default": null, + "description": "Configuration for loading checkpoints" } }, - "required": [ - "deployments" - ], - "title": "ChainDeploymentsV1", + "title": "CreateTrainingJobRuntimeV1", "type": "object" }, - "ChainDeploymentTombstoneV1": { - "description": "A chain deployment tombstone.", + "CreateTrainingJobS3Artifact": { "properties": { - "id": { - "description": "Unique identifier of the chain deployment", - "title": "Id", + "s3_bucket": { + "description": "S3 bucket for the uploaded runtime artifact.", + "examples": [ + "my-s3-bucket" + ], + "title": "S3 Bucket", "type": "string" }, - "deleted": { - "description": "Whether the chain deployment was deleted", - "title": "Deleted", - "type": "boolean" - }, - "chain_id": { - "description": "Unique identifier of the chain", - "title": "Chain Id", + "s3_key": { + "description": "S3 key for the uploaded runtime artifact.", + "examples": [ + "my-s3-key" + ], + "title": "S3 Key", "type": "string" } }, "required": [ - "id", - "deleted", - "chain_id" + "s3_bucket", + "s3_key" ], - "title": "ChainDeploymentTombstoneV1", + "title": "CreateTrainingJobS3Artifact", "type": "object" }, - "ChainletEnvironmentSettingsRequestV1": { - "description": "Request to create environment settings for a chainlet.", + "CreateTrainingJobV1": { + "description": "Configuration for a training job.", "properties": { - "chainlet_name": { - "description": "Name of the chainlet", + "image": { + "$ref": "#/components/schemas/CreateTrainingJobImageV1", "examples": [ - "HelloWorld" - ], - "title": "Chainlet Name", - "type": "string" + { + "base_image": "hello-world", + "docker_auth": null + } + ] }, - "autoscaling_settings": { + "compute": { + "$ref": "#/components/schemas/CreateTrainingJobComputeV1", + "examples": [ + { + "accelerator": { + "accelerator": "H100", + "count": 2 + }, + "availability_model": "spot", + "cpu_count": 1, + "memory": "2Gi", + "node_count": 1 + } + ] + }, + "runtime": { + "$ref": "#/components/schemas/CreateTrainingJobRuntimeV1", + "description": "Configuration for the runtime environment of the training job.", + "examples": [ + { + "artifacts": [], + "cache_config": null, + "checkpointing_config": { + "checkpoint_path": null, + "enabled": false, + "volume_size_gib": null + }, + "enable_cache": null, + "environment_variables": { + "API_KEY": "your_api_key_here", + "PATH": "/usr/bin" + }, + "load_checkpoint_config": null, + "start_commands": [ + "python main.py" + ] + } + ] + }, + "name": { "anyOf": [ { - "$ref": "#/components/schemas/UpdateAutoscalingSettingsV1" + "type": "string" }, { "type": "null" } ], "default": null, - "description": "Autoscaling settings for the chainlet", + "description": "Name of the training job.", "examples": [ + "gpt-oss-job" + ], + "title": "Name" + }, + "truss_user_env": { + "anyOf": [ { - "autoscaling_window": 60, - "concurrency_target": 1, - "max_replica": 1, - "max_scale_down_rate": null, - "min_replica": 0, - "scale_down_delay": 900, - "target_in_flight_tokens": null, - "target_utilization_percentage": 70 + "$ref": "#/components/schemas/TrussUserEnv" + }, + { + "type": "null" } - ] + ], + "default": null, + "description": "Truss user environment information" }, - "instance_type_id": { - "default": "1x2", - "description": "ID of the instance type to use for the chainlet", + "interactive_session": { + "anyOf": [ + { + "$ref": "#/components/schemas/InteractiveSessionConfigV1" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Configuration for interactive debugging sessions." + }, + "weights": { + "description": "MDN weight sources to mount in the training container. Weights are mirrored and cached for fast startup.", "examples": [ - "1x4", - "2x8", - "A10G:2x24x96", - "H100:2x52x468" + [ + { + "allow_patterns": null, + "auth": null, + "auth_secret_name": null, + "ignore_patterns": null, + "mount_location": "/app/models/base", + "source": "hf://meta-llama/Llama-3-8B@main" + } + ] ], - "title": "Instance Type Id", - "type": "string" + "items": { + "$ref": "#/components/schemas/CreateJobWeightConfigV1" + }, + "title": "Weights", + "type": "array" + }, + "enable_baseten_workdir": { + "default": false, + "description": "When enabled, uses /b10/workspace as the working directory instead of the image WORKDIR.", + "examples": [ + false, + true + ], + "title": "Enable Baseten Workdir", + "type": "boolean" + }, + "priority": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Queue priority. Higher values are dequeued first. Defaults to 0.", + "examples": [ + 0, + 10, + 100 + ], + "title": "Priority" } }, "required": [ - "chainlet_name" + "image" ], - "title": "ChainletEnvironmentSettingsRequestV1", + "title": "CreateTrainingJobV1", "type": "object" }, - "CreateChainEnvironmentRequestV1": { - "description": "A request to create a custom environment for a chain.", - "properties": { - "name": { - "description": "Name of the environment", - "examples": [ - "staging" - ], - "title": "Name", + "DockerAuthType": { + "enum": [ + "GCP_SERVICE_ACCOUNT_JSON", + "AWS_IAM", + "AWS_OIDC", + "GCP_OIDC", + "REGISTRY_SECRET", + "AWS_ASSUME_ROLE" + ], + "title": "DockerAuthType", + "type": "string" + }, + "DockerAuthV1": { + "description": "Docker authentication credentials.", + "properties": { + "registry": { + "description": "Registry to authenticate with", + "title": "Registry", "type": "string" }, - "promotion_settings": { + "auth_method": { + "$ref": "#/components/schemas/DockerAuthType", + "description": "Method to authenticate with the registry", + "examples": [ + "GCP_SERVICE_ACCOUNT_JSON", + "AWS_IAM", + "AWS_OIDC", + "GCP_OIDC", + "REGISTRY_SECRET", + "AWS_ASSUME_ROLE" + ] + }, + "gcp_service_account_json_docker_auth": { "anyOf": [ { - "$ref": "#/components/schemas/UpdatePromotionSettingsV1" + "$ref": "#/components/schemas/GcpServiceAccountJsonDockerAuthV1" }, { "type": "null" } ], "default": null, - "description": "Promotion settings for the environment", - "examples": [ + "description": "GCP service account details for the registry" + }, + "aws_iam_docker_auth": { + "anyOf": [ { - "promotion_cleanup_strategy": null, - "ramp_up_duration_seconds": 600, - "ramp_up_while_promoting": true, - "redeploy_on_promotion": true, - "rolling_deploy": null, - "rolling_deploy_config": null + "$ref": "#/components/schemas/AwsIamDockerAuthV1" + }, + { + "type": "null" } - ] + ], + "default": null, + "description": "AWS details for the registry" }, - "chainlet_settings": { + "aws_oidc_docker_auth": { "anyOf": [ { - "items": { - "$ref": "#/components/schemas/ChainletEnvironmentSettingsRequestV1" - }, - "type": "array" + "$ref": "#/components/schemas/AwsOidcDockerAuthV1" }, { "type": "null" } ], "default": null, - "description": "Mapping of chainlet name to the desired chainlet environment settings", - "examples": [ - [ - { - "autoscaling_settings": { - "autoscaling_window": 800, - "concurrency_target": 4, - "max_replica": 3, - "max_scale_down_rate": null, - "min_replica": 2, - "scale_down_delay": 63, - "target_in_flight_tokens": null, - "target_utilization_percentage": null - }, - "chainlet_name": "HelloWorld", - "instance_type_id": "2x8" - }, - { - "autoscaling_settings": { - "autoscaling_window": null, - "concurrency_target": null, - "max_replica": 3, - "max_scale_down_rate": null, - "min_replica": 3, - "scale_down_delay": null, - "target_in_flight_tokens": null, - "target_utilization_percentage": null - }, - "chainlet_name": "RandInt", - "instance_type_id": "A10Gx8x32" - } - ] - ], - "title": "Chainlet Settings" - } - }, - "required": [ - "name" - ], - "title": "CreateChainEnvironmentRequestV1", - "type": "object" - }, - "ChainletEnvironmentSettingsV1": { - "description": "Environment settings for a chainlet.", - "properties": { - "chainlet_name": { - "description": "Name of the chainlet", - "title": "Chainlet Name", - "type": "string" + "description": "AWS OIDC details for the registry" }, - "autoscaling_settings": { + "gcp_oidc_docker_auth": { "anyOf": [ { - "$ref": "#/components/schemas/AutoscalingSettingsV1" + "$ref": "#/components/schemas/GcpOidcDockerAuthV1" }, { "type": "null" } ], - "description": "Autoscaling settings for the chainlet. If null, it has not finished deploying" - }, - "instance_type": { - "$ref": "#/components/schemas/InstanceTypeV1", - "description": "Instance type for the chainlet" - } - }, - "required": [ - "chainlet_name", - "autoscaling_settings", - "instance_type" - ], - "title": "ChainletEnvironmentSettingsV1", - "type": "object" - }, - "ChainEnvironmentV1": { - "description": "Environment for oracles.", - "properties": { - "name": { - "description": "Name of the environment", - "title": "Name", - "type": "string" - }, - "created_at": { - "description": "Time the environment was created in ISO 8601 format", - "format": "date-time", - "title": "Created At", - "type": "string" - }, - "chain_id": { - "description": "Unique identifier of the chain", - "title": "Chain Id", - "type": "string" - }, - "promotion_settings": { - "$ref": "#/components/schemas/PromotionSettingsV1", - "description": "Promotion settings for the environment" - }, - "chainlet_settings": { - "description": "Environment settings for the chainlets", - "items": { - "$ref": "#/components/schemas/ChainletEnvironmentSettingsV1" - }, - "title": "Chainlet Settings", - "type": "array" + "default": null, + "description": "GCP OIDC details for the registry" }, - "current_deployment": { + "registry_secret_docker_auth": { "anyOf": [ { - "$ref": "#/components/schemas/ChainDeploymentV1" + "$ref": "#/components/schemas/RegistrySecretDockerAuthV1" }, { "type": "null" } ], - "description": "Current chain deployment of the environment" + "default": null, + "description": "Required when auth_method is REGISTRY_SECRET. Supports any Docker registry (Docker Hub, GHCR, NGC, etc.) via username:password credentials stored as a Baseten secret." }, - "candidate_deployment": { + "aws_assume_role_docker_auth": { "anyOf": [ { - "$ref": "#/components/schemas/ChainDeploymentV1" + "$ref": "#/components/schemas/AwsAssumeRoleDockerAuthV1" }, { "type": "null" } ], "default": null, - "description": "Candidate chain deployment being promoted to the environment, if a promotion is in progress" + "description": "Required when auth_method is AWS_ASSUME_ROLE. Baseten assumes the given IAM role with its own AWS principal and your organization's external ID, with no OIDC provider registration in your account." } }, "required": [ - "name", - "created_at", - "chain_id", - "promotion_settings", - "chainlet_settings", - "current_deployment" + "registry", + "auth_method" ], - "title": "ChainEnvironmentV1", + "title": "DockerAuthV1", "type": "object" }, - "UpdateChainEnvironmentRequestV1": { - "description": "A request to update a chain environment.", + "GcpOidcDockerAuthV1": { + "description": "GCP OIDC details for the registry.", "properties": { - "promotion_settings": { - "anyOf": [ - { - "$ref": "#/components/schemas/UpdatePromotionSettingsV1" - }, - { - "type": "null" - } - ], - "default": null, - "description": "Promotion settings for the environment", - "examples": [ - { - "promotion_cleanup_strategy": null, - "ramp_up_duration_seconds": 600, - "ramp_up_while_promoting": true, - "redeploy_on_promotion": null, - "rolling_deploy": null, - "rolling_deploy_config": null - } - ] + "service_account": { + "description": "GCP service account name for OIDC authentication", + "title": "Service Account", + "type": "string" + }, + "workload_identity_provider": { + "description": "GCP workload identity provider for OIDC authentication", + "title": "Workload Identity Provider", + "type": "string" } }, - "title": "UpdateChainEnvironmentRequestV1", + "required": [ + "service_account", + "workload_identity_provider" + ], + "title": "GcpOidcDockerAuthV1", "type": "object" }, - "UpdateChainEnvironmentResponseV1": { - "description": "A response to update a chain environment.", + "GcpServiceAccountJsonDockerAuthV1": { + "description": "GCP details for the registry.", "properties": { - "ok": { - "description": "Whether the update was successful", - "title": "Ok", - "type": "boolean" + "service_account_json_secret_ref": { + "$ref": "#/components/schemas/SecretReferenceV1", + "description": "Name of the service account secret" } }, "required": [ - "ok" + "service_account_json_secret_ref" ], - "title": "UpdateChainEnvironmentResponseV1", + "title": "GcpServiceAccountJsonDockerAuthV1", "type": "object" }, - "PromoteToChainEnvironmentRequestV1": { - "description": "A request to promote a deployment to a environment.", + "GitInfo": { "properties": { - "scale_down_previous_deployment": { - "default": true, - "description": "Whether to scale down the previous deployment after promoting", - "examples": [ - true + "latest_commit_sha": { + "title": "Latest Commit Sha", + "type": "string" + }, + "latest_tag": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Latest Tag" + }, + "commits_since_tag": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } ], - "title": "Scale Down Previous Deployment", - "type": "boolean" + "title": "Commits Since Tag" }, - "deployment_id": { - "description": "The id of the chain deployment to promote", - "title": "Deployment Id", - "type": "string" + "has_uncommitted_changes": { + "title": "Has Uncommitted Changes", + "type": "boolean" } }, "required": [ - "deployment_id" + "latest_commit_sha", + "latest_tag", + "commits_since_tag", + "has_uncommitted_changes" ], - "title": "PromoteToChainEnvironmentRequestV1", + "title": "GitInfo", "type": "object" }, - "ChainletEnvironmentAutoscalingSettingsUpdateV1": { - "description": "The request to update the autoscaling settings for a chainlet.", + "InteractiveSessionConfigV1": { + "description": "Configuration for interactive debugging sessions on training jobs.", "properties": { - "chainlet_name": { - "description": "Name of the chainlet", + "trigger": { + "$ref": "#/components/schemas/V1InteractiveSessionTrigger", + "default": "on_demand", + "description": "When to create the interactive session. 'on_startup' creates on job start, 'on_failure' creates on job failure, 'on_demand' bypasses automatic session creation." + }, + "timeout_minutes": { + "default": 480, + "description": "Number of minutes before the interactive session times out.", "examples": [ - "HelloWorld" + 480, + 1440, + 10080 ], - "title": "Chainlet Name", - "type": "string" + "title": "Timeout Minutes", + "type": "integer" }, - "autoscaling_settings": { - "$ref": "#/components/schemas/UpdateAutoscalingSettingsV1", - "description": "Autoscaling settings for the chainlet", - "examples": [ - { - "autoscaling_window": 800, - "concurrency_target": 3, - "max_replica": 2, - "max_scale_down_rate": null, - "min_replica": 1, - "scale_down_delay": 60, - "target_in_flight_tokens": null, - "target_utilization_percentage": null - } - ] + "session_provider": { + "$ref": "#/components/schemas/V1InteractiveSessionProvider", + "default": "vs_code", + "description": "The IDE client for the interactive session." + }, + "auth_provider": { + "$ref": "#/components/schemas/V1InteractiveSessionAuthProvider", + "default": "github", + "description": "The authentication provider for the interactive session." } }, - "required": [ - "chainlet_name", - "autoscaling_settings" - ], - "title": "ChainletEnvironmentAutoscalingSettingsUpdateV1", + "title": "InteractiveSessionConfigV1", "type": "object" }, - "UpdateChainletEnvironmentAutoscalingSettingsRequestV1": { - "description": "A request to update the autoscaling settings for a multiple chainlets in an environment.\nIf a chainlet name doesn't exist, an error is returned.", + "LoadCheckpointConfig": { "properties": { - "updates": { - "description": "Mapping of chainlet name to the desired chainlet autoscaling settings. If the chainlet name doesn't exist, an error is returned.", - "examples": [ - [ + "enabled": { + "default": false, + "description": "Whether checkpoint loading is enabled", + "title": "Enabled", + "type": "boolean" + }, + "download_folder": { + "default": "/tmp/loaded_checkpoints", + "description": "Folder where checkpoints will be downloaded", + "title": "Download Folder", + "type": "string" + }, + "checkpoints": { + "description": "List of checkpoint configurations", + "items": { + "discriminator": { + "mapping": { + "baseten_latest_checkpoint": "#/components/schemas/BasetenLatestCheckpointConfig", + "baseten_named_checkpoint": "#/components/schemas/BasetenNamedCheckpointConfig", + "loops_checkpoint": "#/components/schemas/LoopsCheckpointConfig" + }, + "propertyName": "typ" + }, + "oneOf": [ { - "autoscaling_settings": { - "autoscaling_window": 800, - "concurrency_target": 4, - "max_replica": 3, - "max_scale_down_rate": null, - "min_replica": 2, - "scale_down_delay": 63, - "target_in_flight_tokens": null, - "target_utilization_percentage": null - }, - "chainlet_name": "HelloWorld" - } - ], - [ + "$ref": "#/components/schemas/BasetenLatestCheckpointConfig" + }, { - "autoscaling_settings": { - "autoscaling_window": null, - "concurrency_target": null, - "max_replica": null, - "max_scale_down_rate": null, - "min_replica": 0, - "scale_down_delay": null, - "target_in_flight_tokens": null, - "target_utilization_percentage": null - }, - "chainlet_name": "HelloWorld" + "$ref": "#/components/schemas/BasetenNamedCheckpointConfig" }, { - "autoscaling_settings": { - "autoscaling_window": null, - "concurrency_target": null, - "max_replica": null, - "max_scale_down_rate": null, - "min_replica": 0, - "scale_down_delay": null, - "target_in_flight_tokens": null, - "target_utilization_percentage": null - }, - "chainlet_name": "RandInt" + "$ref": "#/components/schemas/LoopsCheckpointConfig" } ] - ], - "items": { - "$ref": "#/components/schemas/ChainletEnvironmentAutoscalingSettingsUpdateV1" }, - "title": "Updates", + "title": "Checkpoints", "type": "array" } }, - "required": [ - "updates" - ], - "title": "UpdateChainletEnvironmentAutoscalingSettingsRequestV1", + "title": "LoadCheckpointConfig", "type": "object" }, - "ChainletEnvironmentInstanceTypeUpdateV1": { - "description": "A request to update the environment settings for a chainlet.", + "LoopsCheckpointConfig": { "properties": { - "chainlet_name": { - "description": "Name of the chainlet", - "examples": [ - "HelloWorld" - ], - "title": "Chainlet Name", + "run_id": { + "description": "ID of the Loops run to load the checkpoint from", + "title": "Run Id", "type": "string" }, - "instance_type_id": { - "description": "Key of the instance type to use for the chainlet", - "examples": [ - "1x4", - "2x8", - "A10G:2x24x96" - ], - "title": "Instance Type Id", + "checkpoint_name": { + "description": "Name of the checkpoint to load", + "title": "Checkpoint Name", "type": "string" - } - }, - "required": [ - "chainlet_name", - "instance_type_id" - ], - "title": "ChainletEnvironmentInstanceTypeUpdateV1", - "type": "object" - }, - "UpdateChainletEnvironmentInstanceTypeRequestV1": { - "description": "A request to update the instance types for chainlets in an environment. Multiples\nupdates can be made in one request. The updates will be processed in batch and a new deployment\nwill be created, deployed and promoted into the environment.", - "properties": { - "updates": { - "description": "Mapping of chainlet name to the desired chainlet instance type. If the chainlet name doesn't exist, an error is returned.", - "examples": [ - [ - { - "chainlet_name": "HelloWorld", - "instance_type_id": "1x4" - }, - { - "chainlet_name": "RandInt", - "instance_type_id": "A10G:2x24x96" - } - ] + }, + "target": { + "default": "trainer", + "description": "Which checkpoint target to load: 'trainer' (full training state) or 'sampler' (inference weights)", + "enum": [ + "trainer", + "sampler" ], - "items": { - "$ref": "#/components/schemas/ChainletEnvironmentInstanceTypeUpdateV1" - }, - "title": "Updates", - "type": "array" + "title": "Target", + "type": "string" + }, + "typ": { + "const": "loops_checkpoint", + "default": "loops_checkpoint", + "title": "Typ", + "type": "string" } }, "required": [ - "updates" + "run_id", + "checkpoint_name" ], - "title": "UpdateChainletEnvironmentInstanceTypeRequestV1", + "title": "LoopsCheckpointConfig", "type": "object" }, - "UpdateChainletEnvironmentInstanceTypeResponseV1": { - "description": "A response to update the environment settings for a chainlet. If updating the instance type\nresulted in a re-deployment, `requires_redeployment` will be True and the resulting deployment\nwill be returned in the `chain_deployment` field.", + "RegistrySecretDockerAuthV1": { + "description": "Authentication via a Baseten secret for any Docker registry (Docker Hub, GHCR, NGC, etc.).\nThe referenced secret must contain credentials in the format 'username:password'.\nFor Docker Hub, set registry to 'https://index.docker.io/v1/'. For GHCR, use 'ghcr.io'.", "properties": { - "requires_redeployment": { - "description": "Whether the resource update requires a re-deployment to update the instance type.", - "title": "Requires Redeployment", - "type": "boolean" - }, - "chain_deployment": { - "anyOf": [ - { - "$ref": "#/components/schemas/ChainDeploymentV1" - }, - { - "type": "null" - } - ], - "description": "The chain deployment resulting from the resource update, if any." - }, - "chainlet_environment_settings": { - "description": "The updated chainlet environment settings", - "items": { - "$ref": "#/components/schemas/ChainletEnvironmentSettingsV1" - }, - "title": "Chainlet Environment Settings", - "type": "array" + "secret_ref": { + "$ref": "#/components/schemas/SecretReferenceV1", + "description": "Reference to a Baseten secret containing credentials in the format 'username:password'" } }, "required": [ - "requires_redeployment", - "chain_deployment", - "chainlet_environment_settings" + "secret_ref" ], - "title": "UpdateChainletEnvironmentInstanceTypeResponseV1", + "title": "RegistrySecretDockerAuthV1", "type": "object" }, - "UpsertTrainingProjectV1": { - "description": "Fields that can be upserted on a training project.", + "SecretReferenceV1": { "properties": { "name": { - "description": "Name of the training project.", + "description": "Name of the secret to reference.", "examples": [ - "My Training Project" + "hf_token" ], "title": "Name", "type": "string" @@ -19175,51 +23424,17 @@ "required": [ "name" ], - "title": "UpsertTrainingProjectV1", - "type": "object" - }, - "UpsertTrainingProjectRequestV1": { - "description": "A request to upsert a training project.", - "properties": { - "training_project": { - "$ref": "#/components/schemas/UpsertTrainingProjectV1", - "description": "The training project to upsert." - } - }, - "required": [ - "training_project" - ], - "title": "UpsertTrainingProjectRequestV1", + "title": "SecretReferenceV1", "type": "object" }, - "CheckpointSyncStatus": { - "description": "Lifecycle state for the checkpoint uploader.", - "enum": [ - "SYNCING", - "COMPLETED" - ], - "title": "CheckpointSyncStatus", - "type": "string" - }, - "TrainingJobV1": { + "TrainingWeightAuthV1": { + "description": "Authentication configuration for a training weight source.", "properties": { - "id": { - "description": "Unique identifier of the training job.", - "title": "Id", - "type": "string" - }, - "created_at": { - "description": "Time the job was created in ISO 8601 format.", - "format": "date-time", - "title": "Created At", - "type": "string" - }, - "current_status": { - "description": "Current status of the training job.", - "title": "Current Status", - "type": "string" + "auth_method": { + "$ref": "#/components/schemas/AuthMethod", + "description": "Method used to authenticate the weight source." }, - "error_message": { + "auth_secret_name": { "anyOf": [ { "type": "string" @@ -19229,39 +23444,23 @@ } ], "default": null, - "description": "Error message if the training job failed.", - "title": "Error Message" - }, - "instance_type": { - "$ref": "#/components/schemas/InstanceTypeV1", - "description": "Instance type of the training job." + "description": "Name of the workspace secret used for custom-secret authentication.", + "title": "Auth Secret Name" }, - "node_count": { - "default": 1, - "description": "Number of nodes the job runs on. The instance type describes a single node, so the job's total GPU count is gpu_count multiplied by node_count.", - "examples": [ - 2 + "aws_oidc_role_arn": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } ], - "minimum": 1, - "title": "Node Count", - "type": "integer" - }, - "updated_at": { - "description": "Time the job was updated in ISO 8601 format.", - "format": "date-time", - "title": "Updated At", - "type": "string" - }, - "training_project_id": { - "description": "ID of the training project.", - "title": "Training Project Id", - "type": "string" - }, - "training_project": { - "$ref": "#/components/schemas/TrainingProjectSummaryV1", - "description": "Summary of the training project." + "default": null, + "description": "AWS IAM role ARN used for OIDC authentication.", + "title": "Aws Oidc Role Arn" }, - "name": { + "aws_oidc_region": { "anyOf": [ { "type": "string" @@ -19271,106 +23470,84 @@ } ], "default": null, - "description": "Name of the training job.", - "examples": [ - "gpt-oss-job" - ], - "title": "Name" + "description": "AWS region used for OIDC authentication.", + "title": "Aws Oidc Region" }, - "checkpoint_sync_status": { + "gcp_oidc_service_account": { "anyOf": [ { - "$ref": "#/components/schemas/CheckpointSyncStatus" + "type": "string" }, { "type": "null" } ], "default": null, - "description": "Checkpoint sync status of the training job." - }, - "priority": { - "default": 0, - "description": "Queue priority. Higher values are dequeued first. NULL is treated as 0.", - "title": "Priority", - "type": "integer" + "description": "GCP service account used for OIDC authentication.", + "title": "Gcp Oidc Service Account" }, - "availability_model": { - "$ref": "#/components/schemas/V1AvailabilityModel", - "default": "dedicated", - "description": "Capacity guarantee for the job. 'dedicated' is non-preemptible on-demand capacity; 'spot' is interruptible." + "gcp_oidc_workload_id_provider": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "GCP workload identity provider used for OIDC authentication.", + "title": "Gcp Oidc Workload Id Provider" }, - "user": { + "aws_assume_role_arn": { "anyOf": [ { - "$ref": "#/components/schemas/UserV1" + "type": "string" }, { "type": "null" } ], "default": null, - "description": "The user who created the training job." - } - }, - "required": [ - "id", - "created_at", - "current_status", - "instance_type", - "updated_at", - "training_project_id", - "training_project" - ], - "title": "TrainingJobV1", - "type": "object" - }, - "TrainingProjectSummaryV1": { - "description": "A summary of a training project.", - "properties": { - "id": { - "description": "Unique identifier of the training project.", - "title": "Id", - "type": "string" + "description": "AWS IAM role ARN that Baseten assumes to access the weight source.", + "title": "Aws Assume Role Arn" }, - "name": { - "description": "Name of the training project.", - "title": "Name", - "type": "string" + "aws_assume_role_region": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "AWS region used for assume-role authentication.", + "title": "Aws Assume Role Region" } }, "required": [ - "id", - "name" + "auth_method" ], - "title": "TrainingProjectSummaryV1", + "title": "TrainingWeightAuthV1", "type": "object" }, - "TrainingProjectV1": { + "TrussUserEnv": { + "description": "This data models is used to flexibly store info alongside oracle versions.\n\nThere is a corresponding data model in the truss client.\nIn contrast, here all fields are optional for backwards compatibility with old\nclients.", "properties": { - "id": { - "description": "Unique identifier of the training project", - "title": "Id", - "type": "string" - }, - "name": { - "description": "Name of the training project.", - "title": "Name", - "type": "string" - }, - "created_at": { - "description": "Time the training project was created in ISO 8601 format.", - "format": "date-time", - "title": "Created At", - "type": "string" - }, - "updated_at": { - "description": "Time the training project was updated in ISO 8601 format.", - "format": "date-time", - "title": "Updated At", - "type": "string" + "truss_client_version": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Truss Client Version" }, - "team_name": { + "python_version": { "anyOf": [ { "type": "string" @@ -19380,35 +23557,21 @@ } ], "default": null, - "description": "Name of the team associated with the training project.", - "title": "Team Name" + "title": "Python Version" }, - "latest_job": { + "pydantic_version": { "anyOf": [ { - "$ref": "#/components/schemas/TrainingJobV1" + "type": "string" }, { "type": "null" } ], - "description": "Most recently created training job for the training project." - } - }, - "required": [ - "id", - "name", - "created_at", - "updated_at", - "latest_job" - ], - "title": "TrainingProjectV1", - "type": "object" - }, - "UserV1": { - "description": "A user.", - "properties": { - "email": { + "default": null, + "title": "Pydantic Version" + }, + "mypy_version": { "anyOf": [ { "type": "string" @@ -19418,441 +23581,584 @@ } ], "default": null, - "description": "Email of the user.", - "title": "Email" + "title": "Mypy Version" + }, + "is_library_deployment": { + "default": false, + "title": "Is Library Deployment", + "type": "boolean" + }, + "is_frontend_deployment": { + "default": false, + "title": "Is Frontend Deployment", + "type": "boolean" + }, + "git_info": { + "anyOf": [ + { + "$ref": "#/components/schemas/GitInfo" + }, + { + "type": "null" + } + ], + "default": null } }, - "title": "UserV1", + "title": "TrussUserEnv", "type": "object" }, - "V1AvailabilityModel": { - "description": "Capacity guarantee under which a training job is scheduled.\n\n``DEDICATED`` is on-demand capacity that is not preempted (the default). ``SPOT`` is\ninterruptible capacity that may be preempted; the user is responsible for checkpointing\ntheir own progress. A managed/resumable model where the platform handles\ncheckpoint/resume on its own is intentionally not defined yet; it is planned for a\nfuture milestone.", + "V1InteractiveSessionAuthProvider": { "enum": [ - "dedicated", - "spot" + "github", + "microsoft" ], - "title": "V1AvailabilityModel", + "title": "V1InteractiveSessionAuthProvider", "type": "string" }, - "UpsertTrainingProjectResponseV1": { - "description": "A response to upserting a training project.", + "V1InteractiveSessionProvider": { + "enum": [ + "vs_code", + "cursor", + "ssh" + ], + "title": "V1InteractiveSessionProvider", + "type": "string" + }, + "V1InteractiveSessionTrigger": { + "enum": [ + "on_startup", + "on_failure", + "on_demand" + ], + "title": "V1InteractiveSessionTrigger", + "type": "string" + }, + "CreateTrainingJobRequestV1": { + "description": "A request to create a training job.", "properties": { - "training_project": { - "$ref": "#/components/schemas/TrainingProjectV1", - "description": "The upserted training project." + "training_job": { + "$ref": "#/components/schemas/CreateTrainingJobV1", + "description": "The training job to create." } }, "required": [ - "training_project" + "training_job" ], - "title": "UpsertTrainingProjectResponseV1", + "title": "CreateTrainingJobRequestV1", "type": "object" }, - "ListTrainingProjectsResponseV1": { - "description": "A response to list training projects.", + "CreateTrainingJobResponseV1": { + "description": "A response to creating a training job.", "properties": { - "training_projects": { - "description": "List of training projects.", - "items": { - "$ref": "#/components/schemas/TrainingProjectV1" - }, - "title": "Training Projects", - "type": "array" + "training_job": { + "$ref": "#/components/schemas/TrainingJobV1", + "description": "The created training job." } }, "required": [ - "training_projects" + "training_job" ], - "title": "ListTrainingProjectsResponseV1", + "title": "CreateTrainingJobResponseV1", "type": "object" }, - "ListTrainingJobsResponseV1": { - "description": "A response to list training jobs.", + "TrainingJobTombstoneV1": { + "description": "A training job tombstone.", + "properties": { + "id": { + "description": "Unique identifier of the training job", + "title": "Id", + "type": "string" + }, + "deleted": { + "description": "Whether the training job was deleted", + "title": "Deleted", + "type": "boolean" + }, + "training_project_id": { + "description": "Unique identifier of the training project", + "title": "Training Project Id", + "type": "string" + } + }, + "required": [ + "id", + "deleted", + "training_project_id" + ], + "title": "TrainingJobTombstoneV1", + "type": "object" + }, + "GetTrainingJobResponseV1": { + "description": "A response to fetch a training job.", "properties": { "training_project": { "$ref": "#/components/schemas/TrainingProjectV1", "description": "The training project." }, - "training_jobs": { - "description": "List of training jobs.", - "items": { - "$ref": "#/components/schemas/TrainingJobV1" - }, - "title": "Training Jobs", - "type": "array" + "training_job": { + "$ref": "#/components/schemas/TrainingJobV1", + "description": "The fetched training job." } }, "required": [ "training_project", - "training_jobs" + "training_job" ], - "title": "ListTrainingJobsResponseV1", + "title": "GetTrainingJobResponseV1", "type": "object" }, - "AuthMethod": { - "enum": [ - "CUSTOM_SECRET", - "AWS_OIDC", - "GCP_OIDC", - "AWS_ASSUME_ROLE" - ], - "title": "AuthMethod", - "type": "string" - }, - "AwsAssumeRoleDockerAuthV1": { - "description": "AWS assume-role details for the registry.", + "UpdateTrainingJobRequestV1": { + "description": "A request to update mutable fields on a training job.\n\nEvery field is optional so a caller can patch one without the other, but at least\none must be provided: an empty body has nothing to apply.", + "minProperties": 1, "properties": { - "role_arn": { - "description": "AWS IAM role ARN that Baseten assumes to pull from the registry. The role's trust policy must allow Baseten's AWS principal with your Baseten-provided external ID.", - "title": "Role Arn", - "type": "string" + "priority": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "New queue priority for a PENDING training job. Higher values are dequeued first. Only jobs in the PENDING state can have their priority changed.", + "examples": [ + 0, + 10, + 100 + ], + "title": "Priority" }, - "region": { - "description": "AWS region of the registry", - "title": "Region", - "type": "string" + "availability_model": { + "anyOf": [ + { + "$ref": "#/components/schemas/V1AvailabilityModel" + }, + { + "type": "null" + } + ], + "default": null, + "description": "New capacity guarantee for a PENDING training job. 'dedicated' runs on on-demand capacity that is not preempted. 'spot' runs on interruptible capacity that may be preempted; the user is responsible for checkpointing their own progress. Only jobs in the PENDING state can have their availability model changed.", + "examples": [ + "spot" + ] + } + }, + "title": "UpdateTrainingJobRequestV1", + "type": "object" + }, + "UpdateTrainingJobResponseV1": { + "description": "A response to updating a training job.", + "properties": { + "training_job": { + "$ref": "#/components/schemas/TrainingJobV1", + "description": "The updated training job." } }, "required": [ - "role_arn", - "region" + "training_job" ], - "title": "AwsAssumeRoleDockerAuthV1", + "title": "UpdateTrainingJobResponseV1", "type": "object" }, - "AwsIamDockerAuthV1": { - "description": "AWS details for the registry.", + "DownloadTrainingJobResponseV1": { + "description": "A response with presigned URLs for a training job's artifacts.", "properties": { - "access_key_secret_ref": { - "$ref": "#/components/schemas/SecretReferenceV1", - "description": "Name of the access key secret" - }, - "secret_access_key_secret_ref": { - "$ref": "#/components/schemas/SecretReferenceV1", - "description": "Name of the secret key secret" + "artifact_presigned_urls": { + "description": "Presigned URLs for the job's uploaded artifacts.", + "items": { + "type": "string" + }, + "title": "Artifact Presigned Urls", + "type": "array" } }, "required": [ - "access_key_secret_ref", - "secret_access_key_secret_ref" + "artifact_presigned_urls" ], - "title": "AwsIamDockerAuthV1", + "title": "DownloadTrainingJobResponseV1", "type": "object" }, - "AwsOidcDockerAuthV1": { - "description": "AWS OIDC details for the registry.", + "RecreateTrainingJobResponseV1": { + "description": "A response that sends the new training job", "properties": { - "role_arn": { - "description": "AWS IAM role ARN for OIDC authentication", - "title": "Role Arn", - "type": "string" - }, - "region": { - "description": "AWS region for OIDC authentication", - "title": "Region", - "type": "string" + "training_job": { + "$ref": "#/components/schemas/TrainingJobV1", + "description": "The created training job." } }, "required": [ - "role_arn", - "region" + "training_job" ], - "title": "AwsOidcDockerAuthV1", + "title": "RecreateTrainingJobResponseV1", "type": "object" }, - "BasetenLatestCheckpointConfig": { + "GetTrainingJobLogsRequestV1": { + "description": "A request to fetch training logs.", "properties": { - "project_name": { + "start_epoch_millis": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Epoch milliseconds at which to start fetching logs. Defaults to 30 minutes before the end. The window from start to end must not exceed 7 days.", + "title": "Start Epoch Millis" + }, + "end_epoch_millis": { "anyOf": [ { - "type": "string" + "type": "integer" }, { "type": "null" } ], "default": null, - "description": "Name of the project to load the checkpoint from", - "title": "Project Name" + "description": "Epoch milliseconds at which to stop fetching logs. Defaults to the current time.", + "title": "End Epoch Millis" }, - "job_id": { + "direction": { "anyOf": [ { - "type": "string" + "$ref": "#/components/schemas/SortOrderV1" }, { "type": "null" } ], "default": null, - "description": "ID of the job to load the checkpoint from", - "title": "Job Id" - }, - "typ": { - "const": "baseten_latest_checkpoint", - "default": "baseten_latest_checkpoint", - "title": "Typ", - "type": "string" - } - }, - "title": "BasetenLatestCheckpointConfig", - "type": "object" - }, - "BasetenNamedCheckpointConfig": { - "properties": { - "checkpoint_name": { - "description": "Name of the checkpoint to load from", - "title": "Checkpoint Name", - "type": "string" + "description": "Sort order for logs" }, - "project_name": { + "limit": { "anyOf": [ { - "type": "string" + "maximum": 1000, + "minimum": 1, + "type": "integer" }, { "type": "null" } ], - "default": null, - "description": "Name of the project to load the checkpoint from", - "title": "Project Name" + "default": 500, + "description": "Limit of logs to fetch in a single request", + "title": "Limit" }, - "job_id": { + "min_level": { "anyOf": [ { - "type": "string" + "$ref": "#/components/schemas/LogLevelV1" }, { "type": "null" } ], "default": null, - "description": "ID of the job to load the checkpoint from", - "title": "Job Id" + "description": "Minimum log severity to include. Omit to return all log lines, including lines that have no level. Any explicit value returns lines at or above that severity and drops lines without a level." + } + }, + "title": "GetTrainingJobLogsRequestV1", + "type": "object" + }, + "StorageMetricsV1": { + "description": "A metric for a training job.", + "properties": { + "usage_bytes": { + "description": "The number of bytes used on the storage entity.", + "items": { + "$ref": "#/components/schemas/TrainingJobMetricV1" + }, + "title": "Usage Bytes", + "type": "array" }, - "typ": { - "const": "baseten_named_checkpoint", - "default": "baseten_named_checkpoint", - "title": "Typ", - "type": "string" + "utilization": { + "description": "The utilization of the storage entity as a decimal percentage.", + "items": { + "$ref": "#/components/schemas/TrainingJobMetricV1" + }, + "title": "Utilization", + "type": "array" } }, "required": [ - "checkpoint_name" + "usage_bytes", + "utilization" ], - "title": "BasetenNamedCheckpointConfig", + "title": "StorageMetricsV1", "type": "object" }, - "CreateJobWeightConfigV1": { - "description": "Weight source configuration for MDN (Model Distribution Network).\n\nEnables training jobs to mount external model weights from HuggingFace, S3, GCS, R2,\nor CoreWeave via MDN's caching and CSI mounting infrastructure. Weights are mirrored\nonce and deduplicated across training jobs.", + "TrainingJobMetricV1": { + "description": "A metric for a training job.", "properties": { - "source": { - "description": "Weight source URI. Supported formats: hf://, s3://, gs://, r2://, cw://", - "examples": [ - "hf://meta-llama/Llama-3-8B@main", - "s3://my-bucket/models/llama", - "gs://my-bucket/models/llama", - "r2://account_id.bucket/models/llama", - "r2://account_id.eu.bucket/models/llama", - "cw://my-bucket/models/llama" - ], - "title": "Source", + "value": { + "description": "The value of the metric.", + "title": "Value", + "type": "number" + }, + "timestamp": { + "description": "The timestamp of the metric in ISO 8601 format.", + "format": "date-time", + "title": "Timestamp", "type": "string" + } + }, + "required": [ + "value", + "timestamp" + ], + "title": "TrainingJobMetricV1", + "type": "object" + }, + "TrainingJobMetricsV1": { + "properties": { + "gpu_memory_usage_bytes": { + "additionalProperties": { + "items": { + "$ref": "#/components/schemas/TrainingJobMetricV1" + }, + "type": "array" + }, + "description": "A map of GPU rank to memory usage for the training job. For multinode jobs, this is the memory usage of the leader unless specified otherwise.", + "title": "Gpu Memory Usage Bytes", + "type": "object" }, - "mount_location": { - "description": "Path where weights will be mounted in the container", - "examples": [ - "/app/models/base", - "/models/llama" - ], - "title": "Mount Location", + "gpu_utilization": { + "additionalProperties": { + "items": { + "$ref": "#/components/schemas/TrainingJobMetricV1" + }, + "type": "array" + }, + "description": "A map of GPU rank to fractional GPU utilization. For multinode jobs, this is the GPU utilization of the leader unless specified otherwise.", + "title": "Gpu Utilization", + "type": "object" + }, + "cpu_usage": { + "description": "The CPU usage measured in cores. For multinode jobs, this is the CPU usage of the leader unless specified otherwise.", + "items": { + "$ref": "#/components/schemas/TrainingJobMetricV1" + }, + "title": "Cpu Usage", + "type": "array" + }, + "cpu_memory_usage_bytes": { + "description": "The CPU memory usage for the training job. For multinode jobs, this is the CPU memory usage of the leader unless specified otherwise.", + "items": { + "$ref": "#/components/schemas/TrainingJobMetricV1" + }, + "title": "Cpu Memory Usage Bytes", + "type": "array" + }, + "ephemeral_storage": { + "$ref": "#/components/schemas/StorageMetricsV1", + "description": "The storage usage for the ephemeral storage. For multinode jobs, this is the ephemeral storage usage of the leader unless specified otherwise." + } + }, + "required": [ + "gpu_memory_usage_bytes", + "gpu_utilization", + "cpu_usage", + "cpu_memory_usage_bytes", + "ephemeral_storage" + ], + "title": "TrainingJobMetricsV1", + "type": "object" + }, + "TrainingJobNodeMetricsV1": { + "description": "A set of metrics for a training job node.", + "properties": { + "node_id": { + "description": "The name of the node.", + "title": "Node Id", "type": "string" }, - "allow_patterns": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" + "metrics": { + "$ref": "#/components/schemas/TrainingJobMetricsV1", + "description": "The metrics for the node." + } + }, + "required": [ + "node_id", + "metrics" + ], + "title": "TrainingJobNodeMetricsV1", + "type": "object" + }, + "GetTrainingJobMetricsResponseV1": { + "description": "A response to fetch training job metrics. The outer list for each metric represents that metric across time.", + "properties": { + "gpu_memory_usage_bytes": { + "additionalProperties": { + "items": { + "$ref": "#/components/schemas/TrainingJobMetricV1" + }, + "type": "array" + }, + "description": "A map of GPU rank to memory usage for the training job. For multinode jobs, this is the memory usage of the leader unless specified otherwise.", + "title": "Gpu Memory Usage Bytes", + "type": "object" + }, + "gpu_utilization": { + "additionalProperties": { + "items": { + "$ref": "#/components/schemas/TrainingJobMetricV1" + }, + "type": "array" + }, + "description": "A map of GPU rank to fractional GPU utilization. For multinode jobs, this is the GPU utilization of the leader unless specified otherwise.", + "title": "Gpu Utilization", + "type": "object" + }, + "cpu_usage": { + "description": "The CPU usage measured in cores. For multinode jobs, this is the CPU usage of the leader unless specified otherwise.", + "items": { + "$ref": "#/components/schemas/TrainingJobMetricV1" + }, + "title": "Cpu Usage", + "type": "array" + }, + "cpu_memory_usage_bytes": { + "description": "The CPU memory usage for the training job. For multinode jobs, this is the CPU memory usage of the leader unless specified otherwise.", + "items": { + "$ref": "#/components/schemas/TrainingJobMetricV1" + }, + "title": "Cpu Memory Usage Bytes", + "type": "array" + }, + "ephemeral_storage": { + "$ref": "#/components/schemas/StorageMetricsV1", + "description": "The storage usage for the ephemeral storage. For multinode jobs, this is the ephemeral storage usage of the leader unless specified otherwise." + }, + "training_job": { + "$ref": "#/components/schemas/TrainingJobV1", + "description": "The training job." + }, + "cache": { + "anyOf": [ + { + "$ref": "#/components/schemas/StorageMetricsV1" }, { "type": "null" } ], - "default": null, - "description": "File patterns to include (Unix-style shell patterns)", - "examples": [ - [ - "*.safetensors", - "config.json" - ] - ], - "title": "Allow Patterns" + "description": "The storage usage for the read-write cache." }, - "ignore_patterns": { + "per_node_metrics": { + "description": "The metrics for each node in the training job.", + "items": { + "$ref": "#/components/schemas/TrainingJobNodeMetricsV1" + }, + "title": "Per Node Metrics", + "type": "array" + } + }, + "required": [ + "gpu_memory_usage_bytes", + "gpu_utilization", + "cpu_usage", + "cpu_memory_usage_bytes", + "ephemeral_storage", + "training_job", + "cache", + "per_node_metrics" + ], + "title": "GetTrainingJobMetricsResponseV1", + "type": "object" + }, + "GetTrainingJobMetricsRequestV1": { + "description": "A request to fetch metrics. Allows the user to request metrics over a period of time.", + "properties": { + "end_epoch_millis": { "anyOf": [ { - "items": { - "type": "string" - }, - "type": "array" + "type": "integer" }, { "type": "null" } ], "default": null, - "description": "File patterns to exclude (Unix-style shell patterns)", - "examples": [ - [ - "*.bin", - "*.h5" - ] - ], - "title": "Ignore Patterns" + "description": "Epoch millis timestamp to end fetching metrics", + "title": "End Epoch Millis" }, - "auth_secret_name": { + "start_epoch_millis": { "anyOf": [ { - "type": "string" + "type": "integer" }, { "type": "null" } ], "default": null, - "description": "Name of the workspace secret for authentication (e.g., HuggingFace token)", - "examples": [ - "hf_token", - "aws_credentials" - ], - "title": "Auth Secret Name" + "description": "Epoch millis timestamp to start fetching metrics.", + "title": "Start Epoch Millis" }, - "auth": { + "step_seconds": { "anyOf": [ { - "$ref": "#/components/schemas/TrainingWeightAuthV1" + "type": "integer" }, { "type": "null" } ], "default": null, - "description": "Authentication configuration for the weight source.", - "examples": [ - { - "auth_method": "CUSTOM_SECRET", - "auth_secret_name": "hf_token" - }, - { - "auth_method": "AWS_OIDC", - "aws_oidc_region": "us-east-1", - "aws_oidc_role_arn": "arn:aws:iam::123456789012:role/weights-access" - }, - { - "auth_method": "GCP_OIDC", - "gcp_oidc_service_account": "weights-reader@example.iam.gserviceaccount.com", - "gcp_oidc_workload_id_provider": "projects/123456789/locations/global/workloadIdentityPools/baseten/providers/baseten" - }, - { - "auth_method": "AWS_ASSUME_ROLE", - "aws_assume_role_arn": "arn:aws:iam::123456789012:role/baseten-customer-access", - "aws_assume_role_region": "us-east-1" - } - ] + "description": "Resolution of the returned series, in seconds. When omitted, a step is derived from the time range so large windows return fewer points.", + "title": "Step Seconds" } }, - "required": [ - "source", - "mount_location" - ], - "title": "CreateJobWeightConfigV1", + "title": "GetTrainingJobMetricsRequestV1", "type": "object" }, - "CreateTrainingJobAcceleratorV1": { + "StopTrainingJobRequestV1": { + "description": "A request to stop a training job.", + "properties": {}, + "title": "StopTrainingJobRequestV1", + "type": "object" + }, + "StopTrainingJobResponseV1": { + "description": "A response to stopping a training job.", "properties": { - "accelerator": { - "description": "GPU type for the training job.", - "examples": [ - "H100" - ], - "title": "Accelerator", - "type": "string" - }, - "count": { - "description": "GPUs needed for the training job.", - "examples": [ - 2 - ], - "title": "Count", - "type": "integer" + "training_job": { + "$ref": "#/components/schemas/TrainingJobV1", + "description": "The stopped training job." } }, "required": [ - "accelerator", - "count" + "training_job" ], - "title": "CreateTrainingJobAcceleratorV1", + "title": "StopTrainingJobResponseV1", "type": "object" }, - "CreateTrainingJobCacheConfig": { + "TrainingJobCheckpointV1": { + "description": "A checkpoint for a training job.", "properties": { - "enable_legacy_hf_mount": { - "default": false, - "description": "Whether to enable the legacy Hugging Face cache.", - "examples": [ - true - ], - "title": "Enable Legacy Hf Mount", - "type": "boolean" - }, - "enabled": { - "default": false, - "description": "Whether to enable the read-write cache.", - "examples": [ - true - ], - "title": "Enabled", - "type": "boolean" + "checkpoint_id": { + "description": "The ID of the checkpoint.", + "title": "Checkpoint Id", + "type": "string" }, - "require_cache_affinity": { - "default": true, - "description": "Whether to require region affinity for the read-write cache. If False, the resulting job is not guaranteed to be deployed alongside the previous cache.", - "examples": [ - true, - false - ], - "title": "Require Cache Affinity", - "type": "boolean" + "created_at": { + "description": "The timestamp of the checkpoint in ISO 8601 format.", + "format": "date-time", + "title": "Created At", + "type": "string" }, - "mount_base_path": { - "default": "/root/.cache", - "description": "Mount base path for the cache directory. The project cache and team cache will be mounted under this path.", - "examples": [ - "/workspace/.cache", - "/root/.cache" - ], - "title": "Mount Base Path", + "checkpoint_type": { + "description": "The type of checkpoint.", + "title": "Checkpoint Type", "type": "string" - } - }, - "title": "CreateTrainingJobCacheConfig", - "type": "object" - }, - "CreateTrainingJobCheckpointingConfig": { - "properties": { - "enabled": { - "default": false, - "description": "Whether checkpointing is enabled.", - "examples": [ - true - ], - "title": "Enabled", - "type": "boolean" }, - "checkpoint_path": { + "base_model": { "anyOf": [ { "type": "string" @@ -19861,311 +24167,199 @@ "type": "null" } ], - "default": null, - "description": "path where checkpoints will be saved.", - "examples": [ - "/mnt/ckpts" - ], - "title": "Checkpoint Path" - }, - "volume_size_gib": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null, - "description": "Size of the volume in gibibytes. If not provided, the default size will be used", - "examples": [ - 10 - ], - "title": "Volume Size Gib" - } - }, - "title": "CreateTrainingJobCheckpointingConfig", - "type": "object" - }, - "CreateTrainingJobComputeV1": { - "description": "Configuration to specify the compute for a training job.", - "properties": { - "node_count": { - "default": 1, - "description": "Number of nodes for the training job.", - "examples": [ - 1 - ], - "title": "Node Count", - "type": "integer" - }, - "cpu_count": { - "default": 1, - "description": "Number of cpus for the training job.", - "examples": [ - 1 - ], - "title": "Cpu Count", - "type": "integer" - }, - "memory": { - "default": "2Gi", - "description": "Memory for the training job.", - "examples": [ - "2Gi" - ], - "title": "Memory", - "type": "string" + "description": "The base model of the checkpoint.", + "title": "Base Model" }, - "accelerator": { + "lora_adapter_config": { "anyOf": [ { - "$ref": "#/components/schemas/CreateTrainingJobAcceleratorV1" + "additionalProperties": true, + "type": "object" }, { "type": "null" } ], - "default": null, - "description": "GPU specification for the training job", - "examples": [ - { - "accelerator": "H100", - "count": 2 - } - ] + "description": "The adapter config of the checkpoint.", + "title": "Lora Adapter Config" }, - "availability_model": { - "$ref": "#/components/schemas/V1AvailabilityModel", - "default": "dedicated", - "description": "Capacity guarantee for the job. 'dedicated' (the default) runs on on-demand capacity that is not preempted. 'spot' runs on interruptible capacity that may be preempted; the user is responsible for checkpointing their own progress.", - "examples": [ - "spot" - ] - } - }, - "title": "CreateTrainingJobComputeV1", - "type": "object" - }, - "CreateTrainingJobImageV1": { - "description": "Configuration to create a training job image.", - "properties": { - "base_image": { - "description": "Base image for the training job.", - "examples": [ - "hello-world" - ], - "title": "Base Image", - "type": "string" + "size_bytes": { + "description": "The size of the checkpoint in bytes.", + "title": "Size Bytes", + "type": "integer" }, - "docker_auth": { + "sync_status": { "anyOf": [ { - "$ref": "#/components/schemas/DockerAuthV1" + "type": "string" }, { "type": "null" } ], "default": null, - "description": "Docker authentication credentials" + "description": "Sync state of the checkpoint: SYNCING or COMPLETE.", + "title": "Sync Status" + }, + "training_job_id": { + "description": "The ID of the training job.", + "title": "Training Job Id", + "type": "string" } }, "required": [ - "base_image" + "checkpoint_id", + "created_at", + "checkpoint_type", + "base_model", + "lora_adapter_config", + "size_bytes", + "training_job_id" ], - "title": "CreateTrainingJobImageV1", + "title": "TrainingJobCheckpointV1", "type": "object" }, - "CreateTrainingJobRuntimeV1": { - "description": "Configuration to specify the runtime environment for a training job.", + "GetTrainingJobCheckpointsResponseV1": { + "description": "A response to fetch checkpoints for a training job.", "properties": { - "start_commands": { - "description": "Commands to execute when starting the runtime.", - "examples": [ - [ - "python main.py" - ] - ], + "training_job": { + "$ref": "#/components/schemas/TrainingJobV1", + "description": "The training job." + }, + "checkpoints": { + "description": "The checkpoints for the training job.", "items": { - "type": "string" + "$ref": "#/components/schemas/TrainingJobCheckpointV1" }, - "title": "Start Commands", + "title": "Checkpoints", "type": "array" + } + }, + "required": [ + "training_job", + "checkpoints" + ], + "title": "GetTrainingJobCheckpointsResponseV1", + "type": "object" + }, + "CheckpointFile": { + "properties": { + "url": { + "title": "Url", + "type": "string" }, - "environment_variables": { - "additionalProperties": { - "anyOf": [ - { - "type": "string" - }, - { - "$ref": "#/components/schemas/SecretReferenceV1" - } - ] - }, - "description": "Environment variables to set in the runtime.", - "examples": [ - { - "API_KEY": "your_api_key_here", - "PATH": "/usr/bin" - } - ], - "title": "Environment Variables", - "type": "object" + "relative_file_name": { + "title": "Relative File Name", + "type": "string" }, - "artifacts": { - "description": "Runtime artifacts for the training job.", + "node_rank": { + "title": "Node Rank", + "type": "integer" + }, + "size_bytes": { + "title": "Size Bytes", + "type": "integer" + }, + "last_modified": { + "title": "Last Modified", + "type": "string" + } + }, + "required": [ + "url", + "relative_file_name", + "node_rank", + "size_bytes", + "last_modified" + ], + "title": "CheckpointFile", + "type": "object" + }, + "GetTrainingJobCheckpointFilesResponseV1": { + "description": "A response to fetch presigned URLs for checkpoint files of a training job.", + "properties": { + "presigned_urls": { + "description": "List of presigned URLs for checkpoint files.", "items": { - "$ref": "#/components/schemas/CreateTrainingJobS3Artifact" + "$ref": "#/components/schemas/CheckpointFile" }, - "title": "Artifacts", + "title": "Presigned Urls", "type": "array" }, - "enable_cache": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } - ], - "default": null, - "description": "Deprecated. Use cache_config instead.", - "examples": [ - true - ], - "title": "Enable Cache" - }, - "cache_config": { + "next_page_token": { "anyOf": [ { - "$ref": "#/components/schemas/CreateTrainingJobCacheConfig" + "type": "integer" }, { "type": "null" } ], "default": null, - "description": "Configuration for the read-write cache.", - "examples": [ - { - "enable_legacy_hf_mount": true, - "enabled": true, - "mount_base_path": "/root/.cache", - "require_cache_affinity": true - } - ] - }, - "checkpointing_config": { - "$ref": "#/components/schemas/CreateTrainingJobCheckpointingConfig", - "description": "Configuration for checkpointing.", - "examples": [ - { - "checkpoint_path": "/mnt/ckpts", - "enabled": true, - "volume_size_gib": null - } - ] + "description": "Token to use for fetching the next page of results. None when there are no more results.", + "title": "Next Page Token" }, - "load_checkpoint_config": { - "anyOf": [ - { - "$ref": "#/components/schemas/LoadCheckpointConfig" - }, - { - "type": "null" - } - ], - "default": null, - "description": "Configuration for loading checkpoints" + "total_count": { + "description": "Total number of checkpoint files available.", + "title": "Total Count", + "type": "integer" } }, - "title": "CreateTrainingJobRuntimeV1", + "required": [ + "presigned_urls", + "total_count" + ], + "title": "GetTrainingJobCheckpointFilesResponseV1", "type": "object" }, - "CreateTrainingJobS3Artifact": { + "GetTrainingJobCheckpointFilesRequestV1": { + "description": "Pagination params for ``GET /v1/training_projects/.../checkpoint_files``.", "properties": { - "s3_bucket": { - "description": "S3 bucket for the uploaded runtime artifact.", - "examples": [ - "my-s3-bucket" - ], - "title": "S3 Bucket", - "type": "string" + "page_size": { + "default": 1000, + "description": "Max files per page (default 1000).", + "minimum": 1, + "title": "Page Size", + "type": "integer" }, - "s3_key": { - "description": "S3 key for the uploaded runtime artifact.", - "examples": [ - "my-s3-key" - ], - "title": "S3 Key", - "type": "string" - } - }, - "required": [ - "s3_bucket", - "s3_key" - ], - "title": "CreateTrainingJobS3Artifact", + "page_token": { + "default": 0, + "description": "Offset into the file list (default 0).", + "minimum": 0, + "title": "Page Token", + "type": "integer" + } + }, + "title": "GetTrainingJobCheckpointFilesRequestV1", "type": "object" }, - "CreateTrainingJobV1": { - "description": "Configuration for a training job.", + "AuthCodeV1": { + "description": "Authentication code for a training job interactive session node.", "properties": { - "image": { - "$ref": "#/components/schemas/CreateTrainingJobImageV1", - "examples": [ - { - "base_image": "hello-world", - "docker_auth": null - } - ] + "session_id": { + "description": "Unique identifier of the interactive session.", + "title": "Session Id", + "type": "string" }, - "compute": { - "$ref": "#/components/schemas/CreateTrainingJobComputeV1", - "examples": [ - { - "accelerator": { - "accelerator": "H100", - "count": 2 - }, - "availability_model": "spot", - "cpu_count": 1, - "memory": "2Gi", - "node_count": 1 - } - ] + "replica_id": { + "description": "Replica identifier in gXXrY format (e.g., 'g00r0' for group 0, replica 0).", + "title": "Replica Id", + "type": "string" }, - "runtime": { - "$ref": "#/components/schemas/CreateTrainingJobRuntimeV1", - "description": "Configuration for the runtime environment of the training job.", - "examples": [ - { - "artifacts": [], - "cache_config": null, - "checkpointing_config": { - "checkpoint_path": null, - "enabled": false, - "volume_size_gib": null - }, - "enable_cache": null, - "environment_variables": { - "API_KEY": "your_api_key_here", - "PATH": "/usr/bin" - }, - "load_checkpoint_config": null, - "start_commands": [ - "python main.py" - ] - } - ] + "auth_code": { + "description": "The device authentication code (e.g., '4F64-C0D9').", + "title": "Auth Code", + "type": "string" }, - "name": { + "auth_url": { + "description": "URL where the user should enter the auth code (e.g., 'https://github.com/login/device').", + "title": "Auth Url", + "type": "string" + }, + "generated_at": { "anyOf": [ { + "format": "date-time", "type": "string" }, { @@ -20173,67 +24367,81 @@ } ], "default": null, - "description": "Name of the training job.", - "examples": [ - "gpt-oss-job" - ], - "title": "Name" + "description": "When the auth code was generated, in ISO 8601 format.", + "title": "Generated At" }, - "truss_user_env": { + "tunnel_name": { "anyOf": [ { - "$ref": "#/components/schemas/TrussUserEnv" + "type": "string" }, { "type": "null" } ], "default": null, - "description": "Truss user environment information" + "description": "The name of the tunnel node.", + "title": "Tunnel Name" }, - "interactive_session": { + "expires_at": { "anyOf": [ { - "$ref": "#/components/schemas/InteractiveSessionConfigV1" + "format": "date-time", + "type": "string" }, { "type": "null" } ], "default": null, - "description": "Configuration for interactive debugging sessions." + "description": "When the session expires, in ISO 8601 format.", + "title": "Expires At" }, - "weights": { - "description": "MDN weight sources to mount in the training container. Weights are mirrored and cached for fast startup.", - "examples": [ - [ - { - "allow_patterns": null, - "auth": null, - "auth_secret_name": null, - "ignore_patterns": null, - "mount_location": "/app/models/base", - "source": "hf://meta-llama/Llama-3-8B@main" - } - ] + "working_directory": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } ], + "default": null, + "description": "The working directory of the session.", + "title": "Working Directory" + } + }, + "required": [ + "session_id", + "replica_id", + "auth_code", + "auth_url" + ], + "title": "AuthCodeV1", + "type": "object" + }, + "GetAuthCodesResponseV1": { + "description": "Response containing auth codes for all nodes of a training job's interactive sessions.", + "properties": { + "auth_codes": { + "description": "List of auth codes for each node that has an active interactive session.", "items": { - "$ref": "#/components/schemas/CreateJobWeightConfigV1" + "$ref": "#/components/schemas/AuthCodeV1" }, - "title": "Weights", + "title": "Auth Codes", "type": "array" - }, - "enable_baseten_workdir": { - "default": false, - "description": "When enabled, uses /b10/workspace as the working directory instead of the image WORKDIR.", - "examples": [ - false, - true - ], - "title": "Enable Baseten Workdir", - "type": "boolean" - }, - "priority": { + } + }, + "required": [ + "auth_codes" + ], + "title": "GetAuthCodesResponseV1", + "type": "object" + }, + "PatchInteractiveSessionRequestV1": { + "description": "Request to patch an interactive session.\n\nOnly fields that are provided (non-None) will be applied.", + "properties": { + "timeout_minutes": { "anyOf": [ { "type": "integer" @@ -20243,362 +24451,320 @@ } ], "default": null, - "description": "Queue priority. Higher values are dequeued first. Defaults to 0.", - "examples": [ - 0, - 10, - 100 + "description": "For on_startup sessions, minutes to add to the expiration. For on_demand/on_failure sessions, minutes to add to the timeout. Use -1 for infinite timeout (bumps by 10 years).", + "title": "Timeout Minutes" + }, + "trigger": { + "anyOf": [ + { + "$ref": "#/components/schemas/V1InteractiveSessionTrigger" + }, + { + "type": "null" + } ], - "title": "Priority" + "default": null, + "description": "Update when the interactive session is created. Cannot be changed if the session trigger is 'on_startup'." } }, - "required": [ - "image" - ], - "title": "CreateTrainingJobV1", + "title": "PatchInteractiveSessionRequestV1", "type": "object" }, - "DockerAuthType": { - "enum": [ - "GCP_SERVICE_ACCOUNT_JSON", - "AWS_IAM", - "AWS_OIDC", - "GCP_OIDC", - "REGISTRY_SECRET", - "AWS_ASSUME_ROLE" - ], - "title": "DockerAuthType", - "type": "string" - }, - "DockerAuthV1": { - "description": "Docker authentication credentials.", + "InteractiveSessionV1": { + "description": "Representation of a training job interactive session.", "properties": { - "registry": { - "description": "Registry to authenticate with", - "title": "Registry", + "id": { + "description": "Unique identifier of the interactive session.", + "title": "Id", "type": "string" }, - "auth_method": { - "$ref": "#/components/schemas/DockerAuthType", - "description": "Method to authenticate with the registry", - "examples": [ - "GCP_SERVICE_ACCOUNT_JSON", - "AWS_IAM", - "AWS_OIDC", - "GCP_OIDC", - "REGISTRY_SECRET", - "AWS_ASSUME_ROLE" - ] + "trigger": { + "description": "When the interactive session is created.", + "title": "Trigger", + "type": "string" + }, + "timeout_minutes": { + "description": "Minutes before the session times out.", + "title": "Timeout Minutes", + "type": "integer" + }, + "session_provider": { + "description": "The IDE client for the session.", + "title": "Session Provider", + "type": "string" + }, + "auth_provider": { + "description": "The authentication provider for the session.", + "title": "Auth Provider", + "type": "string" + }, + "pod_name": { + "description": "Pod name / node rank for the session.", + "title": "Pod Name", + "type": "string" + }, + "expires_at": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "When the session expires, in ISO 8601 format.", + "title": "Expires At" }, - "gcp_service_account_json_docker_auth": { + "tunnel_name": { "anyOf": [ { - "$ref": "#/components/schemas/GcpServiceAccountJsonDockerAuthV1" + "type": "string" }, { "type": "null" } ], "default": null, - "description": "GCP service account details for the registry" + "description": "The tunnel name for the session.", + "title": "Tunnel Name" }, - "aws_iam_docker_auth": { + "auth_code": { "anyOf": [ { - "$ref": "#/components/schemas/AwsIamDockerAuthV1" + "type": "string" }, { "type": "null" } ], "default": null, - "description": "AWS details for the registry" + "description": "The device authentication code.", + "title": "Auth Code" }, - "aws_oidc_docker_auth": { + "auth_url": { "anyOf": [ { - "$ref": "#/components/schemas/AwsOidcDockerAuthV1" + "type": "string" }, { "type": "null" } ], "default": null, - "description": "AWS OIDC details for the registry" + "description": "URL where the user should enter the auth code.", + "title": "Auth Url" }, - "gcp_oidc_docker_auth": { + "auth_code_generated_at": { "anyOf": [ { - "$ref": "#/components/schemas/GcpOidcDockerAuthV1" + "format": "date-time", + "type": "string" }, { "type": "null" } ], "default": null, - "description": "GCP OIDC details for the registry" + "description": "When the auth code was generated.", + "title": "Auth Code Generated At" }, - "registry_secret_docker_auth": { + "authenticated_at": { "anyOf": [ { - "$ref": "#/components/schemas/RegistrySecretDockerAuthV1" + "format": "date-time", + "type": "string" }, { "type": "null" } ], "default": null, - "description": "Required when auth_method is REGISTRY_SECRET. Supports any Docker registry (Docker Hub, GHCR, NGC, etc.) via username:password credentials stored as a Baseten secret." + "description": "When the session was authenticated.", + "title": "Authenticated At" }, - "aws_assume_role_docker_auth": { + "working_directory": { "anyOf": [ { - "$ref": "#/components/schemas/AwsAssumeRoleDockerAuthV1" + "type": "string" }, { "type": "null" } ], "default": null, - "description": "Required when auth_method is AWS_ASSUME_ROLE. Baseten assumes the given IAM role with its own AWS principal and your organization's external ID, with no OIDC provider registration in your account." + "description": "The working directory of the session.", + "title": "Working Directory" } }, "required": [ - "registry", - "auth_method" + "id", + "trigger", + "timeout_minutes", + "session_provider", + "auth_provider", + "pod_name" ], - "title": "DockerAuthV1", + "title": "InteractiveSessionV1", "type": "object" }, - "GcpOidcDockerAuthV1": { - "description": "GCP OIDC details for the registry.", + "PatchInteractiveSessionResponseV1": { + "description": "Response after patching an interactive session.", "properties": { - "service_account": { - "description": "GCP service account name for OIDC authentication", - "title": "Service Account", - "type": "string" + "interactive_session": { + "$ref": "#/components/schemas/InteractiveSessionV1", + "description": "The updated interactive session." }, - "workload_identity_provider": { - "description": "GCP workload identity provider for OIDC authentication", - "title": "Workload Identity Provider", + "message": { + "description": "Human-readable summary of what was updated.", + "title": "Message", "type": "string" } }, "required": [ - "service_account", - "workload_identity_provider" - ], - "title": "GcpOidcDockerAuthV1", - "type": "object" - }, - "GcpServiceAccountJsonDockerAuthV1": { - "description": "GCP details for the registry.", - "properties": { - "service_account_json_secret_ref": { - "$ref": "#/components/schemas/SecretReferenceV1", - "description": "Name of the service account secret" - } - }, - "required": [ - "service_account_json_secret_ref" + "interactive_session", + "message" ], - "title": "GcpServiceAccountJsonDockerAuthV1", + "title": "PatchInteractiveSessionResponseV1", "type": "object" }, - "GitInfo": { + "FileSummary": { + "description": "Information about a file in the cache.", "properties": { - "latest_commit_sha": { - "title": "Latest Commit Sha", + "path": { + "description": "Relative path of the file in the cache", + "title": "Path", "type": "string" }, - "latest_tag": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Latest Tag" + "size_bytes": { + "description": "Size of the file in bytes", + "title": "Size Bytes", + "type": "integer" }, - "commits_since_tag": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "title": "Commits Since Tag" + "modified": { + "description": "Last modification time of the file", + "title": "Modified", + "type": "string" }, - "has_uncommitted_changes": { - "title": "Has Uncommitted Changes", - "type": "boolean" + "file_type": { + "description": "Type of the file", + "title": "File Type", + "type": "string" + }, + "permissions": { + "description": "Permissions of the file", + "title": "Permissions", + "type": "string" } }, "required": [ - "latest_commit_sha", - "latest_tag", - "commits_since_tag", - "has_uncommitted_changes" + "path", + "size_bytes", + "modified", + "file_type", + "permissions" ], - "title": "GitInfo", - "type": "object" - }, - "InteractiveSessionConfigV1": { - "description": "Configuration for interactive debugging sessions on training jobs.", - "properties": { - "trigger": { - "$ref": "#/components/schemas/V1InteractiveSessionTrigger", - "default": "on_demand", - "description": "When to create the interactive session. 'on_startup' creates on job start, 'on_failure' creates on job failure, 'on_demand' bypasses automatic session creation." - }, - "timeout_minutes": { - "default": 480, - "description": "Number of minutes before the interactive session times out.", - "examples": [ - 480, - 1440, - 10080 - ], - "title": "Timeout Minutes", - "type": "integer" - }, - "session_provider": { - "$ref": "#/components/schemas/V1InteractiveSessionProvider", - "default": "vs_code", - "description": "The IDE client for the interactive session." - }, - "auth_provider": { - "$ref": "#/components/schemas/V1InteractiveSessionAuthProvider", - "default": "github", - "description": "The authentication provider for the interactive session." - } - }, - "title": "InteractiveSessionConfigV1", + "title": "FileSummary", "type": "object" }, - "LoadCheckpointConfig": { + "GetCacheSummaryResponseV1": { + "description": "Response for getting cache summary.", "properties": { - "enabled": { - "default": false, - "description": "Whether checkpoint loading is enabled", - "title": "Enabled", - "type": "boolean" + "timestamp": { + "description": "Timestamp when the cache summary was captured", + "title": "Timestamp", + "type": "string" }, - "download_folder": { - "default": "/tmp/loaded_checkpoints", - "description": "Folder where checkpoints will be downloaded", - "title": "Download Folder", + "project_id": { + "description": "Project ID associated with the cache", + "title": "Project Id", "type": "string" }, - "checkpoints": { - "description": "List of checkpoint configurations", + "file_summaries": { + "description": "List of files in the cache", "items": { - "discriminator": { - "mapping": { - "baseten_latest_checkpoint": "#/components/schemas/BasetenLatestCheckpointConfig", - "baseten_named_checkpoint": "#/components/schemas/BasetenNamedCheckpointConfig", - "loops_checkpoint": "#/components/schemas/LoopsCheckpointConfig" - }, - "propertyName": "typ" - }, - "oneOf": [ - { - "$ref": "#/components/schemas/BasetenLatestCheckpointConfig" - }, - { - "$ref": "#/components/schemas/BasetenNamedCheckpointConfig" - }, - { - "$ref": "#/components/schemas/LoopsCheckpointConfig" - } - ] + "$ref": "#/components/schemas/FileSummary" }, - "title": "Checkpoints", + "title": "File Summaries", "type": "array" } }, - "title": "LoadCheckpointConfig", + "required": [ + "timestamp", + "project_id", + "file_summaries" + ], + "title": "GetCacheSummaryResponseV1", "type": "object" }, - "LoopsCheckpointConfig": { - "properties": { - "run_id": { - "description": "ID of the Loops run to load the checkpoint from", - "title": "Run Id", - "type": "string" - }, - "checkpoint_name": { - "description": "Name of the checkpoint to load", - "title": "Checkpoint Name", - "type": "string" - }, - "target": { - "default": "trainer", - "description": "Which checkpoint target to load: 'trainer' (full training state) or 'sampler' (inference weights)", - "enum": [ - "trainer", - "sampler" - ], - "title": "Target", + "TrainingProjectTombstoneV1": { + "description": "A training project tombstone.", + "properties": { + "id": { + "description": "Unique identifier of the training project", + "title": "Id", "type": "string" }, - "typ": { - "const": "loops_checkpoint", - "default": "loops_checkpoint", - "title": "Typ", - "type": "string" + "deleted": { + "description": "Whether the training project was deleted", + "title": "Deleted", + "type": "boolean" } }, "required": [ - "run_id", - "checkpoint_name" + "id", + "deleted" ], - "title": "LoopsCheckpointConfig", + "title": "TrainingProjectTombstoneV1", "type": "object" }, - "RegistrySecretDockerAuthV1": { - "description": "Authentication via a Baseten secret for any Docker registry (Docker Hub, GHCR, NGC, etc.).\nThe referenced secret must contain credentials in the format 'username:password'.\nFor Docker Hub, set registry to 'https://index.docker.io/v1/'. For GHCR, use 'ghcr.io'.", + "GetTrainingProjectResponseV1": { + "description": "A response to getting a training project.", "properties": { - "secret_ref": { - "$ref": "#/components/schemas/SecretReferenceV1", - "description": "Reference to a Baseten secret containing credentials in the format 'username:password'" + "training_project": { + "$ref": "#/components/schemas/TrainingProjectV1", + "description": "The training project." } }, "required": [ - "secret_ref" + "training_project" ], - "title": "RegistrySecretDockerAuthV1", + "title": "GetTrainingProjectResponseV1", "type": "object" }, - "SecretReferenceV1": { + "OrderByV1": { + "description": "A request to order training jobs.", "properties": { - "name": { - "description": "Name of the secret to reference.", + "field": { + "description": "The field to order by.", "examples": [ - "hf_token" + "created_at" ], - "title": "Name", + "title": "Field", + "type": "string" + }, + "order": { + "description": "The direction to order by.", + "examples": [ + "asc", + "desc" + ], + "title": "Order", "type": "string" } }, "required": [ - "name" + "field", + "order" ], - "title": "SecretReferenceV1", + "title": "OrderByV1", "type": "object" }, - "TrainingWeightAuthV1": { - "description": "Authentication configuration for a training weight source.", + "SearchTrainingJobsRequestV1": { + "description": "A request to search training jobs.", "properties": { - "auth_method": { - "$ref": "#/components/schemas/AuthMethod", - "description": "Method used to authenticate the weight source." - }, - "auth_secret_name": { + "project_id": { "anyOf": [ { "type": "string" @@ -20608,23 +24774,13 @@ } ], "default": null, - "description": "Name of the workspace secret used for custom-secret authentication.", - "title": "Auth Secret Name" - }, - "aws_oidc_role_arn": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "description": "Filter the training jobs by project ID.", + "examples": [ + "n4q95w5" ], - "default": null, - "description": "AWS IAM role ARN used for OIDC authentication.", - "title": "Aws Oidc Role Arn" + "title": "Project Id" }, - "aws_oidc_region": { + "job_id": { "anyOf": [ { "type": "string" @@ -20634,84 +24790,189 @@ } ], "default": null, - "description": "AWS region used for OIDC authentication.", - "title": "Aws Oidc Region" - }, - "gcp_oidc_service_account": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "description": "Filter the training jobs by job ID.", + "examples": [ + "p7qr9qv" ], - "default": null, - "description": "GCP service account used for OIDC authentication.", - "title": "Gcp Oidc Service Account" + "title": "Job Id" }, - "gcp_oidc_workload_id_provider": { + "statuses": { "anyOf": [ { - "type": "string" + "items": { + "type": "string" + }, + "type": "array" }, { "type": "null" } ], "default": null, - "description": "GCP workload identity provider used for OIDC authentication.", - "title": "Gcp Oidc Workload Id Provider" - }, - "aws_assume_role_arn": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "description": "Filter the training jobs by status.", + "examples": [ + [ + "TRAINING_JOB_RUNNING", + "TRAINING_JOB_COMPLETED" + ] ], - "default": null, - "description": "AWS IAM role ARN that Baseten assumes to access the weight source.", - "title": "Aws Assume Role Arn" + "title": "Statuses" }, - "aws_assume_role_region": { - "anyOf": [ - { - "type": "string" - }, + "order_by": { + "default": [ { - "type": "null" + "field": "created_at", + "order": "desc" } ], - "default": null, - "description": "AWS region used for assume-role authentication.", - "title": "Aws Assume Role Region" + "description": "Order the training jobs by a field. Currently supports created_at", + "items": { + "$ref": "#/components/schemas/OrderByV1" + }, + "title": "Order By", + "type": "array" + } + }, + "title": "SearchTrainingJobsRequestV1", + "type": "object" + }, + "SearchTrainingJobsResponseV1": { + "description": "A response to search training jobs.", + "properties": { + "training_jobs": { + "description": "List of training jobs.", + "items": { + "$ref": "#/components/schemas/TrainingJobV1" + }, + "title": "Training Jobs", + "type": "array" } }, "required": [ - "auth_method" + "training_jobs" ], - "title": "TrainingWeightAuthV1", + "title": "SearchTrainingJobsResponseV1", "type": "object" }, - "TrussUserEnv": { - "description": "This data models is used to flexibly store info alongside oracle versions.\n\nThere is a corresponding data model in the truss client.\nIn contrast, here all fields are optional for backwards compatibility with old\nclients.", + "EnablementDetailsV1": { + "description": "Why a supported model is not enabled for this workspace.", "properties": { - "truss_client_version": { + "reason": { + "description": "Machine-readable reason the model is not enabled. Currently one of 'needs_approval', 'sequence_length_unsupported' or 'loops_not_enabled'. Deliberately not a closed enum: values are added as the check learns to distinguish cases that call for a different action, so treat an unrecognized value as 'not enabled, reason unknown' rather than an error.", + "examples": [ + "needs_approval" + ], + "title": "Reason", + "type": "string" + }, + "reason_detail": { + "description": "Human-readable explanation of the reason.", + "title": "Reason Detail", + "type": "string" + }, + "remediation": { + "description": "Human-readable next step to enable the model.", + "title": "Remediation", + "type": "string" + } + }, + "required": [ + "reason", + "reason_detail", + "remediation" + ], + "title": "EnablementDetailsV1", + "type": "object" + }, + "SupportedModelV1": { + "description": "A model supported by the Loops server.", + "properties": { + "model_name": { + "description": "The name of the supported model.", + "title": "Model Name", + "type": "string" + }, + "max_seq_len": { + "description": "The longest sequence length Baseten supports for this model. Independent of the caller: see 'max_enabled_seq_len' for what this workspace can actually train at. Named to match the 'max_seq_len' query parameter and the field of the same name on run creation, so one name follows the value through the API.", + "title": "Max Seq Len", + "type": "integer" + }, + "max_enabled_seq_len": { + "default": 0, + "description": "The longest sequence length this workspace can train at. Lower than 'max_seq_len' when the longer configurations need hardware the workspace is not approved for \u2014 a model's longer sequence lengths often need a bigger SKU of the same GPU. Zero when the workspace cannot run the model at all, so a client can compare against a required length without a null case.", + "title": "Max Enabled Seq Len", + "type": "integer" + }, + "max_context_length": { + "deprecated": true, + "description": "Deprecated. Use 'max_seq_len', which carries the same value. Kept so existing clients keep working.", + "title": "Max Context Length", + "type": "integer" + }, + "supports_vision_language": { + "description": "Whether the model accepts image inputs alongside text.", + "title": "Supports Vision Language", + "type": "boolean" + }, + "enabled": { + "default": true, + "description": "Whether this workspace can start a run with this model now. False means Baseten supports it but the workspace cannot use it yet; 'not_enabled' says why. Capacity is resolved when the run is created, so true is not a guarantee that GPUs are free.", + "title": "Enabled", + "type": "boolean" + }, + "enablement_details": { "anyOf": [ { - "type": "string" + "$ref": "#/components/schemas/EnablementDetailsV1" }, { "type": "null" } ], "default": null, - "title": "Truss Client Version" - }, - "python_version": { + "description": "Why the model is not enabled, and what would change it. Present only when 'enabled' is false \u2014 an enabled model has nothing to explain. Read 'enabled' for the state; this is the detail behind it." + } + }, + "required": [ + "model_name", + "max_seq_len", + "max_context_length", + "supports_vision_language" + ], + "title": "SupportedModelV1", + "type": "object" + }, + "GetLoopsCapabilitiesResponseV1": { + "description": "Response for ``GET /v1/loops/capabilities``.\n\nA model Baseten does not support has no entry at all, so an empty list for\na single-model request means exactly that.", + "properties": { + "supported_models": { + "description": "Models Baseten supports for this use case, each carrying an 'enabled' flag saying whether this workspace can run it now, and 'enablement_details' when it cannot. Filter on 'enabled' to get the models you can use.", + "items": { + "$ref": "#/components/schemas/SupportedModelV1" + }, + "title": "Supported Models", + "type": "array" + } + }, + "required": [ + "supported_models" + ], + "title": "GetLoopsCapabilitiesResponseV1", + "type": "object" + }, + "LoopsUseCaseV1": { + "description": "What the caller intends to run.\n\nReinforcement learning runs a trainer and a sampler; supervised\nfine-tuning runs a trainer alone. A model can therefore be enabled for one\nand not the other, and the same model can support a longer sequence length\nfor SFT than for RL.", + "enum": [ + "rl", + "sft" + ], + "title": "LoopsUseCaseV1", + "type": "string" + }, + "GetLoopsCapabilitiesQueryParamsV1": { + "description": "Query-string filters for ``GET /v1/loops/capabilities``.", + "properties": { + "model": { "anyOf": [ { "type": "string" @@ -20721,21 +24982,116 @@ } ], "default": null, - "title": "Python Version" + "description": "Restrict the response to one model, identified by its HuggingFace repo id. A supported model comes back with its 'enabled' flag and, when false, its 'enablement_details'. An empty list means Baseten does not support that model. Omit to list every supported model.", + "examples": [ + "Qwen/Qwen3-8B" + ], + "title": "Model" }, - "pydantic_version": { + "use_case": { + "$ref": "#/components/schemas/LoopsUseCaseV1", + "default": "rl", + "description": "What the caller intends to run. Defaults to 'rl', the stricter of the two: an RL run needs both a trainer and a sampler, so anything enabled for 'rl' is also enabled for 'sft'.", + "examples": [ + "rl" + ] + }, + "max_seq_len": { "anyOf": [ { - "type": "string" + "minimum": 1, + "type": "integer" }, { "type": "null" } ], "default": null, - "title": "Pydantic Version" + "description": "The sequence length the caller intends to train at \u2014 the same value they would pass as 'max_seq_len' when creating the run. Models that cannot serve it are reported as not enabled rather than returned with a ceiling the caller cannot use. Omit for the model's highest enabled sequence length.", + "examples": [ + 32768 + ], + "title": "Max Seq Len" + } + }, + "title": "GetLoopsCapabilitiesQueryParamsV1", + "type": "object" + }, + "LoopsSessionV1": { + "properties": { + "id": { + "title": "Id", + "type": "string" + } + }, + "required": [ + "id" + ], + "title": "LoopsSessionV1", + "type": "object" + }, + "CreateLoopsSessionResponseV1": { + "properties": { + "session": { + "$ref": "#/components/schemas/LoopsSessionV1" + } + }, + "required": [ + "session" + ], + "title": "CreateLoopsSessionResponseV1", + "type": "object" + }, + "GetLoopsSessionResponseV1": { + "description": "Response for ``GET /v1/loops/sessions/``.", + "properties": { + "session": { + "$ref": "#/components/schemas/LoopsSessionV1", + "description": "The Loops session." + } + }, + "required": [ + "session" + ], + "title": "GetLoopsSessionResponseV1", + "type": "object" + }, + "LoopsRunStatusNameV1": { + "description": "A Loops run's lifecycle state: ACTIVE or INACTIVE.", + "enum": [ + "ACTIVE", + "INACTIVE" + ], + "title": "LoopsRunStatusNameV1", + "type": "string" + }, + "LoopsRunStatusV1": { + "description": "The current status of a Loops run.", + "properties": { + "name": { + "$ref": "#/components/schemas/LoopsRunStatusNameV1", + "description": "ACTIVE while the run is live; INACTIVE once replaced by a newer run or shut down." + } + }, + "required": [ + "name" + ], + "title": "LoopsRunStatusV1", + "type": "object" + }, + "LoopsRunV1": { + "properties": { + "id": { + "description": "The run ID.", + "title": "Id", + "type": "string" }, - "mypy_version": { + "session_id": { + "description": "The session ID this run belongs to.", + "title": "Session Id", + "type": "string" + }, + "deployment_id": { "anyOf": [ { "type": "string" @@ -20745,224 +25101,250 @@ } ], "default": null, - "title": "Mypy Version" + "description": "The ID of the Loops deployment the run executes on, if it has one.", + "title": "Deployment Id" }, - "is_library_deployment": { - "default": false, - "title": "Is Library Deployment", - "type": "boolean" + "name": { + "description": "The run's display name.", + "title": "Name", + "type": "string" }, - "is_frontend_deployment": { - "default": false, - "title": "Is Frontend Deployment", - "type": "boolean" + "base_model": { + "description": "The HuggingFace base model the run is fine-tuning.", + "title": "Base Model", + "type": "string" }, - "git_info": { + "base_url": { + "description": "The run's base URL.", + "title": "Base Url", + "type": "string" + }, + "created_at": { + "description": "Time the run was created in ISO 8601 format", + "format": "date-time", + "title": "Created At", + "type": "string" + }, + "status": { + "$ref": "#/components/schemas/LoopsRunStatusV1", + "description": "The run's current status." + }, + "user": { + "$ref": "#/components/schemas/UserV1", + "description": "The user who owns the run." + }, + "sampler": { "anyOf": [ { - "$ref": "#/components/schemas/GitInfo" + "$ref": "#/components/schemas/LoopsSamplerV1" }, { "type": "null" } ], - "default": null - } - }, - "title": "TrussUserEnv", - "type": "object" - }, - "V1InteractiveSessionAuthProvider": { - "enum": [ - "github", - "microsoft" - ], - "title": "V1InteractiveSessionAuthProvider", - "type": "string" - }, - "V1InteractiveSessionProvider": { - "enum": [ - "vs_code", - "cursor", - "ssh" - ], - "title": "V1InteractiveSessionProvider", - "type": "string" - }, - "V1InteractiveSessionTrigger": { - "enum": [ - "on_startup", - "on_failure", - "on_demand" - ], - "title": "V1InteractiveSessionTrigger", - "type": "string" - }, - "CreateTrainingJobRequestV1": { - "description": "A request to create a training job.", - "properties": { - "training_job": { - "$ref": "#/components/schemas/CreateTrainingJobV1", - "description": "The training job to create." + "default": null, + "description": "The sampler bound to this run, or null for a trainer-only run that has not yet created a sampler." } }, "required": [ - "training_job" + "id", + "session_id", + "name", + "base_model", + "base_url", + "created_at", + "status", + "user" ], - "title": "CreateTrainingJobRequestV1", + "title": "LoopsRunV1", "type": "object" }, - "CreateTrainingJobResponseV1": { - "description": "A response to creating a training job.", + "LoopsSamplerStatusV1": { + "description": "The current status of a Loops sampler.", "properties": { - "training_job": { - "$ref": "#/components/schemas/TrainingJobV1", - "description": "The created training job." + "name": { + "$ref": "#/components/schemas/DeploymentStatusV1", + "description": "The current status of the Loops sampler." } }, "required": [ - "training_job" + "name" ], - "title": "CreateTrainingJobResponseV1", + "title": "LoopsSamplerStatusV1", "type": "object" }, - "TrainingJobTombstoneV1": { - "description": "A training job tombstone.", + "LoopsSamplerV1": { "properties": { "id": { - "description": "Unique identifier of the training job", "title": "Id", "type": "string" }, - "deleted": { - "description": "Whether the training job was deleted", - "title": "Deleted", - "type": "boolean" + "base_url": { + "title": "Base Url", + "type": "string" }, - "training_project_id": { - "description": "Unique identifier of the training project", - "title": "Training Project Id", + "base_model": { + "description": "The HuggingFace base model the sampler is serving.", + "title": "Base Model", + "type": "string" + }, + "created_at": { + "description": "Time the sampler was created in ISO 8601 format", + "format": "date-time", + "title": "Created At", + "type": "string" + }, + "model_id": { + "description": "Hashid of the underlying Baseten model.", + "title": "Model Id", + "type": "string" + }, + "deployment_id": { + "description": "Hashid of the specific model deployment (version).", + "title": "Deployment Id", "type": "string" + }, + "status": { + "$ref": "#/components/schemas/LoopsSamplerStatusV1", + "description": "The sampler's current status." + }, + "user": { + "$ref": "#/components/schemas/UserV1", + "description": "The user who owns the sampler." + }, + "instance_type": { + "anyOf": [ + { + "$ref": "#/components/schemas/InstanceTypeV1" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Instance type serving the sampler." + }, + "node_count": { + "default": 1, + "description": "Number of nodes serving the sampler.", + "title": "Node Count", + "type": "integer" } }, "required": [ "id", - "deleted", - "training_project_id" + "base_url", + "base_model", + "created_at", + "model_id", + "deployment_id", + "status", + "user" ], - "title": "TrainingJobTombstoneV1", + "title": "LoopsSamplerV1", "type": "object" }, - "GetTrainingJobResponseV1": { - "description": "A response to fetch a training job.", + "ListLoopsRunsResponseV1": { + "description": "Runs matching the query filters.", "properties": { - "training_project": { - "$ref": "#/components/schemas/TrainingProjectV1", - "description": "The training project." - }, - "training_job": { - "$ref": "#/components/schemas/TrainingJobV1", - "description": "The fetched training job." + "runs": { + "description": "List of runs.", + "items": { + "$ref": "#/components/schemas/LoopsRunV1" + }, + "title": "Runs", + "type": "array" } }, "required": [ - "training_project", - "training_job" + "runs" ], - "title": "GetTrainingJobResponseV1", + "title": "ListLoopsRunsResponseV1", "type": "object" }, - "UpdateTrainingJobRequestV1": { - "description": "A request to update mutable fields on a training job.\n\nEvery field is optional so a caller can patch one without the other, but at least\none must be provided: an empty body has nothing to apply.", - "minProperties": 1, + "ListLoopsRunsQueryParamsV1": { + "description": "Query-string filters for ``GET /v1/loops/runs``.\n\nAll filters are optional and can be combined; omit them to list the caller's\nown runs. Pass ``scope=org`` to list every run in the caller's organization\ninstead.", "properties": { - "priority": { + "run_id": { "anyOf": [ { - "type": "integer" + "type": "string" }, { "type": "null" } ], "default": null, - "description": "New queue priority for a PENDING training job. Higher values are dequeued first. Only jobs in the PENDING state can have their priority changed.", + "description": "Filter by run ID.", "examples": [ - 0, - 10, - 100 + "k4q95w5" ], - "title": "Priority" + "title": "Run Id" }, - "availability_model": { + "base_model": { "anyOf": [ { - "$ref": "#/components/schemas/V1AvailabilityModel" + "type": "string" }, { "type": "null" } ], "default": null, - "description": "New capacity guarantee for a PENDING training job. 'dedicated' runs on on-demand capacity that is not preempted. 'spot' runs on interruptible capacity that may be preempted; the user is responsible for checkpointing their own progress. Only jobs in the PENDING state can have their availability model changed.", + "description": "Filter runs by base model name.", "examples": [ - "spot" - ] - } - }, - "title": "UpdateTrainingJobRequestV1", - "type": "object" - }, - "UpdateTrainingJobResponseV1": { - "description": "A response to updating a training job.", - "properties": { - "training_job": { - "$ref": "#/components/schemas/TrainingJobV1", - "description": "The updated training job." - } - }, - "required": [ - "training_job" - ], - "title": "UpdateTrainingJobResponseV1", - "type": "object" - }, - "DownloadTrainingJobResponseV1": { - "description": "A response with presigned URLs for a training job's artifacts.", - "properties": { - "artifact_presigned_urls": { - "description": "Presigned URLs for the job's uploaded artifacts.", - "items": { - "type": "string" - }, - "title": "Artifact Presigned Urls", - "type": "array" - } - }, - "required": [ - "artifact_presigned_urls" - ], - "title": "DownloadTrainingJobResponseV1", - "type": "object" - }, - "RecreateTrainingJobResponseV1": { - "description": "A response that sends the new training job", - "properties": { - "training_job": { - "$ref": "#/components/schemas/TrainingJobV1", - "description": "The created training job." + "Qwen/Qwen3-8B" + ], + "title": "Base Model" + }, + "scope": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Defaults to the caller's own runs; pass 'org' to list every run in the caller's organization.", + "examples": [ + "org" + ], + "title": "Scope" } }, - "required": [ - "training_job" - ], - "title": "RecreateTrainingJobResponseV1", + "title": "ListLoopsRunsQueryParamsV1", "type": "object" }, - "GetTrainingJobLogsRequestV1": { - "description": "A request to fetch training logs.", + "CreateLoopsRunRequestV1": { "properties": { - "start_epoch_millis": { + "session_id": { + "description": "ID of the Loops session this run belongs to.", + "title": "Session Id", + "type": "string" + }, + "base_model": { + "description": "Base model ID (e.g. 'Qwen/Qwen3-8B').", + "title": "Base Model", + "type": "string" + }, + "name": { + "anyOf": [ + { + "maxLength": 255, + "minLength": 1, + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Optional display name for the run. Defaults to the base model name when omitted.", + "title": "Name" + }, + "max_seq_len": { "anyOf": [ { "type": "integer" @@ -20972,10 +25354,17 @@ } ], "default": null, - "description": "Epoch milliseconds at which to start fetching logs. Defaults to 30 minutes before the end. The window from start to end must not exceed 7 days.", - "title": "Start Epoch Millis" + "description": "Maximum prompt length (in tokens) the run must handle. Set this to the longest training example you plan to send. Defaults to the maximum supported by the model configuration.", + "title": "Max Seq Len" }, - "end_epoch_millis": { + "lora_rank": { + "default": 64, + "description": "LoRA rank.", + "minimum": 1, + "title": "Lora Rank", + "type": "integer" + }, + "seed": { "anyOf": [ { "type": "integer" @@ -20985,262 +25374,221 @@ } ], "default": null, - "description": "Epoch milliseconds at which to stop fetching logs. Defaults to the current time.", - "title": "End Epoch Millis" + "description": "Random seed for reproducibility.", + "title": "Seed" }, - "direction": { + "scale_down_delay_seconds": { + "default": 900, + "description": "Seconds of inactivity before the run scales to zero. Must be between 1 and 3600 (1 hour). Defaults to 900 (15 minutes).", + "exclusiveMinimum": 0, + "maximum": 3600, + "title": "Scale Down Delay Seconds", + "type": "integer" + }, + "availability_model": { + "$ref": "#/components/schemas/V1AvailabilityModel", + "default": "dedicated", + "description": "Capacity the trainer runs on. 'dedicated' is not preempted. 'spot' runs below inference and reaches idle reserved capacity, but the run is stopped if its GPUs are reclaimed and cannot be resumed.", + "examples": [ + "spot" + ] + }, + "replicas": { + "default": 1, + "description": "Number of data-parallel trainer replicas. Each replica is one full copy of the model's preset node group, so the trainer deployment runs (preset node_count * replicas) nodes (e.g. replicas=4 on a 4-node preset \u2192 16 nodes, 4 DP workers). Must be a positive integer. Defaults to 1.", + "minimum": 1, + "title": "Replicas", + "type": "integer" + }, + "path": { "anyOf": [ { - "$ref": "#/components/schemas/SortOrderV1" + "type": "string" }, { "type": "null" } ], "default": null, - "description": "Sort order for logs" + "description": "Optional bt:// URI of an existing checkpoint to load weights from on startup. Form: bt://loops:/weights/.", + "examples": [ + "bt://loops:k4q95w5/weights/step-100" + ], + "title": "Path" }, - "limit": { + "reuse_from_run_id": { "anyOf": [ { - "maximum": 1000, - "minimum": 1, - "type": "integer" + "type": "string" }, { "type": "null" } ], - "default": 500, - "description": "Limit of logs to fetch in a single request", - "title": "Limit" + "default": null, + "description": "Optional ID of a prior Loops run whose trainer and/or sampler should be reused for this run instead of provisioning fresh. The prior run must use the same base model and belong to the same team.", + "title": "Reuse From Run Id" }, - "min_level": { + "reuse_from_session_id": { "anyOf": [ { - "$ref": "#/components/schemas/LogLevelV1" + "type": "string" }, { "type": "null" } ], "default": null, - "description": "Minimum log severity to include. Omit to return all log lines, including lines that have no level. Any explicit value returns lines at or above that severity and drops lines without a level." + "description": "Optional ID of a prior Loops session whose trainer and/or sampler should be reused for this run. Deprecated in favor of reuse_from_run_id.", + "title": "Reuse From Session Id" } }, - "title": "GetTrainingJobLogsRequestV1", + "required": [ + "session_id", + "base_model" + ], + "title": "CreateLoopsRunRequestV1", "type": "object" }, - "StorageMetricsV1": { - "description": "A metric for a training job.", - "properties": { - "usage_bytes": { - "description": "The number of bytes used on the storage entity.", - "items": { - "$ref": "#/components/schemas/TrainingJobMetricV1" - }, - "title": "Usage Bytes", - "type": "array" - }, - "utilization": { - "description": "The utilization of the storage entity as a decimal percentage.", - "items": { - "$ref": "#/components/schemas/TrainingJobMetricV1" - }, - "title": "Utilization", - "type": "array" + "CreateLoopsRunResponseV1": { + "properties": { + "run": { + "$ref": "#/components/schemas/LoopsRunV1" } }, "required": [ - "usage_bytes", - "utilization" + "run" ], - "title": "StorageMetricsV1", + "title": "CreateLoopsRunResponseV1", "type": "object" }, - "TrainingJobMetricV1": { - "description": "A metric for a training job.", + "DeactivateLoopsRunResponseV1": { + "description": "Response for ``POST /v1/loops/runs//deactivate``.", "properties": { - "value": { - "description": "The value of the metric.", - "title": "Value", - "type": "number" + "id": { + "description": "The deactivated Loops run ID.", + "title": "Id", + "type": "string" }, - "timestamp": { - "description": "The timestamp of the metric in ISO 8601 format.", - "format": "date-time", - "title": "Timestamp", + "base_model": { + "description": "The base model whose Loops run was deactivated.", + "title": "Base Model", "type": "string" + }, + "user": { + "$ref": "#/components/schemas/UserV1", + "description": "The user who owns the Loops run." } }, "required": [ - "value", - "timestamp" + "id", + "base_model", + "user" ], - "title": "TrainingJobMetricV1", + "title": "DeactivateLoopsRunResponseV1", "type": "object" }, - "TrainingJobMetricsV1": { + "GetLoopsRunResponseV1": { + "description": "Response for ``GET /v1/loops/runs/``.", "properties": { - "gpu_memory_usage_bytes": { - "additionalProperties": { - "items": { - "$ref": "#/components/schemas/TrainingJobMetricV1" - }, - "type": "array" - }, - "description": "A map of GPU rank to memory usage for the training job. For multinode jobs, this is the memory usage of the leader unless specified otherwise.", - "title": "Gpu Memory Usage Bytes", - "type": "object" - }, - "gpu_utilization": { - "additionalProperties": { - "items": { - "$ref": "#/components/schemas/TrainingJobMetricV1" - }, - "type": "array" - }, - "description": "A map of GPU rank to fractional GPU utilization. For multinode jobs, this is the GPU utilization of the leader unless specified otherwise.", - "title": "Gpu Utilization", - "type": "object" - }, - "cpu_usage": { - "description": "The CPU usage measured in cores. For multinode jobs, this is the CPU usage of the leader unless specified otherwise.", - "items": { - "$ref": "#/components/schemas/TrainingJobMetricV1" - }, - "title": "Cpu Usage", - "type": "array" - }, - "cpu_memory_usage_bytes": { - "description": "The CPU memory usage for the training job. For multinode jobs, this is the CPU memory usage of the leader unless specified otherwise.", - "items": { - "$ref": "#/components/schemas/TrainingJobMetricV1" - }, - "title": "Cpu Memory Usage Bytes", - "type": "array" - }, - "ephemeral_storage": { - "$ref": "#/components/schemas/StorageMetricsV1", - "description": "The storage usage for the ephemeral storage. For multinode jobs, this is the ephemeral storage usage of the leader unless specified otherwise." + "run": { + "$ref": "#/components/schemas/LoopsRunV1", + "description": "The Loops run with its associated sampler." } }, "required": [ - "gpu_memory_usage_bytes", - "gpu_utilization", - "cpu_usage", - "cpu_memory_usage_bytes", - "ephemeral_storage" + "run" ], - "title": "TrainingJobMetricsV1", + "title": "GetLoopsRunResponseV1", "type": "object" }, - "TrainingJobNodeMetricsV1": { - "description": "A set of metrics for a training job node.", + "ListLoopsSamplersResponseV1": { + "description": "Response for ``GET /v1/loops/samplers``.\n\nReturns the caller's samplers, including those paired to runs and\nstandalone samplers. Ordered newest-first.", "properties": { - "node_id": { - "description": "The name of the node.", - "title": "Node Id", - "type": "string" - }, - "metrics": { - "$ref": "#/components/schemas/TrainingJobMetricsV1", - "description": "The metrics for the node." + "samplers": { + "description": "List of samplers.", + "items": { + "$ref": "#/components/schemas/LoopsSamplerV1" + }, + "title": "Samplers", + "type": "array" } }, "required": [ - "node_id", - "metrics" + "samplers" ], - "title": "TrainingJobNodeMetricsV1", + "title": "ListLoopsSamplersResponseV1", "type": "object" }, - "GetTrainingJobMetricsResponseV1": { - "description": "A response to fetch training job metrics. The outer list for each metric represents that metric across time.", + "ListLoopsSamplersRequestV1": { + "description": "Query-string filters for the Loops sampler listing routes.", "properties": { - "gpu_memory_usage_bytes": { - "additionalProperties": { - "items": { - "$ref": "#/components/schemas/TrainingJobMetricV1" + "scope": { + "anyOf": [ + { + "type": "string" }, - "type": "array" - }, - "description": "A map of GPU rank to memory usage for the training job. For multinode jobs, this is the memory usage of the leader unless specified otherwise.", - "title": "Gpu Memory Usage Bytes", - "type": "object" - }, - "gpu_utilization": { - "additionalProperties": { - "items": { - "$ref": "#/components/schemas/TrainingJobMetricV1" + { + "type": "null" + } + ], + "default": null, + "description": "Defaults to the caller's own samplers; pass 'org' to include samplers owned by other users in the caller's organization.", + "examples": [ + "org" + ], + "title": "Scope" + } + }, + "title": "ListLoopsSamplersRequestV1", + "type": "object" + }, + "CreateLoopsSamplerRequestV1": { + "properties": { + "availability_model": { + "anyOf": [ + { + "$ref": "#/components/schemas/V1AvailabilityModel" }, - "type": "array" - }, - "description": "A map of GPU rank to fractional GPU utilization. For multinode jobs, this is the GPU utilization of the leader unless specified otherwise.", - "title": "Gpu Utilization", - "type": "object" - }, - "cpu_usage": { - "description": "The CPU usage measured in cores. For multinode jobs, this is the CPU usage of the leader unless specified otherwise.", - "items": { - "$ref": "#/components/schemas/TrainingJobMetricV1" - }, - "title": "Cpu Usage", - "type": "array" - }, - "cpu_memory_usage_bytes": { - "description": "The CPU memory usage for the training job. For multinode jobs, this is the CPU memory usage of the leader unless specified otherwise.", - "items": { - "$ref": "#/components/schemas/TrainingJobMetricV1" - }, - "title": "Cpu Memory Usage Bytes", - "type": "array" + { + "type": "null" + } + ], + "default": null, + "description": "Capacity the sampler runs on. 'spot' allows preemption when its GPUs are reclaimed. Defaults to 'dedicated' for standalone samplers. Paired samplers inherit their run's availability model; an explicit value must match it." }, - "ephemeral_storage": { - "$ref": "#/components/schemas/StorageMetricsV1", - "description": "The storage usage for the ephemeral storage. For multinode jobs, this is the ephemeral storage usage of the leader unless specified otherwise." + "session_id": { + "description": "ID of the Loops session this sampler belongs to.", + "title": "Session Id", + "type": "string" }, - "training_job": { - "$ref": "#/components/schemas/TrainingJobV1", - "description": "The training job." + "base_model": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Base model ID for a standalone sampler (for example, a baseline).", + "title": "Base Model" }, - "cache": { + "run_id": { "anyOf": [ { - "$ref": "#/components/schemas/StorageMetricsV1" + "type": "string" }, { "type": "null" } ], - "description": "The storage usage for the read-write cache." + "default": null, + "description": "ID of an existing run to attach this sampler to. When set, the sampler is paired to the run and weight-syncs from its trainer, and base_model is inherited from the run. Omit to create a standalone sampler.", + "title": "Run Id" }, - "per_node_metrics": { - "description": "The metrics for each node in the training job.", - "items": { - "$ref": "#/components/schemas/TrainingJobNodeMetricsV1" - }, - "title": "Per Node Metrics", - "type": "array" - } - }, - "required": [ - "gpu_memory_usage_bytes", - "gpu_utilization", - "cpu_usage", - "cpu_memory_usage_bytes", - "ephemeral_storage", - "training_job", - "cache", - "per_node_metrics" - ], - "title": "GetTrainingJobMetricsResponseV1", - "type": "object" - }, - "GetTrainingJobMetricsRequestV1": { - "description": "A request to fetch metrics. Allows the user to request metrics over a period of time.", - "properties": { - "end_epoch_millis": { + "max_seq_length": { "anyOf": [ { "type": "integer" @@ -21250,61 +25598,73 @@ } ], "default": null, - "description": "Epoch millis timestamp to end fetching metrics", - "title": "End Epoch Millis" + "description": "Maximum prompt length (in tokens) the sampler must handle. Set this to the longest prompt you plan to send.", + "title": "Max Seq Length" }, - "start_epoch_millis": { + "model_path": { "anyOf": [ { - "type": "integer" + "type": "string" }, { "type": "null" } ], - "default": null, - "description": "Epoch millis timestamp to start fetching metrics.", - "title": "Start Epoch Millis" + "default": null, + "description": "bt:// URI of an existing sampler checkpoint to serve. Form: bt://loops:/sampler_weights/.", + "examples": [ + "bt://loops:k4q95w5/sampler_weights/step-100" + ], + "title": "Model Path" }, - "step_seconds": { + "reuse_from_session_id": { "anyOf": [ { - "type": "integer" + "type": "string" }, { "type": "null" } ], "default": null, - "description": "Resolution of the returned series, in seconds. When omitted, a step is derived from the time range so large windows return fewer points.", - "title": "Step Seconds" + "description": "Optional ID of a prior Loops session to reuse a trainer and/or sampler from. Deprecated.", + "title": "Reuse From Session Id" } }, - "title": "GetTrainingJobMetricsRequestV1", + "required": [ + "session_id" + ], + "title": "CreateLoopsSamplerRequestV1", "type": "object" }, - "StopTrainingJobRequestV1": { - "description": "A request to stop a training job.", - "properties": {}, - "title": "StopTrainingJobRequestV1", + "CreateLoopsSamplerResponseV1": { + "properties": { + "sampler": { + "$ref": "#/components/schemas/LoopsSamplerV1" + } + }, + "required": [ + "sampler" + ], + "title": "CreateLoopsSamplerResponseV1", "type": "object" }, - "StopTrainingJobResponseV1": { - "description": "A response to stopping a training job.", + "GetLoopsSamplerResponseV1": { + "description": "Response for ``GET /v1/loops/samplers/``.", "properties": { - "training_job": { - "$ref": "#/components/schemas/TrainingJobV1", - "description": "The stopped training job." + "sampler": { + "$ref": "#/components/schemas/LoopsSamplerV1", + "description": "The Loops sampler." } }, "required": [ - "training_job" + "sampler" ], - "title": "StopTrainingJobResponseV1", + "title": "GetLoopsSamplerResponseV1", "type": "object" }, - "TrainingJobCheckpointV1": { - "description": "A checkpoint for a training job.", + "LoopsCheckpointV1": { + "description": "A checkpoint saved by a Loops run.", "properties": { "checkpoint_id": { "description": "The ID of the checkpoint.", @@ -21365,10 +25725,19 @@ "description": "Sync state of the checkpoint: SYNCING or COMPLETE.", "title": "Sync Status" }, - "training_job_id": { - "description": "The ID of the training job.", - "title": "Training Job Id", + "id": { + "description": "The checkpoint ID.", + "title": "Id", + "type": "string" + }, + "run_id": { + "description": "The ID of the run that produced the checkpoint.", + "title": "Run Id", "type": "string" + }, + "target": { + "$ref": "#/components/schemas/TrainerCheckpointTarget", + "description": "Whether this checkpoint is loadable by the sampler or by the run." } }, "required": [ @@ -21378,69 +25747,121 @@ "base_model", "lora_adapter_config", "size_bytes", - "training_job_id" + "id", + "run_id", + "target" ], - "title": "TrainingJobCheckpointV1", + "title": "LoopsCheckpointV1", "type": "object" }, - "GetTrainingJobCheckpointsResponseV1": { - "description": "A response to fetch checkpoints for a training job.", + "TrainerCheckpointTarget": { + "description": "Whether a TrainerServerCheckpoint is loadable by the sampler or the trainer.\n\nSAMPLER checkpoints are consumed by the sampling server for inference;\nTRAINER checkpoints capture full trainer state for resuming training.\nMirrored in the bt:// URI as\n``bt://loops:/(sampler_weights|weights)/``.", + "enum": [ + "sampler", + "trainer" + ], + "title": "TrainerCheckpointTarget", + "type": "string" + }, + "ListLoopsCheckpointsResponseV1": { + "description": "Checkpoints matching the query filter.", "properties": { - "training_job": { - "$ref": "#/components/schemas/TrainingJobV1", - "description": "The training job." - }, "checkpoints": { - "description": "The checkpoints for the training job.", + "description": "Matching checkpoints.", "items": { - "$ref": "#/components/schemas/TrainingJobCheckpointV1" + "$ref": "#/components/schemas/LoopsCheckpointV1" }, "title": "Checkpoints", "type": "array" } }, "required": [ - "training_job", "checkpoints" ], - "title": "GetTrainingJobCheckpointsResponseV1", + "title": "ListLoopsCheckpointsResponseV1", "type": "object" }, - "CheckpointFile": { + "ListLoopsCheckpointsQueryParamsV1": { + "description": "Query-string filters for ``GET /v1/loops/checkpoints``.\n\nProvide exactly one of ``run_id`` (all checkpoints for the run),\n``base_model`` (all checkpoints across the caller's runs of that\nbase model), or ``checkpoint_path`` (the single matching checkpoint).", "properties": { - "url": { - "title": "Url", - "type": "string" - }, - "relative_file_name": { - "title": "Relative File Name", - "type": "string" - }, - "node_rank": { - "title": "Node Rank", - "type": "integer" + "run_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Filter by run ID. Returns all checkpoints saved by the run.", + "examples": [ + "k4q95w5" + ], + "title": "Run Id" }, - "size_bytes": { - "title": "Size Bytes", - "type": "integer" + "base_model": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Filter by base model. Returns checkpoints across the caller's runs of this base model.", + "examples": [ + "Qwen/Qwen3-8B" + ], + "title": "Base Model" }, - "last_modified": { - "title": "Last Modified", + "checkpoint_path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "bt:// URI of a Loops checkpoint. Form: bt://loops:/(weights|sampler_weights)/.", + "examples": [ + "bt://loops:k4q95w5/sampler_weights/step-100" + ], + "title": "Checkpoint Path" + } + }, + "title": "ListLoopsCheckpointsQueryParamsV1", + "type": "object" + }, + "ValidateLoopsCheckpointRequestV1": { + "description": "Request body for ``POST /v1/loops/checkpoints/validate``.", + "properties": { + "checkpoint_path": { + "description": "bt:// URI of a sampler checkpoint. Form: bt://loops:/sampler_weights/.", + "examples": [ + "bt://loops:k4q95w5/sampler_weights/step-100" + ], + "title": "Checkpoint Path", "type": "string" } }, "required": [ - "url", - "relative_file_name", - "node_rank", - "size_bytes", - "last_modified" + "checkpoint_path" ], - "title": "CheckpointFile", + "title": "ValidateLoopsCheckpointRequestV1", "type": "object" }, - "GetTrainingJobCheckpointFilesResponseV1": { - "description": "A response to fetch presigned URLs for checkpoint files of a training job.", + "ValidateLoopsCheckpointResponseV1": { + "description": "Response for ``POST /v1/loops/checkpoints/validate``. Empty on success;\ninaccessible or malformed paths raise 400.", + "properties": {}, + "title": "ValidateLoopsCheckpointResponseV1", + "type": "object" + }, + "LoopsCheckpointFilesResponseV1": { + "description": "Response with presigned URLs for files under a Loops checkpoint.", "properties": { "presigned_urls": { "description": "List of presigned URLs for checkpoint files.", @@ -21473,11 +25894,11 @@ "presigned_urls", "total_count" ], - "title": "GetTrainingJobCheckpointFilesResponseV1", + "title": "LoopsCheckpointFilesResponseV1", "type": "object" }, - "GetTrainingJobCheckpointFilesRequestV1": { - "description": "Pagination params for ``GET /v1/training_projects/.../checkpoint_files``.", + "GetLoopsCheckpointFilesRequestV1": { + "description": "Pagination params for ``GET /v1/loops/checkpoints//files``.", "properties": { "page_size": { "default": 1000, @@ -21494,36 +25915,103 @@ "type": "integer" } }, - "title": "GetTrainingJobCheckpointFilesRequestV1", + "title": "GetLoopsCheckpointFilesRequestV1", + "type": "object" + }, + "LoopsCheckpointS3SourceV1": { + "description": "The checkpoint's files are fetched as presigned URLs, page by page.", + "properties": { + "kind": { + "const": "s3", + "default": "s3", + "title": "Kind", + "type": "string" + } + }, + "title": "LoopsCheckpointS3SourceV1", + "type": "object" + }, + "LoopsCheckpointVolumeSourceV1": { + "description": "The checkpoint's files are pulled from a Baseten volume.", + "properties": { + "kind": { + "const": "volume", + "default": "volume", + "title": "Kind", + "type": "string" + }, + "volume_ref": { + "description": "Ref of the volume version holding the checkpoint, as `bdn:/:`.", + "title": "Volume Ref", + "type": "string" + }, + "path": { + "description": "Directory inside that version holding the checkpoint's files.", + "title": "Path", + "type": "string" + } + }, + "required": [ + "volume_ref", + "path" + ], + "title": "LoopsCheckpointVolumeSourceV1", + "type": "object" + }, + "LoopsCheckpointSourceResponseV1": { + "description": "Where a checkpoint's files are fetched from, and how.", + "properties": { + "source": { + "description": "`s3` means the files endpoint serves presigned URLs for this checkpoint; `volume` carries the ref to pull instead.", + "discriminator": { + "mapping": { + "s3": "#/components/schemas/LoopsCheckpointS3SourceV1", + "volume": "#/components/schemas/LoopsCheckpointVolumeSourceV1" + }, + "propertyName": "kind" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/LoopsCheckpointS3SourceV1" + }, + { + "$ref": "#/components/schemas/LoopsCheckpointVolumeSourceV1" + } + ], + "title": "Source" + } + }, + "required": [ + "source" + ], + "title": "LoopsCheckpointSourceResponseV1", + "type": "object" + }, + "LoopsDeploymentStatusV1": { + "description": "Latest deployment status for a Loops deployment.", + "properties": { + "name": { + "$ref": "#/components/schemas/Name", + "description": "Latest status of the Loops deployment." + } + }, + "required": [ + "name" + ], + "title": "LoopsDeploymentStatusV1", "type": "object" }, - "AuthCodeV1": { - "description": "Authentication code for a training job interactive session node.", + "LoopsDeploymentV1": { + "description": "A Loops deployment \u2014 the long-lived run + sampler pair owned by a user.\n\nThe deployment's current sampler is included inline. The full list of\nsamplers visible to the caller (across all deployments) lives at\n``GET /v1/loops/samplers``.", "properties": { - "session_id": { - "description": "Unique identifier of the interactive session.", - "title": "Session Id", - "type": "string" - }, - "replica_id": { - "description": "Replica identifier in gXXrY format (e.g., 'g00r0' for group 0, replica 0).", - "title": "Replica Id", - "type": "string" - }, - "auth_code": { - "description": "The device authentication code (e.g., '4F64-C0D9').", - "title": "Auth Code", - "type": "string" - }, - "auth_url": { - "description": "URL where the user should enter the auth code (e.g., 'https://github.com/login/device').", - "title": "Auth Url", + "id": { + "description": "The Loops deployment ID.", + "title": "Id", "type": "string" }, - "generated_at": { + "active_run_id": { "anyOf": [ { - "format": "date-time", "type": "string" }, { @@ -21531,10 +26019,10 @@ } ], "default": null, - "description": "When the auth code was generated, in ISO 8601 format.", - "title": "Generated At" + "description": "The ID of the run currently active on this deployment, if any. Null when the deployment's runs have been marked inactive (e.g. scale-to-zero) without a successor.", + "title": "Active Run Id" }, - "tunnel_name": { + "latest_run_id": { "anyOf": [ { "type": "string" @@ -21544,144 +26032,178 @@ } ], "default": null, - "description": "The name of the tunnel node.", - "title": "Tunnel Name" + "description": "The ID of the most recent run on this deployment, active or not, so idle deployments still expose a usable run handle. Null only if the deployment has no runs.", + "title": "Latest Run Id" }, - "expires_at": { - "anyOf": [ - { - "format": "date-time", - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "description": "When the session expires, in ISO 8601 format.", - "title": "Expires At" + "base_model": { + "description": "The HuggingFace base model the deployment is fine-tuning.", + "title": "Base Model", + "type": "string" }, - "working_directory": { + "base_url": { + "description": "The run's base URL.", + "title": "Base Url", + "type": "string" + }, + "status": { + "$ref": "#/components/schemas/LoopsDeploymentStatusV1", + "description": "Latest deployment status." + }, + "user": { + "$ref": "#/components/schemas/UserV1", + "description": "The user who owns the Loops deployment." + }, + "created_at": { + "description": "Time the deployment was created in ISO 8601 format.", + "format": "date-time", + "title": "Created At", + "type": "string" + }, + "availability_model": { + "$ref": "#/components/schemas/V1AvailabilityModel", + "default": "dedicated", + "description": "Capacity the trainer was scheduled on." + }, + "instance_type": { + "$ref": "#/components/schemas/InstanceTypeV1", + "description": "Instance type backing the trainer." + }, + "node_count": { + "default": 1, + "description": "Number of nodes backing the trainer.", + "title": "Node Count", + "type": "integer" + }, + "sampler": { "anyOf": [ { - "type": "string" + "$ref": "#/components/schemas/LoopsSamplerV1" }, { "type": "null" } ], "default": null, - "description": "The working directory of the session.", - "title": "Working Directory" + "description": "The sampler bound to this deployment." } }, "required": [ - "session_id", - "replica_id", - "auth_code", - "auth_url" + "id", + "base_model", + "base_url", + "status", + "user", + "created_at", + "instance_type" ], - "title": "AuthCodeV1", + "title": "LoopsDeploymentV1", "type": "object" }, - "GetAuthCodesResponseV1": { - "description": "Response containing auth codes for all nodes of a training job's interactive sessions.", + "Name": { + "enum": [ + "CREATED", + "DEPLOYING", + "RUNNING", + "SCALED_TO_ZERO", + "FAILED", + "STOPPED", + "PREEMPTED" + ], + "title": "LoopsDeploymentStatus", + "type": "string" + }, + "ListLoopsDeploymentsResponseV1": { + "description": "Response for ``GET /v1/loops/deployments``.\n\nDefaults to the caller's own; pass ``?scope=org`` to list every deployment in\nthe caller's organization. Returns every deployment regardless of status;\nclients filter terminal states.", "properties": { - "auth_codes": { - "description": "List of auth codes for each node that has an active interactive session.", + "deployments": { + "description": "Active Loops deployments.", "items": { - "$ref": "#/components/schemas/AuthCodeV1" + "$ref": "#/components/schemas/LoopsDeploymentV1" }, - "title": "Auth Codes", + "title": "Deployments", "type": "array" } }, "required": [ - "auth_codes" + "deployments" ], - "title": "GetAuthCodesResponseV1", + "title": "ListLoopsDeploymentsResponseV1", "type": "object" }, - "PatchInteractiveSessionRequestV1": { - "description": "Request to patch an interactive session.\n\nOnly fields that are provided (non-None) will be applied.", + "ListLoopsDeploymentsRequestV1": { + "description": "Query-string filters for ``GET /v1/loops/deployments``.", "properties": { - "timeout_minutes": { + "scope": { "anyOf": [ { - "type": "integer" + "type": "string" }, { "type": "null" } ], "default": null, - "description": "For on_startup sessions, minutes to add to the expiration. For on_demand/on_failure sessions, minutes to add to the timeout. Use -1 for infinite timeout (bumps by 10 years).", - "title": "Timeout Minutes" - }, - "trigger": { - "anyOf": [ - { - "$ref": "#/components/schemas/V1InteractiveSessionTrigger" - }, - { - "type": "null" - } + "description": "Defaults to the caller's own deployments; pass 'org' to list every deployment in the caller's organization.", + "examples": [ + "org" ], - "default": null, - "description": "Update when the interactive session is created. Cannot be changed if the session trigger is 'on_startup'." + "title": "Scope" } }, - "title": "PatchInteractiveSessionRequestV1", + "title": "ListLoopsDeploymentsRequestV1", "type": "object" }, - "InteractiveSessionV1": { - "description": "Representation of a training job interactive session.", + "DeactivateLoopsDeploymentResponseV1": { + "description": "Response for ``POST /v1/loops/deployments//deactivate``.", "properties": { "id": { - "description": "Unique identifier of the interactive session.", + "description": "The deactivated Loops deployment ID.", "title": "Id", "type": "string" }, - "trigger": { - "description": "When the interactive session is created.", - "title": "Trigger", - "type": "string" - }, - "timeout_minutes": { - "description": "Minutes before the session times out.", - "title": "Timeout Minutes", - "type": "integer" - }, - "session_provider": { - "description": "The IDE client for the session.", - "title": "Session Provider", - "type": "string" - }, - "auth_provider": { - "description": "The authentication provider for the session.", - "title": "Auth Provider", - "type": "string" - }, - "pod_name": { - "description": "Pod name / node rank for the session.", - "title": "Pod Name", + "base_model": { + "description": "The base model whose Loops deployment was deactivated.", + "title": "Base Model", "type": "string" }, - "expires_at": { - "anyOf": [ - { - "format": "date-time", - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "description": "When the session expires, in ISO 8601 format.", - "title": "Expires At" + "user": { + "$ref": "#/components/schemas/UserV1", + "description": "The user who owned the Loops deployment." + } + }, + "required": [ + "id", + "base_model", + "user" + ], + "title": "DeactivateLoopsDeploymentResponseV1", + "type": "object" + }, + "GetLoopsDeploymentResponseV1": { + "description": "Response for ``GET /v1/loops/deployments/``.", + "properties": { + "deployment": { + "$ref": "#/components/schemas/LoopsDeploymentV1", + "description": "The Loops deployment." + } + }, + "required": [ + "deployment" + ], + "title": "GetLoopsDeploymentResponseV1", + "type": "object" + }, + "LoopsDebugArchiveFilesResponseV1": { + "description": "Response with presigned URLs for a Loops deployment's debug archive.", + "properties": { + "presigned_urls": { + "items": { + "$ref": "#/components/schemas/CheckpointFile" + }, + "title": "Presigned Urls", + "type": "array" }, - "tunnel_name": { + "next_page_token": { "anyOf": [ { "type": "string" @@ -21690,11 +26212,28 @@ "type": "null" } ], - "default": null, - "description": "The tunnel name for the session.", - "title": "Tunnel Name" + "default": null, + "title": "Next Page Token" + } + }, + "required": [ + "presigned_urls" + ], + "title": "LoopsDebugArchiveFilesResponseV1", + "type": "object" + }, + "GetLoopsDebugArchiveFilesRequestV1": { + "description": "Pagination params for a Loops deployment debug archive.", + "properties": { + "page_size": { + "default": 1000, + "description": "Max files per page (default and maximum 1000).", + "maximum": 1000, + "minimum": 1, + "title": "Page Size", + "type": "integer" }, - "auth_code": { + "page_token": { "anyOf": [ { "type": "string" @@ -21704,440 +26243,599 @@ } ], "default": null, - "description": "The device authentication code.", - "title": "Auth Code" - }, - "auth_url": { + "description": "Opaque token for the next page.", + "title": "Page Token" + } + }, + "title": "GetLoopsDebugArchiveFilesRequestV1", + "type": "object" + }, + "GetLoopsDeploymentMetricsRequestV1": { + "description": "Time-range request for trainer deployment metrics.", + "properties": { + "end_epoch_millis": { "anyOf": [ { - "type": "string" + "type": "integer" }, { "type": "null" } ], "default": null, - "description": "URL where the user should enter the auth code.", - "title": "Auth Url" + "description": "Epoch millis to end fetching metrics.", + "title": "End Epoch Millis" }, - "auth_code_generated_at": { + "start_epoch_millis": { "anyOf": [ { - "format": "date-time", - "type": "string" + "type": "integer" }, { "type": "null" } ], "default": null, - "description": "When the auth code was generated.", - "title": "Auth Code Generated At" + "description": "Epoch millis to start fetching metrics.", + "title": "Start Epoch Millis" }, - "authenticated_at": { + "step_seconds": { "anyOf": [ { - "format": "date-time", - "type": "string" + "type": "integer" }, { "type": "null" } ], "default": null, - "description": "When the session was authenticated.", - "title": "Authenticated At" + "description": "Resolution of the returned series, in seconds. When omitted, a step is derived from the time range so large windows return fewer points.", + "title": "Step Seconds" }, - "working_directory": { + "time_divisor_seconds": { "anyOf": [ { - "type": "string" + "type": "integer" }, { "type": "null" } ], "default": null, - "description": "The working directory of the session.", - "title": "Working Directory" + "description": "Unit of time for request-volume metrics, in seconds (e.g. 60 for requests/minute). Defaults to per-second.", + "title": "Time Divisor Seconds" } }, - "required": [ - "id", - "trigger", - "timeout_minutes", - "session_provider", - "auth_provider", - "pod_name" - ], - "title": "InteractiveSessionV1", + "title": "GetLoopsDeploymentMetricsRequestV1", "type": "object" }, - "PatchInteractiveSessionResponseV1": { - "description": "Response after patching an interactive session.", + "InferenceVolumeByStatusDatapointV1": { + "description": "Request rate split by HTTP response code class.", "properties": { - "interactive_session": { - "$ref": "#/components/schemas/InteractiveSessionV1", - "description": "The updated interactive session." - }, - "message": { - "description": "Human-readable summary of what was updated.", - "title": "Message", + "timestamp": { + "description": "ISO 8601 timestamp.", + "format": "date-time", + "title": "Timestamp", "type": "string" + }, + "status_2xx": { + "description": "2xx requests per second.", + "title": "Status 2Xx", + "type": "number" + }, + "status_4xx": { + "description": "4xx requests per second.", + "title": "Status 4Xx", + "type": "number" + }, + "status_5xx": { + "description": "5xx requests per second.", + "title": "Status 5Xx", + "type": "number" } }, "required": [ - "interactive_session", - "message" + "timestamp", + "status_2xx", + "status_4xx", + "status_5xx" ], - "title": "PatchInteractiveSessionResponseV1", + "title": "InferenceVolumeByStatusDatapointV1", "type": "object" }, - "FileSummary": { - "description": "Information about a file in the cache.", + "LoopsDeploymentMetricsV1": { + "description": "Metrics for a trainer (Loops) deployment.\n\nService-level fields summarize HTTP traffic into the trainer pods (the\nKnative queue-proxy is the source). Compute fields are the leader-pod\naggregate; ``per_node_metrics`` carries the full multinode breakdown.", "properties": { - "path": { - "description": "Relative path of the file in the cache", - "title": "Path", - "type": "string" + "inference_volume": { + "description": "Number of inference requests per unit time (requests per second).", + "items": { + "$ref": "#/components/schemas/TrainingJobMetricV1" + }, + "title": "Inference Volume", + "type": "array" }, - "size_bytes": { - "description": "Size of the file in bytes", - "title": "Size Bytes", - "type": "integer" + "concurrent_requests": { + "description": "Number of in-progress concurrent inference requests. Source: the queue-proxy ``revision_queue_depth`` gauge on ``http-usermetric``.", + "items": { + "$ref": "#/components/schemas/TrainingJobMetricV1" + }, + "title": "Concurrent Requests", + "type": "array" }, - "modified": { - "description": "Last modification time of the file", - "title": "Modified", - "type": "string" + "response_time_stats": { + "description": "Percentiles of the response time distribution.", + "items": { + "$ref": "#/components/schemas/ResponseTimeDatapointV1" + }, + "title": "Response Time Stats", + "type": "array" }, - "file_type": { - "description": "Type of the file", - "title": "File Type", - "type": "string" + "inference_volume_by_status": { + "description": "Request rate split by response code class.", + "items": { + "$ref": "#/components/schemas/InferenceVolumeByStatusDatapointV1" + }, + "title": "Inference Volume By Status", + "type": "array" }, - "permissions": { - "description": "Permissions of the file", - "title": "Permissions", - "type": "string" + "gpu_memory_usage_bytes": { + "additionalProperties": { + "items": { + "$ref": "#/components/schemas/TrainingJobMetricV1" + }, + "type": "array" + }, + "description": "Leader-pod GPU memory bytes per GPU rank.", + "title": "Gpu Memory Usage Bytes", + "type": "object" + }, + "gpu_utilization": { + "additionalProperties": { + "items": { + "$ref": "#/components/schemas/TrainingJobMetricV1" + }, + "type": "array" + }, + "description": "Leader-pod fractional GPU utilization per GPU rank.", + "title": "Gpu Utilization", + "type": "object" + }, + "cpu_usage": { + "description": "Leader-pod CPU usage in cores.", + "items": { + "$ref": "#/components/schemas/TrainingJobMetricV1" + }, + "title": "Cpu Usage", + "type": "array" + }, + "cpu_memory_usage_bytes": { + "description": "Leader-pod CPU memory usage bytes.", + "items": { + "$ref": "#/components/schemas/TrainingJobMetricV1" + }, + "title": "Cpu Memory Usage Bytes", + "type": "array" + }, + "ephemeral_storage": { + "$ref": "#/components/schemas/StorageMetricsV1", + "description": "Leader-pod ephemeral storage usage." + }, + "per_node_metrics": { + "description": "Per-node compute breakdown for multinode trainer deployments.", + "items": { + "$ref": "#/components/schemas/LoopsDeploymentNodeMetricsV1" + }, + "title": "Per Node Metrics", + "type": "array" } }, "required": [ - "path", - "size_bytes", - "modified", - "file_type", - "permissions" + "inference_volume", + "concurrent_requests", + "response_time_stats", + "inference_volume_by_status", + "gpu_memory_usage_bytes", + "gpu_utilization", + "cpu_usage", + "cpu_memory_usage_bytes", + "ephemeral_storage", + "per_node_metrics" ], - "title": "FileSummary", + "title": "LoopsDeploymentMetricsV1", "type": "object" }, - "GetCacheSummaryResponseV1": { - "description": "Response for getting cache summary.", + "LoopsDeploymentNodeMetricsV1": { + "description": "Per-node compute metrics for a multinode trainer deployment.", "properties": { - "timestamp": { - "description": "Timestamp when the cache summary was captured", - "title": "Timestamp", + "node_id": { + "description": "Identifier for the node.", + "title": "Node Id", "type": "string" }, - "project_id": { - "description": "Project ID associated with the cache", - "title": "Project Id", - "type": "string" + "gpu_memory_usage_bytes": { + "additionalProperties": { + "items": { + "$ref": "#/components/schemas/TrainingJobMetricV1" + }, + "type": "array" + }, + "description": "GPU memory usage bytes per GPU rank.", + "title": "Gpu Memory Usage Bytes", + "type": "object" + }, + "gpu_utilization": { + "additionalProperties": { + "items": { + "$ref": "#/components/schemas/TrainingJobMetricV1" + }, + "type": "array" + }, + "description": "Fractional GPU utilization per GPU rank.", + "title": "Gpu Utilization", + "type": "object" }, - "file_summaries": { - "description": "List of files in the cache", + "cpu_usage": { + "description": "CPU usage in cores.", "items": { - "$ref": "#/components/schemas/FileSummary" + "$ref": "#/components/schemas/TrainingJobMetricV1" }, - "title": "File Summaries", + "title": "Cpu Usage", + "type": "array" + }, + "cpu_memory_usage_bytes": { + "description": "CPU memory usage bytes.", + "items": { + "$ref": "#/components/schemas/TrainingJobMetricV1" + }, + "title": "Cpu Memory Usage Bytes", "type": "array" + }, + "ephemeral_storage": { + "$ref": "#/components/schemas/StorageMetricsV1", + "description": "Ephemeral storage usage." } }, "required": [ - "timestamp", - "project_id", - "file_summaries" + "node_id", + "gpu_memory_usage_bytes", + "gpu_utilization", + "cpu_usage", + "cpu_memory_usage_bytes", + "ephemeral_storage" ], - "title": "GetCacheSummaryResponseV1", + "title": "LoopsDeploymentNodeMetricsV1", "type": "object" }, - "TrainingProjectTombstoneV1": { - "description": "A training project tombstone.", + "ResponseTimeDatapointV1": { + "description": "Latency quantile datapoint. Values are reported in milliseconds.", "properties": { - "id": { - "description": "Unique identifier of the training project", - "title": "Id", + "timestamp": { + "description": "ISO 8601 timestamp.", + "format": "date-time", + "title": "Timestamp", "type": "string" }, - "deleted": { - "description": "Whether the training project was deleted", - "title": "Deleted", - "type": "boolean" - } - }, - "required": [ - "id", - "deleted" - ], - "title": "TrainingProjectTombstoneV1", - "type": "object" - }, - "GetTrainingProjectResponseV1": { - "description": "A response to getting a training project.", - "properties": { - "training_project": { - "$ref": "#/components/schemas/TrainingProjectV1", - "description": "The training project." + "p50": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "description": "50th percentile request latency (milliseconds).", + "title": "P50" + }, + "p95": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "description": "95th percentile request latency (milliseconds).", + "title": "P95" + }, + "p99": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "description": "99th percentile request latency (milliseconds).", + "title": "P99" } }, "required": [ - "training_project" + "timestamp" ], - "title": "GetTrainingProjectResponseV1", + "title": "ResponseTimeDatapointV1", "type": "object" }, - "OrderByV1": { - "description": "A request to order training jobs.", + "GetLoopsDeploymentMetricsResponseV1": { + "description": "Response for ``POST /v1/loops/deployments//metrics``.", "properties": { - "field": { - "description": "The field to order by.", - "examples": [ - "created_at" - ], - "title": "Field", + "deployment_id": { + "description": "The trainer deployment ID.", + "title": "Deployment Id", "type": "string" }, - "order": { - "description": "The direction to order by.", - "examples": [ - "asc", - "desc" - ], - "title": "Order", - "type": "string" + "metrics": { + "$ref": "#/components/schemas/LoopsDeploymentMetricsV1", + "description": "Metrics for the deployment." } }, "required": [ - "field", - "order" + "deployment_id", + "metrics" ], - "title": "OrderByV1", + "title": "GetLoopsDeploymentMetricsResponseV1", "type": "object" }, - "SearchTrainingJobsRequestV1": { - "description": "A request to search training jobs.", + "GetLoopsDeploymentLogsRequestV1": { + "description": "Query parameters for fetching a Loops deployment's logs.", "properties": { - "project_id": { + "start_epoch_millis": { "anyOf": [ { - "type": "string" + "type": "integer" }, { "type": "null" } ], "default": null, - "description": "Filter the training jobs by project ID.", - "examples": [ - "n4q95w5" - ], - "title": "Project Id" + "description": "Epoch milliseconds at which to start fetching logs. Defaults to 30 minutes before the end. The window from start to end must not exceed 7 days.", + "title": "Start Epoch Millis" }, - "job_id": { + "end_epoch_millis": { "anyOf": [ { - "type": "string" + "type": "integer" }, { "type": "null" } ], "default": null, - "description": "Filter the training jobs by job ID.", - "examples": [ - "p7qr9qv" - ], - "title": "Job Id" + "description": "Epoch milliseconds at which to stop fetching logs. Defaults to the current time.", + "title": "End Epoch Millis" }, - "statuses": { + "direction": { "anyOf": [ { - "items": { - "type": "string" - }, - "type": "array" + "$ref": "#/components/schemas/SortOrderV1" }, { "type": "null" } ], "default": null, - "description": "Filter the training jobs by status.", - "examples": [ - [ - "TRAINING_JOB_RUNNING", - "TRAINING_JOB_COMPLETED" - ] + "description": "Sort order for logs" + }, + "limit": { + "anyOf": [ + { + "maximum": 1000, + "minimum": 1, + "type": "integer" + }, + { + "type": "null" + } ], - "title": "Statuses" + "default": 500, + "description": "Limit of logs to fetch in a single request", + "title": "Limit" }, - "order_by": { - "default": [ + "min_level": { + "anyOf": [ { - "field": "created_at", - "order": "desc" + "$ref": "#/components/schemas/LogLevelV1" + }, + { + "type": "null" } ], - "description": "Order the training jobs by a field. Currently supports created_at", - "items": { - "$ref": "#/components/schemas/OrderByV1" - }, - "title": "Order By", - "type": "array" + "default": null, + "description": "Minimum log severity to include. Omit to return all log lines, including lines that have no level. Any explicit value returns lines at or above that severity and drops lines without a level." } }, - "title": "SearchTrainingJobsRequestV1", + "title": "GetLoopsDeploymentLogsRequestV1", "type": "object" }, - "SearchTrainingJobsResponseV1": { - "description": "A response to search training jobs.", + "TeamTrainingGpuCapacityItemV1": { + "description": "Per-team GPU capacity and current usage for one GPU type.", "properties": { - "training_jobs": { - "description": "List of training jobs.", - "items": { - "$ref": "#/components/schemas/TrainingJobV1" - }, - "title": "Training Jobs", - "type": "array" + "team_id": { + "description": "Team identifier", + "title": "Team Id", + "type": "string" + }, + "team_name": { + "description": "Team name", + "title": "Team Name", + "type": "string" + }, + "gpu_type": { + "description": "GPU type identifier (e.g. H100, A100-40GB)", + "title": "Gpu Type", + "type": "string" + }, + "baseline": { + "description": "Baseline GPU allocation for the team. 0 if not configured.", + "title": "Baseline", + "type": "integer" + }, + "limit": { + "description": "Maximum concurrent GPUs of this type for this team", + "title": "Limit", + "type": "integer" + }, + "usage_count": { + "description": "GPUs currently in use by the team's active training jobs", + "title": "Usage Count", + "type": "integer" + }, + "dedicated_usage_count": { + "default": 0, + "description": "Portion of usage_count from dedicated (on-demand) jobs.", + "title": "Dedicated Usage Count", + "type": "integer" + }, + "spot_usage_count": { + "default": 0, + "description": "Portion of usage_count from spot jobs.", + "title": "Spot Usage Count", + "type": "integer" } }, "required": [ - "training_jobs" + "team_id", + "team_name", + "gpu_type", + "baseline", + "limit", + "usage_count" ], - "title": "SearchTrainingJobsResponseV1", + "title": "TeamTrainingGpuCapacityItemV1", "type": "object" }, - "SupportedModelV1": { - "description": "A model supported by the Loops server.", + "TrainingGpuCapacityItemV1": { + "description": "GPU capacity and current usage for one GPU type.", "properties": { - "model_name": { - "description": "The name of the supported model.", - "title": "Model Name", + "gpu_type": { + "description": "GPU type identifier (e.g. H100, A100-40GB)", + "title": "Gpu Type", "type": "string" }, - "max_context_length": { - "description": "The maximum context length (in tokens) supported by this model.", - "title": "Max Context Length", + "baseline": { + "description": "Baseline GPU allocation; jobs below this threshold are expected to run immediately. 0 if not configured.", + "title": "Baseline", "type": "integer" }, - "supports_vision_language": { - "description": "Whether the model accepts image inputs alongside text.", - "title": "Supports Vision Language", - "type": "boolean" + "limit": { + "description": "Maximum concurrent GPUs of this type for this org", + "title": "Limit", + "type": "integer" + }, + "usage_count": { + "description": "GPUs currently in use by active training jobs", + "title": "Usage Count", + "type": "integer" + }, + "dedicated_usage_count": { + "default": 0, + "description": "Portion of usage_count from dedicated (on-demand) jobs, which run against the baseline.", + "title": "Dedicated Usage Count", + "type": "integer" + }, + "spot_usage_count": { + "default": 0, + "description": "Portion of usage_count from spot jobs, which burst into the peak and may push usage above the limit.", + "title": "Spot Usage Count", + "type": "integer" } }, "required": [ - "model_name", - "max_context_length", - "supports_vision_language" + "gpu_type", + "baseline", + "limit", + "usage_count" ], - "title": "SupportedModelV1", + "title": "TrainingGpuCapacityItemV1", "type": "object" }, - "GetLoopsCapabilitiesResponseV1": { - "description": "Response for ``GET /v1/loops/capabilities``.", + "GetTrainingGpuCapacityResponseV1": { + "description": "Response for the training GPU capacity endpoint.", "properties": { - "supported_models": { - "description": "List of models available on the server.", + "gpu_capacities": { + "description": "Org-level GPU capacity limits and current usage per GPU type", "items": { - "$ref": "#/components/schemas/SupportedModelV1" + "$ref": "#/components/schemas/TrainingGpuCapacityItemV1" }, - "title": "Supported Models", + "title": "Gpu Capacities", + "type": "array" + }, + "team_gpu_capacities": { + "description": "Per-team GPU capacity limits and current usage per GPU type", + "items": { + "$ref": "#/components/schemas/TeamTrainingGpuCapacityItemV1" + }, + "title": "Team Gpu Capacities", "type": "array" } }, "required": [ - "supported_models" + "gpu_capacities" ], - "title": "GetLoopsCapabilitiesResponseV1", + "title": "GetTrainingGpuCapacityResponseV1", "type": "object" }, - "LoopsSessionV1": { + "PatchTeamTrainingGpuCapacityRequestV1": { + "description": "A request to set the GPU capacity ceiling for a (team, gpu_type) pair.\n\nCreates the limit if one doesn't already exist for this team and GPU type,\notherwise updates it in place.", "properties": { - "id": { - "title": "Id", + "team_id": { + "description": "Team identifier", + "title": "Team Id", "type": "string" + }, + "gpu_type": { + "description": "GPU type identifier (e.g. H100, A100-40GB)", + "title": "Gpu Type", + "type": "string" + }, + "max_gpus": { + "description": "Max concurrent GPUs of this type the team may use", + "examples": [ + 8, + 16, + 32 + ], + "title": "Max Gpus", + "type": "integer" } }, "required": [ - "id" - ], - "title": "LoopsSessionV1", - "type": "object" - }, - "CreateLoopsSessionResponseV1": { - "properties": { - "session": { - "$ref": "#/components/schemas/LoopsSessionV1" - } - }, - "required": [ - "session" - ], - "title": "CreateLoopsSessionResponseV1", - "type": "object" - }, - "GetLoopsSessionResponseV1": { - "description": "Response for ``GET /v1/loops/sessions/``.", - "properties": { - "session": { - "$ref": "#/components/schemas/LoopsSessionV1", - "description": "The Loops session." - } - }, - "required": [ - "session" + "team_id", + "gpu_type", + "max_gpus" ], - "title": "GetLoopsSessionResponseV1", + "title": "PatchTeamTrainingGpuCapacityRequestV1", "type": "object" }, - "LoopsRunStatusNameV1": { - "description": "A Loops run's lifecycle state: ACTIVE or INACTIVE.", - "enum": [ - "ACTIVE", - "INACTIVE" - ], - "title": "LoopsRunStatusNameV1", - "type": "string" - }, - "LoopsRunStatusV1": { - "description": "The current status of a Loops run.", + "PatchTeamTrainingGpuCapacityResponseV1": { + "description": "Response for setting a team's GPU capacity ceiling.", "properties": { - "name": { - "$ref": "#/components/schemas/LoopsRunStatusNameV1", - "description": "ACTIVE while the run is live; INACTIVE once replaced by a newer run or shut down." + "team_gpu_capacity": { + "$ref": "#/components/schemas/TeamTrainingGpuCapacityItemV1", + "description": "The updated per-team GPU capacity limit" } }, "required": [ - "name" + "team_gpu_capacity" ], - "title": "LoopsRunStatusV1", + "title": "PatchTeamTrainingGpuCapacityResponseV1", "type": "object" }, - "LoopsRunV1": { + "ActiveJobAtSubmitV1": { + "description": "One other job in the same (org, gpu_type) pool that was holding GPU\ncapacity at the moment the target was submitted.", "properties": { - "id": { - "description": "The run ID.", - "title": "Id", - "type": "string" - }, - "session_id": { - "description": "The session ID this run belongs to.", - "title": "Session Id", + "training_job_id": { + "description": "Hashid of the other training job", + "title": "Training Job Id", "type": "string" }, - "deployment_id": { + "training_job_name": { "anyOf": [ { "type": "string" @@ -22147,171 +26845,150 @@ } ], "default": null, - "description": "The ID of the Loops deployment the run executes on, if it has one.", - "title": "Deployment Id" + "description": "Other job's name", + "title": "Training Job Name" }, - "name": { - "description": "The run's display name.", - "title": "Name", + "instance_type_name": { + "description": "Instance type of the other job", + "title": "Instance Type Name", "type": "string" }, - "base_model": { - "description": "The HuggingFace base model the run is fine-tuning.", - "title": "Base Model", + "total_gpus": { + "description": "gpu_count * effective_node_count", + "title": "Total Gpus", + "type": "integer" + }, + "workload_plane_name": { + "description": "Workload plane the other job was on", + "title": "Workload Plane Name", "type": "string" }, - "base_url": { - "description": "The run's base URL.", - "title": "Base Url", + "status_at_submit": { + "description": "Other job's status as of submitted_at (one of ACTIVE_STATES)", + "title": "Status At Submit", "type": "string" }, - "created_at": { - "description": "Time the run was created in ISO 8601 format", + "status_set_at": { + "description": "When that status was set", "format": "date-time", - "title": "Created At", + "title": "Status Set At", + "type": "string" + } + }, + "required": [ + "training_job_id", + "instance_type_name", + "total_gpus", + "workload_plane_name", + "status_at_submit", + "status_set_at" + ], + "title": "ActiveJobAtSubmitV1", + "type": "object" + }, + "CapacityAtSubmitV1": { + "description": "A GPU capacity row as it stands now, with ``last_modified`` so callers\ncan judge whether the value matches what the dequeue gate saw at submit\ntime. Capacity rows are not historicized: edits overwrite in place. Compare\n``last_modified`` against the response's ``submitted_at`` \u2014 if it's later,\nthe value may have changed.", + "properties": { + "gpu_type": { + "description": "GPU type identifier (e.g. H100, A100-40GB)", + "title": "Gpu Type", "type": "string" }, - "status": { - "$ref": "#/components/schemas/LoopsRunStatusV1", - "description": "The run's current status." - }, - "user": { - "$ref": "#/components/schemas/UserV1", - "description": "The user who owns the run." + "max_gpus": { + "description": "Current max concurrent GPUs of this type", + "title": "Max Gpus", + "type": "integer" }, - "sampler": { + "min_gpus": { "anyOf": [ { - "$ref": "#/components/schemas/LoopsSamplerV1" + "type": "integer" }, { "type": "null" } ], "default": null, - "description": "The sampler bound to this run, or null for a trainer-only run that has not yet created a sampler." - } - }, - "required": [ - "id", - "session_id", - "name", - "base_model", - "base_url", - "created_at", - "status", - "user" - ], - "title": "LoopsRunV1", - "type": "object" - }, - "LoopsSamplerStatusV1": { - "description": "The current status of a Loops sampler.", - "properties": { - "name": { - "$ref": "#/components/schemas/DeploymentStatusV1", - "description": "The current status of the Loops sampler." + "description": "Current baseline GPU allocation, if configured", + "title": "Min Gpus" + }, + "last_modified": { + "description": "When the capacity row was last modified", + "format": "date-time", + "title": "Last Modified", + "type": "string" } }, "required": [ - "name" + "gpu_type", + "max_gpus", + "last_modified" ], - "title": "LoopsSamplerStatusV1", + "title": "CapacityAtSubmitV1", "type": "object" }, - "LoopsSamplerV1": { + "PendingJobAheadAtSubmitV1": { + "description": "A PENDING job in the same (org, gpu_type) pool that was ahead of the\ntarget in dequeue FIFO order at submitted_at \u2014 higher priority, or same\npriority and earlier submission.", "properties": { - "id": { - "title": "Id", - "type": "string" - }, - "base_url": { - "title": "Base Url", - "type": "string" - }, - "base_model": { - "description": "The HuggingFace base model the sampler is serving.", - "title": "Base Model", - "type": "string" - }, - "created_at": { - "description": "Time the sampler was created in ISO 8601 format", - "format": "date-time", - "title": "Created At", - "type": "string" - }, - "model_id": { - "description": "Hashid of the underlying Baseten model.", - "title": "Model Id", - "type": "string" - }, - "deployment_id": { - "description": "Hashid of the specific model deployment (version).", - "title": "Deployment Id", + "training_job_id": { + "description": "Hashid of the other training job", + "title": "Training Job Id", "type": "string" }, - "status": { - "$ref": "#/components/schemas/LoopsSamplerStatusV1", - "description": "The sampler's current status." - }, - "user": { - "$ref": "#/components/schemas/UserV1", - "description": "The user who owns the sampler." - }, - "instance_type": { + "training_job_name": { "anyOf": [ { - "$ref": "#/components/schemas/InstanceTypeV1" + "type": "string" }, { "type": "null" } ], "default": null, - "description": "Instance type serving the sampler." + "description": "Other job's name", + "title": "Training Job Name" }, - "node_count": { - "default": 1, - "description": "Number of nodes serving the sampler.", - "title": "Node Count", + "instance_type_name": { + "description": "Instance type of the other job", + "title": "Instance Type Name", + "type": "string" + }, + "requested_gpus": { + "description": "gpu_count * effective_node_count", + "title": "Requested Gpus", "type": "integer" + }, + "priority": { + "description": "Effective priority (NULL coalesced to 0)", + "title": "Priority", + "type": "integer" + }, + "submitted_at": { + "description": "The other job's submission time", + "format": "date-time", + "title": "Submitted At", + "type": "string" } }, "required": [ - "id", - "base_url", - "base_model", - "created_at", - "model_id", - "deployment_id", - "status", - "user" - ], - "title": "LoopsSamplerV1", - "type": "object" - }, - "ListLoopsRunsResponseV1": { - "description": "Runs matching the query filters.", - "properties": { - "runs": { - "description": "List of runs.", - "items": { - "$ref": "#/components/schemas/LoopsRunV1" - }, - "title": "Runs", - "type": "array" - } - }, - "required": [ - "runs" + "training_job_id", + "instance_type_name", + "requested_gpus", + "priority", + "submitted_at" ], - "title": "ListLoopsRunsResponseV1", + "title": "PendingJobAheadAtSubmitV1", "type": "object" }, - "ListLoopsRunsQueryParamsV1": { - "description": "Query-string filters for ``GET /v1/loops/runs``.\n\nAll filters are optional and can be combined; omit them to list the caller's\nown runs. Pass ``scope=org`` to list every run in the caller's organization\ninstead.", + "QueueEventV1": { + "description": "A single ``TrainingJobStatus`` row inside the queue-context window.", "properties": { - "run_id": { + "training_job_id": { + "description": "Hashid of the training job this event is for", + "title": "Training Job Id", + "type": "string" + }, + "training_job_name": { "anyOf": [ { "type": "string" @@ -22321,13 +26998,21 @@ } ], "default": null, - "description": "Filter by run ID.", - "examples": [ - "k4q95w5" - ], - "title": "Run Id" + "description": "Job name", + "title": "Training Job Name" }, - "base_model": { + "status": { + "description": "TrainingJobStatus.Name value", + "title": "Status", + "type": "string" + }, + "created": { + "description": "When the status row was inserted", + "format": "date-time", + "title": "Created", + "type": "string" + }, + "event_message": { "anyOf": [ { "type": "string" @@ -22337,49 +27022,42 @@ } ], "default": null, - "description": "Filter runs by base model name.", - "examples": [ - "Qwen/Qwen3-8B" - ], - "title": "Base Model" + "description": "Human-readable event message from the status metadata", + "title": "Event Message" }, - "scope": { + "exit_code": { "anyOf": [ { - "type": "string" + "type": "integer" }, { "type": "null" } ], "default": null, - "description": "Defaults to the caller's own runs; pass 'org' to list every run in the caller's organization.", - "examples": [ - "org" - ], - "title": "Scope" + "description": "Exit code from the status metadata, if any", + "title": "Exit Code" } }, - "title": "ListLoopsRunsQueryParamsV1", + "required": [ + "training_job_id", + "status", + "created" + ], + "title": "QueueEventV1", "type": "object" }, - "CreateLoopsRunRequestV1": { + "GetTrainingJobQueueContextResponseV1": { + "description": "Read-only diagnostic for a training job's PENDING window.\n\nReturns the (org, gpu_type) capacity pool the job was gated by, jobs that\nwere holding GPU capacity in that pool when this job was submitted, and\nevery status event in [submitted_at, released_at] for those jobs (or up to\n\"now\" if the target is still PENDING).", "properties": { - "session_id": { - "description": "ID of the Loops session this run belongs to.", - "title": "Session Id", - "type": "string" - }, - "base_model": { - "description": "Base model ID (e.g. 'Qwen/Qwen3-8B').", - "title": "Base Model", + "target_job_id": { + "description": "Hashid of the target training job", + "title": "Target Job Id", "type": "string" }, - "name": { + "target_job_name": { "anyOf": [ { - "maxLength": 255, - "minLength": 1, "type": "string" }, { @@ -22387,189 +27065,163 @@ } ], "default": null, - "description": "Optional display name for the run. Defaults to the base model name when omitted.", - "title": "Name" + "description": "Target job's name", + "title": "Target Job Name" }, - "max_seq_len": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null, - "description": "Maximum prompt length (in tokens) the run must handle. Set this to the longest training example you plan to send. Defaults to the maximum supported by the model configuration.", - "title": "Max Seq Len" + "gpu_type": { + "description": "GPU type the target requested", + "title": "Gpu Type", + "type": "string" }, - "lora_rank": { - "default": 64, - "description": "LoRA rank.", - "minimum": 1, - "title": "Lora Rank", + "requested_gpus": { + "description": "GPUs the target requested (gpu_count * effective_node_count)", + "title": "Requested Gpus", "type": "integer" }, - "seed": { + "submitted_at": { + "description": "When the job row was inserted (= API POST time)", + "format": "date-time", + "title": "Submitted At", + "type": "string" + }, + "released_at": { "anyOf": [ { - "type": "integer" + "format": "date-time", + "type": "string" }, { "type": "null" } ], "default": null, - "description": "Random seed for reproducibility.", - "title": "Seed" - }, - "scale_down_delay_seconds": { - "default": 900, - "description": "Seconds of inactivity before the run scales to zero. Must be between 1 and 3600 (1 hour). Defaults to 900 (15 minutes).", - "exclusiveMinimum": 0, - "maximum": 3600, - "title": "Scale Down Delay Seconds", - "type": "integer" - }, - "availability_model": { - "$ref": "#/components/schemas/V1AvailabilityModel", - "default": "dedicated", - "description": "Capacity the trainer runs on. 'dedicated' is not preempted. 'spot' runs below inference and reaches idle reserved capacity, but the run is stopped if its GPUs are reclaimed and cannot be resumed.", - "examples": [ - "spot" - ] - }, - "replicas": { - "default": 1, - "description": "Number of data-parallel trainer replicas. Each replica is one full copy of the model's preset node group, so the trainer deployment runs (preset node_count * replicas) nodes (e.g. replicas=4 on a 4-node preset \u2192 16 nodes, 4 DP workers). Must be a positive integer. Defaults to 1.", - "minimum": 1, - "title": "Replicas", - "type": "integer" + "description": "When the job's TRAINING_JOB_CREATED status was set, i.e. the moment it was released from PENDING. None if still PENDING.", + "title": "Released At" }, - "path": { + "pending_seconds": { "anyOf": [ { - "type": "string" + "type": "integer" }, { "type": "null" } ], "default": null, - "description": "Optional bt:// URI of an existing checkpoint to load weights from on startup. Form: bt://loops:/weights/.", - "examples": [ - "bt://loops:k4q95w5/weights/step-100" - ], - "title": "Path" + "description": "released_at - submitted_at in seconds. None if still PENDING.", + "title": "Pending Seconds" }, - "reuse_from_run_id": { + "org_capacity": { "anyOf": [ { - "type": "string" + "$ref": "#/components/schemas/CapacityAtSubmitV1" }, { "type": "null" } ], "default": null, - "description": "Optional ID of a prior Loops run whose trainer and/or sampler should be reused for this run instead of provisioning fresh. The prior run must use the same base model and belong to the same team.", - "title": "Reuse From Run Id" + "description": "Org-level cap for (org, gpu_type). None if no cap is configured." }, - "reuse_from_session_id": { + "team_capacity": { "anyOf": [ { - "type": "string" + "$ref": "#/components/schemas/CapacityAtSubmitV1" }, { "type": "null" } ], "default": null, - "description": "Optional ID of a prior Loops session whose trainer and/or sampler should be reused for this run. Deprecated in favor of reuse_from_run_id.", - "title": "Reuse From Session Id" - } - }, - "required": [ - "session_id", - "base_model" - ], - "title": "CreateLoopsRunRequestV1", - "type": "object" - }, - "CreateLoopsRunResponseV1": { - "properties": { - "run": { - "$ref": "#/components/schemas/LoopsRunV1" + "description": "Team-level cap for (team, gpu_type). None if no team cap is configured." + }, + "active_at_submit": { + "description": "Jobs in the same (org, gpu_type) pool that were holding capacity at submitted_at", + "items": { + "$ref": "#/components/schemas/ActiveJobAtSubmitV1" + }, + "title": "Active At Submit", + "type": "array" + }, + "pending_ahead_at_submit": { + "description": "PENDING jobs in the same (org, gpu_type) pool that were ahead of the target in dequeue FIFO order at submitted_at (priority DESC then created ASC). These also block the target's release.", + "items": { + "$ref": "#/components/schemas/PendingJobAheadAtSubmitV1" + }, + "title": "Pending Ahead At Submit", + "type": "array" + }, + "events": { + "description": "Every status event in [submitted_at, events_window_end] for the target job, every job in active_at_submit, and every job in pending_ahead_at_submit, oldest first.", + "items": { + "$ref": "#/components/schemas/QueueEventV1" + }, + "title": "Events", + "type": "array" + }, + "events_window_end": { + "description": "released_at if set, else 'now' (events ongoing)", + "format": "date-time", + "title": "Events Window End", + "type": "string" } }, "required": [ - "run" + "target_job_id", + "gpu_type", + "requested_gpus", + "submitted_at", + "active_at_submit", + "pending_ahead_at_submit", + "events", + "events_window_end" ], - "title": "CreateLoopsRunResponseV1", + "title": "GetTrainingJobQueueContextResponseV1", "type": "object" }, - "DeactivateLoopsRunResponseV1": { - "description": "Response for ``POST /v1/loops/runs//deactivate``.", + "GetBlobCredentialsResponseV1": { + "description": "Response to create a new set of credentials for blob upload.", "properties": { - "id": { - "description": "The deactivated Loops run ID.", - "title": "Id", - "type": "string" + "creds": { + "$ref": "#/components/schemas/AWSCredentialsV1", + "description": "The credentials to upload the blob to" }, - "base_model": { - "description": "The base model whose Loops run was deactivated.", - "title": "Base Model", + "s3_key": { + "description": "The S3 key to upload the blob to", + "title": "S3 Key", "type": "string" }, - "user": { - "$ref": "#/components/schemas/UserV1", - "description": "The user who owns the Loops run." - } - }, - "required": [ - "id", - "base_model", - "user" - ], - "title": "DeactivateLoopsRunResponseV1", - "type": "object" - }, - "GetLoopsRunResponseV1": { - "description": "Response for ``GET /v1/loops/runs/``.", - "properties": { - "run": { - "$ref": "#/components/schemas/LoopsRunV1", - "description": "The Loops run with its associated sampler." + "s3_bucket": { + "description": "The S3 bucket to upload the blob to", + "title": "S3 Bucket", + "type": "string" } }, "required": [ - "run" + "creds", + "s3_key", + "s3_bucket" ], - "title": "GetLoopsRunResponseV1", + "title": "GetBlobCredentialsResponseV1", "type": "object" }, - "ListLoopsSamplersResponseV1": { - "description": "Response for ``GET /v1/loops/samplers``.\n\nReturns the caller's samplers, including those paired to runs and\nstandalone samplers. Ordered newest-first.", - "properties": { - "samplers": { - "description": "List of samplers.", - "items": { - "$ref": "#/components/schemas/LoopsSamplerV1" - }, - "title": "Samplers", - "type": "array" - } - }, - "required": [ - "samplers" + "APIKeyCategory": { + "description": "Enum representing the category of an API key.", + "enum": [ + "PERSONAL", + "ROUTES", + "WORKSPACE_MANAGE_ALL", + "WORKSPACE_EXPORT_METRICS", + "WORKSPACE_INVOKE", + "WORKSPACE_MANAGE_API_KEYS" ], - "title": "ListLoopsSamplersResponseV1", - "type": "object" + "title": "APIKeyCategory", + "type": "string" }, - "ListLoopsSamplersRequestV1": { - "description": "Query-string filters for the Loops sampler listing routes.", + "CreateAPIKeyRequestV1": { + "description": "Request to create an API key.", "properties": { - "scope": { + "name": { "anyOf": [ { "type": "string" @@ -22579,81 +27231,49 @@ } ], "default": null, - "description": "Defaults to the caller's own samplers; pass 'org' to include samplers owned by other users in the caller's organization.", + "description": "Optional name for the API key", "examples": [ - "org" - ], - "title": "Scope" - } - }, - "title": "ListLoopsSamplersRequestV1", - "type": "object" - }, - "CreateLoopsSamplerRequestV1": { - "properties": { - "session_id": { - "description": "ID of the Loops session this sampler belongs to.", - "title": "Session Id", - "type": "string" - }, - "base_model": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "description": "Base model ID for a standalone sampler (for example, a baseline).", - "title": "Base Model" - }, - "run_id": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "my-api-key" ], - "default": null, - "description": "ID of an existing run to attach this sampler to. When set, the sampler is paired to the run and weight-syncs from its trainer, and base_model is inherited from the run. Omit to create a standalone sampler.", - "title": "Run Id" + "title": "Name" }, - "max_seq_length": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null, - "description": "Maximum prompt length (in tokens) the sampler must handle. Set this to the longest prompt you plan to send.", - "title": "Max Seq Length" + "type": { + "$ref": "#/components/schemas/APIKeyCategory", + "description": "Type of the API key.", + "examples": [ + "PERSONAL", + "ROUTES", + "WORKSPACE_MANAGE_API_KEYS", + "WORKSPACE_EXPORT_METRICS", + "WORKSPACE_INVOKE", + "WORKSPACE_MANAGE_ALL" + ] }, - "model_path": { + "model_ids": { "anyOf": [ { - "type": "string" + "items": { + "type": "string" + }, + "type": "array" }, { "type": "null" } ], "default": null, - "description": "bt:// URI of an existing sampler checkpoint to serve. Form: bt://loops:/sampler_weights/.", + "description": "List of model IDs to scope the API key to, only present if type is 'WORKSPACE_EXPORT_METRICS' or 'WORKSPACE_INVOKE'", "examples": [ - "bt://loops:k4q95w5/sampler_weights/step-100" + [ + "aaaaaaaa" + ] ], - "title": "Model Path" + "title": "Model Ids" }, - "reuse_from_session_id": { + "team_id": { "anyOf": [ { + "minLength": 1, "type": "string" }, { @@ -22661,62 +27281,40 @@ } ], "default": null, - "description": "Optional ID of a prior Loops session to reuse a trainer and/or sampler from. Deprecated.", - "title": "Reuse From Session Id" - } - }, - "required": [ - "session_id" - ], - "title": "CreateLoopsSamplerRequestV1", - "type": "object" - }, - "CreateLoopsSamplerResponseV1": { - "properties": { - "sampler": { - "$ref": "#/components/schemas/LoopsSamplerV1" + "description": "Team ID for a team-scoped key. When omitted, uses the team in the URL if present, otherwise your organization's default team. Must match the URL team when both are provided. Not supported for PERSONAL or WORKSPACE_MANAGE_API_KEYS keys.", + "title": "Team Id" } }, "required": [ - "sampler" + "type" ], - "title": "CreateLoopsSamplerResponseV1", + "title": "CreateAPIKeyRequestV1", "type": "object" }, - "GetLoopsSamplerResponseV1": { - "description": "Response for ``GET /v1/loops/samplers/``.", + "APIKeyV1": { + "description": "Represents an API key.", "properties": { - "sampler": { - "$ref": "#/components/schemas/LoopsSamplerV1", - "description": "The Loops sampler." + "api_key": { + "description": "The API key string", + "title": "Api Key", + "type": "string" } }, "required": [ - "sampler" + "api_key" ], - "title": "GetLoopsSamplerResponseV1", + "title": "APIKeyV1", "type": "object" }, - "LoopsCheckpointV1": { - "description": "A checkpoint saved by a Loops run.", + "APIKeyInfoV1": { + "description": "Represents the metadata of an API key.", "properties": { - "checkpoint_id": { - "description": "The ID of the checkpoint.", - "title": "Checkpoint Id", - "type": "string" - }, - "created_at": { - "description": "The timestamp of the checkpoint in ISO 8601 format.", - "format": "date-time", - "title": "Created At", - "type": "string" - }, - "checkpoint_type": { - "description": "The type of checkpoint.", - "title": "Checkpoint Type", + "prefix": { + "description": "The prefix of the API key", + "title": "Prefix", "type": "string" }, - "base_model": { + "name": { "anyOf": [ { "type": "string" @@ -22725,28 +27323,47 @@ "type": "null" } ], - "description": "The base model of the checkpoint.", - "title": "Base Model" + "default": null, + "description": "Optional name for the API key", + "examples": [ + "my-api-key" + ], + "title": "Name" }, - "lora_adapter_config": { + "type": { + "$ref": "#/components/schemas/APIKeyCategory", + "description": "Type of the API key.", + "examples": [ + "PERSONAL", + "ROUTES", + "WORKSPACE_MANAGE_API_KEYS", + "WORKSPACE_EXPORT_METRICS", + "WORKSPACE_INVOKE", + "WORKSPACE_MANAGE_ALL" + ] + }, + "model_ids": { "anyOf": [ { - "additionalProperties": true, - "type": "object" + "items": { + "type": "string" + }, + "type": "array" }, { "type": "null" } ], - "description": "The adapter config of the checkpoint.", - "title": "Lora Adapter Config" - }, - "size_bytes": { - "description": "The size of the checkpoint in bytes.", - "title": "Size Bytes", - "type": "integer" + "default": null, + "description": "List of model IDs to scope the API key to, only present if type is 'WORKSPACE_EXPORT_METRICS' or 'WORKSPACE_INVOKE'", + "examples": [ + [ + "aaaaaaaa" + ] + ], + "title": "Model Ids" }, - "sync_status": { + "team_name": { "anyOf": [ { "type": "string" @@ -22756,71 +27373,19 @@ } ], "default": null, - "description": "Sync state of the checkpoint: SYNCING or COMPLETE.", - "title": "Sync Status" - }, - "id": { - "description": "The checkpoint ID.", - "title": "Id", - "type": "string" + "description": "The name of the team associated with the API key", + "title": "Team Name" }, - "run_id": { - "description": "The ID of the run that produced the checkpoint.", - "title": "Run Id", + "created_at": { + "description": "Creation time in ISO 8601 format", + "format": "date-time", + "title": "Created At", "type": "string" }, - "target": { - "$ref": "#/components/schemas/TrainerCheckpointTarget", - "description": "Whether this checkpoint is loadable by the sampler or by the run." - } - }, - "required": [ - "checkpoint_id", - "created_at", - "checkpoint_type", - "base_model", - "lora_adapter_config", - "size_bytes", - "id", - "run_id", - "target" - ], - "title": "LoopsCheckpointV1", - "type": "object" - }, - "TrainerCheckpointTarget": { - "description": "Whether a TrainerServerCheckpoint is loadable by the sampler or the trainer.\n\nSAMPLER checkpoints are consumed by the sampling server for inference;\nTRAINER checkpoints capture full trainer state for resuming training.\nMirrored in the bt:// URI as\n``bt://loops:/(sampler_weights|weights)/``.", - "enum": [ - "sampler", - "trainer" - ], - "title": "TrainerCheckpointTarget", - "type": "string" - }, - "ListLoopsCheckpointsResponseV1": { - "description": "Checkpoints matching the query filter.", - "properties": { - "checkpoints": { - "description": "Matching checkpoints.", - "items": { - "$ref": "#/components/schemas/LoopsCheckpointV1" - }, - "title": "Checkpoints", - "type": "array" - } - }, - "required": [ - "checkpoints" - ], - "title": "ListLoopsCheckpointsResponseV1", - "type": "object" - }, - "ListLoopsCheckpointsQueryParamsV1": { - "description": "Query-string filters for ``GET /v1/loops/checkpoints``.\n\nProvide exactly one of ``run_id`` (all checkpoints for the run),\n``base_model`` (all checkpoints across the caller's runs of that\nbase model), or ``checkpoint_path`` (the single matching checkpoint).", - "properties": { - "run_id": { + "last_used_at": { "anyOf": [ { + "format": "date-time", "type": "string" }, { @@ -22828,13 +27393,39 @@ } ], "default": null, - "description": "Filter by run ID. Returns all checkpoints saved by the run.", - "examples": [ - "k4q95w5" + "description": "Last recorded use in ISO 8601 format, or null if unavailable. Updates may be delayed.", + "title": "Last Used At" + }, + "owner": { + "anyOf": [ + { + "$ref": "#/components/schemas/APIKeyOwnerV1" + }, + { + "type": "null" + } ], - "title": "Run Id" + "default": null, + "description": "The user who owns the API key. Only present for personal API keys." + } + }, + "required": [ + "prefix", + "type", + "created_at" + ], + "title": "APIKeyInfoV1", + "type": "object" + }, + "APIKeyOwnerV1": { + "description": "The user who owns a personal API key.", + "properties": { + "user_id": { + "description": "Unique identifier for the user", + "title": "User Id", + "type": "string" }, - "base_model": { + "email": { "anyOf": [ { "type": "string" @@ -22844,13 +27435,10 @@ } ], "default": null, - "description": "Filter by base model. Returns checkpoints across the caller's runs of this base model.", - "examples": [ - "Qwen/Qwen3-8B" - ], - "title": "Base Model" + "description": "Email address of the user", + "title": "Email" }, - "checkpoint_path": { + "name": { "anyOf": [ { "type": "string" @@ -22860,123 +27448,97 @@ } ], "default": null, - "description": "bt:// URI of a Loops checkpoint. Form: bt://loops:/(weights|sampler_weights)/.", - "examples": [ - "bt://loops:k4q95w5/sampler_weights/step-100" - ], - "title": "Checkpoint Path" + "description": "Display name of the user", + "title": "Name" } }, - "title": "ListLoopsCheckpointsQueryParamsV1", + "required": [ + "user_id" + ], + "title": "APIKeyOwnerV1", "type": "object" }, - "ValidateLoopsCheckpointRequestV1": { - "description": "Request body for ``POST /v1/loops/checkpoints/validate``.", + "APIKeysV1": { + "description": "A list of API keys.", "properties": { - "checkpoint_path": { - "description": "bt:// URI of a sampler checkpoint. Form: bt://loops:/sampler_weights/.", - "examples": [ - "bt://loops:k4q95w5/sampler_weights/step-100" - ], - "title": "Checkpoint Path", - "type": "string" + "keys": { + "description": "A list of API key information", + "items": { + "$ref": "#/components/schemas/APIKeyInfoV1" + }, + "title": "Keys", + "type": "array" } }, "required": [ - "checkpoint_path" + "keys" ], - "title": "ValidateLoopsCheckpointRequestV1", - "type": "object" - }, - "ValidateLoopsCheckpointResponseV1": { - "description": "Response for ``POST /v1/loops/checkpoints/validate``. Empty on success;\ninaccessible or malformed paths raise 400.", - "properties": {}, - "title": "ValidateLoopsCheckpointResponseV1", + "title": "APIKeysV1", "type": "object" }, - "LoopsCheckpointFilesResponseV1": { - "description": "Response with presigned URLs for files under a Loops checkpoint.", + "APIKeysRequestV1": { "properties": { - "presigned_urls": { - "description": "List of presigned URLs for checkpoint files.", - "items": { - "$ref": "#/components/schemas/CheckpointFile" - }, - "title": "Presigned Urls", - "type": "array" - }, - "next_page_token": { + "type": { "anyOf": [ { - "type": "integer" + "$ref": "#/components/schemas/APIKeyCategory" }, { "type": "null" } ], "default": null, - "description": "Token to use for fetching the next page of results. None when there are no more results.", - "title": "Next Page Token" - }, - "total_count": { - "description": "Total number of checkpoint files available.", - "title": "Total Count", - "type": "integer" - } - }, - "required": [ - "presigned_urls", - "total_count" - ], - "title": "LoopsCheckpointFilesResponseV1", - "type": "object" - }, - "GetLoopsCheckpointFilesRequestV1": { - "description": "Pagination params for ``GET /v1/loops/checkpoints//files``.", - "properties": { - "page_size": { - "default": 1000, - "description": "Max files per page (default 1000).", - "minimum": 1, - "title": "Page Size", - "type": "integer" + "description": "Filter by API key type" }, - "page_token": { - "default": 0, - "description": "Offset into the file list (default 0).", - "minimum": 0, - "title": "Page Token", - "type": "integer" + "created_by_me": { + "default": false, + "description": "Return only keys created by the authenticated user", + "title": "Created By Me", + "type": "boolean" } }, - "title": "GetLoopsCheckpointFilesRequestV1", + "title": "APIKeysRequestV1", "type": "object" }, - "LoopsDeploymentStatusV1": { - "description": "Latest deployment status for a Loops deployment.", + "APIKeyTombstoneV1": { + "description": "An API key tombstone.", "properties": { - "name": { - "$ref": "#/components/schemas/Name", - "description": "Latest status of the Loops deployment." + "prefix": { + "description": "Unique prefix of the API key", + "title": "Prefix", + "type": "string" } }, "required": [ - "name" + "prefix" ], - "title": "LoopsDeploymentStatusV1", + "title": "APIKeyTombstoneV1", "type": "object" }, - "LoopsDeploymentV1": { - "description": "A Loops deployment \u2014 the long-lived run + sampler pair owned by a user.\n\nThe deployment's current sampler is included inline. The full list of\nsamplers visible to the caller (across all deployments) lives at\n``GET /v1/loops/samplers``.", + "LimitTypeV1": { + "enum": [ + "REQUEST", + "TOKEN", + "CONCURRENT_REQUEST", + "UNCACHED_INPUT_TOKEN", + "OUTPUT_TOKEN" + ], + "title": "LimitTypeV1", + "type": "string" + }, + "ModelAPIOrgDetailsV1": { + "description": "Workspace-specific state for a Model API.", "properties": { - "id": { - "description": "The Loops deployment ID.", - "title": "Id", + "added_at": { + "description": "When the workspace first added this Model API.", + "format": "date-time", + "title": "Added At", "type": "string" }, - "active_run_id": { + "last_used_at": { "anyOf": [ { + "format": "date-time", "type": "string" }, { @@ -22984,10 +27546,41 @@ } ], "default": null, - "description": "The ID of the run currently active on this deployment, if any. Null when the deployment's runs have been marked inactive (e.g. scale-to-zero) without a successor.", - "title": "Active Run Id" + "description": "When the workspace last invoked this Model API. Null if the workspace has never invoked it.", + "title": "Last Used At" + } + }, + "required": [ + "added_at" + ], + "title": "ModelAPIOrgDetailsV1", + "type": "object" + }, + "ModelAPIV1": { + "description": "A Model API catalog row, optionally enriched with workspace-specific state.", + "properties": { + "name": { + "description": "Identifier of the Model API. Stable, URL-safe slug used as the public identifier.", + "examples": [ + "llama-3-3-70b-instruct" + ], + "title": "Name", + "type": "string" }, - "latest_run_id": { + "display_name": { + "description": "Human-readable name of the Model API.", + "examples": [ + "Llama 3.3 70B Instruct" + ], + "title": "Display Name", + "type": "string" + }, + "description": { + "description": "Description of the Model API.", + "title": "Description", + "type": "string" + }, + "model_family": { "anyOf": [ { "type": "string" @@ -22997,178 +27590,181 @@ } ], "default": null, - "description": "The ID of the most recent run on this deployment, active or not, so idle deployments still expose a usable run handle. Null only if the deployment has no runs.", - "title": "Latest Run Id" - }, - "base_model": { - "description": "The HuggingFace base model the deployment is fine-tuning.", - "title": "Base Model", - "type": "string" + "description": "Family the underlying model belongs to.", + "examples": [ + "META", + "DEEPSEEK", + "QWEN" + ], + "title": "Model Family" }, - "base_url": { - "description": "The run's base URL.", - "title": "Base Url", + "release_date": { + "description": "Date the Model API was made available.", + "format": "date", + "title": "Release Date", "type": "string" }, - "status": { - "$ref": "#/components/schemas/LoopsDeploymentStatusV1", - "description": "Latest deployment status." - }, - "user": { - "$ref": "#/components/schemas/UserV1", - "description": "The user who owns the Loops deployment." - }, - "created_at": { - "description": "Time the deployment was created in ISO 8601 format.", - "format": "date-time", - "title": "Created At", + "invoke_url": { + "description": "Base URL for invoking the Model API. OpenAI-shaped routes (e.g. /v1/chat/completions) live underneath this host.", + "examples": [ + "https://inference.baseten.co" + ], + "title": "Invoke Url", "type": "string" }, - "availability_model": { - "$ref": "#/components/schemas/V1AvailabilityModel", - "default": "dedicated", - "description": "Capacity the trainer was scheduled on." - }, - "instance_type": { - "$ref": "#/components/schemas/InstanceTypeV1", - "description": "Instance type backing the trainer." - }, - "node_count": { - "default": 1, - "description": "Number of nodes backing the trainer.", - "title": "Node Count", + "context_length": { + "description": "The model's context window length, in tokens.", + "examples": [ + 8192 + ], + "title": "Context Length", "type": "integer" }, - "sampler": { + "cost_per_million_input_tokens": { "anyOf": [ { - "$ref": "#/components/schemas/LoopsSamplerV1" + "type": "number" + }, + { + "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", + "type": "string" }, { "type": "null" } ], - "default": null, - "description": "The sampler bound to this deployment." - } - }, - "required": [ - "id", - "base_model", - "base_url", - "status", - "user", - "created_at", - "instance_type" - ], - "title": "LoopsDeploymentV1", - "type": "object" - }, - "Name": { - "enum": [ - "CREATED", - "DEPLOYING", - "RUNNING", - "SCALED_TO_ZERO", - "FAILED", - "STOPPED", - "PREEMPTED" - ], - "title": "LoopsDeploymentStatus", - "type": "string" - }, - "ListLoopsDeploymentsResponseV1": { - "description": "Response for ``GET /v1/loops/deployments``.\n\nDefaults to the caller's own; pass ``?scope=org`` to list every deployment in\nthe caller's organization. Returns every deployment regardless of status;\nclients filter terminal states.", - "properties": { - "deployments": { - "description": "Active Loops deployments.", + "description": "Effective cost per million input tokens, in dollars. Null when pricing is unavailable.", + "examples": [ + "0.13" + ], + "title": "Cost Per Million Input Tokens" + }, + "cost_per_million_output_tokens": { + "anyOf": [ + { + "type": "number" + }, + { + "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Effective cost per million output tokens, in dollars. Null when pricing is unavailable.", + "examples": [ + "0.50" + ], + "title": "Cost Per Million Output Tokens" + }, + "rate_limits": { + "description": "Rate limits in effect for the workspace. Workspace-specific overrides are returned when the workspace has added this Model API and configured them; otherwise the catalog default rate limits are returned.", "items": { - "$ref": "#/components/schemas/LoopsDeploymentV1" + "$ref": "#/components/schemas/RateLimitV1" }, - "title": "Deployments", + "title": "Rate Limits", "type": "array" - } - }, - "required": [ - "deployments" - ], - "title": "ListLoopsDeploymentsResponseV1", - "type": "object" - }, - "ListLoopsDeploymentsRequestV1": { - "description": "Query-string filters for ``GET /v1/loops/deployments``.", - "properties": { - "scope": { + }, + "org_details": { "anyOf": [ { - "type": "string" + "$ref": "#/components/schemas/ModelAPIOrgDetailsV1" }, { "type": "null" } ], "default": null, - "description": "Defaults to the caller's own deployments; pass 'org' to list every deployment in the caller's organization.", - "examples": [ - "org" - ], - "title": "Scope" + "description": "Workspace-specific state. Null when the workspace has not added this Model API." } }, - "title": "ListLoopsDeploymentsRequestV1", + "required": [ + "name", + "display_name", + "description", + "release_date", + "invoke_url", + "context_length", + "cost_per_million_input_tokens", + "cost_per_million_output_tokens", + "rate_limits" + ], + "title": "ModelAPIV1", "type": "object" }, - "DeactivateLoopsDeploymentResponseV1": { - "description": "Response for ``POST /v1/loops/deployments//deactivate``.", + "RateLimitUnitV1": { + "enum": [ + "SECOND", + "MINUTE" + ], + "title": "RateLimitUnitV1", + "type": "string" + }, + "RateLimitV1": { "properties": { - "id": { - "description": "The deactivated Loops deployment ID.", - "title": "Id", - "type": "string" + "type": { + "$ref": "#/components/schemas/LimitTypeV1", + "description": "The type of the rate limit", + "examples": [ + "TOKEN", + "REQUEST" + ] }, - "base_model": { - "description": "The base model whose Loops deployment was deactivated.", - "title": "Base Model", - "type": "string" + "unit": { + "$ref": "#/components/schemas/RateLimitUnitV1", + "description": "The unit of the rate limit", + "examples": [ + "SECOND", + "MINUTE" + ] }, - "user": { - "$ref": "#/components/schemas/UserV1", - "description": "The user who owned the Loops deployment." + "threshold": { + "description": "The threshold for the rate limit", + "examples": [ + 1000, + 50000 + ], + "minimum": 0, + "title": "Threshold", + "type": "integer" } }, "required": [ - "id", - "base_model", - "user" + "type", + "unit", + "threshold" ], - "title": "DeactivateLoopsDeploymentResponseV1", + "title": "RateLimitV1", "type": "object" }, - "GetLoopsDeploymentResponseV1": { - "description": "Response for ``GET /v1/loops/deployments/``.", + "ModelAPIsResponseV1": { + "description": "Page of Model APIs visible to the caller.", "properties": { - "deployment": { - "$ref": "#/components/schemas/LoopsDeploymentV1", - "description": "The Loops deployment." + "items": { + "description": "Items in this page.", + "items": { + "$ref": "#/components/schemas/ModelAPIV1" + }, + "title": "Items", + "type": "array" + }, + "pagination": { + "$ref": "#/components/schemas/PaginationResponseV1", + "description": "Pagination metadata for the page." } }, "required": [ - "deployment" + "items", + "pagination" ], - "title": "GetLoopsDeploymentResponseV1", + "title": "ModelAPIsResponseV1", "type": "object" }, - "LoopsDebugArchiveFilesResponseV1": { - "description": "Response with presigned URLs for a Loops deployment's debug archive.", + "ModelAPIsRequestV1": { + "description": "Query-string filters for ``GET /v1/model_apis``.", "properties": { - "presigned_urls": { - "items": { - "$ref": "#/components/schemas/CheckpointFile" - }, - "title": "Presigned Urls", - "type": "array" - }, - "next_page_token": { + "cursor": { "anyOf": [ { "type": "string" @@ -23178,629 +27774,491 @@ } ], "default": null, - "title": "Next Page Token" + "description": "Opaque cursor returned by a previous page. Omit to fetch the first page.", + "title": "Cursor" + }, + "limit": { + "default": 100, + "description": "Maximum number of items to return.", + "maximum": 1000, + "minimum": 1, + "title": "Limit", + "type": "integer" + }, + "added_only": { + "default": false, + "description": "When true, restrict the result to Model APIs the workspace has added. Defaults to the full visible catalog.", + "title": "Added Only", + "type": "boolean" } }, - "required": [ - "presigned_urls" - ], - "title": "LoopsDebugArchiveFilesResponseV1", + "title": "ModelAPIsRequestV1", "type": "object" }, - "GetLoopsDebugArchiveFilesRequestV1": { - "description": "Pagination params for a Loops deployment debug archive.", + "ModelApisUsageBucketV1": { + "description": "One time bucket and the usage recorded in it.", "properties": { - "page_size": { - "default": 1000, - "description": "Max files per page (default and maximum 1000).", - "maximum": 1000, - "minimum": 1, - "title": "Page Size", - "type": "integer" + "start_time": { + "description": "Start of the bucket (inclusive), UTC", + "format": "date-time", + "title": "Start Time", + "type": "string" }, - "page_token": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "description": "Opaque token for the next page.", - "title": "Page Token" + "end_time": { + "description": "End of the bucket (exclusive), UTC", + "format": "date-time", + "title": "End Time", + "type": "string" + }, + "results": { + "description": "Usage totals for this bucket, ordered by total tokens descending", + "items": { + "$ref": "#/components/schemas/ModelApisUsageResultV1" + }, + "title": "Results", + "type": "array" } }, - "title": "GetLoopsDebugArchiveFilesRequestV1", + "required": [ + "start_time", + "end_time" + ], + "title": "ModelApisUsageBucketV1", "type": "object" }, - "GetLoopsDeploymentMetricsRequestV1": { - "description": "Time-range request for trainer deployment metrics.", + "ModelApisUsageResultV1": { + "description": "Usage totals for one combination of the requested dimensions, within one bucket.", "properties": { - "end_epoch_millis": { + "api_key_prefix": { "anyOf": [ { - "type": "integer" + "type": "string" }, { "type": "null" } ], "default": null, - "description": "Epoch millis to end fetching metrics.", - "title": "End Epoch Millis" + "description": "Prefix of the API key the usage is attributed to. Null when not grouping by api_key or when the request was not authenticated with an API key.", + "title": "Api Key Prefix" }, - "start_epoch_millis": { + "user_id": { "anyOf": [ { - "type": "integer" + "type": "string" }, { "type": "null" } ], "default": null, - "description": "Epoch millis to start fetching metrics.", - "title": "Start Epoch Millis" + "description": "User the usage is attributed to. Null when not grouping by user or when the credential is not user-scoped.", + "title": "User Id" }, - "step_seconds": { + "model": { "anyOf": [ { - "type": "integer" + "type": "string" }, { "type": "null" } ], "default": null, - "description": "Resolution of the returned series, in seconds. When omitted, a step is derived from the time range so large windows return fewer points.", - "title": "Step Seconds" + "description": "Model that served the usage. Null when not grouping by model.", + "title": "Model" }, - "time_divisor_seconds": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null, - "description": "Unit of time for request-volume metrics, in seconds (e.g. 60 for requests/minute). Defaults to per-second.", - "title": "Time Divisor Seconds" - } - }, - "title": "GetLoopsDeploymentMetricsRequestV1", - "type": "object" - }, - "InferenceVolumeByStatusDatapointV1": { - "description": "Request rate split by HTTP response code class.", - "properties": { - "timestamp": { - "description": "ISO 8601 timestamp.", - "format": "date-time", - "title": "Timestamp", - "type": "string" + "input_tokens": { + "description": "Total input tokens, cached and uncached combined.", + "title": "Input Tokens", + "type": "integer" }, - "status_2xx": { - "description": "2xx requests per second.", - "title": "Status 2Xx", - "type": "number" + "cached_input_tokens": { + "description": "Input tokens served from the prompt cache.", + "title": "Cached Input Tokens", + "type": "integer" }, - "status_4xx": { - "description": "4xx requests per second.", - "title": "Status 4Xx", - "type": "number" + "uncached_input_tokens": { + "description": "Input tokens not served from the prompt cache.", + "title": "Uncached Input Tokens", + "type": "integer" }, - "status_5xx": { - "description": "5xx requests per second.", - "title": "Status 5Xx", - "type": "number" + "output_tokens": { + "description": "Total output tokens.", + "title": "Output Tokens", + "type": "integer" + }, + "request_count": { + "description": "Total number of requests.", + "title": "Request Count", + "type": "integer" } }, "required": [ - "timestamp", - "status_2xx", - "status_4xx", - "status_5xx" + "input_tokens", + "cached_input_tokens", + "uncached_input_tokens", + "output_tokens", + "request_count" ], - "title": "InferenceVolumeByStatusDatapointV1", + "title": "ModelApisUsageResultV1", "type": "object" }, - "LoopsDeploymentMetricsV1": { - "description": "Metrics for a trainer (Loops) deployment.\n\nService-level fields summarize HTTP traffic into the trainer pods (the\nKnative queue-proxy is the source). Compute fields are the leader-pod\naggregate; ``per_node_metrics`` carries the full multinode breakdown.", + "ModelApisUsageResponseV1": { + "description": "A page of Model APIs token usage: contiguous time buckets, ordered oldest first.", "properties": { - "inference_volume": { - "description": "Number of inference requests per unit time (requests per second).", - "items": { - "$ref": "#/components/schemas/TrainingJobMetricV1" - }, - "title": "Inference Volume", - "type": "array" - }, - "concurrent_requests": { - "description": "Number of in-progress concurrent inference requests. Source: the queue-proxy ``revision_queue_depth`` gauge on ``http-usermetric``.", - "items": { - "$ref": "#/components/schemas/TrainingJobMetricV1" - }, - "title": "Concurrent Requests", - "type": "array" - }, - "response_time_stats": { - "description": "Percentiles of the response time distribution.", - "items": { - "$ref": "#/components/schemas/ResponseTimeDatapointV1" - }, - "title": "Response Time Stats", - "type": "array" - }, - "inference_volume_by_status": { - "description": "Request rate split by response code class.", - "items": { - "$ref": "#/components/schemas/InferenceVolumeByStatusDatapointV1" - }, - "title": "Inference Volume By Status", - "type": "array" - }, - "gpu_memory_usage_bytes": { - "additionalProperties": { - "items": { - "$ref": "#/components/schemas/TrainingJobMetricV1" - }, - "type": "array" - }, - "description": "Leader-pod GPU memory bytes per GPU rank.", - "title": "Gpu Memory Usage Bytes", - "type": "object" - }, - "gpu_utilization": { - "additionalProperties": { - "items": { - "$ref": "#/components/schemas/TrainingJobMetricV1" - }, - "type": "array" - }, - "description": "Leader-pod fractional GPU utilization per GPU rank.", - "title": "Gpu Utilization", - "type": "object" - }, - "cpu_usage": { - "description": "Leader-pod CPU usage in cores.", - "items": { - "$ref": "#/components/schemas/TrainingJobMetricV1" - }, - "title": "Cpu Usage", - "type": "array" - }, - "cpu_memory_usage_bytes": { - "description": "Leader-pod CPU memory usage bytes.", + "items": { + "description": "Items in this page.", "items": { - "$ref": "#/components/schemas/TrainingJobMetricV1" + "$ref": "#/components/schemas/ModelApisUsageBucketV1" }, - "title": "Cpu Memory Usage Bytes", + "title": "Items", "type": "array" }, - "ephemeral_storage": { - "$ref": "#/components/schemas/StorageMetricsV1", - "description": "Leader-pod ephemeral storage usage." - }, - "per_node_metrics": { - "description": "Per-node compute breakdown for multinode trainer deployments.", - "items": { - "$ref": "#/components/schemas/LoopsDeploymentNodeMetricsV1" - }, - "title": "Per Node Metrics", - "type": "array" + "pagination": { + "$ref": "#/components/schemas/PaginationResponseV1", + "description": "Pagination metadata for the page." } }, "required": [ - "inference_volume", - "concurrent_requests", - "response_time_stats", - "inference_volume_by_status", - "gpu_memory_usage_bytes", - "gpu_utilization", - "cpu_usage", - "cpu_memory_usage_bytes", - "ephemeral_storage", - "per_node_metrics" + "items", + "pagination" ], - "title": "LoopsDeploymentMetricsV1", + "title": "ModelApisUsageResponseV1", "type": "object" }, - "LoopsDeploymentNodeMetricsV1": { - "description": "Per-node compute metrics for a multinode trainer deployment.", + "BucketWidth": { + "enum": [ + "1m", + "1h", + "1d" + ], + "title": "BucketWidth", + "type": "string" + }, + "UsageDimensionV1": { + "enum": [ + "api_key", + "user", + "model" + ], + "title": "UsageDimensionV1", + "type": "string" + }, + "ModelApisUsageRequestV1": { "properties": { - "node_id": { - "description": "Identifier for the node.", - "title": "Node Id", - "type": "string" - }, - "gpu_memory_usage_bytes": { - "additionalProperties": { - "items": { - "$ref": "#/components/schemas/TrainingJobMetricV1" + "start_time": { + "anyOf": [ + { + "format": "date-time", + "type": "string" }, - "type": "array" - }, - "description": "GPU memory usage bytes per GPU rank.", - "title": "Gpu Memory Usage Bytes", - "type": "object" + { + "type": "null" + } + ], + "default": null, + "description": "Start of the query range (ISO 8601, UTC), inclusive. Snapped down to the start of its bucket. Required on the first page, and ignored when you pass a cursor.", + "title": "Start Time" }, - "gpu_utilization": { - "additionalProperties": { - "items": { - "$ref": "#/components/schemas/TrainingJobMetricV1" + "end_time": { + "anyOf": [ + { + "format": "date-time", + "type": "string" }, - "type": "array" - }, - "description": "Fractional GPU utilization per GPU rank.", - "title": "Gpu Utilization", - "type": "object" + { + "type": "null" + } + ], + "default": null, + "description": "End of the query range (ISO 8601, UTC), exclusive. Defaults to the current time.", + "title": "End Time" }, - "cpu_usage": { - "description": "CPU usage in cores.", + "bucket_width": { + "$ref": "#/components/schemas/BucketWidth", + "default": "1d", + "description": "Width of each time bucket: 1m, 1h, or 1d. Defaults to 1d." + }, + "group_by": { + "description": "Dimensions to break usage down by, repeated once per dimension: api_key, user, model. Defaults to model.", "items": { - "$ref": "#/components/schemas/TrainingJobMetricV1" + "$ref": "#/components/schemas/UsageDimensionV1" }, - "title": "Cpu Usage", + "title": "Group By", "type": "array" }, - "cpu_memory_usage_bytes": { - "description": "CPU memory usage bytes.", + "api_keys": { + "description": "Return only usage for these API key prefixes, repeated once per prefix.", "items": { - "$ref": "#/components/schemas/TrainingJobMetricV1" + "type": "string" }, - "title": "Cpu Memory Usage Bytes", + "title": "Api Keys", "type": "array" }, - "ephemeral_storage": { - "$ref": "#/components/schemas/StorageMetricsV1", - "description": "Ephemeral storage usage." - } - }, - "required": [ - "node_id", - "gpu_memory_usage_bytes", - "gpu_utilization", - "cpu_usage", - "cpu_memory_usage_bytes", - "ephemeral_storage" - ], - "title": "LoopsDeploymentNodeMetricsV1", - "type": "object" - }, - "ResponseTimeDatapointV1": { - "description": "Latency quantile datapoint. Values are reported in milliseconds.", - "properties": { - "timestamp": { - "description": "ISO 8601 timestamp.", - "format": "date-time", - "title": "Timestamp", - "type": "string" + "user_ids": { + "description": "Return only usage attributed to these user IDs, repeated once per ID.", + "items": { + "type": "string" + }, + "title": "User Ids", + "type": "array" }, - "p50": { + "models": { + "description": "Return only usage for these models, repeated once per model.", + "items": { + "type": "string" + }, + "title": "Models", + "type": "array" + }, + "limit": { "anyOf": [ { - "type": "number" + "type": "integer" }, { "type": "null" } ], "default": null, - "description": "50th percentile request latency (milliseconds).", - "title": "P50" + "description": "Number of time buckets to return. Defaults and maximums depend on bucket_width: 1d defaults to 7 and allows 31, 1h defaults to 24 and allows 168, 1m defaults to 60 and allows 1440.", + "title": "Limit" }, - "p95": { + "cursor": { "anyOf": [ { - "type": "number" + "type": "string" }, { "type": "null" } ], "default": null, - "description": "95th percentile request latency (milliseconds).", - "title": "P95" + "description": "Opaque cursor from the pagination.cursor field of a previous response", + "title": "Cursor" + } + }, + "title": "ModelApisUsageRequestV1", + "type": "object" + }, + "CreateLLMModelRequestV1": { + "description": "A request to create a BIS-LLM model", + "properties": { + "resources": { + "additionalProperties": true, + "description": "Resources allocated to the model", + "title": "Resources", + "type": "object" }, - "p99": { + "region": { "anyOf": [ { - "type": "number" + "type": "string" }, { "type": "null" } ], "default": null, - "description": "99th percentile request latency (milliseconds).", - "title": "P99" - } - }, - "required": [ - "timestamp" - ], - "title": "ResponseTimeDatapointV1", - "type": "object" - }, - "GetLoopsDeploymentMetricsResponseV1": { - "description": "Response for ``POST /v1/loops/deployments//metrics``.", - "properties": { - "deployment_id": { - "description": "The trainer deployment ID.", - "title": "Deployment Id", - "type": "string" + "description": "Region in which to deploy the model", + "title": "Region" }, - "metrics": { - "$ref": "#/components/schemas/LoopsDeploymentMetricsV1", - "description": "Metrics for the deployment." - } - }, - "required": [ - "deployment_id", - "metrics" - ], - "title": "GetLoopsDeploymentMetricsResponseV1", - "type": "object" - }, - "GetLoopsDeploymentLogsRequestV1": { - "description": "Query parameters for fetching a Loops deployment's logs.", - "properties": { - "start_epoch_millis": { + "llm_version": { "anyOf": [ { - "type": "integer" + "type": "string" }, { "type": "null" } ], "default": null, - "description": "Epoch milliseconds at which to start fetching logs. Defaults to 30 minutes before the end. The window from start to end must not exceed 7 days.", - "title": "Start Epoch Millis" + "description": "Version of the helm chart to use.", + "title": "Llm Version" }, - "end_epoch_millis": { + "llm_config": { + "additionalProperties": true, + "description": "Configuration specific to the LLM model", + "title": "Llm Config", + "type": "object" + }, + "environment_variables": { + "additionalProperties": true, + "description": "Environment variables for the model", + "title": "Environment Variables", + "type": "object" + }, + "model_metadata": { "anyOf": [ { - "type": "integer" + "additionalProperties": true, + "type": "object" }, { "type": "null" } ], "default": null, - "description": "Epoch milliseconds at which to stop fetching logs. Defaults to the current time.", - "title": "End Epoch Millis" + "description": "Model metadata persisted into model_config", + "title": "Model Metadata" }, - "direction": { + "autoscaling_settings": { "anyOf": [ { - "$ref": "#/components/schemas/SortOrderV1" + "$ref": "#/components/schemas/UpdateAutoscalingSettingsV1" }, { "type": "null" } ], "default": null, - "description": "Sort order for logs" + "description": "Autoscaling settings for the model", + "examples": [ + { + "autoscaling_window": 600, + "concurrency_target": null, + "max_replica": 5, + "max_scale_down_rate": null, + "min_replica": 1, + "scale_down_delay": 300, + "target_in_flight_tokens": null, + "target_utilization_percentage": null + } + ] }, - "limit": { + "additional_autoscaling_config": { "anyOf": [ { - "maximum": 1000, - "minimum": 1, - "type": "integer" + "additionalProperties": true, + "type": "object" }, { "type": "null" } ], - "default": 500, - "description": "Limit of logs to fetch in a single request", - "title": "Limit" + "default": null, + "description": "Additional autoscaling configuration (e.g. target in-flight tokens)", + "examples": [ + { + "metrics": [ + { + "name": "in_flight_tokens", + "target": 40000 + } + ] + } + ], + "title": "Additional Autoscaling Config" }, - "min_level": { + "metadata": { "anyOf": [ { - "$ref": "#/components/schemas/LogLevelV1" + "additionalProperties": true, + "type": "object" }, { "type": "null" } ], "default": null, - "description": "Minimum log severity to include. Omit to return all log lines, including lines that have no level. Any explicit value returns lines at or above that severity and drops lines without a level." - } - }, - "title": "GetLoopsDeploymentLogsRequestV1", - "type": "object" - }, - "TeamTrainingGpuCapacityItemV1": { - "description": "Per-team GPU capacity and current usage for one GPU type.", - "properties": { - "team_id": { - "description": "Team identifier", - "title": "Team Id", - "type": "string" - }, - "team_name": { - "description": "Team name", - "title": "Team Name", - "type": "string" - }, - "gpu_type": { - "description": "GPU type identifier (e.g. H100, A100-40GB)", - "title": "Gpu Type", - "type": "string" - }, - "baseline": { - "description": "Baseline GPU allocation for the team. 0 if not configured.", - "title": "Baseline", - "type": "integer" - }, - "limit": { - "description": "Maximum concurrent GPUs of this type for this team", - "title": "Limit", - "type": "integer" - }, - "usage_count": { - "description": "GPUs currently in use by the team's active training jobs", - "title": "Usage Count", - "type": "integer" - }, - "dedicated_usage_count": { - "default": 0, - "description": "Portion of usage_count from dedicated (on-demand) jobs.", - "title": "Dedicated Usage Count", - "type": "integer" - }, - "spot_usage_count": { - "default": 0, - "description": "Portion of usage_count from spot jobs.", - "title": "Spot Usage Count", - "type": "integer" - } - }, - "required": [ - "team_id", - "team_name", - "gpu_type", - "baseline", - "limit", - "usage_count" - ], - "title": "TeamTrainingGpuCapacityItemV1", - "type": "object" - }, - "TrainingGpuCapacityItemV1": { - "description": "GPU capacity and current usage for one GPU type.", - "properties": { - "gpu_type": { - "description": "GPU type identifier (e.g. H100, A100-40GB)", - "title": "Gpu Type", - "type": "string" - }, - "baseline": { - "description": "Baseline GPU allocation; jobs below this threshold are expected to run immediately. 0 if not configured.", - "title": "Baseline", - "type": "integer" - }, - "limit": { - "description": "Maximum concurrent GPUs of this type for this org", - "title": "Limit", - "type": "integer" - }, - "usage_count": { - "description": "GPUs currently in use by active training jobs", - "title": "Usage Count", - "type": "integer" - }, - "dedicated_usage_count": { - "default": 0, - "description": "Portion of usage_count from dedicated (on-demand) jobs, which run against the baseline.", - "title": "Dedicated Usage Count", - "type": "integer" + "description": "User-defined metadata for the deployment", + "examples": [ + { + "environment": "production", + "git_sha": "abc123" + } + ], + "title": "Metadata" }, - "spot_usage_count": { - "default": 0, - "description": "Portion of usage_count from spot jobs, which burst into the peak and may push usage above the limit.", - "title": "Spot Usage Count", - "type": "integer" - } - }, - "required": [ - "gpu_type", - "baseline", - "limit", - "usage_count" - ], - "title": "TrainingGpuCapacityItemV1", - "type": "object" - }, - "GetTrainingGpuCapacityResponseV1": { - "description": "Response for the training GPU capacity endpoint.", - "properties": { - "gpu_capacities": { - "description": "Org-level GPU capacity limits and current usage per GPU type", - "items": { - "$ref": "#/components/schemas/TrainingGpuCapacityItemV1" - }, - "title": "Gpu Capacities", - "type": "array" + "weights": { + "anyOf": [ + { + "items": { + "additionalProperties": true, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Weight configurations for BDN model weight distribution", + "examples": [ + [ + { + "mount_location": "/models/base", + "source": "hf://meta-llama/Llama-3-8B" + } + ] + ], + "title": "Weights" }, - "team_gpu_capacities": { - "description": "Per-team GPU capacity limits and current usage per GPU type", - "items": { - "$ref": "#/components/schemas/TeamTrainingGpuCapacityItemV1" - }, - "title": "Team Gpu Capacities", - "type": "array" + "name": { + "description": "Name of the model", + "title": "Name", + "type": "string" } }, "required": [ - "gpu_capacities" + "resources", + "name" ], - "title": "GetTrainingGpuCapacityResponseV1", + "title": "CreateLLMModelRequestV1", "type": "object" }, - "PatchTeamTrainingGpuCapacityRequestV1": { - "description": "A request to set the GPU capacity ceiling for a (team, gpu_type) pair.\n\nCreates the limit if one doesn't already exist for this team and GPU type,\notherwise updates it in place.", + "LLMModelHandleV1": { + "description": "Handle for a BIS-LLM model deployment.", "properties": { - "team_id": { - "description": "Team identifier", - "title": "Team Id", + "model_id": { + "description": "Unique identifier of the model", + "title": "Model Id", "type": "string" }, - "gpu_type": { - "description": "GPU type identifier (e.g. H100, A100-40GB)", - "title": "Gpu Type", + "version_id": { + "description": "Unique identifier of the model version", + "title": "Version Id", "type": "string" }, - "max_gpus": { - "description": "Max concurrent GPUs of this type the team may use", - "examples": [ - 8, - 16, - 32 + "hostname": { + "description": "Hostname used to invoke the model", + "title": "Hostname", + "type": "string" + }, + "instance_type_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } ], - "title": "Max Gpus", - "type": "integer" - } - }, - "required": [ - "team_id", - "gpu_type", - "max_gpus" - ], - "title": "PatchTeamTrainingGpuCapacityRequestV1", - "type": "object" - }, - "PatchTeamTrainingGpuCapacityResponseV1": { - "description": "Response for setting a team's GPU capacity ceiling.", - "properties": { - "team_gpu_capacity": { - "$ref": "#/components/schemas/TeamTrainingGpuCapacityItemV1", - "description": "The updated per-team GPU capacity limit" + "default": null, + "description": "Name of the instance type the model deployment is running on", + "title": "Instance Type Name" } }, "required": [ - "team_gpu_capacity" + "model_id", + "version_id", + "hostname" ], - "title": "PatchTeamTrainingGpuCapacityResponseV1", + "title": "LLMModelHandleV1", "type": "object" }, - "ActiveJobAtSubmitV1": { - "description": "One other job in the same (org, gpu_type) pool that was holding GPU\ncapacity at the moment the target was submitted.", + "CreateLLMModelVersionRequestV1": { + "description": "A request to create a BIS-LLM model version", "properties": { - "training_job_id": { - "description": "Hashid of the other training job", - "title": "Training Job Id", - "type": "string" + "resources": { + "additionalProperties": true, + "description": "Resources allocated to the model", + "title": "Resources", + "type": "object" }, - "training_job_name": { + "region": { "anyOf": [ { "type": "string" @@ -23810,150 +28268,200 @@ } ], "default": null, - "description": "Other job's name", - "title": "Training Job Name" + "description": "Region in which to deploy the model", + "title": "Region" }, - "instance_type_name": { - "description": "Instance type of the other job", - "title": "Instance Type Name", - "type": "string" + "llm_version": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Version of the helm chart to use.", + "title": "Llm Version" }, - "total_gpus": { - "description": "gpu_count * effective_node_count", - "title": "Total Gpus", - "type": "integer" + "llm_config": { + "additionalProperties": true, + "description": "Configuration specific to the LLM model", + "title": "Llm Config", + "type": "object" }, - "workload_plane_name": { - "description": "Workload plane the other job was on", - "title": "Workload Plane Name", - "type": "string" + "environment_variables": { + "additionalProperties": true, + "description": "Environment variables for the model", + "title": "Environment Variables", + "type": "object" }, - "status_at_submit": { - "description": "Other job's status as of submitted_at (one of ACTIVE_STATES)", - "title": "Status At Submit", - "type": "string" + "model_metadata": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Model metadata persisted into model_config", + "title": "Model Metadata" }, - "status_set_at": { - "description": "When that status was set", - "format": "date-time", - "title": "Status Set At", - "type": "string" - } - }, - "required": [ - "training_job_id", - "instance_type_name", - "total_gpus", - "workload_plane_name", - "status_at_submit", - "status_set_at" - ], - "title": "ActiveJobAtSubmitV1", - "type": "object" - }, - "CapacityAtSubmitV1": { - "description": "A GPU capacity row as it stands now, with ``last_modified`` so callers\ncan judge whether the value matches what the dequeue gate saw at submit\ntime. Capacity rows are not historicized: edits overwrite in place. Compare\n``last_modified`` against the response's ``submitted_at`` \u2014 if it's later,\nthe value may have changed.", - "properties": { - "gpu_type": { - "description": "GPU type identifier (e.g. H100, A100-40GB)", - "title": "Gpu Type", - "type": "string" + "autoscaling_settings": { + "anyOf": [ + { + "$ref": "#/components/schemas/UpdateAutoscalingSettingsV1" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Autoscaling settings for the model", + "examples": [ + { + "autoscaling_window": 600, + "concurrency_target": null, + "max_replica": 5, + "max_scale_down_rate": null, + "min_replica": 1, + "scale_down_delay": 300, + "target_in_flight_tokens": null, + "target_utilization_percentage": null + } + ] }, - "max_gpus": { - "description": "Current max concurrent GPUs of this type", - "title": "Max Gpus", - "type": "integer" + "additional_autoscaling_config": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Additional autoscaling configuration (e.g. target in-flight tokens)", + "examples": [ + { + "metrics": [ + { + "name": "in_flight_tokens", + "target": 40000 + } + ] + } + ], + "title": "Additional Autoscaling Config" }, - "min_gpus": { + "metadata": { "anyOf": [ { - "type": "integer" + "additionalProperties": true, + "type": "object" }, { "type": "null" } ], "default": null, - "description": "Current baseline GPU allocation, if configured", - "title": "Min Gpus" + "description": "User-defined metadata for the deployment", + "examples": [ + { + "environment": "production", + "git_sha": "abc123" + } + ], + "title": "Metadata" }, - "last_modified": { - "description": "When the capacity row was last modified", - "format": "date-time", - "title": "Last Modified", - "type": "string" + "weights": { + "anyOf": [ + { + "items": { + "additionalProperties": true, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Weight configurations for BDN model weight distribution", + "examples": [ + [ + { + "mount_location": "/models/base", + "source": "hf://meta-llama/Llama-3-8B" + } + ] + ], + "title": "Weights" } }, "required": [ - "gpu_type", - "max_gpus", - "last_modified" + "resources" ], - "title": "CapacityAtSubmitV1", + "title": "CreateLLMModelVersionRequestV1", "type": "object" }, - "PendingJobAheadAtSubmitV1": { - "description": "A PENDING job in the same (org, gpu_type) pool that was ahead of the\ntarget in dequeue FIFO order at submitted_at \u2014 higher priority, or same\npriority and earlier submission.", + "LibraryListingMetadataV1": { + "additionalProperties": false, "properties": { - "training_job_id": { - "description": "Hashid of the other training job", - "title": "Training Job Id", - "type": "string" - }, - "training_job_name": { + "parameter_count": { "anyOf": [ { - "type": "string" + "type": "integer" }, { "type": "null" } ], "default": null, - "description": "Other job's name", - "title": "Training Job Name" + "title": "Parameter Count" }, - "instance_type_name": { - "description": "Instance type of the other job", - "title": "Instance Type Name", - "type": "string" + "context_length": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Context Length" }, - "requested_gpus": { - "description": "gpu_count * effective_node_count", - "title": "Requested Gpus", - "type": "integer" + "input_modalities": { + "default": [ + "text" + ], + "items": { + "$ref": "#/components/schemas/LibraryListingModality" + }, + "title": "Input Modalities", + "type": "array" }, - "priority": { - "description": "Effective priority (NULL coalesced to 0)", - "title": "Priority", - "type": "integer" + "output_modalities": { + "default": [ + "text" + ], + "items": { + "$ref": "#/components/schemas/LibraryListingModality" + }, + "title": "Output Modalities", + "type": "array" }, - "submitted_at": { - "description": "The other job's submission time", - "format": "date-time", - "title": "Submitted At", - "type": "string" - } - }, - "required": [ - "training_job_id", - "instance_type_name", - "requested_gpus", - "priority", - "submitted_at" - ], - "title": "PendingJobAheadAtSubmitV1", - "type": "object" - }, - "QueueEventV1": { - "description": "A single ``TrainingJobStatus`` row inside the queue-context window.", - "properties": { - "training_job_id": { - "description": "Hashid of the training job this event is for", - "title": "Training Job Id", + "license": { + "title": "License", "type": "string" }, - "training_job_name": { + "variant": { "anyOf": [ { "type": "string" @@ -23963,21 +28471,9 @@ } ], "default": null, - "description": "Job name", - "title": "Training Job Name" - }, - "status": { - "description": "TrainingJobStatus.Name value", - "title": "Status", - "type": "string" - }, - "created": { - "description": "When the status row was inserted", - "format": "date-time", - "title": "Created", - "type": "string" + "title": "Variant" }, - "event_message": { + "publisher": { "anyOf": [ { "type": "string" @@ -23987,42 +28483,24 @@ } ], "default": null, - "description": "Human-readable event message from the status metadata", - "title": "Event Message" + "title": "Publisher" }, - "exit_code": { + "model_api_slug": { "anyOf": [ { - "type": "integer" + "type": "string" }, { "type": "null" } ], "default": null, - "description": "Exit code from the status metadata, if any", - "title": "Exit Code" - } - }, - "required": [ - "training_job_id", - "status", - "created" - ], - "title": "QueueEventV1", - "type": "object" - }, - "GetTrainingJobQueueContextResponseV1": { - "description": "Read-only diagnostic for a training job's PENDING window.\n\nReturns the (org, gpu_type) capacity pool the job was gated by, jobs that\nwere holding GPU capacity in that pool when this job was submitted, and\nevery status event in [submitted_at, released_at] for those jobs (or up to\n\"now\" if the target is still PENDING).", - "properties": { - "target_job_id": { - "description": "Hashid of the target training job", - "title": "Target Job Id", - "type": "string" + "title": "Model Api Slug" }, - "target_job_name": { + "release_date": { "anyOf": [ { + "format": "date", "type": "string" }, { @@ -24030,29 +28508,11 @@ } ], "default": null, - "description": "Target job's name", - "title": "Target Job Name" - }, - "gpu_type": { - "description": "GPU type the target requested", - "title": "Gpu Type", - "type": "string" - }, - "requested_gpus": { - "description": "GPUs the target requested (gpu_count * effective_node_count)", - "title": "Requested Gpus", - "type": "integer" - }, - "submitted_at": { - "description": "When the job row was inserted (= API POST time)", - "format": "date-time", - "title": "Submitted At", - "type": "string" + "title": "Release Date" }, - "released_at": { + "description": { "anyOf": [ { - "format": "date-time", "type": "string" }, { @@ -24060,133 +28520,179 @@ } ], "default": null, - "description": "When the job's TRAINING_JOB_CREATED status was set, i.e. the moment it was released from PENDING. None if still PENDING.", - "title": "Released At" + "title": "Description" + }, + "trending": { + "default": false, + "title": "Trending", + "type": "boolean" + } + }, + "required": [ + "license" + ], + "title": "LibraryListingMetadataV1", + "type": "object" + }, + "LibraryListingModality": { + "enum": [ + "text", + "image", + "audio", + "video", + "embedding", + "rerank" + ], + "title": "LibraryListingModality", + "type": "string" + }, + "LibraryListingV1": { + "description": "A library listing.", + "properties": { + "display_name": { + "description": "Display name of the library listing", + "title": "Display Name", + "type": "string" + }, + "user_defined_id": { + "description": "User-defined identifier of the library listing", + "title": "User Defined Id", + "type": "string" }, - "pending_seconds": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null, - "description": "released_at - submitted_at in seconds. None if still PENDING.", - "title": "Pending Seconds" + "is_public": { + "description": "Whether the listing is publicly accessible", + "title": "Is Public", + "type": "boolean" }, - "org_capacity": { + "trending": { "anyOf": [ { - "$ref": "#/components/schemas/CapacityAtSubmitV1" + "type": "boolean" }, { "type": "null" } ], - "default": null, - "description": "Org-level cap for (org, gpu_type). None if no cap is configured." + "description": "Whether the listing is trending", + "title": "Trending" }, - "team_capacity": { + "closed_source": { + "description": "Whether the listing is closed source (deployers cannot view or download the Truss, and forks copy mirrored weights instead of re-mirroring from upstream)", + "title": "Closed Source", + "type": "boolean" + }, + "created_at": { + "description": "Time the listing was created in ISO 8601 format", + "format": "date-time", + "title": "Created At", + "type": "string" + }, + "modified_at": { + "description": "Time the listing was last modified", + "format": "date-time", + "title": "Modified At", + "type": "string" + }, + "metadata": { "anyOf": [ { - "$ref": "#/components/schemas/CapacityAtSubmitV1" + "$ref": "#/components/schemas/LibraryListingMetadataV1" }, { "type": "null" } ], "default": null, - "description": "Team-level cap for (team, gpu_type). None if no team cap is configured." - }, - "active_at_submit": { - "description": "Jobs in the same (org, gpu_type) pool that were holding capacity at submitted_at", - "items": { - "$ref": "#/components/schemas/ActiveJobAtSubmitV1" - }, - "title": "Active At Submit", - "type": "array" - }, - "pending_ahead_at_submit": { - "description": "PENDING jobs in the same (org, gpu_type) pool that were ahead of the target in dequeue FIFO order at submitted_at (priority DESC then created ASC). These also block the target's release.", - "items": { - "$ref": "#/components/schemas/PendingJobAheadAtSubmitV1" - }, - "title": "Pending Ahead At Submit", - "type": "array" - }, - "events": { - "description": "Every status event in [submitted_at, events_window_end] for the target job, every job in active_at_submit, and every job in pending_ahead_at_submit, oldest first.", + "description": "Model-level metadata for this listing, if it has been uploaded." + } + }, + "required": [ + "display_name", + "user_defined_id", + "is_public", + "trending", + "closed_source", + "created_at", + "modified_at" + ], + "title": "LibraryListingV1", + "type": "object" + }, + "LibraryListingsV1": { + "description": "A list of library listings.", + "properties": { + "listings": { "items": { - "$ref": "#/components/schemas/QueueEventV1" + "$ref": "#/components/schemas/LibraryListingV1" }, - "title": "Events", + "title": "Listings", "type": "array" - }, - "events_window_end": { - "description": "released_at if set, else 'now' (events ongoing)", - "format": "date-time", - "title": "Events Window End", - "type": "string" } }, "required": [ - "target_job_id", - "gpu_type", - "requested_gpus", - "submitted_at", - "active_at_submit", - "pending_ahead_at_submit", - "events", - "events_window_end" + "listings" ], - "title": "GetTrainingJobQueueContextResponseV1", + "title": "LibraryListingsV1", "type": "object" }, - "GetBlobCredentialsResponseV1": { - "description": "Response to create a new set of credentials for blob upload.", + "CreateLibraryListingRequestV1": { + "description": "Request to create a new library listing.", "properties": { - "creds": { - "$ref": "#/components/schemas/AWSCredentialsV1", - "description": "The credentials to upload the blob to" - }, - "s3_key": { - "description": "The S3 key to upload the blob to", - "title": "S3 Key", + "display_name": { + "description": "Display name of the library listing", + "title": "Display Name", "type": "string" }, - "s3_bucket": { - "description": "The S3 bucket to upload the blob to", - "title": "S3 Bucket", + "user_defined_id": { + "description": "User-defined identifier of the library listing", + "title": "User Defined Id", "type": "string" + }, + "is_public": { + "default": false, + "description": "Whether the listing is publicly accessible", + "title": "Is Public", + "type": "boolean" + }, + "closed_source": { + "default": false, + "description": "Whether the listing is closed source (deployers cannot view or download the Truss, and forks copy mirrored weights instead of re-mirroring from upstream)", + "title": "Closed Source", + "type": "boolean" } }, "required": [ - "creds", - "s3_key", - "s3_bucket" + "display_name", + "user_defined_id" ], - "title": "GetBlobCredentialsResponseV1", + "title": "CreateLibraryListingRequestV1", "type": "object" }, - "APIKeyCategory": { - "description": "Enum representing the category of an API key.", - "enum": [ - "PERSONAL", - "ROUTES", - "WORKSPACE_MANAGE_ALL", - "WORKSPACE_EXPORT_METRICS", - "WORKSPACE_INVOKE", - "WORKSPACE_MANAGE_API_KEYS" + "LibraryListingTombstoneV1": { + "description": "A library listing tombstone.", + "properties": { + "user_defined_id": { + "description": "User-defined identifier of the library listing", + "title": "User Defined Id", + "type": "string" + }, + "deleted": { + "description": "Whether the library listing was deleted", + "title": "Deleted", + "type": "boolean" + } + }, + "required": [ + "user_defined_id", + "deleted" ], - "title": "APIKeyCategory", - "type": "string" + "title": "LibraryListingTombstoneV1", + "type": "object" }, - "CreateAPIKeyRequestV1": { - "description": "Request to create an API key.", + "UpdateLibraryListingRequestV1": { + "description": "Request to update a library listing.", "properties": { - "name": { + "display_name": { "anyOf": [ { "type": "string" @@ -24196,582 +28702,381 @@ } ], "default": null, - "description": "Optional name for the API key", - "examples": [ - "my-api-key" - ], - "title": "Name" - }, - "type": { - "$ref": "#/components/schemas/APIKeyCategory", - "description": "Type of the API key.", - "examples": [ - "PERSONAL", - "ROUTES", - "WORKSPACE_MANAGE_API_KEYS", - "WORKSPACE_EXPORT_METRICS", - "WORKSPACE_INVOKE", - "WORKSPACE_MANAGE_ALL" - ] + "description": "New display name for the library listing", + "title": "Display Name" }, - "model_ids": { + "is_public": { "anyOf": [ { - "items": { - "type": "string" - }, - "type": "array" + "type": "boolean" }, { "type": "null" } ], "default": null, - "description": "List of model IDs to scope the API key to, only present if type is 'WORKSPACE_EXPORT_METRICS' or 'WORKSPACE_INVOKE'", - "examples": [ - [ - "aaaaaaaa" - ] + "description": "Whether the listing is publicly accessible", + "title": "Is Public" + }, + "trending": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } ], - "title": "Model Ids" + "default": null, + "description": "Whether the listing is trending", + "title": "Trending" }, - "team_id": { + "metadata": { "anyOf": [ { - "minLength": 1, - "type": "string" + "$ref": "#/components/schemas/LibraryListingMetadataV1" }, { "type": "null" } ], "default": null, - "description": "Team ID for a team-scoped key. When omitted, uses the team in the URL if present, otherwise your organization's default team. Must match the URL team when both are provided. Not supported for PERSONAL or WORKSPACE_MANAGE_API_KEYS keys.", - "title": "Team Id" - } - }, - "required": [ - "type" - ], - "title": "CreateAPIKeyRequestV1", - "type": "object" - }, - "APIKeyV1": { - "description": "Represents an API key.", - "properties": { - "api_key": { - "description": "The API key string", - "title": "Api Key", - "type": "string" + "description": "Model-level metadata for the listing. When provided, replaces the stored metadata. Unknown fields are rejected." } }, - "required": [ - "api_key" - ], - "title": "APIKeyV1", + "title": "UpdateLibraryListingRequestV1", "type": "object" }, - "APIKeyInfoV1": { - "description": "Represents the metadata of an API key.", + "BenchmarkSnapshotV1": { "properties": { - "prefix": { - "description": "The prefix of the API key", - "title": "Prefix", + "run_id": { + "title": "Run Id", "type": "string" }, - "name": { + "measured_at": { + "format": "date", + "title": "Measured At", + "type": "string" + }, + "llm": { "anyOf": [ { - "type": "string" + "$ref": "#/components/schemas/LLMBenchmarkMetricsV1" }, { "type": "null" } ], - "default": null, - "description": "Optional name for the API key", - "examples": [ - "my-api-key" - ], - "title": "Name" - }, - "type": { - "$ref": "#/components/schemas/APIKeyCategory", - "description": "Type of the API key.", - "examples": [ - "PERSONAL", - "WORKSPACE_MANAGE_API_KEYS", - "WORKSPACE_EXPORT_METRICS", - "WORKSPACE_INVOKE", - "WORKSPACE_MANAGE_ALL" - ] + "default": null }, - "model_ids": { + "tts": { "anyOf": [ { - "items": { - "type": "string" - }, - "type": "array" + "$ref": "#/components/schemas/TTSBenchmarkMetricsV1" }, { "type": "null" } ], - "default": null, - "description": "List of model IDs to scope the API key to, only present if type is 'WORKSPACE_EXPORT_METRICS' or 'WORKSPACE_INVOKE'", - "examples": [ - [ - "aaaaaaaa" - ] + "default": null + }, + "embedding": { + "anyOf": [ + { + "$ref": "#/components/schemas/EmbeddingBenchmarkMetricsV1" + }, + { + "type": "null" + } ], - "title": "Model Ids" + "default": null }, - "team_name": { + "replicas": { "anyOf": [ { - "type": "string" + "type": "integer" }, { "type": "null" } ], - "default": null, - "description": "The name of the team associated with the API key", - "title": "Team Name" + "default": 2, + "title": "Replicas" }, - "owner": { + "profile": { "anyOf": [ { - "$ref": "#/components/schemas/APIKeyOwnerV1" + "type": "string" }, { "type": "null" } ], - "default": null, - "description": "The user who owns the API key. Only present for personal API keys." + "default": "512x256", + "title": "Profile" } }, "required": [ - "prefix", - "type" + "run_id", + "measured_at" ], - "title": "APIKeyInfoV1", + "title": "BenchmarkSnapshotV1", "type": "object" }, - "APIKeyOwnerV1": { - "description": "The user who owns a personal API key.", + "EmbeddingBenchmarkMetricsV1": { "properties": { - "user_id": { - "description": "Unique identifier for the user", - "title": "User Id", - "type": "string" + "e2e_latency_ms_p50": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "title": "E2E Latency Ms P50" }, - "email": { + "e2e_latency_ms_p99": { "anyOf": [ { - "type": "string" + "type": "number" }, { "type": "null" } ], "default": null, - "description": "Email address of the user", - "title": "Email" + "title": "E2E Latency Ms P99" }, - "name": { + "input_tokens_per_sec": { "anyOf": [ { - "type": "string" + "type": "number" }, { "type": "null" } ], "default": null, - "description": "Display name of the user", - "title": "Name" - } - }, - "required": [ - "user_id" - ], - "title": "APIKeyOwnerV1", - "type": "object" - }, - "APIKeysV1": { - "description": "A list of API keys.", - "properties": { - "keys": { - "description": "A list of API key information", - "items": { - "$ref": "#/components/schemas/APIKeyInfoV1" - }, - "title": "Keys", - "type": "array" - } - }, - "required": [ - "keys" - ], - "title": "APIKeysV1", - "type": "object" - }, - "APIKeyTombstoneV1": { - "description": "An API key tombstone.", - "properties": { - "prefix": { - "description": "Unique prefix of the API key", - "title": "Prefix", - "type": "string" - } - }, - "required": [ - "prefix" - ], - "title": "APIKeyTombstoneV1", - "type": "object" - }, - "LimitTypeV1": { - "enum": [ - "REQUEST", - "TOKEN" - ], - "title": "LimitTypeV1", - "type": "string" - }, - "ModelAPIOrgDetailsV1": { - "description": "Workspace-specific state for a Model API.", - "properties": { - "added_at": { - "description": "When the workspace first added this Model API.", - "format": "date-time", - "title": "Added At", - "type": "string" + "title": "Input Tokens Per Sec" }, - "last_used_at": { + "requests_per_sec": { "anyOf": [ { - "format": "date-time", - "type": "string" + "type": "number" }, { "type": "null" } ], "default": null, - "description": "When the workspace last invoked this Model API. Null if the workspace has never invoked it.", - "title": "Last Used At" + "title": "Requests Per Sec" } }, - "required": [ - "added_at" - ], - "title": "ModelAPIOrgDetailsV1", + "title": "EmbeddingBenchmarkMetricsV1", "type": "object" }, - "ModelAPIV1": { - "description": "A Model API catalog row, optionally enriched with workspace-specific state.", + "LLMBenchmarkMetricsV1": { "properties": { - "name": { - "description": "Identifier of the Model API. Stable, URL-safe slug used as the public identifier.", - "examples": [ - "llama-3-3-70b-instruct" - ], - "title": "Name", - "type": "string" - }, - "display_name": { - "description": "Human-readable name of the Model API.", - "examples": [ - "Llama 3.3 70B Instruct" - ], - "title": "Display Name", - "type": "string" - }, - "description": { - "description": "Description of the Model API.", - "title": "Description", - "type": "string" - }, - "model_family": { + "ttft_ms_p50": { "anyOf": [ { - "type": "string" + "type": "number" }, { "type": "null" } ], "default": null, - "description": "Family the underlying model belongs to.", - "examples": [ - "META", - "DEEPSEEK", - "QWEN" - ], - "title": "Model Family" - }, - "release_date": { - "description": "Date the Model API was made available.", - "format": "date", - "title": "Release Date", - "type": "string" - }, - "invoke_url": { - "description": "Base URL for invoking the Model API. OpenAI-shaped routes (e.g. /v1/chat/completions) live underneath this host.", - "examples": [ - "https://inference.baseten.co" - ], - "title": "Invoke Url", - "type": "string" - }, - "context_length": { - "description": "The model's context window length, in tokens.", - "examples": [ - 8192 - ], - "title": "Context Length", - "type": "integer" + "title": "Ttft Ms P50" }, - "cost_per_million_input_tokens": { + "output_tokens_per_sec_per_user_p50": { "anyOf": [ { "type": "number" }, { - "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", - "type": "string" + "type": "null" + } + ], + "default": null, + "title": "Output Tokens Per Sec Per User P50" + }, + "max_concurrent_users_at_50ms_tpot": { + "anyOf": [ + { + "type": "integer" }, { "type": "null" } ], - "description": "Effective cost per million input tokens, in dollars. Null when pricing is unavailable.", - "examples": [ - "0.13" - ], - "title": "Cost Per Million Input Tokens" + "default": null, + "title": "Max Concurrent Users At 50Ms Tpot" }, - "cost_per_million_output_tokens": { + "requests_per_sec_p50": { "anyOf": [ { "type": "number" }, - { - "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", - "type": "string" - }, { "type": "null" } ], - "description": "Effective cost per million output tokens, in dollars. Null when pricing is unavailable.", - "examples": [ - "0.50" - ], - "title": "Cost Per Million Output Tokens" - }, - "rate_limits": { - "description": "Rate limits in effect for the workspace. Workspace-specific overrides are returned when the workspace has added this Model API and configured them; otherwise the catalog default rate limits are returned.", - "items": { - "$ref": "#/components/schemas/RateLimitV1" - }, - "title": "Rate Limits", - "type": "array" + "default": null, + "title": "Requests Per Sec P50" }, - "org_details": { + "cost_per_1m_tokens_usd": { "anyOf": [ { - "$ref": "#/components/schemas/ModelAPIOrgDetailsV1" + "type": "number" }, { "type": "null" } ], "default": null, - "description": "Workspace-specific state. Null when the workspace has not added this Model API." + "title": "Cost Per 1M Tokens Usd" } }, - "required": [ - "name", - "display_name", - "description", - "release_date", - "invoke_url", - "context_length", - "cost_per_million_input_tokens", - "cost_per_million_output_tokens", - "rate_limits" - ], - "title": "ModelAPIV1", + "title": "LLMBenchmarkMetricsV1", "type": "object" }, - "RateLimitUnitV1": { - "enum": [ - "SECOND", - "MINUTE" - ], - "title": "RateLimitUnitV1", - "type": "string" - }, - "RateLimitV1": { + "LibraryListingVersionV1": { + "description": "A library listing version.", "properties": { - "type": { - "$ref": "#/components/schemas/LimitTypeV1", - "description": "The type of the rate limit", - "examples": [ - "TOKEN", - "REQUEST" - ] + "version_tag": { + "description": "Human-readable tag for this version", + "title": "Version Tag", + "type": "string" }, - "unit": { - "$ref": "#/components/schemas/RateLimitUnitV1", - "description": "The unit of the rate limit", - "examples": [ - "SECOND", - "MINUTE" - ] + "is_live": { + "description": "Whether this version is the live version", + "title": "Is Live", + "type": "boolean" }, - "threshold": { - "description": "The threshold for the rate limit", - "examples": [ - 1000, - 50000 - ], - "minimum": 0, - "title": "Threshold", - "type": "integer" - } - }, - "required": [ - "type", - "unit", - "threshold" - ], - "title": "RateLimitV1", - "type": "object" - }, - "ModelAPIsResponseV1": { - "description": "Page of Model APIs visible to the caller.", - "properties": { - "items": { - "description": "Items in this page.", - "items": { - "$ref": "#/components/schemas/ModelAPIV1" - }, - "title": "Items", - "type": "array" + "allow_truss_download": { + "description": "Whether users deploying this model can download the Truss", + "title": "Allow Truss Download", + "type": "boolean" }, - "pagination": { - "$ref": "#/components/schemas/PaginationResponseV1", - "description": "Pagination metadata for the page." + "oracle_version_id": { + "description": "Id of the source model version", + "title": "Oracle Version Id", + "type": "string" + }, + "created_at": { + "description": "Time the version was created in ISO 8601 format", + "format": "date-time", + "title": "Created At", + "type": "string" + }, + "modified_at": { + "description": "Time the version was last modified", + "format": "date-time", + "title": "Modified At", + "type": "string" + }, + "benchmark": { + "anyOf": [ + { + "$ref": "#/components/schemas/BenchmarkSnapshotV1" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Benchmark snapshot for this version, if one has been uploaded." } }, "required": [ - "items", - "pagination" + "version_tag", + "is_live", + "allow_truss_download", + "oracle_version_id", + "created_at", + "modified_at" ], - "title": "ModelAPIsResponseV1", + "title": "LibraryListingVersionV1", "type": "object" }, - "ModelAPIsRequestV1": { - "description": "Query-string filters for ``GET /v1/model_apis``.", + "TTSBenchmarkMetricsV1": { "properties": { - "cursor": { + "ttft_ms_p50": { "anyOf": [ { - "type": "string" + "type": "number" }, { "type": "null" } ], "default": null, - "description": "Opaque cursor returned by a previous page. Omit to fetch the first page.", - "title": "Cursor" - }, - "limit": { - "default": 100, - "description": "Maximum number of items to return.", - "maximum": 1000, - "minimum": 1, - "title": "Limit", - "type": "integer" - }, - "added_only": { - "default": false, - "description": "When true, restrict the result to Model APIs the workspace has added. Defaults to the full visible catalog.", - "title": "Added Only", - "type": "boolean" - } - }, - "title": "ModelAPIsRequestV1", - "type": "object" - }, - "ModelApisUsageBucketV1": { - "description": "One time bucket and the usage recorded in it.", - "properties": { - "start_time": { - "description": "Start of the bucket (inclusive), UTC", - "format": "date-time", - "title": "Start Time", - "type": "string" - }, - "end_time": { - "description": "End of the bucket (exclusive), UTC", - "format": "date-time", - "title": "End Time", - "type": "string" + "title": "Ttft Ms P50" }, - "results": { - "description": "Usage totals for this bucket, ordered by total tokens descending", - "items": { - "$ref": "#/components/schemas/ModelApisUsageResultV1" - }, - "title": "Results", - "type": "array" - } - }, - "required": [ - "start_time", - "end_time" - ], - "title": "ModelApisUsageBucketV1", - "type": "object" - }, - "ModelApisUsageResultV1": { - "description": "Usage totals for one combination of the requested dimensions, within one bucket.", - "properties": { - "api_key_prefix": { + "max_concurrent_streams_at_rtf1": { "anyOf": [ { - "type": "string" + "type": "integer" }, { "type": "null" } ], "default": null, - "description": "Prefix of the API key the usage is attributed to. Null when not grouping by api_key or when the request was not authenticated with an API key.", - "title": "Api Key Prefix" + "title": "Max Concurrent Streams At Rtf1" }, - "user_id": { + "ttft_ms_p50_at_max_concurrency": { "anyOf": [ { - "type": "string" + "type": "number" }, { "type": "null" } ], "default": null, - "description": "User the usage is attributed to. Null when not grouping by user or when the credential is not user-scoped.", - "title": "User Id" + "title": "Ttft Ms P50 At Max Concurrency" }, - "model": { + "cost_per_audio_minute_usd": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Cost Per Audio Minute Usd" + } + }, + "title": "TTSBenchmarkMetricsV1", + "type": "object" + }, + "LibraryListingVersionsV1": { + "description": "A list of library listing versions.", + "properties": { + "versions": { + "items": { + "$ref": "#/components/schemas/LibraryListingVersionV1" + }, + "title": "Versions", + "type": "array" + } + }, + "required": [ + "versions" + ], + "title": "LibraryListingVersionsV1", + "type": "object" + }, + "CreateLibraryListingVersionRequestV1": { + "description": "Request to create a new library listing version from an existing model version.", + "properties": { + "display_name": { "anyOf": [ { "type": "string" @@ -24781,206 +29086,154 @@ } ], "default": null, - "description": "Model that served the usage. Null when not grouping by model.", - "title": "Model" + "description": "Display name of the library listing. Required when creating a new listing.", + "title": "Display Name" }, - "input_tokens": { - "description": "Total input tokens, cached and uncached combined.", - "title": "Input Tokens", - "type": "integer" + "is_public": { + "default": false, + "description": "Whether the listing is publicly accessible. Only used when creating a new listing.", + "title": "Is Public", + "type": "boolean" }, - "cached_input_tokens": { - "description": "Input tokens served from the prompt cache.", - "title": "Cached Input Tokens", - "type": "integer" + "oracle_version_id": { + "description": "Id of the source model version to publish", + "title": "Oracle Version Id", + "type": "string" }, - "uncached_input_tokens": { - "description": "Input tokens not served from the prompt cache.", - "title": "Uncached Input Tokens", - "type": "integer" + "allow_truss_download": { + "default": false, + "description": "Whether users deploying this model can download the Truss", + "title": "Allow Truss Download", + "type": "boolean" }, - "output_tokens": { - "description": "Total output tokens.", - "title": "Output Tokens", - "type": "integer" + "closed_source": { + "default": false, + "description": "Whether the listing is closed source (deployers cannot view or download the Truss, and forks copy mirrored weights instead of re-mirroring from upstream). Only used when creating a new listing.", + "title": "Closed Source", + "type": "boolean" }, - "request_count": { - "description": "Total number of requests.", - "title": "Request Count", - "type": "integer" + "version_tag": { + "description": "Human-readable tag for this version", + "title": "Version Tag", + "type": "string" } }, "required": [ - "input_tokens", - "cached_input_tokens", - "uncached_input_tokens", - "output_tokens", - "request_count" + "oracle_version_id", + "version_tag" ], - "title": "ModelApisUsageResultV1", + "title": "CreateLibraryListingVersionRequestV1", "type": "object" }, - "ModelApisUsageResponseV1": { - "description": "A page of Model APIs token usage: contiguous time buckets, ordered oldest first.", + "LibraryListingVersionTombstoneV1": { + "description": "A library listing version tombstone.", "properties": { - "items": { - "description": "Items in this page.", - "items": { - "$ref": "#/components/schemas/ModelApisUsageBucketV1" - }, - "title": "Items", - "type": "array" + "version_tag": { + "description": "Human-readable tag for this version", + "title": "Version Tag", + "type": "string" }, - "pagination": { - "$ref": "#/components/schemas/PaginationResponseV1", - "description": "Pagination metadata for the page." + "deleted": { + "description": "Whether the library listing version was deleted", + "title": "Deleted", + "type": "boolean" } }, "required": [ - "items", - "pagination" + "version_tag", + "deleted" ], - "title": "ModelApisUsageResponseV1", + "title": "LibraryListingVersionTombstoneV1", "type": "object" }, - "BucketWidth": { - "enum": [ - "1m", - "1h", - "1d" - ], - "title": "BucketWidth", - "type": "string" - }, - "UsageDimensionV1": { - "enum": [ - "api_key", - "user", - "model" - ], - "title": "UsageDimensionV1", - "type": "string" - }, - "ModelApisUsageRequestV1": { + "UpdateLibraryListingVersionRequestV1": { + "description": "Request to update a library listing version.", "properties": { - "start_time": { - "anyOf": [ - { - "format": "date-time", - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "description": "Start of the query range (ISO 8601, UTC), inclusive. Snapped down to the start of its bucket. Required on the first page, and ignored when you pass a cursor.", - "title": "Start Time" - }, - "end_time": { + "is_live": { "anyOf": [ { - "format": "date-time", - "type": "string" + "type": "boolean" }, { "type": "null" } ], "default": null, - "description": "End of the query range (ISO 8601, UTC), exclusive. Defaults to the current time.", - "title": "End Time" - }, - "bucket_width": { - "$ref": "#/components/schemas/BucketWidth", - "default": "1d", - "description": "Width of each time bucket: 1m, 1h, or 1d. Defaults to 1d." - }, - "group_by": { - "description": "Dimensions to break usage down by, repeated once per dimension: api_key, user, model. Defaults to model.", - "items": { - "$ref": "#/components/schemas/UsageDimensionV1" - }, - "title": "Group By", - "type": "array" - }, - "api_keys": { - "description": "Return only usage for these API key prefixes, repeated once per prefix.", - "items": { - "type": "string" - }, - "title": "Api Keys", - "type": "array" - }, - "user_ids": { - "description": "Return only usage attributed to these user IDs, repeated once per ID.", - "items": { - "type": "string" - }, - "title": "User Ids", - "type": "array" - }, - "models": { - "description": "Return only usage for these models, repeated once per model.", - "items": { - "type": "string" - }, - "title": "Models", - "type": "array" + "description": "Whether this version should be the live version. Setting to true demotes the current live version.", + "title": "Is Live" }, - "limit": { + "allow_truss_download": { "anyOf": [ { - "type": "integer" + "type": "boolean" }, { "type": "null" } ], "default": null, - "description": "Number of time buckets to return. Defaults and maximums depend on bucket_width: 1d defaults to 7 and allows 31, 1h defaults to 24 and allows 168, 1m defaults to 60 and allows 1440.", - "title": "Limit" + "description": "Whether users deploying this model can download the Truss", + "title": "Allow Truss Download" }, - "cursor": { + "benchmark": { "anyOf": [ { - "type": "string" + "$ref": "#/components/schemas/BenchmarkSnapshotV1" }, { "type": "null" } ], "default": null, - "description": "Opaque cursor from the pagination.cursor field of a previous response", - "title": "Cursor" + "description": "Benchmark snapshot for this version. When provided, replaces the stored benchmark." } }, - "title": "ModelApisUsageRequestV1", + "title": "UpdateLibraryListingVersionRequestV1", "type": "object" }, - "CreateLLMModelRequestV1": { - "description": "A request to create a BIS-LLM model", + "ModelApisCostBucketV1": { + "description": "One daily bucket and the costs attributed to it.", "properties": { - "resources": { - "additionalProperties": true, - "description": "Resources allocated to the model", - "title": "Resources", - "type": "object" + "date": { + "description": "UTC calendar date for this bucket, from midnight inclusive to the next midnight exclusive.", + "format": "date", + "title": "Date", + "type": "string" }, - "region": { + "results": { + "description": "Cost totals for the observed combinations of requested dimensions in this bucket, ordered by those dimensions. Empty when the day has no matching usage.", + "items": { + "$ref": "#/components/schemas/ModelApisCostResultV1" + }, + "title": "Results", + "type": "array" + } + }, + "required": [ + "date" + ], + "title": "ModelApisCostBucketV1", + "type": "object" + }, + "ModelApisCostResultV1": { + "properties": { + "api_key_prefixes": { "anyOf": [ { - "type": "string" + "items": { + "type": "string" + }, + "type": "array" }, { "type": "null" } ], "default": null, - "description": "Region in which to deploy the model", - "title": "Region" + "description": "The single attributed API key prefix for this result. Null when not grouping by api_key_prefix or when attribution is unavailable.", + "title": "Api Key Prefixes" }, - "llm_version": { + "user_id": { "anyOf": [ { "type": "string" @@ -24990,160 +29243,203 @@ } ], "default": null, - "description": "Version of the helm chart to use.", - "title": "Llm Version" - }, - "llm_config": { - "additionalProperties": true, - "description": "Configuration specific to the LLM model", - "title": "Llm Config", - "type": "object" - }, - "environment_variables": { - "additionalProperties": true, - "description": "Environment variables for the model", - "title": "Environment Variables", - "type": "object" + "description": "Attributed user ID. Null when not grouping by user or when attribution is unavailable.", + "title": "User Id" }, - "model_metadata": { + "model": { "anyOf": [ { - "additionalProperties": true, - "type": "object" + "type": "string" }, { "type": "null" } ], "default": null, - "description": "Model metadata persisted into model_config", - "title": "Model Metadata" + "description": "Model identifier. Null when not grouping by model.", + "title": "Model" }, - "autoscaling_settings": { + "service_tier": { "anyOf": [ { - "$ref": "#/components/schemas/UpdateAutoscalingSettingsV1" + "type": "string" }, { "type": "null" } ], "default": null, - "description": "Autoscaling settings for the model", + "description": "Service tier. Null when not grouping by service_tier or when attribution is unavailable.", + "title": "Service Tier" + }, + "subtotal": { + "description": "Model API cost in USD for this day and grouping combination, returned as an exact decimal string preserving fractional-cent amounts. This amount may differ from finalized invoice amounts.", "examples": [ - { - "autoscaling_window": 600, - "concurrency_target": null, - "max_replica": 5, - "max_scale_down_rate": null, - "min_replica": 1, - "scale_down_delay": 300, - "target_in_flight_tokens": null, - "target_utilization_percentage": null - } - ] + "0.00000123" + ], + "title": "Subtotal", + "type": "string" + } + }, + "required": [ + "subtotal" + ], + "title": "ModelApisCostResultV1", + "type": "object" + }, + "ModelApisCostsResponseV1": { + "description": "One non-overlapping bucket per UTC day, ordered oldest first with no gaps.\n\nDays without matching usage are included with an empty results list.", + "properties": { + "items": { + "description": "Items in this page.", + "items": { + "$ref": "#/components/schemas/ModelApisCostBucketV1" + }, + "title": "Items", + "type": "array" }, - "additional_autoscaling_config": { + "pagination": { + "$ref": "#/components/schemas/PaginationResponseV1", + "description": "Pagination metadata for the page." + } + }, + "required": [ + "items", + "pagination" + ], + "title": "ModelApisCostsResponseV1", + "type": "object" + }, + "ModelApiCostDimensionV1": { + "enum": [ + "api_key_prefix", + "user", + "model", + "service_tier" + ], + "title": "ModelApiCostDimensionV1", + "type": "string" + }, + "ModelApisCostsRequestV1": { + "properties": { + "cursor": { "anyOf": [ { - "additionalProperties": true, - "type": "object" + "type": "string" }, { "type": "null" } ], "default": null, - "description": "Additional autoscaling configuration (e.g. target in-flight tokens)", - "examples": [ - { - "metrics": [ - { - "name": "in_flight_tokens", - "target": 40000 - } - ] - } - ], - "title": "Additional Autoscaling Config" + "description": "Opaque cursor returned by a previous page. Omit to fetch the first page.", + "title": "Cursor" }, - "metadata": { + "limit": { + "default": 7, + "description": "Number of daily cost buckets to return. Defaults to 7; maximum 31.", + "maximum": 31, + "minimum": 1, + "title": "Limit", + "type": "integer" + }, + "start_date": { "anyOf": [ { - "additionalProperties": true, - "type": "object" + "format": "date", + "type": "string" }, { "type": "null" } ], "default": null, - "description": "User-defined metadata for the deployment", - "examples": [ - { - "environment": "production", - "git_sha": "abc123" - } - ], - "title": "Metadata" + "description": "Inclusive UTC calendar day at the start of the query range. Defaults to the previous UTC date, cannot be before 2026-08-05, and is ignored when you pass a cursor.", + "title": "Start Date" }, - "weights": { + "end_date": { "anyOf": [ { - "items": { - "additionalProperties": true, - "type": "object" - }, - "type": "array" + "format": "date", + "type": "string" }, { "type": "null" } ], "default": null, - "description": "Weight configurations for BDN model weight distribution", - "examples": [ - [ - { - "mount_location": "/models/base", - "source": "hf://meta-llama/Llama-3-8B" - } - ] - ], - "title": "Weights" + "description": "Exclusive UTC calendar day at the end of the query range. Defaults to the day after the current UTC date so current-day usage is included. The date range cannot exceed 90 days.", + "title": "End Date" }, - "name": { - "description": "Name of the model", - "title": "Name", - "type": "string" + "group_by": { + "description": "Dimensions to break costs down by, repeated once per dimension: api_key_prefix, user, model, or service_tier. Each result represents one observed combination of the requested dimensions within that day. For example, grouping by api_key_prefix and user returns each API-key and user pair that had usage. Combinations without usage are omitted, so result counts can differ between days. Omit for daily organization totals.", + "items": { + "$ref": "#/components/schemas/ModelApiCostDimensionV1" + }, + "title": "Group By", + "type": "array" + }, + "api_key_prefixes": { + "description": "Return only costs for these exact API key prefixes, repeated once per prefix.", + "items": { + "type": "string" + }, + "title": "Api Key Prefixes", + "type": "array" + }, + "user_ids": { + "description": "Return only costs attributed to these exact user IDs, repeated once per ID.", + "items": { + "type": "string" + }, + "title": "User Ids", + "type": "array" + }, + "models": { + "description": "Return only costs for these exact model identifiers, repeated once per model.", + "items": { + "type": "string" + }, + "title": "Models", + "type": "array" + }, + "service_tiers": { + "description": "Return only costs for these exact service tiers, repeated once per tier.", + "items": { + "type": "string" + }, + "title": "Service Tiers", + "type": "array" } }, - "required": [ - "resources", - "name" - ], - "title": "CreateLLMModelRequestV1", + "title": "ModelApisCostsRequestV1", "type": "object" }, - "LLMModelHandleV1": { - "description": "Handle for a BIS-LLM model deployment.", + "BillableResourceV1": { "properties": { - "model_id": { - "description": "Unique identifier of the model", - "title": "Model Id", + "id": { + "description": "Unique identifier of the resource", + "title": "Id", "type": "string" }, - "version_id": { - "description": "Unique identifier of the model version", - "title": "Version Id", - "type": "string" + "kind": { + "$ref": "#/components/schemas/ResourceKind", + "description": "Resource kind (MODEL_DEPLOYMENT, CHAINLET, TRAINING_JOB, LOOPS_TRAINER, or LOOPS_SAMPLER)" }, - "hostname": { - "description": "Hostname used to invoke the model", - "title": "Hostname", - "type": "string" + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Name of the resource", + "title": "Name" }, - "instance_type_name": { + "model_id": { "anyOf": [ { "type": "string" @@ -25153,28 +29449,28 @@ } ], "default": null, - "description": "Name of the instance type the model deployment is running on", - "title": "Instance Type Name" - } - }, - "required": [ - "model_id", - "version_id", - "hostname" - ], - "title": "LLMModelHandleV1", - "type": "object" - }, - "CreateLLMModelVersionRequestV1": { - "description": "A request to create a BIS-LLM model version", - "properties": { - "resources": { - "additionalProperties": true, - "description": "Resources allocated to the model", - "title": "Resources", - "type": "object" + "description": "Unique identifier of the parent model for model deployments and chainlets", + "title": "Model Id" + }, + "model_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Name of the parent resource (e.g., model name for model deployments, training project name for training jobs)", + "title": "Model Name" }, - "region": { + "is_deleted": { + "description": "Indicates if the resource has been deleted", + "title": "Is Deleted", + "type": "boolean" + }, + "instance_type": { "anyOf": [ { "type": "string" @@ -25184,10 +29480,10 @@ } ], "default": null, - "description": "Region in which to deploy the model", - "title": "Region" + "description": "Instance type used", + "title": "Instance Type" }, - "llm_version": { + "base_model": { "anyOf": [ { "type": "string" @@ -25197,1048 +29493,1308 @@ } ], "default": null, - "description": "Version of the helm chart to use.", - "title": "Llm Version" - }, - "llm_config": { - "additionalProperties": true, - "description": "Configuration specific to the LLM model", - "title": "Llm Config", - "type": "object" - }, - "environment_variables": { - "additionalProperties": true, - "description": "Environment variables for the model", - "title": "Environment Variables", - "type": "object" + "description": "Base model used by this Loops trainer or sampler", + "title": "Base Model" }, - "model_metadata": { + "environment_name": { "anyOf": [ { - "additionalProperties": true, - "type": "object" + "type": "string" }, { "type": "null" } ], "default": null, - "description": "Model metadata persisted into model_config", - "title": "Model Metadata" + "description": "Environment name (e.g., 'production', 'staging')", + "title": "Environment Name" }, - "autoscaling_settings": { + "chain_metadata": { "anyOf": [ { - "$ref": "#/components/schemas/UpdateAutoscalingSettingsV1" + "$ref": "#/components/schemas/ChainMetadataV1" }, { "type": "null" } ], "default": null, - "description": "Autoscaling settings for the model", - "examples": [ - { - "autoscaling_window": 600, - "concurrency_target": null, - "max_replica": 5, - "max_scale_down_rate": null, - "min_replica": 1, - "scale_down_delay": 300, - "target_in_flight_tokens": null, - "target_utilization_percentage": null - } - ] + "description": "Chain metadata if this is a chainlet deployment" }, - "additional_autoscaling_config": { + "team_id": { "anyOf": [ { - "additionalProperties": true, - "type": "object" + "type": "string" }, { "type": "null" } ], "default": null, - "description": "Additional autoscaling configuration (e.g. target in-flight tokens)", - "examples": [ - { - "metrics": [ - { - "name": "in_flight_tokens", - "target": 40000 - } - ] - } - ], - "title": "Additional Autoscaling Config" + "description": "Unique identifier of the team that owns the resource. Only present for organizations with multiple teams enabled.", + "title": "Team Id" }, - "metadata": { + "team_name": { "anyOf": [ { - "additionalProperties": true, - "type": "object" + "type": "string" }, { "type": "null" } ], "default": null, - "description": "User-defined metadata for the deployment", - "examples": [ - { - "environment": "production", - "git_sha": "abc123" - } - ], - "title": "Metadata" + "description": "Name of the team that owns the resource. Only present for organizations with multiple teams enabled.", + "title": "Team Name" + } + }, + "required": [ + "id", + "kind", + "is_deleted" + ], + "title": "BillableResourceV1", + "type": "object" + }, + "ChainMetadataV1": { + "properties": { + "chain_id": { + "description": "Unique identifier of the chain", + "title": "Chain Id", + "type": "string" }, - "weights": { + "chain_name": { "anyOf": [ { - "items": { - "additionalProperties": true, - "type": "object" - }, - "type": "array" + "type": "string" }, { "type": "null" } ], "default": null, - "description": "Weight configurations for BDN model weight distribution", - "examples": [ - [ - { - "mount_location": "/models/base", - "source": "hf://meta-llama/Llama-3-8B" - } - ] - ], - "title": "Weights" + "description": "Name of the chain", + "title": "Chain Name" + }, + "chain_deployment_id": { + "description": "Unique identifier of the chain deployment", + "title": "Chain Deployment Id", + "type": "string" } }, "required": [ - "resources" + "chain_id", + "chain_deployment_id" ], - "title": "CreateLLMModelVersionRequestV1", + "title": "ChainMetadataV1", "type": "object" }, - "LibraryListingMetadataV1": { - "additionalProperties": false, + "DailyDedicatedUsageV1": { "properties": { - "parameter_count": { + "date": { + "description": "Date of the usage", + "format": "date", + "title": "Date", + "type": "string" + }, + "subtotal": { "anyOf": [ { - "type": "integer" + "type": "number" }, { - "type": "null" + "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", + "type": "string" } ], - "default": null, - "title": "Parameter Count" + "description": "Subtotal cost incurred on this date in dollars", + "title": "Subtotal" }, - "context_length": { + "compute_cost": { "anyOf": [ { - "type": "integer" + "type": "number" }, { - "type": "null" + "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", + "type": "string" } ], - "default": null, - "title": "Context Length" + "description": "Compute cost incurred on this date in dollars", + "title": "Compute Cost" }, - "input_modalities": { - "default": [ - "text" + "surcharge_cost": { + "anyOf": [ + { + "type": "number" + }, + { + "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", + "type": "string" + } ], - "items": { - "$ref": "#/components/schemas/LibraryListingModality" - }, - "title": "Input Modalities", - "type": "array" + "description": "Model distribution surcharge incurred on this date in dollars", + "title": "Surcharge Cost" }, - "output_modalities": { - "default": [ - "text" + "minutes": { + "description": "Minutes used on this date", + "title": "Minutes", + "type": "integer" + }, + "inference_requests": { + "description": "Number of inference requests on this date", + "title": "Inference Requests", + "type": "integer" + } + }, + "required": [ + "date", + "subtotal", + "compute_cost", + "surcharge_cost", + "minutes", + "inference_requests" + ], + "title": "DailyDedicatedUsageV1", + "type": "object" + }, + "DailyModelApiUsageV1": { + "properties": { + "date": { + "description": "Date of the usage", + "format": "date", + "title": "Date", + "type": "string" + }, + "subtotal": { + "anyOf": [ + { + "type": "number" + }, + { + "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", + "type": "string" + } ], - "items": { - "$ref": "#/components/schemas/LibraryListingModality" - }, - "title": "Output Modalities", - "type": "array" + "description": "Subtotal cost incurred on this date in dollars", + "title": "Subtotal" }, - "license": { - "title": "License", + "input_tokens": { + "description": "Number of input tokens on this date", + "title": "Input Tokens", + "type": "integer" + }, + "output_tokens": { + "description": "Number of output tokens on this date", + "title": "Output Tokens", + "type": "integer" + }, + "cached_input_tokens": { + "description": "Number of cached input tokens on this date", + "title": "Cached Input Tokens", + "type": "integer" + } + }, + "required": [ + "date", + "subtotal", + "input_tokens", + "output_tokens", + "cached_input_tokens" + ], + "title": "DailyModelApiUsageV1", + "type": "object" + }, + "DailyTrainingUsageV1": { + "properties": { + "date": { + "description": "Date of the usage", + "format": "date", + "title": "Date", "type": "string" }, - "variant": { + "subtotal": { "anyOf": [ { - "type": "string" + "type": "number" }, { - "type": "null" - } - ], - "default": null, - "title": "Variant" - }, - "publisher": { - "anyOf": [ - { + "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", "type": "string" - }, - { - "type": "null" } ], - "default": null, - "title": "Publisher" + "description": "Subtotal cost incurred on this date in dollars", + "title": "Subtotal" }, - "model_api_slug": { + "minutes": { + "description": "Minutes used on this date", + "title": "Minutes", + "type": "integer" + } + }, + "required": [ + "date", + "subtotal", + "minutes" + ], + "title": "DailyTrainingUsageV1", + "type": "object" + }, + "DedicatedItemV1": { + "properties": { + "billable_resource": { + "$ref": "#/components/schemas/BillableResourceV1", + "description": "The model deployment resource" + }, + "subtotal": { "anyOf": [ { - "type": "string" + "type": "number" }, { - "type": "null" + "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", + "type": "string" } ], - "default": null, - "title": "Model Api Slug" + "description": "Subtotal cost in dollars for this billable resource", + "title": "Subtotal" }, - "release_date": { + "compute_cost": { "anyOf": [ { - "format": "date", - "type": "string" + "type": "number" }, { - "type": "null" + "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", + "type": "string" } ], - "default": null, - "title": "Release Date" + "description": "Compute cost in dollars for this billable resource", + "title": "Compute Cost" }, - "description": { + "surcharge_cost": { "anyOf": [ { - "type": "string" + "type": "number" }, { - "type": "null" + "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", + "type": "string" } ], - "default": null, - "title": "Description" + "description": "Model distribution surcharge in dollars for this billable resource", + "title": "Surcharge Cost" }, - "trending": { - "default": false, - "title": "Trending", - "type": "boolean" + "minutes": { + "description": "Total minutes used for this billable resource", + "title": "Minutes", + "type": "integer" + }, + "inference_requests": { + "description": "Total inference requests for this billable resource", + "title": "Inference Requests", + "type": "integer" + }, + "daily": { + "description": "Daily usage breakdown", + "items": { + "$ref": "#/components/schemas/DailyDedicatedUsageV1" + }, + "title": "Daily", + "type": "array" } }, "required": [ - "license" + "billable_resource", + "subtotal", + "compute_cost", + "surcharge_cost", + "minutes", + "inference_requests" ], - "title": "LibraryListingMetadataV1", + "title": "DedicatedItemV1", "type": "object" }, - "LibraryListingModality": { - "enum": [ - "text", - "image", - "audio", - "video", - "embedding", - "rerank" - ], - "title": "LibraryListingModality", - "type": "string" - }, - "LibraryListingV1": { - "description": "A library listing.", + "DedicatedUsageV1": { "properties": { - "display_name": { - "description": "Display name of the library listing", - "title": "Display Name", - "type": "string" - }, - "user_defined_id": { - "description": "User-defined identifier of the library listing", - "title": "User Defined Id", - "type": "string" - }, - "is_public": { - "description": "Whether the listing is publicly accessible", - "title": "Is Public", - "type": "boolean" - }, - "trending": { + "subtotal": { "anyOf": [ { - "type": "boolean" + "type": "number" }, { - "type": "null" + "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", + "type": "string" } ], - "description": "Whether the listing is trending", - "title": "Trending" - }, - "closed_source": { - "description": "Whether the listing is closed source (deployers cannot view or download the Truss, and forks copy mirrored weights instead of re-mirroring from upstream)", - "title": "Closed Source", - "type": "boolean" - }, - "created_at": { - "description": "Time the listing was created in ISO 8601 format", - "format": "date-time", - "title": "Created At", - "type": "string" - }, - "modified_at": { - "description": "Time the listing was last modified", - "format": "date-time", - "title": "Modified At", - "type": "string" + "description": "Subtotal cost in dollars after applying credits used", + "title": "Subtotal" }, - "metadata": { + "credits_used": { "anyOf": [ { - "$ref": "#/components/schemas/LibraryListingMetadataV1" + "type": "number" }, { - "type": "null" + "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", + "type": "string" } ], - "default": null, - "description": "Model-level metadata for this listing, if it has been uploaded." - } - }, - "required": [ - "display_name", - "user_defined_id", - "is_public", - "trending", - "closed_source", - "created_at", - "modified_at" - ], - "title": "LibraryListingV1", - "type": "object" - }, - "LibraryListingsV1": { - "description": "A list of library listings.", - "properties": { - "listings": { - "items": { - "$ref": "#/components/schemas/LibraryListingV1" - }, - "title": "Listings", - "type": "array" - } - }, - "required": [ - "listings" - ], - "title": "LibraryListingsV1", - "type": "object" - }, - "CreateLibraryListingRequestV1": { - "description": "Request to create a new library listing.", - "properties": { - "display_name": { - "description": "Display name of the library listing", - "title": "Display Name", - "type": "string" - }, - "user_defined_id": { - "description": "User-defined identifier of the library listing", - "title": "User Defined Id", - "type": "string" + "description": "Credits applied in dollars", + "title": "Credits Used" }, - "is_public": { - "default": false, - "description": "Whether the listing is publicly accessible", - "title": "Is Public", - "type": "boolean" + "total": { + "anyOf": [ + { + "type": "number" + }, + { + "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", + "type": "string" + } + ], + "description": "Total cost in dollars", + "title": "Total" }, - "closed_source": { - "default": false, - "description": "Whether the listing is closed source (deployers cannot view or download the Truss, and forks copy mirrored weights instead of re-mirroring from upstream)", - "title": "Closed Source", - "type": "boolean" + "minutes": { + "description": "Total minutes used", + "title": "Minutes", + "type": "integer" + }, + "breakdown": { + "description": "Per-deployment usage breakdown", + "items": { + "$ref": "#/components/schemas/DedicatedItemV1" + }, + "title": "Breakdown", + "type": "array" } }, "required": [ - "display_name", - "user_defined_id" + "subtotal", + "credits_used", + "total", + "minutes" ], - "title": "CreateLibraryListingRequestV1", + "title": "DedicatedUsageV1", "type": "object" }, - "LibraryListingTombstoneV1": { - "description": "A library listing tombstone.", + "ModelApiItemV1": { "properties": { - "user_defined_id": { - "description": "User-defined identifier of the library listing", - "title": "User Defined Id", + "model_name": { + "description": "Model name", + "title": "Model Name", "type": "string" }, - "deleted": { - "description": "Whether the library listing was deleted", - "title": "Deleted", - "type": "boolean" + "model_family": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Model family (e.g., llama, mistral)", + "title": "Model Family" + }, + "subtotal": { + "anyOf": [ + { + "type": "number" + }, + { + "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", + "type": "string" + } + ], + "description": "Subtotal cost in dollars for this model", + "title": "Subtotal" + }, + "input_tokens": { + "description": "Total input tokens for this model", + "title": "Input Tokens", + "type": "integer" + }, + "output_tokens": { + "description": "Total output tokens for this model", + "title": "Output Tokens", + "type": "integer" + }, + "cached_input_tokens": { + "description": "Total cached input tokens for this model", + "title": "Cached Input Tokens", + "type": "integer" + }, + "daily": { + "description": "Daily usage breakdown", + "items": { + "$ref": "#/components/schemas/DailyModelApiUsageV1" + }, + "title": "Daily", + "type": "array" } }, "required": [ - "user_defined_id", - "deleted" + "model_name", + "subtotal", + "input_tokens", + "output_tokens", + "cached_input_tokens" ], - "title": "LibraryListingTombstoneV1", + "title": "ModelApiItemV1", "type": "object" }, - "UpdateLibraryListingRequestV1": { - "description": "Request to update a library listing.", + "ModelApisUsageV1": { "properties": { - "display_name": { + "subtotal": { "anyOf": [ { - "type": "string" + "type": "number" }, { - "type": "null" + "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", + "type": "string" } ], - "default": null, - "description": "New display name for the library listing", - "title": "Display Name" + "description": "Subtotal cost in dollars after applying credits used", + "title": "Subtotal" }, - "is_public": { + "credits_used": { "anyOf": [ { - "type": "boolean" + "type": "number" }, { - "type": "null" + "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", + "type": "string" } ], - "default": null, - "description": "Whether the listing is publicly accessible", - "title": "Is Public" + "description": "Credits applied in dollars", + "title": "Credits Used" }, - "trending": { + "total": { "anyOf": [ { - "type": "boolean" + "type": "number" }, { - "type": "null" + "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", + "type": "string" } ], - "default": null, - "description": "Whether the listing is trending", - "title": "Trending" + "description": "Total cost in dollars", + "title": "Total" }, - "metadata": { + "breakdown": { + "description": "Per-model usage breakdown", + "items": { + "$ref": "#/components/schemas/ModelApiItemV1" + }, + "title": "Breakdown", + "type": "array" + } + }, + "required": [ + "subtotal", + "credits_used", + "total" + ], + "title": "ModelApisUsageV1", + "type": "object" + }, + "ResourceKind": { + "enum": [ + "LOOPS_SAMPLER", + "LOOPS_TRAINER", + "MODEL_DEPLOYMENT", + "TRAINING_JOB", + "CHAINLET" + ], + "title": "ResourceKind", + "type": "string" + }, + "TrainingItemV1": { + "properties": { + "billable_resource": { + "$ref": "#/components/schemas/BillableResourceV1", + "description": "The training job resource" + }, + "subtotal": { "anyOf": [ { - "$ref": "#/components/schemas/LibraryListingMetadataV1" + "type": "number" }, { - "type": "null" + "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", + "type": "string" } ], - "default": null, - "description": "Model-level metadata for the listing. When provided, replaces the stored metadata. Unknown fields are rejected." + "description": "Subtotal cost in dollars for this billable resource", + "title": "Subtotal" + }, + "minutes": { + "description": "Total minutes used for this billable resource", + "title": "Minutes", + "type": "integer" + }, + "daily": { + "description": "Daily usage breakdown", + "items": { + "$ref": "#/components/schemas/DailyTrainingUsageV1" + }, + "title": "Daily", + "type": "array" } }, - "title": "UpdateLibraryListingRequestV1", + "required": [ + "billable_resource", + "subtotal", + "minutes" + ], + "title": "TrainingItemV1", "type": "object" }, - "BenchmarkSnapshotV1": { + "TrainingUsageV1": { "properties": { - "run_id": { - "title": "Run Id", - "type": "string" + "subtotal": { + "anyOf": [ + { + "type": "number" + }, + { + "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", + "type": "string" + } + ], + "description": "Subtotal cost in dollars after applying credits used", + "title": "Subtotal" }, - "measured_at": { - "format": "date", - "title": "Measured At", - "type": "string" + "credits_used": { + "anyOf": [ + { + "type": "number" + }, + { + "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", + "type": "string" + } + ], + "description": "Credits applied in dollars", + "title": "Credits Used" }, - "llm": { + "total": { "anyOf": [ { - "$ref": "#/components/schemas/LLMBenchmarkMetricsV1" + "type": "number" }, { - "type": "null" + "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", + "type": "string" } ], - "default": null + "description": "Total cost in dollars", + "title": "Total" }, - "tts": { + "minutes": { + "description": "Total minutes used", + "title": "Minutes", + "type": "integer" + }, + "breakdown": { + "description": "Per-job usage breakdown", + "items": { + "$ref": "#/components/schemas/TrainingItemV1" + }, + "title": "Breakdown", + "type": "array" + } + }, + "required": [ + "subtotal", + "credits_used", + "total", + "minutes" + ], + "title": "TrainingUsageV1", + "type": "object" + }, + "UsageSummaryV1": { + "description": "Billing usage summary for the requested date range.", + "properties": { + "dedicated_usage": { "anyOf": [ { - "$ref": "#/components/schemas/TTSBenchmarkMetricsV1" + "$ref": "#/components/schemas/DedicatedUsageV1" }, { "type": "null" } ], - "default": null + "default": null, + "description": "Dedicated model serving usage" }, - "embedding": { + "training_usage": { "anyOf": [ { - "$ref": "#/components/schemas/EmbeddingBenchmarkMetricsV1" + "$ref": "#/components/schemas/TrainingUsageV1" }, { "type": "null" } ], - "default": null + "default": null, + "description": "Training usage" }, - "replicas": { + "model_apis_usage": { "anyOf": [ { - "type": "integer" + "$ref": "#/components/schemas/ModelApisUsageV1" }, { "type": "null" } ], - "default": 2, - "title": "Replicas" + "default": null, + "description": "Model APIs usage" + } + }, + "title": "UsageSummaryV1", + "type": "object" + }, + "UsageSummaryRequestV1": { + "properties": { + "start_date": { + "description": "Start date (ISO 8601, UTC). Earliest queryable: 2026-01-01.", + "format": "date-time", + "title": "Start Date", + "type": "string" }, - "profile": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": "512x256", - "title": "Profile" + "end_date": { + "description": "End date in ISO 8601 format (UTC). Date range cannot exceed 31 days.", + "format": "date-time", + "title": "End Date", + "type": "string" } }, "required": [ - "run_id", - "measured_at" + "start_date", + "end_date" ], - "title": "BenchmarkSnapshotV1", + "title": "UsageSummaryRequestV1", "type": "object" }, - "EmbeddingBenchmarkMetricsV1": { + "ToolCallUsageBucketV1": { + "description": "Server-side tool call usage for one day, provider, charge unit, and model.", "properties": { - "e2e_latency_ms_p50": { + "date": { + "description": "UTC day the usage was recorded on.", + "format": "date", + "title": "Date", + "type": "string" + }, + "provider": { + "description": "Tool provider, such as exa or parallel.", + "title": "Provider", + "type": "string" + }, + "sku": { + "description": "Charge unit, as `/`. The unit is what the provider reported, or the tool name when it reported none. Its meaning varies by provider.", + "title": "Sku", + "type": "string" + }, + "model": { + "description": "Model that made the tool calls.", + "title": "Model", + "type": "string" + }, + "calls": { + "description": "Number of tool calls.", + "title": "Calls", + "type": "integer" + }, + "quantity": { + "description": "Billable quantity in the provider's sku unit, summed over the calls.", + "title": "Quantity", + "type": "number" + } + }, + "required": [ + "date", + "provider", + "sku", + "model", + "calls", + "quantity" + ], + "title": "ToolCallUsageBucketV1", + "type": "object" + }, + "ToolCallUsageResponseV1": { + "description": "Daily server-side tool call usage, ordered by day, provider, sku, and model.", + "properties": { + "items": { + "items": { + "$ref": "#/components/schemas/ToolCallUsageBucketV1" + }, + "title": "Items", + "type": "array" + } + }, + "title": "ToolCallUsageResponseV1", + "type": "object" + }, + "ToolCallUsageRequestV1": { + "properties": { + "start_date": { + "description": "Inclusive UTC calendar day at the start of the query range.", + "format": "date", + "title": "Start Date", + "type": "string" + }, + "end_date": { "anyOf": [ { - "type": "number" + "format": "date", + "type": "string" }, { "type": "null" } ], "default": null, - "title": "E2E Latency Ms P50" + "description": "Exclusive UTC calendar day at the end of the query range. Defaults to the day after the current UTC date so current-day usage is included. The date range cannot exceed 90 days.", + "title": "End Date" + } + }, + "required": [ + "start_date" + ], + "title": "ToolCallUsageRequestV1", + "type": "object" + }, + "UserInfoV1": { + "description": "A Baseten user.", + "properties": { + "user_id": { + "description": "Unique identifier for the user", + "title": "User Id", + "type": "string" }, - "e2e_latency_ms_p99": { + "email": { "anyOf": [ { - "type": "number" + "type": "string" }, { "type": "null" } ], "default": null, - "title": "E2E Latency Ms P99" + "description": "Email address of the user", + "title": "Email" }, - "input_tokens_per_sec": { + "name": { "anyOf": [ { - "type": "number" + "type": "string" }, { "type": "null" } ], "default": null, - "title": "Input Tokens Per Sec" + "description": "Display name of the user", + "title": "Name" }, - "requests_per_sec": { + "workspace_name": { "anyOf": [ { - "type": "number" + "type": "string" }, { "type": "null" } ], "default": null, - "title": "Requests Per Sec" + "description": "Name of the user's workspace", + "title": "Workspace Name" } }, - "title": "EmbeddingBenchmarkMetricsV1", + "required": [ + "user_id" + ], + "title": "UserInfoV1", "type": "object" }, - "LLMBenchmarkMetricsV1": { + "UsersResponseV1": { + "description": "A page of users in the caller's workspace.", "properties": { - "ttft_ms_p50": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Ttft Ms P50" + "items": { + "description": "Items in this page.", + "items": { + "$ref": "#/components/schemas/UserInfoV1" + }, + "title": "Items", + "type": "array" }, - "output_tokens_per_sec_per_user_p50": { + "pagination": { + "$ref": "#/components/schemas/PaginationResponseV1", + "description": "Pagination metadata for the page." + } + }, + "required": [ + "items", + "pagination" + ], + "title": "UsersResponseV1", + "type": "object" + }, + "UsersRequestV1": { + "description": "Request parameters for listing users.", + "properties": { + "cursor": { "anyOf": [ { - "type": "number" + "type": "string" }, { "type": "null" } ], "default": null, - "title": "Output Tokens Per Sec Per User P50" + "description": "Opaque cursor returned by a previous page. Omit to fetch the first page.", + "title": "Cursor" }, - "max_concurrent_users_at_50ms_tpot": { + "limit": { + "default": 100, + "description": "Maximum number of items to return.", + "maximum": 1000, + "minimum": 1, + "title": "Limit", + "type": "integer" + }, + "email": { "anyOf": [ { - "type": "integer" + "type": "string" }, { "type": "null" } ], "default": null, - "title": "Max Concurrent Users At 50Ms Tpot" + "description": "When set, returns only users with this exact email, if any.", + "title": "Email" + } + }, + "title": "UsersRequestV1", + "type": "object" + }, + "AwsAssumeRoleV1": { + "description": "AWS AssumeRole trust-policy inputs for the organization.", + "properties": { + "baseten_role_arn": { + "description": "Baseten role ARN to allow in an IAM role's trust policy", + "title": "Baseten Role Arn", + "type": "string" }, - "requests_per_sec_p50": { + "external_id": { + "description": "sts:ExternalId Baseten presents when assuming the role", + "title": "External Id", + "type": "string" + } + }, + "required": [ + "baseten_role_arn", + "external_id" + ], + "title": "AwsAssumeRoleV1", + "type": "object" + }, + "OrganizationInfoV1": { + "description": "The caller's organization.", + "properties": { + "org_id": { + "description": "Unique identifier for the organization", + "title": "Org Id", + "type": "string" + }, + "name": { "anyOf": [ { - "type": "number" + "type": "string" }, { "type": "null" } ], "default": null, - "title": "Requests Per Sec P50" + "description": "Display name of the organization", + "title": "Name" }, - "cost_per_1m_tokens_usd": { + "created_at": { + "description": "Time the organization was created in ISO 8601 format", + "format": "date-time", + "title": "Created At", + "type": "string" + }, + "aws_assume_role": { "anyOf": [ { - "type": "number" + "$ref": "#/components/schemas/AwsAssumeRoleV1" }, { "type": "null" } ], "default": null, - "title": "Cost Per 1M Tokens Usd" + "description": "AWS AssumeRole trust-policy inputs; null while the method is not enabled for the organization" } }, - "title": "LLMBenchmarkMetricsV1", + "required": [ + "org_id", + "created_at" + ], + "title": "OrganizationInfoV1", "type": "object" }, - "LibraryListingVersionV1": { - "description": "A library listing version.", + "GatewayEventTokensV1": { "properties": { - "version_tag": { - "description": "Human-readable tag for this version", - "title": "Version Tag", + "inputTokens": { + "description": "Cached and uncached input tokens.", + "title": "Inputtokens", + "type": "integer" + }, + "outputTokens": { + "description": "Output tokens.", + "title": "Outputtokens", + "type": "integer" + }, + "cachedInputTokens": { + "description": "Cached input tokens.", + "title": "Cachedinputtokens", + "type": "integer" + } + }, + "required": [ + "inputTokens", + "outputTokens", + "cachedInputTokens" + ], + "title": "GatewayEventTokensV1", + "type": "object" + }, + "GatewayEventV1": { + "properties": { + "type": { + "default": "API_BILLING_USAGE", + "description": "Event type.", + "title": "Type", "type": "string" }, - "is_live": { - "description": "Whether this version is the live version", - "title": "Is Live", - "type": "boolean" + "idempotencyKey": { + "description": "Deduplication key.", + "title": "Idempotencykey", + "type": "string" }, - "allow_truss_download": { - "description": "Whether users deploying this model can download the Truss", - "title": "Allow Truss Download", - "type": "boolean" + "timestamp": { + "description": "Billing event time (ISO 8601, UTC).", + "title": "Timestamp", + "type": "string" }, - "oracle_version_id": { - "description": "Id of the source model version", - "title": "Oracle Version Id", + "requestId": { + "description": "Inference request ID.", + "title": "Requestid", "type": "string" }, - "created_at": { - "description": "Time the version was created in ISO 8601 format", - "format": "date-time", - "title": "Created At", + "modelSlug": { + "description": "Served model.", + "title": "Modelslug", "type": "string" }, - "modified_at": { - "description": "Time the version was last modified", - "format": "date-time", - "title": "Modified At", + "externalEntityId": { + "description": "Calling group's external ID.", + "title": "Externalentityid", "type": "string" }, - "benchmark": { - "anyOf": [ - { - "$ref": "#/components/schemas/BenchmarkSnapshotV1" - }, - { - "type": "null" - } - ], - "default": null, - "description": "Benchmark snapshot for this version, if one has been uploaded." + "apiKeyPrefix": { + "description": "API key prefix.", + "title": "Apikeyprefix", + "type": "string" + }, + "tokens": { + "$ref": "#/components/schemas/GatewayEventTokensV1" } }, "required": [ - "version_tag", - "is_live", - "allow_truss_download", - "oracle_version_id", - "created_at", - "modified_at" + "idempotencyKey", + "timestamp", + "requestId", + "modelSlug", + "externalEntityId", + "apiKeyPrefix", + "tokens" ], - "title": "LibraryListingVersionV1", + "title": "GatewayEventV1", "type": "object" }, - "TTSBenchmarkMetricsV1": { + "GatewayEventsResponseV1": { "properties": { - "ttft_ms_p50": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Ttft Ms P50" + "items": { + "description": "Items in this page.", + "items": { + "$ref": "#/components/schemas/GatewayEventV1" + }, + "title": "Items", + "type": "array" }, - "max_concurrent_streams_at_rtf1": { + "pagination": { + "$ref": "#/components/schemas/PaginationResponseV1", + "description": "Pagination metadata for the page." + } + }, + "required": [ + "items", + "pagination" + ], + "title": "GatewayEventsResponseV1", + "type": "object" + }, + "GatewayEventsRequestV1": { + "properties": { + "start_time": { "anyOf": [ { - "type": "integer" + "format": "date-time", + "type": "string" }, { "type": "null" } ], "default": null, - "title": "Max Concurrent Streams At Rtf1" + "description": "Inclusive start (ISO 8601, UTC). Required without a cursor.", + "title": "Start Time" }, - "ttft_ms_p50_at_max_concurrency": { + "end_time": { "anyOf": [ { - "type": "number" + "format": "date-time", + "type": "string" }, { "type": "null" } ], "default": null, - "title": "Ttft Ms P50 At Max Concurrency" + "description": "Exclusive end (ISO 8601, UTC). Defaults to now.", + "title": "End Time" }, - "cost_per_audio_minute_usd": { + "limit": { "anyOf": [ { - "type": "number" + "maximum": 1000, + "minimum": 1, + "type": "integer" }, { "type": "null" } ], "default": null, - "title": "Cost Per Audio Minute Usd" - } - }, - "title": "TTSBenchmarkMetricsV1", - "type": "object" - }, - "LibraryListingVersionsV1": { - "description": "A list of library listing versions.", - "properties": { - "versions": { + "description": "Max events. Default 100, max 1000.", + "title": "Limit" + }, + "api_keys": { + "description": "Return only events for these API key prefixes, repeated once per prefix.", "items": { - "$ref": "#/components/schemas/LibraryListingVersionV1" + "type": "string" }, - "title": "Versions", + "title": "Api Keys", "type": "array" - } - }, - "required": [ - "versions" - ], - "title": "LibraryListingVersionsV1", - "type": "object" - }, - "CreateLibraryListingVersionRequestV1": { - "description": "Request to create a new library listing version from an existing model version.", - "properties": { - "display_name": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "description": "Display name of the library listing. Required when creating a new listing.", - "title": "Display Name" - }, - "is_public": { - "default": false, - "description": "Whether the listing is publicly accessible. Only used when creating a new listing.", - "title": "Is Public", - "type": "boolean" - }, - "oracle_version_id": { - "description": "Id of the source model version to publish", - "title": "Oracle Version Id", - "type": "string" - }, - "allow_truss_download": { - "default": false, - "description": "Whether users deploying this model can download the Truss", - "title": "Allow Truss Download", - "type": "boolean" - }, - "closed_source": { - "default": false, - "description": "Whether the listing is closed source (deployers cannot view or download the Truss, and forks copy mirrored weights instead of re-mirroring from upstream). Only used when creating a new listing.", - "title": "Closed Source", - "type": "boolean" }, - "version_tag": { - "description": "Human-readable tag for this version", - "title": "Version Tag", - "type": "string" - } - }, - "required": [ - "oracle_version_id", - "version_tag" - ], - "title": "CreateLibraryListingVersionRequestV1", - "type": "object" - }, - "LibraryListingVersionTombstoneV1": { - "description": "A library listing version tombstone.", - "properties": { - "version_tag": { - "description": "Human-readable tag for this version", - "title": "Version Tag", - "type": "string" + "external_entity_ids": { + "description": "Return only events for these external entity IDs, repeated once per ID.", + "items": { + "type": "string" + }, + "title": "External Entity Ids", + "type": "array" }, - "deleted": { - "description": "Whether the library listing version was deleted", - "title": "Deleted", - "type": "boolean" + "cursor": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Next-page cursor. Other parameters are ignored.", + "title": "Cursor" } }, - "required": [ - "version_tag", - "deleted" - ], - "title": "LibraryListingVersionTombstoneV1", + "title": "GatewayEventsRequestV1", "type": "object" }, - "UpdateLibraryListingVersionRequestV1": { - "description": "Request to update a library listing version.", + "ExploreCostV1": { "properties": { - "is_live": { + "input": { "anyOf": [ { - "type": "boolean" + "type": "number" }, { "type": "null" } ], "default": null, - "description": "Whether this version should be the live version. Setting to true demotes the current live version.", - "title": "Is Live" + "description": "USD per 1M input tokens, when available.", + "title": "Input" }, - "allow_truss_download": { + "output": { "anyOf": [ { - "type": "boolean" + "type": "number" }, { "type": "null" } ], "default": null, - "description": "Whether users deploying this model can download the Truss", - "title": "Allow Truss Download" + "description": "USD per 1M output tokens, when available.", + "title": "Output" }, - "benchmark": { + "cache_read": { "anyOf": [ { - "$ref": "#/components/schemas/BenchmarkSnapshotV1" + "type": "number" }, { "type": "null" } ], "default": null, - "description": "Benchmark snapshot for this version. When provided, replaces the stored benchmark." - } - }, - "title": "UpdateLibraryListingVersionRequestV1", - "type": "object" - }, - "ModelApisCostBucketV1": { - "description": "One daily bucket and the costs attributed to it.", - "properties": { - "date": { - "description": "UTC calendar date for this bucket, from midnight inclusive to the next midnight exclusive.", - "format": "date", - "title": "Date", - "type": "string" + "description": "USD per 1M input tokens read from cache, when available.", + "title": "Cache Read" }, - "results": { - "description": "Cost totals for the observed combinations of requested dimensions in this bucket, ordered by those dimensions. Empty when the day has no matching usage.", - "items": { - "$ref": "#/components/schemas/ModelApisCostResultV1" - }, - "title": "Results", - "type": "array" + "cache_write": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "description": "USD per 1M input tokens written to cache, when available.", + "title": "Cache Write" + }, + "long_context": { + "anyOf": [ + { + "$ref": "#/components/schemas/ExploreCostValuesV1" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Prices for long-context requests, when the provider tiers by context length." } }, - "required": [ - "date" - ], - "title": "ModelApisCostBucketV1", + "title": "ExploreCostV1", "type": "object" }, - "ModelApisCostResultV1": { + "ExploreCostValuesV1": { "properties": { - "api_key_prefixes": { + "input": { "anyOf": [ { - "items": { - "type": "string" - }, - "type": "array" + "type": "number" }, { "type": "null" } ], "default": null, - "description": "The single attributed API key prefix for this result. Null when not grouping by api_key_prefix or when attribution is unavailable.", - "title": "Api Key Prefixes" + "description": "USD per 1M input tokens, when available.", + "title": "Input" }, - "user_id": { + "output": { "anyOf": [ { - "type": "string" + "type": "number" }, { "type": "null" } ], "default": null, - "description": "Attributed user ID. Null when not grouping by user or when attribution is unavailable.", - "title": "User Id" + "description": "USD per 1M output tokens, when available.", + "title": "Output" }, - "model": { + "cache_read": { "anyOf": [ { - "type": "string" + "type": "number" }, { "type": "null" } ], "default": null, - "description": "Model identifier. Null when not grouping by model.", - "title": "Model" + "description": "USD per 1M input tokens read from cache, when available.", + "title": "Cache Read" }, - "service_tier": { + "cache_write": { "anyOf": [ { - "type": "string" + "type": "number" }, { "type": "null" } ], "default": null, - "description": "Service tier. Null when not grouping by service_tier or when attribution is unavailable.", - "title": "Service Tier" - }, - "subtotal": { - "description": "Model API cost in USD for this day and grouping combination, returned as an exact decimal string preserving fractional-cent amounts. This amount may differ from finalized invoice amounts.", - "examples": [ - "0.00000123" - ], - "title": "Subtotal", - "type": "string" + "description": "USD per 1M input tokens written to cache, when available.", + "title": "Cache Write" } }, - "required": [ - "subtotal" - ], - "title": "ModelApisCostResultV1", + "title": "ExploreCostValuesV1", "type": "object" }, - "ModelApisCostsResponseV1": { - "description": "One non-overlapping bucket per UTC day, ordered oldest first with no gaps.\n\nDays without matching usage are included with an empty results list.", + "ExploreMetadataAPIFormatsV1": { "properties": { - "items": { - "description": "Items in this page.", - "items": { - "$ref": "#/components/schemas/ModelApisCostBucketV1" - }, - "title": "Items", - "type": "array" + "messages": { + "default": false, + "description": "Anthropic Messages API support.", + "title": "Messages", + "type": "boolean" }, - "pagination": { - "$ref": "#/components/schemas/PaginationResponseV1", - "description": "Pagination metadata for the page." + "responses": { + "default": false, + "description": "OpenAI Responses API support.", + "title": "Responses", + "type": "boolean" + }, + "chat_completions": { + "default": false, + "description": "OpenAI Chat Completions API support.", + "title": "Chat Completions", + "type": "boolean" } }, - "required": [ - "items", - "pagination" - ], - "title": "ModelApisCostsResponseV1", + "title": "ExploreMetadataAPIFormatsV1", "type": "object" }, - "ModelApiCostDimensionV1": { - "enum": [ - "api_key_prefix", - "user", - "model", - "service_tier" - ], - "title": "ModelApiCostDimensionV1", - "type": "string" - }, - "ModelApisCostsRequestV1": { + "ExploreMetadataV1": { "properties": { - "cursor": { + "slug": { "anyOf": [ { "type": "string" @@ -26247,33 +30803,22 @@ "type": "null" } ], - "default": null, - "description": "Opaque cursor returned by a previous page. Omit to fetch the first page.", - "title": "Cursor" - }, - "limit": { - "default": 7, - "description": "Number of daily cost buckets to return. Defaults to 7; maximum 31.", - "maximum": 31, - "minimum": 1, - "title": "Limit", - "type": "integer" + "description": "Metadata slug, e.g. 'anthropic/claude-opus-4'; null for rows without one.", + "title": "Slug" }, - "start_date": { + "display_name": { "anyOf": [ { - "format": "date", "type": "string" }, { "type": "null" } ], - "default": null, - "description": "Inclusive UTC calendar day at the start of the query range. Defaults to the previous UTC date, cannot be before 2026-08-05, and is ignored when you pass a cursor.", - "title": "Start Date" + "description": "Model display name, when available.", + "title": "Display Name" }, - "end_date": { + "release_date": { "anyOf": [ { "format": "date", @@ -26283,79 +30828,10 @@ "type": "null" } ], - "default": null, - "description": "Exclusive UTC calendar day at the end of the query range. Defaults to the day after the current UTC date so current-day usage is included. The date range cannot exceed 90 days.", - "title": "End Date" - }, - "group_by": { - "description": "Dimensions to break costs down by, repeated once per dimension: api_key_prefix, user, model, or service_tier. Each result represents one observed combination of the requested dimensions within that day. For example, grouping by api_key_prefix and user returns each API-key and user pair that had usage. Combinations without usage are omitted, so result counts can differ between days. Omit for daily organization totals.", - "items": { - "$ref": "#/components/schemas/ModelApiCostDimensionV1" - }, - "title": "Group By", - "type": "array" - }, - "api_key_prefixes": { - "description": "Return only costs for these exact API key prefixes, repeated once per prefix.", - "items": { - "type": "string" - }, - "title": "Api Key Prefixes", - "type": "array" - }, - "user_ids": { - "description": "Return only costs attributed to these exact user IDs, repeated once per ID.", - "items": { - "type": "string" - }, - "title": "User Ids", - "type": "array" - }, - "models": { - "description": "Return only costs for these exact model identifiers, repeated once per model.", - "items": { - "type": "string" - }, - "title": "Models", - "type": "array" - }, - "service_tiers": { - "description": "Return only costs for these exact service tiers, repeated once per tier.", - "items": { - "type": "string" - }, - "title": "Service Tiers", - "type": "array" - } - }, - "title": "ModelApisCostsRequestV1", - "type": "object" - }, - "BillableResourceV1": { - "properties": { - "id": { - "description": "Unique identifier of the resource", - "title": "Id", - "type": "string" - }, - "kind": { - "$ref": "#/components/schemas/ResourceKind", - "description": "Resource kind (MODEL_DEPLOYMENT, CHAINLET, TRAINING_JOB, LOOPS_TRAINER, or LOOPS_SAMPLER)" - }, - "name": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "description": "Name of the resource", - "title": "Name" + "description": "Model release date. Month-only source dates use the first day of that month.", + "title": "Release Date" }, - "model_id": { + "provider": { "anyOf": [ { "type": "string" @@ -26363,446 +30839,629 @@ { "type": "null" } - ], - "default": null, - "description": "Unique identifier of the parent model for model deployments and chainlets", - "title": "Model Id" + ], + "description": "Provider key derived from the slug prefix, e.g. 'anthropic'; null for unprefixed slugs.", + "title": "Provider" }, - "model_name": { + "context_window": { "anyOf": [ { - "type": "string" + "type": "integer" }, { "type": "null" } ], - "default": null, - "description": "Name of the parent resource (e.g., model name for model deployments, training project name for training jobs)", - "title": "Model Name" - }, - "is_deleted": { - "description": "Indicates if the resource has been deleted", - "title": "Is Deleted", - "type": "boolean" + "description": "Total context window in tokens.", + "title": "Context Window" }, - "instance_type": { + "max_output_tokens": { "anyOf": [ { - "type": "string" + "type": "integer" }, { "type": "null" } ], - "default": null, - "description": "Instance type used", - "title": "Instance Type" + "description": "Maximum output tokens per response.", + "title": "Max Output Tokens" }, - "base_model": { + "input_modalities": { + "description": "Accepted input modalities.", + "items": { + "type": "string" + }, + "title": "Input Modalities", + "type": "array" + }, + "tools": { "anyOf": [ { - "type": "string" + "type": "boolean" }, { "type": "null" } ], - "default": null, - "description": "Base model used by this Loops trainer or sampler", - "title": "Base Model" + "description": "Whether the model supports tool calling.", + "title": "Tools" }, - "environment_name": { + "reasoning_effort_levels": { "anyOf": [ { - "type": "string" + "items": { + "type": "string" + }, + "type": "array" }, { "type": "null" } ], - "default": null, - "description": "Environment name (e.g., 'production', 'staging')", - "title": "Environment Name" + "description": "Reasoning effort levels the model supports.", + "title": "Reasoning Effort Levels" }, - "chain_metadata": { + "parallel_tool_calls": { "anyOf": [ { - "$ref": "#/components/schemas/ChainMetadataV1" + "type": "boolean" }, { "type": "null" } ], - "default": null, - "description": "Chain metadata if this is a chainlet deployment" + "description": "Whether the model supports parallel tool calls.", + "title": "Parallel Tool Calls" }, - "team_id": { + "supported_api_formats": { "anyOf": [ { - "type": "string" + "$ref": "#/components/schemas/ExploreMetadataAPIFormatsV1" }, { "type": "null" } ], - "default": null, - "description": "Unique identifier of the team that owns the resource. Only present for organizations with multiple teams enabled.", - "title": "Team Id" + "description": "API formats the model supports." }, - "team_name": { + "cost": { "anyOf": [ { - "type": "string" + "$ref": "#/components/schemas/ExploreCostV1" }, { "type": "null" } ], - "default": null, - "description": "Name of the team that owns the resource. Only present for organizations with multiple teams enabled.", - "title": "Team Name" + "description": "Provider list prices in USD per 1M tokens, when available." } }, "required": [ - "id", - "kind", - "is_deleted" + "slug", + "display_name", + "release_date", + "provider", + "context_window", + "max_output_tokens", + "input_modalities", + "tools", + "reasoning_effort_levels", + "parallel_tool_calls", + "supported_api_formats", + "cost" ], - "title": "BillableResourceV1", + "title": "ExploreMetadataV1", "type": "object" }, - "ChainMetadataV1": { + "ExploreMetadataResponseV1": { "properties": { - "chain_id": { - "description": "Unique identifier of the chain", - "title": "Chain Id", - "type": "string" - }, - "chain_name": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "description": "Name of the chain", - "title": "Chain Name" + "items": { + "description": "Items in this page.", + "items": { + "$ref": "#/components/schemas/ExploreMetadataV1" + }, + "title": "Items", + "type": "array" }, - "chain_deployment_id": { - "description": "Unique identifier of the chain deployment", - "title": "Chain Deployment Id", - "type": "string" + "pagination": { + "$ref": "#/components/schemas/PaginationResponseV1", + "description": "Pagination metadata for the page." } }, "required": [ - "chain_id", - "chain_deployment_id" + "items", + "pagination" ], - "title": "ChainMetadataV1", + "title": "ExploreMetadataResponseV1", "type": "object" }, - "DailyDedicatedUsageV1": { + "ExploreMetadataRequestV1": { "properties": { - "date": { - "description": "Date of the usage", - "format": "date", - "title": "Date", - "type": "string" - }, - "subtotal": { + "cursor": { "anyOf": [ { - "type": "number" + "type": "string" }, { - "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", - "type": "string" + "type": "null" } ], - "description": "Subtotal cost incurred on this date in dollars", - "title": "Subtotal" + "default": null, + "description": "Opaque cursor returned by a previous page. Omit to fetch the first page.", + "title": "Cursor" }, - "compute_cost": { + "limit": { + "default": 100, + "description": "Maximum number of items to return.", + "maximum": 1000, + "minimum": 1, + "title": "Limit", + "type": "integer" + }, + "provider": { "anyOf": [ { - "type": "number" + "type": "string" }, { - "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", - "type": "string" + "type": "null" } ], - "description": "Compute cost incurred on this date in dollars", - "title": "Compute Cost" + "default": null, + "description": "Filter to a provider by slug prefix, e.g. 'anthropic'. Preserved by the cursor; if repeated, must match the original filter.", + "title": "Provider" }, - "surcharge_cost": { + "q": { "anyOf": [ { - "type": "number" + "type": "string" }, { - "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", - "type": "string" + "type": "null" } ], - "description": "Model distribution surcharge incurred on this date in dollars", - "title": "Surcharge Cost" + "default": null, + "description": "Case-insensitive substring search over metadata slugs. Preserved by the cursor; if repeated, must match the original filter.", + "title": "Q" + } + }, + "title": "ExploreMetadataRequestV1", + "type": "object" + }, + "RouteTargetAnthropicV1": { + "additionalProperties": false, + "properties": { + "type": { + "const": "ANTHROPIC", + "description": "Target kind for Anthropic.", + "title": "Type", + "type": "string" }, - "minutes": { - "description": "Minutes used on this date", - "title": "Minutes", - "type": "integer" + "model": { + "description": "Model name sent to the provider.", + "minLength": 1, + "title": "Model", + "type": "string" }, - "inference_requests": { - "description": "Number of inference requests on this date", - "title": "Inference Requests", - "type": "integer" + "secret_name": { + "description": "Name of a credential secret owned by the route's team.", + "minLength": 1, + "title": "Secret Name", + "type": "string" } }, "required": [ - "date", - "subtotal", - "compute_cost", - "surcharge_cost", - "minutes", - "inference_requests" + "type", + "model", + "secret_name" ], - "title": "DailyDedicatedUsageV1", + "title": "RouteTargetAnthropicV1", "type": "object" }, - "DailyModelApiUsageV1": { + "RouteTargetBasetenModelAPIV1": { + "additionalProperties": false, "properties": { - "date": { - "description": "Date of the usage", - "format": "date", - "title": "Date", + "type": { + "const": "BASETEN_MODEL_API", + "description": "Target kind for a Baseten Model API.", + "title": "Type", + "type": "string" + }, + "model": { + "description": "Name of the target Model API.", + "minLength": 1, + "title": "Model", + "type": "string" + } + }, + "required": [ + "type", + "model" + ], + "title": "RouteTargetBasetenModelAPIV1", + "type": "object" + }, + "RouteTargetOpenAIV1": { + "additionalProperties": false, + "properties": { + "type": { + "const": "OPENAI", + "description": "Target kind for OpenAI.", + "title": "Type", + "type": "string" + }, + "model": { + "description": "Model name sent to the provider.", + "minLength": 1, + "title": "Model", + "type": "string" + }, + "secret_name": { + "description": "Name of a credential secret owned by the route's team.", + "minLength": 1, + "title": "Secret Name", + "type": "string" + } + }, + "required": [ + "type", + "model", + "secret_name" + ], + "title": "RouteTargetOpenAIV1", + "type": "object" + }, + "RouteTargetXAIV1": { + "additionalProperties": false, + "properties": { + "type": { + "const": "XAI", + "description": "Target kind for xAI.", + "title": "Type", + "type": "string" + }, + "model": { + "description": "Model name sent to the provider.", + "minLength": 1, + "title": "Model", + "type": "string" + }, + "secret_name": { + "description": "Name of a credential secret owned by the route's team.", + "minLength": 1, + "title": "Secret Name", + "type": "string" + } + }, + "required": [ + "type", + "model", + "secret_name" + ], + "title": "RouteTargetXAIV1", + "type": "object" + }, + "RouteV1": { + "properties": { + "id": { + "description": "Stable route identifier.", + "title": "Id", + "type": "string" + }, + "name": { + "description": "Name to send in the inference request's model field.", + "title": "Name", + "type": "string" + }, + "team_id": { + "description": "Identifier of the owning team.", + "title": "Team Id", "type": "string" }, - "subtotal": { - "anyOf": [ + "team_name": { + "description": "Name of the owning team.", + "title": "Team Name", + "type": "string" + }, + "display_name": { + "description": "Display label, defaulting to the route name.", + "title": "Display Name", + "type": "string" + }, + "description": { + "description": "Short description of the route, empty when unset.", + "title": "Description", + "type": "string" + }, + "target": { + "description": "Configured upstream target.", + "discriminator": { + "mapping": { + "ANTHROPIC": "#/components/schemas/RouteTargetAnthropicV1", + "BASETEN_MODEL_API": "#/components/schemas/RouteTargetBasetenModelAPIV1", + "OPENAI": "#/components/schemas/RouteTargetOpenAIV1", + "XAI": "#/components/schemas/RouteTargetXAIV1" + }, + "propertyName": "type" + }, + "oneOf": [ { - "type": "number" + "$ref": "#/components/schemas/RouteTargetBasetenModelAPIV1" }, { - "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", - "type": "string" + "$ref": "#/components/schemas/RouteTargetAnthropicV1" + }, + { + "$ref": "#/components/schemas/RouteTargetOpenAIV1" + }, + { + "$ref": "#/components/schemas/RouteTargetXAIV1" } ], - "description": "Subtotal cost incurred on this date in dollars", - "title": "Subtotal" + "title": "Target" }, - "input_tokens": { - "description": "Number of input tokens on this date", - "title": "Input Tokens", - "type": "integer" + "metadata": { + "anyOf": [ + { + "$ref": "#/components/schemas/ExploreMetadataV1" + }, + { + "type": "null" + } + ], + "description": "Resolved model metadata; null when the route has no linked metadata row." }, - "output_tokens": { - "description": "Number of output tokens on this date", - "title": "Output Tokens", - "type": "integer" + "invoke_url": { + "description": "Base URL for inference requests using this route.", + "title": "Invoke Url", + "type": "string" }, - "cached_input_tokens": { - "description": "Number of cached input tokens on this date", - "title": "Cached Input Tokens", - "type": "integer" + "created_at": { + "description": "Creation time, ISO 8601.", + "format": "date-time", + "title": "Created At", + "type": "string" } }, "required": [ - "date", - "subtotal", - "input_tokens", - "output_tokens", - "cached_input_tokens" + "id", + "name", + "team_id", + "team_name", + "display_name", + "description", + "target", + "metadata", + "invoke_url", + "created_at" ], - "title": "DailyModelApiUsageV1", + "title": "RouteV1", "type": "object" }, - "DailyTrainingUsageV1": { + "RoutesResponseV1": { "properties": { - "date": { - "description": "Date of the usage", - "format": "date", - "title": "Date", - "type": "string" - }, - "subtotal": { - "anyOf": [ - { - "type": "number" - }, - { - "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", - "type": "string" - } - ], - "description": "Subtotal cost incurred on this date in dollars", - "title": "Subtotal" + "items": { + "description": "Items in this page.", + "items": { + "$ref": "#/components/schemas/RouteV1" + }, + "title": "Items", + "type": "array" }, - "minutes": { - "description": "Minutes used on this date", - "title": "Minutes", - "type": "integer" + "pagination": { + "$ref": "#/components/schemas/PaginationResponseV1", + "description": "Pagination metadata for the page." } }, "required": [ - "date", - "subtotal", - "minutes" + "items", + "pagination" ], - "title": "DailyTrainingUsageV1", + "title": "RoutesResponseV1", "type": "object" }, - "DedicatedItemV1": { + "RoutesRequestV1": { "properties": { - "billable_resource": { - "$ref": "#/components/schemas/BillableResourceV1", - "description": "The model deployment resource" - }, - "subtotal": { + "cursor": { "anyOf": [ { - "type": "number" + "type": "string" }, { - "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", - "type": "string" + "type": "null" } ], - "description": "Subtotal cost in dollars for this billable resource", - "title": "Subtotal" + "default": null, + "description": "Opaque cursor returned by a previous page. Omit to fetch the first page.", + "title": "Cursor" }, - "compute_cost": { + "limit": { + "default": 100, + "description": "Maximum number of items to return.", + "maximum": 1000, + "minimum": 1, + "title": "Limit", + "type": "integer" + }, + "team_id": { "anyOf": [ { - "type": "number" + "type": "string" }, { - "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", - "type": "string" + "type": "null" } ], - "description": "Compute cost in dollars for this billable resource", - "title": "Compute Cost" + "default": null, + "description": "Filter by owning team ID. Preserved by the cursor; if repeated, must match the original filter.", + "title": "Team Id" }, - "surcharge_cost": { + "name": { "anyOf": [ { - "type": "number" + "type": "string" }, { - "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", - "type": "string" + "type": "null" } ], - "description": "Model distribution surcharge in dollars for this billable resource", - "title": "Surcharge Cost" - }, - "minutes": { - "description": "Total minutes used for this billable resource", - "title": "Minutes", - "type": "integer" - }, - "inference_requests": { - "description": "Total inference requests for this billable resource", - "title": "Inference Requests", - "type": "integer" - }, - "daily": { - "description": "Daily usage breakdown", - "items": { - "$ref": "#/components/schemas/DailyDedicatedUsageV1" - }, - "title": "Daily", - "type": "array" + "default": null, + "description": "Filter by exact route name. Preserved by the cursor; if repeated, must match the original filter.", + "title": "Name" } }, - "required": [ - "billable_resource", - "subtotal", - "compute_cost", - "surcharge_cost", - "minutes", - "inference_requests" - ], - "title": "DedicatedItemV1", + "title": "RoutesRequestV1", "type": "object" }, - "DedicatedUsageV1": { + "CreateRouteRequestV1": { + "additionalProperties": false, "properties": { - "subtotal": { + "team_id": { "anyOf": [ { - "type": "number" + "minLength": 1, + "type": "string" }, { - "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", - "type": "string" + "type": "null" } ], - "description": "Subtotal cost in dollars after applying credits used", - "title": "Subtotal" + "default": null, + "description": "Identifier of the team that owns the route. When omitted, uses your organization's default team.", + "examples": [ + "abc1234" + ], + "title": "Team Id" }, - "credits_used": { + "display_name": { "anyOf": [ { - "type": "number" + "maxLength": 255, + "minLength": 1, + "type": "string" }, { - "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", - "type": "string" + "type": "null" } ], - "description": "Credits applied in dollars", - "title": "Credits Used" + "default": null, + "description": "Display label. Omit to use the route name; null is not accepted.", + "examples": [ + "Assistant" + ], + "title": "Display Name" }, - "total": { - "anyOf": [ + "target": { + "description": "Upstream target for the route.", + "discriminator": { + "mapping": { + "ANTHROPIC": "#/components/schemas/RouteTargetAnthropicV1", + "BASETEN_MODEL_API": "#/components/schemas/RouteTargetBasetenModelAPIV1", + "OPENAI": "#/components/schemas/RouteTargetOpenAIV1", + "XAI": "#/components/schemas/RouteTargetXAIV1" + }, + "propertyName": "type" + }, + "examples": [ { - "type": "number" + "model": "zai-org/GLM-5.3", + "type": "BASETEN_MODEL_API" + } + ], + "oneOf": [ + { + "$ref": "#/components/schemas/RouteTargetBasetenModelAPIV1" }, { - "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", - "type": "string" + "$ref": "#/components/schemas/RouteTargetAnthropicV1" + }, + { + "$ref": "#/components/schemas/RouteTargetOpenAIV1" + }, + { + "$ref": "#/components/schemas/RouteTargetXAIV1" } ], - "description": "Total cost in dollars", - "title": "Total" + "title": "Target" }, - "minutes": { - "description": "Total minutes used", - "title": "Minutes", - "type": "integer" + "description": { + "anyOf": [ + { + "maxLength": 1000, + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Short description of the route. Omit for no description; null is not accepted.", + "examples": [ + "Assistant for code review and debugging." + ], + "title": "Description" + } + }, + "required": [ + "target" + ], + "title": "CreateRouteRequestV1", + "type": "object" + }, + "RouteProviderV1": { + "description": "Upstream provider of a route target, named like the route target types.", + "enum": [ + "BASETEN_MODEL_API", + "OPENAI", + "ANTHROPIC", + "XAI", + "VERTEX", + "OPENAI_COMPATIBLE" + ], + "title": "RouteProviderV1", + "type": "string" + }, + "RoutesUsageBucketV1": { + "properties": { + "date": { + "description": "UTC calendar date for this bucket, from midnight inclusive to the next midnight exclusive.", + "format": "date", + "title": "Date", + "type": "string" }, - "breakdown": { - "description": "Per-deployment usage breakdown", + "results": { + "description": "Usage broken down by the requested dimensions. Empty when there is no usage.", "items": { - "$ref": "#/components/schemas/DedicatedItemV1" + "$ref": "#/components/schemas/RoutesUsageResultV1" }, - "title": "Breakdown", + "title": "Results", "type": "array" } }, "required": [ - "subtotal", - "credits_used", - "total", - "minutes" + "date", + "results" ], - "title": "DedicatedUsageV1", + "title": "RoutesUsageBucketV1", "type": "object" }, - "ModelApiItemV1": { + "RoutesUsageResultV1": { "properties": { - "model_name": { - "description": "Model name", - "title": "Model Name", - "type": "string" + "user_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "ID of the user who created the Routes key. Null when not grouping by USER.", + "title": "User Id" }, - "model_family": { + "model": { "anyOf": [ { "type": "string" @@ -26812,317 +31471,468 @@ } ], "default": null, - "description": "Model family (e.g., llama, mistral)", - "title": "Model Family" + "description": "Model name. For external providers, the model name sent to the provider. Null when not grouping by MODEL.", + "title": "Model" }, - "subtotal": { + "provider": { "anyOf": [ { - "type": "number" + "$ref": "#/components/schemas/RouteProviderV1" }, { - "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", - "type": "string" + "type": "null" } ], - "description": "Subtotal cost in dollars for this model", - "title": "Subtotal" + "default": null, + "description": "Provider that served the requests. Null when not grouping by PROVIDER." + }, + "cost_usd": { + "description": "Estimated cost in USD, returned as an exact decimal string. Costs for OpenAI, Anthropic, and xAI estimate what you pay those providers; they are not Baseten charges.", + "examples": [ + "0.00035625" + ], + "title": "Cost Usd", + "type": "string" }, "input_tokens": { - "description": "Total input tokens for this model", + "description": "Input tokens, including cached input tokens.", "title": "Input Tokens", "type": "integer" }, - "output_tokens": { - "description": "Total output tokens for this model", - "title": "Output Tokens", - "type": "integer" - }, "cached_input_tokens": { - "description": "Total cached input tokens for this model", + "description": "Input tokens read from the prompt cache.", "title": "Cached Input Tokens", "type": "integer" }, - "daily": { - "description": "Daily usage breakdown", + "uncached_input_tokens": { + "description": "Input tokens not read from the prompt cache, including tokens written to the cache.", + "title": "Uncached Input Tokens", + "type": "integer" + }, + "output_tokens": { + "description": "Output tokens.", + "title": "Output Tokens", + "type": "integer" + } + }, + "required": [ + "cost_usd", + "input_tokens", + "cached_input_tokens", + "uncached_input_tokens", + "output_tokens" + ], + "title": "RoutesUsageResultV1", + "type": "object" + }, + "RoutesUsageResponseV1": { + "properties": { + "items": { + "description": "Items in this page.", "items": { - "$ref": "#/components/schemas/DailyModelApiUsageV1" + "$ref": "#/components/schemas/RoutesUsageBucketV1" }, - "title": "Daily", + "title": "Items", "type": "array" + }, + "pagination": { + "$ref": "#/components/schemas/PaginationResponseV1", + "description": "Pagination metadata for the page." } }, "required": [ - "model_name", - "subtotal", - "input_tokens", - "output_tokens", - "cached_input_tokens" + "items", + "pagination" ], - "title": "ModelApiItemV1", + "title": "RoutesUsageResponseV1", "type": "object" }, - "ModelApisUsageV1": { + "RouteUsageDimensionV1": { + "enum": [ + "USER", + "MODEL", + "PROVIDER" + ], + "title": "RouteUsageDimensionV1", + "type": "string" + }, + "RoutesUsageRequestV1": { "properties": { - "subtotal": { + "cursor": { "anyOf": [ { - "type": "number" + "type": "string" }, { - "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", - "type": "string" + "type": "null" } ], - "description": "Subtotal cost in dollars after applying credits used", - "title": "Subtotal" + "default": null, + "description": "Opaque cursor returned by a previous page. Omit to fetch the first page.", + "title": "Cursor" }, - "credits_used": { + "limit": { + "default": 7, + "description": "Number of daily buckets to return. Defaults to 7; maximum 31.", + "maximum": 31, + "minimum": 1, + "title": "Limit", + "type": "integer" + }, + "start_date": { "anyOf": [ { - "type": "number" + "format": "date", + "type": "string" }, { - "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", - "type": "string" + "type": "null" } ], - "description": "Credits applied in dollars", - "title": "Credits Used" + "default": null, + "description": "Inclusive UTC calendar day at the start of the query range. Defaults to the previous UTC date, and is ignored when you pass a cursor.", + "title": "Start Date" }, - "total": { + "end_date": { "anyOf": [ { - "type": "number" + "format": "date", + "type": "string" }, { - "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", - "type": "string" + "type": "null" } ], - "description": "Total cost in dollars", - "title": "Total" + "default": null, + "description": "Exclusive UTC calendar day at the end of the query range. Defaults to the day after the current UTC date so current-day usage is included.", + "title": "End Date" }, - "breakdown": { - "description": "Per-model usage breakdown", + "group_by": { + "description": "Dimensions to break usage down by, repeated once per dimension: USER, MODEL, or PROVIDER. Each result represents one observed combination of the requested dimensions within that day, and results are sorted by those values. Combinations without usage are omitted, so result counts can differ between days. Defaults to MODEL.", "items": { - "$ref": "#/components/schemas/ModelApiItemV1" + "$ref": "#/components/schemas/RouteUsageDimensionV1" }, - "title": "Breakdown", + "title": "Group By", + "type": "array" + }, + "user_ids": { + "description": "Return only usage from Routes keys created by these user IDs, repeated once per ID.", + "items": { + "type": "string" + }, + "title": "User Ids", + "type": "array" + }, + "models": { + "description": "Return only usage for these exact model names, repeated once per model.", + "items": { + "type": "string" + }, + "title": "Models", + "type": "array" + }, + "providers": { + "description": "Return only usage for these providers, repeated once per provider.", + "items": { + "$ref": "#/components/schemas/RouteProviderV1" + }, + "title": "Providers", "type": "array" } }, - "required": [ - "subtotal", - "credits_used", - "total" - ], - "title": "ModelApisUsageV1", + "title": "RoutesUsageRequestV1", "type": "object" }, - "ResourceKind": { - "enum": [ - "LOOPS_SAMPLER", - "LOOPS_TRAINER", - "MODEL_DEPLOYMENT", - "TRAINING_JOB", - "CHAINLET" + "RouteTombstoneV1": { + "properties": { + "id": { + "description": "Stable identifier of the deleted route.", + "title": "Id", + "type": "string" + }, + "name": { + "description": "Name of the deleted route.", + "title": "Name", + "type": "string" + } + }, + "required": [ + "id", + "name" ], - "title": "ResourceKind", - "type": "string" + "title": "RouteTombstoneV1", + "type": "object" }, - "TrainingItemV1": { + "UpdateRouteRequestV1": { + "additionalProperties": false, + "minProperties": 1, "properties": { - "billable_resource": { - "$ref": "#/components/schemas/BillableResourceV1", - "description": "The training job resource" - }, - "subtotal": { + "description": { "anyOf": [ { - "type": "number" + "maxLength": 1000, + "type": "string" }, { - "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", - "type": "string" + "type": "null" } ], - "description": "Subtotal cost in dollars for this billable resource", - "title": "Subtotal" - }, - "minutes": { - "description": "Total minutes used for this billable resource", - "title": "Minutes", - "type": "integer" + "default": null, + "description": "New description. Omit to keep the current description; use an empty string to clear it. Null is not accepted.", + "examples": [ + "Assistant for code review and debugging." + ], + "title": "Description" }, - "daily": { - "description": "Daily usage breakdown", - "items": { - "$ref": "#/components/schemas/DailyTrainingUsageV1" - }, - "title": "Daily", - "type": "array" + "display_name": { + "anyOf": [ + { + "maxLength": 255, + "minLength": 1, + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "New display label. Omit to keep the current label; null is not accepted.", + "examples": [ + "Assistant" + ], + "title": "Display Name" } }, - "required": [ - "billable_resource", - "subtotal", - "minutes" - ], - "title": "TrainingItemV1", + "title": "UpdateRouteRequestV1", "type": "object" }, - "TrainingUsageV1": { + "EndpointTargetV1": { + "description": "One configured upstream target of an endpoint.", "properties": { - "subtotal": { + "provider": { + "$ref": "#/components/schemas/GatewayProvider", + "description": "Upstream provider." + }, + "secret_id": { "anyOf": [ { - "type": "number" + "type": "string" }, { - "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", - "type": "string" + "type": "null" } ], - "description": "Subtotal cost in dollars after applying credits used", - "title": "Subtotal" + "default": null, + "description": "Referenced secret, if any.", + "title": "Secret Id" }, - "credits_used": { + "target_model": { "anyOf": [ { - "type": "number" + "type": "string" }, { - "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", - "type": "string" + "type": "null" } ], - "description": "Credits applied in dollars", - "title": "Credits Used" + "default": null, + "description": "Upstream model name, if any.", + "title": "Target Model" }, - "total": { + "base_url": { "anyOf": [ { - "type": "number" + "type": "string" }, { - "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", - "type": "string" + "type": "null" } ], - "description": "Total cost in dollars", - "title": "Total" - }, - "minutes": { - "description": "Total minutes used", - "title": "Minutes", - "type": "integer" + "default": null, + "description": "Custom OpenAI-compatible base URL, if any.", + "title": "Base Url" }, - "breakdown": { - "description": "Per-job usage breakdown", - "items": { - "$ref": "#/components/schemas/TrainingItemV1" - }, - "title": "Breakdown", - "type": "array" - } - }, - "required": [ - "subtotal", - "credits_used", - "total", - "minutes" - ], - "title": "TrainingUsageV1", - "type": "object" - }, - "UsageSummaryV1": { - "description": "Billing usage summary for the requested date range.", - "properties": { - "dedicated_usage": { + "model_id": { "anyOf": [ { - "$ref": "#/components/schemas/DedicatedUsageV1" + "type": "string" }, { "type": "null" } ], "default": null, - "description": "Dedicated model serving usage" + "description": "Baseten model, if any.", + "title": "Model Id" }, - "training_usage": { + "environment_name": { "anyOf": [ { - "$ref": "#/components/schemas/TrainingUsageV1" + "type": "string" }, { "type": "null" } ], "default": null, - "description": "Training usage" + "description": "Baseten model environment, if non-production.", + "title": "Environment Name" }, - "model_apis_usage": { + "vertex_config": { "anyOf": [ { - "$ref": "#/components/schemas/ModelApisUsageV1" + "$ref": "#/components/schemas/VertexTargetConfigV1" }, { "type": "null" } ], "default": null, - "description": "Model APIs usage" + "description": "Google Vertex configuration, if any." } }, - "title": "UsageSummaryV1", + "required": [ + "provider" + ], + "title": "EndpointTargetV1", "type": "object" }, - "UsageSummaryRequestV1": { + "EndpointV1": { + "description": "A Gateway endpoint: a slug and its priority-ordered targets (index 0 tried first).", "properties": { - "start_date": { - "description": "Start date (ISO 8601, UTC). Earliest queryable: 2026-01-01.", + "id": { + "description": "Stable identifier for the endpoint.", + "title": "Id", + "type": "string" + }, + "slug": { + "description": "Globally-unique routing slug.", + "examples": [ + "baseten/mymodel-4" + ], + "title": "Slug", + "type": "string" + }, + "region": { + "$ref": "#/components/schemas/SharedEndpointRegionV1", + "description": "Region this endpoint's routing serves." + }, + "created_at": { + "description": "Creation time, ISO 8601.", "format": "date-time", - "title": "Start Date", + "title": "Created At", "type": "string" }, - "end_date": { - "description": "End date in ISO 8601 format (UTC). Date range cannot exceed 31 days.", + "updated_at": { + "description": "Last update time, ISO 8601.", "format": "date-time", - "title": "End Date", + "title": "Updated At", "type": "string" + }, + "targets": { + "description": "The endpoint's upstream targets. Exactly one target is supported at this time.", + "items": { + "$ref": "#/components/schemas/EndpointTargetV1" + }, + "title": "Targets", + "type": "array" } }, "required": [ - "start_date", - "end_date" + "id", + "slug", + "region", + "created_at", + "updated_at", + "targets" ], - "title": "UsageSummaryRequestV1", + "title": "EndpointV1", "type": "object" }, - "UserInfoV1": { - "description": "A Baseten user.", + "GatewayProvider": { + "enum": [ + "ANTHROPIC", + "OPENAI", + "XAI", + "BASETEN", + "BASETEN_MODEL_API", + "VERTEX", + "OPENAI_COMPATIBLE" + ], + "title": "GatewayProvider", + "type": "string" + }, + "SharedEndpointRegionV1": { + "enum": [ + "UNRESTRICTED", + "EU" + ], + "title": "SharedEndpointRegionV1", + "type": "string" + }, + "VertexTargetConfigV1": { "properties": { - "user_id": { - "description": "Unique identifier for the user", - "title": "User Id", + "project_id": { + "description": "Google Cloud project ID or project number.", + "examples": [ + "my-gcp-project", + "464036093014" + ], + "title": "Project Id", "type": "string" }, - "email": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "location": { + "description": "Google Cloud location.", + "examples": [ + "global" ], - "default": null, - "description": "Email address of the user", - "title": "Email" + "title": "Location", + "type": "string" + } + }, + "required": [ + "project_id", + "location" + ], + "title": "VertexTargetConfigV1", + "type": "object" + }, + "EndpointsResponseV1": { + "properties": { + "items": { + "description": "Items in this page.", + "items": { + "$ref": "#/components/schemas/EndpointV1" + }, + "title": "Items", + "type": "array" }, - "name": { + "pagination": { + "$ref": "#/components/schemas/PaginationResponseV1", + "description": "Pagination metadata for the page." + } + }, + "required": [ + "items", + "pagination" + ], + "title": "EndpointsResponseV1", + "type": "object" + }, + "EndpointTargetRequestV1": { + "description": "One desired upstream target. The customer picks a provider; Baseten owns the\nupstream host and protocol adapter.", + "properties": { + "provider": { + "$ref": "#/components/schemas/GatewayProvider", + "description": "Upstream provider for this target.", + "examples": [ + "ANTHROPIC", + "OPENAI", + "OPENAI_COMPATIBLE", + "BASETEN" + ] + }, + "secret_id": { "anyOf": [ { "type": "string" @@ -27132,10 +31942,13 @@ } ], "default": null, - "description": "Display name of the user", - "title": "Name" + "description": "Secret holding the provider credential. Required for external providers.", + "examples": [ + "3kZ9xqd" + ], + "title": "Secret Id" }, - "workspace_name": { + "target_model": { "anyOf": [ { "type": "string" @@ -27145,43 +31958,13 @@ } ], "default": null, - "description": "Name of the user's workspace", - "title": "Workspace Name" - } - }, - "required": [ - "user_id" - ], - "title": "UserInfoV1", - "type": "object" - }, - "UsersResponseV1": { - "description": "A page of users in the caller's workspace.", - "properties": { - "items": { - "description": "Items in this page.", - "items": { - "$ref": "#/components/schemas/UserInfoV1" - }, - "title": "Items", - "type": "array" + "description": "Model name to send upstream. Required for external providers and optional for BASETEN targets.", + "examples": [ + "gpt-4o" + ], + "title": "Target Model" }, - "pagination": { - "$ref": "#/components/schemas/PaginationResponseV1", - "description": "Pagination metadata for the page." - } - }, - "required": [ - "items", - "pagination" - ], - "title": "UsersResponseV1", - "type": "object" - }, - "UsersRequestV1": { - "description": "Request parameters for listing users.", - "properties": { - "cursor": { + "base_url": { "anyOf": [ { "type": "string" @@ -27191,18 +31974,13 @@ } ], "default": null, - "description": "Opaque cursor returned by a previous page. Omit to fetch the first page.", - "title": "Cursor" - }, - "limit": { - "default": 100, - "description": "Maximum number of items to return.", - "maximum": 1000, - "minimum": 1, - "title": "Limit", - "type": "integer" + "description": "HTTPS base URL of the upstream OpenAI-compatible server. Must not include a port. Required for and only valid with OPENAI_COMPATIBLE.", + "examples": [ + "https://my-vllm.example.com" + ], + "title": "Base Url" }, - "email": { + "model_id": { "anyOf": [ { "type": "string" @@ -27212,43 +31990,13 @@ } ], "default": null, - "description": "When set, returns only users with this exact email, if any.", - "title": "Email" - } - }, - "title": "UsersRequestV1", - "type": "object" - }, - "AwsAssumeRoleV1": { - "description": "AWS AssumeRole trust-policy inputs for the organization.", - "properties": { - "baseten_role_arn": { - "description": "Baseten role ARN to allow in an IAM role's trust policy", - "title": "Baseten Role Arn", - "type": "string" - }, - "external_id": { - "description": "sts:ExternalId Baseten presents when assuming the role", - "title": "External Id", - "type": "string" - } - }, - "required": [ - "baseten_role_arn", - "external_id" - ], - "title": "AwsAssumeRoleV1", - "type": "object" - }, - "OrganizationInfoV1": { - "description": "The caller's organization.", - "properties": { - "org_id": { - "description": "Unique identifier for the organization", - "title": "Org Id", - "type": "string" + "description": "Baseten model to route to. Required for and only valid with BASETEN.", + "examples": [ + "3kZ9xqd" + ], + "title": "Model Id" }, - "name": { + "environment_name": { "anyOf": [ { "type": "string" @@ -27258,262 +32006,287 @@ } ], "default": null, - "description": "Display name of the organization", - "title": "Name" - }, - "created_at": { - "description": "Time the organization was created in ISO 8601 format", - "format": "date-time", - "title": "Created At", - "type": "string" + "description": "Baseten model environment to route to. Only valid with BASETEN. Omit or pass `production` to target production.", + "examples": [ + "staging" + ], + "title": "Environment Name" }, - "aws_assume_role": { + "vertex_config": { "anyOf": [ { - "$ref": "#/components/schemas/AwsAssumeRoleV1" + "$ref": "#/components/schemas/VertexTargetConfigV1" }, { "type": "null" } ], "default": null, - "description": "AWS AssumeRole trust-policy inputs; null while the method is not enabled for the organization" - } - }, - "required": [ - "org_id", - "created_at" - ], - "title": "OrganizationInfoV1", - "type": "object" - }, - "GatewayEventTokensV1": { - "properties": { - "inputTokens": { - "description": "Cached and uncached input tokens.", - "title": "Inputtokens", - "type": "integer" - }, - "outputTokens": { - "description": "Output tokens.", - "title": "Outputtokens", - "type": "integer" - }, - "cachedInputTokens": { - "description": "Cached input tokens.", - "title": "Cachedinputtokens", - "type": "integer" + "description": "Google Vertex configuration. Required for and only valid with VERTEX." } }, "required": [ - "inputTokens", - "outputTokens", - "cachedInputTokens" + "provider" ], - "title": "GatewayEventTokensV1", + "title": "EndpointTargetRequestV1", "type": "object" }, - "GatewayEventV1": { + "CreateEndpointRequestV1": { "properties": { - "type": { - "default": "API_BILLING_USAGE", - "description": "Event type.", - "title": "Type", - "type": "string" - }, - "idempotencyKey": { - "description": "Deduplication key.", - "title": "Idempotencykey", - "type": "string" - }, - "timestamp": { - "description": "Billing event time (ISO 8601, UTC).", - "title": "Timestamp", - "type": "string" - }, - "requestId": { - "description": "Inference request ID.", - "title": "Requestid", - "type": "string" - }, - "modelSlug": { - "description": "Served model.", - "title": "Modelslug", - "type": "string" - }, - "externalEntityId": { - "description": "Calling group's external ID.", - "title": "Externalentityid", + "slug": { + "description": "Globally-unique slug of the form '{org_prefix}/{name}'.", + "examples": [ + "baseten/mymodel-4" + ], + "title": "Slug", "type": "string" }, - "apiKeyPrefix": { - "description": "API key prefix.", - "title": "Apikeyprefix", - "type": "string" + "region": { + "$ref": "#/components/schemas/SharedEndpointRegionV1", + "default": "UNRESTRICTED", + "description": "Region the new routing serves." }, - "tokens": { - "$ref": "#/components/schemas/GatewayEventTokensV1" + "targets": { + "description": "The endpoint's upstream targets. Exactly one target is supported at this time.", + "examples": [ + [ + { + "environment_name": "staging", + "model_id": "3kZ9xqd", + "provider": "BASETEN", + "target_model": "custom/model-name" + } + ], + [ + { + "provider": "OPENAI", + "secret_id": "3kZ9xqd", + "target_model": "gpt-4o" + } + ], + [ + { + "base_url": "https://my-vllm.example.com", + "provider": "OPENAI_COMPATIBLE", + "secret_id": "3kZ9xqd", + "target_model": "my-model" + } + ] + ], + "items": { + "$ref": "#/components/schemas/EndpointTargetRequestV1" + }, + "maxItems": 1, + "minItems": 1, + "title": "Targets", + "type": "array" } }, "required": [ - "idempotencyKey", - "timestamp", - "requestId", - "modelSlug", - "externalEntityId", - "apiKeyPrefix", - "tokens" + "slug", + "targets" ], - "title": "GatewayEventV1", - "type": "object" - }, - "GatewayEventsResponseV1": { - "properties": { - "items": { - "description": "Items in this page.", - "items": { - "$ref": "#/components/schemas/GatewayEventV1" - }, - "title": "Items", - "type": "array" + "title": "CreateEndpointRequestV1", + "type": "object" + }, + "EndpointTombstoneV1": { + "properties": { + "id": { + "description": "Identifier of the deleted endpoint.", + "title": "Id", + "type": "string" }, - "pagination": { - "$ref": "#/components/schemas/PaginationResponseV1", - "description": "Pagination metadata for the page." + "slug": { + "description": "Slug of the deleted endpoint.", + "title": "Slug", + "type": "string" } }, "required": [ - "items", - "pagination" + "id", + "slug" ], - "title": "GatewayEventsResponseV1", + "title": "EndpointTombstoneV1", "type": "object" }, - "GatewayEventsRequestV1": { + "UpdateEndpointRequestV1": { + "description": "PATCH body. Replaces the endpoint's full target list. The slug is immutable\nafter creation; to change it, create a new endpoint and delete this one.", "properties": { - "start_time": { - "anyOf": [ - { - "format": "date-time", - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "description": "Inclusive start (ISO 8601, UTC). Required without a cursor.", - "title": "Start Time" - }, - "end_time": { + "targets": { "anyOf": [ { - "format": "date-time", - "type": "string" + "items": { + "$ref": "#/components/schemas/EndpointTargetRequestV1" + }, + "maxItems": 1, + "minItems": 1, + "type": "array" }, { "type": "null" } ], "default": null, - "description": "Exclusive end (ISO 8601, UTC). Defaults to now.", - "title": "End Time" - }, - "limit": { - "anyOf": [ - { - "maximum": 1000, - "minimum": 1, - "type": "integer" - }, - { - "type": "null" - } + "description": "The endpoint's upstream targets. Exactly one target is supported at this time.", + "examples": [ + [ + { + "environment_name": "staging", + "model_id": "3kZ9xqd", + "provider": "BASETEN", + "target_model": "custom/model-name" + } + ], + [ + { + "provider": "OPENAI", + "secret_id": "3kZ9xqd", + "target_model": "gpt-4o" + } + ], + [ + { + "base_url": "https://my-vllm.example.com", + "provider": "OPENAI_COMPATIBLE", + "secret_id": "3kZ9xqd", + "target_model": "my-model" + } + ] ], - "default": null, - "description": "Max events. Default 100, max 1000.", - "title": "Limit" + "title": "Targets" + } + }, + "title": "UpdateEndpointRequestV1", + "type": "object" + }, + "EffectiveModelConfigV1": { + "properties": { + "slug": { + "description": "Shared endpoint slug.", + "title": "Slug", + "type": "string" }, - "api_keys": { - "description": "Return only events for these API key prefixes, repeated once per prefix.", + "rate_limits": { "items": { - "type": "string" + "$ref": "#/components/schemas/EffectiveRateLimitV1" }, - "title": "Api Keys", + "title": "Rate Limits", "type": "array" }, - "external_entity_ids": { - "description": "Return only events for these external entity IDs, repeated once per ID.", + "usage_limits": { "items": { - "type": "string" + "$ref": "#/components/schemas/EffectiveUsageLimitV1" }, - "title": "External Entity Ids", + "title": "Usage Limits", "type": "array" + } + }, + "required": [ + "slug" + ], + "title": "EffectiveModelConfigV1", + "type": "object" + }, + "EffectiveRateLimitV1": { + "properties": { + "type": { + "$ref": "#/components/schemas/LimitTypeV1", + "description": "The type of the rate limit", + "examples": [ + "TOKEN", + "REQUEST" + ] }, - "cursor": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "unit": { + "$ref": "#/components/schemas/RateLimitUnitV1", + "description": "The unit of the rate limit", + "examples": [ + "SECOND", + "MINUTE" + ] + }, + "threshold": { + "description": "The threshold for the rate limit", + "examples": [ + 1000, + 50000 ], - "default": null, - "description": "Next-page cursor. Other parameters are ignored.", - "title": "Cursor" + "minimum": 0, + "title": "Threshold", + "type": "integer" + }, + "source_group": { + "description": "ID of the group in the hierarchy this limit is anchored to.", + "examples": [ + "abc123" + ], + "title": "Source Group", + "type": "string" } }, - "title": "GatewayEventsRequestV1", + "required": [ + "type", + "unit", + "threshold", + "source_group" + ], + "title": "EffectiveRateLimitV1", "type": "object" }, - "EndpointTargetV1": { - "description": "One configured upstream target of an endpoint.", + "EffectiveUsageLimitV1": { "properties": { - "provider": { - "$ref": "#/components/schemas/GatewayProvider", - "description": "Upstream provider." + "type": { + "$ref": "#/components/schemas/LimitTypeV1", + "description": "The type of the usage limit", + "examples": [ + "REQUEST", + "TOKEN" + ] }, - "secret_id": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "description": "Referenced secret, if any.", - "title": "Secret Id" + "unit": { + "$ref": "#/components/schemas/UsageLimitUnitV1", + "description": "The unit of the usage limit", + "examples": [ + "DAY" + ] }, - "target_model": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "threshold": { + "description": "The threshold for the usage limit", + "examples": [ + 10000000 ], - "default": null, - "description": "Upstream model name, if any.", - "title": "Target Model" + "minimum": 0, + "title": "Threshold", + "type": "integer" }, - "base_url": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } + "source_group": { + "description": "ID of the group in the hierarchy this limit is anchored to.", + "examples": [ + "abc123" ], - "default": null, - "description": "Custom OpenAI-compatible base URL, if any.", - "title": "Base Url" + "title": "Source Group", + "type": "string" + } + }, + "required": [ + "type", + "unit", + "threshold", + "source_group" + ], + "title": "EffectiveUsageLimitV1", + "type": "object" + }, + "GroupHierarchyV1": { + "properties": { + "limit_enforcement": { + "$ref": "#/components/schemas/LimitEnforcementV1", + "examples": [ + "CASCADING", + "INDEPENDENT" + ] }, - "model_id": { + "parent_group_id": { "anyOf": [ { "type": "string" @@ -27523,12 +32296,24 @@ } ], "default": null, - "description": "Baseten model, if any.", - "title": "Model Id" - }, - "environment_name": { + "examples": [ + "abc123" + ], + "title": "Parent Group Id" + } + }, + "required": [ + "limit_enforcement" + ], + "title": "GroupHierarchyV1", + "type": "object" + }, + "GroupMetadataV1": { + "properties": { + "name": { "anyOf": [ { + "maxLength": 255, "type": "string" }, { @@ -27536,167 +32321,251 @@ } ], "default": null, - "description": "Baseten model environment, if non-production.", - "title": "Environment Name" + "description": "Optional display name for the group.", + "examples": [ + "Acme prod" + ], + "title": "Name" }, - "vertex_config": { - "anyOf": [ - { - "$ref": "#/components/schemas/VertexTargetConfigV1" - }, - { - "type": "null" - } + "external_entity_id": { + "description": "External-system identifier for this group. Unique within the caller's org.", + "examples": [ + "cust_42" ], - "default": null, - "description": "Google Vertex configuration, if any." + "maxLength": 255, + "minLength": 1, + "title": "External Entity Id", + "type": "string" } }, "required": [ - "provider" + "external_entity_id" ], - "title": "EndpointTargetV1", + "title": "GroupMetadataV1", "type": "object" }, - "EndpointV1": { - "description": "A Gateway endpoint: a slug and its priority-ordered targets (index 0 tried first).", + "GroupV1": { "properties": { "id": { - "description": "Stable identifier for the endpoint.", + "description": "Internal Baseten ID for the group.", "title": "Id", "type": "string" }, - "slug": { - "description": "Globally-unique routing slug.", - "examples": [ - "baseten/mymodel-4" - ], - "title": "Slug", - "type": "string" + "metadata": { + "$ref": "#/components/schemas/GroupMetadataV1", + "description": "Group identity + display metadata." }, - "region": { - "$ref": "#/components/schemas/SharedEndpointRegionV1", - "description": "Region this endpoint's routing serves." + "models": { + "items": { + "$ref": "#/components/schemas/ModelConfigV1" + }, + "title": "Models", + "type": "array" + }, + "effective_models": { + "items": { + "$ref": "#/components/schemas/EffectiveModelConfigV1" + }, + "title": "Effective Models", + "type": "array" + }, + "hierarchy": { + "$ref": "#/components/schemas/GroupHierarchyV1", + "description": "Parent linkage and limit enforcement mode. Parent is null for root groups." }, "created_at": { - "description": "Creation time, ISO 8601.", + "description": "When this group was created.", "format": "date-time", "title": "Created At", "type": "string" - }, - "updated_at": { - "description": "Last update time, ISO 8601.", - "format": "date-time", - "title": "Updated At", - "type": "string" - }, - "targets": { - "description": "The endpoint's upstream targets. Exactly one target is supported at this time.", - "items": { - "$ref": "#/components/schemas/EndpointTargetV1" - }, - "title": "Targets", - "type": "array" } }, "required": [ "id", - "slug", - "region", - "created_at", - "updated_at", - "targets" + "metadata", + "hierarchy", + "created_at" ], - "title": "EndpointV1", + "title": "GroupV1", "type": "object" }, - "GatewayProvider": { - "description": "Customer-facing provider for an endpoint target.\n\nExternal providers resolve to a fixed upstream host + protocol adapter via\n``external_provider_configs()``; ``BASETEN`` derives its host from the referenced oracle.", + "LimitEnforcementV1": { "enum": [ - "ANTHROPIC", - "OPENAI", - "XAI", - "BASETEN", - "BASETEN_MODEL_API", - "VERTEX", - "OPENAI_COMPATIBLE" + "CASCADING", + "INDEPENDENT" ], - "title": "GatewayProvider", + "title": "LimitEnforcementV1", "type": "string" }, - "SharedEndpointRegionV1": { + "ModelConfigV1": { + "properties": { + "slug": { + "description": "Shared endpoint slug.", + "title": "Slug", + "type": "string" + }, + "rate_limits": { + "items": { + "$ref": "#/components/schemas/RateLimitV1" + }, + "title": "Rate Limits", + "type": "array" + }, + "usage_limits": { + "items": { + "$ref": "#/components/schemas/UsageLimitV1" + }, + "title": "Usage Limits", + "type": "array" + } + }, + "required": [ + "slug" + ], + "title": "ModelConfigV1", + "type": "object" + }, + "UsageLimitUnitV1": { "enum": [ - "UNRESTRICTED", - "EU" + "DAY" ], - "title": "SharedEndpointRegionV1", + "title": "UsageLimitUnitV1", "type": "string" }, - "VertexTargetConfigV1": { + "UsageLimitV1": { "properties": { - "project_id": { - "description": "Google Cloud project ID or project number.", + "type": { + "$ref": "#/components/schemas/LimitTypeV1", + "description": "The type of the usage limit", "examples": [ - "my-gcp-project", - "464036093014" + "REQUEST", + "TOKEN" + ] + }, + "unit": { + "$ref": "#/components/schemas/UsageLimitUnitV1", + "description": "The unit of the usage limit", + "examples": [ + "DAY" + ] + }, + "threshold": { + "description": "The threshold for the usage limit", + "examples": [ + 10000000 ], - "title": "Project Id", - "type": "string" + "minimum": 0, + "title": "Threshold", + "type": "integer" + } + }, + "required": [ + "type", + "unit", + "threshold" + ], + "title": "UsageLimitV1", + "type": "object" + }, + "GroupsResponseV1": { + "properties": { + "items": { + "description": "Items in this page.", + "items": { + "$ref": "#/components/schemas/GroupV1" + }, + "title": "Items", + "type": "array" }, - "location": { - "description": "Google Cloud location.", + "pagination": { + "$ref": "#/components/schemas/PaginationResponseV1", + "description": "Pagination metadata for the page." + } + }, + "required": [ + "items", + "pagination" + ], + "title": "GroupsResponseV1", + "type": "object" + }, + "CreateGroupHierarchyV1": { + "properties": { + "limit_enforcement": { + "anyOf": [ + { + "$ref": "#/components/schemas/LimitEnforcementV1" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Limit behavior. Child groups inherit their parent's behavior when omitted; root groups default to Independent for backwards compatibility.", "examples": [ - "global" + "INDEPENDENT" + ] + }, + "parent_group_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } ], - "title": "Location", - "type": "string" + "default": null, + "examples": [ + "abc123" + ], + "title": "Parent Group Id" } }, - "required": [ - "project_id", - "location" - ], - "title": "VertexTargetConfigV1", + "title": "CreateGroupHierarchyV1", "type": "object" }, - "EndpointsResponseV1": { + "CreateGroupRequestV1": { "properties": { - "items": { - "description": "Items in this page.", + "metadata": { + "$ref": "#/components/schemas/GroupMetadataV1", + "description": "Group identity + display metadata." + }, + "models": { + "description": "Per-model rate and usage limit configuration. Defines the group's complete model set. Must be non-empty.", + "examples": [ + [ + { + "slug": "my-org/claude" + } + ] + ], "items": { - "$ref": "#/components/schemas/EndpointV1" + "$ref": "#/components/schemas/ModelConfigV1" }, - "title": "Items", + "minItems": 1, + "title": "Models", "type": "array" }, - "pagination": { - "$ref": "#/components/schemas/PaginationResponseV1", - "description": "Pagination metadata for the page." + "hierarchy": { + "$ref": "#/components/schemas/CreateGroupHierarchyV1", + "description": "Parent linkage and limit enforcement mode. Immutable after creation." } }, "required": [ - "items", - "pagination" + "metadata", + "models", + "hierarchy" ], - "title": "EndpointsResponseV1", + "title": "CreateGroupRequestV1", "type": "object" }, - "EndpointTargetRequestV1": { - "description": "One desired upstream target. The customer picks a provider; Baseten owns the\nupstream host and protocol adapter.", + "UpdateGroupMetadataV1": { "properties": { - "provider": { - "$ref": "#/components/schemas/GatewayProvider", - "description": "Upstream provider for this target.", - "examples": [ - "ANTHROPIC", - "OPENAI", - "OPENAI_COMPATIBLE", - "BASETEN" - ] - }, - "secret_id": { + "name": { "anyOf": [ { + "maxLength": 255, "type": "string" }, { @@ -27704,45 +32573,63 @@ } ], "default": null, - "description": "Secret holding the provider credential. Required for external providers.", + "description": "Optional display name for the group.", "examples": [ - "3kZ9xqd" + "Acme prod" ], - "title": "Secret Id" - }, - "target_model": { + "title": "Name" + } + }, + "title": "UpdateGroupMetadataV1", + "type": "object" + }, + "UpdateGroupRequestV1": { + "properties": { + "metadata": { "anyOf": [ { - "type": "string" + "$ref": "#/components/schemas/UpdateGroupMetadataV1" }, { "type": "null" } ], "default": null, - "description": "Model name to send upstream. Required for external providers and optional for BASETEN targets.", + "description": "Mutable group metadata.", "examples": [ - "gpt-4o" - ], - "title": "Target Model" + { + "name": "Acme Prod" + } + ] }, - "base_url": { + "models": { "anyOf": [ { - "type": "string" + "items": { + "$ref": "#/components/schemas/ModelConfigV1" + }, + "type": "array" }, { "type": "null" } ], "default": null, - "description": "HTTPS base URL of the upstream OpenAI-compatible server. Must not include a port. Required for and only valid with OPENAI_COMPATIBLE.", - "examples": [ - "https://my-vllm.example.com" - ], - "title": "Base Url" + "description": "Per-model rate and usage limit configuration.", + "title": "Models" + } + }, + "title": "UpdateGroupRequestV1", + "type": "object" + }, + "GatewayKeyInfoV1": { + "properties": { + "prefix": { + "description": "The prefix of the Model API key.", + "title": "Prefix", + "type": "string" }, - "model_id": { + "name": { "anyOf": [ { "type": "string" @@ -27752,13 +32639,41 @@ } ], "default": null, - "description": "Baseten model to route to. Required for and only valid with BASETEN.", - "examples": [ - "3kZ9xqd" - ], - "title": "Model Id" + "description": "Optional display name.", + "title": "Name" + } + }, + "required": [ + "prefix" + ], + "title": "GatewayKeyInfoV1", + "type": "object" + }, + "KeysForGroupResponseV1": { + "properties": { + "items": { + "description": "Items in this page.", + "items": { + "$ref": "#/components/schemas/GatewayKeyInfoV1" + }, + "title": "Items", + "type": "array" }, - "environment_name": { + "pagination": { + "$ref": "#/components/schemas/PaginationResponseV1", + "description": "Pagination metadata for the page." + } + }, + "required": [ + "items", + "pagination" + ], + "title": "KeysForGroupResponseV1", + "type": "object" + }, + "CreateApiKeyForGroupRequestV1": { + "properties": { + "name": { "anyOf": [ { "type": "string" @@ -27768,776 +32683,2018 @@ } ], "default": null, - "description": "Baseten model environment to route to. Only valid with BASETEN. Omit or pass `production` to target production.", + "description": "Optional display name for the new key.", "examples": [ - "staging" + "prod-key-1" ], - "title": "Environment Name" + "title": "Name" + } + }, + "title": "CreateApiKeyForGroupRequestV1", + "type": "object" + }, + "CreateApiKeyForGroupResponseV1": { + "properties": { + "api_key": { + "description": "Plaintext key string, returned exactly once.", + "title": "Api Key", + "type": "string" }, - "vertex_config": { + "prefix": { + "description": "Key prefix (the part before the dot).", + "title": "Prefix", + "type": "string" + }, + "name": { "anyOf": [ { - "$ref": "#/components/schemas/VertexTargetConfigV1" + "type": "string" }, { "type": "null" } ], "default": null, - "description": "Google Vertex configuration. Required for and only valid with VERTEX." + "description": "Display name of the key.", + "title": "Name" } }, "required": [ - "provider" + "api_key", + "prefix" ], - "title": "EndpointTargetRequestV1", + "title": "CreateApiKeyForGroupResponseV1", "type": "object" }, - "CreateEndpointRequestV1": { + "RegisterAPIKeyRequestV1": { + "description": "Request to register a caller-supplied API key against an existing FederatedGroup.", "properties": { - "slug": { - "description": "Globally-unique slug of the form '{org_prefix}/{name}'.", + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Optional name for the Model API key", "examples": [ - "baseten/mymodel-4" + "my-model-api-key" ], - "title": "Slug", - "type": "string" - }, - "region": { - "$ref": "#/components/schemas/SharedEndpointRegionV1", - "default": "UNRESTRICTED", - "description": "Region the new routing serves." + "title": "Name" }, - "targets": { - "description": "The endpoint's upstream targets. Exactly one target is supported at this time.", + "key": { + "description": "Value of the API key to register", "examples": [ - [ - { - "environment_name": "staging", - "model_id": "3kZ9xqd", - "provider": "BASETEN", - "target_model": "custom/model-name" - } - ], - [ - { - "provider": "OPENAI", - "secret_id": "3kZ9xqd", - "target_model": "gpt-4o" - } - ], - [ - { - "base_url": "https://my-vllm.example.com", - "provider": "OPENAI_COMPATIBLE", - "secret_id": "3kZ9xqd", - "target_model": "my-model" - } - ] + "my-secure-api-key-value" ], - "items": { - "$ref": "#/components/schemas/EndpointTargetRequestV1" - }, - "maxItems": 1, - "minItems": 1, - "title": "Targets", - "type": "array" + "title": "Key", + "type": "string" + } + }, + "required": [ + "key" + ], + "title": "RegisterAPIKeyRequestV1", + "type": "object" + }, + "RegisterAPIKeyResponseV1": { + "properties": { + "ok": { + "description": "Whether the registration was successful", + "title": "Ok", + "type": "boolean" } }, "required": [ - "slug", - "targets" + "ok" ], - "title": "CreateEndpointRequestV1", + "title": "RegisterAPIKeyResponseV1", "type": "object" }, - "EndpointTombstoneV1": { + "SandboxLifecycleV1": { + "type": "object", + "description": "Lifecycle configuration controlling automatic sandbox deletion based on idle time, max age, or specific dates", "properties": { - "id": { - "description": "Identifier of the deleted endpoint.", - "title": "Id", - "type": "string" + "expiration_policies": { + "type": "array", + "description": "List of expiration policies. Multiple policies can be combined; whichever condition is met first triggers the action.", + "items": { + "$ref": "#/components/schemas/SandboxExpirationPolicyV1" + }, + "example": [ + { + "action": "DELETE", + "type": "TTL_IDLE", + "value": "24h" + }, + { + "action": "DELETE", + "type": "TTL_MAX_AGE", + "value": "7d" + }, + { + "action": "DELETE", + "type": "DATE", + "value": "2026-09-23T21:26:58Z" + } + ] }, - "slug": { - "description": "Slug of the deleted endpoint.", - "title": "Slug", - "type": "string" + "terminated_retention": { + "type": "string", + "description": "Duration to keep the sandbox record after termination for log access (e.g., '1h', '24h', '7d'). Defaults to 5m. Subject to maximum quota limits.", + "example": "24h" } }, + "example": { + "expiration_policies": [ + { + "action": "DELETE", + "type": "TTL_IDLE", + "value": "24h" + }, + { + "action": "DELETE", + "type": "TTL_MAX_AGE", + "value": "7d" + }, + { + "action": "DELETE", + "type": "DATE", + "value": "2026-09-23T21:26:58Z" + } + ], + "terminated_retention": "24h" + } + }, + "SandboxExpirationPolicyV1": { + "description": "Expiration policy. The type determines whether value is a duration or an absolute timestamp.", + "oneOf": [ + { + "$ref": "#/components/schemas/SandboxTTLIdleExpirationPolicyV1" + }, + { + "$ref": "#/components/schemas/SandboxTTLMaxAgeExpirationPolicyV1" + }, + { + "$ref": "#/components/schemas/SandboxDateExpirationPolicyV1" + } + ], + "discriminator": { + "propertyName": "type", + "mapping": { + "TTL_IDLE": "#/components/schemas/SandboxTTLIdleExpirationPolicyV1", + "TTL_MAX_AGE": "#/components/schemas/SandboxTTLMaxAgeExpirationPolicyV1", + "DATE": "#/components/schemas/SandboxDateExpirationPolicyV1" + } + } + }, + "SandboxDurationV1": { + "type": "string", + "description": "Duration using seconds, minutes, hours, or composite durations such as 1h30m. Whole days and weeks are also supported, for example 7d or 2w.", + "pattern": "^[+-]?(0|[0-9]+[dw]|([0-9]+(\\.[0-9]*)?|\\.[0-9]+)(ns|us|\u00b5s|\u03bcs|ms|s|m|h)(([0-9]+(\\.[0-9]*)?|\\.[0-9]+)(ns|us|\u00b5s|\u03bcs|ms|s|m|h))*)$", + "example": "24h" + }, + "SandboxTTLIdleExpirationPolicyV1": { + "type": "object", + "description": "Delete after the specified period of inactivity.", "required": [ - "id", - "slug" + "action", + "type", + "value" ], - "title": "EndpointTombstoneV1", - "type": "object" + "properties": { + "action": { + "type": "string", + "enum": [ + "DELETE" + ] + }, + "type": { + "type": "string", + "enum": [ + "TTL_IDLE" + ] + }, + "value": { + "$ref": "#/components/schemas/SandboxDurationV1" + } + } }, - "UpdateEndpointRequestV1": { - "description": "PATCH body. Replaces the endpoint's full target list. The slug is immutable\nafter creation; to change it, create a new endpoint and delete this one.", + "SandboxTTLMaxAgeExpirationPolicyV1": { + "type": "object", + "description": "Delete after the specified total lifetime.", + "required": [ + "action", + "type", + "value" + ], "properties": { - "targets": { - "anyOf": [ - { - "items": { - "$ref": "#/components/schemas/EndpointTargetRequestV1" - }, - "maxItems": 1, - "minItems": 1, - "type": "array" - }, + "action": { + "type": "string", + "enum": [ + "DELETE" + ] + }, + "type": { + "type": "string", + "enum": [ + "TTL_MAX_AGE" + ] + }, + "value": { + "$ref": "#/components/schemas/SandboxDurationV1" + } + } + }, + "SandboxDateExpirationPolicyV1": { + "type": "object", + "description": "Delete at the specified absolute timestamp.", + "required": [ + "action", + "type", + "value" + ], + "properties": { + "action": { + "type": "string", + "enum": [ + "DELETE" + ] + }, + "type": { + "type": "string", + "enum": [ + "DATE" + ] + }, + "value": { + "type": "string", + "format": "date-time", + "example": "2026-09-23T21:26:58Z" + } + } + }, + "SandboxNetworkV1": { + "type": "object", + "description": "Network configuration for a sandbox including subnet, domain filtering, and proxy settings", + "properties": { + "proxy": { + "description": "Proxy configuration for routing sandbox HTTP traffic through the platform proxy with MITM inspection and per-destination header/body injection", + "allOf": [ { - "type": "null" + "$ref": "#/components/schemas/SandboxProxyConfigV1" } ], - "default": null, - "description": "The endpoint's upstream targets. Exactly one target is supported at this time.", - "examples": [ - [ - { - "environment_name": "staging", - "model_id": "3kZ9xqd", - "provider": "BASETEN", - "target_model": "custom/model-name" - } + "example": { + "allowed_domains": [ + "api.openai.com", + "pypi.org", + "files.pythonhosted.org", + "registry.npmjs.org" ], - [ - { - "provider": "OPENAI", - "secret_id": "3kZ9xqd", - "target_model": "gpt-4o" - } + "bypass": [ + "registry.npmjs.org" ], - [ + "forbidden_domains": [ + "facebook.com", + "*.facebook.com" + ], + "routing": [ { - "base_url": "https://my-vllm.example.com", - "provider": "OPENAI_COMPATIBLE", - "secret_id": "3kZ9xqd", - "target_model": "my-model" + "destinations": [ + "api.openai.com" + ], + "headers": { + "Authorization": "Bearer {{SECRET:openai-key}}" + }, + "body": { + "user": "baseten-api-review-0916" + }, + "secrets": { + "openai-key": "sk-proj-demo-not-a-valid-api-key" + } } ] - ], - "title": "Targets" + } + }, + "subnet": { + "type": "string", + "description": "Subnet name for the sandbox. Defaults to \"default\" at creation.", + "example": "default" } }, - "title": "UpdateEndpointRequestV1", - "type": "object" + "example": { + "proxy": { + "allowed_domains": [ + "api.openai.com", + "pypi.org", + "files.pythonhosted.org", + "registry.npmjs.org" + ], + "bypass": [ + "registry.npmjs.org" + ], + "forbidden_domains": [ + "facebook.com", + "*.facebook.com" + ], + "routing": [ + { + "destinations": [ + "api.openai.com" + ], + "headers": { + "Authorization": "Bearer {{SECRET:openai-key}}" + }, + "body": { + "user": "baseten-api-review-0916" + }, + "secrets": { + "openai-key": "sk-proj-demo-not-a-valid-api-key" + } + } + ] + }, + "subnet": "default" + } }, - "EffectiveModelConfigV1": { + "SandboxProxyConfigV1": { + "type": "object", + "description": "Proxy configuration for routing sandbox HTTP traffic through the platform proxy with MITM inspection and per-destination header/body injection", "properties": { - "slug": { - "description": "Shared endpoint slug.", - "title": "Slug", - "type": "string" + "allowed_domains": { + "type": "array", + "description": "List of allowed external domains (allowlist). When set, only these domains are reachable. Supports wildcards (e.g. *.storage.example.com).", + "items": { + "type": "string", + "example": "api.openai.com" + }, + "example": [ + "api.openai.com", + "pypi.org", + "files.pythonhosted.org", + "registry.npmjs.org" + ] }, - "rate_limits": { + "bypass": { + "type": "array", + "description": "Domains that bypass the proxy entirely via the NO_PROXY directive. Traffic to these destinations goes direct, not through the CONNECT tunnel. Supports wildcards. Note that localhost, private ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16), 169.254.169.254, .local and .internal are always bypassed by default.", "items": { - "$ref": "#/components/schemas/EffectiveRateLimitV1" + "type": "string", + "example": "registry.npmjs.org" }, - "title": "Rate Limits", - "type": "array" + "example": [ + "registry.npmjs.org" + ] }, - "usage_limits": { + "forbidden_domains": { + "type": "array", + "description": "List of forbidden external domains (denylist). When set, all domains except these are reachable. Supports wildcards (e.g. *.malware.com). If both allowed_domains and forbidden_domains are set, allowed_domains takes precedence.", "items": { - "$ref": "#/components/schemas/EffectiveUsageLimitV1" + "type": "string", + "example": "facebook.com" }, - "title": "Usage Limits", - "type": "array" + "example": [ + "facebook.com", + "*.facebook.com" + ] + }, + "routing": { + "type": "array", + "description": "Per-destination routing rules with header/body injection and secrets. Use destinations [\"*\"] for global rules that apply to all destinations.", + "items": { + "$ref": "#/components/schemas/SandboxProxyTargetV1" + }, + "example": [ + { + "destinations": [ + "api.openai.com" + ], + "headers": { + "Authorization": "Bearer {{SECRET:openai-key}}" + }, + "body": { + "user": "baseten-api-review-0916" + }, + "secrets": { + "openai-key": "sk-proj-demo-not-a-valid-api-key" + } + } + ] } }, - "required": [ - "slug" - ], - "title": "EffectiveModelConfigV1", - "type": "object" + "example": { + "allowed_domains": [ + "api.openai.com", + "pypi.org", + "files.pythonhosted.org", + "registry.npmjs.org" + ], + "bypass": [ + "registry.npmjs.org" + ], + "forbidden_domains": [ + "facebook.com", + "*.facebook.com" + ], + "routing": [ + { + "destinations": [ + "api.openai.com" + ], + "headers": { + "Authorization": "Bearer {{SECRET:openai-key}}" + }, + "body": { + "user": "baseten-api-review-0916" + }, + "secrets": { + "openai-key": "sk-proj-demo-not-a-valid-api-key" + } + } + ] + } }, - "EffectiveRateLimitV1": { + "SandboxProxyTargetV1": { + "type": "object", + "description": "Routing rule that injects headers and body fields into requests matching the given destinations. Use destinations [\"*\"] for a global rule that applies to all proxied traffic.", "properties": { - "type": { - "$ref": "#/components/schemas/LimitTypeV1", - "description": "The type of the rate limit", - "examples": [ - "TOKEN", - "REQUEST" - ] + "body": { + "type": "object", + "description": "Body fields to inject into matching requests. Values may contain {{SECRET:name}} references resolved from this rule's secrets.", + "additionalProperties": { + "type": "string" + }, + "example": { + "user": "baseten-api-review-0916" + } }, - "unit": { - "$ref": "#/components/schemas/RateLimitUnitV1", - "description": "The unit of the rate limit", - "examples": [ - "SECOND", - "MINUTE" + "destinations": { + "type": "array", + "description": "Destination domains this rule applies to. Use [\"*\"] for a global rule that matches all destinations.", + "items": { + "type": "string", + "example": "api.openai.com" + }, + "example": [ + "api.openai.com" ] }, - "threshold": { - "description": "The threshold for the rate limit", - "examples": [ - 1000, - 50000 - ], - "minimum": 0, - "title": "Threshold", - "type": "integer" + "headers": { + "type": "object", + "description": "Headers to inject into matching requests. Values may contain {{SECRET:name}} references resolved from this rule's secrets.", + "additionalProperties": { + "type": "string" + }, + "example": { + "Authorization": "Bearer {{SECRET:openai-key}}" + } }, - "source_group": { - "description": "ID of the group in the hierarchy this limit is anchored to.", - "examples": [ - "abc123" - ], - "title": "Source Group", - "type": "string" + "secrets": { + "type": "object", + "description": "Named secret values for this routing rule, referenced in headers/body via {{SECRET:name}}. Stored encrypted at rest. Write-only: never returned in API responses.", + "additionalProperties": { + "type": "string" + }, + "example": { + "openai-key": "sk-proj-demo-not-a-valid-api-key" + }, + "writeOnly": true + } + }, + "example": { + "destinations": [ + "api.openai.com" + ], + "headers": { + "Authorization": "Bearer {{SECRET:openai-key}}" + }, + "body": { + "user": "baseten-api-review-0916" + }, + "secrets": { + "openai-key": "sk-proj-demo-not-a-valid-api-key" + } + } + }, + "SandboxEnvV1": { + "type": "object", + "description": "Environment variable with name and value", + "properties": { + "name": { + "type": "string", + "description": "Name of the environment variable", + "example": "NODE_ENV" + }, + "secret": { + "type": "boolean", + "description": "Whether the value is a secret", + "example": false + }, + "value": { + "type": "string", + "description": "Value of the environment variable", + "example": "production" } }, - "required": [ - "type", - "unit", - "threshold", - "source_group" - ], - "title": "EffectiveRateLimitV1", - "type": "object" + "example": { + "name": "NODE_ENV", + "secret": false, + "value": "production" + } }, - "EffectiveUsageLimitV1": { + "SandboxPortsV1": { + "type": "array", + "description": "Set of ports for a resource", + "items": { + "$ref": "#/components/schemas/SandboxPortV1" + }, + "example": [ + { + "name": "http", + "protocol": "HTTP", + "target": 3000 + } + ] + }, + "SandboxPortV1": { + "type": "object", + "description": "A port for a resource", "properties": { - "type": { - "$ref": "#/components/schemas/LimitTypeV1", - "description": "The type of the usage limit", - "examples": [ - "REQUEST", - "TOKEN" - ] - }, - "unit": { - "$ref": "#/components/schemas/UsageLimitUnitV1", - "description": "The unit of the usage limit", - "examples": [ - "DAY" - ] + "name": { + "type": "string", + "description": "The name of the port", + "example": "http" }, - "threshold": { - "description": "The threshold for the usage limit", - "examples": [ - 10000000 + "protocol": { + "type": "string", + "description": "The protocol of the port", + "enum": [ + "HTTP", + "TCP", + "UDP", + "TLS" ], - "minimum": 0, - "title": "Threshold", - "type": "integer" + "example": "HTTP" }, - "source_group": { - "description": "ID of the group in the hierarchy this limit is anchored to.", - "examples": [ - "abc123" - ], - "title": "Source Group", - "type": "string" + "target": { + "type": "integer", + "description": "The target port of the port", + "example": 3000, + "minimum": 1, + "maximum": 65535 } }, "required": [ - "type", - "unit", - "threshold", - "source_group" + "target" ], - "title": "EffectiveUsageLimitV1", - "type": "object" + "example": { + "name": "http", + "protocol": "HTTP", + "target": 3000 + } }, - "GroupHierarchyV1": { + "SandboxMetadataLabelsV1": { + "type": "object", + "description": "Key-value pairs for organizing and filtering resources. Labels can be used to categorize resources by environment, project, team, or any custom taxonomy.", + "additionalProperties": { + "type": "string" + }, + "example": { + "env": "development", + "project": "api-review", + "team": "engineering" + } + }, + "SandboxConfigurationV1": { + "type": "object", + "description": "Writable sandbox configuration. Fields are serialized at the root of the request or resource.", "properties": { - "limit_enforcement": { - "$ref": "#/components/schemas/LimitEnforcementV1", - "examples": [ - "CASCADING", - "INDEPENDENT" - ] + "enabled": { + "type": "boolean", + "description": "When false, the sandbox is disabled and will not accept connections", + "example": true, + "default": true }, - "parent_group_id": { - "anyOf": [ - { - "type": "string" - }, + "lifecycle": { + "description": "Lifecycle configuration controlling automatic sandbox deletion based on idle time, max age, or specific dates", + "allOf": [ { - "type": "null" + "$ref": "#/components/schemas/SandboxLifecycleV1" } ], - "default": null, - "examples": [ - "abc123" + "example": { + "expiration_policies": [ + { + "action": "DELETE", + "type": "TTL_IDLE", + "value": "24h" + }, + { + "action": "DELETE", + "type": "TTL_MAX_AGE", + "value": "7d" + }, + { + "action": "DELETE", + "type": "DATE", + "value": "2026-09-23T21:26:58Z" + } + ], + "terminated_retention": "24h" + } + }, + "network": { + "description": "Network configuration for a sandbox including subnet, domain filtering, and proxy settings", + "allOf": [ + { + "$ref": "#/components/schemas/SandboxNetworkV1" + } ], - "title": "Parent Group Id" - } - }, - "required": [ - "limit_enforcement" - ], - "title": "GroupHierarchyV1", - "type": "object" - }, - "GroupMetadataV1": { - "properties": { - "name": { - "anyOf": [ + "example": { + "proxy": { + "allowed_domains": [ + "api.openai.com", + "pypi.org", + "files.pythonhosted.org", + "registry.npmjs.org" + ], + "bypass": [ + "registry.npmjs.org" + ], + "forbidden_domains": [ + "facebook.com", + "*.facebook.com" + ], + "routing": [ + { + "destinations": [ + "api.openai.com" + ], + "headers": { + "Authorization": "Bearer {{SECRET:openai-key}}" + }, + "body": { + "user": "baseten-api-review-0916" + }, + "secrets": { + "openai-key": "sk-proj-demo-not-a-valid-api-key" + } + } + ] + }, + "subnet": "default" + } + }, + "region": { + "type": "string", + "description": "Region where the sandbox runs (for example us-pdx-1 or eu-lon-1). When omitted at creation, the closest region is selected.", + "example": "us-pdx-1" + }, + "envs": { + "type": "array", + "description": "Environment variables injected into the sandbox.", + "items": { + "$ref": "#/components/schemas/SandboxEnvV1" + }, + "example": [ { - "maxLength": 255, - "type": "string" + "name": "NODE_ENV", + "secret": false, + "value": "production" }, { - "type": "null" + "name": "PORT", + "secret": false, + "value": "3000" + } + ] + }, + "image": { + "type": "string", + "description": "Image reference including its tag. Use blaxel/base-image:latest to get started with the built-in sandbox execution API. This image is available directly without building, pushing, or listing images through GET /v1/sandboxes/images.", + "example": "blaxel/base-image:latest" + }, + "memory": { + "type": "integer", + "description": "Memory allocation in megabytes. Also determines CPU allocation (CPU cores = memory in MB / 2048, e.g., 4096MB = 2 CPUs).", + "example": 4096, + "minimum": 1 + }, + "ports": { + "description": "Set of ports for a resource", + "allOf": [ + { + "$ref": "#/components/schemas/SandboxPortsV1" } ], - "default": null, - "description": "Optional display name for the group.", - "examples": [ - "Acme prod" - ], - "title": "Name" + "example": [ + { + "name": "http", + "protocol": "HTTP", + "target": 3000 + } + ] }, - "external_entity_id": { - "description": "External-system identifier for this group. Unique within the caller's org.", - "examples": [ - "cust_42" + "display_name": { + "type": "string", + "description": "Human-readable name for display in the UI. Can contain spaces and special characters, max 63 characters.", + "example": "Baseten API review", + "maxLength": 63 + }, + "external_id": { + "type": "string", + "description": "Caller-owned identifier for external lookups. Max 64 chars, alphanumeric + dash.", + "example": "api-review-20260916-001", + "maxLength": 64, + "pattern": "^[A-Za-z0-9-]+$" + }, + "labels": { + "description": "Key-value pairs for organizing and filtering resources. Labels can be used to categorize resources by environment, project, team, or any custom taxonomy.", + "allOf": [ + { + "$ref": "#/components/schemas/SandboxMetadataLabelsV1" + } ], - "maxLength": 255, - "minLength": 1, - "title": "External Entity Id", - "type": "string" + "example": { + "env": "development", + "project": "api-review", + "team": "engineering" + } } }, - "required": [ - "external_entity_id" - ], - "title": "GroupMetadataV1", - "type": "object" - }, - "GroupV1": { - "properties": { - "id": { - "description": "Internal Baseten ID for the group.", - "title": "Id", - "type": "string" - }, - "metadata": { - "$ref": "#/components/schemas/GroupMetadataV1", - "description": "Group identity + display metadata." + "example": { + "enabled": true, + "lifecycle": { + "expiration_policies": [ + { + "action": "DELETE", + "type": "TTL_IDLE", + "value": "24h" + }, + { + "action": "DELETE", + "type": "TTL_MAX_AGE", + "value": "7d" + }, + { + "action": "DELETE", + "type": "DATE", + "value": "2026-09-23T21:26:58Z" + } + ], + "terminated_retention": "24h" }, - "models": { - "items": { - "$ref": "#/components/schemas/ModelConfigV1" + "network": { + "proxy": { + "allowed_domains": [ + "api.openai.com", + "pypi.org", + "files.pythonhosted.org", + "registry.npmjs.org" + ], + "bypass": [ + "registry.npmjs.org" + ], + "forbidden_domains": [ + "facebook.com", + "*.facebook.com" + ], + "routing": [ + { + "destinations": [ + "api.openai.com" + ], + "headers": { + "Authorization": "Bearer {{SECRET:openai-key}}" + }, + "body": { + "user": "baseten-api-review-0916" + }, + "secrets": { + "openai-key": "sk-proj-demo-not-a-valid-api-key" + } + } + ] }, - "title": "Models", - "type": "array" - }, - "effective_models": { - "items": { - "$ref": "#/components/schemas/EffectiveModelConfigV1" + "subnet": "default" + }, + "region": "us-pdx-1", + "envs": [ + { + "name": "NODE_ENV", + "secret": false, + "value": "production" }, - "title": "Effective Models", - "type": "array" - }, - "hierarchy": { - "$ref": "#/components/schemas/GroupHierarchyV1", - "description": "Parent linkage and limit enforcement mode. Parent is null for root groups." - }, - "created_at": { - "description": "When this group was created.", - "format": "date-time", - "title": "Created At", - "type": "string" + { + "name": "PORT", + "secret": false, + "value": "3000" + } + ], + "image": "blaxel/base-image:latest", + "memory": 4096, + "ports": [ + { + "name": "http", + "protocol": "HTTP", + "target": 3000 + } + ], + "display_name": "Baseten API review", + "external_id": "api-review-20260916-001", + "labels": { + "env": "development", + "project": "api-review", + "team": "engineering" } - }, - "required": [ - "id", - "metadata", - "hierarchy", - "created_at" - ], - "title": "GroupV1", - "type": "object" - }, - "LimitEnforcementV1": { - "enum": [ - "CASCADING", - "INDEPENDENT" - ], - "title": "LimitEnforcementV1", - "type": "string" + } }, - "ModelConfigV1": { + "CreateSandboxRequestV1": { + "type": "object", + "description": "Configuration for a new sandbox. The client may provide a name; otherwise the server generates one. The name is immutable after creation.", "properties": { - "slug": { - "description": "Shared endpoint slug.", - "title": "Slug", - "type": "string" + "name": { + "type": "string", + "description": "Optional unique sandbox name. Generated by the server when omitted; immutable after creation.", + "minLength": 1, + "example": "baseten-api-review-0916" + }, + "lifecycle": { + "description": "Lifecycle configuration controlling automatic sandbox deletion based on idle time, max age, or specific dates", + "allOf": [ + { + "$ref": "#/components/schemas/SandboxLifecycleV1" + } + ], + "example": { + "expiration_policies": [ + { + "action": "DELETE", + "type": "TTL_IDLE", + "value": "24h" + }, + { + "action": "DELETE", + "type": "TTL_MAX_AGE", + "value": "7d" + }, + { + "action": "DELETE", + "type": "DATE", + "value": "2026-09-23T21:26:58Z" + } + ], + "terminated_retention": "24h" + } + }, + "network": { + "description": "Network configuration for a sandbox including subnet, domain filtering, and proxy settings", + "allOf": [ + { + "$ref": "#/components/schemas/SandboxNetworkV1" + } + ], + "example": { + "proxy": { + "allowed_domains": [ + "api.openai.com", + "pypi.org", + "files.pythonhosted.org", + "registry.npmjs.org" + ], + "bypass": [ + "registry.npmjs.org" + ], + "forbidden_domains": [ + "facebook.com", + "*.facebook.com" + ], + "routing": [ + { + "destinations": [ + "api.openai.com" + ], + "headers": { + "Authorization": "Bearer {{SECRET:openai-key}}" + }, + "body": { + "user": "baseten-api-review-0916" + }, + "secrets": { + "openai-key": "sk-proj-demo-not-a-valid-api-key" + } + } + ] + }, + "subnet": "default" + } }, - "rate_limits": { - "items": { - "$ref": "#/components/schemas/RateLimitV1" - }, - "title": "Rate Limits", - "type": "array" + "region": { + "type": "string", + "description": "Region where the sandbox runs (for example us-pdx-1 or eu-lon-1). When omitted at creation, the closest region is selected.", + "example": "us-pdx-1" }, - "usage_limits": { + "envs": { + "type": "array", + "description": "Environment variables injected into the sandbox.", "items": { - "$ref": "#/components/schemas/UsageLimitV1" + "$ref": "#/components/schemas/SandboxEnvV1" }, - "title": "Usage Limits", - "type": "array" - } - }, - "required": [ - "slug" - ], - "title": "ModelConfigV1", - "type": "object" - }, - "UsageLimitUnitV1": { - "enum": [ - "DAY" - ], - "title": "UsageLimitUnitV1", - "type": "string" - }, - "UsageLimitV1": { - "properties": { - "type": { - "$ref": "#/components/schemas/LimitTypeV1", - "description": "The type of the usage limit", - "examples": [ - "REQUEST", - "TOKEN" + "example": [ + { + "name": "NODE_ENV", + "secret": false, + "value": "production" + }, + { + "name": "PORT", + "secret": false, + "value": "3000" + } ] }, - "unit": { - "$ref": "#/components/schemas/UsageLimitUnitV1", - "description": "The unit of the usage limit", - "examples": [ - "DAY" + "image": { + "type": "string", + "description": "Image reference including its tag. Use blaxel/base-image:latest to get started with the built-in sandbox execution API. This image is available directly without building, pushing, or listing images through GET /v1/sandboxes/images.", + "example": "blaxel/base-image:latest" + }, + "memory": { + "type": "integer", + "description": "Memory allocation in megabytes. Also determines CPU allocation (CPU cores = memory in MB / 2048, e.g., 4096MB = 2 CPUs).", + "example": 4096, + "minimum": 1 + }, + "ports": { + "description": "Set of ports for a resource", + "allOf": [ + { + "$ref": "#/components/schemas/SandboxPortsV1" + } + ], + "example": [ + { + "name": "http", + "protocol": "HTTP", + "target": 3000 + } ] }, - "threshold": { - "description": "The threshold for the usage limit", - "examples": [ - 10000000 + "display_name": { + "type": "string", + "description": "Human-readable name for display in the UI. Can contain spaces and special characters, max 63 characters.", + "example": "Baseten API review", + "maxLength": 63 + }, + "external_id": { + "type": "string", + "description": "Caller-owned identifier for external lookups. Max 64 chars, alphanumeric + dash.", + "example": "api-review-20260916-001", + "maxLength": 64, + "pattern": "^[A-Za-z0-9-]+$" + }, + "labels": { + "description": "Key-value pairs for organizing and filtering resources. Labels can be used to categorize resources by environment, project, team, or any custom taxonomy.", + "allOf": [ + { + "$ref": "#/components/schemas/SandboxMetadataLabelsV1" + } ], - "minimum": 0, - "title": "Threshold", - "type": "integer" + "example": { + "env": "development", + "project": "api-review", + "team": "engineering" + } } }, - "required": [ - "type", - "unit", - "threshold" - ], - "title": "UsageLimitV1", - "type": "object" - }, - "GroupsResponseV1": { - "properties": { - "items": { - "description": "Items in this page.", - "items": { - "$ref": "#/components/schemas/GroupV1" - }, - "title": "Items", - "type": "array" + "example": { + "name": "baseten-api-review-0916", + "lifecycle": { + "expiration_policies": [ + { + "action": "DELETE", + "type": "TTL_IDLE", + "value": "24h" + }, + { + "action": "DELETE", + "type": "TTL_MAX_AGE", + "value": "7d" + }, + { + "action": "DELETE", + "type": "DATE", + "value": "2026-09-23T21:26:58Z" + } + ], + "terminated_retention": "24h" }, - "pagination": { - "$ref": "#/components/schemas/PaginationResponseV1", - "description": "Pagination metadata for the page." + "network": { + "proxy": { + "allowed_domains": [ + "api.openai.com", + "pypi.org", + "files.pythonhosted.org", + "registry.npmjs.org" + ], + "bypass": [ + "registry.npmjs.org" + ], + "forbidden_domains": [ + "facebook.com", + "*.facebook.com" + ], + "routing": [ + { + "destinations": [ + "api.openai.com" + ], + "headers": { + "Authorization": "Bearer {{SECRET:openai-key}}" + }, + "body": { + "user": "baseten-api-review-0916" + }, + "secrets": { + "openai-key": "sk-proj-demo-not-a-valid-api-key" + } + } + ] + }, + "subnet": "default" + }, + "region": "us-pdx-1", + "envs": [ + { + "name": "NODE_ENV", + "secret": false, + "value": "production" + }, + { + "name": "PORT", + "secret": false, + "value": "3000" + } + ], + "image": "blaxel/base-image:latest", + "memory": 4096, + "ports": [ + { + "name": "http", + "protocol": "HTTP", + "target": 3000 + } + ], + "display_name": "Baseten API review", + "external_id": "api-review-20260916-001", + "labels": { + "env": "development", + "project": "api-review", + "team": "engineering" } - }, - "required": [ - "items", - "pagination" - ], - "title": "GroupsResponseV1", - "type": "object" + } }, - "CreateGroupHierarchyV1": { + "UpdateSandboxRequestV1": { + "type": "object", + "description": "Partial sandbox update. Omitted fields remain unchanged. Supplied arrays and maps (including labels) replace their previous values; supplied structured objects update only their supplied fields. Null is not accepted. The name, memory, and network configuration are immutable after creation. Supplying memory or network returns 400, including unchanged, empty, or null values.", "properties": { - "limit_enforcement": { - "anyOf": [ + "enabled": { + "type": "boolean", + "description": "When false, the sandbox is disabled and will not accept connections", + "example": true + }, + "lifecycle": { + "description": "Lifecycle configuration controlling automatic sandbox deletion based on idle time, max age, or specific dates", + "allOf": [ { - "$ref": "#/components/schemas/LimitEnforcementV1" + "$ref": "#/components/schemas/SandboxLifecycleV1" + } + ], + "example": { + "expiration_policies": [ + { + "action": "DELETE", + "type": "TTL_IDLE", + "value": "24h" + }, + { + "action": "DELETE", + "type": "TTL_MAX_AGE", + "value": "7d" + }, + { + "action": "DELETE", + "type": "DATE", + "value": "2026-09-23T21:26:58Z" + } + ], + "terminated_retention": "24h" + } + }, + "region": { + "type": "string", + "description": "Region where the sandbox runs (for example us-pdx-1 or eu-lon-1). When omitted at creation, the closest region is selected.", + "example": "us-pdx-1" + }, + "envs": { + "type": "array", + "description": "Environment variables injected into the sandbox.", + "items": { + "$ref": "#/components/schemas/SandboxEnvV1" + }, + "example": [ + { + "name": "NODE_ENV", + "secret": false, + "value": "production" }, { - "type": "null" + "name": "PORT", + "secret": false, + "value": "3000" + } + ] + }, + "image": { + "type": "string", + "description": "Image reference including its tag. Use blaxel/base-image:latest to get started with the built-in sandbox execution API. This image is available directly without building, pushing, or listing images through GET /v1/sandboxes/images.", + "example": "blaxel/base-image:latest" + }, + "ports": { + "description": "Set of ports for a resource", + "allOf": [ + { + "$ref": "#/components/schemas/SandboxPortsV1" } ], - "default": null, - "description": "Limit behavior. Child groups inherit their parent's behavior when omitted; root groups default to Independent for backwards compatibility.", - "examples": [ - "INDEPENDENT" + "example": [ + { + "name": "http", + "protocol": "HTTP", + "target": 3000 + } ] }, - "parent_group_id": { - "anyOf": [ + "display_name": { + "type": "string", + "description": "Human-readable name for display in the UI. Can contain spaces and special characters, max 63 characters.", + "example": "Baseten API review - revised", + "maxLength": 63 + }, + "external_id": { + "type": "string", + "description": "Caller-owned identifier for external lookups. Max 64 chars, alphanumeric + dash.", + "example": "api-review-20260916-001", + "maxLength": 64, + "pattern": "^[A-Za-z0-9-]+$" + }, + "labels": { + "description": "Key-value pairs for organizing and filtering resources. Labels can be used to categorize resources by environment, project, team, or any custom taxonomy.", + "allOf": [ { - "type": "string" + "$ref": "#/components/schemas/SandboxMetadataLabelsV1" + } + ], + "example": { + "env": "development", + "project": "api-review", + "team": "engineering", + "revision": "2" + } + } + }, + "minProperties": 1, + "example": { + "enabled": true, + "lifecycle": { + "expiration_policies": [ + { + "action": "DELETE", + "type": "TTL_IDLE", + "value": "24h" }, { - "type": "null" + "action": "DELETE", + "type": "TTL_MAX_AGE", + "value": "7d" + }, + { + "action": "DELETE", + "type": "DATE", + "value": "2026-09-23T21:26:58Z" } ], - "default": null, - "examples": [ - "abc123" - ], - "title": "Parent Group Id" + "terminated_retention": "24h" + }, + "region": "us-pdx-1", + "envs": [ + { + "name": "NODE_ENV", + "secret": false, + "value": "production" + }, + { + "name": "PORT", + "secret": false, + "value": "3000" + } + ], + "image": "blaxel/base-image:latest", + "ports": [ + { + "name": "http", + "protocol": "HTTP", + "target": 3000 + } + ], + "display_name": "Baseten API review - revised", + "external_id": "api-review-20260916-001", + "labels": { + "env": "development", + "project": "api-review", + "team": "engineering", + "revision": "2" } - }, - "title": "CreateGroupHierarchyV1", - "type": "object" + } }, - "CreateGroupRequestV1": { - "properties": { - "metadata": { - "$ref": "#/components/schemas/GroupMetadataV1", - "description": "Group identity + display metadata." + "SandboxV1": { + "description": "Sandbox resource with configuration and server-managed fields at the root. No metadata, spec, or runtime wrapper.", + "allOf": [ + { + "$ref": "#/components/schemas/SandboxConfigurationV1" }, - "models": { - "description": "Per-model rate and usage limit configuration. Defines the group's complete model set. Must be non-empty.", - "examples": [ - [ + { + "type": "object", + "description": "Server-managed sandbox fields.", + "properties": { + "name": { + "type": "string", + "description": "Immutable sandbox name, provided by the client or generated by the server, used in sandbox_name path parameters.", + "readOnly": true, + "example": "baseten-api-review-0916" + }, + "url": { + "type": "string", + "description": "Base URL of this sandbox's execution API. Use this exact returned URL; do not reconstruct its hostname. Authenticate requests with the same Authorization: Bearer header used to create the sandbox. No additional routing headers are required. Fetch GET {url}/swagger/doc.json with that header for the API reference served by this sandbox. For example, POST {url}/process with Content-Type: application/json and {\"command\":\"echo hello\",\"waitForCompletion\":true} executes a command and waits for its result. Execution API fields use camelCase, independently of this API's snake_case fields.", + "format": "uri", + "readOnly": true, + "example": "https://sbx-baseten-api-review-0916-esb1qo.us-pdx-1.b10.run" + }, + "status": { + "description": "Sandbox deployment status.", + "allOf": [ + { + "$ref": "#/components/schemas/SandboxStatusV1" + } + ], + "example": "DEPLOYED" + }, + "state": { + "type": "string", + "description": "Current execution state when available.", + "enum": [ + "RUNNING", + "STANDBY" + ], + "readOnly": true, + "example": "RUNNING" + }, + "created_at": { + "type": "string", + "description": "Time the sandbox was created.", + "format": "date-time", + "readOnly": true, + "example": "2026-09-16T21:26:58.545765901Z" + }, + "updated_at": { + "type": "string", + "description": "Time the sandbox was last updated.", + "format": "date-time", + "readOnly": true, + "example": "2026-09-16T21:31:13Z" + }, + "created_by": { + "type": "string", + "description": "User or service account that created the sandbox.", + "readOnly": true, + "example": "sandbox-automation" + }, + "updated_by": { + "type": "string", + "description": "User or service account that last updated the sandbox.", + "readOnly": true, + "example": "sandbox-automation" + }, + "last_used_at": { + "type": "string", + "description": "Time the sandbox was last used.", + "format": "date-time", + "readOnly": true, + "example": "2026-09-16T21:31:13Z" + }, + "expires_in": { + "type": "integer", + "description": "Seconds remaining before automatic deletion, when expiration is configured.", + "readOnly": true, + "minimum": 0, + "example": 86400 + } + }, + "required": [ + "name", + "status", + "created_at" + ], + "example": { + "name": "baseten-api-review-0916", + "url": "https://sbx-baseten-api-review-0916-esb1qo.us-pdx-1.b10.run", + "status": "DEPLOYED", + "state": "RUNNING", + "created_at": "2026-09-16T21:26:58.545765901Z", + "updated_at": "2026-09-16T21:31:13Z", + "created_by": "sandbox-automation", + "updated_by": "sandbox-automation", + "last_used_at": "2026-09-16T21:31:13Z", + "expires_in": 86400 + } + } + ], + "example": { + "enabled": true, + "lifecycle": { + "expiration_policies": [ + { + "action": "DELETE", + "type": "TTL_IDLE", + "value": "24h" + }, + { + "action": "DELETE", + "type": "TTL_MAX_AGE", + "value": "7d" + }, + { + "action": "DELETE", + "type": "DATE", + "value": "2026-09-23T21:26:58Z" + } + ], + "terminated_retention": "24h" + }, + "network": { + "proxy": { + "allowed_domains": [ + "api.openai.com", + "pypi.org", + "files.pythonhosted.org", + "registry.npmjs.org" + ], + "bypass": [ + "registry.npmjs.org" + ], + "forbidden_domains": [ + "facebook.com", + "*.facebook.com" + ], + "routing": [ { - "slug": "my-org/claude" + "destinations": [ + "api.openai.com" + ], + "headers": { + "Authorization": "Bearer {{SECRET:openai-key}}" + }, + "body": { + "user": "baseten-api-review-0916" + } } ] - ], - "items": { - "$ref": "#/components/schemas/ModelConfigV1" }, - "minItems": 1, - "title": "Models", - "type": "array" - }, - "hierarchy": { - "$ref": "#/components/schemas/CreateGroupHierarchyV1", - "description": "Parent linkage and limit enforcement mode. Immutable after creation." - } - }, - "required": [ - "metadata", - "models", - "hierarchy" + "subnet": "default" + }, + "region": "us-pdx-1", + "envs": [ + { + "name": "NODE_ENV", + "secret": false, + "value": "production" + }, + { + "name": "PORT", + "secret": false, + "value": "3000" + } + ], + "image": "blaxel/base-image:latest", + "memory": 4096, + "ports": [ + { + "name": "http", + "protocol": "HTTP", + "target": 3000 + } + ], + "display_name": "Baseten API review", + "external_id": "api-review-20260916-001", + "labels": { + "env": "development", + "project": "api-review", + "team": "engineering" + }, + "name": "baseten-api-review-0916", + "url": "https://sbx-baseten-api-review-0916-esb1qo.us-pdx-1.b10.run", + "status": "DEPLOYED", + "state": "RUNNING", + "created_at": "2026-09-16T21:26:58.545765901Z", + "updated_at": "2026-09-16T21:31:13Z", + "created_by": "sandbox-automation", + "updated_by": "sandbox-automation", + "last_used_at": "2026-09-16T21:31:13Z", + "expires_in": 86400 + } + }, + "SandboxStatusV1": { + "type": "string", + "description": "Sandbox deployment status.", + "enum": [ + "DEPLOYING", + "DEPLOYED", + "FAILED", + "DEACTIVATING", + "DEACTIVATED", + "DELETING", + "TERMINATED", + "ARCHIVING", + "ARCHIVED", + "UNARCHIVING", + "BUILDING", + "UPLOADING" ], - "title": "CreateGroupRequestV1", - "type": "object" + "readOnly": true, + "example": "DEPLOYED" }, - "UpdateGroupMetadataV1": { + "SandboxApiPaginationV1": { + "type": "object", + "description": "Cursor pagination information. The cursor is present only when another page is available.", "properties": { - "name": { - "anyOf": [ - { - "maxLength": 255, - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "description": "Optional display name for the group.", - "examples": [ - "Acme prod" - ], - "title": "Name" + "has_more": { + "type": "boolean", + "description": "Whether another page is available.", + "example": true + }, + "cursor": { + "type": "string", + "description": "Opaque cursor to pass to the next list request. Keep the same filters.", + "minLength": 1, + "example": "eyJ2IjoxLCJsYXN0X2tleSI6ImJhc2V0ZW4tYXBpLXJldmlldy0wOTE2Iiwic29ydCI6ImRlc2MifQ" } }, - "title": "UpdateGroupMetadataV1", - "type": "object" + "required": [ + "has_more" + ], + "example": { + "has_more": true, + "cursor": "eyJ2IjoxLCJsYXN0X2tleSI6ImJhc2V0ZW4tYXBpLXJldmlldy0wOTE2Iiwic29ydCI6ImRlc2MifQ" + } }, - "UpdateGroupRequestV1": { + "ListSandboxesResponseV1": { + "type": "object", + "description": "One page of sandboxes.", "properties": { - "metadata": { - "anyOf": [ - { - "$ref": "#/components/schemas/UpdateGroupMetadataV1" - }, - { - "type": "null" - } - ], - "default": null, - "description": "Mutable group metadata.", - "examples": [ + "items": { + "type": "array", + "description": "Resources on this page.", + "items": { + "$ref": "#/components/schemas/SandboxV1" + }, + "example": [ { - "name": "Acme Prod" + "enabled": true, + "lifecycle": { + "expiration_policies": [ + { + "action": "DELETE", + "type": "TTL_IDLE", + "value": "24h" + }, + { + "action": "DELETE", + "type": "TTL_MAX_AGE", + "value": "7d" + }, + { + "action": "DELETE", + "type": "DATE", + "value": "2026-09-23T21:26:58Z" + } + ], + "terminated_retention": "24h" + }, + "network": { + "proxy": { + "allowed_domains": [ + "api.openai.com", + "pypi.org", + "files.pythonhosted.org", + "registry.npmjs.org" + ], + "bypass": [ + "registry.npmjs.org" + ], + "forbidden_domains": [ + "facebook.com", + "*.facebook.com" + ], + "routing": [ + { + "destinations": [ + "api.openai.com" + ], + "headers": { + "Authorization": "Bearer {{SECRET:openai-key}}" + }, + "body": { + "user": "baseten-api-review-0916" + } + } + ] + }, + "subnet": "default" + }, + "region": "us-pdx-1", + "envs": [ + { + "name": "NODE_ENV", + "secret": false, + "value": "production" + }, + { + "name": "PORT", + "secret": false, + "value": "3000" + } + ], + "image": "blaxel/base-image:latest", + "memory": 4096, + "ports": [ + { + "name": "http", + "protocol": "HTTP", + "target": 3000 + } + ], + "display_name": "Baseten API review", + "external_id": "api-review-20260916-001", + "labels": { + "env": "development", + "project": "api-review", + "team": "engineering" + }, + "name": "baseten-api-review-0916", + "url": "https://sbx-baseten-api-review-0916-esb1qo.us-pdx-1.b10.run", + "status": "DEPLOYED", + "state": "RUNNING", + "created_at": "2026-09-16T21:26:58.545765901Z", + "updated_at": "2026-09-16T21:31:13Z", + "created_by": "sandbox-automation", + "updated_by": "sandbox-automation", + "last_used_at": "2026-09-16T21:31:13Z", + "expires_in": 86400 } ] }, - "models": { - "anyOf": [ - { - "items": { - "$ref": "#/components/schemas/ModelConfigV1" - }, - "type": "array" - }, + "pagination": { + "description": "Cursor pagination information. The cursor is present only when another page is available.", + "allOf": [ { - "type": "null" + "$ref": "#/components/schemas/SandboxApiPaginationV1" } ], - "default": null, - "description": "Per-model rate and usage limit configuration.", - "title": "Models" + "example": { + "has_more": true, + "cursor": "eyJ2IjoxLCJsYXN0X2tleSI6ImJhc2V0ZW4tYXBpLXJldmlldy0wOTE2Iiwic29ydCI6ImRlc2MifQ" + } } }, - "title": "UpdateGroupRequestV1", - "type": "object" + "required": [ + "items", + "pagination" + ], + "example": { + "items": [ + { + "enabled": true, + "lifecycle": { + "expiration_policies": [ + { + "action": "DELETE", + "type": "TTL_IDLE", + "value": "24h" + }, + { + "action": "DELETE", + "type": "TTL_MAX_AGE", + "value": "7d" + }, + { + "action": "DELETE", + "type": "DATE", + "value": "2026-09-23T21:26:58Z" + } + ], + "terminated_retention": "24h" + }, + "network": { + "proxy": { + "allowed_domains": [ + "api.openai.com", + "pypi.org", + "files.pythonhosted.org", + "registry.npmjs.org" + ], + "bypass": [ + "registry.npmjs.org" + ], + "forbidden_domains": [ + "facebook.com", + "*.facebook.com" + ], + "routing": [ + { + "destinations": [ + "api.openai.com" + ], + "headers": { + "Authorization": "Bearer {{SECRET:openai-key}}" + }, + "body": { + "user": "baseten-api-review-0916" + } + } + ] + }, + "subnet": "default" + }, + "region": "us-pdx-1", + "envs": [ + { + "name": "NODE_ENV", + "secret": false, + "value": "production" + }, + { + "name": "PORT", + "secret": false, + "value": "3000" + } + ], + "image": "blaxel/base-image:latest", + "memory": 4096, + "ports": [ + { + "name": "http", + "protocol": "HTTP", + "target": 3000 + } + ], + "display_name": "Baseten API review", + "external_id": "api-review-20260916-001", + "labels": { + "env": "development", + "project": "api-review", + "team": "engineering" + }, + "name": "baseten-api-review-0916", + "url": "https://sbx-baseten-api-review-0916-esb1qo.us-pdx-1.b10.run", + "status": "DEPLOYED", + "state": "RUNNING", + "created_at": "2026-09-16T21:26:58.545765901Z", + "updated_at": "2026-09-16T21:31:13Z", + "created_by": "sandbox-automation", + "updated_by": "sandbox-automation", + "last_used_at": "2026-09-16T21:31:13Z", + "expires_in": 86400 + } + ], + "pagination": { + "has_more": true, + "cursor": "eyJ2IjoxLCJsYXN0X2tleSI6ImJhc2V0ZW4tYXBpLXJldmlldy0wOTE2Iiwic29ydCI6ImRlc2MifQ" + } + } }, - "GatewayKeyInfoV1": { + "ListImagesResponseV1": { + "type": "object", + "description": "One page of image repository summaries. Fetch tags through the separate tag listing endpoint.", "properties": { - "prefix": { - "description": "The prefix of the Model API key.", - "title": "Prefix", - "type": "string" + "items": { + "type": "array", + "description": "Image repositories on this page.", + "items": { + "$ref": "#/components/schemas/ImageV1" + } }, - "name": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "description": "Optional display name.", - "title": "Name" + "pagination": { + "$ref": "#/components/schemas/SandboxApiPaginationV1" } }, "required": [ - "prefix" - ], - "title": "GatewayKeyInfoV1", - "type": "object" + "items", + "pagination" + ] }, - "KeysForGroupResponseV1": { + "ListImageTagsResponseV1": { + "type": "object", + "description": "One page of image tags.", "properties": { "items": { - "description": "Items in this page.", + "type": "array", "items": { - "$ref": "#/components/schemas/GatewayKeyInfoV1" - }, - "title": "Items", - "type": "array" + "$ref": "#/components/schemas/ImageTagV1" + } }, "pagination": { - "$ref": "#/components/schemas/PaginationResponseV1", - "description": "Pagination metadata for the page." + "$ref": "#/components/schemas/SandboxApiPaginationV1" } }, "required": [ "items", "pagination" + ] + }, + "ImageStatusV1": { + "type": "string", + "description": "Image processing status. Only BUILT images are ready to use.", + "enum": [ + "UPLOADING", + "BUILDING", + "BUILT", + "FAILED" ], - "title": "KeysForGroupResponseV1", - "type": "object" + "readOnly": true, + "example": "BUILT" }, - "CreateApiKeyForGroupRequestV1": { + "ImageTagV1": { + "type": "object", + "description": "A tag identifying a version of a sandbox image.", "properties": { "name": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "description": "Optional display name for the new key.", - "examples": [ - "prod-key-1" - ], - "title": "Name" + "type": "string", + "description": "Image tag name.", + "example": "latest" + }, + "created_at": { + "type": "string", + "description": "Time the tag was created.", + "format": "date-time", + "readOnly": true, + "example": "2026-09-16T21:20:00Z" + }, + "updated_at": { + "type": "string", + "description": "Time the tag was last updated.", + "format": "date-time", + "readOnly": true, + "example": "2026-09-16T21:25:00Z" + }, + "size": { + "type": "integer", + "description": "Image size in bytes.", + "format": "int64", + "minimum": 0, + "readOnly": true, + "example": 134217728 } }, - "title": "CreateApiKeyForGroupRequestV1", - "type": "object" + "required": [ + "name" + ], + "example": { + "name": "latest", + "created_at": "2026-09-16T21:20:00Z", + "updated_at": "2026-09-16T21:25:00Z", + "size": 134217728 + } }, - "CreateApiKeyForGroupResponseV1": { + "ImageV1": { + "type": "object", + "description": "Sandbox image repository. List and get operations return a summary without embedded tags.", "properties": { - "api_key": { - "description": "Plaintext key string, returned exactly once.", - "title": "Api Key", - "type": "string" + "name": { + "type": "string", + "description": "Stable repository name supplied when pushing the image.", + "example": "base-image" }, - "prefix": { - "description": "Key prefix (the part before the dot).", - "title": "Prefix", - "type": "string" + "display_name": { + "type": "string", + "description": "Human-readable image repository name.", + "example": "b10/base-image" }, - "name": { - "anyOf": [ + "status": { + "description": "Image processing status. Only BUILT images are ready to use.", + "allOf": [ { - "type": "string" + "$ref": "#/components/schemas/ImageStatusV1" + } + ], + "example": "BUILT" + }, + "created_at": { + "type": "string", + "description": "Time the image was created.", + "format": "date-time", + "readOnly": true, + "example": "2026-09-15T21:20:00Z" + }, + "updated_at": { + "type": "string", + "description": "Time the image was last updated.", + "format": "date-time", + "readOnly": true, + "example": "2026-09-16T21:25:00Z" + }, + "last_deployed_at": { + "type": "string", + "description": "Most recent deployment time across all tags, if deployed.", + "format": "date-time", + "readOnly": true, + "example": "2026-09-16T21:26:58.545765901Z" + }, + "size": { + "type": "integer", + "description": "Total repository size in bytes.", + "format": "int64", + "minimum": 0, + "readOnly": true, + "example": 260046848 + }, + "tag_count": { + "type": "integer", + "format": "int64", + "minimum": 0, + "readOnly": true, + "description": "Number of image versions in the repository.", + "example": 2 + }, + "tags": { + "type": "array", + "description": "Empty for list and get summary responses. Use GET /sandboxes/images/{image_name}/tags to retrieve paginated image versions.", + "items": { + "$ref": "#/components/schemas/ImageTagV1" + }, + "example": [ + { + "name": "latest", + "created_at": "2026-09-16T21:20:00Z", + "updated_at": "2026-09-16T21:25:00Z", + "size": 134217728 }, { - "type": "null" + "name": "20260915212000", + "created_at": "2026-09-15T21:20:00Z", + "updated_at": "2026-09-15T21:25:00Z", + "size": 125829120 } - ], - "default": null, - "description": "Display name of the key.", - "title": "Name" + ] } }, "required": [ - "api_key", - "prefix" - ], - "title": "CreateApiKeyForGroupResponseV1", - "type": "object" + "name", + "status", + "tags" + ], + "example": { + "name": "base-image", + "display_name": "b10/base-image", + "status": "BUILT", + "created_at": "2026-09-15T21:20:00Z", + "updated_at": "2026-09-16T21:25:00Z", + "last_deployed_at": "2026-09-16T21:26:58.545765901Z", + "size": 260046848, + "tags": [ + { + "name": "latest", + "created_at": "2026-09-16T21:20:00Z", + "updated_at": "2026-09-16T21:25:00Z", + "size": 134217728 + }, + { + "name": "20260915212000", + "created_at": "2026-09-15T21:20:00Z", + "updated_at": "2026-09-15T21:25:00Z", + "size": 125829120 + } + ] + } }, - "RegisterAPIKeyRequestV1": { - "description": "Request to register a caller-supplied API key against an existing FederatedGroup.", + "PushImageRequestV1": { + "type": "object", + "description": "Push a sandbox image from a source archive or an existing registry image.", "properties": { "name": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "description": "Optional name for the Model API key", - "examples": [ - "my-model-api-key" - ], - "title": "Name" + "type": "string", + "description": "Target image repository name. Reusing a name pushes a new version to the existing repository.", + "minLength": 1, + "example": "base-image" }, - "key": { - "description": "Value of the API key to register", - "examples": [ - "my-secure-api-key-value" + "image": { + "type": "string", + "description": "Optional source registry image reference including a registry hostname. When omitted, the response provides an archive upload URL.", + "example": "docker.io/b10/base-image:latest" + }, + "docker_config": { + "type": "string", + "description": "Optional serialized registry authentication configuration for importing a private image. Used only when image is supplied; never returned.", + "writeOnly": true, + "example": "{\"auths\":{\"https://index.docker.io/v1/\":{\"auth\":\"YjEwLXJldmlldzpkZW1vLW5vdC1hLXZhbGlkLXJlZ2lzdHJ5LXRva2Vu\"}}}" + } + }, + "required": [ + "name" + ], + "example": { + "name": "base-image", + "image": "docker.io/b10/base-image:latest", + "docker_config": "{\"auths\":{\"https://index.docker.io/v1/\":{\"auth\":\"YjEwLXJldmlldzpkZW1vLW5vdC1hLXZhbGlkLXJlZ2lzdHJ5LXRva2Vu\"}}}" + } + }, + "PushImageResponseV1": { + "type": "object", + "description": "Accepted image push. Acceptance does not imply readiness; poll GET /sandboxes/images/{image_name} until status is BUILT or FAILED.", + "properties": { + "name": { + "type": "string", + "description": "Target image repository name.", + "example": "base-image" + }, + "status": { + "description": "Image processing status. Only BUILT images are ready to use.", + "allOf": [ + { + "$ref": "#/components/schemas/ImageStatusV1" + } ], - "title": "Key", - "type": "string" + "example": "BUILDING" + }, + "upload_url": { + "type": "string", + "description": "Temporary signed URL for uploading the source ZIP archive with HTTP PUT. Present only when no source image was supplied. Uploading starts asynchronous processing. This storage upload is separate from the API endpoints.", + "format": "uri", + "example": "https://uploads.b10.run/images/base-image/20260916212658/source.zip?expires=2026-09-16T22%3A26%3A58Z&signature=demo-not-a-valid-upload-signature" + }, + "image": { + "type": "string", + "description": "Registered image reference including its tag, when available. Tags are assigned by the service; GET /sandboxes/images/{image_name} returns the available tags once processing completes.", + "example": "b10/base-image:latest" } }, "required": [ - "key" + "name", + "status" ], - "title": "RegisterAPIKeyRequestV1", - "type": "object" + "example": { + "name": "base-image", + "status": "BUILDING", + "image": "b10/base-image:latest" + } }, - "RegisterAPIKeyResponseV1": { + "CleanupImagesResponseV1": { + "type": "object", + "description": "Result of cleaning up unused sandbox images.", "properties": { - "ok": { - "description": "Whether the registration was successful", - "title": "Ok", - "type": "boolean" + "deleted": { + "type": "integer", + "description": "Number of image versions removed.", + "minimum": 0, + "example": 3 + }, + "message": { + "type": "string", + "description": "Human-readable cleanup result.", + "example": "Removed 3 unused image versions. Image versions used by active sandboxes were retained." } }, "required": [ - "ok" + "deleted", + "message" ], - "title": "RegisterAPIKeyResponseV1", - "type": "object" + "example": { + "deleted": 3, + "message": "Removed 3 unused image versions. Image versions used by active sandboxes were retained." + } } }, "parameters": { + "volume_sync_id": { + "schema": { + "type": "string" + }, + "name": "volume_sync_id", + "in": "path", + "required": true + }, "volume_namespace": { "schema": { "type": "string" @@ -28722,6 +34879,14 @@ "in": "path", "required": true }, + "route_id": { + "schema": { + "type": "string" + }, + "name": "route_id", + "in": "path", + "required": true + }, "endpoint_id": { "schema": { "type": "string" @@ -28737,6 +34902,82 @@ "name": "group_id", "in": "path", "required": true + }, + "TeamId": { + "name": "team_id", + "in": "query", + "required": false, + "description": "Optional team ID. Must match X-Team-Id when both are supplied. If neither selector is supplied, defaults to the caller's only accessible team. Callers with multiple accessible teams must select a team. Requests without access to any team are forbidden.", + "schema": { + "type": "string", + "minLength": 1 + } + }, + "TeamIdHeader": { + "name": "X-Team-Id", + "in": "header", + "required": false, + "description": "Optional team ID. Must match the team_id query parameter when both are supplied. If neither selector is supplied, defaults to the caller's only accessible team. Callers with multiple accessible teams must select a team. Requests without access to any team are forbidden.", + "schema": { + "type": "string", + "minLength": 1 + } + }, + "SandboxName": { + "name": "sandbox_name", + "in": "path", + "required": true, + "description": "Immutable sandbox name returned by creation.", + "schema": { + "type": "string", + "minLength": 1, + "example": "baseten-api-review-0916" + } + }, + "ImageName": { + "name": "image_name", + "in": "path", + "required": true, + "description": "Image repository name.", + "schema": { + "type": "string", + "minLength": 1, + "example": "base-image" + } + }, + "TagName": { + "name": "tag_name", + "in": "path", + "required": true, + "description": "Image tag name.", + "schema": { + "type": "string", + "minLength": 1, + "example": "20260915212000" + } + }, + "Cursor": { + "name": "cursor", + "in": "query", + "required": false, + "description": "Opaque cursor from the previous page; omit for the first page.", + "schema": { + "type": "string", + "example": "eyJ2IjoxLCJsYXN0X2tleSI6ImJhc2V0ZW4tYXBpLXJldmlldy0wOTE2Iiwic29ydCI6ImRlc2MifQ" + } + }, + "Limit": { + "name": "limit", + "in": "query", + "required": false, + "description": "Maximum number of items to return.", + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 20, + "example": 20 + } } }, "securitySchemes": { @@ -28745,6 +34986,881 @@ "scheme": "bearer", "description": "Send `Authorization: Bearer `. The legacy `Authorization: Api-Key ` scheme is also accepted." } + }, + "responses": { + "SandboxError400": { + "description": "Invalid request. Returns a JSON error with code, message, and optional details.", + "content": { + "application/json": { + "example": { + "code": "INVALID_REQUEST", + "message": "One or more request parameters are invalid.", + "details": { + "request_id": "a3b7c4d2-91e6-4f08-9b5a-2c6d7e8f1043" + } + } + } + } + }, + "SandboxError401": { + "description": "Missing or invalid authentication. Returns a JSON error with code, message, and optional details.", + "content": { + "application/json": { + "example": { + "code": "UNAUTHORIZED", + "message": "Provide a valid API key in the Authorization header.", + "details": { + "header": "Authorization" + } + } + } + } + }, + "SandboxError403": { + "description": "Insufficient permissions. Returns a JSON error with code, message, and optional details.", + "content": { + "application/json": { + "example": { + "code": "FORBIDDEN", + "message": "This API key does not have permission to perform this operation.", + "details": { + "request_id": "a3b7c4d2-91e6-4f08-9b5a-2c6d7e8f1043" + } + } + } + } + }, + "SandboxError404": { + "description": "Resource not found. Returns a JSON error with code, message, and optional details.", + "content": { + "application/json": { + "example": { + "code": "NOT_FOUND", + "message": "The requested resource was not found.", + "details": { + "request_id": "a3b7c4d2-91e6-4f08-9b5a-2c6d7e8f1043" + } + } + } + } + }, + "SandboxError409": { + "description": "Resource is currently in use or conflicts with the requested operation. Returns a JSON error with code, message, and optional details.", + "content": { + "application/json": { + "example": { + "code": "RESOURCE_IN_USE", + "message": "The resource is currently in use or conflicts with the requested operation.", + "details": { + "request_id": "a3b7c4d2-91e6-4f08-9b5a-2c6d7e8f1043" + } + } + } + } + }, + "SandboxError429": { + "description": "Request limit exceeded. Returns a JSON error with code, message, and optional details.", + "content": { + "application/json": { + "example": { + "code": "RATE_LIMITED", + "message": "Too many requests. Try again in 30 seconds.", + "details": { + "retry_after_seconds": 30 + } + } + } + } + }, + "SandboxError500": { + "description": "Internal server error. Returns a JSON error with code, message, and optional details.", + "content": { + "application/json": { + "example": { + "code": "INTERNAL_ERROR", + "message": "The request could not be completed. Try again later.", + "details": { + "request_id": "a3b7c4d2-91e6-4f08-9b5a-2c6d7e8f1043" + } + } + } + } + } + }, + "examples": { + "CreateSandboxQuickstart": { + "summary": "Run code with the built-in image", + "description": "Create directly with the built-in image; no image discovery, build, or push is needed. Use the returned url to call the sandbox execution API with the same Bearer API key.", + "value": { + "image": "blaxel/base-image:latest", + "memory": 2048 + } + }, + "CreateSandbox": { + "summary": "Create with every supported field", + "value": { + "name": "baseten-api-review-0916", + "lifecycle": { + "expiration_policies": [ + { + "action": "DELETE", + "type": "TTL_IDLE", + "value": "24h" + }, + { + "action": "DELETE", + "type": "TTL_MAX_AGE", + "value": "7d" + }, + { + "action": "DELETE", + "type": "DATE", + "value": "2026-09-23T21:26:58Z" + } + ], + "terminated_retention": "24h" + }, + "network": { + "proxy": { + "allowed_domains": [ + "api.openai.com", + "pypi.org", + "files.pythonhosted.org", + "registry.npmjs.org" + ], + "bypass": [ + "registry.npmjs.org" + ], + "forbidden_domains": [ + "facebook.com", + "*.facebook.com" + ], + "routing": [ + { + "destinations": [ + "api.openai.com" + ], + "headers": { + "Authorization": "Bearer {{SECRET:openai-key}}" + }, + "body": { + "user": "baseten-api-review-0916" + }, + "secrets": { + "openai-key": "sk-proj-demo-not-a-valid-api-key" + } + } + ] + }, + "subnet": "default" + }, + "region": "us-pdx-1", + "envs": [ + { + "name": "NODE_ENV", + "secret": false, + "value": "production" + }, + { + "name": "PORT", + "secret": false, + "value": "3000" + } + ], + "image": "blaxel/base-image:latest", + "memory": 4096, + "ports": [ + { + "name": "http", + "protocol": "HTTP", + "target": 3000 + } + ], + "display_name": "Baseten API review", + "external_id": "api-review-20260916-001", + "labels": { + "env": "development", + "project": "api-review", + "team": "engineering" + } + }, + "description": "All supported request fields are shown. Credential values are nonfunctional demonstration values." + }, + "UpdateSandbox": { + "summary": "Update every mutable field", + "value": { + "enabled": true, + "lifecycle": { + "expiration_policies": [ + { + "action": "DELETE", + "type": "TTL_IDLE", + "value": "24h" + }, + { + "action": "DELETE", + "type": "TTL_MAX_AGE", + "value": "7d" + }, + { + "action": "DELETE", + "type": "DATE", + "value": "2026-09-23T21:26:58Z" + } + ], + "terminated_retention": "24h" + }, + "region": "us-pdx-1", + "envs": [ + { + "name": "NODE_ENV", + "secret": false, + "value": "production" + }, + { + "name": "PORT", + "secret": false, + "value": "3000" + } + ], + "image": "blaxel/base-image:latest", + "ports": [ + { + "name": "http", + "protocol": "HTTP", + "target": 3000 + } + ], + "display_name": "Baseten API review - revised", + "external_id": "api-review-20260916-001", + "labels": { + "env": "development", + "project": "api-review", + "team": "engineering", + "revision": "2" + } + }, + "description": "All mutable request fields are shown. Memory and network configuration are only accepted during creation." + }, + "SandboxReady": { + "summary": "Running sandbox with complete configuration", + "value": { + "enabled": true, + "lifecycle": { + "expiration_policies": [ + { + "action": "DELETE", + "type": "TTL_IDLE", + "value": "24h" + }, + { + "action": "DELETE", + "type": "TTL_MAX_AGE", + "value": "7d" + }, + { + "action": "DELETE", + "type": "DATE", + "value": "2026-09-23T21:26:58Z" + } + ], + "terminated_retention": "24h" + }, + "network": { + "proxy": { + "allowed_domains": [ + "api.openai.com", + "pypi.org", + "files.pythonhosted.org", + "registry.npmjs.org" + ], + "bypass": [ + "registry.npmjs.org" + ], + "forbidden_domains": [ + "facebook.com", + "*.facebook.com" + ], + "routing": [ + { + "destinations": [ + "api.openai.com" + ], + "headers": { + "Authorization": "Bearer {{SECRET:openai-key}}" + }, + "body": { + "user": "baseten-api-review-0916" + } + } + ] + }, + "subnet": "default" + }, + "region": "us-pdx-1", + "envs": [ + { + "name": "NODE_ENV", + "secret": false, + "value": "production" + }, + { + "name": "PORT", + "secret": false, + "value": "3000" + } + ], + "image": "blaxel/base-image:latest", + "memory": 4096, + "ports": [ + { + "name": "http", + "protocol": "HTTP", + "target": 3000 + } + ], + "display_name": "Baseten API review", + "external_id": "api-review-20260916-001", + "labels": { + "env": "development", + "project": "api-review", + "team": "engineering" + }, + "name": "baseten-api-review-0916", + "url": "https://sbx-baseten-api-review-0916-esb1qo.us-pdx-1.b10.run", + "status": "DEPLOYED", + "state": "RUNNING", + "created_at": "2026-09-16T21:26:58.545765901Z", + "updated_at": "2026-09-16T21:31:13Z", + "created_by": "sandbox-automation", + "updated_by": "sandbox-automation", + "last_used_at": "2026-09-16T21:31:13Z", + "expires_in": 86400 + }, + "description": "Example sandbox URL in the b10.run domain. Write-only proxy secrets are not returned. Other values illustrate a fully configured sandbox." + }, + "SandboxUpdated": { + "summary": "Updated sandbox with complete configuration", + "value": { + "enabled": true, + "lifecycle": { + "expiration_policies": [ + { + "action": "DELETE", + "type": "TTL_IDLE", + "value": "24h" + }, + { + "action": "DELETE", + "type": "TTL_MAX_AGE", + "value": "7d" + }, + { + "action": "DELETE", + "type": "DATE", + "value": "2026-09-23T21:26:58Z" + } + ], + "terminated_retention": "24h" + }, + "network": { + "proxy": { + "allowed_domains": [ + "api.openai.com", + "pypi.org", + "files.pythonhosted.org", + "registry.npmjs.org" + ], + "bypass": [ + "registry.npmjs.org" + ], + "forbidden_domains": [ + "facebook.com", + "*.facebook.com" + ], + "routing": [ + { + "destinations": [ + "api.openai.com" + ], + "headers": { + "Authorization": "Bearer {{SECRET:openai-key}}" + }, + "body": { + "user": "baseten-api-review-0916" + } + } + ] + }, + "subnet": "default" + }, + "region": "us-pdx-1", + "envs": [ + { + "name": "NODE_ENV", + "secret": false, + "value": "production" + }, + { + "name": "PORT", + "secret": false, + "value": "3000" + } + ], + "image": "blaxel/base-image:latest", + "memory": 4096, + "ports": [ + { + "name": "http", + "protocol": "HTTP", + "target": 3000 + } + ], + "display_name": "Baseten API review - revised", + "external_id": "api-review-20260916-001", + "labels": { + "env": "development", + "project": "api-review", + "team": "engineering", + "revision": "2" + }, + "name": "baseten-api-review-0916", + "url": "https://sbx-baseten-api-review-0916-esb1qo.us-pdx-1.b10.run", + "status": "DEPLOYED", + "state": "RUNNING", + "created_at": "2026-09-16T21:26:58.545765901Z", + "updated_at": "2026-09-16T21:36:13Z", + "created_by": "sandbox-automation", + "updated_by": "sandbox-automation", + "last_used_at": "2026-09-16T21:36:13Z", + "expires_in": 86400 + } + }, + "SandboxDeleting": { + "summary": "Sandbox deletion accepted", + "value": { + "enabled": true, + "lifecycle": { + "expiration_policies": [ + { + "action": "DELETE", + "type": "TTL_IDLE", + "value": "24h" + }, + { + "action": "DELETE", + "type": "TTL_MAX_AGE", + "value": "7d" + }, + { + "action": "DELETE", + "type": "DATE", + "value": "2026-09-23T21:26:58Z" + } + ], + "terminated_retention": "24h" + }, + "network": { + "proxy": { + "allowed_domains": [ + "api.openai.com", + "pypi.org", + "files.pythonhosted.org", + "registry.npmjs.org" + ], + "bypass": [ + "registry.npmjs.org" + ], + "forbidden_domains": [ + "facebook.com", + "*.facebook.com" + ], + "routing": [ + { + "destinations": [ + "api.openai.com" + ], + "headers": { + "Authorization": "Bearer {{SECRET:openai-key}}" + }, + "body": { + "user": "baseten-api-review-0916" + } + } + ] + }, + "subnet": "default" + }, + "region": "us-pdx-1", + "envs": [ + { + "name": "NODE_ENV", + "secret": false, + "value": "production" + }, + { + "name": "PORT", + "secret": false, + "value": "3000" + } + ], + "image": "blaxel/base-image:latest", + "memory": 4096, + "ports": [ + { + "name": "http", + "protocol": "HTTP", + "target": 3000 + } + ], + "display_name": "Baseten API review", + "external_id": "api-review-20260916-001", + "labels": { + "env": "development", + "project": "api-review", + "team": "engineering" + }, + "name": "baseten-api-review-0916", + "url": "https://sbx-baseten-api-review-0916-esb1qo.us-pdx-1.b10.run", + "status": "DELETING", + "state": "RUNNING", + "created_at": "2026-09-16T21:26:58.545765901Z", + "updated_at": "2026-09-16T21:41:13Z", + "created_by": "sandbox-automation", + "updated_by": "sandbox-automation", + "last_used_at": "2026-09-16T21:31:13Z", + "expires_in": 85800 + } + }, + "SandboxesPage": { + "summary": "Sandbox page with another page available", + "value": { + "items": [ + { + "enabled": true, + "lifecycle": { + "expiration_policies": [ + { + "action": "DELETE", + "type": "TTL_IDLE", + "value": "24h" + }, + { + "action": "DELETE", + "type": "TTL_MAX_AGE", + "value": "7d" + }, + { + "action": "DELETE", + "type": "DATE", + "value": "2026-09-23T21:26:58Z" + } + ], + "terminated_retention": "24h" + }, + "network": { + "proxy": { + "allowed_domains": [ + "api.openai.com", + "pypi.org", + "files.pythonhosted.org", + "registry.npmjs.org" + ], + "bypass": [ + "registry.npmjs.org" + ], + "forbidden_domains": [ + "facebook.com", + "*.facebook.com" + ], + "routing": [ + { + "destinations": [ + "api.openai.com" + ], + "headers": { + "Authorization": "Bearer {{SECRET:openai-key}}" + }, + "body": { + "user": "baseten-api-review-0916" + } + } + ] + }, + "subnet": "default" + }, + "region": "us-pdx-1", + "envs": [ + { + "name": "NODE_ENV", + "secret": false, + "value": "production" + }, + { + "name": "PORT", + "secret": false, + "value": "3000" + } + ], + "image": "blaxel/base-image:latest", + "memory": 4096, + "ports": [ + { + "name": "http", + "protocol": "HTTP", + "target": 3000 + } + ], + "display_name": "Baseten API review", + "external_id": "api-review-20260916-001", + "labels": { + "env": "development", + "project": "api-review", + "team": "engineering" + }, + "name": "baseten-api-review-0916", + "url": "https://sbx-baseten-api-review-0916-esb1qo.us-pdx-1.b10.run", + "status": "DEPLOYED", + "state": "RUNNING", + "created_at": "2026-09-16T21:26:58.545765901Z", + "updated_at": "2026-09-16T21:31:13Z", + "created_by": "sandbox-automation", + "updated_by": "sandbox-automation", + "last_used_at": "2026-09-16T21:31:13Z", + "expires_in": 86400 + } + ], + "pagination": { + "has_more": true, + "cursor": "eyJ2IjoxLCJsYXN0X2tleSI6ImJhc2V0ZW4tYXBpLXJldmlldy0wOTE2Iiwic29ydCI6ImRlc2MifQ" + } + }, + "description": "The cursor illustrates an opaque pagination token; it is not a reusable live cursor." + }, + "SandboxesLastPage": { + "summary": "Last sandbox page", + "value": { + "items": [ + { + "enabled": true, + "lifecycle": { + "expiration_policies": [ + { + "action": "DELETE", + "type": "TTL_IDLE", + "value": "24h" + }, + { + "action": "DELETE", + "type": "TTL_MAX_AGE", + "value": "7d" + }, + { + "action": "DELETE", + "type": "DATE", + "value": "2026-09-23T21:26:58Z" + } + ], + "terminated_retention": "24h" + }, + "network": { + "proxy": { + "allowed_domains": [ + "api.openai.com", + "pypi.org", + "files.pythonhosted.org", + "registry.npmjs.org" + ], + "bypass": [ + "registry.npmjs.org" + ], + "forbidden_domains": [ + "facebook.com", + "*.facebook.com" + ], + "routing": [ + { + "destinations": [ + "api.openai.com" + ], + "headers": { + "Authorization": "Bearer {{SECRET:openai-key}}" + }, + "body": { + "user": "baseten-api-review-0916" + } + } + ] + }, + "subnet": "default" + }, + "region": "us-pdx-1", + "envs": [ + { + "name": "NODE_ENV", + "secret": false, + "value": "production" + }, + { + "name": "PORT", + "secret": false, + "value": "3000" + } + ], + "image": "blaxel/base-image:latest", + "memory": 4096, + "ports": [ + { + "name": "http", + "protocol": "HTTP", + "target": 3000 + } + ], + "display_name": "Baseten API review", + "external_id": "api-review-20260916-001", + "labels": { + "env": "development", + "project": "api-review", + "team": "engineering" + }, + "name": "baseten-api-review-0916", + "url": "https://sbx-baseten-api-review-0916-esb1qo.us-pdx-1.b10.run", + "status": "DEPLOYED", + "state": "RUNNING", + "created_at": "2026-09-16T21:26:58.545765901Z", + "updated_at": "2026-09-16T21:31:13Z", + "created_by": "sandbox-automation", + "updated_by": "sandbox-automation", + "last_used_at": "2026-09-16T21:31:13Z", + "expires_in": 86400 + } + ], + "pagination": { + "has_more": false + } + } + }, + "ImageReady": { + "summary": "Built image with all metadata and tags", + "value": { + "name": "base-image", + "display_name": "b10/base-image", + "status": "BUILT", + "created_at": "2026-09-15T21:20:00Z", + "updated_at": "2026-09-16T21:25:00Z", + "last_deployed_at": "2026-09-16T21:26:58.545765901Z", + "size": 260046848, + "tags": [ + { + "name": "latest", + "created_at": "2026-09-16T21:20:00Z", + "updated_at": "2026-09-16T21:25:00Z", + "size": 134217728 + }, + { + "name": "20260915212000", + "created_at": "2026-09-15T21:20:00Z", + "updated_at": "2026-09-15T21:25:00Z", + "size": 125829120 + } + ] + }, + "description": "Dates and byte sizes are representative example data. Image references use the b10 namespace." + }, + "ImageAfterTagDeletion": { + "summary": "Image after deleting its older tag", + "value": { + "name": "base-image", + "display_name": "b10/base-image", + "status": "BUILT", + "created_at": "2026-09-15T21:20:00Z", + "updated_at": "2026-09-16T21:41:13Z", + "last_deployed_at": "2026-09-16T21:26:58.545765901Z", + "size": 134217728, + "tags": [ + { + "name": "latest", + "created_at": "2026-09-16T21:20:00Z", + "updated_at": "2026-09-16T21:25:00Z", + "size": 134217728 + } + ] + } + }, + "ImageSummary": { + "summary": "Image repository summary", + "value": { + "name": "base-image", + "display_name": "b10/base-image", + "status": "BUILT", + "created_at": "2026-09-15T21:20:00Z", + "size": 260046848, + "tag_count": 2, + "tags": [] + } + }, + "ImagesList": { + "summary": "One page of image repositories", + "value": { + "items": [ + { + "name": "base-image", + "display_name": "b10/base-image", + "status": "BUILT", + "created_at": "2026-09-15T21:20:00Z", + "updated_at": "2026-09-16T21:25:00Z", + "last_deployed_at": "2026-09-16T21:26:58.545765901Z", + "size": 260046848, + "tag_count": 2, + "tags": [] + } + ], + "pagination": { + "has_more": false + } + } + }, + "PushArchive": { + "summary": "Build an image from an uploaded source archive", + "value": { + "name": "base-image" + }, + "description": "Omit image and docker_config to request an upload URL. Those fields do not apply to source-archive uploads." + }, + "PushRegistry": { + "summary": "Import an image with registry authentication", + "value": { + "name": "base-image", + "image": "docker.io/b10/base-image:latest", + "docker_config": "{\"auths\":{\"https://index.docker.io/v1/\":{\"auth\":\"YjEwLXJldmlldzpkZW1vLW5vdC1hLXZhbGlkLXJlZ2lzdHJ5LXRva2Vu\"}}}" + }, + "description": "Shows every request field. docker_config is serialized registry configuration with a deliberately invalid demonstration credential." + }, + "PushArchiveAccepted": { + "summary": "Source upload required", + "value": { + "name": "base-image", + "status": "UPLOADING", + "upload_url": "https://uploads.b10.run/images/base-image/20260916212658/source.zip?expires=2026-09-16T22%3A26%3A58Z&signature=demo-not-a-valid-upload-signature" + }, + "description": "The signed upload URL is illustrative, with a nonfunctional signature. image is unavailable until processing produces a registered image reference." + }, + "PushRegistryAccepted": { + "summary": "Image import accepted", + "value": { + "name": "base-image", + "status": "BUILDING", + "image": "b10/base-image:latest" + }, + "description": "No upload_url is returned for registry imports." + }, + "CleanupImages": { + "summary": "Unused image versions removed", + "value": { + "deleted": 3, + "message": "Removed 3 unused image versions. Image versions used by active sandboxes were retained." + } + } } } } \ No newline at end of file From 34f9127c60f9f9ed3b3137c54f7891888c8a5fb2 Mon Sep 17 00:00:00 2001 From: "Marius F. Killinger" Date: Tue, 29 Sep 2026 17:11:23 -0700 Subject: [PATCH 02/15] Add sandbox API client and split query params from request bodies Query parameters now go on `params` and request bodies on `request` (both may coexist on sandbox operations; management and inference still enforce query-XOR-body). Success responses are a code collection, non-JSON bodies (multipart, octet-stream) are supported, and operations with non-JSON success responses get a `_raw` sibling that takes an `accept` and returns the httpx response unread. Generator changes: rename injected query schemas XRequest -> XParams, hoist inline 2xx response schemas into components, fold non-identifier schema names (archive.Change -> ArchiveChange) into PascalCase, accept YAML specs, and add the sandbox spec from blaxel-ai/sandbox. Management spec updated from staging, which adds /v1/sandboxes and /v1/token over prod. New internal SandboxClient/AsyncSandboxClient wrapper. Bumped to 0.12.0 for the breaking argument split. Co-Authored-By: Claude Code --- README.md | 15 +- baseten/client/_sandbox.py | 205 ++ baseten/client/inferenceapi/_client.py | 480 ++- baseten/client/managementapi/__init__.py | 342 ++- baseten/client/managementapi/_client.py | 2129 ++++++++++---- baseten/client/managementapi/_models.py | 3374 +++++++++++++++++++--- baseten/client/sandboxapi/__init__.py | 164 ++ baseten/client/sandboxapi/_client.py | 1931 +++++++++++++ baseten/client/sandboxapi/_models.py | 927 ++++++ pyproject.toml | 2 +- scripts/apigen/__main__.py | 38 +- scripts/apigen/clientgen.py | 317 +- scripts/apigen/preprocess.py | 105 +- scripts/apigen/specs/sandbox.yml | 2794 ++++++++++++++++++ scripts/docgen/conf.py | 1 + tests/client/test_management.py | 2 +- tests/client/test_sandbox.py | 200 ++ tests/conftest.py | 26 +- 18 files changed, 11773 insertions(+), 1279 deletions(-) create mode 100644 baseten/client/_sandbox.py create mode 100644 baseten/client/sandboxapi/__init__.py create mode 100644 baseten/client/sandboxapi/_client.py create mode 100644 baseten/client/sandboxapi/_models.py create mode 100644 scripts/apigen/specs/sandbox.yml create mode 100644 tests/client/test_sandbox.py diff --git a/README.md b/README.md index 37cdb33..da4203d 100644 --- a/README.md +++ b/README.md @@ -37,4 +37,17 @@ async with AsyncManagementClient(api_key="my-api-key") as client: ## Upgrading from 0.8.2 and earlier Version 0.9.0 is a rewrite and shares no API with the earlier `baseten` releases. -Code written against 0.8.2 or earlier will not work. Pin `baseten<0.9` to keep it. \ No newline at end of file +Code written against 0.8.2 or earlier will not work. Pin `baseten<0.9` to keep it. + +## Upgrading from 0.11.0 and earlier + +Version 0.12.0 splits request arguments. Query parameters now go on `params`, and +request bodies stay on `request`. Before, both used `request`. Rename the keyword on +calls that pass query parameters: + +```python +# 0.11.0 and earlier +client.api.get_model_apis(request=GetModelApisRequest(added_only=True)) +# 0.12.0 +client.api.get_model_apis(params=GetModelApisParams(added_only=True)) +``` \ No newline at end of file diff --git a/baseten/client/_sandbox.py b/baseten/client/_sandbox.py new file mode 100644 index 0000000..6d26535 --- /dev/null +++ b/baseten/client/_sandbox.py @@ -0,0 +1,205 @@ +from __future__ import annotations + +from collections.abc import Mapping +from dataclasses import dataclass +from typing import Self + +import httpx + +import baseten.client.sandboxapi +from baseten.client._user_agent import with_user_agent + + +@dataclass(frozen=True) +class SandboxClientOptions: + """Options for :class:`SandboxClient` and :class:`AsyncSandboxClient`. + + Obtain via :attr:`SandboxClient.options` to inspect the values a client + was constructed with. + """ + + token: str + """Sandbox token for authentication.""" + + base_url: str + """Base URL of the sandbox, without a trailing slash. + + Each sandbox is reached at its own host, so there is no default. + """ + + headers: Mapping[str, str] | None = None + """Additional headers to send on every request.""" + + +class SandboxClient: + """Synchronous client for one sandbox's execution-plane API. + + Can be used as a context manager to ensure the underlying HTTP client is + closed on exit. + """ + + def __init__( + self, + *, + token: str, + base_url: str, + headers: Mapping[str, str] | None = None, + http_client_override: httpx.Client | None = None, + close_http_client_on_close: bool | None = None, + ) -> None: + """Create a new synchronous sandbox client. + + Args: + token: Sandbox token for authentication. + base_url: Base URL of the sandbox, without a trailing slash. + headers: Additional headers to send on every request. + http_client_override: Pre-configured httpx client. When provided, + the caller is responsible for setting base URL and all + headers. + close_http_client_on_close: Whether :meth:`close` should close the + underlying HTTP client. Defaults to ``True`` when the client + is created internally, ``False`` when *http_client_override* + is provided. + """ + self._options = SandboxClientOptions( + token=token, base_url=base_url, headers=headers + ) + if http_client_override is None: + request_headers: dict[str, str] = {**(headers or {})} + # Empty token is an advanced opt-out from sending Authorization. + if token != "": + request_headers["Authorization"] = f"Bearer {token}" + self._http_client = httpx.Client( + base_url=base_url, + headers=with_user_agent(request_headers), + ) + self.close_http_client_on_close = ( + True + if close_http_client_on_close is None + else close_http_client_on_close + ) + else: + self._http_client = http_client_override + self.close_http_client_on_close = ( + False + if close_http_client_on_close is None + else close_http_client_on_close + ) + self._api = baseten.client.sandboxapi.ApiClient(self._http_client) + + @property + def options(self) -> SandboxClientOptions: + """Client options.""" + return self._options + + @property + def http_client(self) -> httpx.Client: + """The underlying HTTP client.""" + return self._http_client + + @property + def api(self) -> baseten.client.sandboxapi.ApiClient: + """The generated API client. + + The generated API surface is not covered by stability guarantees and + may change between versions. + """ + return self._api + + def close(self) -> None: + """Close the client, optionally closing the underlying HTTP client.""" + if self.close_http_client_on_close: + self._http_client.close() + + def __enter__(self) -> Self: + return self + + def __exit__(self, *args: object) -> None: + self.close() + + +class AsyncSandboxClient: + """Asynchronous client for one sandbox's execution-plane API. + + Can be used as an async context manager to ensure the underlying HTTP + client is closed on exit. + """ + + def __init__( + self, + *, + token: str, + base_url: str, + headers: Mapping[str, str] | None = None, + http_client_override: httpx.AsyncClient | None = None, + close_http_client_on_close: bool | None = None, + ) -> None: + """Create a new asynchronous sandbox client. + + Args: + token: Sandbox token for authentication. + base_url: Base URL of the sandbox, without a trailing slash. + headers: Additional headers to send on every request. + http_client_override: Pre-configured httpx client. When provided, + the caller is responsible for setting base URL and all + headers. + close_http_client_on_close: Whether :meth:`close` should close the + underlying HTTP client. Defaults to ``True`` when the client + is created internally, ``False`` when *http_client_override* + is provided. + """ + self._options = SandboxClientOptions( + token=token, base_url=base_url, headers=headers + ) + if http_client_override is None: + request_headers: dict[str, str] = {**(headers or {})} + # Empty token is an advanced opt-out from sending Authorization. + if token != "": + request_headers["Authorization"] = f"Bearer {token}" + self._http_client = httpx.AsyncClient( + base_url=base_url, + headers=with_user_agent(request_headers), + ) + self.close_http_client_on_close = ( + True + if close_http_client_on_close is None + else close_http_client_on_close + ) + else: + self._http_client = http_client_override + self.close_http_client_on_close = ( + False + if close_http_client_on_close is None + else close_http_client_on_close + ) + self._api = baseten.client.sandboxapi.AsyncApiClient(self._http_client) + + @property + def options(self) -> SandboxClientOptions: + """Client options.""" + return self._options + + @property + def http_client(self) -> httpx.AsyncClient: + """The underlying HTTP client.""" + return self._http_client + + @property + def api(self) -> baseten.client.sandboxapi.AsyncApiClient: + """The generated API client. + + The generated API surface is not covered by stability guarantees and + may change between versions. + """ + return self._api + + async def close(self) -> None: + """Close the client, optionally closing the underlying HTTP client.""" + if self.close_http_client_on_close: + await self._http_client.aclose() + + async def __aenter__(self) -> Self: + return self + + async def __aexit__(self, *args: object) -> None: + await self.close() diff --git a/baseten/client/inferenceapi/_client.py b/baseten/client/inferenceapi/_client.py index ae50cd8..8b50a43 100644 --- a/baseten/client/inferenceapi/_client.py +++ b/baseten/client/inferenceapi/_client.py @@ -5,7 +5,7 @@ import contextlib import urllib.parse from dataclasses import dataclass -from typing import Any, TypeVar +from typing import Any, Literal, TypeVar import httpx from pydantic import BaseModel, ValidationError @@ -58,8 +58,10 @@ class _ApiRequest: path_args: list[str] body: Any query: Any - success_code: int + success_codes: list[int] error_codes: dict[int, str] | None + body_content_type: str | None = None + accept: str | None = None class ApiClient: @@ -86,7 +88,7 @@ def async_predict( path_args=[env_name], body=request, query=None, - success_code=201, + success_codes=[201], error_codes={ 400: "ErrorResponse", 401: "ErrorResponse", @@ -109,7 +111,7 @@ def async_predict_deployment( path_args=[deployment_id], body=request, query=None, - success_code=201, + success_codes=[201], error_codes={ 400: "ErrorResponse", 401: "ErrorResponse", @@ -132,7 +134,7 @@ def async_predict_development( path_args=[], body=request, query=None, - success_code=201, + success_codes=[201], error_codes={ 400: "ErrorResponse", 401: "ErrorResponse", @@ -155,7 +157,7 @@ def async_predict_production( path_args=[], body=request, query=None, - success_code=201, + success_codes=[201], error_codes={ 400: "ErrorResponse", 401: "ErrorResponse", @@ -178,7 +180,7 @@ def async_predict_regional( path_args=[], body=request, query=None, - success_code=201, + success_codes=[201], error_codes={ 400: "ErrorResponse", 401: "ErrorResponse", @@ -201,7 +203,7 @@ def async_run_remote( path_args=[env_name], body=request, query=None, - success_code=201, + success_codes=[201], error_codes={ 400: "ErrorResponse", 401: "ErrorResponse", @@ -223,7 +225,7 @@ def async_run_remote_deployment( path_args=[deployment_id], body=request, query=None, - success_code=201, + success_codes=[201], error_codes={ 400: "ErrorResponse", 401: "ErrorResponse", @@ -245,7 +247,7 @@ def async_run_remote_development( path_args=[], body=request, query=None, - success_code=201, + success_codes=[201], error_codes={ 400: "ErrorResponse", 401: "ErrorResponse", @@ -267,7 +269,7 @@ def async_run_remote_production( path_args=[], body=request, query=None, - success_code=201, + success_codes=[201], error_codes={ 400: "ErrorResponse", 401: "ErrorResponse", @@ -289,7 +291,7 @@ def async_run_remote_regional( path_args=[], body=request, query=None, - success_code=201, + success_codes=[201], error_codes={ 400: "ErrorResponse", 401: "ErrorResponse", @@ -309,7 +311,7 @@ def cancel_async_request(self, *, request_id: str) -> CancelAsyncRequestOutput: path_args=[request_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes={401: "ErrorResponse", 429: "ErrorResponse"}, ), ) @@ -324,7 +326,7 @@ def get_async_queue_status(self, *, env_name: str) -> GetAsyncQueueStatusOutput: path_args=[env_name], body=None, query=None, - success_code=200, + success_codes=[200], error_codes={401: "ErrorResponse", 429: "ErrorResponse"}, ), ) @@ -341,7 +343,7 @@ def get_async_queue_status_deployment( path_args=[deployment_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes={401: "ErrorResponse", 429: "ErrorResponse"}, ), ) @@ -356,7 +358,7 @@ def get_async_queue_status_development(self) -> GetAsyncQueueStatusOutput: path_args=[], body=None, query=None, - success_code=200, + success_codes=[200], error_codes={401: "ErrorResponse", 429: "ErrorResponse"}, ), ) @@ -371,7 +373,7 @@ def get_async_queue_status_production(self) -> GetAsyncQueueStatusOutput: path_args=[], body=None, query=None, - success_code=200, + success_codes=[200], error_codes={401: "ErrorResponse", 429: "ErrorResponse"}, ), ) @@ -386,7 +388,7 @@ def get_async_queue_status_regional(self) -> GetAsyncQueueStatusOutput: path_args=[], body=None, query=None, - success_code=200, + success_codes=[200], error_codes={401: "ErrorResponse", 429: "ErrorResponse"}, ), ) @@ -403,7 +405,7 @@ def get_async_request_status( path_args=[request_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes={401: "ErrorResponse", 429: "ErrorResponse"}, ), ) @@ -418,7 +420,7 @@ def predict(self, *, env_name: str, request: PredictInput) -> PredictOutput: path_args=[env_name], body=request, query=None, - success_code=200, + success_codes=[200], error_codes={ 400: "ErrorResponse", 401: "ErrorResponse", @@ -430,6 +432,34 @@ def predict(self, *, env_name: str, request: PredictInput) -> PredictOutput: ), ) + def predict_raw( + self, + *, + env_name: str, + request: PredictInput, + accept: Literal["application/json", "application/octet-stream"], + ) -> httpx.Response: + """Call the model deployment associated with a specified environment.. Returns the response unread, in the requested content type.""" + return self._do( + _ApiRequest( + method="POST", + path_fmt="/environments/{}/predict", + path_args=[env_name], + body=request, + query=None, + success_codes=[200], + error_codes={ + 400: "ErrorResponse", + 401: "ErrorResponse", + 429: "ErrorResponse", + 502: "ErrorResponse", + 503: "ErrorResponse", + 504: "ErrorResponse", + }, + accept=accept, + ) + ) + def predict_deployment( self, *, deployment_id: str, request: PredictInput ) -> PredictOutput: @@ -442,7 +472,7 @@ def predict_deployment( path_args=[deployment_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes={ 400: "ErrorResponse", 401: "ErrorResponse", @@ -454,6 +484,34 @@ def predict_deployment( ), ) + def predict_deployment_raw( + self, + *, + deployment_id: str, + request: PredictInput, + accept: Literal["application/json", "application/octet-stream"], + ) -> httpx.Response: + """Call a specific deployment of a model by deployment ID.. Returns the response unread, in the requested content type.""" + return self._do( + _ApiRequest( + method="POST", + path_fmt="/deployment/{}/predict", + path_args=[deployment_id], + body=request, + query=None, + success_codes=[200], + error_codes={ + 400: "ErrorResponse", + 401: "ErrorResponse", + 429: "ErrorResponse", + 502: "ErrorResponse", + 503: "ErrorResponse", + 504: "ErrorResponse", + }, + accept=accept, + ) + ) + def predict_development(self, *, request: PredictInput) -> PredictOutput: """Call the development deployment of a model.""" return self._do_json( @@ -464,7 +522,7 @@ def predict_development(self, *, request: PredictInput) -> PredictOutput: path_args=[], body=request, query=None, - success_code=200, + success_codes=[200], error_codes={ 400: "ErrorResponse", 401: "ErrorResponse", @@ -476,6 +534,33 @@ def predict_development(self, *, request: PredictInput) -> PredictOutput: ), ) + def predict_development_raw( + self, + *, + request: PredictInput, + accept: Literal["application/json", "application/octet-stream"], + ) -> httpx.Response: + """Call the development deployment of a model.. Returns the response unread, in the requested content type.""" + return self._do( + _ApiRequest( + method="POST", + path_fmt="/development/predict", + path_args=[], + body=request, + query=None, + success_codes=[200], + error_codes={ + 400: "ErrorResponse", + 401: "ErrorResponse", + 429: "ErrorResponse", + 502: "ErrorResponse", + 503: "ErrorResponse", + 504: "ErrorResponse", + }, + accept=accept, + ) + ) + def predict_production(self, *, request: PredictInput) -> PredictOutput: """Call the production environment of a model.""" return self._do_json( @@ -486,7 +571,7 @@ def predict_production(self, *, request: PredictInput) -> PredictOutput: path_args=[], body=request, query=None, - success_code=200, + success_codes=[200], error_codes={ 400: "ErrorResponse", 401: "ErrorResponse", @@ -498,6 +583,33 @@ def predict_production(self, *, request: PredictInput) -> PredictOutput: ), ) + def predict_production_raw( + self, + *, + request: PredictInput, + accept: Literal["application/json", "application/octet-stream"], + ) -> httpx.Response: + """Call the production environment of a model.. Returns the response unread, in the requested content type.""" + return self._do( + _ApiRequest( + method="POST", + path_fmt="/production/predict", + path_args=[], + body=request, + query=None, + success_codes=[200], + error_codes={ + 400: "ErrorResponse", + 401: "ErrorResponse", + 429: "ErrorResponse", + 502: "ErrorResponse", + 503: "ErrorResponse", + 504: "ErrorResponse", + }, + accept=accept, + ) + ) + def predict_regional(self, *, request: PredictInput) -> PredictOutput: """Call a regional environment of a model.""" return self._do_json( @@ -508,7 +620,7 @@ def predict_regional(self, *, request: PredictInput) -> PredictOutput: path_args=[], body=request, query=None, - success_code=200, + success_codes=[200], error_codes={ 400: "ErrorResponse", 401: "ErrorResponse", @@ -520,6 +632,33 @@ def predict_regional(self, *, request: PredictInput) -> PredictOutput: ), ) + def predict_regional_raw( + self, + *, + request: PredictInput, + accept: Literal["application/json", "application/octet-stream"], + ) -> httpx.Response: + """Call a regional environment of a model.. Returns the response unread, in the requested content type.""" + return self._do( + _ApiRequest( + method="POST", + path_fmt="/predict", + path_args=[], + body=request, + query=None, + success_codes=[200], + error_codes={ + 400: "ErrorResponse", + 401: "ErrorResponse", + 429: "ErrorResponse", + 502: "ErrorResponse", + 503: "ErrorResponse", + 504: "ErrorResponse", + }, + accept=accept, + ) + ) + def run_remote(self, *, env_name: str, request: RunRemoteInput) -> RunRemoteOutput: """Call the chain deployment associated with a specified environment.""" return self._do_json( @@ -530,7 +669,7 @@ def run_remote(self, *, env_name: str, request: RunRemoteInput) -> RunRemoteOutp path_args=[env_name], body=request, query=None, - success_code=200, + success_codes=[200], error_codes={ 400: "ErrorResponse", 401: "ErrorResponse", @@ -554,7 +693,7 @@ def run_remote_deployment( path_args=[deployment_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes={ 400: "ErrorResponse", 401: "ErrorResponse", @@ -576,7 +715,7 @@ def run_remote_development(self, *, request: RunRemoteInput) -> RunRemoteOutput: path_args=[], body=request, query=None, - success_code=200, + success_codes=[200], error_codes={ 400: "ErrorResponse", 401: "ErrorResponse", @@ -598,7 +737,7 @@ def run_remote_production(self, *, request: RunRemoteInput) -> RunRemoteOutput: path_args=[], body=request, query=None, - success_code=200, + success_codes=[200], error_codes={ 400: "ErrorResponse", 401: "ErrorResponse", @@ -620,7 +759,7 @@ def run_remote_regional(self, *, request: RunRemoteInput) -> RunRemoteOutput: path_args=[], body=request, query=None, - success_code=200, + success_codes=[200], error_codes={ 400: "ErrorResponse", 401: "ErrorResponse", @@ -641,7 +780,7 @@ def wake(self, *, env_name: str) -> None: path_args=[env_name], body=None, query=None, - success_code=202, + success_codes=[202], error_codes={401: "ErrorResponse"}, ) ) @@ -655,7 +794,7 @@ def wake_deployment(self, *, deployment_id: str) -> None: path_args=[deployment_id], body=None, query=None, - success_code=202, + success_codes=[202], error_codes={401: "ErrorResponse"}, ) ) @@ -669,7 +808,7 @@ def wake_development(self) -> None: path_args=[], body=None, query=None, - success_code=202, + success_codes=[202], error_codes={401: "ErrorResponse"}, ) ) @@ -683,7 +822,7 @@ def wake_production(self) -> None: path_args=[], body=None, query=None, - success_code=202, + success_codes=[202], error_codes={401: "ErrorResponse"}, ) ) @@ -697,7 +836,7 @@ def wake_regional(self) -> None: path_args=[], body=None, query=None, - success_code=202, + success_codes=[202], error_codes={401: "ErrorResponse"}, ) ) @@ -707,14 +846,26 @@ def _do(self, request: _ApiRequest) -> httpx.Response: *[urllib.parse.quote(a, safe="") for a in request.path_args] ) json_body = None + content_body = None + files_body = None + headers: dict[str, str] = {} + if request.accept is not None: + headers["Accept"] = request.accept if request.body is not None: - if isinstance(request.body, BaseModel): - # Only fields the caller set are sent, so unset fields fall - # back to the server default rather than being reset here. - # An explicit None is kept, since null can mean "clear". - json_body = request.body.model_dump(mode="json", exclude_unset=True) + if request.body_content_type is None: + if isinstance(request.body, BaseModel): + # Only fields the caller set are sent, so unset fields fall + # back to the server default rather than being reset here. + # An explicit None is kept, since null can mean "clear". + json_body = request.body.model_dump(mode="json", exclude_unset=True) + else: + json_body = request.body + elif request.body_content_type == "multipart/form-data": + # httpx derives the multipart Content-Type, boundary included. + files_body = request.body else: - json_body = request.body + headers["Content-Type"] = request.body_content_type + content_body = request.body params = None if request.query is not None: if isinstance(request.query, BaseModel): @@ -726,9 +877,15 @@ def _do(self, request: _ApiRequest) -> httpx.Response: else: params = request.query response = self._http_client.request( - request.method, path, json=json_body, params=params - ) - if response.status_code != request.success_code: + request.method, + path, + json=json_body, + content=content_body, + files=files_body, + params=params, + headers=headers, + ) + if response.status_code not in request.success_codes: if request.error_codes and response.status_code in request.error_codes: error_name = request.error_codes[response.status_code] if error_name in _ERROR_TYPES: @@ -783,7 +940,7 @@ async def async_predict( path_args=[env_name], body=request, query=None, - success_code=201, + success_codes=[201], error_codes={ 400: "ErrorResponse", 401: "ErrorResponse", @@ -806,7 +963,7 @@ async def async_predict_deployment( path_args=[deployment_id], body=request, query=None, - success_code=201, + success_codes=[201], error_codes={ 400: "ErrorResponse", 401: "ErrorResponse", @@ -829,7 +986,7 @@ async def async_predict_development( path_args=[], body=request, query=None, - success_code=201, + success_codes=[201], error_codes={ 400: "ErrorResponse", 401: "ErrorResponse", @@ -852,7 +1009,7 @@ async def async_predict_production( path_args=[], body=request, query=None, - success_code=201, + success_codes=[201], error_codes={ 400: "ErrorResponse", 401: "ErrorResponse", @@ -875,7 +1032,7 @@ async def async_predict_regional( path_args=[], body=request, query=None, - success_code=201, + success_codes=[201], error_codes={ 400: "ErrorResponse", 401: "ErrorResponse", @@ -898,7 +1055,7 @@ async def async_run_remote( path_args=[env_name], body=request, query=None, - success_code=201, + success_codes=[201], error_codes={ 400: "ErrorResponse", 401: "ErrorResponse", @@ -920,7 +1077,7 @@ async def async_run_remote_deployment( path_args=[deployment_id], body=request, query=None, - success_code=201, + success_codes=[201], error_codes={ 400: "ErrorResponse", 401: "ErrorResponse", @@ -942,7 +1099,7 @@ async def async_run_remote_development( path_args=[], body=request, query=None, - success_code=201, + success_codes=[201], error_codes={ 400: "ErrorResponse", 401: "ErrorResponse", @@ -964,7 +1121,7 @@ async def async_run_remote_production( path_args=[], body=request, query=None, - success_code=201, + success_codes=[201], error_codes={ 400: "ErrorResponse", 401: "ErrorResponse", @@ -986,7 +1143,7 @@ async def async_run_remote_regional( path_args=[], body=request, query=None, - success_code=201, + success_codes=[201], error_codes={ 400: "ErrorResponse", 401: "ErrorResponse", @@ -1008,7 +1165,7 @@ async def cancel_async_request( path_args=[request_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes={401: "ErrorResponse", 429: "ErrorResponse"}, ), ) @@ -1025,7 +1182,7 @@ async def get_async_queue_status( path_args=[env_name], body=None, query=None, - success_code=200, + success_codes=[200], error_codes={401: "ErrorResponse", 429: "ErrorResponse"}, ), ) @@ -1042,7 +1199,7 @@ async def get_async_queue_status_deployment( path_args=[deployment_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes={401: "ErrorResponse", 429: "ErrorResponse"}, ), ) @@ -1057,7 +1214,7 @@ async def get_async_queue_status_development(self) -> GetAsyncQueueStatusOutput: path_args=[], body=None, query=None, - success_code=200, + success_codes=[200], error_codes={401: "ErrorResponse", 429: "ErrorResponse"}, ), ) @@ -1072,7 +1229,7 @@ async def get_async_queue_status_production(self) -> GetAsyncQueueStatusOutput: path_args=[], body=None, query=None, - success_code=200, + success_codes=[200], error_codes={401: "ErrorResponse", 429: "ErrorResponse"}, ), ) @@ -1087,7 +1244,7 @@ async def get_async_queue_status_regional(self) -> GetAsyncQueueStatusOutput: path_args=[], body=None, query=None, - success_code=200, + success_codes=[200], error_codes={401: "ErrorResponse", 429: "ErrorResponse"}, ), ) @@ -1104,7 +1261,7 @@ async def get_async_request_status( path_args=[request_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes={401: "ErrorResponse", 429: "ErrorResponse"}, ), ) @@ -1119,7 +1276,7 @@ async def predict(self, *, env_name: str, request: PredictInput) -> PredictOutpu path_args=[env_name], body=request, query=None, - success_code=200, + success_codes=[200], error_codes={ 400: "ErrorResponse", 401: "ErrorResponse", @@ -1131,6 +1288,34 @@ async def predict(self, *, env_name: str, request: PredictInput) -> PredictOutpu ), ) + async def predict_raw( + self, + *, + env_name: str, + request: PredictInput, + accept: Literal["application/json", "application/octet-stream"], + ) -> httpx.Response: + """Call the model deployment associated with a specified environment.. Returns the response unread, in the requested content type.""" + return await self._do( + _ApiRequest( + method="POST", + path_fmt="/environments/{}/predict", + path_args=[env_name], + body=request, + query=None, + success_codes=[200], + error_codes={ + 400: "ErrorResponse", + 401: "ErrorResponse", + 429: "ErrorResponse", + 502: "ErrorResponse", + 503: "ErrorResponse", + 504: "ErrorResponse", + }, + accept=accept, + ) + ) + async def predict_deployment( self, *, deployment_id: str, request: PredictInput ) -> PredictOutput: @@ -1143,7 +1328,7 @@ async def predict_deployment( path_args=[deployment_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes={ 400: "ErrorResponse", 401: "ErrorResponse", @@ -1155,6 +1340,34 @@ async def predict_deployment( ), ) + async def predict_deployment_raw( + self, + *, + deployment_id: str, + request: PredictInput, + accept: Literal["application/json", "application/octet-stream"], + ) -> httpx.Response: + """Call a specific deployment of a model by deployment ID.. Returns the response unread, in the requested content type.""" + return await self._do( + _ApiRequest( + method="POST", + path_fmt="/deployment/{}/predict", + path_args=[deployment_id], + body=request, + query=None, + success_codes=[200], + error_codes={ + 400: "ErrorResponse", + 401: "ErrorResponse", + 429: "ErrorResponse", + 502: "ErrorResponse", + 503: "ErrorResponse", + 504: "ErrorResponse", + }, + accept=accept, + ) + ) + async def predict_development(self, *, request: PredictInput) -> PredictOutput: """Call the development deployment of a model.""" return await self._do_json( @@ -1165,7 +1378,7 @@ async def predict_development(self, *, request: PredictInput) -> PredictOutput: path_args=[], body=request, query=None, - success_code=200, + success_codes=[200], error_codes={ 400: "ErrorResponse", 401: "ErrorResponse", @@ -1177,6 +1390,33 @@ async def predict_development(self, *, request: PredictInput) -> PredictOutput: ), ) + async def predict_development_raw( + self, + *, + request: PredictInput, + accept: Literal["application/json", "application/octet-stream"], + ) -> httpx.Response: + """Call the development deployment of a model.. Returns the response unread, in the requested content type.""" + return await self._do( + _ApiRequest( + method="POST", + path_fmt="/development/predict", + path_args=[], + body=request, + query=None, + success_codes=[200], + error_codes={ + 400: "ErrorResponse", + 401: "ErrorResponse", + 429: "ErrorResponse", + 502: "ErrorResponse", + 503: "ErrorResponse", + 504: "ErrorResponse", + }, + accept=accept, + ) + ) + async def predict_production(self, *, request: PredictInput) -> PredictOutput: """Call the production environment of a model.""" return await self._do_json( @@ -1187,7 +1427,7 @@ async def predict_production(self, *, request: PredictInput) -> PredictOutput: path_args=[], body=request, query=None, - success_code=200, + success_codes=[200], error_codes={ 400: "ErrorResponse", 401: "ErrorResponse", @@ -1199,6 +1439,33 @@ async def predict_production(self, *, request: PredictInput) -> PredictOutput: ), ) + async def predict_production_raw( + self, + *, + request: PredictInput, + accept: Literal["application/json", "application/octet-stream"], + ) -> httpx.Response: + """Call the production environment of a model.. Returns the response unread, in the requested content type.""" + return await self._do( + _ApiRequest( + method="POST", + path_fmt="/production/predict", + path_args=[], + body=request, + query=None, + success_codes=[200], + error_codes={ + 400: "ErrorResponse", + 401: "ErrorResponse", + 429: "ErrorResponse", + 502: "ErrorResponse", + 503: "ErrorResponse", + 504: "ErrorResponse", + }, + accept=accept, + ) + ) + async def predict_regional(self, *, request: PredictInput) -> PredictOutput: """Call a regional environment of a model.""" return await self._do_json( @@ -1209,7 +1476,7 @@ async def predict_regional(self, *, request: PredictInput) -> PredictOutput: path_args=[], body=request, query=None, - success_code=200, + success_codes=[200], error_codes={ 400: "ErrorResponse", 401: "ErrorResponse", @@ -1221,6 +1488,33 @@ async def predict_regional(self, *, request: PredictInput) -> PredictOutput: ), ) + async def predict_regional_raw( + self, + *, + request: PredictInput, + accept: Literal["application/json", "application/octet-stream"], + ) -> httpx.Response: + """Call a regional environment of a model.. Returns the response unread, in the requested content type.""" + return await self._do( + _ApiRequest( + method="POST", + path_fmt="/predict", + path_args=[], + body=request, + query=None, + success_codes=[200], + error_codes={ + 400: "ErrorResponse", + 401: "ErrorResponse", + 429: "ErrorResponse", + 502: "ErrorResponse", + 503: "ErrorResponse", + 504: "ErrorResponse", + }, + accept=accept, + ) + ) + async def run_remote( self, *, env_name: str, request: RunRemoteInput ) -> RunRemoteOutput: @@ -1233,7 +1527,7 @@ async def run_remote( path_args=[env_name], body=request, query=None, - success_code=200, + success_codes=[200], error_codes={ 400: "ErrorResponse", 401: "ErrorResponse", @@ -1257,7 +1551,7 @@ async def run_remote_deployment( path_args=[deployment_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes={ 400: "ErrorResponse", 401: "ErrorResponse", @@ -1281,7 +1575,7 @@ async def run_remote_development( path_args=[], body=request, query=None, - success_code=200, + success_codes=[200], error_codes={ 400: "ErrorResponse", 401: "ErrorResponse", @@ -1305,7 +1599,7 @@ async def run_remote_production( path_args=[], body=request, query=None, - success_code=200, + success_codes=[200], error_codes={ 400: "ErrorResponse", 401: "ErrorResponse", @@ -1327,7 +1621,7 @@ async def run_remote_regional(self, *, request: RunRemoteInput) -> RunRemoteOutp path_args=[], body=request, query=None, - success_code=200, + success_codes=[200], error_codes={ 400: "ErrorResponse", 401: "ErrorResponse", @@ -1348,7 +1642,7 @@ async def wake(self, *, env_name: str) -> None: path_args=[env_name], body=None, query=None, - success_code=202, + success_codes=[202], error_codes={401: "ErrorResponse"}, ) ) @@ -1362,7 +1656,7 @@ async def wake_deployment(self, *, deployment_id: str) -> None: path_args=[deployment_id], body=None, query=None, - success_code=202, + success_codes=[202], error_codes={401: "ErrorResponse"}, ) ) @@ -1376,7 +1670,7 @@ async def wake_development(self) -> None: path_args=[], body=None, query=None, - success_code=202, + success_codes=[202], error_codes={401: "ErrorResponse"}, ) ) @@ -1390,7 +1684,7 @@ async def wake_production(self) -> None: path_args=[], body=None, query=None, - success_code=202, + success_codes=[202], error_codes={401: "ErrorResponse"}, ) ) @@ -1404,7 +1698,7 @@ async def wake_regional(self) -> None: path_args=[], body=None, query=None, - success_code=202, + success_codes=[202], error_codes={401: "ErrorResponse"}, ) ) @@ -1414,14 +1708,26 @@ async def _do(self, request: _ApiRequest) -> httpx.Response: *[urllib.parse.quote(a, safe="") for a in request.path_args] ) json_body = None + content_body = None + files_body = None + headers: dict[str, str] = {} + if request.accept is not None: + headers["Accept"] = request.accept if request.body is not None: - if isinstance(request.body, BaseModel): - # Only fields the caller set are sent, so unset fields fall - # back to the server default rather than being reset here. - # An explicit None is kept, since null can mean "clear". - json_body = request.body.model_dump(mode="json", exclude_unset=True) + if request.body_content_type is None: + if isinstance(request.body, BaseModel): + # Only fields the caller set are sent, so unset fields fall + # back to the server default rather than being reset here. + # An explicit None is kept, since null can mean "clear". + json_body = request.body.model_dump(mode="json", exclude_unset=True) + else: + json_body = request.body + elif request.body_content_type == "multipart/form-data": + # httpx derives the multipart Content-Type, boundary included. + files_body = request.body else: - json_body = request.body + headers["Content-Type"] = request.body_content_type + content_body = request.body params = None if request.query is not None: if isinstance(request.query, BaseModel): @@ -1433,9 +1739,15 @@ async def _do(self, request: _ApiRequest) -> httpx.Response: else: params = request.query response = await self._http_client.request( - request.method, path, json=json_body, params=params - ) - if response.status_code != request.success_code: + request.method, + path, + json=json_body, + content=content_body, + files=files_body, + params=params, + headers=headers, + ) + if response.status_code not in request.success_codes: if request.error_codes and response.status_code in request.error_codes: error_name = request.error_codes[response.status_code] if error_name in _ERROR_TYPES: diff --git a/baseten/client/managementapi/__init__.py b/baseten/client/managementapi/__init__.py index 9f12cc8..f794eb8 100644 --- a/baseten/client/managementapi/__init__.py +++ b/baseten/client/managementapi/__init__.py @@ -12,6 +12,7 @@ from ._client import ApiClient, AsyncApiClient, ResponseError from ._models import ( + Action, ActivateResponse, ActiveJobAtSubmit, APIKey, @@ -59,6 +60,10 @@ AuditLogEventModelDeploymentRequestBackpressureSettingsChanged, AuditLogEventModelDeploymentRetried, AuditLogEventModelPromotionControlAction, + AuditLogEventModelRenamed, + AuditLogEventProviderConnectionCreated, + AuditLogEventProviderConnectionDeleted, + AuditLogEventProviderConnectionUpdated, AuditLogEventReplicaTerminated, AuditLogEventRequireGroupBasedAdminsEnabled, AuditLogEventSecretDeleted, @@ -82,6 +87,7 @@ AuditLogSource, AuthCode, AuthMethod, + AuthSecretName, AutoscalingSchedule, AutoscalingScheduleSettings, AutoscalingScheduleSettingsRequest, @@ -119,6 +125,7 @@ CheckpointFile, Checkpoints, CheckpointSyncStatus, + CleanupImagesResponse, Component, ComputeCost, ComputeCost1, @@ -148,6 +155,9 @@ CreateLoopsSessionResponse, CreateModelDeploymentRequest, CreateModelRequest, + CreateRouteRequest, + CreateSandboxRequest, + CreateTokenRequest, CreateTrainingJob, CreateTrainingJobAccelerator, CreateTrainingJobCacheConfig, @@ -158,6 +168,7 @@ CreateTrainingJobResponse, CreateTrainingJobRuntime, CreateTrainingJobS3Artifact, + CreateVolumeSyncRequest, CreateVolumeTokenRequest, CreateVolumeTokenResponse, CreditsUsed, @@ -190,6 +201,10 @@ Deployments, DeploymentStatus, DeploymentTombstone, + Description, + Description1, + DisplayName, + DisplayName1, DockerAuth, DockerAuthType, DownloadDeploymentResponse, @@ -198,6 +213,7 @@ EffectiveRateLimit, EffectiveUsageLimit, EmbeddingBenchmarkMetrics, + EnablementDetails, Endpoint, EndpointsResponse, EndpointTarget, @@ -211,6 +227,11 @@ EnvironmentGroupUser, Environments, EnvironmentTombstone, + ExploreCost, + ExploreCostValues, + ExploreMetadata, + ExploreMetadataAPIFormats, + ExploreMetadataResponse, FileSummary, GatewayEvent, GatewayEventsResponse, @@ -219,48 +240,54 @@ GatewayProvider, GcpOidcDockerAuth, GcpServiceAccountJsonDockerAuth, - GetAuditLogsRequest, + GetApiKeysParams, + GetAuditLogsParams, GetAuthCodesResponse, - GetBillingModelApisRequest, - GetBillingUsageSummaryRequest, + GetBillingModelApisParams, + GetBillingToolCallUsageParams, + GetBillingUsageSummaryParams, GetBlobCredentialsResponse, GetCacheSummaryResponse, - GetChainsAuditLogsRequest, - GetChainsDeploymentsChainletsLogsRequest, + GetChainsAuditLogsParams, + GetChainsDeploymentsChainletsLogsParams, GetDeploymentLogsRequest, GetDeploymentPatchesStateResponse, - GetGatewayEventsRequest, + GetExploreMetadataParams, + GetGatewayEventsParams, GetLogsResponse, + GetLoopsCapabilitiesParams, GetLoopsCapabilitiesResponse, - GetLoopsCheckpointsFilesRequest, - GetLoopsCheckpointsRequest, + GetLoopsCheckpointsFilesParams, + GetLoopsCheckpointsParams, GetLoopsDeploymentMetricsRequest, GetLoopsDeploymentMetricsResponse, GetLoopsDeploymentResponse, - GetLoopsDeploymentsDebugArchiveFilesRequest, - GetLoopsDeploymentsLogsRequest, - GetLoopsDeploymentsRequest, + GetLoopsDeploymentsDebugArchiveFilesParams, + GetLoopsDeploymentsLogsParams, + GetLoopsDeploymentsParams, GetLoopsRunResponse, - GetLoopsRunsRequest, + GetLoopsRunsParams, GetLoopsSamplerResponse, - GetLoopsSamplersRequest, + GetLoopsSamplersParams, GetLoopsSessionResponse, GetLoopsUserConfigResponse, - GetModelApisRequest, - GetModelApisUsageRequest, + GetModelApisParams, + GetModelApisUsageParams, GetModelMetricsResponse, - GetModelsAuditLogsRequest, - GetModelsDeploymentsConfigRequest, - GetModelsDeploymentsLogsRequest, - GetModelsDeploymentsMetricsRequest, - GetModelsDeploymentsRequest, - GetModelsEnvironmentsLogsRequest, - GetModelsEnvironmentsMetricsRequest, - GetModelsRequest, - GetTeamsLoopsRunsRequest, - GetTeamsLoopsSamplersRequest, - GetTeamsModelsRequest, - GetTeamsRequest, + GetModelsAuditLogsParams, + GetModelsDeploymentsConfigParams, + GetModelsDeploymentsLogsParams, + GetModelsDeploymentsMetricsParams, + GetModelsDeploymentsParams, + GetModelsEnvironmentsLogsParams, + GetModelsEnvironmentsMetricsParams, + GetModelsParams, + GetRoutesParams, + GetRoutesUsageParams, + GetTeamsLoopsRunsParams, + GetTeamsLoopsSamplersParams, + GetTeamsModelsParams, + GetTeamsParams, GetTrainingGpuCapacityResponse, GetTrainingJobCheckpointFilesResponse, GetTrainingJobCheckpointsResponse, @@ -270,18 +297,22 @@ GetTrainingJobQueueContextResponse, GetTrainingJobResponse, GetTrainingProjectResponse, - GetTrainingProjectsJobsCheckpointFilesRequest, - GetTrainingProjectsJobsLogsRequest, - GetTrainingProjectsJobsMetricsRequest, - GetUsersRequest, - GetVolumesNamespacesRequest, - GetVolumesRequest, - GetVolumesVersionsRequest, + GetTrainingProjectsJobsCheckpointFilesParams, + GetTrainingProjectsJobsLogsParams, + GetTrainingProjectsJobsMetricsParams, + GetUsersParams, + GetVolumesNamespacesParams, + GetVolumesParams, + GetVolumesSyncsParams, + GetVolumesVersionsParams, GitInfo, Group, GroupHierarchy, GroupMetadata, GroupsResponse, + Image, + ImageStatus, + ImageTag, InferenceVolumeByStatusDatapoint, InProgressPromotion, InProgressPromotionStatus, @@ -307,10 +338,16 @@ LimitEnforcement, LimitType, ListAuditLogsResponse, + ListImagesParams, + ListImagesResponse, + ListImageTagsParams, + ListImageTagsResponse, ListLoopsCheckpointsResponse, ListLoopsDeploymentsResponse, ListLoopsRunsResponse, ListLoopsSamplersResponse, + ListSandboxesParams, + ListSandboxesResponse, ListTrainingJobsResponse, ListTrainingProjectsResponse, ListVolumeNamespacesResponse, @@ -324,6 +361,9 @@ LoopsCheckpoint, LoopsCheckpointConfig, LoopsCheckpointFilesResponse, + LoopsCheckpointS3Source, + LoopsCheckpointSourceResponse, + LoopsCheckpointVolumeSource, LoopsDebugArchiveFilesResponse, LoopsDeployment, LoopsDeploymentMetrics, @@ -335,9 +375,11 @@ LoopsSampler, LoopsSamplerStatus, LoopsSession, + LoopsUseCase, LoopsUserConfig, MaxScaleDownRate, MaxScaleDownRate1, + MaxSeqLen, Model, ModelAPI, ModelApiCostDimension, @@ -364,6 +406,7 @@ Name1, Name2, Name3, + Name4, OneTimeAutoscalingSchedule, OneTimeAutoscalingScheduleUpsert, OrderBy, @@ -384,6 +427,9 @@ PromoteToEnvironmentRequest, PromotionCleanupStrategy, PromotionSettings, + Protocol, + PushImageRequest, + PushImageResponse, QueueEvent, RateLimit, RateLimitUnit, @@ -404,6 +450,35 @@ RetryDeploymentResponse, RollingDeployConfig, RollingDeployStrategy, + Route, + RouteProvider, + RoutesResponse, + RoutesUsageBucket, + RoutesUsageResponse, + RoutesUsageResult, + RouteTargetAnthropic, + RouteTargetBasetenModelAPI, + RouteTargetOpenAI, + RouteTargetXAI, + RouteTombstone, + RouteUsageDimension, + Sandbox, + SandboxApiPagination, + SandboxConfiguration, + SandboxDateExpirationPolicy, + SandboxDuration, + SandboxEnv, + SandboxExpirationPolicy, + SandboxLifecycle, + SandboxMetadataLabels, + SandboxNetwork, + SandboxPort, + SandboxPorts, + SandboxProxyConfig, + SandboxProxyTarget, + SandboxStatus, + SandboxTTLIdleExpirationPolicy, + SandboxTTLMaxAgeExpirationPolicy, Schedules, Schedules1, SearchPattern, @@ -418,6 +493,8 @@ SignSSHCertificateRequest, SignSSHCertificateResponse, SortOrder, + State, + StatusItem, StopTrainingJobRequest, StopTrainingJobResponse, StorageMetrics, @@ -437,9 +514,14 @@ Targets, Team, TeamId, + TeamId1, Teams, TeamTrainingGpuCapacityItem, TerminateReplicaResponse, + Token, + TokenScope, + ToolCallUsageBucket, + ToolCallUsageResponse, Total, TrainerCheckpointTarget, TrainingGpuCapacityItem, @@ -457,6 +539,9 @@ TrainingWeightAuth, TrussUserEnv, TTSBenchmarkMetrics, + Type, + Type1, + Type2, UpdateAutoscalingScheduleSettings, UpdateAutoscalingSettings, UpdateAutoscalingSettingsResponse, @@ -476,9 +561,12 @@ UpdateGroupRequest, UpdateLibraryListingRequest, UpdateLibraryListingVersionRequest, + UpdateModelRequest, UpdatePromotionSettings, UpdateRequestBackpressureSettings, UpdateRollingDeployConfig, + UpdateRouteRequest, + UpdateSandboxRequest, UpdateTrainingJobRequest, UpdateTrainingJobResponse, UpsertSecretRequest, @@ -500,6 +588,21 @@ ValidateLoopsCheckpointResponse, VertexTargetConfig, Volume, + VolumeSync, + VolumeSyncAuthenticationAWSAssumeRole, + VolumeSyncAuthenticationAWSOIDC, + VolumeSyncAuthenticationGCPOIDC, + VolumeSyncDestination, + VolumeSyncError, + VolumeSyncs, + VolumeSyncSourceAzure, + VolumeSyncSourceBasetenTraining, + VolumeSyncSourceCoreWeave, + VolumeSyncSourceGCS, + VolumeSyncSourceHuggingFace, + VolumeSyncSourceR2, + VolumeSyncSourceS3, + VolumeSyncStatus, VolumeTag, VolumeTokenScope, VolumeVersion, @@ -515,6 +618,7 @@ "APIKeyTombstone", "APIKeys", "AWSCredentials", + "Action", "ActivateResponse", "ActiveJobAtSubmit", "ApiClient", @@ -558,6 +662,10 @@ "AuditLogEventModelDeploymentRequestBackpressureSettingsChanged", "AuditLogEventModelDeploymentRetried", "AuditLogEventModelPromotionControlAction", + "AuditLogEventModelRenamed", + "AuditLogEventProviderConnectionCreated", + "AuditLogEventProviderConnectionDeleted", + "AuditLogEventProviderConnectionUpdated", "AuditLogEventReplicaTerminated", "AuditLogEventRequireGroupBasedAdminsEnabled", "AuditLogEventSecretDeleted", @@ -581,6 +689,7 @@ "AuditLogSource", "AuthCode", "AuthMethod", + "AuthSecretName", "AutoscalingSchedule", "AutoscalingScheduleSettings", "AutoscalingScheduleSettingsRequest", @@ -617,6 +726,7 @@ "CheckpointFile", "CheckpointSyncStatus", "Checkpoints", + "CleanupImagesResponse", "Component", "ComputeCost", "ComputeCost1", @@ -645,6 +755,9 @@ "CreateLoopsSessionResponse", "CreateModelDeploymentRequest", "CreateModelRequest", + "CreateRouteRequest", + "CreateSandboxRequest", + "CreateTokenRequest", "CreateTrainingJob", "CreateTrainingJobAccelerator", "CreateTrainingJobCacheConfig", @@ -655,6 +768,7 @@ "CreateTrainingJobResponse", "CreateTrainingJobRuntime", "CreateTrainingJobS3Artifact", + "CreateVolumeSyncRequest", "CreateVolumeTokenRequest", "CreateVolumeTokenResponse", "CreatedModelDeployment", @@ -688,6 +802,10 @@ "DeploymentStatus", "DeploymentTombstone", "Deployments", + "Description", + "Description1", + "DisplayName", + "DisplayName1", "DockerAuth", "DockerAuthType", "DownloadDeploymentResponse", @@ -696,6 +814,7 @@ "EffectiveRateLimit", "EffectiveUsageLimit", "EmbeddingBenchmarkMetrics", + "EnablementDetails", "Endpoint", "EndpointTarget", "EndpointTargetRequest", @@ -709,6 +828,11 @@ "EnvironmentGroups", "EnvironmentTombstone", "Environments", + "ExploreCost", + "ExploreCostValues", + "ExploreMetadata", + "ExploreMetadataAPIFormats", + "ExploreMetadataResponse", "FileSummary", "GatewayEvent", "GatewayEventTokens", @@ -717,48 +841,54 @@ "GatewayProvider", "GcpOidcDockerAuth", "GcpServiceAccountJsonDockerAuth", - "GetAuditLogsRequest", + "GetApiKeysParams", + "GetAuditLogsParams", "GetAuthCodesResponse", - "GetBillingModelApisRequest", - "GetBillingUsageSummaryRequest", + "GetBillingModelApisParams", + "GetBillingToolCallUsageParams", + "GetBillingUsageSummaryParams", "GetBlobCredentialsResponse", "GetCacheSummaryResponse", - "GetChainsAuditLogsRequest", - "GetChainsDeploymentsChainletsLogsRequest", + "GetChainsAuditLogsParams", + "GetChainsDeploymentsChainletsLogsParams", "GetDeploymentLogsRequest", "GetDeploymentPatchesStateResponse", - "GetGatewayEventsRequest", + "GetExploreMetadataParams", + "GetGatewayEventsParams", "GetLogsResponse", + "GetLoopsCapabilitiesParams", "GetLoopsCapabilitiesResponse", - "GetLoopsCheckpointsFilesRequest", - "GetLoopsCheckpointsRequest", + "GetLoopsCheckpointsFilesParams", + "GetLoopsCheckpointsParams", "GetLoopsDeploymentMetricsRequest", "GetLoopsDeploymentMetricsResponse", "GetLoopsDeploymentResponse", - "GetLoopsDeploymentsDebugArchiveFilesRequest", - "GetLoopsDeploymentsLogsRequest", - "GetLoopsDeploymentsRequest", + "GetLoopsDeploymentsDebugArchiveFilesParams", + "GetLoopsDeploymentsLogsParams", + "GetLoopsDeploymentsParams", "GetLoopsRunResponse", - "GetLoopsRunsRequest", + "GetLoopsRunsParams", "GetLoopsSamplerResponse", - "GetLoopsSamplersRequest", + "GetLoopsSamplersParams", "GetLoopsSessionResponse", "GetLoopsUserConfigResponse", - "GetModelApisRequest", - "GetModelApisUsageRequest", + "GetModelApisParams", + "GetModelApisUsageParams", "GetModelMetricsResponse", - "GetModelsAuditLogsRequest", - "GetModelsDeploymentsConfigRequest", - "GetModelsDeploymentsLogsRequest", - "GetModelsDeploymentsMetricsRequest", - "GetModelsDeploymentsRequest", - "GetModelsEnvironmentsLogsRequest", - "GetModelsEnvironmentsMetricsRequest", - "GetModelsRequest", - "GetTeamsLoopsRunsRequest", - "GetTeamsLoopsSamplersRequest", - "GetTeamsModelsRequest", - "GetTeamsRequest", + "GetModelsAuditLogsParams", + "GetModelsDeploymentsConfigParams", + "GetModelsDeploymentsLogsParams", + "GetModelsDeploymentsMetricsParams", + "GetModelsDeploymentsParams", + "GetModelsEnvironmentsLogsParams", + "GetModelsEnvironmentsMetricsParams", + "GetModelsParams", + "GetRoutesParams", + "GetRoutesUsageParams", + "GetTeamsLoopsRunsParams", + "GetTeamsLoopsSamplersParams", + "GetTeamsModelsParams", + "GetTeamsParams", "GetTrainingGpuCapacityResponse", "GetTrainingJobCheckpointFilesResponse", "GetTrainingJobCheckpointsResponse", @@ -768,18 +898,22 @@ "GetTrainingJobQueueContextResponse", "GetTrainingJobResponse", "GetTrainingProjectResponse", - "GetTrainingProjectsJobsCheckpointFilesRequest", - "GetTrainingProjectsJobsLogsRequest", - "GetTrainingProjectsJobsMetricsRequest", - "GetUsersRequest", - "GetVolumesNamespacesRequest", - "GetVolumesRequest", - "GetVolumesVersionsRequest", + "GetTrainingProjectsJobsCheckpointFilesParams", + "GetTrainingProjectsJobsLogsParams", + "GetTrainingProjectsJobsMetricsParams", + "GetUsersParams", + "GetVolumesNamespacesParams", + "GetVolumesParams", + "GetVolumesSyncsParams", + "GetVolumesVersionsParams", "GitInfo", "Group", "GroupHierarchy", "GroupMetadata", "GroupsResponse", + "Image", + "ImageStatus", + "ImageTag", "InProgressPromotion", "InProgressPromotionStatus", "InferenceVolumeByStatusDatapoint", @@ -807,10 +941,16 @@ "LimitEnforcement", "LimitType", "ListAuditLogsResponse", + "ListImageTagsParams", + "ListImageTagsResponse", + "ListImagesParams", + "ListImagesResponse", "ListLoopsCheckpointsResponse", "ListLoopsDeploymentsResponse", "ListLoopsRunsResponse", "ListLoopsSamplersResponse", + "ListSandboxesParams", + "ListSandboxesResponse", "ListTrainingJobsResponse", "ListTrainingProjectsResponse", "ListVolumeNamespacesResponse", @@ -822,6 +962,9 @@ "LoopsCheckpoint", "LoopsCheckpointConfig", "LoopsCheckpointFilesResponse", + "LoopsCheckpointS3Source", + "LoopsCheckpointSourceResponse", + "LoopsCheckpointVolumeSource", "LoopsDebugArchiveFilesResponse", "LoopsDeployment", "LoopsDeploymentMetrics", @@ -833,9 +976,11 @@ "LoopsSampler", "LoopsSamplerStatus", "LoopsSession", + "LoopsUseCase", "LoopsUserConfig", "MaxScaleDownRate", "MaxScaleDownRate1", + "MaxSeqLen", "Model", "ModelAPI", "ModelAPIOrgDetails", @@ -862,6 +1007,7 @@ "Name1", "Name2", "Name3", + "Name4", "OneTimeAutoscalingSchedule", "OneTimeAutoscalingScheduleUpsert", "OrderBy", @@ -882,6 +1028,9 @@ "PromoteToEnvironmentRequest", "PromotionCleanupStrategy", "PromotionSettings", + "Protocol", + "PushImageRequest", + "PushImageResponse", "QueueEvent", "RateLimit", "RateLimitUnit", @@ -903,6 +1052,35 @@ "RetryDeploymentResponse", "RollingDeployConfig", "RollingDeployStrategy", + "Route", + "RouteProvider", + "RouteTargetAnthropic", + "RouteTargetBasetenModelAPI", + "RouteTargetOpenAI", + "RouteTargetXAI", + "RouteTombstone", + "RouteUsageDimension", + "RoutesResponse", + "RoutesUsageBucket", + "RoutesUsageResponse", + "RoutesUsageResult", + "Sandbox", + "SandboxApiPagination", + "SandboxConfiguration", + "SandboxDateExpirationPolicy", + "SandboxDuration", + "SandboxEnv", + "SandboxExpirationPolicy", + "SandboxLifecycle", + "SandboxMetadataLabels", + "SandboxNetwork", + "SandboxPort", + "SandboxPorts", + "SandboxProxyConfig", + "SandboxProxyTarget", + "SandboxStatus", + "SandboxTTLIdleExpirationPolicy", + "SandboxTTLMaxAgeExpirationPolicy", "Schedules", "Schedules1", "SearchPattern", @@ -917,6 +1095,8 @@ "SignSSHCertificateResponse", "SignalPromotionResponse", "SortOrder", + "State", + "StatusItem", "StopTrainingJobRequest", "StopTrainingJobResponse", "StorageMetrics", @@ -937,9 +1117,14 @@ "Targets", "Team", "TeamId", + "TeamId1", "TeamTrainingGpuCapacityItem", "Teams", "TerminateReplicaResponse", + "Token", + "TokenScope", + "ToolCallUsageBucket", + "ToolCallUsageResponse", "Total", "TrainerCheckpointTarget", "TrainingGpuCapacityItem", @@ -956,6 +1141,9 @@ "TrainingUsage", "TrainingWeightAuth", "TrussUserEnv", + "Type", + "Type1", + "Type2", "UpdateAutoscalingScheduleSettings", "UpdateAutoscalingSettings", "UpdateAutoscalingSettingsResponse", @@ -975,9 +1163,12 @@ "UpdateGroupRequest", "UpdateLibraryListingRequest", "UpdateLibraryListingVersionRequest", + "UpdateModelRequest", "UpdatePromotionSettings", "UpdateRequestBackpressureSettings", "UpdateRollingDeployConfig", + "UpdateRouteRequest", + "UpdateSandboxRequest", "UpdateTrainingJobRequest", "UpdateTrainingJobResponse", "UpsertSecretRequest", @@ -999,6 +1190,21 @@ "ValidateLoopsCheckpointResponse", "VertexTargetConfig", "Volume", + "VolumeSync", + "VolumeSyncAuthenticationAWSAssumeRole", + "VolumeSyncAuthenticationAWSOIDC", + "VolumeSyncAuthenticationGCPOIDC", + "VolumeSyncDestination", + "VolumeSyncError", + "VolumeSyncSourceAzure", + "VolumeSyncSourceBasetenTraining", + "VolumeSyncSourceCoreWeave", + "VolumeSyncSourceGCS", + "VolumeSyncSourceHuggingFace", + "VolumeSyncSourceR2", + "VolumeSyncSourceS3", + "VolumeSyncStatus", + "VolumeSyncs", "VolumeTag", "VolumeTokenScope", "VolumeVersion", diff --git a/baseten/client/managementapi/_client.py b/baseten/client/managementapi/_client.py index e35ecc3..6d8e021 100644 --- a/baseten/client/managementapi/_client.py +++ b/baseten/client/managementapi/_client.py @@ -22,6 +22,7 @@ ChainEnvironment, Chains, ChainTombstone, + CleanupImagesResponse, CreateApiKeyForGroupRequest, CreateApiKeyForGroupResponse, CreateAPIKeyRequest, @@ -43,8 +44,12 @@ CreateLoopsSessionResponse, CreateModelDeploymentRequest, CreateModelRequest, + CreateRouteRequest, + CreateSandboxRequest, + CreateTokenRequest, CreateTrainingJobRequest, CreateTrainingJobResponse, + CreateVolumeSyncRequest, CreateVolumeTokenRequest, CreateVolumeTokenResponse, DeactivateLoopsDeploymentResponse, @@ -68,50 +73,57 @@ EnvironmentGroups, Environments, EnvironmentTombstone, + ExploreMetadataResponse, GatewayEventsResponse, GatewayKeyInfo, - GetAuditLogsRequest, + GetApiKeysParams, + GetAuditLogsParams, GetAuthCodesResponse, - GetBillingModelApisRequest, - GetBillingUsageSummaryRequest, + GetBillingModelApisParams, + GetBillingToolCallUsageParams, + GetBillingUsageSummaryParams, GetBlobCredentialsResponse, GetCacheSummaryResponse, - GetChainsAuditLogsRequest, - GetChainsDeploymentsChainletsLogsRequest, + GetChainsAuditLogsParams, + GetChainsDeploymentsChainletsLogsParams, GetDeploymentLogsRequest, GetDeploymentPatchesStateResponse, - GetGatewayEventsRequest, + GetExploreMetadataParams, + GetGatewayEventsParams, GetLogsResponse, + GetLoopsCapabilitiesParams, GetLoopsCapabilitiesResponse, - GetLoopsCheckpointsFilesRequest, - GetLoopsCheckpointsRequest, + GetLoopsCheckpointsFilesParams, + GetLoopsCheckpointsParams, GetLoopsDeploymentMetricsRequest, GetLoopsDeploymentMetricsResponse, GetLoopsDeploymentResponse, - GetLoopsDeploymentsDebugArchiveFilesRequest, - GetLoopsDeploymentsLogsRequest, - GetLoopsDeploymentsRequest, + GetLoopsDeploymentsDebugArchiveFilesParams, + GetLoopsDeploymentsLogsParams, + GetLoopsDeploymentsParams, GetLoopsRunResponse, - GetLoopsRunsRequest, + GetLoopsRunsParams, GetLoopsSamplerResponse, - GetLoopsSamplersRequest, + GetLoopsSamplersParams, GetLoopsSessionResponse, GetLoopsUserConfigResponse, - GetModelApisRequest, - GetModelApisUsageRequest, + GetModelApisParams, + GetModelApisUsageParams, GetModelMetricsResponse, - GetModelsAuditLogsRequest, - GetModelsDeploymentsConfigRequest, - GetModelsDeploymentsLogsRequest, - GetModelsDeploymentsMetricsRequest, - GetModelsDeploymentsRequest, - GetModelsEnvironmentsLogsRequest, - GetModelsEnvironmentsMetricsRequest, - GetModelsRequest, - GetTeamsLoopsRunsRequest, - GetTeamsLoopsSamplersRequest, - GetTeamsModelsRequest, - GetTeamsRequest, + GetModelsAuditLogsParams, + GetModelsDeploymentsConfigParams, + GetModelsDeploymentsLogsParams, + GetModelsDeploymentsMetricsParams, + GetModelsDeploymentsParams, + GetModelsEnvironmentsLogsParams, + GetModelsEnvironmentsMetricsParams, + GetModelsParams, + GetRoutesParams, + GetRoutesUsageParams, + GetTeamsLoopsRunsParams, + GetTeamsLoopsSamplersParams, + GetTeamsModelsParams, + GetTeamsParams, GetTrainingGpuCapacityResponse, GetTrainingJobCheckpointFilesResponse, GetTrainingJobCheckpointsResponse, @@ -121,15 +133,17 @@ GetTrainingJobQueueContextResponse, GetTrainingJobResponse, GetTrainingProjectResponse, - GetTrainingProjectsJobsCheckpointFilesRequest, - GetTrainingProjectsJobsLogsRequest, - GetTrainingProjectsJobsMetricsRequest, - GetUsersRequest, - GetVolumesNamespacesRequest, - GetVolumesRequest, - GetVolumesVersionsRequest, + GetTrainingProjectsJobsCheckpointFilesParams, + GetTrainingProjectsJobsLogsParams, + GetTrainingProjectsJobsMetricsParams, + GetUsersParams, + GetVolumesNamespacesParams, + GetVolumesParams, + GetVolumesSyncsParams, + GetVolumesVersionsParams, Group, GroupsResponse, + Image, InstanceTypePrices, InstanceTypes, KeysForGroupResponse, @@ -140,10 +154,16 @@ LibraryListingVersions, LibraryListingVersionTombstone, ListAuditLogsResponse, + ListImagesParams, + ListImagesResponse, + ListImageTagsParams, + ListImageTagsResponse, ListLoopsCheckpointsResponse, ListLoopsDeploymentsResponse, ListLoopsRunsResponse, ListLoopsSamplersResponse, + ListSandboxesParams, + ListSandboxesResponse, ListTrainingJobsResponse, ListTrainingProjectsResponse, ListVolumeNamespacesResponse, @@ -151,6 +171,7 @@ ListVolumeVersionsResponse, LLMModelHandle, LoopsCheckpointFilesResponse, + LoopsCheckpointSourceResponse, LoopsDebugArchiveFilesResponse, Model, ModelAPI, @@ -171,6 +192,8 @@ PromoteRequest, PromoteToChainEnvironmentRequest, PromoteToEnvironmentRequest, + PushImageRequest, + PushImageResponse, RecreateTrainingJobResponse, Regions, RegisterAPIKeyRequest, @@ -179,6 +202,11 @@ RestoreVolumeVersionRequest, RestoreVolumeVersionResponse, RetryDeploymentResponse, + Route, + RoutesResponse, + RoutesUsageResponse, + RouteTombstone, + Sandbox, SearchTrainingJobsRequest, SearchTrainingJobsResponse, Secret, @@ -194,6 +222,8 @@ Team, Teams, TerminateReplicaResponse, + Token, + ToolCallUsageResponse, TrainingJobTombstone, TrainingProjectTombstone, UpdateAutoscalingSettings, @@ -211,7 +241,10 @@ UpdateGroupRequest, UpdateLibraryListingRequest, UpdateLibraryListingVersionRequest, + UpdateModelRequest, UpdateRequestBackpressureSettings, + UpdateRouteRequest, + UpdateSandboxRequest, UpdateTrainingJobRequest, UpdateTrainingJobResponse, UpsertSecretRequest, @@ -223,6 +256,8 @@ ValidateLoopsCheckpointRequest, ValidateLoopsCheckpointResponse, Volume, + VolumeSync, + VolumeSyncs, VolumeVersionDetail, ) @@ -245,8 +280,10 @@ class _ApiRequest: path_args: list[str] body: Any query: Any - success_code: int + success_codes: list[int] error_codes: dict[int, str] | None + body_content_type: str | None = None + accept: str | None = None class ApiClient: @@ -261,6 +298,36 @@ def __init__(self, http_client: httpx.Client) -> None: """Create a new client. The caller is responsible for closing *http_client*.""" self._http_client = http_client + def cleanup_images(self) -> CleanupImagesResponse: + """Clean up unused images""" + return self._do_json( + CleanupImagesResponse, + _ApiRequest( + method="POST", + path_fmt="/v1/sandboxes/cleanup_images", + path_args=[], + body=None, + query=None, + success_codes=[200], + error_codes=None, + ), + ) + + def create_sandbox(self, *, request: CreateSandboxRequest) -> Sandbox: + """Create a sandbox""" + return self._do_json( + Sandbox, + _ApiRequest( + method="POST", + path_fmt="/v1/sandboxes/instances", + path_args=[], + body=request, + query=None, + success_codes=[201], + error_codes=None, + ), + ) + def delete_api_keys(self, *, api_key_prefix: str) -> APIKeyTombstone: """Deletes an API key by prefix""" return self._do_json( @@ -271,7 +338,7 @@ def delete_api_keys(self, *, api_key_prefix: str) -> APIKeyTombstone: path_args=[api_key_prefix], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -286,7 +353,7 @@ def delete_chains(self, *, chain_id: str) -> ChainTombstone: path_args=[chain_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -303,7 +370,7 @@ def delete_chains_deployments( path_args=[chain_id, chain_deployment_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -318,7 +385,37 @@ def delete_gateway_endpoints(self, *, endpoint_id: str) -> EndpointTombstone: path_args=[endpoint_id], body=None, query=None, - success_code=200, + success_codes=[200], + error_codes=None, + ), + ) + + def delete_image(self, *, image_name: str) -> Image: + """Delete a sandbox image""" + return self._do_json( + Image, + _ApiRequest( + method="DELETE", + path_fmt="/v1/sandboxes/images/{}", + path_args=[image_name], + body=None, + query=None, + success_codes=[200], + error_codes=None, + ), + ) + + def delete_image_tag(self, *, image_name: str, tag_name: str) -> Image: + """Delete an image tag""" + return self._do_json( + Image, + _ApiRequest( + method="DELETE", + path_fmt="/v1/sandboxes/images/{}/tags/{}", + path_args=[image_name, tag_name], + body=None, + query=None, + success_codes=[200], error_codes=None, ), ) @@ -335,7 +432,7 @@ def delete_library_listings( path_args=[user_defined_listing_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -352,7 +449,7 @@ def delete_library_listings_versions( path_args=[user_defined_listing_id, version_tag], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -367,7 +464,7 @@ def delete_models(self, *, model_id: str) -> ModelTombstone: path_args=[model_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -384,7 +481,7 @@ def delete_models_deployments( path_args=[model_id, deployment_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -401,7 +498,7 @@ def delete_models_deployments_replicas( path_args=[model_id, deployment_id, replica_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -418,7 +515,37 @@ def delete_models_environments( path_args=[model_id, env_name], body=None, query=None, - success_code=200, + success_codes=[200], + error_codes=None, + ), + ) + + def delete_routes(self, *, route_id: str) -> RouteTombstone: + """Deletes a route""" + return self._do_json( + RouteTombstone, + _ApiRequest( + method="DELETE", + path_fmt="/v1/routes/{}", + path_args=[route_id], + body=None, + query=None, + success_codes=[200], + error_codes=None, + ), + ) + + def delete_sandbox(self, *, sandbox_name: str) -> Sandbox: + """Delete a sandbox""" + return self._do_json( + Sandbox, + _ApiRequest( + method="DELETE", + path_fmt="/v1/sandboxes/instances/{}", + path_args=[sandbox_name], + body=None, + query=None, + success_codes=[202], error_codes=None, ), ) @@ -433,7 +560,7 @@ def delete_secrets(self, *, secret_name: str) -> SecretTombstone: path_args=[secret_name], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -450,7 +577,7 @@ def delete_teams_secrets( path_args=[team_id, secret_name], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -467,7 +594,7 @@ def delete_training_projects( path_args=[training_project_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -484,7 +611,7 @@ def delete_training_projects_jobs( path_args=[training_project_id, training_job_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -501,7 +628,7 @@ def delete_volumes( path_args=[volume_namespace, volume_name], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -523,12 +650,12 @@ def delete_volumes_versions( path_args=[volume_namespace, volume_name, volume_version], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) - def get_api_keys(self) -> APIKeys: + def get_api_keys(self, *, params: GetApiKeysParams | None = None) -> APIKeys: """Lists API keys (metadata only, no plain text keys)""" return self._do_json( APIKeys, @@ -537,14 +664,14 @@ def get_api_keys(self) -> APIKeys: path_fmt="/v1/api_keys", path_args=[], body=None, - query=None, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) def get_audit_logs( - self, *, request: GetAuditLogsRequest | None = None + self, *, params: GetAuditLogsParams | None = None ) -> ListAuditLogsResponse: """Gets the audit log for the workspace""" return self._do_json( @@ -554,14 +681,14 @@ def get_audit_logs( path_fmt="/v1/audit_logs", path_args=[], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) def get_billing_model_apis( - self, *, request: GetBillingModelApisRequest | None = None + self, *, params: GetBillingModelApisParams | None = None ) -> ModelApisCostsResponse: """Gets daily Model APIs costs""" return self._do_json( @@ -571,14 +698,31 @@ def get_billing_model_apis( path_fmt="/v1/billing/model_apis", path_args=[], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], + error_codes=None, + ), + ) + + def get_billing_tool_call_usage( + self, *, params: GetBillingToolCallUsageParams + ) -> ToolCallUsageResponse: + """Gets server-side tool call usage""" + return self._do_json( + ToolCallUsageResponse, + _ApiRequest( + method="GET", + path_fmt="/v1/billing/tool_call_usage", + path_args=[], + body=None, + query=params, + success_codes=[200], error_codes=None, ), ) def get_billing_usage_summary( - self, *, request: GetBillingUsageSummaryRequest + self, *, params: GetBillingUsageSummaryParams ) -> UsageSummary: """Gets billing usage summary for a date range""" return self._do_json( @@ -588,8 +732,8 @@ def get_billing_usage_summary( path_fmt="/v1/billing/usage_summary", path_args=[], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) @@ -604,7 +748,7 @@ def get_blobs_credentials_model(self) -> GetBlobCredentialsResponse: path_args=[], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -619,7 +763,7 @@ def get_blobs_credentials_train(self) -> GetBlobCredentialsResponse: path_args=[], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -634,13 +778,13 @@ def get_chains(self) -> Chains: path_args=[], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) def get_chains_audit_logs( - self, *, chain_id: str, request: GetChainsAuditLogsRequest | None = None + self, *, chain_id: str, params: GetChainsAuditLogsParams | None = None ) -> ListAuditLogsResponse: """Gets the audit log for a chain""" return self._do_json( @@ -650,8 +794,8 @@ def get_chains_audit_logs( path_fmt="/v1/chains/{}/audit_logs", path_args=[chain_id], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) @@ -666,7 +810,7 @@ def get_chains_chain_id(self, *, chain_id: str) -> Chain: path_args=[chain_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -681,7 +825,7 @@ def get_chains_deployments(self, *, chain_id: str) -> ChainDeployments: path_args=[chain_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -698,7 +842,7 @@ def get_chains_deployments_chain_deployment_id( path_args=[chain_id, chain_deployment_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -709,7 +853,7 @@ def get_chains_deployments_chainlets_logs( chain_id: str, chain_deployment_id: str, chainlet_id: str, - request: GetChainsDeploymentsChainletsLogsRequest | None = None, + params: GetChainsDeploymentsChainletsLogsParams | None = None, ) -> GetLogsResponse: """Gets the logs for a chainlet within a chain deployment""" return self._do_json( @@ -719,8 +863,8 @@ def get_chains_deployments_chainlets_logs( path_fmt="/v1/chains/{}/deployments/{}/chainlets/{}/logs", path_args=[chain_id, chain_deployment_id, chainlet_id], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) @@ -735,7 +879,7 @@ def get_chains_environments(self, *, chain_id: str) -> Environments: path_args=[chain_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -752,7 +896,7 @@ def get_chains_environments_env_name( path_args=[chain_id, env_name], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -767,7 +911,7 @@ def get_environment_groups(self) -> EnvironmentGroups: path_args=[], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -782,7 +926,24 @@ def get_environment_groups_env_name(self, *, env_name: str) -> EnvironmentGroup: path_args=[env_name], body=None, query=None, - success_code=200, + success_codes=[200], + error_codes=None, + ), + ) + + def get_explore_metadata( + self, *, params: GetExploreMetadataParams | None = None + ) -> ExploreMetadataResponse: + """Lists model metadata""" + return self._do_json( + ExploreMetadataResponse, + _ApiRequest( + method="GET", + path_fmt="/v1/explore/metadata", + path_args=[], + body=None, + query=params, + success_codes=[200], error_codes=None, ), ) @@ -797,7 +958,7 @@ def get_gateway_endpoints(self) -> EndpointsResponse: path_args=[], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -812,13 +973,13 @@ def get_gateway_endpoints_endpoint_id(self, *, endpoint_id: str) -> Endpoint: path_args=[endpoint_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) def get_gateway_events( - self, *, request: GetGatewayEventsRequest | None = None + self, *, params: GetGatewayEventsParams | None = None ) -> GatewayEventsResponse: """Lists gateway events""" return self._do_json( @@ -828,8 +989,8 @@ def get_gateway_events( path_fmt="/v1/gateway/events", path_args=[], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) @@ -844,7 +1005,7 @@ def get_gateway_groups(self) -> GroupsResponse: path_args=[], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -859,7 +1020,7 @@ def get_gateway_groups_api_keys(self, *, group_id: str) -> KeysForGroupResponse: path_args=[group_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -876,7 +1037,7 @@ def get_gateway_groups_api_keys_api_key_prefix( path_args=[group_id, api_key_prefix], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -891,7 +1052,22 @@ def get_gateway_groups_group_id(self, *, group_id: str) -> Group: path_args=[group_id], body=None, query=None, - success_code=200, + success_codes=[200], + error_codes=None, + ), + ) + + def get_image(self, *, image_name: str) -> Image: + """Get a sandbox image""" + return self._do_json( + Image, + _ApiRequest( + method="GET", + path_fmt="/v1/sandboxes/images/{}", + path_args=[image_name], + body=None, + query=None, + success_codes=[200], error_codes=None, ), ) @@ -906,7 +1082,7 @@ def get_instance_type_prices(self) -> InstanceTypePrices: path_args=[], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -921,7 +1097,7 @@ def get_instance_types(self) -> InstanceTypes: path_args=[], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -936,7 +1112,7 @@ def get_library_listings(self) -> LibraryListings: path_args=[], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -953,7 +1129,7 @@ def get_library_listings_user_defined_listing_id( path_args=[user_defined_listing_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -970,7 +1146,7 @@ def get_library_listings_versions( path_args=[user_defined_listing_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -987,12 +1163,14 @@ def get_library_listings_versions_version_tag( path_args=[user_defined_listing_id, version_tag], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) - def get_loops_capabilities(self) -> GetLoopsCapabilitiesResponse: + def get_loops_capabilities( + self, *, params: GetLoopsCapabilitiesParams | None = None + ) -> GetLoopsCapabilitiesResponse: """Gets Loops server capabilities""" return self._do_json( GetLoopsCapabilitiesResponse, @@ -1001,14 +1179,14 @@ def get_loops_capabilities(self) -> GetLoopsCapabilitiesResponse: path_fmt="/v1/loops/capabilities", path_args=[], body=None, - query=None, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) def get_loops_checkpoints( - self, *, request: GetLoopsCheckpointsRequest | None = None + self, *, params: GetLoopsCheckpointsParams | None = None ) -> ListLoopsCheckpointsResponse: """Lists Loops checkpoints""" return self._do_json( @@ -1018,8 +1196,8 @@ def get_loops_checkpoints( path_fmt="/v1/loops/checkpoints", path_args=[], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) @@ -1028,7 +1206,7 @@ def get_loops_checkpoints_files( self, *, checkpoint_id: str, - request: GetLoopsCheckpointsFilesRequest | None = None, + params: GetLoopsCheckpointsFilesParams | None = None, ) -> LoopsCheckpointFilesResponse: """Gets Loops checkpoint files""" return self._do_json( @@ -1038,14 +1216,31 @@ def get_loops_checkpoints_files( path_fmt="/v1/loops/checkpoints/{}/files", path_args=[checkpoint_id], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], + error_codes=None, + ), + ) + + def get_loops_checkpoints_source( + self, *, checkpoint_id: str + ) -> LoopsCheckpointSourceResponse: + """Gets where a Loops checkpoint's files come from""" + return self._do_json( + LoopsCheckpointSourceResponse, + _ApiRequest( + method="GET", + path_fmt="/v1/loops/checkpoints/{}/source", + path_args=[checkpoint_id], + body=None, + query=None, + success_codes=[200], error_codes=None, ), ) def get_loops_deployments( - self, *, request: GetLoopsDeploymentsRequest | None = None + self, *, params: GetLoopsDeploymentsParams | None = None ) -> ListLoopsDeploymentsResponse: """Lists Loops deployments""" return self._do_json( @@ -1055,8 +1250,8 @@ def get_loops_deployments( path_fmt="/v1/loops/deployments", path_args=[], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) @@ -1065,7 +1260,7 @@ def get_loops_deployments_debug_archive_files( self, *, deployment_id: str, - request: GetLoopsDeploymentsDebugArchiveFilesRequest | None = None, + params: GetLoopsDeploymentsDebugArchiveFilesParams | None = None, ) -> LoopsDebugArchiveFilesResponse: """Gets Loops debug archive files""" return self._do_json( @@ -1075,8 +1270,8 @@ def get_loops_deployments_debug_archive_files( path_fmt="/v1/loops/deployments/{}/debug_archive/files", path_args=[deployment_id], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) @@ -1093,16 +1288,13 @@ def get_loops_deployments_deployment_id( path_args=[deployment_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) def get_loops_deployments_logs( - self, - *, - deployment_id: str, - request: GetLoopsDeploymentsLogsRequest | None = None, + self, *, deployment_id: str, params: GetLoopsDeploymentsLogsParams | None = None ) -> GetLogsResponse: """Gets logs for a Loops trainer deployment""" return self._do_json( @@ -1112,14 +1304,14 @@ def get_loops_deployments_logs( path_fmt="/v1/loops/deployments/{}/logs", path_args=[deployment_id], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) def get_loops_runs( - self, *, request: GetLoopsRunsRequest | None = None + self, *, params: GetLoopsRunsParams | None = None ) -> ListLoopsRunsResponse: """Lists Loops runs""" return self._do_json( @@ -1129,8 +1321,8 @@ def get_loops_runs( path_fmt="/v1/loops/runs", path_args=[], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) @@ -1145,13 +1337,13 @@ def get_loops_runs_run_id(self, *, run_id: str) -> GetLoopsRunResponse: path_args=[run_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) def get_loops_samplers( - self, *, request: GetLoopsSamplersRequest | None = None + self, *, params: GetLoopsSamplersParams | None = None ) -> ListLoopsSamplersResponse: """Lists Loops samplers""" return self._do_json( @@ -1161,8 +1353,8 @@ def get_loops_samplers( path_fmt="/v1/loops/samplers", path_args=[], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) @@ -1179,7 +1371,7 @@ def get_loops_samplers_sampler_id( path_args=[sampler_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -1194,7 +1386,7 @@ def get_loops_sessions(self, *, session_id: str) -> GetLoopsSessionResponse: path_args=[session_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -1209,13 +1401,13 @@ def get_loops_user_config(self) -> GetLoopsUserConfigResponse: path_args=[], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) def get_model_apis( - self, *, request: GetModelApisRequest | None = None + self, *, params: GetModelApisParams | None = None ) -> ModelAPIsResponse: """Lists Model APIs""" return self._do_json( @@ -1225,8 +1417,8 @@ def get_model_apis( path_fmt="/v1/model_apis", path_args=[], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) @@ -1241,13 +1433,13 @@ def get_model_apis_model_api_name(self, *, model_api_name: str) -> ModelAPI: path_args=[model_api_name], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) def get_model_apis_usage( - self, *, request: GetModelApisUsageRequest | None = None + self, *, params: GetModelApisUsageParams | None = None ) -> ModelApisUsageResponse: """Gets Model APIs token usage in time buckets""" return self._do_json( @@ -1257,13 +1449,13 @@ def get_model_apis_usage( path_fmt="/v1/model_apis/usage", path_args=[], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) - def get_models(self, *, request: GetModelsRequest | None = None) -> Models: + def get_models(self, *, params: GetModelsParams | None = None) -> Models: """Gets all models""" return self._do_json( Models, @@ -1272,14 +1464,14 @@ def get_models(self, *, request: GetModelsRequest | None = None) -> Models: path_fmt="/v1/models", path_args=[], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) def get_models_audit_logs( - self, *, model_id: str, request: GetModelsAuditLogsRequest | None = None + self, *, model_id: str, params: GetModelsAuditLogsParams | None = None ) -> ListAuditLogsResponse: """Gets the audit log for a model""" return self._do_json( @@ -1289,14 +1481,14 @@ def get_models_audit_logs( path_fmt="/v1/models/{}/audit_logs", path_args=[model_id], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) def get_models_deployments( - self, *, model_id: str, request: GetModelsDeploymentsRequest | None = None + self, *, model_id: str, params: GetModelsDeploymentsParams | None = None ) -> Deployments: """Gets all deployments of a model""" return self._do_json( @@ -1306,8 +1498,8 @@ def get_models_deployments( path_fmt="/v1/models/{}/deployments", path_args=[model_id], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) @@ -1317,7 +1509,7 @@ def get_models_deployments_config( *, model_id: str, deployment_id: str, - request: GetModelsDeploymentsConfigRequest | None = None, + params: GetModelsDeploymentsConfigParams | None = None, ) -> DeploymentConfigResponse: """Gets a deployment's config""" return self._do_json( @@ -1327,8 +1519,8 @@ def get_models_deployments_config( path_fmt="/v1/models/{}/deployments/{}/config", path_args=[model_id, deployment_id], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) @@ -1345,7 +1537,7 @@ def get_models_deployments_deployment_id( path_args=[model_id, deployment_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -1360,7 +1552,7 @@ def get_models_deployments_development(self, *, model_id: str) -> Deployment: path_args=[model_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -1377,7 +1569,7 @@ def get_models_deployments_download( path_args=[model_id, deployment_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -1387,7 +1579,7 @@ def get_models_deployments_logs( *, model_id: str, deployment_id: str, - request: GetModelsDeploymentsLogsRequest | None = None, + params: GetModelsDeploymentsLogsParams | None = None, ) -> GetLogsResponse: """Gets the logs for a model deployment""" return self._do_json( @@ -1397,8 +1589,8 @@ def get_models_deployments_logs( path_fmt="/v1/models/{}/deployments/{}/logs", path_args=[model_id, deployment_id], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) @@ -1408,7 +1600,7 @@ def get_models_deployments_metrics( *, model_id: str, deployment_id: str, - request: GetModelsDeploymentsMetricsRequest | None = None, + params: GetModelsDeploymentsMetricsParams | None = None, ) -> GetModelMetricsResponse: """Gets the metrics for a model deployment""" return self._do_json( @@ -1418,8 +1610,8 @@ def get_models_deployments_metrics( path_fmt="/v1/models/{}/deployments/{}/metrics", path_args=[model_id, deployment_id], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) @@ -1436,7 +1628,7 @@ def get_models_deployments_patches_state( path_args=[model_id, deployment_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -1451,7 +1643,7 @@ def get_models_deployments_production(self, *, model_id: str) -> Deployment: path_args=[model_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -1466,7 +1658,7 @@ def get_models_environments(self, *, model_id: str) -> Environments: path_args=[model_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -1483,7 +1675,7 @@ def get_models_environments_env_name( path_args=[model_id, env_name], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -1493,7 +1685,7 @@ def get_models_environments_logs( *, model_id: str, env_name: str, - request: GetModelsEnvironmentsLogsRequest | None = None, + params: GetModelsEnvironmentsLogsParams | None = None, ) -> GetLogsResponse: """Gets the logs for a model environment""" return self._do_json( @@ -1503,8 +1695,8 @@ def get_models_environments_logs( path_fmt="/v1/models/{}/environments/{}/logs", path_args=[model_id, env_name], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) @@ -1514,7 +1706,7 @@ def get_models_environments_metrics( *, model_id: str, env_name: str, - request: GetModelsEnvironmentsMetricsRequest | None = None, + params: GetModelsEnvironmentsMetricsParams | None = None, ) -> GetModelMetricsResponse: """Gets the metrics for a model environment.""" return self._do_json( @@ -1524,8 +1716,8 @@ def get_models_environments_metrics( path_fmt="/v1/models/{}/environments/{}/metrics", path_args=[model_id, env_name], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) @@ -1540,7 +1732,7 @@ def get_models_model_id(self, *, model_id: str) -> Model: path_args=[model_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -1555,7 +1747,7 @@ def get_organizations_me(self) -> OrganizationInfo: path_args=[], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -1570,7 +1762,69 @@ def get_regions(self) -> Regions: path_args=[], body=None, query=None, - success_code=200, + success_codes=[200], + error_codes=None, + ), + ) + + def get_routes(self, *, params: GetRoutesParams | None = None) -> RoutesResponse: + """Lists routes""" + return self._do_json( + RoutesResponse, + _ApiRequest( + method="GET", + path_fmt="/v1/routes", + path_args=[], + body=None, + query=params, + success_codes=[200], + error_codes=None, + ), + ) + + def get_routes_route_id(self, *, route_id: str) -> Route: + """Gets a route""" + return self._do_json( + Route, + _ApiRequest( + method="GET", + path_fmt="/v1/routes/{}", + path_args=[route_id], + body=None, + query=None, + success_codes=[200], + error_codes=None, + ), + ) + + def get_routes_usage( + self, *, params: GetRoutesUsageParams | None = None + ) -> RoutesUsageResponse: + """Gets daily route usage and estimated costs""" + return self._do_json( + RoutesUsageResponse, + _ApiRequest( + method="GET", + path_fmt="/v1/routes/usage", + path_args=[], + body=None, + query=params, + success_codes=[200], + error_codes=None, + ), + ) + + def get_sandbox(self, *, sandbox_name: str) -> Sandbox: + """Get a sandbox""" + return self._do_json( + Sandbox, + _ApiRequest( + method="GET", + path_fmt="/v1/sandboxes/instances/{}", + path_args=[sandbox_name], + body=None, + query=None, + success_codes=[200], error_codes=None, ), ) @@ -1585,12 +1839,12 @@ def get_secrets(self) -> Secrets: path_args=[], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) - def get_teams(self, *, request: GetTeamsRequest | None = None) -> Teams: + def get_teams(self, *, params: GetTeamsParams | None = None) -> Teams: """Lists all teams""" return self._do_json( Teams, @@ -1599,8 +1853,8 @@ def get_teams(self, *, request: GetTeamsRequest | None = None) -> Teams: path_fmt="/v1/teams", path_args=[], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) @@ -1615,7 +1869,7 @@ def get_teams_environment_groups(self, *, team_id: str) -> EnvironmentGroups: path_args=[team_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -1632,13 +1886,13 @@ def get_teams_environment_groups_env_name( path_args=[team_id, env_name], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) def get_teams_loops_runs( - self, *, team_id: str, request: GetTeamsLoopsRunsRequest | None = None + self, *, team_id: str, params: GetTeamsLoopsRunsParams | None = None ) -> ListLoopsRunsResponse: """Lists a team's Loops runs""" return self._do_json( @@ -1648,14 +1902,14 @@ def get_teams_loops_runs( path_fmt="/v1/teams/{}/loops/runs", path_args=[team_id], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) def get_teams_loops_samplers( - self, *, team_id: str, request: GetTeamsLoopsSamplersRequest | None = None + self, *, team_id: str, params: GetTeamsLoopsSamplersParams | None = None ) -> ListLoopsSamplersResponse: """Lists a team's Loops samplers""" return self._do_json( @@ -1665,14 +1919,14 @@ def get_teams_loops_samplers( path_fmt="/v1/teams/{}/loops/samplers", path_args=[team_id], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) def get_teams_models( - self, *, team_id: str, request: GetTeamsModelsRequest | None = None + self, *, team_id: str, params: GetTeamsModelsParams | None = None ) -> Models: """Gets all models""" return self._do_json( @@ -1682,8 +1936,8 @@ def get_teams_models( path_fmt="/v1/teams/{}/models", path_args=[team_id], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) @@ -1698,7 +1952,7 @@ def get_teams_regions(self, *, team_id: str) -> Regions: path_args=[team_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -1713,7 +1967,7 @@ def get_teams_secrets(self, *, team_id: str) -> Secrets: path_args=[team_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -1728,7 +1982,7 @@ def get_teams_team_id(self, *, team_id: str) -> Team: path_args=[team_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -1743,7 +1997,7 @@ def get_training_capacity(self) -> GetTrainingGpuCapacityResponse: path_args=[], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -1760,7 +2014,7 @@ def get_training_jobs_queue_context( path_args=[training_job_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -1775,7 +2029,7 @@ def get_training_projects(self) -> ListTrainingProjectsResponse: path_args=[], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -1792,7 +2046,7 @@ def get_training_projects_cache_summary( path_args=[training_project_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -1809,7 +2063,7 @@ def get_training_projects_jobs( path_args=[training_project_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -1826,7 +2080,7 @@ def get_training_projects_jobs_auth_codes( path_args=[training_project_id, training_job_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -1836,7 +2090,7 @@ def get_training_projects_jobs_checkpoint_files( *, training_project_id: str, training_job_id: str, - request: GetTrainingProjectsJobsCheckpointFilesRequest | None = None, + params: GetTrainingProjectsJobsCheckpointFilesParams | None = None, ) -> GetTrainingJobCheckpointFilesResponse: """Gets training job checkpoint files""" return self._do_json( @@ -1846,8 +2100,8 @@ def get_training_projects_jobs_checkpoint_files( path_fmt="/v1/training_projects/{}/jobs/{}/checkpoint_files", path_args=[training_project_id, training_job_id], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) @@ -1864,7 +2118,7 @@ def get_training_projects_jobs_checkpoints( path_args=[training_project_id, training_job_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -1881,7 +2135,7 @@ def get_training_projects_jobs_download( path_args=[training_project_id, training_job_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -1891,7 +2145,7 @@ def get_training_projects_jobs_logs( *, training_project_id: str, training_job_id: str, - request: GetTrainingProjectsJobsLogsRequest | None = None, + params: GetTrainingProjectsJobsLogsParams | None = None, ) -> GetLogsResponse: """Gets the logs for a training job""" return self._do_json( @@ -1901,8 +2155,8 @@ def get_training_projects_jobs_logs( path_fmt="/v1/training_projects/{}/jobs/{}/logs", path_args=[training_project_id, training_job_id], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) @@ -1912,7 +2166,7 @@ def get_training_projects_jobs_metrics( *, training_project_id: str, training_job_id: str, - request: GetTrainingProjectsJobsMetricsRequest | None = None, + params: GetTrainingProjectsJobsMetricsParams | None = None, ) -> GetTrainingJobMetricsResponse: """Gets the metrics for a training job""" return self._do_json( @@ -1922,8 +2176,8 @@ def get_training_projects_jobs_metrics( path_fmt="/v1/training_projects/{}/jobs/{}/metrics", path_args=[training_project_id, training_job_id], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) @@ -1940,7 +2194,7 @@ def get_training_projects_jobs_training_job_id( path_args=[training_project_id, training_job_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -1957,12 +2211,12 @@ def get_training_projects_training_project_id( path_args=[training_project_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) - def get_users(self, *, request: GetUsersRequest | None = None) -> UsersResponse: + def get_users(self, *, params: GetUsersParams | None = None) -> UsersResponse: """Lists users in the workspace""" return self._do_json( UsersResponse, @@ -1971,8 +2225,8 @@ def get_users(self, *, request: GetUsersRequest | None = None) -> UsersResponse: path_fmt="/v1/users", path_args=[], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) @@ -1987,7 +2241,7 @@ def get_users_me(self) -> UserInfo: path_args=[], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -2002,12 +2256,12 @@ def get_users_user_id(self, *, user_id: str) -> UserInfo: path_args=[user_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) - def get_volumes(self, *, request: GetVolumesRequest) -> ListVolumesResponse: + def get_volumes(self, *, params: GetVolumesParams) -> ListVolumesResponse: """Gets the volumes in a namespace""" return self._do_json( ListVolumesResponse, @@ -2016,14 +2270,14 @@ def get_volumes(self, *, request: GetVolumesRequest) -> ListVolumesResponse: path_fmt="/v1/volumes", path_args=[], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) def get_volumes_namespaces( - self, *, request: GetVolumesNamespacesRequest | None = None + self, *, params: GetVolumesNamespacesParams | None = None ) -> ListVolumeNamespacesResponse: """Gets the volume namespaces in your workspace""" return self._do_json( @@ -2033,8 +2287,40 @@ def get_volumes_namespaces( path_fmt="/v1/volumes/namespaces", path_args=[], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], + error_codes=None, + ), + ) + + def get_volumes_syncs( + self, *, params: GetVolumesSyncsParams | None = None + ) -> VolumeSyncs: + """Lists volume syncs""" + return self._do_json( + VolumeSyncs, + _ApiRequest( + method="GET", + path_fmt="/v1/volumes/syncs", + path_args=[], + body=None, + query=params, + success_codes=[200], + error_codes=None, + ), + ) + + def get_volumes_syncs_volume_sync_id(self, *, volume_sync_id: str) -> VolumeSync: + """Gets a volume sync""" + return self._do_json( + VolumeSync, + _ApiRequest( + method="GET", + path_fmt="/v1/volumes/syncs/{}", + path_args=[volume_sync_id], + body=None, + query=None, + success_codes=[200], error_codes=None, ), ) @@ -2044,7 +2330,7 @@ def get_volumes_versions( *, volume_namespace: str, volume_name: str, - request: GetVolumesVersionsRequest | None = None, + params: GetVolumesVersionsParams | None = None, ) -> ListVolumeVersionsResponse: """Gets the versions of a volume""" return self._do_json( @@ -2054,8 +2340,8 @@ def get_volumes_versions( path_fmt="/v1/volumes/{}/{}/versions", path_args=[volume_namespace, volume_name], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) @@ -2072,7 +2358,7 @@ def get_volumes_versions_volume_version( path_args=[volume_namespace, volume_name, volume_version], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -2089,7 +2375,58 @@ def get_volumes_volume_name( path_args=[volume_namespace, volume_name], body=None, query=None, - success_code=200, + success_codes=[200], + error_codes=None, + ), + ) + + def list_image_tags( + self, *, image_name: str, params: ListImageTagsParams | None = None + ) -> ListImageTagsResponse: + """List image tags""" + return self._do_json( + ListImageTagsResponse, + _ApiRequest( + method="GET", + path_fmt="/v1/sandboxes/images/{}/tags", + path_args=[image_name], + body=None, + query=params, + success_codes=[200], + error_codes=None, + ), + ) + + def list_images( + self, *, params: ListImagesParams | None = None + ) -> ListImagesResponse: + """List sandbox images""" + return self._do_json( + ListImagesResponse, + _ApiRequest( + method="GET", + path_fmt="/v1/sandboxes/images", + path_args=[], + body=None, + query=params, + success_codes=[200], + error_codes=None, + ), + ) + + def list_sandboxes( + self, *, params: ListSandboxesParams | None = None + ) -> ListSandboxesResponse: + """List sandboxes""" + return self._do_json( + ListSandboxesResponse, + _ApiRequest( + method="GET", + path_fmt="/v1/sandboxes/instances", + path_args=[], + body=None, + query=params, + success_codes=[200], error_codes=None, ), ) @@ -2106,7 +2443,7 @@ def patch_chains_environments( path_args=[chain_id, env_name], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -2127,7 +2464,7 @@ def patch_chains_environments_chainlet_settings_autoscaling_settings( path_args=[chain_id, env_name], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -2144,7 +2481,7 @@ def patch_environment_groups( path_args=[env_name], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -2161,7 +2498,7 @@ def patch_gateway_endpoints( path_args=[endpoint_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -2178,7 +2515,7 @@ def patch_gateway_groups( path_args=[group_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -2195,7 +2532,7 @@ def patch_library_listings( path_args=[user_defined_listing_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -2216,7 +2553,7 @@ def patch_library_listings_versions( path_args=[user_defined_listing_id, version_tag], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -2233,7 +2570,22 @@ def patch_loops_user_config( path_args=[], body=request, query=None, - success_code=200, + success_codes=[200], + error_codes=None, + ), + ) + + def patch_models(self, *, model_id: str, request: UpdateModelRequest) -> Model: + """Updates a model by ID""" + return self._do_json( + Model, + _ApiRequest( + method="PATCH", + path_fmt="/v1/models/{}", + path_args=[model_id], + body=request, + query=None, + success_codes=[200], error_codes=None, ), ) @@ -2250,7 +2602,7 @@ def patch_models_deployments( path_args=[model_id, deployment_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -2267,7 +2619,7 @@ def patch_models_deployments_autoscaling_settings( path_args=[model_id, deployment_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -2284,7 +2636,7 @@ def patch_models_deployments_development_autoscaling_settings( path_args=[model_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -2301,7 +2653,7 @@ def patch_models_deployments_production_autoscaling_settings( path_args=[model_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -2322,7 +2674,7 @@ def patch_models_deployments_request_backpressure_settings( path_args=[model_id, deployment_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -2339,7 +2691,22 @@ def patch_models_environments( path_args=[model_id, env_name], body=request, query=None, - success_code=200, + success_codes=[200], + error_codes=None, + ), + ) + + def patch_routes(self, *, route_id: str, request: UpdateRouteRequest) -> Route: + """Updates a route's display name or description""" + return self._do_json( + Route, + _ApiRequest( + method="PATCH", + path_fmt="/v1/routes/{}", + path_args=[route_id], + body=request, + query=None, + success_codes=[200], error_codes=None, ), ) @@ -2356,7 +2723,7 @@ def patch_teams_environment_groups( path_args=[team_id, env_name], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -2373,7 +2740,7 @@ def patch_training_capacity( path_args=[], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -2394,7 +2761,7 @@ def patch_training_projects_jobs( path_args=[training_project_id, training_job_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -2416,7 +2783,7 @@ def patch_training_projects_jobs_interactive_sessions( path_args=[training_project_id, training_job_id, session_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -2431,7 +2798,7 @@ def post_api_keys(self, *, request: CreateAPIKeyRequest) -> APIKey: path_args=[], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -2448,7 +2815,7 @@ def post_chains_deployments_deactivate( path_args=[chain_id, chain_deployment_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -2465,7 +2832,7 @@ def post_chains_environments( path_args=[chain_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -2486,7 +2853,7 @@ def post_chains_environments_chainlet_settings_instance_types_update( path_args=[chain_id, env_name], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -2503,7 +2870,7 @@ def post_chains_environments_promote( path_args=[chain_id, env_name], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -2518,7 +2885,7 @@ def post_gateway_endpoints(self, *, request: CreateEndpointRequest) -> Endpoint: path_args=[], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -2533,7 +2900,7 @@ def post_gateway_groups(self, *, request: CreateGroupRequest) -> Group: path_args=[], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -2550,7 +2917,7 @@ def post_gateway_groups_api_keys( path_args=[group_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -2567,7 +2934,7 @@ def post_gateway_groups_api_keys_register( path_args=[group_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -2584,7 +2951,7 @@ def post_library_listings( path_args=[], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -2604,7 +2971,7 @@ def post_library_listings_versions( path_args=[user_defined_listing_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -2619,7 +2986,7 @@ def post_llm_models(self, *, request: CreateLLMModelRequest) -> LLMModelHandle: path_args=[], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -2636,7 +3003,7 @@ def post_llm_models_deployments( path_args=[model_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -2653,7 +3020,7 @@ def post_loops_checkpoints_validate( path_args=[], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -2670,7 +3037,7 @@ def post_loops_deployments_deactivate( path_args=[deployment_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -2687,7 +3054,7 @@ def post_loops_deployments_metrics( path_args=[deployment_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -2704,7 +3071,7 @@ def post_loops_runs( path_args=[], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -2719,7 +3086,7 @@ def post_loops_runs_deactivate(self, *, run_id: str) -> DeactivateLoopsRunRespon path_args=[run_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -2736,7 +3103,7 @@ def post_loops_samplers( path_args=[], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -2751,7 +3118,7 @@ def post_loops_sessions(self) -> CreateLoopsSessionResponse: path_args=[], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -2768,7 +3135,7 @@ def post_loops_trainers( path_args=[], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -2783,7 +3150,7 @@ def post_models(self, *, request: CreateModelRequest) -> CreatedModelDeployment: path_args=[], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -2800,7 +3167,7 @@ def post_models_deployments( path_args=[model_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -2817,7 +3184,7 @@ def post_models_deployments_activate( path_args=[model_id, deployment_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -2834,7 +3201,7 @@ def post_models_deployments_deactivate( path_args=[model_id, deployment_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -2851,7 +3218,7 @@ def post_models_deployments_development_activate( path_args=[model_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -2868,7 +3235,7 @@ def post_models_deployments_development_deactivate( path_args=[model_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -2885,7 +3252,7 @@ def post_models_deployments_development_promote( path_args=[model_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -2902,7 +3269,7 @@ def post_models_deployments_development_retry( path_args=[model_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -2919,7 +3286,7 @@ def post_models_deployments_logs( path_args=[model_id, deployment_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -2940,7 +3307,7 @@ def post_models_deployments_patches( path_args=[model_id, deployment_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -2961,7 +3328,7 @@ def post_models_deployments_patches_sync( path_args=[model_id, deployment_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -2978,7 +3345,7 @@ def post_models_deployments_production_activate( path_args=[model_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -2995,7 +3362,7 @@ def post_models_deployments_production_deactivate( path_args=[model_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -3012,7 +3379,7 @@ def post_models_deployments_production_retry( path_args=[model_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -3029,7 +3396,7 @@ def post_models_deployments_promote( path_args=[model_id, deployment_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -3046,7 +3413,7 @@ def post_models_deployments_retry( path_args=[model_id, deployment_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -3063,7 +3430,7 @@ def post_models_deployments_ssh_sign( path_args=[model_id, deployment_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -3080,7 +3447,7 @@ def post_models_environments( path_args=[model_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -3097,7 +3464,7 @@ def post_models_environments_activate( path_args=[model_id, env_name], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -3114,7 +3481,7 @@ def post_models_environments_cancel_promotion( path_args=[model_id, env_name], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -3131,7 +3498,7 @@ def post_models_environments_deactivate( path_args=[model_id, env_name], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -3148,7 +3515,7 @@ def post_models_environments_force_cancel_promotion( path_args=[model_id, env_name], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -3165,7 +3532,7 @@ def post_models_environments_force_roll_forward_promotion( path_args=[model_id, env_name], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -3182,7 +3549,7 @@ def post_models_environments_pause_promotion( path_args=[model_id, env_name], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -3199,7 +3566,7 @@ def post_models_environments_promote( path_args=[model_id, env_name], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -3216,7 +3583,7 @@ def post_models_environments_resume_promotion( path_args=[model_id, env_name], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -3233,7 +3600,22 @@ def post_prepare_model_upload( path_args=[], body=request, query=None, - success_code=200, + success_codes=[200], + error_codes=None, + ), + ) + + def post_routes(self, *, request: CreateRouteRequest) -> Route: + """Creates a route""" + return self._do_json( + Route, + _ApiRequest( + method="POST", + path_fmt="/v1/routes", + path_args=[], + body=request, + query=None, + success_codes=[200], error_codes=None, ), ) @@ -3248,7 +3630,7 @@ def post_secrets(self, *, request: UpsertSecretRequest) -> Secret: path_args=[], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -3265,7 +3647,7 @@ def post_teams_api_keys( path_args=[team_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -3282,7 +3664,7 @@ def post_teams_llm_models( path_args=[team_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -3299,7 +3681,7 @@ def post_teams_loops_runs( path_args=[team_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -3316,7 +3698,7 @@ def post_teams_loops_samplers( path_args=[team_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -3331,7 +3713,7 @@ def post_teams_loops_sessions(self, *, team_id: str) -> CreateLoopsSessionRespon path_args=[team_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -3348,7 +3730,7 @@ def post_teams_loops_trainers( path_args=[team_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -3365,7 +3747,7 @@ def post_teams_models( path_args=[team_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -3382,7 +3764,7 @@ def post_teams_secrets( path_args=[team_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -3399,7 +3781,22 @@ def post_teams_training_projects( path_args=[team_id], body=request, query=None, - success_code=200, + success_codes=[200], + error_codes=None, + ), + ) + + def post_token(self, *, request: CreateTokenRequest) -> Token: + """Creates a sandbox access token""" + return self._do_json( + Token, + _ApiRequest( + method="POST", + path_fmt="/v1/token", + path_args=[], + body=request, + query=None, + success_codes=[200], error_codes=None, ), ) @@ -3416,7 +3813,7 @@ def post_training_jobs_search( path_args=[], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -3433,7 +3830,7 @@ def post_training_projects( path_args=[], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -3450,7 +3847,7 @@ def post_training_projects_jobs( path_args=[training_project_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -3471,7 +3868,7 @@ def post_training_projects_jobs_logs( path_args=[training_project_id, training_job_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -3492,7 +3889,7 @@ def post_training_projects_jobs_metrics( path_args=[training_project_id, training_job_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -3509,7 +3906,7 @@ def post_training_projects_jobs_recreate( path_args=[training_project_id, training_job_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -3530,7 +3927,7 @@ def post_training_projects_jobs_ssh_sign( path_args=[training_project_id, training_job_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -3551,7 +3948,37 @@ def post_training_projects_jobs_stop( path_args=[training_project_id, training_job_id], body=request, query=None, - success_code=200, + success_codes=[200], + error_codes=None, + ), + ) + + def post_volumes_syncs(self, *, request: CreateVolumeSyncRequest) -> VolumeSync: + """Starts a volume sync""" + return self._do_json( + VolumeSync, + _ApiRequest( + method="POST", + path_fmt="/v1/volumes/syncs", + path_args=[], + body=request, + query=None, + success_codes=[200], + error_codes=None, + ), + ) + + def post_volumes_syncs_cancel(self, *, volume_sync_id: str) -> VolumeSync: + """Cancels a volume sync""" + return self._do_json( + VolumeSync, + _ApiRequest( + method="POST", + path_fmt="/v1/volumes/syncs/{}/cancel", + path_args=[volume_sync_id], + body=None, + query=None, + success_codes=[200], error_codes=None, ), ) @@ -3568,7 +3995,7 @@ def post_volumes_token( path_args=[], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -3581,7 +4008,7 @@ def post_volumes_versions_restore( volume_version: str, request: RestoreVolumeVersionRequest, ) -> RestoreVolumeVersionResponse: - """Restores a deleted version of a volume""" + """Restores a deleted or expired version of a volume""" return self._do_json( RestoreVolumeVersionResponse, _ApiRequest( @@ -3590,7 +4017,39 @@ def post_volumes_versions_restore( path_args=[volume_namespace, volume_name, volume_version], body=request, query=None, - success_code=200, + success_codes=[200], + error_codes=None, + ), + ) + + def push_image(self, *, request: PushImageRequest) -> PushImageResponse: + """Push a sandbox image""" + return self._do_json( + PushImageResponse, + _ApiRequest( + method="POST", + path_fmt="/v1/sandboxes/images", + path_args=[], + body=request, + query=None, + success_codes=[202], + error_codes=None, + ), + ) + + def update_sandbox( + self, *, sandbox_name: str, request: UpdateSandboxRequest + ) -> Sandbox: + """Update a sandbox""" + return self._do_json( + Sandbox, + _ApiRequest( + method="PATCH", + path_fmt="/v1/sandboxes/instances/{}", + path_args=[sandbox_name], + body=request, + query=None, + success_codes=[200], error_codes=None, ), ) @@ -3600,14 +4059,26 @@ def _do(self, request: _ApiRequest) -> httpx.Response: *[urllib.parse.quote(a, safe="") for a in request.path_args] ) json_body = None + content_body = None + files_body = None + headers: dict[str, str] = {} + if request.accept is not None: + headers["Accept"] = request.accept if request.body is not None: - if isinstance(request.body, BaseModel): - # Only fields the caller set are sent, so unset fields fall - # back to the server default rather than being reset here. - # An explicit None is kept, since null can mean "clear". - json_body = request.body.model_dump(mode="json", exclude_unset=True) + if request.body_content_type is None: + if isinstance(request.body, BaseModel): + # Only fields the caller set are sent, so unset fields fall + # back to the server default rather than being reset here. + # An explicit None is kept, since null can mean "clear". + json_body = request.body.model_dump(mode="json", exclude_unset=True) + else: + json_body = request.body + elif request.body_content_type == "multipart/form-data": + # httpx derives the multipart Content-Type, boundary included. + files_body = request.body else: - json_body = request.body + headers["Content-Type"] = request.body_content_type + content_body = request.body params = None if request.query is not None: if isinstance(request.query, BaseModel): @@ -3619,9 +4090,15 @@ def _do(self, request: _ApiRequest) -> httpx.Response: else: params = request.query response = self._http_client.request( - request.method, path, json=json_body, params=params - ) - if response.status_code != request.success_code: + request.method, + path, + json=json_body, + content=content_body, + files=files_body, + params=params, + headers=headers, + ) + if response.status_code not in request.success_codes: raise ResponseError(status_code=response.status_code, body=response.text) return response @@ -3643,9 +4120,39 @@ class AsyncApiClient: They may change without notice between versions. """ - def __init__(self, http_client: httpx.AsyncClient) -> None: - """Create a new client. The caller is responsible for closing *http_client*.""" - self._http_client = http_client + def __init__(self, http_client: httpx.AsyncClient) -> None: + """Create a new client. The caller is responsible for closing *http_client*.""" + self._http_client = http_client + + async def cleanup_images(self) -> CleanupImagesResponse: + """Clean up unused images""" + return await self._do_json( + CleanupImagesResponse, + _ApiRequest( + method="POST", + path_fmt="/v1/sandboxes/cleanup_images", + path_args=[], + body=None, + query=None, + success_codes=[200], + error_codes=None, + ), + ) + + async def create_sandbox(self, *, request: CreateSandboxRequest) -> Sandbox: + """Create a sandbox""" + return await self._do_json( + Sandbox, + _ApiRequest( + method="POST", + path_fmt="/v1/sandboxes/instances", + path_args=[], + body=request, + query=None, + success_codes=[201], + error_codes=None, + ), + ) async def delete_api_keys(self, *, api_key_prefix: str) -> APIKeyTombstone: """Deletes an API key by prefix""" @@ -3657,7 +4164,7 @@ async def delete_api_keys(self, *, api_key_prefix: str) -> APIKeyTombstone: path_args=[api_key_prefix], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -3672,7 +4179,7 @@ async def delete_chains(self, *, chain_id: str) -> ChainTombstone: path_args=[chain_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -3689,7 +4196,7 @@ async def delete_chains_deployments( path_args=[chain_id, chain_deployment_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -3704,7 +4211,37 @@ async def delete_gateway_endpoints(self, *, endpoint_id: str) -> EndpointTombsto path_args=[endpoint_id], body=None, query=None, - success_code=200, + success_codes=[200], + error_codes=None, + ), + ) + + async def delete_image(self, *, image_name: str) -> Image: + """Delete a sandbox image""" + return await self._do_json( + Image, + _ApiRequest( + method="DELETE", + path_fmt="/v1/sandboxes/images/{}", + path_args=[image_name], + body=None, + query=None, + success_codes=[200], + error_codes=None, + ), + ) + + async def delete_image_tag(self, *, image_name: str, tag_name: str) -> Image: + """Delete an image tag""" + return await self._do_json( + Image, + _ApiRequest( + method="DELETE", + path_fmt="/v1/sandboxes/images/{}/tags/{}", + path_args=[image_name, tag_name], + body=None, + query=None, + success_codes=[200], error_codes=None, ), ) @@ -3721,7 +4258,7 @@ async def delete_library_listings( path_args=[user_defined_listing_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -3738,7 +4275,7 @@ async def delete_library_listings_versions( path_args=[user_defined_listing_id, version_tag], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -3753,7 +4290,7 @@ async def delete_models(self, *, model_id: str) -> ModelTombstone: path_args=[model_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -3770,7 +4307,7 @@ async def delete_models_deployments( path_args=[model_id, deployment_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -3787,7 +4324,7 @@ async def delete_models_deployments_replicas( path_args=[model_id, deployment_id, replica_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -3804,7 +4341,37 @@ async def delete_models_environments( path_args=[model_id, env_name], body=None, query=None, - success_code=200, + success_codes=[200], + error_codes=None, + ), + ) + + async def delete_routes(self, *, route_id: str) -> RouteTombstone: + """Deletes a route""" + return await self._do_json( + RouteTombstone, + _ApiRequest( + method="DELETE", + path_fmt="/v1/routes/{}", + path_args=[route_id], + body=None, + query=None, + success_codes=[200], + error_codes=None, + ), + ) + + async def delete_sandbox(self, *, sandbox_name: str) -> Sandbox: + """Delete a sandbox""" + return await self._do_json( + Sandbox, + _ApiRequest( + method="DELETE", + path_fmt="/v1/sandboxes/instances/{}", + path_args=[sandbox_name], + body=None, + query=None, + success_codes=[202], error_codes=None, ), ) @@ -3819,7 +4386,7 @@ async def delete_secrets(self, *, secret_name: str) -> SecretTombstone: path_args=[secret_name], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -3836,7 +4403,7 @@ async def delete_teams_secrets( path_args=[team_id, secret_name], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -3853,7 +4420,7 @@ async def delete_training_projects( path_args=[training_project_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -3870,7 +4437,7 @@ async def delete_training_projects_jobs( path_args=[training_project_id, training_job_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -3887,7 +4454,7 @@ async def delete_volumes( path_args=[volume_namespace, volume_name], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -3909,12 +4476,12 @@ async def delete_volumes_versions( path_args=[volume_namespace, volume_name, volume_version], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) - async def get_api_keys(self) -> APIKeys: + async def get_api_keys(self, *, params: GetApiKeysParams | None = None) -> APIKeys: """Lists API keys (metadata only, no plain text keys)""" return await self._do_json( APIKeys, @@ -3923,14 +4490,14 @@ async def get_api_keys(self) -> APIKeys: path_fmt="/v1/api_keys", path_args=[], body=None, - query=None, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) async def get_audit_logs( - self, *, request: GetAuditLogsRequest | None = None + self, *, params: GetAuditLogsParams | None = None ) -> ListAuditLogsResponse: """Gets the audit log for the workspace""" return await self._do_json( @@ -3940,14 +4507,14 @@ async def get_audit_logs( path_fmt="/v1/audit_logs", path_args=[], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) async def get_billing_model_apis( - self, *, request: GetBillingModelApisRequest | None = None + self, *, params: GetBillingModelApisParams | None = None ) -> ModelApisCostsResponse: """Gets daily Model APIs costs""" return await self._do_json( @@ -3957,14 +4524,31 @@ async def get_billing_model_apis( path_fmt="/v1/billing/model_apis", path_args=[], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], + error_codes=None, + ), + ) + + async def get_billing_tool_call_usage( + self, *, params: GetBillingToolCallUsageParams + ) -> ToolCallUsageResponse: + """Gets server-side tool call usage""" + return await self._do_json( + ToolCallUsageResponse, + _ApiRequest( + method="GET", + path_fmt="/v1/billing/tool_call_usage", + path_args=[], + body=None, + query=params, + success_codes=[200], error_codes=None, ), ) async def get_billing_usage_summary( - self, *, request: GetBillingUsageSummaryRequest + self, *, params: GetBillingUsageSummaryParams ) -> UsageSummary: """Gets billing usage summary for a date range""" return await self._do_json( @@ -3974,8 +4558,8 @@ async def get_billing_usage_summary( path_fmt="/v1/billing/usage_summary", path_args=[], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) @@ -3990,7 +4574,7 @@ async def get_blobs_credentials_model(self) -> GetBlobCredentialsResponse: path_args=[], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -4005,7 +4589,7 @@ async def get_blobs_credentials_train(self) -> GetBlobCredentialsResponse: path_args=[], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -4020,13 +4604,13 @@ async def get_chains(self) -> Chains: path_args=[], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) async def get_chains_audit_logs( - self, *, chain_id: str, request: GetChainsAuditLogsRequest | None = None + self, *, chain_id: str, params: GetChainsAuditLogsParams | None = None ) -> ListAuditLogsResponse: """Gets the audit log for a chain""" return await self._do_json( @@ -4036,8 +4620,8 @@ async def get_chains_audit_logs( path_fmt="/v1/chains/{}/audit_logs", path_args=[chain_id], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) @@ -4052,7 +4636,7 @@ async def get_chains_chain_id(self, *, chain_id: str) -> Chain: path_args=[chain_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -4067,7 +4651,7 @@ async def get_chains_deployments(self, *, chain_id: str) -> ChainDeployments: path_args=[chain_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -4084,7 +4668,7 @@ async def get_chains_deployments_chain_deployment_id( path_args=[chain_id, chain_deployment_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -4095,7 +4679,7 @@ async def get_chains_deployments_chainlets_logs( chain_id: str, chain_deployment_id: str, chainlet_id: str, - request: GetChainsDeploymentsChainletsLogsRequest | None = None, + params: GetChainsDeploymentsChainletsLogsParams | None = None, ) -> GetLogsResponse: """Gets the logs for a chainlet within a chain deployment""" return await self._do_json( @@ -4105,8 +4689,8 @@ async def get_chains_deployments_chainlets_logs( path_fmt="/v1/chains/{}/deployments/{}/chainlets/{}/logs", path_args=[chain_id, chain_deployment_id, chainlet_id], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) @@ -4121,7 +4705,7 @@ async def get_chains_environments(self, *, chain_id: str) -> Environments: path_args=[chain_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -4138,7 +4722,7 @@ async def get_chains_environments_env_name( path_args=[chain_id, env_name], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -4153,7 +4737,7 @@ async def get_environment_groups(self) -> EnvironmentGroups: path_args=[], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -4170,7 +4754,24 @@ async def get_environment_groups_env_name( path_args=[env_name], body=None, query=None, - success_code=200, + success_codes=[200], + error_codes=None, + ), + ) + + async def get_explore_metadata( + self, *, params: GetExploreMetadataParams | None = None + ) -> ExploreMetadataResponse: + """Lists model metadata""" + return await self._do_json( + ExploreMetadataResponse, + _ApiRequest( + method="GET", + path_fmt="/v1/explore/metadata", + path_args=[], + body=None, + query=params, + success_codes=[200], error_codes=None, ), ) @@ -4185,7 +4786,7 @@ async def get_gateway_endpoints(self) -> EndpointsResponse: path_args=[], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -4200,13 +4801,13 @@ async def get_gateway_endpoints_endpoint_id(self, *, endpoint_id: str) -> Endpoi path_args=[endpoint_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) async def get_gateway_events( - self, *, request: GetGatewayEventsRequest | None = None + self, *, params: GetGatewayEventsParams | None = None ) -> GatewayEventsResponse: """Lists gateway events""" return await self._do_json( @@ -4216,8 +4817,8 @@ async def get_gateway_events( path_fmt="/v1/gateway/events", path_args=[], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) @@ -4232,7 +4833,7 @@ async def get_gateway_groups(self) -> GroupsResponse: path_args=[], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -4249,7 +4850,7 @@ async def get_gateway_groups_api_keys( path_args=[group_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -4266,7 +4867,7 @@ async def get_gateway_groups_api_keys_api_key_prefix( path_args=[group_id, api_key_prefix], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -4281,7 +4882,22 @@ async def get_gateway_groups_group_id(self, *, group_id: str) -> Group: path_args=[group_id], body=None, query=None, - success_code=200, + success_codes=[200], + error_codes=None, + ), + ) + + async def get_image(self, *, image_name: str) -> Image: + """Get a sandbox image""" + return await self._do_json( + Image, + _ApiRequest( + method="GET", + path_fmt="/v1/sandboxes/images/{}", + path_args=[image_name], + body=None, + query=None, + success_codes=[200], error_codes=None, ), ) @@ -4296,7 +4912,7 @@ async def get_instance_type_prices(self) -> InstanceTypePrices: path_args=[], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -4311,7 +4927,7 @@ async def get_instance_types(self) -> InstanceTypes: path_args=[], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -4326,7 +4942,7 @@ async def get_library_listings(self) -> LibraryListings: path_args=[], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -4343,7 +4959,7 @@ async def get_library_listings_user_defined_listing_id( path_args=[user_defined_listing_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -4360,7 +4976,7 @@ async def get_library_listings_versions( path_args=[user_defined_listing_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -4377,12 +4993,14 @@ async def get_library_listings_versions_version_tag( path_args=[user_defined_listing_id, version_tag], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) - async def get_loops_capabilities(self) -> GetLoopsCapabilitiesResponse: + async def get_loops_capabilities( + self, *, params: GetLoopsCapabilitiesParams | None = None + ) -> GetLoopsCapabilitiesResponse: """Gets Loops server capabilities""" return await self._do_json( GetLoopsCapabilitiesResponse, @@ -4391,14 +5009,14 @@ async def get_loops_capabilities(self) -> GetLoopsCapabilitiesResponse: path_fmt="/v1/loops/capabilities", path_args=[], body=None, - query=None, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) async def get_loops_checkpoints( - self, *, request: GetLoopsCheckpointsRequest | None = None + self, *, params: GetLoopsCheckpointsParams | None = None ) -> ListLoopsCheckpointsResponse: """Lists Loops checkpoints""" return await self._do_json( @@ -4408,8 +5026,8 @@ async def get_loops_checkpoints( path_fmt="/v1/loops/checkpoints", path_args=[], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) @@ -4418,7 +5036,7 @@ async def get_loops_checkpoints_files( self, *, checkpoint_id: str, - request: GetLoopsCheckpointsFilesRequest | None = None, + params: GetLoopsCheckpointsFilesParams | None = None, ) -> LoopsCheckpointFilesResponse: """Gets Loops checkpoint files""" return await self._do_json( @@ -4428,14 +5046,31 @@ async def get_loops_checkpoints_files( path_fmt="/v1/loops/checkpoints/{}/files", path_args=[checkpoint_id], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], + error_codes=None, + ), + ) + + async def get_loops_checkpoints_source( + self, *, checkpoint_id: str + ) -> LoopsCheckpointSourceResponse: + """Gets where a Loops checkpoint's files come from""" + return await self._do_json( + LoopsCheckpointSourceResponse, + _ApiRequest( + method="GET", + path_fmt="/v1/loops/checkpoints/{}/source", + path_args=[checkpoint_id], + body=None, + query=None, + success_codes=[200], error_codes=None, ), ) async def get_loops_deployments( - self, *, request: GetLoopsDeploymentsRequest | None = None + self, *, params: GetLoopsDeploymentsParams | None = None ) -> ListLoopsDeploymentsResponse: """Lists Loops deployments""" return await self._do_json( @@ -4445,8 +5080,8 @@ async def get_loops_deployments( path_fmt="/v1/loops/deployments", path_args=[], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) @@ -4455,7 +5090,7 @@ async def get_loops_deployments_debug_archive_files( self, *, deployment_id: str, - request: GetLoopsDeploymentsDebugArchiveFilesRequest | None = None, + params: GetLoopsDeploymentsDebugArchiveFilesParams | None = None, ) -> LoopsDebugArchiveFilesResponse: """Gets Loops debug archive files""" return await self._do_json( @@ -4465,8 +5100,8 @@ async def get_loops_deployments_debug_archive_files( path_fmt="/v1/loops/deployments/{}/debug_archive/files", path_args=[deployment_id], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) @@ -4483,16 +5118,13 @@ async def get_loops_deployments_deployment_id( path_args=[deployment_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) async def get_loops_deployments_logs( - self, - *, - deployment_id: str, - request: GetLoopsDeploymentsLogsRequest | None = None, + self, *, deployment_id: str, params: GetLoopsDeploymentsLogsParams | None = None ) -> GetLogsResponse: """Gets logs for a Loops trainer deployment""" return await self._do_json( @@ -4502,14 +5134,14 @@ async def get_loops_deployments_logs( path_fmt="/v1/loops/deployments/{}/logs", path_args=[deployment_id], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) async def get_loops_runs( - self, *, request: GetLoopsRunsRequest | None = None + self, *, params: GetLoopsRunsParams | None = None ) -> ListLoopsRunsResponse: """Lists Loops runs""" return await self._do_json( @@ -4519,8 +5151,8 @@ async def get_loops_runs( path_fmt="/v1/loops/runs", path_args=[], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) @@ -4535,13 +5167,13 @@ async def get_loops_runs_run_id(self, *, run_id: str) -> GetLoopsRunResponse: path_args=[run_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) async def get_loops_samplers( - self, *, request: GetLoopsSamplersRequest | None = None + self, *, params: GetLoopsSamplersParams | None = None ) -> ListLoopsSamplersResponse: """Lists Loops samplers""" return await self._do_json( @@ -4551,8 +5183,8 @@ async def get_loops_samplers( path_fmt="/v1/loops/samplers", path_args=[], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) @@ -4569,7 +5201,7 @@ async def get_loops_samplers_sampler_id( path_args=[sampler_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -4584,7 +5216,7 @@ async def get_loops_sessions(self, *, session_id: str) -> GetLoopsSessionRespons path_args=[session_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -4599,13 +5231,13 @@ async def get_loops_user_config(self) -> GetLoopsUserConfigResponse: path_args=[], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) async def get_model_apis( - self, *, request: GetModelApisRequest | None = None + self, *, params: GetModelApisParams | None = None ) -> ModelAPIsResponse: """Lists Model APIs""" return await self._do_json( @@ -4615,8 +5247,8 @@ async def get_model_apis( path_fmt="/v1/model_apis", path_args=[], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) @@ -4631,13 +5263,13 @@ async def get_model_apis_model_api_name(self, *, model_api_name: str) -> ModelAP path_args=[model_api_name], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) async def get_model_apis_usage( - self, *, request: GetModelApisUsageRequest | None = None + self, *, params: GetModelApisUsageParams | None = None ) -> ModelApisUsageResponse: """Gets Model APIs token usage in time buckets""" return await self._do_json( @@ -4647,13 +5279,13 @@ async def get_model_apis_usage( path_fmt="/v1/model_apis/usage", path_args=[], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) - async def get_models(self, *, request: GetModelsRequest | None = None) -> Models: + async def get_models(self, *, params: GetModelsParams | None = None) -> Models: """Gets all models""" return await self._do_json( Models, @@ -4662,14 +5294,14 @@ async def get_models(self, *, request: GetModelsRequest | None = None) -> Models path_fmt="/v1/models", path_args=[], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) async def get_models_audit_logs( - self, *, model_id: str, request: GetModelsAuditLogsRequest | None = None + self, *, model_id: str, params: GetModelsAuditLogsParams | None = None ) -> ListAuditLogsResponse: """Gets the audit log for a model""" return await self._do_json( @@ -4679,14 +5311,14 @@ async def get_models_audit_logs( path_fmt="/v1/models/{}/audit_logs", path_args=[model_id], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) async def get_models_deployments( - self, *, model_id: str, request: GetModelsDeploymentsRequest | None = None + self, *, model_id: str, params: GetModelsDeploymentsParams | None = None ) -> Deployments: """Gets all deployments of a model""" return await self._do_json( @@ -4696,8 +5328,8 @@ async def get_models_deployments( path_fmt="/v1/models/{}/deployments", path_args=[model_id], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) @@ -4707,7 +5339,7 @@ async def get_models_deployments_config( *, model_id: str, deployment_id: str, - request: GetModelsDeploymentsConfigRequest | None = None, + params: GetModelsDeploymentsConfigParams | None = None, ) -> DeploymentConfigResponse: """Gets a deployment's config""" return await self._do_json( @@ -4717,8 +5349,8 @@ async def get_models_deployments_config( path_fmt="/v1/models/{}/deployments/{}/config", path_args=[model_id, deployment_id], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) @@ -4735,7 +5367,7 @@ async def get_models_deployments_deployment_id( path_args=[model_id, deployment_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -4750,7 +5382,7 @@ async def get_models_deployments_development(self, *, model_id: str) -> Deployme path_args=[model_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -4767,7 +5399,7 @@ async def get_models_deployments_download( path_args=[model_id, deployment_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -4777,7 +5409,7 @@ async def get_models_deployments_logs( *, model_id: str, deployment_id: str, - request: GetModelsDeploymentsLogsRequest | None = None, + params: GetModelsDeploymentsLogsParams | None = None, ) -> GetLogsResponse: """Gets the logs for a model deployment""" return await self._do_json( @@ -4787,8 +5419,8 @@ async def get_models_deployments_logs( path_fmt="/v1/models/{}/deployments/{}/logs", path_args=[model_id, deployment_id], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) @@ -4798,7 +5430,7 @@ async def get_models_deployments_metrics( *, model_id: str, deployment_id: str, - request: GetModelsDeploymentsMetricsRequest | None = None, + params: GetModelsDeploymentsMetricsParams | None = None, ) -> GetModelMetricsResponse: """Gets the metrics for a model deployment""" return await self._do_json( @@ -4808,8 +5440,8 @@ async def get_models_deployments_metrics( path_fmt="/v1/models/{}/deployments/{}/metrics", path_args=[model_id, deployment_id], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) @@ -4826,7 +5458,7 @@ async def get_models_deployments_patches_state( path_args=[model_id, deployment_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -4841,7 +5473,7 @@ async def get_models_deployments_production(self, *, model_id: str) -> Deploymen path_args=[model_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -4856,7 +5488,7 @@ async def get_models_environments(self, *, model_id: str) -> Environments: path_args=[model_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -4873,7 +5505,7 @@ async def get_models_environments_env_name( path_args=[model_id, env_name], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -4883,7 +5515,7 @@ async def get_models_environments_logs( *, model_id: str, env_name: str, - request: GetModelsEnvironmentsLogsRequest | None = None, + params: GetModelsEnvironmentsLogsParams | None = None, ) -> GetLogsResponse: """Gets the logs for a model environment""" return await self._do_json( @@ -4893,8 +5525,8 @@ async def get_models_environments_logs( path_fmt="/v1/models/{}/environments/{}/logs", path_args=[model_id, env_name], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) @@ -4904,7 +5536,7 @@ async def get_models_environments_metrics( *, model_id: str, env_name: str, - request: GetModelsEnvironmentsMetricsRequest | None = None, + params: GetModelsEnvironmentsMetricsParams | None = None, ) -> GetModelMetricsResponse: """Gets the metrics for a model environment.""" return await self._do_json( @@ -4914,8 +5546,8 @@ async def get_models_environments_metrics( path_fmt="/v1/models/{}/environments/{}/metrics", path_args=[model_id, env_name], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) @@ -4930,7 +5562,7 @@ async def get_models_model_id(self, *, model_id: str) -> Model: path_args=[model_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -4945,7 +5577,7 @@ async def get_organizations_me(self) -> OrganizationInfo: path_args=[], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -4960,7 +5592,71 @@ async def get_regions(self) -> Regions: path_args=[], body=None, query=None, - success_code=200, + success_codes=[200], + error_codes=None, + ), + ) + + async def get_routes( + self, *, params: GetRoutesParams | None = None + ) -> RoutesResponse: + """Lists routes""" + return await self._do_json( + RoutesResponse, + _ApiRequest( + method="GET", + path_fmt="/v1/routes", + path_args=[], + body=None, + query=params, + success_codes=[200], + error_codes=None, + ), + ) + + async def get_routes_route_id(self, *, route_id: str) -> Route: + """Gets a route""" + return await self._do_json( + Route, + _ApiRequest( + method="GET", + path_fmt="/v1/routes/{}", + path_args=[route_id], + body=None, + query=None, + success_codes=[200], + error_codes=None, + ), + ) + + async def get_routes_usage( + self, *, params: GetRoutesUsageParams | None = None + ) -> RoutesUsageResponse: + """Gets daily route usage and estimated costs""" + return await self._do_json( + RoutesUsageResponse, + _ApiRequest( + method="GET", + path_fmt="/v1/routes/usage", + path_args=[], + body=None, + query=params, + success_codes=[200], + error_codes=None, + ), + ) + + async def get_sandbox(self, *, sandbox_name: str) -> Sandbox: + """Get a sandbox""" + return await self._do_json( + Sandbox, + _ApiRequest( + method="GET", + path_fmt="/v1/sandboxes/instances/{}", + path_args=[sandbox_name], + body=None, + query=None, + success_codes=[200], error_codes=None, ), ) @@ -4975,12 +5671,12 @@ async def get_secrets(self) -> Secrets: path_args=[], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) - async def get_teams(self, *, request: GetTeamsRequest | None = None) -> Teams: + async def get_teams(self, *, params: GetTeamsParams | None = None) -> Teams: """Lists all teams""" return await self._do_json( Teams, @@ -4989,8 +5685,8 @@ async def get_teams(self, *, request: GetTeamsRequest | None = None) -> Teams: path_fmt="/v1/teams", path_args=[], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) @@ -5005,7 +5701,7 @@ async def get_teams_environment_groups(self, *, team_id: str) -> EnvironmentGrou path_args=[team_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -5022,13 +5718,13 @@ async def get_teams_environment_groups_env_name( path_args=[team_id, env_name], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) async def get_teams_loops_runs( - self, *, team_id: str, request: GetTeamsLoopsRunsRequest | None = None + self, *, team_id: str, params: GetTeamsLoopsRunsParams | None = None ) -> ListLoopsRunsResponse: """Lists a team's Loops runs""" return await self._do_json( @@ -5038,14 +5734,14 @@ async def get_teams_loops_runs( path_fmt="/v1/teams/{}/loops/runs", path_args=[team_id], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) async def get_teams_loops_samplers( - self, *, team_id: str, request: GetTeamsLoopsSamplersRequest | None = None + self, *, team_id: str, params: GetTeamsLoopsSamplersParams | None = None ) -> ListLoopsSamplersResponse: """Lists a team's Loops samplers""" return await self._do_json( @@ -5055,14 +5751,14 @@ async def get_teams_loops_samplers( path_fmt="/v1/teams/{}/loops/samplers", path_args=[team_id], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) async def get_teams_models( - self, *, team_id: str, request: GetTeamsModelsRequest | None = None + self, *, team_id: str, params: GetTeamsModelsParams | None = None ) -> Models: """Gets all models""" return await self._do_json( @@ -5072,8 +5768,8 @@ async def get_teams_models( path_fmt="/v1/teams/{}/models", path_args=[team_id], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) @@ -5088,7 +5784,7 @@ async def get_teams_regions(self, *, team_id: str) -> Regions: path_args=[team_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -5103,7 +5799,7 @@ async def get_teams_secrets(self, *, team_id: str) -> Secrets: path_args=[team_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -5118,7 +5814,7 @@ async def get_teams_team_id(self, *, team_id: str) -> Team: path_args=[team_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -5133,7 +5829,7 @@ async def get_training_capacity(self) -> GetTrainingGpuCapacityResponse: path_args=[], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -5150,7 +5846,7 @@ async def get_training_jobs_queue_context( path_args=[training_job_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -5165,7 +5861,7 @@ async def get_training_projects(self) -> ListTrainingProjectsResponse: path_args=[], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -5182,7 +5878,7 @@ async def get_training_projects_cache_summary( path_args=[training_project_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -5199,7 +5895,7 @@ async def get_training_projects_jobs( path_args=[training_project_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -5216,7 +5912,7 @@ async def get_training_projects_jobs_auth_codes( path_args=[training_project_id, training_job_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -5226,7 +5922,7 @@ async def get_training_projects_jobs_checkpoint_files( *, training_project_id: str, training_job_id: str, - request: GetTrainingProjectsJobsCheckpointFilesRequest | None = None, + params: GetTrainingProjectsJobsCheckpointFilesParams | None = None, ) -> GetTrainingJobCheckpointFilesResponse: """Gets training job checkpoint files""" return await self._do_json( @@ -5236,8 +5932,8 @@ async def get_training_projects_jobs_checkpoint_files( path_fmt="/v1/training_projects/{}/jobs/{}/checkpoint_files", path_args=[training_project_id, training_job_id], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) @@ -5254,7 +5950,7 @@ async def get_training_projects_jobs_checkpoints( path_args=[training_project_id, training_job_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -5271,7 +5967,7 @@ async def get_training_projects_jobs_download( path_args=[training_project_id, training_job_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -5281,7 +5977,7 @@ async def get_training_projects_jobs_logs( *, training_project_id: str, training_job_id: str, - request: GetTrainingProjectsJobsLogsRequest | None = None, + params: GetTrainingProjectsJobsLogsParams | None = None, ) -> GetLogsResponse: """Gets the logs for a training job""" return await self._do_json( @@ -5291,8 +5987,8 @@ async def get_training_projects_jobs_logs( path_fmt="/v1/training_projects/{}/jobs/{}/logs", path_args=[training_project_id, training_job_id], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) @@ -5302,7 +5998,7 @@ async def get_training_projects_jobs_metrics( *, training_project_id: str, training_job_id: str, - request: GetTrainingProjectsJobsMetricsRequest | None = None, + params: GetTrainingProjectsJobsMetricsParams | None = None, ) -> GetTrainingJobMetricsResponse: """Gets the metrics for a training job""" return await self._do_json( @@ -5312,8 +6008,8 @@ async def get_training_projects_jobs_metrics( path_fmt="/v1/training_projects/{}/jobs/{}/metrics", path_args=[training_project_id, training_job_id], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) @@ -5330,7 +6026,7 @@ async def get_training_projects_jobs_training_job_id( path_args=[training_project_id, training_job_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -5347,14 +6043,12 @@ async def get_training_projects_training_project_id( path_args=[training_project_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) - async def get_users( - self, *, request: GetUsersRequest | None = None - ) -> UsersResponse: + async def get_users(self, *, params: GetUsersParams | None = None) -> UsersResponse: """Lists users in the workspace""" return await self._do_json( UsersResponse, @@ -5363,8 +6057,8 @@ async def get_users( path_fmt="/v1/users", path_args=[], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) @@ -5379,7 +6073,7 @@ async def get_users_me(self) -> UserInfo: path_args=[], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -5394,12 +6088,12 @@ async def get_users_user_id(self, *, user_id: str) -> UserInfo: path_args=[user_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) - async def get_volumes(self, *, request: GetVolumesRequest) -> ListVolumesResponse: + async def get_volumes(self, *, params: GetVolumesParams) -> ListVolumesResponse: """Gets the volumes in a namespace""" return await self._do_json( ListVolumesResponse, @@ -5408,14 +6102,14 @@ async def get_volumes(self, *, request: GetVolumesRequest) -> ListVolumesRespons path_fmt="/v1/volumes", path_args=[], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) async def get_volumes_namespaces( - self, *, request: GetVolumesNamespacesRequest | None = None + self, *, params: GetVolumesNamespacesParams | None = None ) -> ListVolumeNamespacesResponse: """Gets the volume namespaces in your workspace""" return await self._do_json( @@ -5425,8 +6119,42 @@ async def get_volumes_namespaces( path_fmt="/v1/volumes/namespaces", path_args=[], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], + error_codes=None, + ), + ) + + async def get_volumes_syncs( + self, *, params: GetVolumesSyncsParams | None = None + ) -> VolumeSyncs: + """Lists volume syncs""" + return await self._do_json( + VolumeSyncs, + _ApiRequest( + method="GET", + path_fmt="/v1/volumes/syncs", + path_args=[], + body=None, + query=params, + success_codes=[200], + error_codes=None, + ), + ) + + async def get_volumes_syncs_volume_sync_id( + self, *, volume_sync_id: str + ) -> VolumeSync: + """Gets a volume sync""" + return await self._do_json( + VolumeSync, + _ApiRequest( + method="GET", + path_fmt="/v1/volumes/syncs/{}", + path_args=[volume_sync_id], + body=None, + query=None, + success_codes=[200], error_codes=None, ), ) @@ -5436,7 +6164,7 @@ async def get_volumes_versions( *, volume_namespace: str, volume_name: str, - request: GetVolumesVersionsRequest | None = None, + params: GetVolumesVersionsParams | None = None, ) -> ListVolumeVersionsResponse: """Gets the versions of a volume""" return await self._do_json( @@ -5446,8 +6174,8 @@ async def get_volumes_versions( path_fmt="/v1/volumes/{}/{}/versions", path_args=[volume_namespace, volume_name], body=None, - query=request, - success_code=200, + query=params, + success_codes=[200], error_codes=None, ), ) @@ -5464,7 +6192,7 @@ async def get_volumes_versions_volume_version( path_args=[volume_namespace, volume_name, volume_version], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -5481,7 +6209,58 @@ async def get_volumes_volume_name( path_args=[volume_namespace, volume_name], body=None, query=None, - success_code=200, + success_codes=[200], + error_codes=None, + ), + ) + + async def list_image_tags( + self, *, image_name: str, params: ListImageTagsParams | None = None + ) -> ListImageTagsResponse: + """List image tags""" + return await self._do_json( + ListImageTagsResponse, + _ApiRequest( + method="GET", + path_fmt="/v1/sandboxes/images/{}/tags", + path_args=[image_name], + body=None, + query=params, + success_codes=[200], + error_codes=None, + ), + ) + + async def list_images( + self, *, params: ListImagesParams | None = None + ) -> ListImagesResponse: + """List sandbox images""" + return await self._do_json( + ListImagesResponse, + _ApiRequest( + method="GET", + path_fmt="/v1/sandboxes/images", + path_args=[], + body=None, + query=params, + success_codes=[200], + error_codes=None, + ), + ) + + async def list_sandboxes( + self, *, params: ListSandboxesParams | None = None + ) -> ListSandboxesResponse: + """List sandboxes""" + return await self._do_json( + ListSandboxesResponse, + _ApiRequest( + method="GET", + path_fmt="/v1/sandboxes/instances", + path_args=[], + body=None, + query=params, + success_codes=[200], error_codes=None, ), ) @@ -5498,7 +6277,7 @@ async def patch_chains_environments( path_args=[chain_id, env_name], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -5519,7 +6298,7 @@ async def patch_chains_environments_chainlet_settings_autoscaling_settings( path_args=[chain_id, env_name], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -5536,7 +6315,7 @@ async def patch_environment_groups( path_args=[env_name], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -5553,7 +6332,7 @@ async def patch_gateway_endpoints( path_args=[endpoint_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -5570,7 +6349,7 @@ async def patch_gateway_groups( path_args=[group_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -5587,7 +6366,7 @@ async def patch_library_listings( path_args=[user_defined_listing_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -5608,7 +6387,7 @@ async def patch_library_listings_versions( path_args=[user_defined_listing_id, version_tag], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -5625,7 +6404,24 @@ async def patch_loops_user_config( path_args=[], body=request, query=None, - success_code=200, + success_codes=[200], + error_codes=None, + ), + ) + + async def patch_models( + self, *, model_id: str, request: UpdateModelRequest + ) -> Model: + """Updates a model by ID""" + return await self._do_json( + Model, + _ApiRequest( + method="PATCH", + path_fmt="/v1/models/{}", + path_args=[model_id], + body=request, + query=None, + success_codes=[200], error_codes=None, ), ) @@ -5642,7 +6438,7 @@ async def patch_models_deployments( path_args=[model_id, deployment_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -5659,7 +6455,7 @@ async def patch_models_deployments_autoscaling_settings( path_args=[model_id, deployment_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -5676,7 +6472,7 @@ async def patch_models_deployments_development_autoscaling_settings( path_args=[model_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -5693,7 +6489,7 @@ async def patch_models_deployments_production_autoscaling_settings( path_args=[model_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -5714,7 +6510,7 @@ async def patch_models_deployments_request_backpressure_settings( path_args=[model_id, deployment_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -5731,7 +6527,24 @@ async def patch_models_environments( path_args=[model_id, env_name], body=request, query=None, - success_code=200, + success_codes=[200], + error_codes=None, + ), + ) + + async def patch_routes( + self, *, route_id: str, request: UpdateRouteRequest + ) -> Route: + """Updates a route's display name or description""" + return await self._do_json( + Route, + _ApiRequest( + method="PATCH", + path_fmt="/v1/routes/{}", + path_args=[route_id], + body=request, + query=None, + success_codes=[200], error_codes=None, ), ) @@ -5748,7 +6561,7 @@ async def patch_teams_environment_groups( path_args=[team_id, env_name], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -5765,7 +6578,7 @@ async def patch_training_capacity( path_args=[], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -5786,7 +6599,7 @@ async def patch_training_projects_jobs( path_args=[training_project_id, training_job_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -5808,7 +6621,7 @@ async def patch_training_projects_jobs_interactive_sessions( path_args=[training_project_id, training_job_id, session_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -5823,7 +6636,7 @@ async def post_api_keys(self, *, request: CreateAPIKeyRequest) -> APIKey: path_args=[], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -5840,7 +6653,7 @@ async def post_chains_deployments_deactivate( path_args=[chain_id, chain_deployment_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -5857,7 +6670,7 @@ async def post_chains_environments( path_args=[chain_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -5878,7 +6691,7 @@ async def post_chains_environments_chainlet_settings_instance_types_update( path_args=[chain_id, env_name], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -5895,7 +6708,7 @@ async def post_chains_environments_promote( path_args=[chain_id, env_name], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -5912,7 +6725,7 @@ async def post_gateway_endpoints( path_args=[], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -5927,7 +6740,7 @@ async def post_gateway_groups(self, *, request: CreateGroupRequest) -> Group: path_args=[], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -5944,7 +6757,7 @@ async def post_gateway_groups_api_keys( path_args=[group_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -5961,7 +6774,7 @@ async def post_gateway_groups_api_keys_register( path_args=[group_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -5978,7 +6791,7 @@ async def post_library_listings( path_args=[], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -5998,7 +6811,7 @@ async def post_library_listings_versions( path_args=[user_defined_listing_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -6015,7 +6828,7 @@ async def post_llm_models( path_args=[], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -6032,7 +6845,7 @@ async def post_llm_models_deployments( path_args=[model_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -6049,7 +6862,7 @@ async def post_loops_checkpoints_validate( path_args=[], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -6066,7 +6879,7 @@ async def post_loops_deployments_deactivate( path_args=[deployment_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -6083,7 +6896,7 @@ async def post_loops_deployments_metrics( path_args=[deployment_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -6100,7 +6913,7 @@ async def post_loops_runs( path_args=[], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -6117,7 +6930,7 @@ async def post_loops_runs_deactivate( path_args=[run_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -6134,7 +6947,7 @@ async def post_loops_samplers( path_args=[], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -6149,7 +6962,7 @@ async def post_loops_sessions(self) -> CreateLoopsSessionResponse: path_args=[], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -6166,7 +6979,7 @@ async def post_loops_trainers( path_args=[], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -6183,7 +6996,7 @@ async def post_models( path_args=[], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -6200,7 +7013,7 @@ async def post_models_deployments( path_args=[model_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -6217,7 +7030,7 @@ async def post_models_deployments_activate( path_args=[model_id, deployment_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -6234,7 +7047,7 @@ async def post_models_deployments_deactivate( path_args=[model_id, deployment_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -6251,7 +7064,7 @@ async def post_models_deployments_development_activate( path_args=[model_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -6268,7 +7081,7 @@ async def post_models_deployments_development_deactivate( path_args=[model_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -6285,7 +7098,7 @@ async def post_models_deployments_development_promote( path_args=[model_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -6302,7 +7115,7 @@ async def post_models_deployments_development_retry( path_args=[model_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -6319,7 +7132,7 @@ async def post_models_deployments_logs( path_args=[model_id, deployment_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -6340,7 +7153,7 @@ async def post_models_deployments_patches( path_args=[model_id, deployment_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -6361,7 +7174,7 @@ async def post_models_deployments_patches_sync( path_args=[model_id, deployment_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -6378,7 +7191,7 @@ async def post_models_deployments_production_activate( path_args=[model_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -6395,7 +7208,7 @@ async def post_models_deployments_production_deactivate( path_args=[model_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -6412,7 +7225,7 @@ async def post_models_deployments_production_retry( path_args=[model_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -6429,7 +7242,7 @@ async def post_models_deployments_promote( path_args=[model_id, deployment_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -6446,7 +7259,7 @@ async def post_models_deployments_retry( path_args=[model_id, deployment_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -6463,7 +7276,7 @@ async def post_models_deployments_ssh_sign( path_args=[model_id, deployment_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -6480,7 +7293,7 @@ async def post_models_environments( path_args=[model_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -6497,7 +7310,7 @@ async def post_models_environments_activate( path_args=[model_id, env_name], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -6514,7 +7327,7 @@ async def post_models_environments_cancel_promotion( path_args=[model_id, env_name], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -6531,7 +7344,7 @@ async def post_models_environments_deactivate( path_args=[model_id, env_name], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -6548,7 +7361,7 @@ async def post_models_environments_force_cancel_promotion( path_args=[model_id, env_name], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -6565,7 +7378,7 @@ async def post_models_environments_force_roll_forward_promotion( path_args=[model_id, env_name], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -6582,7 +7395,7 @@ async def post_models_environments_pause_promotion( path_args=[model_id, env_name], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -6599,7 +7412,7 @@ async def post_models_environments_promote( path_args=[model_id, env_name], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -6616,7 +7429,7 @@ async def post_models_environments_resume_promotion( path_args=[model_id, env_name], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -6633,7 +7446,22 @@ async def post_prepare_model_upload( path_args=[], body=request, query=None, - success_code=200, + success_codes=[200], + error_codes=None, + ), + ) + + async def post_routes(self, *, request: CreateRouteRequest) -> Route: + """Creates a route""" + return await self._do_json( + Route, + _ApiRequest( + method="POST", + path_fmt="/v1/routes", + path_args=[], + body=request, + query=None, + success_codes=[200], error_codes=None, ), ) @@ -6648,7 +7476,7 @@ async def post_secrets(self, *, request: UpsertSecretRequest) -> Secret: path_args=[], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -6665,7 +7493,7 @@ async def post_teams_api_keys( path_args=[team_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -6682,7 +7510,7 @@ async def post_teams_llm_models( path_args=[team_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -6699,7 +7527,7 @@ async def post_teams_loops_runs( path_args=[team_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -6716,7 +7544,7 @@ async def post_teams_loops_samplers( path_args=[team_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -6733,7 +7561,7 @@ async def post_teams_loops_sessions( path_args=[team_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -6750,7 +7578,7 @@ async def post_teams_loops_trainers( path_args=[team_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -6767,7 +7595,7 @@ async def post_teams_models( path_args=[team_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -6784,7 +7612,7 @@ async def post_teams_secrets( path_args=[team_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -6801,7 +7629,22 @@ async def post_teams_training_projects( path_args=[team_id], body=request, query=None, - success_code=200, + success_codes=[200], + error_codes=None, + ), + ) + + async def post_token(self, *, request: CreateTokenRequest) -> Token: + """Creates a sandbox access token""" + return await self._do_json( + Token, + _ApiRequest( + method="POST", + path_fmt="/v1/token", + path_args=[], + body=request, + query=None, + success_codes=[200], error_codes=None, ), ) @@ -6818,7 +7661,7 @@ async def post_training_jobs_search( path_args=[], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -6835,7 +7678,7 @@ async def post_training_projects( path_args=[], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -6852,7 +7695,7 @@ async def post_training_projects_jobs( path_args=[training_project_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -6873,7 +7716,7 @@ async def post_training_projects_jobs_logs( path_args=[training_project_id, training_job_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -6894,7 +7737,7 @@ async def post_training_projects_jobs_metrics( path_args=[training_project_id, training_job_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -6911,7 +7754,7 @@ async def post_training_projects_jobs_recreate( path_args=[training_project_id, training_job_id], body=None, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -6932,7 +7775,7 @@ async def post_training_projects_jobs_ssh_sign( path_args=[training_project_id, training_job_id], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -6953,7 +7796,39 @@ async def post_training_projects_jobs_stop( path_args=[training_project_id, training_job_id], body=request, query=None, - success_code=200, + success_codes=[200], + error_codes=None, + ), + ) + + async def post_volumes_syncs( + self, *, request: CreateVolumeSyncRequest + ) -> VolumeSync: + """Starts a volume sync""" + return await self._do_json( + VolumeSync, + _ApiRequest( + method="POST", + path_fmt="/v1/volumes/syncs", + path_args=[], + body=request, + query=None, + success_codes=[200], + error_codes=None, + ), + ) + + async def post_volumes_syncs_cancel(self, *, volume_sync_id: str) -> VolumeSync: + """Cancels a volume sync""" + return await self._do_json( + VolumeSync, + _ApiRequest( + method="POST", + path_fmt="/v1/volumes/syncs/{}/cancel", + path_args=[volume_sync_id], + body=None, + query=None, + success_codes=[200], error_codes=None, ), ) @@ -6970,7 +7845,7 @@ async def post_volumes_token( path_args=[], body=request, query=None, - success_code=200, + success_codes=[200], error_codes=None, ), ) @@ -6983,7 +7858,7 @@ async def post_volumes_versions_restore( volume_version: str, request: RestoreVolumeVersionRequest, ) -> RestoreVolumeVersionResponse: - """Restores a deleted version of a volume""" + """Restores a deleted or expired version of a volume""" return await self._do_json( RestoreVolumeVersionResponse, _ApiRequest( @@ -6992,7 +7867,39 @@ async def post_volumes_versions_restore( path_args=[volume_namespace, volume_name, volume_version], body=request, query=None, - success_code=200, + success_codes=[200], + error_codes=None, + ), + ) + + async def push_image(self, *, request: PushImageRequest) -> PushImageResponse: + """Push a sandbox image""" + return await self._do_json( + PushImageResponse, + _ApiRequest( + method="POST", + path_fmt="/v1/sandboxes/images", + path_args=[], + body=request, + query=None, + success_codes=[202], + error_codes=None, + ), + ) + + async def update_sandbox( + self, *, sandbox_name: str, request: UpdateSandboxRequest + ) -> Sandbox: + """Update a sandbox""" + return await self._do_json( + Sandbox, + _ApiRequest( + method="PATCH", + path_fmt="/v1/sandboxes/instances/{}", + path_args=[sandbox_name], + body=request, + query=None, + success_codes=[200], error_codes=None, ), ) @@ -7002,14 +7909,26 @@ async def _do(self, request: _ApiRequest) -> httpx.Response: *[urllib.parse.quote(a, safe="") for a in request.path_args] ) json_body = None + content_body = None + files_body = None + headers: dict[str, str] = {} + if request.accept is not None: + headers["Accept"] = request.accept if request.body is not None: - if isinstance(request.body, BaseModel): - # Only fields the caller set are sent, so unset fields fall - # back to the server default rather than being reset here. - # An explicit None is kept, since null can mean "clear". - json_body = request.body.model_dump(mode="json", exclude_unset=True) + if request.body_content_type is None: + if isinstance(request.body, BaseModel): + # Only fields the caller set are sent, so unset fields fall + # back to the server default rather than being reset here. + # An explicit None is kept, since null can mean "clear". + json_body = request.body.model_dump(mode="json", exclude_unset=True) + else: + json_body = request.body + elif request.body_content_type == "multipart/form-data": + # httpx derives the multipart Content-Type, boundary included. + files_body = request.body else: - json_body = request.body + headers["Content-Type"] = request.body_content_type + content_body = request.body params = None if request.query is not None: if isinstance(request.query, BaseModel): @@ -7021,9 +7940,15 @@ async def _do(self, request: _ApiRequest) -> httpx.Response: else: params = request.query response = await self._http_client.request( - request.method, path, json=json_body, params=params - ) - if response.status_code != request.success_code: + request.method, + path, + json=json_body, + content=content_body, + files=files_body, + params=params, + headers=headers, + ) + if response.status_code not in request.success_codes: raise ResponseError(status_code=response.status_code, body=response.text) return response diff --git a/baseten/client/managementapi/_models.py b/baseten/client/managementapi/_models.py index deb73a1..8d48aee 100644 --- a/baseten/client/managementapi/_models.py +++ b/baseten/client/managementapi/_models.py @@ -7,7 +7,7 @@ from enum import StrEnum from typing import Annotated, Any, Literal -from pydantic import AwareDatetime, BaseModel, ConfigDict, Field, RootModel +from pydantic import AnyUrl, AwareDatetime, BaseModel, ConfigDict, Field, RootModel class DeploymentConfigOutputFormat(StrEnum): @@ -309,7 +309,7 @@ class GatewayProvider(StrEnum): OPENAI_COMPATIBLE = "OPENAI_COMPATIBLE" -class GetVolumesRequest(BaseModel): +class GetVolumesParams(BaseModel): cursor: Annotated[ str | None, Field( @@ -335,7 +335,7 @@ class GetVolumesRequest(BaseModel): ] -class GetVolumesNamespacesRequest(BaseModel): +class GetVolumesNamespacesParams(BaseModel): cursor: Annotated[ str | None, Field( @@ -354,17 +354,40 @@ class GetVolumesNamespacesRequest(BaseModel): ] = 100 -class GetVolumesVersionsRequest(BaseModel): +class GetVolumesSyncsParams(BaseModel): + cursor: Annotated[ + str | None, + Field( + description="Opaque cursor returned by a previous page. Omit to fetch the first page.", + title="Cursor", + ), + ] = None + limit: Annotated[ + int, + Field( + description="Maximum number of items to return.", + ge=1, + le=1000, + title="Limit", + ), + ] = 100 + ref: Annotated[ + str | None, + Field(description="Exact destination reference to match.", title="Ref"), + ] = None + + +class GetVolumesVersionsParams(BaseModel): include_tombstoned: Annotated[ bool, Field( - description="Whether to include deleted versions. A deleted version carries a TOMBSTONED lifecycle and stays restorable until its recovery deadline passes.", + description="Whether to include deleted and expired versions. Such a version carries a TOMBSTONED lifecycle and stays restorable until its recovery deadline passes.", title="Include Tombstoned", ), ] = False -class GetTeamsRequest(BaseModel): +class GetTeamsParams(BaseModel): name: Annotated[ str | None, Field( @@ -374,7 +397,7 @@ class GetTeamsRequest(BaseModel): ] = None -class GetModelsRequest(BaseModel): +class GetModelsParams(BaseModel): name: Annotated[ str | None, Field( @@ -384,7 +407,7 @@ class GetModelsRequest(BaseModel): ] = None -class GetTeamsModelsRequest(BaseModel): +class GetTeamsModelsParams(BaseModel): name: Annotated[ str | None, Field( @@ -394,7 +417,7 @@ class GetTeamsModelsRequest(BaseModel): ] = None -class GetModelsDeploymentsRequest(BaseModel): +class GetModelsDeploymentsParams(BaseModel): name: Annotated[ str | None, Field( @@ -404,7 +427,7 @@ class GetModelsDeploymentsRequest(BaseModel): ] = None -class GetModelsDeploymentsConfigRequest(BaseModel): +class GetModelsDeploymentsConfigParams(BaseModel): output_format: Annotated[ DeploymentConfigOutputFormat, Field( @@ -469,7 +492,7 @@ class SearchPattern(RootModel[str]): ] = None -class GetTrainingProjectsJobsMetricsRequest(BaseModel): +class GetTrainingProjectsJobsMetricsParams(BaseModel): end_epoch_millis: Annotated[ int | None, Field( @@ -493,7 +516,7 @@ class GetTrainingProjectsJobsMetricsRequest(BaseModel): ] = None -class GetTrainingProjectsJobsCheckpointFilesRequest(BaseModel): +class GetTrainingProjectsJobsCheckpointFilesParams(BaseModel): page_size: Annotated[ int, Field( @@ -510,7 +533,19 @@ class GetTrainingProjectsJobsCheckpointFilesRequest(BaseModel): ] = 0 -class GetLoopsRunsRequest(BaseModel): +class MaxSeqLen(RootModel[int]): + root: Annotated[ + int | None, + Field( + description="The sequence length the caller intends to train at — the same value they would pass as 'max_seq_len' when creating the run. Models that cannot serve it are reported as not enabled rather than returned with a ceiling the caller cannot use. Omit for the model's highest enabled sequence length.", + examples=[32768], + ge=1, + title="Max Seq Len", + ), + ] = None + + +class GetLoopsRunsParams(BaseModel): run_id: Annotated[ str | None, Field(description="Filter by run ID.", examples=["k4q95w5"], title="Run Id"), @@ -533,7 +568,7 @@ class GetLoopsRunsRequest(BaseModel): ] = None -class GetLoopsSamplersRequest(BaseModel): +class GetLoopsSamplersParams(BaseModel): scope: Annotated[ str | None, Field( @@ -544,7 +579,7 @@ class GetLoopsSamplersRequest(BaseModel): ] = None -class GetLoopsCheckpointsRequest(BaseModel): +class GetLoopsCheckpointsParams(BaseModel): run_id: Annotated[ str | None, Field( @@ -571,7 +606,7 @@ class GetLoopsCheckpointsRequest(BaseModel): ] = None -class GetLoopsCheckpointsFilesRequest(BaseModel): +class GetLoopsCheckpointsFilesParams(BaseModel): page_size: Annotated[ int, Field( @@ -588,7 +623,7 @@ class GetLoopsCheckpointsFilesRequest(BaseModel): ] = 0 -class GetLoopsDeploymentsRequest(BaseModel): +class GetLoopsDeploymentsParams(BaseModel): scope: Annotated[ str | None, Field( @@ -599,7 +634,7 @@ class GetLoopsDeploymentsRequest(BaseModel): ] = None -class GetLoopsDeploymentsDebugArchiveFilesRequest(BaseModel): +class GetLoopsDeploymentsDebugArchiveFilesParams(BaseModel): page_size: Annotated[ int, Field( @@ -615,7 +650,7 @@ class GetLoopsDeploymentsDebugArchiveFilesRequest(BaseModel): ] = None -class GetTeamsLoopsRunsRequest(BaseModel): +class GetTeamsLoopsRunsParams(BaseModel): run_id: Annotated[ str | None, Field(description="Filter by run ID.", examples=["k4q95w5"], title="Run Id"), @@ -638,7 +673,7 @@ class GetTeamsLoopsRunsRequest(BaseModel): ] = None -class GetTeamsLoopsSamplersRequest(BaseModel): +class GetTeamsLoopsSamplersParams(BaseModel): scope: Annotated[ str | None, Field( @@ -649,7 +684,20 @@ class GetTeamsLoopsSamplersRequest(BaseModel): ] = None -class GetModelApisRequest(BaseModel): +class GetApiKeysParams(BaseModel): + type: Annotated[ + APIKeyCategory | None, Field(description="Filter by API key type") + ] = None + created_by_me: Annotated[ + bool, + Field( + description="Return only keys created by the authenticated user", + title="Created By Me", + ), + ] = False + + +class GetModelApisParams(BaseModel): cursor: Annotated[ str | None, Field( @@ -675,7 +723,7 @@ class GetModelApisRequest(BaseModel): ] = False -class GetBillingUsageSummaryRequest(BaseModel): +class GetBillingUsageSummaryParams(BaseModel): start_date: Annotated[ AwareDatetime, Field( @@ -692,7 +740,24 @@ class GetBillingUsageSummaryRequest(BaseModel): ] -class GetUsersRequest(BaseModel): +class GetBillingToolCallUsageParams(BaseModel): + start_date: Annotated[ + date_aliased, + Field( + description="Inclusive UTC calendar day at the start of the query range.", + title="Start Date", + ), + ] + end_date: Annotated[ + date_aliased | None, + Field( + description="Exclusive UTC calendar day at the end of the query range. Defaults to the day after the current UTC date so current-day usage is included. The date range cannot exceed 90 days.", + title="End Date", + ), + ] = None + + +class GetUsersParams(BaseModel): cursor: Annotated[ str | None, Field( @@ -730,7 +795,7 @@ class Limit5(RootModel[int]): ] = None -class GetGatewayEventsRequest(BaseModel): +class GetGatewayEventsParams(BaseModel): start_time: Annotated[ AwareDatetime | None, Field( @@ -772,6 +837,137 @@ class GetGatewayEventsRequest(BaseModel): ] = None +class GetExploreMetadataParams(BaseModel): + cursor: Annotated[ + str | None, + Field( + description="Opaque cursor returned by a previous page. Omit to fetch the first page.", + title="Cursor", + ), + ] = None + limit: Annotated[ + int, + Field( + description="Maximum number of items to return.", + ge=1, + le=1000, + title="Limit", + ), + ] = 100 + provider: Annotated[ + str | None, + Field( + description="Filter to a provider by slug prefix, e.g. 'anthropic'. Preserved by the cursor; if repeated, must match the original filter.", + title="Provider", + ), + ] = None + q: Annotated[ + str | None, + Field( + description="Case-insensitive substring search over metadata slugs. Preserved by the cursor; if repeated, must match the original filter.", + title="Q", + ), + ] = None + + +class GetRoutesParams(BaseModel): + cursor: Annotated[ + str | None, + Field( + description="Opaque cursor returned by a previous page. Omit to fetch the first page.", + title="Cursor", + ), + ] = None + limit: Annotated[ + int, + Field( + description="Maximum number of items to return.", + ge=1, + le=1000, + title="Limit", + ), + ] = 100 + team_id: Annotated[ + str | None, + Field( + description="Filter by owning team ID. Preserved by the cursor; if repeated, must match the original filter.", + title="Team Id", + ), + ] = None + name: Annotated[ + str | None, + Field( + description="Filter by exact route name. Preserved by the cursor; if repeated, must match the original filter.", + title="Name", + ), + ] = None + + +class StatusItem(RootModel[str]): + root: Annotated[str, Field(min_length=1)] + + +class ListSandboxesParams(BaseModel): + q: Annotated[ + str | None, + Field( + description="Search indexed sandbox names and labels. Search is applied before pagination.", + examples=["api-review"], + ), + ] = None + status: Annotated[ + list[StatusItem] | None, + Field( + description="Deployment statuses. Repeat the query parameter for each status, for example status=DEPLOYED&status=FAILED. Unknown values are rejected. Cannot be combined with external_id.", + examples=[["DEPLOYED", "FAILED"]], + min_length=1, + ), + ] = None + external_id: Annotated[ + str | None, + Field( + description="Filter by a caller-owned external identifier. Cannot be combined with status.", + examples=["api-review-20260916-001"], + ), + ] = None + + +class ListImagesParams(BaseModel): + sort: Annotated[ + str, + Field( + description="Sort by repository name or creation time: name:asc, name:desc, createdAt:asc, or createdAt:desc. Keep the same sort when following a cursor." + ), + ] = "createdAt:desc" + q: Annotated[ + str | None, + Field( + description="Case-sensitive repository name prefix. Search is applied before pagination." + ), + ] = None + + +class ListImageTagsParams(BaseModel): + sort: Annotated[ + str, + Field( + description="Sort by tag name: name:asc or name:desc. Keep the same sort when following a cursor." + ), + ] = "name:asc" + q: Annotated[ + str | None, + Field( + description="Case-sensitive tag name prefix. Cannot be combined with name. Forces ascending name order." + ), + ] = None + name: Annotated[ + str | None, + Field( + description="Exact tag name. Cannot be combined with q. Forces ascending name order." + ), + ] = None + + class PaginationResponse(BaseModel): has_more: Annotated[ bool, @@ -799,6 +995,13 @@ class VolumeTag(BaseModel): title="Digest", ), ] + expires_at: Annotated[ + AwareDatetime | None, + Field( + description="When the tag stops resolving and leaves the volume, in ISO 8601 format. Null for a tag that never expires. The version it points at is not affected.", + title="Expires At", + ), + ] class VolumeVersionSummary(BaseModel): @@ -929,186 +1132,474 @@ class ListVolumeNamespacesResponse(BaseModel): ] -class DeleteVolumeRequest(BaseModel): - expected_sequence: Annotated[ - int | None, +class VolumeSyncAuthenticationAWSAssumeRole(BaseModel): + model_config = ConfigDict( + extra="forbid", + ) + role_arn: Annotated[ + str, Field( - description="Revision the volume is expected to be at. When set, the delete fails with a conflict if the volume has changed since, so it cannot act on a volume someone else has pushed to. Take the value from a volume's sequence, or from volume_sequence.", - title="Expected Sequence", + description="AWS IAM role ARN to assume.", min_length=1, title="Role Arn" ), - ] = None - - -class DeleteVolumeResponse(BaseModel): - namespace: Annotated[ + ] + region: Annotated[ str, Field( - description="Namespace the volume belongs to, in lowercase.", - title="Namespace", + description="AWS region for the assumed role session.", + min_length=1, + title="Region", ), ] - name: Annotated[ - str, Field(description="Name of the volume, in lowercase.", title="Name") - ] - versions_deleted: Annotated[ - int, + + +class VolumeSyncAuthenticationAWSOIDC(BaseModel): + model_config = ConfigDict( + extra="forbid", + ) + role_arn: Annotated[ + str, Field( - description="Number of versions this request deleted. Zero when the volume had no live versions left, which is not an error.", - title="Versions Deleted", + description="AWS IAM role ARN to assume through OIDC.", + min_length=1, + title="Role Arn", ), ] - volume_sequence: Annotated[ - int, + region: Annotated[ + str, Field( - description="Revision of the volume after the delete.", - title="Volume Sequence", + description="AWS region for the OIDC role session.", + min_length=1, + title="Region", ), ] -class VolumeVersion(BaseModel): - namespace: Annotated[ +class VolumeSyncAuthenticationGCPOIDC(BaseModel): + model_config = ConfigDict( + extra="forbid", + ) + service_account: Annotated[ str, Field( - description="Namespace the volume belongs to, in lowercase.", - title="Namespace", + description="GCP service account to impersonate through OIDC.", + min_length=1, + title="Service Account", ), ] - volume: Annotated[ - str, Field(description="Name of the volume, in lowercase.", title="Volume") - ] - version_ref: Annotated[ + workload_identity_provider: Annotated[ str, Field( - description="Full address of this version, as `bdn:/@`. Paste this into the `bdn.mounts` section of a config.yaml to pin to it.", - title="Version Ref", + description="Full resource name of the GCP workload identity provider.", + min_length=1, + title="Workload Identity Provider", ), ] - digest: Annotated[ + + +class VolumeSyncDestination(BaseModel): + model_config = ConfigDict( + extra="forbid", + ) + ref: Annotated[ str, Field( - description="Content digest of the version, as `b3:`.", title="Digest" + description="Destination as bdn:/ with an optional tag.", + title="Ref", ), ] - sequence: Annotated[ - int | None, + + +class VolumeSyncError(BaseModel): + code: Annotated[ + str, Field( - description="Revision the version was committed at. Null for versions committed before the volume service recorded it.", - title="Sequence", + description="Stable machine-readable failure classification.", title="Code" ), ] - lifecycle: Annotated[ - str, + message: Annotated[ + str, Field(description="Redacted user-facing failure message.", title="Message") + ] + + +class AuthSecretName(RootModel[str]): + root: Annotated[ + str | None, Field( - description="Lifecycle state of the version, for example ALIVE or TOMBSTONED.", - title="Lifecycle", + description="Optional workspace secret containing credentials for this source.", + min_length=1, + title="Auth Secret Name", ), - ] - is_head: Annotated[ - bool, + ] = None + + +class VolumeSyncSourceAzure(BaseModel): + model_config = ConfigDict( + extra="forbid", + ) + uri: Annotated[ + str, Field( - description="Whether the reserved `head` tag points at this version.", - title="Is Head", + description="Remote source URI to materialize into the destination volume.", + title="Uri", ), ] - tags: Annotated[ - list[str], + include: Annotated[ + list[str] | None, + Field(description="Glob patterns selecting files to include.", title="Include"), + ] = None + exclude: Annotated[ + list[str] | None, + Field(description="Glob patterns selecting files to exclude.", title="Exclude"), + ] = None + auth_secret_name: Annotated[ + AuthSecretName | None, Field( - description="Tags pointing at this version that your API key can read.", - title="Tags", + description="Optional workspace secret containing credentials for this source.", + title="Auth Secret Name", ), + ] = None + type: Annotated[ + Literal["AZURE"], + Field(description="Azure Blob Storage source type.", title="Type"), ] - total_size_bytes: Annotated[ - int | None, + + +class VolumeSyncSourceBasetenTraining(BaseModel): + model_config = ConfigDict( + extra="forbid", + ) + uri: Annotated[ + str, Field( - description="Total size of the version's files in bytes. Null when not recorded.", - title="Total Size Bytes", + description="Remote source URI to materialize into the destination volume.", + title="Uri", ), ] - created_at: Annotated[ - AwareDatetime, + include: Annotated[ + list[str] | None, + Field(description="Glob patterns selecting files to include.", title="Include"), + ] = None + exclude: Annotated[ + list[str] | None, + Field(description="Glob patterns selecting files to exclude.", title="Exclude"), + ] = None + type: Annotated[ + Literal["BASETEN_TRAINING"], + Field(description="Baseten training artifact source type.", title="Type"), + ] + + +class VolumeSyncSourceCoreWeave(BaseModel): + model_config = ConfigDict( + extra="forbid", + ) + uri: Annotated[ + str, Field( - description="When the version was committed, in ISO 8601 format.", - title="Created At", + description="Remote source URI to materialize into the destination volume.", + title="Uri", ), ] - tombstoned_at: Annotated[ - AwareDatetime | None, + include: Annotated[ + list[str] | None, + Field(description="Glob patterns selecting files to include.", title="Include"), + ] = None + exclude: Annotated[ + list[str] | None, + Field(description="Glob patterns selecting files to exclude.", title="Exclude"), + ] = None + auth_secret_name: Annotated[ + AuthSecretName | None, Field( - description="When the version was deleted, in ISO 8601 format. Null unless the lifecycle is TOMBSTONED.", - title="Tombstoned At", + description="Optional workspace secret containing credentials for this source.", + title="Auth Secret Name", ), + ] = None + type: Annotated[ + Literal["COREWEAVE"], + Field(description="CoreWeave object storage source type.", title="Type"), ] - delete_after: Annotated[ - AwareDatetime | None, + + +class VolumeSyncSourceGCS(BaseModel): + model_config = ConfigDict( + extra="forbid", + ) + uri: Annotated[ + str, Field( - description="When the version stops being restorable, in ISO 8601 format. Null unless the lifecycle is TOMBSTONED.", - title="Delete After", + description="Remote source URI to materialize into the destination volume.", + title="Uri", + ), + ] + include: Annotated[ + list[str] | None, + Field(description="Glob patterns selecting files to include.", title="Include"), + ] = None + exclude: Annotated[ + list[str] | None, + Field(description="Glob patterns selecting files to exclude.", title="Exclude"), + ] = None + auth_secret_name: Annotated[ + AuthSecretName | None, + Field( + description="Optional workspace secret containing credentials for this source.", + title="Auth Secret Name", ), + ] = None + type: Annotated[ + Literal["GCS"], + Field(description="Google Cloud Storage source type.", title="Type"), ] + gcp_oidc: Annotated[ + VolumeSyncAuthenticationGCPOIDC | None, + Field( + description="GCP OIDC authentication for this source. Cannot be combined with auth_secret_name." + ), + ] = None -class ListVolumeVersionsResponse(BaseModel): - versions: Annotated[ - list[VolumeVersion], - Field(description="Versions of the volume, newest first.", title="Versions"), +class VolumeSyncSourceHuggingFace(BaseModel): + model_config = ConfigDict( + extra="forbid", + ) + uri: Annotated[ + str, + Field( + description="Remote source URI to materialize into the destination volume.", + title="Uri", + ), ] - volume_sequence: Annotated[ - int, + include: Annotated[ + list[str] | None, + Field(description="Glob patterns selecting files to include.", title="Include"), + ] = None + exclude: Annotated[ + list[str] | None, + Field(description="Glob patterns selecting files to exclude.", title="Exclude"), + ] = None + auth_secret_name: Annotated[ + AuthSecretName | None, Field( - description="Revision of the volume as a whole when the versions were read. Pass it as expected_sequence on a later delete to make that delete conditional on the volume not having changed since. Distinct from the per-version sequence, which is the revision a version was committed at.", - title="Volume Sequence", + description="Optional workspace secret containing credentials for this source.", + title="Auth Secret Name", ), + ] = None + type: Annotated[ + Literal["HUGGING_FACE"], + Field(description="Hugging Face source type.", title="Type"), ] -class DeleteVolumeVersionRequest(BaseModel): - expected_sequence: Annotated[ - int | None, +class VolumeSyncSourceR2(BaseModel): + model_config = ConfigDict( + extra="forbid", + ) + uri: Annotated[ + str, Field( - description="Revision the volume is expected to be at. When set, the delete fails with a conflict if the volume has changed since, so a read followed by a delete cannot act on a version a tag has since been moved off. Take the value from volume_sequence.", - title="Expected Sequence", + description="Remote source URI to materialize into the destination volume.", + title="Uri", + ), + ] + include: Annotated[ + list[str] | None, + Field(description="Glob patterns selecting files to include.", title="Include"), + ] = None + exclude: Annotated[ + list[str] | None, + Field(description="Glob patterns selecting files to exclude.", title="Exclude"), + ] = None + auth_secret_name: Annotated[ + AuthSecretName | None, + Field( + description="Optional workspace secret containing credentials for this source.", + title="Auth Secret Name", ), ] = None + type: Annotated[ + Literal["R2"], Field(description="Cloudflare R2 source type.", title="Type") + ] -class DeleteVolumeVersionResponse(BaseModel): - namespace: Annotated[ +class VolumeSyncSourceS3(BaseModel): + model_config = ConfigDict( + extra="forbid", + ) + uri: Annotated[ str, Field( - description="Namespace the volume belongs to, in lowercase.", - title="Namespace", + description="Remote source URI to materialize into the destination volume.", + title="Uri", ), ] - volume: Annotated[ - str, Field(description="Name of the volume, in lowercase.", title="Volume") + include: Annotated[ + list[str] | None, + Field(description="Glob patterns selecting files to include.", title="Include"), + ] = None + exclude: Annotated[ + list[str] | None, + Field(description="Glob patterns selecting files to exclude.", title="Exclude"), + ] = None + auth_secret_name: Annotated[ + AuthSecretName | None, + Field( + description="Optional workspace secret containing credentials for this source.", + title="Auth Secret Name", + ), + ] = None + type: Annotated[ + Literal["S3"], Field(description="Amazon S3 source type.", title="Type") + ] + aws_assume_role: Annotated[ + VolumeSyncAuthenticationAWSAssumeRole | None, + Field( + description="AWS AssumeRole authentication for this source. Cannot be combined with auth_secret_name." + ), + ] = None + aws_oidc: Annotated[ + VolumeSyncAuthenticationAWSOIDC | None, + Field( + description="AWS OIDC authentication for this source. Cannot be combined with other authentication fields." + ), + ] = None + + +class VolumeSyncStatus(StrEnum): + PENDING = "PENDING" + SYNCING = "SYNCING" + READY = "READY" + FAILED = "FAILED" + CANCELED = "CANCELED" + + +class VolumeSync(BaseModel): + sync_id: Annotated[ + str, Field(description="Identifier of this sync operation.", title="Sync Id") + ] + status: Annotated[ + VolumeSyncStatus, Field(description="Current lifecycle state of the sync.") + ] + source: Annotated[ + VolumeSyncSourceHuggingFace + | VolumeSyncSourceS3 + | VolumeSyncSourceGCS + | VolumeSyncSourceAzure + | VolumeSyncSourceR2 + | VolumeSyncSourceCoreWeave + | VolumeSyncSourceBasetenTraining, + Field( + description="Remote source being synced.", + discriminator="type", + title="Source", + ), ] + destination: Annotated[ + VolumeSyncDestination, Field(description="BDN volume being populated.") + ] + volume_version_id: Annotated[ + str | None, + Field( + description="Produced artifact identifier; null until the sync is ready.", + title="Volume Version Id", + ), + ] = None version_ref: Annotated[ - str, + str | None, Field( - description="Full address of the deleted version, as `bdn:/@`.", + description="Immutable BDN reference; null until the sync is ready.", title="Version Ref", ), + ] = None + content_digest: Annotated[ + str | None, + Field( + description="BLAKE3 digest of the synced content; null until available.", + title="Content Digest", + ), + ] = None + total_size_bytes: Annotated[ + int | None, + Field( + description="Total size of the synced content in bytes; null until available.", + title="Total Size Bytes", + ), + ] = None + created_at: Annotated[ + AwareDatetime, + Field(description="Time at which the sync was created.", title="Created At"), ] - digest: Annotated[ - str, + completed_at: Annotated[ + AwareDatetime | None, Field( - description="Content digest of the deleted version, as `b3:`.", - title="Digest", + description="Time at which the sync reached a terminal state.", + title="Completed At", ), + ] = None + error: Annotated[ + VolumeSyncError | None, + Field(description="Redacted failure details; null unless the sync failed."), + ] = None + + +class VolumeSyncs(BaseModel): + items: Annotated[ + list[VolumeSync], Field(description="Items in this page.", title="Items") ] - lifecycle: Annotated[ + pagination: Annotated[ + PaginationResponse, Field(description="Pagination metadata for the page.") + ] + + +class CreateVolumeSyncRequest(BaseModel): + model_config = ConfigDict( + extra="forbid", + ) + source: Annotated[ + VolumeSyncSourceHuggingFace + | VolumeSyncSourceS3 + | VolumeSyncSourceGCS + | VolumeSyncSourceAzure + | VolumeSyncSourceR2 + | VolumeSyncSourceCoreWeave + | VolumeSyncSourceBasetenTraining, + Field( + description="Remote source to sync from.", + discriminator="type", + title="Source", + ), + ] + destination: Annotated[ + VolumeSyncDestination, Field(description="BDN volume to sync into.") + ] + + +class DeleteVolumeRequest(BaseModel): + expected_sequence: Annotated[ + int | None, + Field( + description="Revision the volume is expected to be at. When set, the delete fails with a conflict if the volume has changed since, so it cannot act on a volume someone else has pushed to. Take the value from a volume's sequence, or from volume_sequence.", + title="Expected Sequence", + ), + ] = None + + +class DeleteVolumeResponse(BaseModel): + namespace: Annotated[ str, Field( - description="Lifecycle state of the version after the delete.", - title="Lifecycle", + description="Namespace the volume belongs to, in lowercase.", + title="Namespace", ), ] - delete_after: Annotated[ - AwareDatetime, + name: Annotated[ + str, Field(description="Name of the volume, in lowercase.", title="Name") + ] + versions_deleted: Annotated[ + int, Field( - description="When the version stops being restorable, in ISO 8601 format. Until then it can be returned to service.", - title="Delete After", + description="Number of versions this request deleted. Zero when the volume had no live versions left, which is not an error.", + title="Versions Deleted", ), ] volume_sequence: Annotated[ @@ -1120,7 +1611,7 @@ class DeleteVolumeVersionResponse(BaseModel): ] -class VolumeVersionDetail(BaseModel): +class VolumeVersion(BaseModel): namespace: Annotated[ str, Field( @@ -1154,7 +1645,7 @@ class VolumeVersionDetail(BaseModel): lifecycle: Annotated[ str, Field( - description="Lifecycle state of the version, for example ALIVE or TOMBSTONED.", + description="Lifecycle state of the version: ALIVE, or TOMBSTONED once it has been deleted or has expired.", title="Lifecycle", ), ] @@ -1186,10 +1677,17 @@ class VolumeVersionDetail(BaseModel): title="Created At", ), ] + expires_at: Annotated[ + AwareDatetime | None, + Field( + description="When the version expires, in ISO 8601 format. At that instant it becomes TOMBSTONED with `tombstoned_at` set to this value, and every tag pointing at it drops. Null for a version that never expires, and null once the lifecycle is TOMBSTONED.", + title="Expires At", + ), + ] tombstoned_at: Annotated[ AwareDatetime | None, Field( - description="When the version was deleted, in ISO 8601 format. Null unless the lifecycle is TOMBSTONED.", + description="When the version was deleted or expired, in ISO 8601 format. Null unless the lifecycle is TOMBSTONED.", title="Tombstoned At", ), ] @@ -1200,33 +1698,194 @@ class VolumeVersionDetail(BaseModel): title="Delete After", ), ] - entry_count: Annotated[ - int | None, - Field( - description="Number of files in the version. Null when not recorded.", - title="Entry Count", - ), + + +class ListVolumeVersionsResponse(BaseModel): + versions: Annotated[ + list[VolumeVersion], + Field(description="Versions of the volume, newest first.", title="Versions"), ] volume_sequence: Annotated[ int, Field( - description="Revision of the volume as a whole when this version was read. Pass it as expected_sequence on a later delete to make that delete conditional on the volume not having changed since.", + description="Revision of the volume as a whole when the versions were read. Pass it as expected_sequence on a later delete to make that delete conditional on the volume not having changed since. Distinct from the per-version sequence, which is the revision a version was committed at.", title="Volume Sequence", ), ] -class RestoreVolumeVersionRequest(BaseModel): +class DeleteVolumeVersionRequest(BaseModel): expected_sequence: Annotated[ int | None, Field( - description="Revision the volume is expected to be at. When set, the restore fails with a conflict if the volume has changed since. Take the value from volume_sequence.", + description="Revision the volume is expected to be at. When set, the delete fails with a conflict if the volume has changed since, so a read followed by a delete cannot act on a version a tag has since been moved off. Take the value from volume_sequence.", title="Expected Sequence", ), ] = None -class RestoreVolumeVersionResponse(BaseModel): +class DeleteVolumeVersionResponse(BaseModel): + namespace: Annotated[ + str, + Field( + description="Namespace the volume belongs to, in lowercase.", + title="Namespace", + ), + ] + volume: Annotated[ + str, Field(description="Name of the volume, in lowercase.", title="Volume") + ] + version_ref: Annotated[ + str, + Field( + description="Full address of the deleted version, as `bdn:/@`.", + title="Version Ref", + ), + ] + digest: Annotated[ + str, + Field( + description="Content digest of the deleted version, as `b3:`.", + title="Digest", + ), + ] + lifecycle: Annotated[ + str, + Field( + description="Lifecycle state of the version after the delete.", + title="Lifecycle", + ), + ] + delete_after: Annotated[ + AwareDatetime, + Field( + description="When the version stops being restorable, in ISO 8601 format. Until then it can be returned to service.", + title="Delete After", + ), + ] + volume_sequence: Annotated[ + int, + Field( + description="Revision of the volume after the delete.", + title="Volume Sequence", + ), + ] + + +class VolumeVersionDetail(BaseModel): + namespace: Annotated[ + str, + Field( + description="Namespace the volume belongs to, in lowercase.", + title="Namespace", + ), + ] + volume: Annotated[ + str, Field(description="Name of the volume, in lowercase.", title="Volume") + ] + version_ref: Annotated[ + str, + Field( + description="Full address of this version, as `bdn:/@`. Paste this into the `bdn.mounts` section of a config.yaml to pin to it.", + title="Version Ref", + ), + ] + digest: Annotated[ + str, + Field( + description="Content digest of the version, as `b3:`.", title="Digest" + ), + ] + sequence: Annotated[ + int | None, + Field( + description="Revision the version was committed at. Null for versions committed before the volume service recorded it.", + title="Sequence", + ), + ] + lifecycle: Annotated[ + str, + Field( + description="Lifecycle state of the version: ALIVE, or TOMBSTONED once it has been deleted or has expired.", + title="Lifecycle", + ), + ] + is_head: Annotated[ + bool, + Field( + description="Whether the reserved `head` tag points at this version.", + title="Is Head", + ), + ] + tags: Annotated[ + list[str], + Field( + description="Tags pointing at this version that your API key can read.", + title="Tags", + ), + ] + total_size_bytes: Annotated[ + int | None, + Field( + description="Total size of the version's files in bytes. Null when not recorded.", + title="Total Size Bytes", + ), + ] + created_at: Annotated[ + AwareDatetime, + Field( + description="When the version was committed, in ISO 8601 format.", + title="Created At", + ), + ] + expires_at: Annotated[ + AwareDatetime | None, + Field( + description="When the version expires, in ISO 8601 format. At that instant it becomes TOMBSTONED with `tombstoned_at` set to this value, and every tag pointing at it drops. Null for a version that never expires, and null once the lifecycle is TOMBSTONED.", + title="Expires At", + ), + ] + tombstoned_at: Annotated[ + AwareDatetime | None, + Field( + description="When the version was deleted or expired, in ISO 8601 format. Null unless the lifecycle is TOMBSTONED.", + title="Tombstoned At", + ), + ] + delete_after: Annotated[ + AwareDatetime | None, + Field( + description="When the version stops being restorable, in ISO 8601 format. Null unless the lifecycle is TOMBSTONED.", + title="Delete After", + ), + ] + entry_count: Annotated[ + int | None, + Field( + description="Number of files in the version. Null when not recorded.", + title="Entry Count", + ), + ] + volume_sequence: Annotated[ + int, + Field( + description="Revision of the volume as a whole when this version was read. Pass it as expected_sequence on a later delete to make that delete conditional on the volume not having changed since.", + title="Volume Sequence", + ), + ] + + +class RestoreVolumeVersionRequest(BaseModel): + expected_sequence: Annotated[ + int | None, + Field( + description="Revision the volume is expected to be at. When set, the restore fails with a conflict if the volume has changed since. Take the value from volume_sequence.", + title="Expected Sequence", + ), + ] = None + + +class RestoreVolumeVersionResponse(BaseModel): namespace: Annotated[ str, Field( @@ -1267,6 +1926,39 @@ class RestoreVolumeVersionResponse(BaseModel): ] +class TokenScope(StrEnum): + sandboxes = "sandboxes" + + +class CreateTokenRequest(BaseModel): + scopes: Annotated[ + list[TokenScope], + Field( + description="What the token should grant access to. Only `sandboxes` is supported today; the token then authenticates against the sandbox API.", + examples=[["sandboxes"]], + min_length=1, + title="Scopes", + ), + ] + + +class Token(BaseModel): + token: Annotated[ + str, + Field( + description="Short-lived bearer token for the sandbox API. Send it as Authorization: Bearer .", + title="Token", + ), + ] + expires_at: Annotated[ + AwareDatetime, + Field( + description="Token expiry in ISO 8601 format. Tokens cannot be renewed; request a new one.", + title="Expires At", + ), + ] + + class Secret(BaseModel): id: Annotated[ str, @@ -2230,6 +2922,52 @@ class AuditLogEventModelDeploymentRetried(BaseModel): retried: Annotated[bool, Field(title="Retried")] +class AuditLogEventModelRenamed(BaseModel): + model_config = ConfigDict( + extra="forbid", + ) + event_type: Annotated[Literal["MODEL_RENAMED"], Field(title="Event Type")] + model_id: Annotated[str, Field(title="Model Id")] + model_name: Annotated[str, Field(title="Model Name")] + previous_name: Annotated[str | None, Field(title="Previous Name")] + + +class AuditLogEventProviderConnectionCreated(BaseModel): + model_config = ConfigDict( + extra="forbid", + ) + event_type: Annotated[ + Literal["PROVIDER_CONNECTION_CREATED"], Field(title="Event Type") + ] + provider_connection_id: Annotated[str, Field(title="Provider Connection Id")] + provider: Annotated[str, Field(title="Provider")] + secret_name: Annotated[str, Field(title="Secret Name")] + + +class AuditLogEventProviderConnectionDeleted(BaseModel): + model_config = ConfigDict( + extra="forbid", + ) + event_type: Annotated[ + Literal["PROVIDER_CONNECTION_DELETED"], Field(title="Event Type") + ] + provider_connection_id: Annotated[str, Field(title="Provider Connection Id")] + provider: Annotated[str, Field(title="Provider")] + secret_name: Annotated[str, Field(title="Secret Name")] + + +class AuditLogEventProviderConnectionUpdated(BaseModel): + model_config = ConfigDict( + extra="forbid", + ) + event_type: Annotated[ + Literal["PROVIDER_CONNECTION_UPDATED"], Field(title="Event Type") + ] + provider_connection_id: Annotated[str, Field(title="Provider Connection Id")] + provider: Annotated[str, Field(title="Provider")] + secret_name: Annotated[str, Field(title="Secret Name")] + + class AuditLogEventReplicaTerminated(BaseModel): model_config = ConfigDict( extra="forbid", @@ -2298,6 +3036,7 @@ class AuditLogEventType(StrEnum): MODEL_DEPLOYMENT_INSTANCE_TYPE_CHANGED = "MODEL_DEPLOYMENT_INSTANCE_TYPE_CHANGED" MODEL_DEPLOYMENT_DELETED = "MODEL_DEPLOYMENT_DELETED" MODEL_DELETED = "MODEL_DELETED" + MODEL_RENAMED = "MODEL_RENAMED" CHAIN_DEPLOYED = "CHAIN_DEPLOYED" CHAIN_DEPLOYMENT_ACTIVATED = "CHAIN_DEPLOYMENT_ACTIVATED" CHAIN_DEPLOYMENT_DEACTIVATED = "CHAIN_DEPLOYMENT_DEACTIVATED" @@ -2315,6 +3054,9 @@ class AuditLogEventType(StrEnum): GATEWAY_ENDPOINT_CREATED = "GATEWAY_ENDPOINT_CREATED" GATEWAY_ENDPOINT_UPDATED = "GATEWAY_ENDPOINT_UPDATED" GATEWAY_ENDPOINT_DELETED = "GATEWAY_ENDPOINT_DELETED" + PROVIDER_CONNECTION_CREATED = "PROVIDER_CONNECTION_CREATED" + PROVIDER_CONNECTION_UPDATED = "PROVIDER_CONNECTION_UPDATED" + PROVIDER_CONNECTION_DELETED = "PROVIDER_CONNECTION_DELETED" USER_INVITED = "USER_INVITED" USER_JOINED_ORGANIZATION = "USER_JOINED_ORGANIZATION" WEBHOOK_SIGNING_SECRET_CREATED = "WEBHOOK_SIGNING_SECRET_CREATED" @@ -2477,9 +3219,11 @@ class AuditLogEventTypeGroup(StrEnum): ENVIRONMENT_SETTINGS = "ENVIRONMENT_SETTINGS" REPLICA_TERMINATED = "REPLICA_TERMINATED" DELETED = "DELETED" + METADATA = "METADATA" SECRETS = "SECRETS" API_KEYS = "API_KEYS" GATEWAY = "GATEWAY" + CODE = "CODE" WEBHOOK_SIGNING_SECRETS = "WEBHOOK_SIGNING_SECRETS" USER_MANAGEMENT = "USER_MANAGEMENT" DIRECTORY_GROUP_MANAGEMENT = "DIRECTORY_GROUP_MANAGEMENT" @@ -2688,6 +3432,33 @@ class ModelTombstone(BaseModel): ] +class Name1(RootModel[str]): + root: Annotated[ + str | None, + Field( + description="New name for the model, unique within its team. Renaming does not change the model ID, endpoints, or deployments. Pushes that still use the old model_name create another model or target a model that now uses that name, so update config.yaml after renaming.", + examples=["my-model"], + max_length=255, + min_length=1, + title="Name", + ), + ] = None + + +class UpdateModelRequest(BaseModel): + model_config = ConfigDict( + extra="forbid", + ) + name: Annotated[ + Name1 | None, + Field( + description="New name for the model, unique within its team. Renaming does not change the model ID, endpoints, or deployments. Pushes that still use the old model_name create another model or target a model that now uses that name, so update config.yaml after renaming.", + examples=["my-model"], + title="Name", + ), + ] = None + + class DeploymentArchiveSource(BaseModel): kind: Annotated[Literal["model_archive"], Field(title="Kind")] = "model_archive" deployment: Annotated[ @@ -2725,7 +3496,7 @@ class DeploymentTombstone(BaseModel): ] -class Name1(RootModel[str]): +class Name2(RootModel[str]): root: Annotated[ str | None, Field( @@ -2743,7 +3514,7 @@ class UpdateDeploymentRequest(BaseModel): extra="forbid", ) name: Annotated[ - Name1 | None, + Name2 | None, Field( description="New name for the deployment, unique among the model's deployments. Only alphanumeric characters, hyphens, underscores, and periods are allowed.", examples=["my-deployment"], @@ -4809,36 +5580,94 @@ class SearchTrainingJobsRequest(BaseModel): ] = [OrderBy.model_validate({"field": "created_at", "order": "desc"})] -class SupportedModel(BaseModel): - model_name: Annotated[ - str, Field(description="The name of the supported model.", title="Model Name") +class EnablementDetails(BaseModel): + reason: Annotated[ + str, + Field( + description="Machine-readable reason the model is not enabled. Currently one of 'needs_approval', 'sequence_length_unsupported' or 'loops_not_enabled'. Deliberately not a closed enum: values are added as the check learns to distinguish cases that call for a different action, so treat an unrecognized value as 'not enabled, reason unknown' rather than an error.", + examples=["needs_approval"], + title="Reason", + ), ] - max_context_length: Annotated[ - int, + reason_detail: Annotated[ + str, Field( - description="The maximum context length (in tokens) supported by this model.", - title="Max Context Length", + description="Human-readable explanation of the reason.", + title="Reason Detail", ), ] - supports_vision_language: Annotated[ - bool, + remediation: Annotated[ + str, Field( - description="Whether the model accepts image inputs alongside text.", - title="Supports Vision Language", + description="Human-readable next step to enable the model.", + title="Remediation", ), ] +class SupportedModel(BaseModel): + model_name: Annotated[ + str, Field(description="The name of the supported model.", title="Model Name") + ] + max_seq_len: Annotated[ + int, + Field( + description="The longest sequence length Baseten supports for this model. Independent of the caller: see 'max_enabled_seq_len' for what this workspace can actually train at. Named to match the 'max_seq_len' query parameter and the field of the same name on run creation, so one name follows the value through the API.", + title="Max Seq Len", + ), + ] + max_enabled_seq_len: Annotated[ + int, + Field( + description="The longest sequence length this workspace can train at. Lower than 'max_seq_len' when the longer configurations need hardware the workspace is not approved for — a model's longer sequence lengths often need a bigger SKU of the same GPU. Zero when the workspace cannot run the model at all, so a client can compare against a required length without a null case.", + title="Max Enabled Seq Len", + ), + ] = 0 + max_context_length: Annotated[ + int, + Field( + deprecated=True, + description="Deprecated. Use 'max_seq_len', which carries the same value. Kept so existing clients keep working.", + title="Max Context Length", + ), + ] + supports_vision_language: Annotated[ + bool, + Field( + description="Whether the model accepts image inputs alongside text.", + title="Supports Vision Language", + ), + ] + enabled: Annotated[ + bool, + Field( + description="Whether this workspace can start a run with this model now. False means Baseten supports it but the workspace cannot use it yet; 'not_enabled' says why. Capacity is resolved when the run is created, so true is not a guarantee that GPUs are free.", + title="Enabled", + ), + ] = True + enablement_details: Annotated[ + EnablementDetails | None, + Field( + description="Why the model is not enabled, and what would change it. Present only when 'enabled' is false — an enabled model has nothing to explain. Read 'enabled' for the state; this is the detail behind it." + ), + ] = None + + class GetLoopsCapabilitiesResponse(BaseModel): supported_models: Annotated[ list[SupportedModel], Field( - description="List of models available on the server.", + description="Models Baseten supports for this use case, each carrying an 'enabled' flag saying whether this workspace can run it now, and 'enablement_details' when it cannot. Filter on 'enabled' to get the models you can use.", title="Supported Models", ), ] +class LoopsUseCase(StrEnum): + rl = "rl" + sft = "sft" + + class LoopsSession(BaseModel): id: Annotated[str, Field(title="Id")] @@ -4912,7 +5741,7 @@ class LoopsSampler(BaseModel): ] = 1 -class Name2(RootModel[str]): +class Name3(RootModel[str]): root: Annotated[ str | None, Field( @@ -4937,7 +5766,7 @@ class CreateLoopsRunRequest(BaseModel): Field(description="Base model ID (e.g. 'Qwen/Qwen3-8B').", title="Base Model"), ] name: Annotated[ - Name2 | None, + Name3 | None, Field( description="Optional display name for the run. Defaults to the base model name when omitted.", title="Name", @@ -5023,6 +5852,12 @@ class ListLoopsSamplersResponse(BaseModel): class CreateLoopsSamplerRequest(BaseModel): + availability_model: Annotated[ + V1AvailabilityModel | None, + Field( + description="Capacity the sampler runs on. 'spot' allows preemption when its GPUs are reclaimed. Defaults to 'dedicated' for standalone samplers. Paired samplers inherit their run's availability model; an explicit value must match it." + ), + ] = None session_id: Annotated[ str, Field( @@ -5174,6 +6009,39 @@ class LoopsCheckpointFilesResponse(BaseModel): ] +class LoopsCheckpointS3Source(BaseModel): + kind: Annotated[Literal["s3"], Field(title="Kind")] = "s3" + + +class LoopsCheckpointVolumeSource(BaseModel): + kind: Annotated[Literal["volume"], Field(title="Kind")] = "volume" + volume_ref: Annotated[ + str, + Field( + description="Ref of the volume version holding the checkpoint, as `bdn:/:`.", + title="Volume Ref", + ), + ] + path: Annotated[ + str, + Field( + description="Directory inside that version holding the checkpoint's files.", + title="Path", + ), + ] + + +class LoopsCheckpointSourceResponse(BaseModel): + source: Annotated[ + LoopsCheckpointS3Source | LoopsCheckpointVolumeSource, + Field( + description="`s3` means the files endpoint serves presigned URLs for this checkpoint; `volume` carries the ref to pull instead.", + discriminator="kind", + title="Source", + ), + ] + + class LoopsDeploymentStatus(BaseModel): name: Annotated[Name, Field(description="Latest status of the Loops deployment.")] @@ -5749,6 +6617,9 @@ class APIKeyTombstone(BaseModel): class LimitType(StrEnum): REQUEST = "REQUEST" TOKEN = "TOKEN" + CONCURRENT_REQUEST = "CONCURRENT_REQUEST" + UNCACHED_INPUT_TOKEN = "UNCACHED_INPUT_TOKEN" + OUTPUT_TOKEN = "OUTPUT_TOKEN" class ModelAPIOrgDetails(BaseModel): @@ -6679,6 +7550,39 @@ class Subtotal8(RootModel[str]): ] +class ToolCallUsageBucket(BaseModel): + date: Annotated[ + date_aliased, + Field(description="UTC day the usage was recorded on.", title="Date"), + ] + provider: Annotated[ + str, + Field(description="Tool provider, such as exa or parallel.", title="Provider"), + ] + sku: Annotated[ + str, + Field( + description="Charge unit, as `/`. The unit is what the provider reported, or the tool name when it reported none. Its meaning varies by provider.", + title="Sku", + ), + ] + model: Annotated[ + str, Field(description="Model that made the tool calls.", title="Model") + ] + calls: Annotated[int, Field(description="Number of tool calls.", title="Calls")] + quantity: Annotated[ + float, + Field( + description="Billable quantity in the provider's sku unit, summed over the calls.", + title="Quantity", + ), + ] + + +class ToolCallUsageResponse(BaseModel): + items: Annotated[list[ToolCallUsageBucket] | None, Field(title="Items")] = None + + class UserInfo(BaseModel): user_id: Annotated[ str, Field(description="Unique identifier for the user", title="User Id") @@ -6787,95 +7691,422 @@ class GatewayEventsResponse(BaseModel): ] -class SharedEndpointRegion(StrEnum): - UNRESTRICTED = "UNRESTRICTED" - EU = "EU" +class ExploreCostValues(BaseModel): + input: Annotated[ + float | None, + Field(description="USD per 1M input tokens, when available.", title="Input"), + ] = None + output: Annotated[ + float | None, + Field(description="USD per 1M output tokens, when available.", title="Output"), + ] = None + cache_read: Annotated[ + float | None, + Field( + description="USD per 1M input tokens read from cache, when available.", + title="Cache Read", + ), + ] = None + cache_write: Annotated[ + float | None, + Field( + description="USD per 1M input tokens written to cache, when available.", + title="Cache Write", + ), + ] = None -class VertexTargetConfig(BaseModel): - project_id: Annotated[ +class ExploreMetadataAPIFormats(BaseModel): + messages: Annotated[ + bool, Field(description="Anthropic Messages API support.", title="Messages") + ] = False + responses: Annotated[ + bool, Field(description="OpenAI Responses API support.", title="Responses") + ] = False + chat_completions: Annotated[ + bool, + Field( + description="OpenAI Chat Completions API support.", title="Chat Completions" + ), + ] = False + + +class RouteTargetAnthropic(BaseModel): + model_config = ConfigDict( + extra="forbid", + ) + type: Annotated[ + Literal["ANTHROPIC"], + Field(description="Target kind for Anthropic.", title="Type"), + ] + model: Annotated[ str, Field( - description="Google Cloud project ID or project number.", - examples=["my-gcp-project", "464036093014"], - title="Project Id", + description="Model name sent to the provider.", min_length=1, title="Model" ), ] - location: Annotated[ + secret_name: Annotated[ str, Field( - description="Google Cloud location.", examples=["global"], title="Location" + description="Name of a credential secret owned by the route's team.", + min_length=1, + title="Secret Name", ), ] -class EndpointTargetRequest(BaseModel): - provider: Annotated[ - GatewayProvider, +class RouteTargetBasetenModelAPI(BaseModel): + model_config = ConfigDict( + extra="forbid", + ) + type: Annotated[ + Literal["BASETEN_MODEL_API"], + Field(description="Target kind for a Baseten Model API.", title="Type"), + ] + model: Annotated[ + str, + Field(description="Name of the target Model API.", min_length=1, title="Model"), + ] + + +class RouteTargetOpenAI(BaseModel): + model_config = ConfigDict( + extra="forbid", + ) + type: Annotated[ + Literal["OPENAI"], Field(description="Target kind for OpenAI.", title="Type") + ] + model: Annotated[ + str, Field( - description="Upstream provider for this target.", - examples=["ANTHROPIC", "OPENAI", "OPENAI_COMPATIBLE", "BASETEN"], + description="Model name sent to the provider.", min_length=1, title="Model" ), ] - secret_id: Annotated[ + secret_name: Annotated[ + str, + Field( + description="Name of a credential secret owned by the route's team.", + min_length=1, + title="Secret Name", + ), + ] + + +class RouteTargetXAI(BaseModel): + model_config = ConfigDict( + extra="forbid", + ) + type: Annotated[ + Literal["XAI"], Field(description="Target kind for xAI.", title="Type") + ] + model: Annotated[ + str, + Field( + description="Model name sent to the provider.", min_length=1, title="Model" + ), + ] + secret_name: Annotated[ + str, + Field( + description="Name of a credential secret owned by the route's team.", + min_length=1, + title="Secret Name", + ), + ] + + +class TeamId1(RootModel[str]): + root: Annotated[ str | None, Field( - description="Secret holding the provider credential. Required for external providers.", - examples=["3kZ9xqd"], - title="Secret Id", + description="Identifier of the team that owns the route. When omitted, uses your organization's default team.", + examples=["abc1234"], + min_length=1, + title="Team Id", ), ] = None - target_model: Annotated[ + + +class DisplayName(RootModel[str]): + root: Annotated[ str | None, Field( - description="Model name to send upstream. Required for external providers and optional for BASETEN targets.", - examples=["gpt-4o"], - title="Target Model", + description="Display label. Omit to use the route name; null is not accepted.", + examples=["Assistant"], + max_length=255, + min_length=1, + title="Display Name", ), ] = None - base_url: Annotated[ + + +class Description(RootModel[str]): + root: Annotated[ str | None, Field( - description="HTTPS base URL of the upstream OpenAI-compatible server. Must not include a port. Required for and only valid with OPENAI_COMPATIBLE.", - examples=["https://my-vllm.example.com"], - title="Base Url", + description="Short description of the route. Omit for no description; null is not accepted.", + examples=["Assistant for code review and debugging."], + max_length=1000, + title="Description", ), ] = None - model_id: Annotated[ - str | None, + + +class CreateRouteRequest(BaseModel): + model_config = ConfigDict( + extra="forbid", + ) + team_id: Annotated[ + TeamId1 | None, Field( - description="Baseten model to route to. Required for and only valid with BASETEN.", - examples=["3kZ9xqd"], - title="Model Id", + description="Identifier of the team that owns the route. When omitted, uses your organization's default team.", + examples=["abc1234"], + title="Team Id", ), ] = None - environment_name: Annotated[ - str | None, + display_name: Annotated[ + DisplayName | None, Field( - description="Baseten model environment to route to. Only valid with BASETEN. Omit or pass `production` to target production.", - examples=["staging"], - title="Environment Name", + description="Display label. Omit to use the route name; null is not accepted.", + examples=["Assistant"], + title="Display Name", ), ] = None - vertex_config: Annotated[ - VertexTargetConfig | None, + target: Annotated[ + RouteTargetBasetenModelAPI + | RouteTargetAnthropic + | RouteTargetOpenAI + | RouteTargetXAI, + Field( + description="Upstream target for the route.", + discriminator="type", + examples=[{"model": "zai-org/GLM-5.3", "type": "BASETEN_MODEL_API"}], + title="Target", + ), + ] + description: Annotated[ + Description | None, Field( - description="Google Vertex configuration. Required for and only valid with VERTEX." + description="Short description of the route. Omit for no description; null is not accepted.", + examples=["Assistant for code review and debugging."], + title="Description", ), ] = None -class CreateEndpointRequest(BaseModel): - slug: Annotated[ +class RouteProvider(StrEnum): + BASETEN_MODEL_API = "BASETEN_MODEL_API" + OPENAI = "OPENAI" + ANTHROPIC = "ANTHROPIC" + XAI = "XAI" + VERTEX = "VERTEX" + OPENAI_COMPATIBLE = "OPENAI_COMPATIBLE" + + +class RoutesUsageResult(BaseModel): + user_id: Annotated[ + str | None, + Field( + description="ID of the user who created the Routes key. Null when not grouping by USER.", + title="User Id", + ), + ] = None + model: Annotated[ + str | None, + Field( + description="Model name. For external providers, the model name sent to the provider. Null when not grouping by MODEL.", + title="Model", + ), + ] = None + provider: Annotated[ + RouteProvider | None, + Field( + description="Provider that served the requests. Null when not grouping by PROVIDER." + ), + ] = None + cost_usd: Annotated[ str, Field( - description="Globally-unique slug of the form '{org_prefix}/{name}'.", - examples=["baseten/mymodel-4"], - title="Slug", + description="Estimated cost in USD, returned as an exact decimal string. Costs for OpenAI, Anthropic, and xAI estimate what you pay those providers; they are not Baseten charges.", + examples=["0.00035625"], + title="Cost Usd", ), ] - region: Annotated[ - SharedEndpointRegion, Field(description="Region the new routing serves.") + input_tokens: Annotated[ + int, + Field( + description="Input tokens, including cached input tokens.", + title="Input Tokens", + ), + ] + cached_input_tokens: Annotated[ + int, + Field( + description="Input tokens read from the prompt cache.", + title="Cached Input Tokens", + ), + ] + uncached_input_tokens: Annotated[ + int, + Field( + description="Input tokens not read from the prompt cache, including tokens written to the cache.", + title="Uncached Input Tokens", + ), + ] + output_tokens: Annotated[ + int, Field(description="Output tokens.", title="Output Tokens") + ] + + +class RouteUsageDimension(StrEnum): + USER = "USER" + MODEL = "MODEL" + PROVIDER = "PROVIDER" + + +class RouteTombstone(BaseModel): + id: Annotated[ + str, Field(description="Stable identifier of the deleted route.", title="Id") + ] + name: Annotated[str, Field(description="Name of the deleted route.", title="Name")] + + +class Description1(RootModel[str]): + root: Annotated[ + str | None, + Field( + description="New description. Omit to keep the current description; use an empty string to clear it. Null is not accepted.", + examples=["Assistant for code review and debugging."], + max_length=1000, + title="Description", + ), + ] = None + + +class DisplayName1(RootModel[str]): + root: Annotated[ + str | None, + Field( + description="New display label. Omit to keep the current label; null is not accepted.", + examples=["Assistant"], + max_length=255, + min_length=1, + title="Display Name", + ), + ] = None + + +class UpdateRouteRequest(BaseModel): + model_config = ConfigDict( + extra="forbid", + ) + description: Annotated[ + Description1 | None, + Field( + description="New description. Omit to keep the current description; use an empty string to clear it. Null is not accepted.", + examples=["Assistant for code review and debugging."], + title="Description", + ), + ] = None + display_name: Annotated[ + DisplayName1 | None, + Field( + description="New display label. Omit to keep the current label; null is not accepted.", + examples=["Assistant"], + title="Display Name", + ), + ] = None + + +class SharedEndpointRegion(StrEnum): + UNRESTRICTED = "UNRESTRICTED" + EU = "EU" + + +class VertexTargetConfig(BaseModel): + project_id: Annotated[ + str, + Field( + description="Google Cloud project ID or project number.", + examples=["my-gcp-project", "464036093014"], + title="Project Id", + ), + ] + location: Annotated[ + str, + Field( + description="Google Cloud location.", examples=["global"], title="Location" + ), + ] + + +class EndpointTargetRequest(BaseModel): + provider: Annotated[ + GatewayProvider, + Field( + description="Upstream provider for this target.", + examples=["ANTHROPIC", "OPENAI", "OPENAI_COMPATIBLE", "BASETEN"], + ), + ] + secret_id: Annotated[ + str | None, + Field( + description="Secret holding the provider credential. Required for external providers.", + examples=["3kZ9xqd"], + title="Secret Id", + ), + ] = None + target_model: Annotated[ + str | None, + Field( + description="Model name to send upstream. Required for external providers and optional for BASETEN targets.", + examples=["gpt-4o"], + title="Target Model", + ), + ] = None + base_url: Annotated[ + str | None, + Field( + description="HTTPS base URL of the upstream OpenAI-compatible server. Must not include a port. Required for and only valid with OPENAI_COMPATIBLE.", + examples=["https://my-vllm.example.com"], + title="Base Url", + ), + ] = None + model_id: Annotated[ + str | None, + Field( + description="Baseten model to route to. Required for and only valid with BASETEN.", + examples=["3kZ9xqd"], + title="Model Id", + ), + ] = None + environment_name: Annotated[ + str | None, + Field( + description="Baseten model environment to route to. Only valid with BASETEN. Omit or pass `production` to target production.", + examples=["staging"], + title="Environment Name", + ), + ] = None + vertex_config: Annotated[ + VertexTargetConfig | None, + Field( + description="Google Vertex configuration. Required for and only valid with VERTEX." + ), + ] = None + + +class CreateEndpointRequest(BaseModel): + slug: Annotated[ + str, + Field( + description="Globally-unique slug of the form '{org_prefix}/{name}'.", + examples=["baseten/mymodel-4"], + title="Slug", + ), + ] + region: Annotated[ + SharedEndpointRegion, Field(description="Region the new routing serves.") ] = SharedEndpointRegion.UNRESTRICTED targets: Annotated[ list[EndpointTargetRequest], @@ -7022,7 +8253,7 @@ class EffectiveRateLimit(BaseModel): ] -class Name3(RootModel[str]): +class Name4(RootModel[str]): root: Annotated[ str | None, Field( @@ -7036,7 +8267,7 @@ class Name3(RootModel[str]): class GroupMetadata(BaseModel): name: Annotated[ - Name3 | None, + Name4 | None, Field( description="Optional display name for the group.", examples=["Acme prod"], @@ -7099,7 +8330,7 @@ class CreateGroupHierarchy(BaseModel): class UpdateGroupMetadata(BaseModel): name: Annotated[ - Name3 | None, + Name4 | None, Field( description="Optional display name for the group.", examples=["Acme prod"], @@ -7177,128 +8408,373 @@ class RegisterAPIKeyResponse(BaseModel): ] -class Checkpoints( - RootModel[ - BasetenLatestCheckpointConfig - | BasetenNamedCheckpointConfig - | LoopsCheckpointConfig - ] -): +class SandboxDuration(RootModel[str]): root: Annotated[ - BasetenLatestCheckpointConfig - | BasetenNamedCheckpointConfig - | LoopsCheckpointConfig, - Field(discriminator="typ"), - ] - - -class LoadCheckpointConfig(BaseModel): - enabled: Annotated[ - bool, - Field(description="Whether checkpoint loading is enabled", title="Enabled"), - ] = False - download_folder: Annotated[ str, Field( - description="Folder where checkpoints will be downloaded", - title="Download Folder", + description="Duration using seconds, minutes, hours, or composite durations such as 1h30m. Whole days and weeks are also supported, for example 7d or 2w.", + examples=["24h"], + pattern="^[+-]?(0|[0-9]+[dw]|([0-9]+(\\.[0-9]*)?|\\.[0-9]+)(ns|us|µs|μs|ms|s|m|h)(([0-9]+(\\.[0-9]*)?|\\.[0-9]+)(ns|us|µs|μs|ms|s|m|h))*)$", ), - ] = "/tmp/loaded_checkpoints" - checkpoints: Annotated[ - list[Checkpoints] | None, - Field(description="List of checkpoint configurations", title="Checkpoints"), - ] = None + ] -class GetAuditLogsRequest(BaseModel): - cursor: Annotated[ - str | None, - Field( - description="Opaque cursor returned by a previous page. Omit to fetch the first page.", - title="Cursor", - ), - ] = None - limit: Annotated[ - int, - Field( - description="Maximum number of entries to return per page. Defaults to 20, and must be between 1 and 200.", - ge=1, - le=200, - title="Limit", - ), - ] = 20 - direction: Annotated[ - AuditLogSortDirection, - Field( - description="Sort order by the time the action occurred. Defaults to DESC (newest first). Ignored when paginating with a cursor." - ), - ] = AuditLogSortDirection.DESC - search: Annotated[ - str | None, - Field( - description="Case-insensitive substring matched against resource names and IDs in the entry.", - title="Search", - ), - ] = None - event_type_groups: Annotated[ - list[AuditLogEventTypeGroup] | None, +class Action(StrEnum): + DELETE = "DELETE" + + +class Type(StrEnum): + TTL_IDLE = "TTL_IDLE" + + +class SandboxTTLIdleExpirationPolicy(BaseModel): + action: Action + type: Literal["TTL_IDLE"] + value: SandboxDuration + + +class Type1(StrEnum): + TTL_MAX_AGE = "TTL_MAX_AGE" + + +class SandboxTTLMaxAgeExpirationPolicy(BaseModel): + action: Action + type: Literal["TTL_MAX_AGE"] + value: SandboxDuration + + +class Type2(StrEnum): + DATE = "DATE" + + +class SandboxDateExpirationPolicy(BaseModel): + action: Action + type: Literal["DATE"] + value: Annotated[AwareDatetime, Field(examples=["2026-09-23T21:26:58Z"])] + + +class SandboxProxyTarget(BaseModel): + body: Annotated[ + dict[str, str] | None, Field( - description="When set, returns only entries whose event type falls in one of these groups.", - title="Event Type Groups", + description="Body fields to inject into matching requests. Values may contain {{SECRET:name}} references resolved from this rule's secrets.", + examples=[{"user": "baseten-api-review-0916"}], ), ] = None - user_ids: Annotated[ + destinations: Annotated[ list[str] | None, Field( - description="When set, returns only entries whose acting user is one of these IDs.", - title="User Ids", + description='Destination domains this rule applies to. Use ["*"] for a global rule that matches all destinations.', + examples=[["api.openai.com"]], ), ] = None - deployment_ids: Annotated[ - list[str] | None, + headers: Annotated[ + dict[str, str] | None, Field( - description="When set, returns only entries referencing one of these model deployment IDs.", - title="Deployment Ids", + description="Headers to inject into matching requests. Values may contain {{SECRET:name}} references resolved from this rule's secrets.", + examples=[{"Authorization": "Bearer {{SECRET:openai-key}}"}], ), ] = None - chain_deployment_ids: Annotated[ - list[str] | None, + secrets: Annotated[ + dict[str, str] | None, Field( - description="When set, returns only entries referencing one of these chain deployment IDs.", - title="Chain Deployment Ids", + description="Named secret values for this routing rule, referenced in headers/body via {{SECRET:name}}. Stored encrypted at rest. Write-only: never returned in API responses.", + examples=[{"openai-key": "sk-proj-demo-not-a-valid-api-key"}], ), ] = None - environment_names: Annotated[ - list[str] | None, - Field( - description="When set, returns only entries for one of these environments.", - title="Environment Names", - ), + + +class SandboxEnv(BaseModel): + name: Annotated[ + str | None, + Field(description="Name of the environment variable", examples=["NODE_ENV"]), ] = None - sources: Annotated[ - list[AuditLogSource] | None, - Field( - description="When set, returns only entries issued from one of these surfaces.", - title="Sources", - ), + secret: Annotated[ + bool | None, + Field(description="Whether the value is a secret", examples=[False]), ] = None - start_epoch_millis: Annotated[ + value: Annotated[ + str | None, + Field(description="Value of the environment variable", examples=["production"]), + ] = None + + +class Protocol(StrEnum): + HTTP = "HTTP" + TCP = "TCP" + UDP = "UDP" + TLS = "TLS" + + +class SandboxPort(BaseModel): + name: Annotated[ + str | None, Field(description="The name of the port", examples=["http"]) + ] = None + protocol: Annotated[ + Protocol | None, + Field(description="The protocol of the port", examples=["HTTP"]), + ] = None + target: Annotated[ + int, + Field( + description="The target port of the port", examples=[3000], ge=1, le=65535 + ), + ] + + +class SandboxMetadataLabels(RootModel[dict[str, str]]): + root: dict[str, str] + + +class State(StrEnum): + RUNNING = "RUNNING" + STANDBY = "STANDBY" + + +class SandboxStatus(StrEnum): + DEPLOYING = "DEPLOYING" + DEPLOYED = "DEPLOYED" + FAILED = "FAILED" + DEACTIVATING = "DEACTIVATING" + DEACTIVATED = "DEACTIVATED" + DELETING = "DELETING" + TERMINATED = "TERMINATED" + ARCHIVING = "ARCHIVING" + ARCHIVED = "ARCHIVED" + UNARCHIVING = "UNARCHIVING" + BUILDING = "BUILDING" + UPLOADING = "UPLOADING" + + +class SandboxApiPagination(BaseModel): + has_more: Annotated[ + bool, Field(description="Whether another page is available.", examples=[True]) + ] + cursor: Annotated[ + str | None, + Field( + description="Opaque cursor to pass to the next list request. Keep the same filters.", + examples=[ + "eyJ2IjoxLCJsYXN0X2tleSI6ImJhc2V0ZW4tYXBpLXJldmlldy0wOTE2Iiwic29ydCI6ImRlc2MifQ" + ], + min_length=1, + ), + ] = None + + +class ImageStatus(StrEnum): + UPLOADING = "UPLOADING" + BUILDING = "BUILDING" + BUILT = "BUILT" + FAILED = "FAILED" + + +class ImageTag(BaseModel): + name: Annotated[str, Field(description="Image tag name.", examples=["latest"])] + created_at: Annotated[ + AwareDatetime | None, + Field( + description="Time the tag was created.", examples=["2026-09-16T21:20:00Z"] + ), + ] = None + updated_at: Annotated[ + AwareDatetime | None, + Field( + description="Time the tag was last updated.", + examples=["2026-09-16T21:25:00Z"], + ), + ] = None + size: Annotated[ int | None, + Field(description="Image size in bytes.", examples=[134217728], ge=0), + ] = None + + +class Image(BaseModel): + name: Annotated[ + str, Field( - description="Epoch milliseconds for the start of the window. Defaults to the beginning of the audit-log history.", - title="Start Epoch Millis", + description="Stable repository name supplied when pushing the image.", + examples=["base-image"], + ), + ] + display_name: Annotated[ + str | None, + Field( + description="Human-readable image repository name.", + examples=["b10/base-image"], ), ] = None - end_epoch_millis: Annotated[ + status: Annotated[ + ImageStatus, + Field( + description="Image processing status. Only BUILT images are ready to use.", + examples=["BUILT"], + ), + ] + created_at: Annotated[ + AwareDatetime | None, + Field( + description="Time the image was created.", examples=["2026-09-15T21:20:00Z"] + ), + ] = None + updated_at: Annotated[ + AwareDatetime | None, + Field( + description="Time the image was last updated.", + examples=["2026-09-16T21:25:00Z"], + ), + ] = None + last_deployed_at: Annotated[ + AwareDatetime | None, + Field( + description="Most recent deployment time across all tags, if deployed.", + examples=["2026-09-16T21:26:58.545765901Z"], + ), + ] = None + size: Annotated[ int | None, Field( - description="Epoch milliseconds for the end of the window. Defaults to the current time.", - title="End Epoch Millis", + description="Total repository size in bytes.", examples=[260046848], ge=0 + ), + ] = None + tag_count: Annotated[ + int | None, + Field( + description="Number of image versions in the repository.", + examples=[2], + ge=0, + ), + ] = None + tags: Annotated[ + list[ImageTag], + Field( + description="Empty for list and get summary responses. Use GET /sandboxes/images/{image_name}/tags to retrieve paginated image versions.", + examples=[ + [ + { + "name": "latest", + "created_at": "2026-09-16T21:20:00Z", + "updated_at": "2026-09-16T21:25:00Z", + "size": 134217728, + }, + { + "name": "20260915212000", + "created_at": "2026-09-15T21:20:00Z", + "updated_at": "2026-09-15T21:25:00Z", + "size": 125829120, + }, + ] + ], + ), + ] + + +class PushImageRequest(BaseModel): + name: Annotated[ + str, + Field( + description="Target image repository name. Reusing a name pushes a new version to the existing repository.", + examples=["base-image"], + min_length=1, + ), + ] + image: Annotated[ + str | None, + Field( + description="Optional source registry image reference including a registry hostname. When omitted, the response provides an archive upload URL.", + examples=["docker.io/b10/base-image:latest"], + ), + ] = None + docker_config: Annotated[ + str | None, + Field( + description="Optional serialized registry authentication configuration for importing a private image. Used only when image is supplied; never returned.", + examples=[ + '{"auths":{"https://index.docker.io/v1/":{"auth":"YjEwLXJldmlldzpkZW1vLW5vdC1hLXZhbGlkLXJlZ2lzdHJ5LXRva2Vu"}}}' + ], + ), + ] = None + + +class PushImageResponse(BaseModel): + name: Annotated[ + str, Field(description="Target image repository name.", examples=["base-image"]) + ] + status: Annotated[ + ImageStatus, + Field( + description="Image processing status. Only BUILT images are ready to use.", + examples=["BUILDING"], + ), + ] + upload_url: Annotated[ + AnyUrl | None, + Field( + description="Temporary signed URL for uploading the source ZIP archive with HTTP PUT. Present only when no source image was supplied. Uploading starts asynchronous processing. This storage upload is separate from the API endpoints.", + examples=[ + "https://uploads.b10.run/images/base-image/20260916212658/source.zip?expires=2026-09-16T22%3A26%3A58Z&signature=demo-not-a-valid-upload-signature" + ], + ), + ] = None + image: Annotated[ + str | None, + Field( + description="Registered image reference including its tag, when available. Tags are assigned by the service; GET /sandboxes/images/{image_name} returns the available tags once processing completes.", + examples=["b10/base-image:latest"], + ), + ] = None + + +class CleanupImagesResponse(BaseModel): + deleted: Annotated[ + int, Field(description="Number of image versions removed.", examples=[3], ge=0) + ] + message: Annotated[ + str, + Field( + description="Human-readable cleanup result.", + examples=[ + "Removed 3 unused image versions. Image versions used by active sandboxes were retained." + ], + ), + ] + + +class Checkpoints( + RootModel[ + BasetenLatestCheckpointConfig + | BasetenNamedCheckpointConfig + | LoopsCheckpointConfig + ] +): + root: Annotated[ + BasetenLatestCheckpointConfig + | BasetenNamedCheckpointConfig + | LoopsCheckpointConfig, + Field(discriminator="typ"), + ] + + +class LoadCheckpointConfig(BaseModel): + enabled: Annotated[ + bool, + Field(description="Whether checkpoint loading is enabled", title="Enabled"), + ] = False + download_folder: Annotated[ + str, + Field( + description="Folder where checkpoints will be downloaded", + title="Download Folder", ), + ] = "/tmp/loaded_checkpoints" + checkpoints: Annotated[ + list[Checkpoints] | None, + Field(description="List of checkpoint configurations", title="Checkpoints"), ] = None -class GetModelsAuditLogsRequest(BaseModel): +class GetAuditLogsParams(BaseModel): cursor: Annotated[ str | None, Field( @@ -7386,69 +8862,157 @@ class GetModelsAuditLogsRequest(BaseModel): ] = None -class GetModelsDeploymentsLogsRequest(BaseModel): - start_epoch_millis: Annotated[ - int | None, - Field( - description="Epoch milliseconds at which to start fetching logs. Defaults to 30 minutes before the end. The window from start to end must not exceed 7 days.", - title="Start Epoch Millis", - ), - ] = None - end_epoch_millis: Annotated[ - int | None, +class GetModelsAuditLogsParams(BaseModel): + cursor: Annotated[ + str | None, Field( - description="Epoch milliseconds at which to stop fetching logs. Defaults to the current time.", - title="End Epoch Millis", + description="Opaque cursor returned by a previous page. Omit to fetch the first page.", + title="Cursor", ), ] = None - direction: Annotated[SortOrder | None, Field(description="Sort order for logs")] = ( - None - ) limit: Annotated[ - Limit | None, + int, Field( - description="Limit of logs to fetch in a single request", + description="Maximum number of entries to return per page. Defaults to 20, and must be between 1 and 200.", + ge=1, + le=200, title="Limit", - validate_default=True, ), - ] = Limit.model_validate(500) - min_level: Annotated[ - LogLevel | None, + ] = 20 + direction: Annotated[ + AuditLogSortDirection, Field( - description="Minimum log severity to include. Omit to return all log lines, including lines that have no level. Any explicit value returns lines at or above that severity and drops lines without a level." + description="Sort order by the time the action occurred. Defaults to DESC (newest first). Ignored when paginating with a cursor." ), - ] = None - replica: Annotated[ - Replica | None, + ] = AuditLogSortDirection.DESC + search: Annotated[ + str | None, Field( - description="Only return logs emitted by this replica (5-char short ID).", - title="Replica", + description="Case-insensitive substring matched against resource names and IDs in the entry.", + title="Search", ), ] = None - request_id: Annotated[ - RequestId | None, + event_type_groups: Annotated[ + list[AuditLogEventTypeGroup] | None, Field( - description="Only return logs tagged with this inference request ID.", - title="Request Id", + description="When set, returns only entries whose event type falls in one of these groups.", + title="Event Type Groups", ), ] = None - component: Annotated[ - Component | None, - Field(description="Only return logs from this component.", title="Component"), - ] = None - search_pattern: Annotated[ - SearchPattern | None, + user_ids: Annotated[ + list[str] | None, Field( - description="RE2 regular expression matched against the log message. Prefer `includes` and `excludes` for plain substring matches.", - title="Search Pattern", + description="When set, returns only entries whose acting user is one of these IDs.", + title="User Ids", ), ] = None - includes: Annotated[ + deployment_ids: Annotated[ list[str] | None, Field( - description="Case-sensitive substrings that must all appear in the log message.", - max_length=8, - title="Includes", + description="When set, returns only entries referencing one of these model deployment IDs.", + title="Deployment Ids", + ), + ] = None + chain_deployment_ids: Annotated[ + list[str] | None, + Field( + description="When set, returns only entries referencing one of these chain deployment IDs.", + title="Chain Deployment Ids", + ), + ] = None + environment_names: Annotated[ + list[str] | None, + Field( + description="When set, returns only entries for one of these environments.", + title="Environment Names", + ), + ] = None + sources: Annotated[ + list[AuditLogSource] | None, + Field( + description="When set, returns only entries issued from one of these surfaces.", + title="Sources", + ), + ] = None + start_epoch_millis: Annotated[ + int | None, + Field( + description="Epoch milliseconds for the start of the window. Defaults to the beginning of the audit-log history.", + title="Start Epoch Millis", + ), + ] = None + end_epoch_millis: Annotated[ + int | None, + Field( + description="Epoch milliseconds for the end of the window. Defaults to the current time.", + title="End Epoch Millis", + ), + ] = None + + +class GetModelsDeploymentsLogsParams(BaseModel): + start_epoch_millis: Annotated[ + int | None, + Field( + description="Epoch milliseconds at which to start fetching logs. Defaults to 30 minutes before the end. The window from start to end must not exceed 7 days.", + title="Start Epoch Millis", + ), + ] = None + end_epoch_millis: Annotated[ + int | None, + Field( + description="Epoch milliseconds at which to stop fetching logs. Defaults to the current time.", + title="End Epoch Millis", + ), + ] = None + direction: Annotated[SortOrder | None, Field(description="Sort order for logs")] = ( + None + ) + limit: Annotated[ + Limit | None, + Field( + description="Limit of logs to fetch in a single request", + title="Limit", + validate_default=True, + ), + ] = Limit.model_validate(500) + min_level: Annotated[ + LogLevel | None, + Field( + description="Minimum log severity to include. Omit to return all log lines, including lines that have no level. Any explicit value returns lines at or above that severity and drops lines without a level." + ), + ] = None + replica: Annotated[ + Replica | None, + Field( + description="Only return logs emitted by this replica (5-char short ID).", + title="Replica", + ), + ] = None + request_id: Annotated[ + RequestId | None, + Field( + description="Only return logs tagged with this inference request ID.", + title="Request Id", + ), + ] = None + component: Annotated[ + Component | None, + Field(description="Only return logs from this component.", title="Component"), + ] = None + search_pattern: Annotated[ + SearchPattern | None, + Field( + description="RE2 regular expression matched against the log message. Prefer `includes` and `excludes` for plain substring matches.", + title="Search Pattern", + ), + ] = None + includes: Annotated[ + list[str] | None, + Field( + description="Case-sensitive substrings that must all appear in the log message.", + max_length=8, + title="Includes", ), ] = None excludes: Annotated[ @@ -7461,7 +9025,7 @@ class GetModelsDeploymentsLogsRequest(BaseModel): ] = None -class GetModelsDeploymentsMetricsRequest(BaseModel): +class GetModelsDeploymentsMetricsParams(BaseModel): mode: Annotated[ ModelMetricMode, Field( @@ -7491,7 +9055,7 @@ class GetModelsDeploymentsMetricsRequest(BaseModel): ] = None -class GetModelsEnvironmentsLogsRequest(BaseModel): +class GetModelsEnvironmentsLogsParams(BaseModel): start_epoch_millis: Annotated[ int | None, Field( @@ -7566,7 +9130,7 @@ class GetModelsEnvironmentsLogsRequest(BaseModel): ] = None -class GetModelsEnvironmentsMetricsRequest(BaseModel): +class GetModelsEnvironmentsMetricsParams(BaseModel): mode: Annotated[ ModelMetricMode, Field( @@ -7596,7 +9160,7 @@ class GetModelsEnvironmentsMetricsRequest(BaseModel): ] = None -class GetChainsAuditLogsRequest(BaseModel): +class GetChainsAuditLogsParams(BaseModel): cursor: Annotated[ str | None, Field( @@ -7684,7 +9248,7 @@ class GetChainsAuditLogsRequest(BaseModel): ] = None -class GetChainsDeploymentsChainletsLogsRequest(BaseModel): +class GetChainsDeploymentsChainletsLogsParams(BaseModel): start_epoch_millis: Annotated[ int | None, Field( @@ -7759,7 +9323,7 @@ class GetChainsDeploymentsChainletsLogsRequest(BaseModel): ] = None -class GetTrainingProjectsJobsLogsRequest(BaseModel): +class GetTrainingProjectsJobsLogsParams(BaseModel): start_epoch_millis: Annotated[ int | None, Field( @@ -7793,7 +9357,33 @@ class GetTrainingProjectsJobsLogsRequest(BaseModel): ] = None -class GetLoopsDeploymentsLogsRequest(BaseModel): +class GetLoopsCapabilitiesParams(BaseModel): + model: Annotated[ + str | None, + Field( + description="Restrict the response to one model, identified by its HuggingFace repo id. A supported model comes back with its 'enabled' flag and, when false, its 'enablement_details'. An empty list means Baseten does not support that model. Omit to list every supported model.", + examples=["Qwen/Qwen3-8B"], + title="Model", + ), + ] = None + use_case: Annotated[ + LoopsUseCase, + Field( + description="What the caller intends to run. Defaults to 'rl', the stricter of the two: an RL run needs both a trainer and a sampler, so anything enabled for 'rl' is also enabled for 'sft'.", + examples=["rl"], + ), + ] = LoopsUseCase.rl + max_seq_len: Annotated[ + MaxSeqLen | None, + Field( + description="The sequence length the caller intends to train at — the same value they would pass as 'max_seq_len' when creating the run. Models that cannot serve it are reported as not enabled rather than returned with a ceiling the caller cannot use. Omit for the model's highest enabled sequence length.", + examples=[32768], + title="Max Seq Len", + ), + ] = None + + +class GetLoopsDeploymentsLogsParams(BaseModel): start_epoch_millis: Annotated[ int | None, Field( @@ -7827,7 +9417,7 @@ class GetLoopsDeploymentsLogsRequest(BaseModel): ] = None -class GetModelApisUsageRequest(BaseModel): +class GetModelApisUsageParams(BaseModel): start_time: Annotated[ AwareDatetime | None, Field( @@ -7890,7 +9480,7 @@ class GetModelApisUsageRequest(BaseModel): ] = None -class GetBillingModelApisRequest(BaseModel): +class GetBillingModelApisParams(BaseModel): cursor: Annotated[ str | None, Field( @@ -7958,6 +9548,67 @@ class GetBillingModelApisRequest(BaseModel): ] = None +class GetRoutesUsageParams(BaseModel): + cursor: Annotated[ + str | None, + Field( + description="Opaque cursor returned by a previous page. Omit to fetch the first page.", + title="Cursor", + ), + ] = None + limit: Annotated[ + int, + Field( + description="Number of daily buckets to return. Defaults to 7; maximum 31.", + ge=1, + le=31, + title="Limit", + ), + ] = 7 + start_date: Annotated[ + date_aliased | None, + Field( + description="Inclusive UTC calendar day at the start of the query range. Defaults to the previous UTC date, and is ignored when you pass a cursor.", + title="Start Date", + ), + ] = None + end_date: Annotated[ + date_aliased | None, + Field( + description="Exclusive UTC calendar day at the end of the query range. Defaults to the day after the current UTC date so current-day usage is included.", + title="End Date", + ), + ] = None + group_by: Annotated[ + list[RouteUsageDimension] | None, + Field( + description="Dimensions to break usage down by, repeated once per dimension: USER, MODEL, or PROVIDER. Each result represents one observed combination of the requested dimensions within that day, and results are sorted by those values. Combinations without usage are omitted, so result counts can differ between days. Defaults to MODEL.", + title="Group By", + ), + ] = None + user_ids: Annotated[ + list[str] | None, + Field( + description="Return only usage from Routes keys created by these user IDs, repeated once per ID.", + title="User Ids", + ), + ] = None + models: Annotated[ + list[str] | None, + Field( + description="Return only usage for these exact model names, repeated once per model.", + title="Models", + ), + ] = None + providers: Annotated[ + list[RouteProvider] | None, + Field( + description="Return only usage for these providers, repeated once per provider.", + title="Providers", + ), + ] = None + + class Volume(BaseModel): namespace: Annotated[ str, @@ -7979,57 +9630,79 @@ class Volume(BaseModel): sequence: Annotated[ int, Field( - description="Revision counter for the volume, incremented on every commit and tag change. Use it to detect that a volume changed.", + description="Revision counter for the volume, incremented on every commit, tag change, delete, and restore. A tag or version that expires leaves without changing it; the next write then increments it once. Use it to detect that a volume was written to.", title="Sequence", ), ] updated_at: Annotated[ AwareDatetime, Field( - description="When the volume last changed, in ISO 8601 format.", + description="When the volume was last written to, in ISO 8601 format. An expiry does not update it.", title="Updated At", ), ] + expires_at: Annotated[ + AwareDatetime | None, + Field( + description="When the whole volume expires, in ISO 8601 format. At that instant every live version is deleted, every tag drops, and the volume leaves the volume listing; each version then stays restorable until its recovery deadline passes. Null for a volume that never expires.", + title="Expires At", + ), + ] head: Annotated[ VolumeVersionSummary | None, Field( - description="Version that the reserved `head` tag points at, which a reference with no tag or digest resolves to. Null when the volume has no head, or when your API key cannot read it." + description="Version that the reserved `head` tag points at, which a reference with no tag or digest resolves to. Never an expiring version. Null when the volume has no head, or when your API key cannot read it." ), ] tags: Annotated[ list[VolumeTag], Field( - description="Tags on the volume that your API key can read.", title="Tags" + description="Tags on the volume that your API key can read. A tag with `expires_at` leaves this list at that instant.", + title="Tags", ), ] tag_count: Annotated[ int, Field( - description="Total number of tags on the volume, which can exceed the length of `tags` when your API key cannot read all of them.", + description="Total number of tags on the volume, which can exceed the length of `tags` when your API key cannot read all of them. Counts only tags that have not expired.", title="Tag Count", ), ] versions_alive: Annotated[ int, Field( - description="Number of versions that have not been deleted.", + description="Number of versions that have not been deleted or expired.", title="Versions Alive", ), ] versions_tombstoned: Annotated[ int, Field( - description="Number of versions that have been deleted.", + description="Number of versions that have been deleted or expired and are still within their recovery window.", title="Versions Tombstoned", ), ] versions_untagged: Annotated[ int, Field( - description="Number of versions that no tag points at.", + description="Number of live versions that no tag points at.", title="Versions Untagged", ), ] + versions_expiring: Annotated[ + int, + Field( + description="Number of live versions with an expiry still ahead of them. A version that has already expired counts in `versions_tombstoned` instead.", + title="Versions Expiring", + ), + ] + versions_earliest_expires_at: Annotated[ + AwareDatetime | None, + Field( + description="Earliest expiry among the live versions, in ISO 8601 format. Null when no live version is scheduled to expire.", + title="Versions Earliest Expires At", + ), + ] class ListVolumesResponse(BaseModel): @@ -8566,14 +10239,14 @@ class CreateEnvironmentRequest(BaseModel): promotion_settings: Annotated[ UpdatePromotionSettings | None, Field( - description="Promotion settings for the environment", + description="Promotion settings for the environment. New Model environments use rolling promotions by default. Set `rolling_deploy` to `false` to opt out.", examples=[ { "promotion_cleanup_strategy": None, "ramp_up_duration_seconds": 600, "ramp_up_while_promoting": True, "redeploy_on_promotion": True, - "rolling_deploy": True, + "rolling_deploy": False, "rolling_deploy_config": None, } ], @@ -9370,6 +11043,7 @@ class APIKeyInfo(BaseModel): description="Type of the API key.", examples=[ "PERSONAL", + "ROUTES", "WORKSPACE_MANAGE_API_KEYS", "WORKSPACE_EXPORT_METRICS", "WORKSPACE_INVOKE", @@ -9392,6 +11066,17 @@ class APIKeyInfo(BaseModel): title="Team Name", ), ] = None + created_at: Annotated[ + AwareDatetime, + Field(description="Creation time in ISO 8601 format", title="Created At"), + ] + last_used_at: Annotated[ + AwareDatetime | None, + Field( + description="Last recorded use in ISO 8601 format, or null if unavailable. Updates may be delayed.", + title="Last Used At", + ), + ] = None owner: Annotated[ APIKeyOwner | None, Field( @@ -9821,74 +11506,275 @@ class UsageSummary(BaseModel): ] = None -class EndpointTarget(BaseModel): - provider: Annotated[GatewayProvider, Field(description="Upstream provider.")] - secret_id: Annotated[ - str | None, Field(description="Referenced secret, if any.", title="Secret Id") +class ExploreCost(BaseModel): + input: Annotated[ + float | None, + Field(description="USD per 1M input tokens, when available.", title="Input"), ] = None - target_model: Annotated[ - str | None, - Field(description="Upstream model name, if any.", title="Target Model"), + output: Annotated[ + float | None, + Field(description="USD per 1M output tokens, when available.", title="Output"), ] = None - base_url: Annotated[ - str | None, + cache_read: Annotated[ + float | None, Field( - description="Custom OpenAI-compatible base URL, if any.", title="Base Url" + description="USD per 1M input tokens read from cache, when available.", + title="Cache Read", ), ] = None - model_id: Annotated[ - str | None, Field(description="Baseten model, if any.", title="Model Id") - ] = None - environment_name: Annotated[ - str | None, + cache_write: Annotated[ + float | None, Field( - description="Baseten model environment, if non-production.", - title="Environment Name", + description="USD per 1M input tokens written to cache, when available.", + title="Cache Write", ), ] = None - vertex_config: Annotated[ - VertexTargetConfig | None, - Field(description="Google Vertex configuration, if any."), + long_context: Annotated[ + ExploreCostValues | None, + Field( + description="Prices for long-context requests, when the provider tiers by context length." + ), ] = None -class Endpoint(BaseModel): - id: Annotated[ - str, Field(description="Stable identifier for the endpoint.", title="Id") - ] +class ExploreMetadata(BaseModel): slug: Annotated[ - str, + str | None, Field( - description="Globally-unique routing slug.", - examples=["baseten/mymodel-4"], + description="Metadata slug, e.g. 'anthropic/claude-opus-4'; null for rows without one.", title="Slug", ), ] - region: Annotated[ - SharedEndpointRegion, - Field(description="Region this endpoint's routing serves."), - ] - created_at: Annotated[ - AwareDatetime, Field(description="Creation time, ISO 8601.", title="Created At") + display_name: Annotated[ + str | None, + Field(description="Model display name, when available.", title="Display Name"), ] - updated_at: Annotated[ - AwareDatetime, - Field(description="Last update time, ISO 8601.", title="Updated At"), + release_date: Annotated[ + date_aliased | None, + Field( + description="Model release date. Month-only source dates use the first day of that month.", + title="Release Date", + ), ] - targets: Annotated[ - list[EndpointTarget], + provider: Annotated[ + str | None, Field( - description="The endpoint's upstream targets. Exactly one target is supported at this time.", - title="Targets", + description="Provider key derived from the slug prefix, e.g. 'anthropic'; null for unprefixed slugs.", + title="Provider", ), ] - - -class EndpointsResponse(BaseModel): - items: Annotated[ - list[Endpoint], Field(description="Items in this page.", title="Items") + context_window: Annotated[ + int | None, + Field(description="Total context window in tokens.", title="Context Window"), ] - pagination: Annotated[ + max_output_tokens: Annotated[ + int | None, + Field( + description="Maximum output tokens per response.", title="Max Output Tokens" + ), + ] + input_modalities: Annotated[ + list[str], + Field(description="Accepted input modalities.", title="Input Modalities"), + ] + tools: Annotated[ + bool | None, + Field(description="Whether the model supports tool calling.", title="Tools"), + ] + reasoning_effort_levels: Annotated[ + list[str] | None, + Field( + description="Reasoning effort levels the model supports.", + title="Reasoning Effort Levels", + ), + ] + parallel_tool_calls: Annotated[ + bool | None, + Field( + description="Whether the model supports parallel tool calls.", + title="Parallel Tool Calls", + ), + ] + supported_api_formats: Annotated[ + ExploreMetadataAPIFormats | None, + Field(description="API formats the model supports."), + ] + cost: Annotated[ + ExploreCost | None, + Field(description="Provider list prices in USD per 1M tokens, when available."), + ] + + +class ExploreMetadataResponse(BaseModel): + items: Annotated[ + list[ExploreMetadata], Field(description="Items in this page.", title="Items") + ] + pagination: Annotated[ + PaginationResponse, Field(description="Pagination metadata for the page.") + ] + + +class Route(BaseModel): + id: Annotated[str, Field(description="Stable route identifier.", title="Id")] + name: Annotated[ + str, + Field( + description="Name to send in the inference request's model field.", + title="Name", + ), + ] + team_id: Annotated[ + str, Field(description="Identifier of the owning team.", title="Team Id") + ] + team_name: Annotated[ + str, Field(description="Name of the owning team.", title="Team Name") + ] + display_name: Annotated[ + str, + Field( + description="Display label, defaulting to the route name.", + title="Display Name", + ), + ] + description: Annotated[ + str, + Field( + description="Short description of the route, empty when unset.", + title="Description", + ), + ] + target: Annotated[ + RouteTargetBasetenModelAPI + | RouteTargetAnthropic + | RouteTargetOpenAI + | RouteTargetXAI, + Field( + description="Configured upstream target.", + discriminator="type", + title="Target", + ), + ] + metadata: Annotated[ + ExploreMetadata | None, + Field( + description="Resolved model metadata; null when the route has no linked metadata row." + ), + ] + invoke_url: Annotated[ + str, + Field( + description="Base URL for inference requests using this route.", + title="Invoke Url", + ), + ] + created_at: Annotated[ + AwareDatetime, Field(description="Creation time, ISO 8601.", title="Created At") + ] + + +class RoutesResponse(BaseModel): + items: Annotated[ + list[Route], Field(description="Items in this page.", title="Items") + ] + pagination: Annotated[ + PaginationResponse, Field(description="Pagination metadata for the page.") + ] + + +class RoutesUsageBucket(BaseModel): + date: Annotated[ + date_aliased, + Field( + description="UTC calendar date for this bucket, from midnight inclusive to the next midnight exclusive.", + title="Date", + ), + ] + results: Annotated[ + list[RoutesUsageResult], + Field( + description="Usage broken down by the requested dimensions. Empty when there is no usage.", + title="Results", + ), + ] + + +class RoutesUsageResponse(BaseModel): + items: Annotated[ + list[RoutesUsageBucket], Field(description="Items in this page.", title="Items") + ] + pagination: Annotated[ + PaginationResponse, Field(description="Pagination metadata for the page.") + ] + + +class EndpointTarget(BaseModel): + provider: Annotated[GatewayProvider, Field(description="Upstream provider.")] + secret_id: Annotated[ + str | None, Field(description="Referenced secret, if any.", title="Secret Id") + ] = None + target_model: Annotated[ + str | None, + Field(description="Upstream model name, if any.", title="Target Model"), + ] = None + base_url: Annotated[ + str | None, + Field( + description="Custom OpenAI-compatible base URL, if any.", title="Base Url" + ), + ] = None + model_id: Annotated[ + str | None, Field(description="Baseten model, if any.", title="Model Id") + ] = None + environment_name: Annotated[ + str | None, + Field( + description="Baseten model environment, if non-production.", + title="Environment Name", + ), + ] = None + vertex_config: Annotated[ + VertexTargetConfig | None, + Field(description="Google Vertex configuration, if any."), + ] = None + + +class Endpoint(BaseModel): + id: Annotated[ + str, Field(description="Stable identifier for the endpoint.", title="Id") + ] + slug: Annotated[ + str, + Field( + description="Globally-unique routing slug.", + examples=["baseten/mymodel-4"], + title="Slug", + ), + ] + region: Annotated[ + SharedEndpointRegion, + Field(description="Region this endpoint's routing serves."), + ] + created_at: Annotated[ + AwareDatetime, Field(description="Creation time, ISO 8601.", title="Created At") + ] + updated_at: Annotated[ + AwareDatetime, + Field(description="Last update time, ISO 8601.", title="Updated At"), + ] + targets: Annotated[ + list[EndpointTarget], + Field( + description="The endpoint's upstream targets. Exactly one target is supported at this time.", + title="Targets", + ), + ] + + +class EndpointsResponse(BaseModel): + items: Annotated[ + list[Endpoint], Field(description="Items in this page.", title="Items") + ] + pagination: Annotated[ PaginationResponse, Field(description="Pagination metadata for the page.") ] @@ -9970,6 +11856,91 @@ class UpdateGroupRequest(BaseModel): ] = None +class SandboxExpirationPolicy( + RootModel[ + SandboxTTLIdleExpirationPolicy + | SandboxTTLMaxAgeExpirationPolicy + | SandboxDateExpirationPolicy + ] +): + root: Annotated[ + SandboxTTLIdleExpirationPolicy + | SandboxTTLMaxAgeExpirationPolicy + | SandboxDateExpirationPolicy, + Field( + description="Expiration policy. The type determines whether value is a duration or an absolute timestamp.", + discriminator="type", + ), + ] + + +class SandboxProxyConfig(BaseModel): + allowed_domains: Annotated[ + list[str] | None, + Field( + description="List of allowed external domains (allowlist). When set, only these domains are reachable. Supports wildcards (e.g. *.storage.example.com).", + examples=[ + [ + "api.openai.com", + "pypi.org", + "files.pythonhosted.org", + "registry.npmjs.org", + ] + ], + ), + ] = None + bypass: Annotated[ + list[str] | None, + Field( + description="Domains that bypass the proxy entirely via the NO_PROXY directive. Traffic to these destinations goes direct, not through the CONNECT tunnel. Supports wildcards. Note that localhost, private ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16), 169.254.169.254, .local and .internal are always bypassed by default.", + examples=[["registry.npmjs.org"]], + ), + ] = None + forbidden_domains: Annotated[ + list[str] | None, + Field( + description="List of forbidden external domains (denylist). When set, all domains except these are reachable. Supports wildcards (e.g. *.malware.com). If both allowed_domains and forbidden_domains are set, allowed_domains takes precedence.", + examples=[["facebook.com", "*.facebook.com"]], + ), + ] = None + routing: Annotated[ + list[SandboxProxyTarget] | None, + Field( + description='Per-destination routing rules with header/body injection and secrets. Use destinations ["*"] for global rules that apply to all destinations.', + examples=[ + [ + { + "destinations": ["api.openai.com"], + "headers": {"Authorization": "Bearer {{SECRET:openai-key}}"}, + "body": {"user": "baseten-api-review-0916"}, + "secrets": {"openai-key": "sk-proj-demo-not-a-valid-api-key"}, + } + ] + ], + ), + ] = None + + +class SandboxPorts(RootModel[list[SandboxPort]]): + root: Annotated[ + list[SandboxPort], + Field( + description="Set of ports for a resource", + examples=[[{"name": "http", "protocol": "HTTP", "target": 3000}]], + ), + ] + + +class ListImagesResponse(BaseModel): + items: Annotated[list[Image], Field(description="Image repositories on this page.")] + pagination: SandboxApiPagination + + +class ListImageTagsResponse(BaseModel): + items: list[ImageTag] + pagination: SandboxApiPagination + + class AuditLogEntry(BaseModel): id: Annotated[ str, Field(description="Unique identifier of the audit-log entry.", title="Id") @@ -9994,6 +11965,7 @@ class AuditLogEntry(BaseModel): | AuditLogEventModelDeploymentInstanceTypeChanged | AuditLogEventModelDeploymentDeleted | AuditLogEventModelDeleted + | AuditLogEventModelRenamed | AuditLogEventChainDeployed | AuditLogEventChainDeploymentActivated | AuditLogEventChainDeploymentDeactivated @@ -10011,6 +11983,9 @@ class AuditLogEntry(BaseModel): | AuditLogEventGatewayEndpointCreated | AuditLogEventGatewayEndpointUpdated | AuditLogEventGatewayEndpointDeleted + | AuditLogEventProviderConnectionCreated + | AuditLogEventProviderConnectionUpdated + | AuditLogEventProviderConnectionDeleted | AuditLogEventUserInvited | AuditLogEventUserJoinedOrganization | AuditLogEventWebhookSigningSecretCreated @@ -10153,6 +12128,10 @@ class ChainEnvironment(BaseModel): description="Candidate chain deployment being promoted to the environment, if a promotion is in progress" ), ] = None + in_progress_promotion: Annotated[ + InProgressPromotion | None, + Field(description="Details of the in-progress promotion, if any"), + ] = None class DockerAuth(BaseModel): @@ -10317,6 +12296,597 @@ class GroupsResponse(BaseModel): ] +class SandboxLifecycle(BaseModel): + expiration_policies: Annotated[ + list[SandboxExpirationPolicy] | None, + Field( + description="List of expiration policies. Multiple policies can be combined; whichever condition is met first triggers the action.", + examples=[ + [ + {"action": "DELETE", "type": "TTL_IDLE", "value": "24h"}, + {"action": "DELETE", "type": "TTL_MAX_AGE", "value": "7d"}, + { + "action": "DELETE", + "type": "DATE", + "value": "2026-09-23T21:26:58Z", + }, + ] + ], + ), + ] = None + terminated_retention: Annotated[ + str | None, + Field( + description="Duration to keep the sandbox record after termination for log access (e.g., '1h', '24h', '7d'). Defaults to 5m. Subject to maximum quota limits.", + examples=["24h"], + ), + ] = None + + +class SandboxNetwork(BaseModel): + proxy: Annotated[ + SandboxProxyConfig | None, + Field( + description="Proxy configuration for routing sandbox HTTP traffic through the platform proxy with MITM inspection and per-destination header/body injection", + examples=[ + { + "allowed_domains": [ + "api.openai.com", + "pypi.org", + "files.pythonhosted.org", + "registry.npmjs.org", + ], + "bypass": ["registry.npmjs.org"], + "forbidden_domains": ["facebook.com", "*.facebook.com"], + "routing": [ + { + "destinations": ["api.openai.com"], + "headers": { + "Authorization": "Bearer {{SECRET:openai-key}}" + }, + "body": {"user": "baseten-api-review-0916"}, + "secrets": { + "openai-key": "sk-proj-demo-not-a-valid-api-key" + }, + } + ], + } + ], + ), + ] = None + subnet: Annotated[ + str | None, + Field( + description='Subnet name for the sandbox. Defaults to "default" at creation.', + examples=["default"], + ), + ] = None + + +class SandboxConfiguration(BaseModel): + enabled: Annotated[ + bool, + Field( + description="When false, the sandbox is disabled and will not accept connections", + examples=[True], + ), + ] = True + lifecycle: Annotated[ + SandboxLifecycle | None, + Field( + description="Lifecycle configuration controlling automatic sandbox deletion based on idle time, max age, or specific dates", + examples=[ + { + "expiration_policies": [ + {"action": "DELETE", "type": "TTL_IDLE", "value": "24h"}, + {"action": "DELETE", "type": "TTL_MAX_AGE", "value": "7d"}, + { + "action": "DELETE", + "type": "DATE", + "value": "2026-09-23T21:26:58Z", + }, + ], + "terminated_retention": "24h", + } + ], + ), + ] = None + network: Annotated[ + SandboxNetwork | None, + Field( + description="Network configuration for a sandbox including subnet, domain filtering, and proxy settings", + examples=[ + { + "proxy": { + "allowed_domains": [ + "api.openai.com", + "pypi.org", + "files.pythonhosted.org", + "registry.npmjs.org", + ], + "bypass": ["registry.npmjs.org"], + "forbidden_domains": ["facebook.com", "*.facebook.com"], + "routing": [ + { + "destinations": ["api.openai.com"], + "headers": { + "Authorization": "Bearer {{SECRET:openai-key}}" + }, + "body": {"user": "baseten-api-review-0916"}, + "secrets": { + "openai-key": "sk-proj-demo-not-a-valid-api-key" + }, + } + ], + }, + "subnet": "default", + } + ], + ), + ] = None + region: Annotated[ + str | None, + Field( + description="Region where the sandbox runs (for example us-pdx-1 or eu-lon-1). When omitted at creation, the closest region is selected.", + examples=["us-pdx-1"], + ), + ] = None + envs: Annotated[ + list[SandboxEnv] | None, + Field( + description="Environment variables injected into the sandbox.", + examples=[ + [ + {"name": "NODE_ENV", "secret": False, "value": "production"}, + {"name": "PORT", "secret": False, "value": "3000"}, + ] + ], + ), + ] = None + image: Annotated[ + str | None, + Field( + description="Image reference including its tag. Use blaxel/base-image:latest to get started with the built-in sandbox execution API. This image is available directly without building, pushing, or listing images through GET /v1/sandboxes/images.", + examples=["blaxel/base-image:latest"], + ), + ] = None + memory: Annotated[ + int | None, + Field( + description="Memory allocation in megabytes. Also determines CPU allocation (CPU cores = memory in MB / 2048, e.g., 4096MB = 2 CPUs).", + examples=[4096], + ge=1, + ), + ] = None + ports: Annotated[ + SandboxPorts | None, + Field( + description="Set of ports for a resource", + examples=[[{"name": "http", "protocol": "HTTP", "target": 3000}]], + ), + ] = None + display_name: Annotated[ + str | None, + Field( + description="Human-readable name for display in the UI. Can contain spaces and special characters, max 63 characters.", + examples=["Baseten API review"], + max_length=63, + ), + ] = None + external_id: Annotated[ + str | None, + Field( + description="Caller-owned identifier for external lookups. Max 64 chars, alphanumeric + dash.", + examples=["api-review-20260916-001"], + max_length=64, + pattern="^[A-Za-z0-9-]+$", + ), + ] = None + labels: Annotated[ + SandboxMetadataLabels | None, + Field( + description="Key-value pairs for organizing and filtering resources. Labels can be used to categorize resources by environment, project, team, or any custom taxonomy.", + examples=[ + {"env": "development", "project": "api-review", "team": "engineering"} + ], + ), + ] = None + + +class CreateSandboxRequest(BaseModel): + name: Annotated[ + str | None, + Field( + description="Optional unique sandbox name. Generated by the server when omitted; immutable after creation.", + examples=["baseten-api-review-0916"], + min_length=1, + ), + ] = None + lifecycle: Annotated[ + SandboxLifecycle | None, + Field( + description="Lifecycle configuration controlling automatic sandbox deletion based on idle time, max age, or specific dates", + examples=[ + { + "expiration_policies": [ + {"action": "DELETE", "type": "TTL_IDLE", "value": "24h"}, + {"action": "DELETE", "type": "TTL_MAX_AGE", "value": "7d"}, + { + "action": "DELETE", + "type": "DATE", + "value": "2026-09-23T21:26:58Z", + }, + ], + "terminated_retention": "24h", + } + ], + ), + ] = None + network: Annotated[ + SandboxNetwork | None, + Field( + description="Network configuration for a sandbox including subnet, domain filtering, and proxy settings", + examples=[ + { + "proxy": { + "allowed_domains": [ + "api.openai.com", + "pypi.org", + "files.pythonhosted.org", + "registry.npmjs.org", + ], + "bypass": ["registry.npmjs.org"], + "forbidden_domains": ["facebook.com", "*.facebook.com"], + "routing": [ + { + "destinations": ["api.openai.com"], + "headers": { + "Authorization": "Bearer {{SECRET:openai-key}}" + }, + "body": {"user": "baseten-api-review-0916"}, + "secrets": { + "openai-key": "sk-proj-demo-not-a-valid-api-key" + }, + } + ], + }, + "subnet": "default", + } + ], + ), + ] = None + region: Annotated[ + str | None, + Field( + description="Region where the sandbox runs (for example us-pdx-1 or eu-lon-1). When omitted at creation, the closest region is selected.", + examples=["us-pdx-1"], + ), + ] = None + envs: Annotated[ + list[SandboxEnv] | None, + Field( + description="Environment variables injected into the sandbox.", + examples=[ + [ + {"name": "NODE_ENV", "secret": False, "value": "production"}, + {"name": "PORT", "secret": False, "value": "3000"}, + ] + ], + ), + ] = None + image: Annotated[ + str | None, + Field( + description="Image reference including its tag. Use blaxel/base-image:latest to get started with the built-in sandbox execution API. This image is available directly without building, pushing, or listing images through GET /v1/sandboxes/images.", + examples=["blaxel/base-image:latest"], + ), + ] = None + memory: Annotated[ + int | None, + Field( + description="Memory allocation in megabytes. Also determines CPU allocation (CPU cores = memory in MB / 2048, e.g., 4096MB = 2 CPUs).", + examples=[4096], + ge=1, + ), + ] = None + ports: Annotated[ + SandboxPorts | None, + Field( + description="Set of ports for a resource", + examples=[[{"name": "http", "protocol": "HTTP", "target": 3000}]], + ), + ] = None + display_name: Annotated[ + str | None, + Field( + description="Human-readable name for display in the UI. Can contain spaces and special characters, max 63 characters.", + examples=["Baseten API review"], + max_length=63, + ), + ] = None + external_id: Annotated[ + str | None, + Field( + description="Caller-owned identifier for external lookups. Max 64 chars, alphanumeric + dash.", + examples=["api-review-20260916-001"], + max_length=64, + pattern="^[A-Za-z0-9-]+$", + ), + ] = None + labels: Annotated[ + SandboxMetadataLabels | None, + Field( + description="Key-value pairs for organizing and filtering resources. Labels can be used to categorize resources by environment, project, team, or any custom taxonomy.", + examples=[ + {"env": "development", "project": "api-review", "team": "engineering"} + ], + ), + ] = None + + +class UpdateSandboxRequest(BaseModel): + enabled: Annotated[ + bool | None, + Field( + description="When false, the sandbox is disabled and will not accept connections", + examples=[True], + ), + ] = None + lifecycle: Annotated[ + SandboxLifecycle | None, + Field( + description="Lifecycle configuration controlling automatic sandbox deletion based on idle time, max age, or specific dates", + examples=[ + { + "expiration_policies": [ + {"action": "DELETE", "type": "TTL_IDLE", "value": "24h"}, + {"action": "DELETE", "type": "TTL_MAX_AGE", "value": "7d"}, + { + "action": "DELETE", + "type": "DATE", + "value": "2026-09-23T21:26:58Z", + }, + ], + "terminated_retention": "24h", + } + ], + ), + ] = None + region: Annotated[ + str | None, + Field( + description="Region where the sandbox runs (for example us-pdx-1 or eu-lon-1). When omitted at creation, the closest region is selected.", + examples=["us-pdx-1"], + ), + ] = None + envs: Annotated[ + list[SandboxEnv] | None, + Field( + description="Environment variables injected into the sandbox.", + examples=[ + [ + {"name": "NODE_ENV", "secret": False, "value": "production"}, + {"name": "PORT", "secret": False, "value": "3000"}, + ] + ], + ), + ] = None + image: Annotated[ + str | None, + Field( + description="Image reference including its tag. Use blaxel/base-image:latest to get started with the built-in sandbox execution API. This image is available directly without building, pushing, or listing images through GET /v1/sandboxes/images.", + examples=["blaxel/base-image:latest"], + ), + ] = None + ports: Annotated[ + SandboxPorts | None, + Field( + description="Set of ports for a resource", + examples=[[{"name": "http", "protocol": "HTTP", "target": 3000}]], + ), + ] = None + display_name: Annotated[ + str | None, + Field( + description="Human-readable name for display in the UI. Can contain spaces and special characters, max 63 characters.", + examples=["Baseten API review - revised"], + max_length=63, + ), + ] = None + external_id: Annotated[ + str | None, + Field( + description="Caller-owned identifier for external lookups. Max 64 chars, alphanumeric + dash.", + examples=["api-review-20260916-001"], + max_length=64, + pattern="^[A-Za-z0-9-]+$", + ), + ] = None + labels: Annotated[ + SandboxMetadataLabels | None, + Field( + description="Key-value pairs for organizing and filtering resources. Labels can be used to categorize resources by environment, project, team, or any custom taxonomy.", + examples=[ + { + "env": "development", + "project": "api-review", + "team": "engineering", + "revision": "2", + } + ], + ), + ] = None + + +class Sandbox(SandboxConfiguration): + name: Annotated[ + str, + Field( + description="Immutable sandbox name, provided by the client or generated by the server, used in sandbox_name path parameters.", + examples=["baseten-api-review-0916"], + ), + ] + url: Annotated[ + AnyUrl | None, + Field( + description='Base URL of this sandbox\'s execution API. Use this exact returned URL; do not reconstruct its hostname. Authenticate requests with the same Authorization: Bearer header used to create the sandbox. No additional routing headers are required. Fetch GET {url}/swagger/doc.json with that header for the API reference served by this sandbox. For example, POST {url}/process with Content-Type: application/json and {"command":"echo hello","waitForCompletion":true} executes a command and waits for its result. Execution API fields use camelCase, independently of this API\'s snake_case fields.', + examples=["https://sbx-baseten-api-review-0916-esb1qo.us-pdx-1.b10.run"], + ), + ] = None + status: Annotated[ + SandboxStatus, + Field(description="Sandbox deployment status.", examples=["DEPLOYED"]), + ] + state: Annotated[ + State | None, + Field( + description="Current execution state when available.", examples=["RUNNING"] + ), + ] = None + created_at: Annotated[ + AwareDatetime, + Field( + description="Time the sandbox was created.", + examples=["2026-09-16T21:26:58.545765901Z"], + ), + ] + updated_at: Annotated[ + AwareDatetime | None, + Field( + description="Time the sandbox was last updated.", + examples=["2026-09-16T21:31:13Z"], + ), + ] = None + created_by: Annotated[ + str | None, + Field( + description="User or service account that created the sandbox.", + examples=["sandbox-automation"], + ), + ] = None + updated_by: Annotated[ + str | None, + Field( + description="User or service account that last updated the sandbox.", + examples=["sandbox-automation"], + ), + ] = None + last_used_at: Annotated[ + AwareDatetime | None, + Field( + description="Time the sandbox was last used.", + examples=["2026-09-16T21:31:13Z"], + ), + ] = None + expires_in: Annotated[ + int | None, + Field( + description="Seconds remaining before automatic deletion, when expiration is configured.", + examples=[86400], + ge=0, + ), + ] = None + + +class ListSandboxesResponse(BaseModel): + items: Annotated[ + list[Sandbox], + Field( + description="Resources on this page.", + examples=[ + [ + { + "enabled": True, + "lifecycle": { + "expiration_policies": [ + { + "action": "DELETE", + "type": "TTL_IDLE", + "value": "24h", + }, + { + "action": "DELETE", + "type": "TTL_MAX_AGE", + "value": "7d", + }, + { + "action": "DELETE", + "type": "DATE", + "value": "2026-09-23T21:26:58Z", + }, + ], + "terminated_retention": "24h", + }, + "network": { + "proxy": { + "allowed_domains": [ + "api.openai.com", + "pypi.org", + "files.pythonhosted.org", + "registry.npmjs.org", + ], + "bypass": ["registry.npmjs.org"], + "forbidden_domains": ["facebook.com", "*.facebook.com"], + "routing": [ + { + "destinations": ["api.openai.com"], + "headers": { + "Authorization": "Bearer {{SECRET:openai-key}}" + }, + "body": {"user": "baseten-api-review-0916"}, + } + ], + }, + "subnet": "default", + }, + "region": "us-pdx-1", + "envs": [ + { + "name": "NODE_ENV", + "secret": False, + "value": "production", + }, + {"name": "PORT", "secret": False, "value": "3000"}, + ], + "image": "blaxel/base-image:latest", + "memory": 4096, + "ports": [{"name": "http", "protocol": "HTTP", "target": 3000}], + "display_name": "Baseten API review", + "external_id": "api-review-20260916-001", + "labels": { + "env": "development", + "project": "api-review", + "team": "engineering", + }, + "name": "baseten-api-review-0916", + "url": "https://sbx-baseten-api-review-0916-esb1qo.us-pdx-1.b10.run", + "status": "DEPLOYED", + "state": "RUNNING", + "created_at": "2026-09-16T21:26:58.545765901Z", + "updated_at": "2026-09-16T21:31:13Z", + "created_by": "sandbox-automation", + "updated_by": "sandbox-automation", + "last_used_at": "2026-09-16T21:31:13Z", + "expires_in": 86400, + } + ] + ], + ), + ] + pagination: Annotated[ + SandboxApiPagination, + Field( + description="Cursor pagination information. The cursor is present only when another page is available.", + examples=[ + { + "has_more": True, + "cursor": "eyJ2IjoxLCJsYXN0X2tleSI6ImJhc2V0ZW4tYXBpLXJldmlldy0wOTE2Iiwic29ydCI6ImRlc2MifQ", + } + ], + ), + ] + + class Environment(BaseModel): name: Annotated[str, Field(description="Name of the environment", title="Name")] created_at: Annotated[ diff --git a/baseten/client/sandboxapi/__init__.py b/baseten/client/sandboxapi/__init__.py new file mode 100644 index 0000000..95ac2cd --- /dev/null +++ b/baseten/client/sandboxapi/__init__.py @@ -0,0 +1,164 @@ +# Code generated by apigen. DO NOT EDIT. + +"""Generated client and models for the Baseten Sandbox API. + +Use :class:`ApiClient` for synchronous access or :class:`AsyncApiClient` for +asynchronous access. + +Types in this module are generated from the OpenAPI specification and are NOT +covered by any stability or compatibility guarantees. They may change without +notice between versions. +""" + +from ._client import ApiClient, AsyncApiClient, ResponseError, ResponseErrorResponse +from ._models import ( + ApplyEditRequest, + ApplyEditResponse, + ArchiveChange, + ArchiveChangeKind, + ArchiveExportState, + ArchiveManifest, + ArchiveQuiesceState, + ArchiveRestoreState, + ContentSearchMatch, + ContentSearchResponse, + DeleteFilesystemParams, + DeleteFilesystemTreeParams, + DeleteNetworkProcessMonitorResponse, + Directory, + DriveListResponse, + DriveMountInfo, + DriveMountRequest, + DriveMountResponse, + DriveUnmountResponse, + ErrorResponse, + ExportOptions, + ExportProgress, + ExportResult, + File, + FileRequest, + FilesystemMultipartUpload, + FilesystemUploadedPart, + FileWithContent, + FindMatch, + FindResponse, + FuzzySearchMatch, + FuzzySearchResponse, + GetCodegenRerankingParams, + GetFilesystemContentSearchParams, + GetFilesystemFindParams, + GetFilesystemParams, + GetFilesystemResponse, + GetFilesystemSearchParams, + GetFilesystemTreeResponse, + GetNetworkProcessPortsResponse, + GetProcessResponse, + GetWatchFilesystemParams, + HandlerReloadResponse, + HealthResponse, + MultipartCompleteRequest, + MultipartInitiateRequest, + MultipartInitiateResponse, + MultipartListPartsResponse, + MultipartListUploadsResponse, + MultipartPartInfo, + MultipartUpload, + MultipartUploadPartResponse, + PortMonitorRequest, + PostNetworkProcessMonitorResponse, + ProcessLogs, + ProcessRequest, + ProcessResponse, + ProcessUpgradeState, + PutFilesystemMultipartPartParams, + PutFilesystemTreeResponse, + QuiesceStatus, + RankedFile, + RerankingResponse, + RestoreProgress, + Status, + Subdirectory, + SuccessResponse, + TreeRequest, + TunnelConfigRequest, + UpgradeRequest, + UpgradeStatus, +) + +__all__ = [ + "ApiClient", + "ApplyEditRequest", + "ApplyEditResponse", + "ArchiveChange", + "ArchiveChangeKind", + "ArchiveExportState", + "ArchiveManifest", + "ArchiveQuiesceState", + "ArchiveRestoreState", + "AsyncApiClient", + "ContentSearchMatch", + "ContentSearchResponse", + "DeleteFilesystemParams", + "DeleteFilesystemTreeParams", + "DeleteNetworkProcessMonitorResponse", + "Directory", + "DriveListResponse", + "DriveMountInfo", + "DriveMountRequest", + "DriveMountResponse", + "DriveUnmountResponse", + "ErrorResponse", + "ExportOptions", + "ExportProgress", + "ExportResult", + "File", + "FileRequest", + "FileWithContent", + "FilesystemMultipartUpload", + "FilesystemUploadedPart", + "FindMatch", + "FindResponse", + "FuzzySearchMatch", + "FuzzySearchResponse", + "GetCodegenRerankingParams", + "GetFilesystemContentSearchParams", + "GetFilesystemFindParams", + "GetFilesystemParams", + "GetFilesystemResponse", + "GetFilesystemSearchParams", + "GetFilesystemTreeResponse", + "GetNetworkProcessPortsResponse", + "GetProcessResponse", + "GetWatchFilesystemParams", + "HandlerReloadResponse", + "HealthResponse", + "MultipartCompleteRequest", + "MultipartInitiateRequest", + "MultipartInitiateResponse", + "MultipartListPartsResponse", + "MultipartListUploadsResponse", + "MultipartPartInfo", + "MultipartUpload", + "MultipartUploadPartResponse", + "PortMonitorRequest", + "PostNetworkProcessMonitorResponse", + "ProcessLogs", + "ProcessRequest", + "ProcessResponse", + "ProcessUpgradeState", + "PutFilesystemMultipartPartParams", + "PutFilesystemTreeResponse", + "QuiesceStatus", + "RankedFile", + "RerankingResponse", + "ResponseError", + "ResponseErrorResponse", + "RestoreProgress", + "Status", + "Subdirectory", + "SuccessResponse", + "TreeRequest", + "TunnelConfigRequest", + "UpgradeRequest", + "UpgradeStatus", +] diff --git a/baseten/client/sandboxapi/_client.py b/baseten/client/sandboxapi/_client.py new file mode 100644 index 0000000..62aba21 --- /dev/null +++ b/baseten/client/sandboxapi/_client.py @@ -0,0 +1,1931 @@ +# Code generated by apigen/clientgen. DO NOT EDIT. + +from __future__ import annotations + +import contextlib +import urllib.parse +from collections.abc import Mapping +from dataclasses import dataclass +from typing import IO, Any, Literal, TypeVar + +import httpx +from pydantic import BaseModel, ValidationError + +from ._models import ( + ApplyEditRequest, + ApplyEditResponse, + ContentSearchResponse, + DeleteFilesystemParams, + DeleteFilesystemTreeParams, + DeleteNetworkProcessMonitorResponse, + DriveListResponse, + DriveMountRequest, + DriveMountResponse, + DriveUnmountResponse, + ErrorResponse, + ExportOptions, + ExportProgress, + ExportResult, + FileRequest, + FindResponse, + FuzzySearchResponse, + GetCodegenRerankingParams, + GetFilesystemContentSearchParams, + GetFilesystemFindParams, + GetFilesystemParams, + GetFilesystemResponse, + GetFilesystemSearchParams, + GetFilesystemTreeResponse, + GetNetworkProcessPortsResponse, + GetProcessResponse, + GetWatchFilesystemParams, + HandlerReloadResponse, + HealthResponse, + MultipartCompleteRequest, + MultipartInitiateRequest, + MultipartInitiateResponse, + MultipartListPartsResponse, + MultipartListUploadsResponse, + MultipartUploadPartResponse, + PortMonitorRequest, + PostNetworkProcessMonitorResponse, + ProcessLogs, + ProcessRequest, + ProcessResponse, + PutFilesystemMultipartPartParams, + PutFilesystemTreeResponse, + QuiesceStatus, + RerankingResponse, + SuccessResponse, + TreeRequest, + TunnelConfigRequest, + UpgradeRequest, +) + +_T = TypeVar("_T", bound=BaseModel) + + +@dataclass +class ResponseError(Exception): + status_code: int + body: str + + def __str__(self) -> str: + return f"baseten API error (HTTP {self.status_code}): {self.body}" + + +@dataclass +class ResponseErrorResponse(Exception): + status_code: int + error_response: ErrorResponse + + def __str__(self) -> str: + return f"baseten API error (HTTP {self.status_code}): {self.error_response.model_dump_json()}" + + +_ERROR_TYPES: dict[str, tuple[type[BaseModel], type[Exception], str]] = { + "ErrorResponse": (ErrorResponse, ResponseErrorResponse, "error_response"), +} + + +@dataclass +class _ApiRequest: + method: str + path_fmt: str + path_args: list[str] + body: Any + query: Any + success_codes: list[int] + error_codes: dict[int, str] | None + body_content_type: str | None = None + accept: str | None = None + + +class ApiClient: + """Generated HTTP client for the Baseten API. + + Methods on this client are generated from the OpenAPI specification + and are NOT covered by any stability or compatibility guarantees. + They may change without notice between versions. + """ + + def __init__(self, http_client: httpx.Client) -> None: + """Create a new client. The caller is responsible for closing *http_client*.""" + self._http_client = http_client + + def delete_drives_mount(self, *, mount_path: str) -> DriveUnmountResponse: + """Detach a drive from a local path""" + return self._do_json( + DriveUnmountResponse, + _ApiRequest( + method="DELETE", + path_fmt="/drives/mount/{}", + path_args=[mount_path], + body=None, + query=None, + success_codes=[200], + error_codes={400: "ErrorResponse", 500: "ErrorResponse"}, + ), + ) + + def delete_filesystem( + self, *, path: str, params: DeleteFilesystemParams | None = None + ) -> SuccessResponse: + """Delete file or directory""" + return self._do_json( + SuccessResponse, + _ApiRequest( + method="DELETE", + path_fmt="/filesystem/{}", + path_args=[path], + body=None, + query=params, + success_codes=[200], + error_codes={ + 404: "ErrorResponse", + 422: "ErrorResponse", + 500: "ErrorResponse", + }, + ), + ) + + def delete_filesystem_multipart_abort(self, *, upload_id: str) -> SuccessResponse: + """Abort multipart upload""" + return self._do_json( + SuccessResponse, + _ApiRequest( + method="DELETE", + path_fmt="/filesystem-multipart/{}/abort", + path_args=[upload_id], + body=None, + query=None, + success_codes=[200], + error_codes={ + 400: "ErrorResponse", + 404: "ErrorResponse", + 500: "ErrorResponse", + }, + ), + ) + + def delete_filesystem_tree( + self, *, path: str, params: DeleteFilesystemTreeParams | None = None + ) -> SuccessResponse: + """Delete directory tree""" + return self._do_json( + SuccessResponse, + _ApiRequest( + method="DELETE", + path_fmt="/filesystem/tree/{}", + path_args=[path], + body=None, + query=params, + success_codes=[200], + error_codes={ + 400: "ErrorResponse", + 422: "ErrorResponse", + 500: "ErrorResponse", + }, + ), + ) + + def delete_network_process_monitor( + self, *, pid: str + ) -> DeleteNetworkProcessMonitorResponse: + """Stop monitoring ports for a process""" + return self._do_json( + DeleteNetworkProcessMonitorResponse, + _ApiRequest( + method="DELETE", + path_fmt="/network/process/{}/monitor", + path_args=[pid], + body=None, + query=None, + success_codes=[200], + error_codes={ + 400: "ErrorResponse", + 422: "ErrorResponse", + 500: "ErrorResponse", + }, + ), + ) + + def delete_network_tunnel(self) -> SuccessResponse: + """Disconnect tunnel""" + return self._do_json( + SuccessResponse, + _ApiRequest( + method="DELETE", + path_fmt="/network/tunnel", + path_args=[], + body=None, + query=None, + success_codes=[200], + error_codes={400: "ErrorResponse", 500: "ErrorResponse"}, + ), + ) + + def delete_process(self, *, identifier: str) -> SuccessResponse: + """Stop a process""" + return self._do_json( + SuccessResponse, + _ApiRequest( + method="DELETE", + path_fmt="/process/{}", + path_args=[identifier], + body=None, + query=None, + success_codes=[200], + error_codes={ + 404: "ErrorResponse", + 422: "ErrorResponse", + 500: "ErrorResponse", + }, + ), + ) + + def delete_process_kill(self, *, identifier: str) -> SuccessResponse: + """Kill a process""" + return self._do_json( + SuccessResponse, + _ApiRequest( + method="DELETE", + path_fmt="/process/{}/kill", + path_args=[identifier], + body=None, + query=None, + success_codes=[200], + error_codes={ + 404: "ErrorResponse", + 422: "ErrorResponse", + 500: "ErrorResponse", + }, + ), + ) + + def delete_process_stdin(self, *, identifier: str) -> SuccessResponse: + """Close a process's stdin""" + return self._do_json( + SuccessResponse, + _ApiRequest( + method="DELETE", + path_fmt="/process/{}/stdin", + path_args=[identifier], + body=None, + query=None, + success_codes=[200], + error_codes={404: "ErrorResponse", 409: "ErrorResponse"}, + ), + ) + + def get_archive_status(self) -> QuiesceStatus: + """Get the archive status""" + return self._do_json( + QuiesceStatus, + _ApiRequest( + method="GET", + path_fmt="/archive/status", + path_args=[], + body=None, + query=None, + success_codes=[200], + error_codes=None, + ), + ) + + def get_codegen_reranking( + self, *, path: str, params: GetCodegenRerankingParams + ) -> RerankingResponse: + """Code reranking/semantic search""" + return self._do_json( + RerankingResponse, + _ApiRequest( + method="GET", + path_fmt="/codegen/reranking/{}", + path_args=[path], + body=None, + query=params, + success_codes=[200], + error_codes={ + 400: "ErrorResponse", + 422: "ErrorResponse", + 503: "ErrorResponse", + }, + ), + ) + + def get_drives_mount(self) -> DriveListResponse: + """List currently mounted drives""" + return self._do_json( + DriveListResponse, + _ApiRequest( + method="GET", + path_fmt="/drives/mount", + path_args=[], + body=None, + query=None, + success_codes=[200], + error_codes={500: "ErrorResponse"}, + ), + ) + + def get_filesystem( + self, *, path: str, params: GetFilesystemParams | None = None + ) -> GetFilesystemResponse: + """Get file or directory information""" + return self._do_json( + GetFilesystemResponse, + _ApiRequest( + method="GET", + path_fmt="/filesystem/{}", + path_args=[path], + body=None, + query=params, + success_codes=[200], + error_codes={ + 404: "ErrorResponse", + 422: "ErrorResponse", + 500: "ErrorResponse", + }, + ), + ) + + def get_filesystem_raw( + self, + *, + path: str, + params: GetFilesystemParams | None = None, + accept: Literal["application/json", "application/octet-stream"], + ) -> httpx.Response: + """Get file or directory information. Returns the response unread, in the requested content type.""" + return self._do( + _ApiRequest( + method="GET", + path_fmt="/filesystem/{}", + path_args=[path], + body=None, + query=params, + success_codes=[200], + error_codes={ + 404: "ErrorResponse", + 422: "ErrorResponse", + 500: "ErrorResponse", + }, + accept=accept, + ) + ) + + def get_filesystem_content_search( + self, *, path: str, params: GetFilesystemContentSearchParams + ) -> ContentSearchResponse: + """Search for text content in files""" + return self._do_json( + ContentSearchResponse, + _ApiRequest( + method="GET", + path_fmt="/filesystem-content-search/{}", + path_args=[path], + body=None, + query=params, + success_codes=[200], + error_codes={ + 400: "ErrorResponse", + 422: "ErrorResponse", + 500: "ErrorResponse", + }, + ), + ) + + def get_filesystem_find( + self, *, path: str, params: GetFilesystemFindParams | None = None + ) -> FindResponse: + """Find files and directories""" + return self._do_json( + FindResponse, + _ApiRequest( + method="GET", + path_fmt="/filesystem-find/{}", + path_args=[path], + body=None, + query=params, + success_codes=[200], + error_codes={ + 400: "ErrorResponse", + 422: "ErrorResponse", + 500: "ErrorResponse", + }, + ), + ) + + def get_filesystem_multipart(self) -> MultipartListUploadsResponse: + """List multipart uploads""" + return self._do_json( + MultipartListUploadsResponse, + _ApiRequest( + method="GET", + path_fmt="/filesystem-multipart", + path_args=[], + body=None, + query=None, + success_codes=[200], + error_codes={500: "ErrorResponse"}, + ), + ) + + def get_filesystem_multipart_parts( + self, *, upload_id: str + ) -> MultipartListPartsResponse: + """List parts""" + return self._do_json( + MultipartListPartsResponse, + _ApiRequest( + method="GET", + path_fmt="/filesystem-multipart/{}/parts", + path_args=[upload_id], + body=None, + query=None, + success_codes=[200], + error_codes={ + 400: "ErrorResponse", + 404: "ErrorResponse", + 500: "ErrorResponse", + }, + ), + ) + + def get_filesystem_search( + self, *, path: str, params: GetFilesystemSearchParams | None = None + ) -> FuzzySearchResponse: + """Fuzzy search for files and directories""" + return self._do_json( + FuzzySearchResponse, + _ApiRequest( + method="GET", + path_fmt="/filesystem-search/{}", + path_args=[path], + body=None, + query=params, + success_codes=[200], + error_codes={ + 400: "ErrorResponse", + 422: "ErrorResponse", + 500: "ErrorResponse", + }, + ), + ) + + def get_filesystem_tree(self, *, path: str) -> GetFilesystemTreeResponse: + """Get directory tree""" + return self._do_json( + GetFilesystemTreeResponse, + _ApiRequest( + method="GET", + path_fmt="/filesystem/tree/{}", + path_args=[path], + body=None, + query=None, + success_codes=[200], + error_codes={ + 400: "ErrorResponse", + 422: "ErrorResponse", + 500: "ErrorResponse", + }, + ), + ) + + def get_health(self) -> HealthResponse: + """Health check""" + return self._do_json( + HealthResponse, + _ApiRequest( + method="GET", + path_fmt="/health", + path_args=[], + body=None, + query=None, + success_codes=[200], + error_codes=None, + ), + ) + + def get_network_process_ports(self, *, pid: str) -> GetNetworkProcessPortsResponse: + """Get open ports for a process""" + return self._do_json( + GetNetworkProcessPortsResponse, + _ApiRequest( + method="GET", + path_fmt="/network/process/{}/ports", + path_args=[pid], + body=None, + query=None, + success_codes=[200], + error_codes={ + 400: "ErrorResponse", + 422: "ErrorResponse", + 500: "ErrorResponse", + }, + ), + ) + + def get_process(self) -> GetProcessResponse: + """List all processes""" + return self._do_json( + GetProcessResponse, + _ApiRequest( + method="GET", + path_fmt="/process", + path_args=[], + body=None, + query=None, + success_codes=[200], + error_codes=None, + ), + ) + + def get_process_identifier(self, *, identifier: str) -> ProcessResponse: + """Get process by identifier""" + return self._do_json( + ProcessResponse, + _ApiRequest( + method="GET", + path_fmt="/process/{}", + path_args=[identifier], + body=None, + query=None, + success_codes=[200], + error_codes={404: "ErrorResponse"}, + ), + ) + + def get_process_logs(self, *, identifier: str) -> ProcessLogs: + """Get process logs""" + return self._do_json( + ProcessLogs, + _ApiRequest( + method="GET", + path_fmt="/process/{}/logs", + path_args=[identifier], + body=None, + query=None, + success_codes=[200], + error_codes={ + 404: "ErrorResponse", + 422: "ErrorResponse", + 500: "ErrorResponse", + }, + ), + ) + + def get_process_logs_stream(self, *, identifier: str) -> httpx.Response: + """Stream process logs in real time. Returns the response unread, in the requested content type.""" + return self._do( + _ApiRequest( + method="GET", + path_fmt="/process/{}/logs/stream", + path_args=[identifier], + body=None, + query=None, + success_codes=[200], + error_codes=None, + accept="text/plain", + ) + ) + + def get_watch_filesystem( + self, *, path: str, params: GetWatchFilesystemParams | None = None + ) -> httpx.Response: + """Stream file modification events in a directory. Returns the response unread, in the requested content type.""" + return self._do( + _ApiRequest( + method="GET", + path_fmt="/watch/filesystem/{}", + path_args=[path], + body=None, + query=params, + success_codes=[200], + error_codes=None, + accept="text/plain", + ) + ) + + def post_archive_export( + self, *, request: ExportOptions + ) -> ExportResult | ExportProgress: + """Export the filesystem changes to a presigned URL""" + return self._do_json_with_status( + {200: ExportResult, 202: ExportProgress}, + _ApiRequest( + method="POST", + path_fmt="/archive/export", + path_args=[], + body=request, + query=None, + success_codes=[200, 202], + error_codes={ + 400: "ErrorResponse", + 409: "ErrorResponse", + 500: "ErrorResponse", + }, + ), + ) + + def post_archive_resume(self) -> QuiesceStatus: + """Lift the archive freeze""" + return self._do_json( + QuiesceStatus, + _ApiRequest( + method="POST", + path_fmt="/archive/resume", + path_args=[], + body=None, + query=None, + success_codes=[200], + error_codes={409: "ErrorResponse", 500: "ErrorResponse"}, + ), + ) + + def post_drives_mount(self, *, request: DriveMountRequest) -> DriveMountResponse: + """Attach a drive to a local path""" + return self._do_json( + DriveMountResponse, + _ApiRequest( + method="POST", + path_fmt="/drives/mount", + path_args=[], + body=request, + query=None, + success_codes=[200], + error_codes={ + 400: "ErrorResponse", + 403: "ErrorResponse", + 409: "ErrorResponse", + 500: "ErrorResponse", + }, + ), + ) + + def post_environment_reload(self) -> HandlerReloadResponse: + """Reload environment from guest metadata""" + return self._do_json( + HandlerReloadResponse, + _ApiRequest( + method="POST", + path_fmt="/environment/reload", + path_args=[], + body=None, + query=None, + success_codes=[200], + error_codes={404: "ErrorResponse", 500: "ErrorResponse"}, + ), + ) + + def post_filesystem_multipart_complete( + self, *, upload_id: str, request: MultipartCompleteRequest + ) -> SuccessResponse: + """Complete multipart upload""" + return self._do_json( + SuccessResponse, + _ApiRequest( + method="POST", + path_fmt="/filesystem-multipart/{}/complete", + path_args=[upload_id], + body=request, + query=None, + success_codes=[200], + error_codes={ + 400: "ErrorResponse", + 404: "ErrorResponse", + 500: "ErrorResponse", + }, + ), + ) + + def post_filesystem_multipart_initiate( + self, *, path: str, request: MultipartInitiateRequest + ) -> MultipartInitiateResponse: + """Initiate multipart upload""" + return self._do_json( + MultipartInitiateResponse, + _ApiRequest( + method="POST", + path_fmt="/filesystem-multipart/initiate/{}", + path_args=[path], + body=request, + query=None, + success_codes=[200], + error_codes={400: "ErrorResponse", 500: "ErrorResponse"}, + ), + ) + + def post_network_process_monitor( + self, *, pid: str, request: PortMonitorRequest + ) -> PostNetworkProcessMonitorResponse: + """Start monitoring ports for a process""" + return self._do_json( + PostNetworkProcessMonitorResponse, + _ApiRequest( + method="POST", + path_fmt="/network/process/{}/monitor", + path_args=[pid], + body=request, + query=None, + success_codes=[200], + error_codes={ + 400: "ErrorResponse", + 422: "ErrorResponse", + 500: "ErrorResponse", + }, + ), + ) + + def post_process(self, *, request: ProcessRequest) -> ProcessResponse: + """Execute a command""" + return self._do_json( + ProcessResponse, + _ApiRequest( + method="POST", + path_fmt="/process", + path_args=[], + body=request, + query=None, + success_codes=[200], + error_codes={ + 400: "ErrorResponse", + 422: "ErrorResponse", + 500: "ErrorResponse", + }, + ), + ) + + def post_process_raw( + self, + *, + request: ProcessRequest, + accept: Literal["application/json", "text/event-stream"], + ) -> httpx.Response: + """Execute a command. Returns the response unread, in the requested content type.""" + return self._do( + _ApiRequest( + method="POST", + path_fmt="/process", + path_args=[], + body=request, + query=None, + success_codes=[200], + error_codes={ + 400: "ErrorResponse", + 422: "ErrorResponse", + 500: "ErrorResponse", + }, + accept=accept, + ) + ) + + def post_process_stdin( + self, *, identifier: str, content: bytes | IO[bytes] | str + ) -> SuccessResponse: + """Write to a process's stdin""" + return self._do_json( + SuccessResponse, + _ApiRequest( + method="POST", + path_fmt="/process/{}/stdin", + path_args=[identifier], + body=content, + query=None, + success_codes=[200], + error_codes={ + 404: "ErrorResponse", + 409: "ErrorResponse", + 413: "ErrorResponse", + 500: "ErrorResponse", + 503: "ErrorResponse", + }, + body_content_type="application/octet-stream", + ), + ) + + def post_upgrade(self, *, request: UpgradeRequest) -> SuccessResponse: + """Upgrade the sandbox-api""" + return self._do_json( + SuccessResponse, + _ApiRequest( + method="POST", + path_fmt="/upgrade", + path_args=[], + body=request, + query=None, + success_codes=[200], + error_codes={500: "ErrorResponse"}, + ), + ) + + def put_codegen_fastapply( + self, *, path: str, request: ApplyEditRequest + ) -> ApplyEditResponse: + """Apply code edit""" + return self._do_json( + ApplyEditResponse, + _ApiRequest( + method="PUT", + path_fmt="/codegen/fastapply/{}", + path_args=[path], + body=request, + query=None, + success_codes=[200], + error_codes={ + 400: "ErrorResponse", + 422: "ErrorResponse", + 503: "ErrorResponse", + }, + ), + ) + + def put_filesystem(self, *, path: str, request: FileRequest) -> SuccessResponse: + """Create or update a file or directory""" + return self._do_json( + SuccessResponse, + _ApiRequest( + method="PUT", + path_fmt="/filesystem/{}", + path_args=[path], + body=request, + query=None, + success_codes=[200], + error_codes={ + 400: "ErrorResponse", + 422: "ErrorResponse", + 500: "ErrorResponse", + }, + ), + ) + + def put_filesystem_multipart_part( + self, *, upload_id: str, params: PutFilesystemMultipartPartParams, files: Any + ) -> MultipartUploadPartResponse: + """Upload part""" + return self._do_json( + MultipartUploadPartResponse, + _ApiRequest( + method="PUT", + path_fmt="/filesystem-multipart/{}/part", + path_args=[upload_id], + body=files, + query=params, + success_codes=[200], + error_codes={ + 400: "ErrorResponse", + 404: "ErrorResponse", + 500: "ErrorResponse", + }, + body_content_type="multipart/form-data", + ), + ) + + def put_filesystem_tree( + self, *, path: str, request: TreeRequest + ) -> PutFilesystemTreeResponse: + """Create or update directory tree""" + return self._do_json( + PutFilesystemTreeResponse, + _ApiRequest( + method="PUT", + path_fmt="/filesystem/tree/{}", + path_args=[path], + body=request, + query=None, + success_codes=[200], + error_codes={ + 400: "ErrorResponse", + 422: "ErrorResponse", + 500: "ErrorResponse", + }, + ), + ) + + def put_network_tunnel_config( + self, *, request: TunnelConfigRequest + ) -> SuccessResponse: + """Update tunnel configuration""" + return self._do_json( + SuccessResponse, + _ApiRequest( + method="PUT", + path_fmt="/network/tunnel/config", + path_args=[], + body=request, + query=None, + success_codes=[200], + error_codes={ + 400: "ErrorResponse", + 422: "ErrorResponse", + 500: "ErrorResponse", + }, + ), + ) + + def _do(self, request: _ApiRequest) -> httpx.Response: + path = request.path_fmt.format( + *[urllib.parse.quote(a, safe="") for a in request.path_args] + ) + json_body = None + content_body = None + files_body = None + headers: dict[str, str] = {} + if request.accept is not None: + headers["Accept"] = request.accept + if request.body is not None: + if request.body_content_type is None: + if isinstance(request.body, BaseModel): + # Only fields the caller set are sent, so unset fields fall + # back to the server default rather than being reset here. + # An explicit None is kept, since null can mean "clear". + json_body = request.body.model_dump(mode="json", exclude_unset=True) + else: + json_body = request.body + elif request.body_content_type == "multipart/form-data": + # httpx derives the multipart Content-Type, boundary included. + files_body = request.body + else: + headers["Content-Type"] = request.body_content_type + content_body = request.body + params = None + if request.query is not None: + if isinstance(request.query, BaseModel): + # As above, plus dropping None: a null query parameter is + # meaningless and would otherwise serialize as an empty string. + params = request.query.model_dump( + mode="json", exclude_unset=True, exclude_none=True + ) + else: + params = request.query + response = self._http_client.request( + request.method, + path, + json=json_body, + content=content_body, + files=files_body, + params=params, + headers=headers, + ) + if response.status_code not in request.success_codes: + if request.error_codes and response.status_code in request.error_codes: + error_name = request.error_codes[response.status_code] + if error_name in _ERROR_TYPES: + model_cls, exc_cls, field_name = _ERROR_TYPES[error_name] + # A body that does not match the declared error schema + # falls through to the generic ResponseError below. + model = None + with contextlib.suppress(ValidationError): + model = model_cls.model_validate_json(response.content) + if model is not None: + raise exc_cls( + status_code=response.status_code, # ty: ignore[unknown-argument] + **{field_name: model}, + ) + raise ResponseError(status_code=response.status_code, body=response.text) + return response + + def _do_json(self, response_type: type[_T], request: _ApiRequest) -> _T: + response = self._do(request) + content_type = response.headers.get("content-type", "") + if not content_type.startswith("application/json"): + raise ValueError( + f"unexpected content type {content_type!r}, expected application/json" + ) + return response_type.model_validate_json(response.content) + + def _do_json_with_status( + self, response_types: Mapping[int, type[_T]], request: _ApiRequest + ) -> _T: + response = self._do(request) + response_type = response_types.get(response.status_code) + if response_type is None: + raise ValueError( + f"no JSON response schema declared for HTTP {response.status_code}" + ) + content_type = response.headers.get("content-type", "") + if not content_type.startswith("application/json"): + raise ValueError( + f"unexpected content type {content_type!r}, expected application/json" + ) + return response_type.model_validate_json(response.content) + + +class AsyncApiClient: + """Generated HTTP client for the Baseten API. + + Methods on this client are generated from the OpenAPI specification + and are NOT covered by any stability or compatibility guarantees. + They may change without notice between versions. + """ + + def __init__(self, http_client: httpx.AsyncClient) -> None: + """Create a new client. The caller is responsible for closing *http_client*.""" + self._http_client = http_client + + async def delete_drives_mount(self, *, mount_path: str) -> DriveUnmountResponse: + """Detach a drive from a local path""" + return await self._do_json( + DriveUnmountResponse, + _ApiRequest( + method="DELETE", + path_fmt="/drives/mount/{}", + path_args=[mount_path], + body=None, + query=None, + success_codes=[200], + error_codes={400: "ErrorResponse", 500: "ErrorResponse"}, + ), + ) + + async def delete_filesystem( + self, *, path: str, params: DeleteFilesystemParams | None = None + ) -> SuccessResponse: + """Delete file or directory""" + return await self._do_json( + SuccessResponse, + _ApiRequest( + method="DELETE", + path_fmt="/filesystem/{}", + path_args=[path], + body=None, + query=params, + success_codes=[200], + error_codes={ + 404: "ErrorResponse", + 422: "ErrorResponse", + 500: "ErrorResponse", + }, + ), + ) + + async def delete_filesystem_multipart_abort( + self, *, upload_id: str + ) -> SuccessResponse: + """Abort multipart upload""" + return await self._do_json( + SuccessResponse, + _ApiRequest( + method="DELETE", + path_fmt="/filesystem-multipart/{}/abort", + path_args=[upload_id], + body=None, + query=None, + success_codes=[200], + error_codes={ + 400: "ErrorResponse", + 404: "ErrorResponse", + 500: "ErrorResponse", + }, + ), + ) + + async def delete_filesystem_tree( + self, *, path: str, params: DeleteFilesystemTreeParams | None = None + ) -> SuccessResponse: + """Delete directory tree""" + return await self._do_json( + SuccessResponse, + _ApiRequest( + method="DELETE", + path_fmt="/filesystem/tree/{}", + path_args=[path], + body=None, + query=params, + success_codes=[200], + error_codes={ + 400: "ErrorResponse", + 422: "ErrorResponse", + 500: "ErrorResponse", + }, + ), + ) + + async def delete_network_process_monitor( + self, *, pid: str + ) -> DeleteNetworkProcessMonitorResponse: + """Stop monitoring ports for a process""" + return await self._do_json( + DeleteNetworkProcessMonitorResponse, + _ApiRequest( + method="DELETE", + path_fmt="/network/process/{}/monitor", + path_args=[pid], + body=None, + query=None, + success_codes=[200], + error_codes={ + 400: "ErrorResponse", + 422: "ErrorResponse", + 500: "ErrorResponse", + }, + ), + ) + + async def delete_network_tunnel(self) -> SuccessResponse: + """Disconnect tunnel""" + return await self._do_json( + SuccessResponse, + _ApiRequest( + method="DELETE", + path_fmt="/network/tunnel", + path_args=[], + body=None, + query=None, + success_codes=[200], + error_codes={400: "ErrorResponse", 500: "ErrorResponse"}, + ), + ) + + async def delete_process(self, *, identifier: str) -> SuccessResponse: + """Stop a process""" + return await self._do_json( + SuccessResponse, + _ApiRequest( + method="DELETE", + path_fmt="/process/{}", + path_args=[identifier], + body=None, + query=None, + success_codes=[200], + error_codes={ + 404: "ErrorResponse", + 422: "ErrorResponse", + 500: "ErrorResponse", + }, + ), + ) + + async def delete_process_kill(self, *, identifier: str) -> SuccessResponse: + """Kill a process""" + return await self._do_json( + SuccessResponse, + _ApiRequest( + method="DELETE", + path_fmt="/process/{}/kill", + path_args=[identifier], + body=None, + query=None, + success_codes=[200], + error_codes={ + 404: "ErrorResponse", + 422: "ErrorResponse", + 500: "ErrorResponse", + }, + ), + ) + + async def delete_process_stdin(self, *, identifier: str) -> SuccessResponse: + """Close a process's stdin""" + return await self._do_json( + SuccessResponse, + _ApiRequest( + method="DELETE", + path_fmt="/process/{}/stdin", + path_args=[identifier], + body=None, + query=None, + success_codes=[200], + error_codes={404: "ErrorResponse", 409: "ErrorResponse"}, + ), + ) + + async def get_archive_status(self) -> QuiesceStatus: + """Get the archive status""" + return await self._do_json( + QuiesceStatus, + _ApiRequest( + method="GET", + path_fmt="/archive/status", + path_args=[], + body=None, + query=None, + success_codes=[200], + error_codes=None, + ), + ) + + async def get_codegen_reranking( + self, *, path: str, params: GetCodegenRerankingParams + ) -> RerankingResponse: + """Code reranking/semantic search""" + return await self._do_json( + RerankingResponse, + _ApiRequest( + method="GET", + path_fmt="/codegen/reranking/{}", + path_args=[path], + body=None, + query=params, + success_codes=[200], + error_codes={ + 400: "ErrorResponse", + 422: "ErrorResponse", + 503: "ErrorResponse", + }, + ), + ) + + async def get_drives_mount(self) -> DriveListResponse: + """List currently mounted drives""" + return await self._do_json( + DriveListResponse, + _ApiRequest( + method="GET", + path_fmt="/drives/mount", + path_args=[], + body=None, + query=None, + success_codes=[200], + error_codes={500: "ErrorResponse"}, + ), + ) + + async def get_filesystem( + self, *, path: str, params: GetFilesystemParams | None = None + ) -> GetFilesystemResponse: + """Get file or directory information""" + return await self._do_json( + GetFilesystemResponse, + _ApiRequest( + method="GET", + path_fmt="/filesystem/{}", + path_args=[path], + body=None, + query=params, + success_codes=[200], + error_codes={ + 404: "ErrorResponse", + 422: "ErrorResponse", + 500: "ErrorResponse", + }, + ), + ) + + async def get_filesystem_raw( + self, + *, + path: str, + params: GetFilesystemParams | None = None, + accept: Literal["application/json", "application/octet-stream"], + ) -> httpx.Response: + """Get file or directory information. Returns the response unread, in the requested content type.""" + return await self._do( + _ApiRequest( + method="GET", + path_fmt="/filesystem/{}", + path_args=[path], + body=None, + query=params, + success_codes=[200], + error_codes={ + 404: "ErrorResponse", + 422: "ErrorResponse", + 500: "ErrorResponse", + }, + accept=accept, + ) + ) + + async def get_filesystem_content_search( + self, *, path: str, params: GetFilesystemContentSearchParams + ) -> ContentSearchResponse: + """Search for text content in files""" + return await self._do_json( + ContentSearchResponse, + _ApiRequest( + method="GET", + path_fmt="/filesystem-content-search/{}", + path_args=[path], + body=None, + query=params, + success_codes=[200], + error_codes={ + 400: "ErrorResponse", + 422: "ErrorResponse", + 500: "ErrorResponse", + }, + ), + ) + + async def get_filesystem_find( + self, *, path: str, params: GetFilesystemFindParams | None = None + ) -> FindResponse: + """Find files and directories""" + return await self._do_json( + FindResponse, + _ApiRequest( + method="GET", + path_fmt="/filesystem-find/{}", + path_args=[path], + body=None, + query=params, + success_codes=[200], + error_codes={ + 400: "ErrorResponse", + 422: "ErrorResponse", + 500: "ErrorResponse", + }, + ), + ) + + async def get_filesystem_multipart(self) -> MultipartListUploadsResponse: + """List multipart uploads""" + return await self._do_json( + MultipartListUploadsResponse, + _ApiRequest( + method="GET", + path_fmt="/filesystem-multipart", + path_args=[], + body=None, + query=None, + success_codes=[200], + error_codes={500: "ErrorResponse"}, + ), + ) + + async def get_filesystem_multipart_parts( + self, *, upload_id: str + ) -> MultipartListPartsResponse: + """List parts""" + return await self._do_json( + MultipartListPartsResponse, + _ApiRequest( + method="GET", + path_fmt="/filesystem-multipart/{}/parts", + path_args=[upload_id], + body=None, + query=None, + success_codes=[200], + error_codes={ + 400: "ErrorResponse", + 404: "ErrorResponse", + 500: "ErrorResponse", + }, + ), + ) + + async def get_filesystem_search( + self, *, path: str, params: GetFilesystemSearchParams | None = None + ) -> FuzzySearchResponse: + """Fuzzy search for files and directories""" + return await self._do_json( + FuzzySearchResponse, + _ApiRequest( + method="GET", + path_fmt="/filesystem-search/{}", + path_args=[path], + body=None, + query=params, + success_codes=[200], + error_codes={ + 400: "ErrorResponse", + 422: "ErrorResponse", + 500: "ErrorResponse", + }, + ), + ) + + async def get_filesystem_tree(self, *, path: str) -> GetFilesystemTreeResponse: + """Get directory tree""" + return await self._do_json( + GetFilesystemTreeResponse, + _ApiRequest( + method="GET", + path_fmt="/filesystem/tree/{}", + path_args=[path], + body=None, + query=None, + success_codes=[200], + error_codes={ + 400: "ErrorResponse", + 422: "ErrorResponse", + 500: "ErrorResponse", + }, + ), + ) + + async def get_health(self) -> HealthResponse: + """Health check""" + return await self._do_json( + HealthResponse, + _ApiRequest( + method="GET", + path_fmt="/health", + path_args=[], + body=None, + query=None, + success_codes=[200], + error_codes=None, + ), + ) + + async def get_network_process_ports( + self, *, pid: str + ) -> GetNetworkProcessPortsResponse: + """Get open ports for a process""" + return await self._do_json( + GetNetworkProcessPortsResponse, + _ApiRequest( + method="GET", + path_fmt="/network/process/{}/ports", + path_args=[pid], + body=None, + query=None, + success_codes=[200], + error_codes={ + 400: "ErrorResponse", + 422: "ErrorResponse", + 500: "ErrorResponse", + }, + ), + ) + + async def get_process(self) -> GetProcessResponse: + """List all processes""" + return await self._do_json( + GetProcessResponse, + _ApiRequest( + method="GET", + path_fmt="/process", + path_args=[], + body=None, + query=None, + success_codes=[200], + error_codes=None, + ), + ) + + async def get_process_identifier(self, *, identifier: str) -> ProcessResponse: + """Get process by identifier""" + return await self._do_json( + ProcessResponse, + _ApiRequest( + method="GET", + path_fmt="/process/{}", + path_args=[identifier], + body=None, + query=None, + success_codes=[200], + error_codes={404: "ErrorResponse"}, + ), + ) + + async def get_process_logs(self, *, identifier: str) -> ProcessLogs: + """Get process logs""" + return await self._do_json( + ProcessLogs, + _ApiRequest( + method="GET", + path_fmt="/process/{}/logs", + path_args=[identifier], + body=None, + query=None, + success_codes=[200], + error_codes={ + 404: "ErrorResponse", + 422: "ErrorResponse", + 500: "ErrorResponse", + }, + ), + ) + + async def get_process_logs_stream(self, *, identifier: str) -> httpx.Response: + """Stream process logs in real time. Returns the response unread, in the requested content type.""" + return await self._do( + _ApiRequest( + method="GET", + path_fmt="/process/{}/logs/stream", + path_args=[identifier], + body=None, + query=None, + success_codes=[200], + error_codes=None, + accept="text/plain", + ) + ) + + async def get_watch_filesystem( + self, *, path: str, params: GetWatchFilesystemParams | None = None + ) -> httpx.Response: + """Stream file modification events in a directory. Returns the response unread, in the requested content type.""" + return await self._do( + _ApiRequest( + method="GET", + path_fmt="/watch/filesystem/{}", + path_args=[path], + body=None, + query=params, + success_codes=[200], + error_codes=None, + accept="text/plain", + ) + ) + + async def post_archive_export( + self, *, request: ExportOptions + ) -> ExportResult | ExportProgress: + """Export the filesystem changes to a presigned URL""" + return await self._do_json_with_status( + {200: ExportResult, 202: ExportProgress}, + _ApiRequest( + method="POST", + path_fmt="/archive/export", + path_args=[], + body=request, + query=None, + success_codes=[200, 202], + error_codes={ + 400: "ErrorResponse", + 409: "ErrorResponse", + 500: "ErrorResponse", + }, + ), + ) + + async def post_archive_resume(self) -> QuiesceStatus: + """Lift the archive freeze""" + return await self._do_json( + QuiesceStatus, + _ApiRequest( + method="POST", + path_fmt="/archive/resume", + path_args=[], + body=None, + query=None, + success_codes=[200], + error_codes={409: "ErrorResponse", 500: "ErrorResponse"}, + ), + ) + + async def post_drives_mount( + self, *, request: DriveMountRequest + ) -> DriveMountResponse: + """Attach a drive to a local path""" + return await self._do_json( + DriveMountResponse, + _ApiRequest( + method="POST", + path_fmt="/drives/mount", + path_args=[], + body=request, + query=None, + success_codes=[200], + error_codes={ + 400: "ErrorResponse", + 403: "ErrorResponse", + 409: "ErrorResponse", + 500: "ErrorResponse", + }, + ), + ) + + async def post_environment_reload(self) -> HandlerReloadResponse: + """Reload environment from guest metadata""" + return await self._do_json( + HandlerReloadResponse, + _ApiRequest( + method="POST", + path_fmt="/environment/reload", + path_args=[], + body=None, + query=None, + success_codes=[200], + error_codes={404: "ErrorResponse", 500: "ErrorResponse"}, + ), + ) + + async def post_filesystem_multipart_complete( + self, *, upload_id: str, request: MultipartCompleteRequest + ) -> SuccessResponse: + """Complete multipart upload""" + return await self._do_json( + SuccessResponse, + _ApiRequest( + method="POST", + path_fmt="/filesystem-multipart/{}/complete", + path_args=[upload_id], + body=request, + query=None, + success_codes=[200], + error_codes={ + 400: "ErrorResponse", + 404: "ErrorResponse", + 500: "ErrorResponse", + }, + ), + ) + + async def post_filesystem_multipart_initiate( + self, *, path: str, request: MultipartInitiateRequest + ) -> MultipartInitiateResponse: + """Initiate multipart upload""" + return await self._do_json( + MultipartInitiateResponse, + _ApiRequest( + method="POST", + path_fmt="/filesystem-multipart/initiate/{}", + path_args=[path], + body=request, + query=None, + success_codes=[200], + error_codes={400: "ErrorResponse", 500: "ErrorResponse"}, + ), + ) + + async def post_network_process_monitor( + self, *, pid: str, request: PortMonitorRequest + ) -> PostNetworkProcessMonitorResponse: + """Start monitoring ports for a process""" + return await self._do_json( + PostNetworkProcessMonitorResponse, + _ApiRequest( + method="POST", + path_fmt="/network/process/{}/monitor", + path_args=[pid], + body=request, + query=None, + success_codes=[200], + error_codes={ + 400: "ErrorResponse", + 422: "ErrorResponse", + 500: "ErrorResponse", + }, + ), + ) + + async def post_process(self, *, request: ProcessRequest) -> ProcessResponse: + """Execute a command""" + return await self._do_json( + ProcessResponse, + _ApiRequest( + method="POST", + path_fmt="/process", + path_args=[], + body=request, + query=None, + success_codes=[200], + error_codes={ + 400: "ErrorResponse", + 422: "ErrorResponse", + 500: "ErrorResponse", + }, + ), + ) + + async def post_process_raw( + self, + *, + request: ProcessRequest, + accept: Literal["application/json", "text/event-stream"], + ) -> httpx.Response: + """Execute a command. Returns the response unread, in the requested content type.""" + return await self._do( + _ApiRequest( + method="POST", + path_fmt="/process", + path_args=[], + body=request, + query=None, + success_codes=[200], + error_codes={ + 400: "ErrorResponse", + 422: "ErrorResponse", + 500: "ErrorResponse", + }, + accept=accept, + ) + ) + + async def post_process_stdin( + self, *, identifier: str, content: bytes | IO[bytes] | str + ) -> SuccessResponse: + """Write to a process's stdin""" + return await self._do_json( + SuccessResponse, + _ApiRequest( + method="POST", + path_fmt="/process/{}/stdin", + path_args=[identifier], + body=content, + query=None, + success_codes=[200], + error_codes={ + 404: "ErrorResponse", + 409: "ErrorResponse", + 413: "ErrorResponse", + 500: "ErrorResponse", + 503: "ErrorResponse", + }, + body_content_type="application/octet-stream", + ), + ) + + async def post_upgrade(self, *, request: UpgradeRequest) -> SuccessResponse: + """Upgrade the sandbox-api""" + return await self._do_json( + SuccessResponse, + _ApiRequest( + method="POST", + path_fmt="/upgrade", + path_args=[], + body=request, + query=None, + success_codes=[200], + error_codes={500: "ErrorResponse"}, + ), + ) + + async def put_codegen_fastapply( + self, *, path: str, request: ApplyEditRequest + ) -> ApplyEditResponse: + """Apply code edit""" + return await self._do_json( + ApplyEditResponse, + _ApiRequest( + method="PUT", + path_fmt="/codegen/fastapply/{}", + path_args=[path], + body=request, + query=None, + success_codes=[200], + error_codes={ + 400: "ErrorResponse", + 422: "ErrorResponse", + 503: "ErrorResponse", + }, + ), + ) + + async def put_filesystem( + self, *, path: str, request: FileRequest + ) -> SuccessResponse: + """Create or update a file or directory""" + return await self._do_json( + SuccessResponse, + _ApiRequest( + method="PUT", + path_fmt="/filesystem/{}", + path_args=[path], + body=request, + query=None, + success_codes=[200], + error_codes={ + 400: "ErrorResponse", + 422: "ErrorResponse", + 500: "ErrorResponse", + }, + ), + ) + + async def put_filesystem_multipart_part( + self, *, upload_id: str, params: PutFilesystemMultipartPartParams, files: Any + ) -> MultipartUploadPartResponse: + """Upload part""" + return await self._do_json( + MultipartUploadPartResponse, + _ApiRequest( + method="PUT", + path_fmt="/filesystem-multipart/{}/part", + path_args=[upload_id], + body=files, + query=params, + success_codes=[200], + error_codes={ + 400: "ErrorResponse", + 404: "ErrorResponse", + 500: "ErrorResponse", + }, + body_content_type="multipart/form-data", + ), + ) + + async def put_filesystem_tree( + self, *, path: str, request: TreeRequest + ) -> PutFilesystemTreeResponse: + """Create or update directory tree""" + return await self._do_json( + PutFilesystemTreeResponse, + _ApiRequest( + method="PUT", + path_fmt="/filesystem/tree/{}", + path_args=[path], + body=request, + query=None, + success_codes=[200], + error_codes={ + 400: "ErrorResponse", + 422: "ErrorResponse", + 500: "ErrorResponse", + }, + ), + ) + + async def put_network_tunnel_config( + self, *, request: TunnelConfigRequest + ) -> SuccessResponse: + """Update tunnel configuration""" + return await self._do_json( + SuccessResponse, + _ApiRequest( + method="PUT", + path_fmt="/network/tunnel/config", + path_args=[], + body=request, + query=None, + success_codes=[200], + error_codes={ + 400: "ErrorResponse", + 422: "ErrorResponse", + 500: "ErrorResponse", + }, + ), + ) + + async def _do(self, request: _ApiRequest) -> httpx.Response: + path = request.path_fmt.format( + *[urllib.parse.quote(a, safe="") for a in request.path_args] + ) + json_body = None + content_body = None + files_body = None + headers: dict[str, str] = {} + if request.accept is not None: + headers["Accept"] = request.accept + if request.body is not None: + if request.body_content_type is None: + if isinstance(request.body, BaseModel): + # Only fields the caller set are sent, so unset fields fall + # back to the server default rather than being reset here. + # An explicit None is kept, since null can mean "clear". + json_body = request.body.model_dump(mode="json", exclude_unset=True) + else: + json_body = request.body + elif request.body_content_type == "multipart/form-data": + # httpx derives the multipart Content-Type, boundary included. + files_body = request.body + else: + headers["Content-Type"] = request.body_content_type + content_body = request.body + params = None + if request.query is not None: + if isinstance(request.query, BaseModel): + # As above, plus dropping None: a null query parameter is + # meaningless and would otherwise serialize as an empty string. + params = request.query.model_dump( + mode="json", exclude_unset=True, exclude_none=True + ) + else: + params = request.query + response = await self._http_client.request( + request.method, + path, + json=json_body, + content=content_body, + files=files_body, + params=params, + headers=headers, + ) + if response.status_code not in request.success_codes: + if request.error_codes and response.status_code in request.error_codes: + error_name = request.error_codes[response.status_code] + if error_name in _ERROR_TYPES: + model_cls, exc_cls, field_name = _ERROR_TYPES[error_name] + # A body that does not match the declared error schema + # falls through to the generic ResponseError below. + model = None + with contextlib.suppress(ValidationError): + model = model_cls.model_validate_json(response.content) + if model is not None: + raise exc_cls( + status_code=response.status_code, # ty: ignore[unknown-argument] + **{field_name: model}, + ) + raise ResponseError(status_code=response.status_code, body=response.text) + return response + + async def _do_json(self, response_type: type[_T], request: _ApiRequest) -> _T: + response = await self._do(request) + content_type = response.headers.get("content-type", "") + if not content_type.startswith("application/json"): + raise ValueError( + f"unexpected content type {content_type!r}, expected application/json" + ) + return response_type.model_validate_json(response.content) + + async def _do_json_with_status( + self, response_types: Mapping[int, type[_T]], request: _ApiRequest + ) -> _T: + response = await self._do(request) + response_type = response_types.get(response.status_code) + if response_type is None: + raise ValueError( + f"no JSON response schema declared for HTTP {response.status_code}" + ) + content_type = response.headers.get("content-type", "") + if not content_type.startswith("application/json"): + raise ValueError( + f"unexpected content type {content_type!r}, expected application/json" + ) + return response_type.model_validate_json(response.content) diff --git a/baseten/client/sandboxapi/_models.py b/baseten/client/sandboxapi/_models.py new file mode 100644 index 0000000..f81b964 --- /dev/null +++ b/baseten/client/sandboxapi/_models.py @@ -0,0 +1,927 @@ +# generated by datamodel-codegen: +# filename: + +from __future__ import annotations + +from enum import StrEnum +from typing import Annotated + +from pydantic import BaseModel, ConfigDict, Field, RootModel + + +class ApplyEditRequest(BaseModel): + codeEdit: Annotated[ + str, + Field( + examples=[ + "// Add world parameter\nfunction hello(world) {\n console.log('Hello', world);\n}" + ] + ), + ] + model: Annotated[str | None, Field(examples=["relace-apply-3"])] = None + + +class ApplyEditResponse(BaseModel): + message: Annotated[ + str | None, Field(examples=["Code edit applied successfully"]) + ] = None + originalContent: Annotated[ + str | None, Field(examples=["function hello() {\n console.log('Hello');\n}"]) + ] = None + path: Annotated[str | None, Field(examples=["src/main.js"])] = None + provider: Annotated[str | None, Field(examples=["Relace"])] = None + success: Annotated[bool | None, Field(examples=[True])] = None + updatedContent: Annotated[ + str | None, + Field(examples=["function hello(world) {\n console.log('Hello', world);\n}"]), + ] = None + + +class ArchiveManifest(BaseModel): + added: Annotated[ + int | None, + Field( + description="Added and Modified count the archive's payload members.", + examples=[11], + ), + ] = None + apiVersion: Annotated[ + str | None, + Field( + description="APIVersion is the sandbox-api build that produced the archive.", + examples=["v0.1.0"], + ), + ] = None + createdAt: str + deleted: Annotated[ + list[str] | None, + Field( + description="Deleted are paths the image has and the sandbox deleted. Tar cannot carry\na deletion, so import applies these from the manifest." + ), + ] = None + excludes: Annotated[ + list[str] | None, + Field(description="Excludes are the paths left out of the comparison."), + ] = None + imageDevice: Annotated[ + str | None, + Field( + description="ImageDevice is the device the pristine image was read from, for the record:\nit says where the sandbox that exported the archive found its image.", + examples=["/dev/vda"], + ), + ] = None + modified: Annotated[int | None, Field(examples=[3])] = None + payloadBytes: Annotated[ + int | None, + Field( + description="PayloadBytes is the total content size of the payload members.", + examples=[3073449], + ), + ] = None + processes: Annotated[ + bool | None, + Field( + description="Processes tells whether ProcessesName is present.", + examples=[True], + ), + ] = None + root: Annotated[ + str, + Field( + description="Root is the directory the paths are relative to.", + examples=["/"], + ), + ] + version: Annotated[int, Field(examples=[1])] + + +class ContentSearchMatch(BaseModel): + column: Annotated[int, Field(examples=[10])] + context: Annotated[ + str | None, Field(examples=["previous line\ncurrent line\nnext line"]) + ] = None + line: Annotated[int, Field(examples=[42])] + path: Annotated[str, Field(examples=["src/main.go"])] + text: Annotated[str, Field(examples=["const searchText = 'example'"])] + + +class ContentSearchResponse(BaseModel): + matches: list[ContentSearchMatch] + query: Annotated[str, Field(examples=["searchText"])] + total: Annotated[int, Field(examples=[5])] + + +class DriveMountInfo(BaseModel): + driveName: str | None = None + drivePath: str | None = None + gidMap: Annotated[ + str | None, Field(description="The local GID used for this mount") + ] = None + mountPath: str | None = None + readOnly: bool | None = None + uidMap: Annotated[ + str | None, Field(description="The local UID used for this mount") + ] = None + + +class DriveMountRequest(BaseModel): + driveName: str + drivePath: Annotated[str | None, Field(description='Optional, defaults to "/"')] = ( + None + ) + gidMap: Annotated[ + str | None, + Field(description="Optional, local GID to map (filer GID is always 0)"), + ] = None + mountPath: str + readOnly: Annotated[ + bool | None, Field(description="Optional, defaults to false") + ] = None + uidMap: Annotated[ + str | None, + Field(description="Optional, local UID to map (filer UID is always 0)"), + ] = None + + +class DriveMountResponse(BaseModel): + driveName: str | None = None + drivePath: str | None = None + gidMap: Annotated[ + str | None, Field(description="The local GID used for this mount") + ] = None + message: str | None = None + mountPath: str | None = None + readOnly: bool | None = None + success: bool | None = None + uidMap: Annotated[ + str | None, Field(description="The local UID used for this mount") + ] = None + + +class DriveUnmountResponse(BaseModel): + message: str | None = None + mountPath: str | None = None + success: bool | None = None + + +class ErrorResponse(BaseModel): + error: Annotated[str, Field(examples=["Error message"])] + + +class File(BaseModel): + group: str + lastModified: str + name: str + owner: str + path: str + permissions: str + size: int + + +class FileRequest(BaseModel): + content: Annotated[str | None, Field(examples=["file contents here"])] = None + isDirectory: Annotated[bool | None, Field(examples=[False])] = None + permissions: Annotated[str | None, Field(examples=["0644"])] = None + + +class FileWithContent(BaseModel): + content: str + group: str + lastModified: str + name: str + owner: str + path: str + permissions: str + size: int + + +class FindMatch(BaseModel): + path: Annotated[str, Field(examples=["src/main.go"])] + type: Annotated[str, Field(description='"file" or "directory"', examples=["file"])] + + +class FindResponse(BaseModel): + matches: list[FindMatch] + total: Annotated[int, Field(examples=[5])] + + +class FuzzySearchMatch(BaseModel): + path: Annotated[str, Field(examples=["src/main.go"])] + score: Annotated[int, Field(examples=[100])] + type: Annotated[str, Field(description='"file" or "directory"', examples=["file"])] + + +class FuzzySearchResponse(BaseModel): + matches: list[FuzzySearchMatch] + total: Annotated[int, Field(examples=[5])] + + +class MultipartInitiateRequest(BaseModel): + permissions: Annotated[str | None, Field(examples=["0644"])] = None + + +class MultipartInitiateResponse(BaseModel): + path: Annotated[str | None, Field(examples=["/tmp/largefile.dat"])] = None + uploadId: Annotated[ + str | None, Field(examples=["550e8400-e29b-41d4-a716-446655440000"]) + ] = None + + +class MultipartPartInfo(BaseModel): + etag: Annotated[ + str | None, Field(examples=["5d41402abc4b2a76b9719d911017c592"]) + ] = None + partNumber: Annotated[int | None, Field(examples=[1])] = None + + +class MultipartUpload(BaseModel): + abortUrl: Annotated[ + str | None, + Field( + description="AbortURL is a presigned DELETE URL that discards the parts already\nuploaded. Without it a failed export leaves them on the storage until a\nlifecycle rule removes them." + ), + ] = None + completeUrl: Annotated[ + str | None, + Field( + description="CompleteURL is a presigned POST URL that assembles the parts." + ), + ] = None + partSize: Annotated[ + int | None, + Field( + description="PartSize is the number of bytes sent to every part but the last.", + examples=[536870912], + ), + ] = None + partUrls: Annotated[ + list[str] | None, + Field( + description="PartURLs are presigned PUT URLs, one per part, in order. Extra ones are\nleft unused." + ), + ] = None + + +class MultipartUploadPartResponse(BaseModel): + etag: Annotated[ + str | None, Field(examples=["5d41402abc4b2a76b9719d911017c592"]) + ] = None + partNumber: Annotated[int | None, Field(examples=[1])] = None + size: Annotated[int | None, Field(examples=[5242880])] = None + + +class PortMonitorRequest(BaseModel): + callback: Annotated[ + str | None, + Field( + description="URL to call when a new port is detected", + examples=["http://localhost:3000/callback"], + ), + ] = None + + +class ProcessLogs(BaseModel): + logs: Annotated[str, Field(examples=["logs output"])] + stderr: Annotated[str, Field(examples=["stderr output"])] + stdout: Annotated[str, Field(examples=["stdout output"])] + + +class ProcessRequest(BaseModel): + command: Annotated[str, Field(examples=["ls -la"])] + env: Annotated[dict[str, str] | None, Field(examples=[{'{"PORT"': ' "3000"}'}])] = ( + None + ) + keepAlive: Annotated[ + bool | None, + Field( + description="Disable scale-to-zero while process runs. Default timeout is 600s (10 minutes). Set timeout to 0 for infinite.", + examples=[False], + ), + ] = None + maxRestarts: Annotated[ + int | None, + Field( + description="Maximum number of restarts on failure. Set to a negative value (e.g. -1) for unlimited restarts.", + examples=[3], + ), + ] = None + name: Annotated[str | None, Field(examples=["my-process"])] = None + restartOnFailure: Annotated[bool | None, Field(examples=[True])] = None + stdin: Annotated[ + bool | None, + Field( + description="Open a writable stdin pipe, fed via POST /process/{identifier}/stdin and closed via DELETE. The pipe does not survive a sandbox-api restart: the process then sees EOF.", + examples=[False], + ), + ] = None + timeout: Annotated[ + int | None, + Field( + description="Timeout in seconds. When keepAlive is true, defaults to 600s (10 minutes). Set to 0 for infinite (no auto-kill).", + examples=[30], + ), + ] = None + waitForCompletion: Annotated[bool | None, Field(examples=[False])] = None + waitForPorts: Annotated[list[int] | None, Field(examples=[[3000, 8080]])] = None + workingDir: Annotated[str | None, Field(examples=["/home/user"])] = None + + +class Status(StrEnum): + failed = "failed" + killed = "killed" + stopped = "stopped" + running = "running" + completed = "completed" + + +class ProcessResponse(BaseModel): + command: Annotated[str, Field(examples=["ls -la"])] + completedAt: Annotated[str, Field(examples=["Wed, 01 Jan 2023 12:01:00 GMT"])] + exitCode: Annotated[int, Field(examples=[0])] + keepAlive: Annotated[ + bool | None, + Field( + description="Whether scale-to-zero is disabled for this process", + examples=[False], + ), + ] = None + logs: Annotated[str, Field(examples=["logs output"])] + maxRestarts: Annotated[int | None, Field(examples=[3])] = None + name: Annotated[str, Field(examples=["my-process"])] + pid: Annotated[str, Field(examples=["1234"])] + restartCount: Annotated[int | None, Field(examples=[2])] = None + restartOnFailure: Annotated[bool | None, Field(examples=[True])] = None + startedAt: Annotated[str, Field(examples=["Wed, 01 Jan 2023 12:00:00 GMT"])] + status: Annotated[Status, Field(examples=["running"])] + stderr: Annotated[str, Field(examples=["stderr output"])] + stdin: Annotated[ + bool | None, + Field( + description="Whether the process was started with a writable stdin pipe", + examples=[False], + ), + ] = None + stdout: Annotated[str, Field(examples=["stdout output"])] + workingDir: Annotated[str, Field(examples=["/home/user"])] + + +class RankedFile(BaseModel): + content: str | None = None + path: str | None = None + score: float | None = None + + +class RerankingResponse(BaseModel): + files: list[RankedFile] | None = None + message: Annotated[str | None, Field(examples=["Found 5 relevant files"])] = None + success: Annotated[bool | None, Field(examples=[True])] = None + + +class Subdirectory(BaseModel): + name: str + path: str + + +class SuccessResponse(BaseModel): + message: Annotated[str, Field(examples=["File created successfully"])] + path: Annotated[str | None, Field(examples=["/path/to/file"])] = None + + +class TreeRequest(BaseModel): + files: Annotated[ + dict[str, str] | None, + Field( + examples=[{'"dir/file2.txt"': '"content2"}', '{"file1.txt"': '"content1"'}] + ), + ] = None + + +class TunnelConfigRequest(BaseModel): + config: Annotated[ + str, + Field( + description="Base64-encoded tunnel config JSON", + examples=["eyJsb2NhbF9pcCI6ICIxMC4wLjAuMS8zMiIsIC4uLn0="], + ), + ] + + +class UpgradeRequest(BaseModel): + baseUrl: Annotated[ + str | None, + Field( + description="Base URL for releases (useful for forks)", + examples=["https://github.com/blaxel-ai/sandbox/releases"], + ), + ] = None + version: Annotated[ + str | None, + Field( + description='Version to upgrade to: "latest" (default), "develop", "main", or specific tag like "v1.0.0"', + examples=["latest"], + ), + ] = None + + +class GetCodegenRerankingParams(BaseModel): + query: Annotated[str, Field(description="Natural language query to search for")] + scoreThreshold: Annotated[ + float | None, Field(description="Minimum relevance score (default: 0.5)") + ] = None + tokenLimit: Annotated[ + int | None, Field(description="Maximum tokens to return (default: 30000)") + ] = None + filePattern: Annotated[ + str | None, + Field( + description="Regex pattern to filter files (e.g., .*\\\\.ts$ for TypeScript files)" + ), + ] = None + + +class GetFilesystemContentSearchParams(BaseModel): + query: Annotated[str, Field(description="Text to search for")] + caseSensitive: Annotated[ + bool | None, Field(description="Case sensitive search (default: false)") + ] = None + maxResults: Annotated[ + int | None, + Field(description="Maximum number of results to return (default: 100)"), + ] = None + filePattern: Annotated[ + str | None, Field(description="File pattern to include (e.g., *.go)") + ] = None + excludeDirs: Annotated[ + str | None, + Field( + description="Comma-separated directory names to skip (default: node_modules,vendor,.git,dist,build,target,__pycache__,.venv,.next,coverage)" + ), + ] = None + + +class GetFilesystemFindParams(BaseModel): + type: Annotated[ + str | None, Field(description="Type of search (file or directory)") + ] = None + patterns: Annotated[ + str | None, + Field(description="Comma-separated file patterns to include (e.g., *.go,*.js)"), + ] = None + maxResults: Annotated[ + int | None, + Field( + description="Maximum number of results to return (default: 20). If set to 0, all results will be returned." + ), + ] = None + excludeDirs: Annotated[ + str | None, + Field( + description="Comma-separated directory names to skip (default: node_modules,vendor,.git,dist,build,target,__pycache__,.venv,.next,coverage). Use empty string to skip no directories." + ), + ] = None + excludeHidden: Annotated[ + bool | None, + Field(description="Exclude hidden files and directories (default: true)"), + ] = None + + +class PutFilesystemMultipartPartParams(BaseModel): + partNumber: Annotated[int, Field(description="Part number (1-10000)")] + + +class GetFilesystemSearchParams(BaseModel): + maxResults: Annotated[ + int | None, + Field(description="Maximum number of results to return (default: 20)"), + ] = None + patterns: Annotated[ + str | None, + Field(description="Comma-separated file patterns to include (e.g., *.go,*.js)"), + ] = None + excludeDirs: Annotated[ + str | None, + Field( + description="Comma-separated directory names to skip (default: node_modules,vendor,.git,dist,build,target,__pycache__,.venv,.next,coverage). Use empty string to skip no directories." + ), + ] = None + excludeHidden: Annotated[ + bool | None, + Field(description="Exclude hidden files and directories (default: true)"), + ] = None + + +class DeleteFilesystemParams(BaseModel): + recursive: Annotated[ + bool | None, Field(description="Delete directory recursively") + ] = None + + +class GetFilesystemParams(BaseModel): + download: Annotated[ + bool | None, Field(description="Force download mode for files") + ] = None + + +class DeleteFilesystemTreeParams(BaseModel): + recursive: Annotated[ + bool | None, Field(description="Delete directory recursively") + ] = None + + +class GetWatchFilesystemParams(BaseModel): + ignore: Annotated[ + str | None, Field(description="Ignore patterns (comma-separated)") + ] = None + + +class DeleteNetworkProcessMonitorResponse(BaseModel): + model_config = ConfigDict( + extra="allow", + ) + + +class PostNetworkProcessMonitorResponse(BaseModel): + model_config = ConfigDict( + extra="allow", + ) + + +class GetNetworkProcessPortsResponse(BaseModel): + model_config = ConfigDict( + extra="allow", + ) + + +class GetProcessResponse(RootModel[list[ProcessResponse]]): + root: list[ProcessResponse] + + +class ArchiveChangeKind(StrEnum): + ChangeAdded = "added" + ChangeModified = "modified" + ChangeDeleted = "deleted" + + +class ArchiveExportState(StrEnum): + ExportRunning = "running" + ExportSucceeded = "succeeded" + ExportFailed = "failed" + + +class ArchiveQuiesceState(StrEnum): + StateActive = "active" + StateQuiescing = "quiescing" + StateQuiesced = "quiesced" + StateRestoring = "restoring" + + +class ArchiveRestoreState(StrEnum): + RestoreDownloading = "downloading" + RestoreExtracting = "extracting" + RestoreRelaunching = "relaunching" + RestoreSucceeded = "succeeded" + RestoreFailed = "failed" + + +class FilesystemUploadedPart(BaseModel): + etag: Annotated[ + str | None, Field(examples=["5d41402abc4b2a76b9719d911017c592"]) + ] = None + partNumber: Annotated[int | None, Field(examples=[1])] = None + size: Annotated[int | None, Field(examples=[5242880])] = None + uploadedAt: str | None = None + + +class HandlerReloadResponse(BaseModel): + applied: int | None = None + generation: int | None = None + removed: int | None = None + + +class ProcessUpgradeState(StrEnum): + UpgradeStateIdle = "idle" + UpgradeStateRunning = "running" + UpgradeStateCompleted = "completed" + UpgradeStateFailed = "failed" + + +class Directory(BaseModel): + files: list[File] + name: str + path: str + subdirectories: Annotated[ + list[Subdirectory], Field(description="@name Subdirectories") + ] + + +class DriveListResponse(BaseModel): + mounts: list[DriveMountInfo] | None = None + + +class ExportOptions(BaseModel): + async_: Annotated[ + bool | None, + Field( + alias="async", + description="Async starts the export and answers immediately, leaving it to run: an\narchive of a large filesystem takes longer than a request may be held\nopen. Its progress is reported by /archive/status.", + examples=[False], + ), + ] = None + dryRun: Annotated[ + bool | None, + Field( + description="DryRun reports what would be archived, and its exact size, without\nstopping anything and without uploading.", + examples=[False], + ), + ] = None + excludes: Annotated[ + list[str] | None, + Field(description="Excludes are added to the paths excluded by default."), + ] = None + headers: Annotated[ + dict[str, str] | None, + Field( + description="Headers are sent with the upload request as given. A presigned URL only\naccepts the headers it was signed for, so these have to match what the\ncaller signed: sending one that was not signed, or signing one that is not\nsent, is rejected as a signature mismatch. Typical use is a storage class,\nx-amz-storage-class: GLACIER_IR." + ), + ] = None + imageDevice: Annotated[ + str | None, + Field( + description="ImageDevice is the device holding the pristine image. It is found on its\nown, wherever the sandbox booted from attached it, and naming one here\nonly overrides that.", + examples=["/dev/vda"], + ), + ] = None + imageMountPoint: Annotated[ + str | None, + Field( + description="ImageMountPoint is a directory where the pristine image is already mounted.\nWhen set the image device is neither mounted nor unmounted.", + examples=["/mnt/lower"], + ), + ] = None + multipart: Annotated[ + MultipartUpload | None, + Field( + description="Multipart uploads the archive part by part instead, which is how an\narchive larger than the 5 GB a single PUT accepts is stored. It takes\nprecedence over URL." + ), + ] = None + saveProcesses: Annotated[ + bool | None, + Field( + description="SaveProcesses stores the process list in the archive so restore can\nrelaunch the workload. Defaults to true; set it to false to archive\nstorage only.", + examples=[True], + ), + ] = None + stopTimeoutSeconds: Annotated[ + int | None, + Field( + description="StopTimeoutSeconds bounds the graceful stop of each process.", + examples=[30], + ), + ] = None + url: Annotated[ + str | None, + Field( + description="URL is a presigned S3 PUT URL the archive is streamed to. Empty is only\nvalid with DryRun, or with Multipart.", + examples=["https://bucket.s3.amazonaws.com/key?..."], + ), + ] = None + + +class ExportProgress(BaseModel): + error: Annotated[ + str | None, + Field( + description="Error is why the export failed, without the presigned URL it used." + ), + ] = None + finishedAt: str | None = None + size: Annotated[ + int | None, + Field( + description="Size is the archive's exact size, known once the filesystem is scanned.", + examples=[3074211], + ), + ] = None + startedAt: str | None = None + state: Annotated[ArchiveExportState | None, Field(examples=["running"])] = None + uploaded: Annotated[ + bool | None, + Field( + description="Uploaded reports whether the storage holds the archive.", + examples=[False], + ), + ] = None + + +class MultipartCompleteRequest(BaseModel): + parts: list[MultipartPartInfo] | None = None + + +class MultipartListPartsResponse(BaseModel): + parts: list[FilesystemUploadedPart] | None = None + uploadId: Annotated[ + str | None, Field(examples=["550e8400-e29b-41d4-a716-446655440000"]) + ] = None + + +class RestoreProgress(BaseModel): + deleted: Annotated[int | None, Field(examples=[3])] = None + downloaded: Annotated[ + int | None, + Field( + description="Downloaded is how much of the archive has been read so far.", + examples=[1048576], + ), + ] = None + error: Annotated[ + str | None, + Field( + description="Error is why the restore failed, without the presigned URL it used." + ), + ] = None + finishedAt: str | None = None + restored: Annotated[ + int | None, + Field( + description="Restored and Deleted count what the archive changed on the filesystem.", + examples=[1204], + ), + ] = None + size: Annotated[ + int | None, + Field( + description="Size is the archive's size as the storage announced it, and zero when it\nannounced none - a client showing a percentage has to allow for that.", + examples=[3074211], + ), + ] = None + startedAt: str | None = None + state: Annotated[ArchiveRestoreState | None, Field(examples=["extracting"])] = None + + +class UpgradeStatus(BaseModel): + binaryPath: Annotated[ + str | None, + Field( + description="Path to downloaded binary", examples=["/tmp/sandbox-api-new"] + ), + ] = None + bytesDownloaded: Annotated[ + int | None, Field(description="Bytes downloaded", examples=[25034936]) + ] = None + downloadUrl: Annotated[ + str | None, + Field(description="URL used for download", examples=["https://github.com/..."]), + ] = None + error: Annotated[ + str | None, + Field( + description="Error message if failed", + examples=["Failed to download binary"], + ), + ] = None + lastAttempt: Annotated[ + str | None, Field(description="When the upgrade was attempted") + ] = None + status: Annotated[ + ProcessUpgradeState, + Field( + description="Current state (idle, running, completed, failed)", + examples=["running"], + ), + ] + step: Annotated[ + str, + Field( + description="Current/last step (none, starting, download, validate, replace, completed, skipped)", + examples=["download"], + ), + ] + version: Annotated[ + str, Field(description="Version being upgraded to", examples=["latest"]) + ] + + +class GetFilesystemResponse(RootModel[Directory | FileWithContent | bytes]): + root: Directory | FileWithContent | bytes + + +class GetFilesystemTreeResponse(RootModel[Directory | FileWithContent | bytes]): + root: Directory | FileWithContent | bytes + + +class PutFilesystemTreeResponse(RootModel[Directory | FileWithContent | bytes]): + root: Directory | FileWithContent | bytes + + +class ArchiveChange(BaseModel): + kind: Annotated[ArchiveChangeKind, Field(examples=["added"])] + path: Annotated[ + str, + Field( + description="Path is relative to the root, without a leading slash.", + examples=["usr/bin/curl"], + ), + ] + size: Annotated[ + int | None, + Field( + description="Size is the file content size in bytes, 0 for anything but a regular file.", + examples=[256216], + ), + ] = None + + +class FilesystemMultipartUpload(BaseModel): + initiatedAt: str | None = None + parts: dict[str, FilesystemUploadedPart] | None = None + path: Annotated[str | None, Field(examples=["/tmp/largefile.dat"])] = None + permissions: Annotated[int | None, Field(examples=[420])] = None + uploadId: Annotated[ + str | None, Field(examples=["550e8400-e29b-41d4-a716-446655440000"]) + ] = None + + +class ExportResult(BaseModel): + changes: Annotated[ + list[ArchiveChange] | None, + Field( + description="Changes lists every path in the archive. Only filled for a dry run,\nwhere it is the point of the call." + ), + ] = None + duration: Annotated[str | None, Field(examples=["4.2s"])] = None + manifest: ArchiveManifest + size: Annotated[ + int | None, + Field( + description="Size is the exact number of bytes uploaded, known before the upload\nstarts since the archive is not compressed.", + examples=[3074211], + ), + ] = None + stoppedProcesses: Annotated[ + list[str] | None, + Field( + description="StoppedProcesses are the processes stopped to freeze the filesystem." + ), + ] = None + uploaded: Annotated[ + bool | None, + Field(description="Uploaded is false for a dry run.", examples=[True]), + ] = None + + +class HealthResponse(BaseModel): + arch: Annotated[str, Field(examples=["amd64"])] + buildTime: Annotated[str, Field(examples=["2026-01-29T17:36:52+00:00"])] + gitCommit: Annotated[str, Field(examples=["abc123"])] + goVersion: Annotated[str, Field(examples=["go1.25.0"])] + lastUpgrade: UpgradeStatus + os: Annotated[str, Field(examples=["linux"])] + startedAt: Annotated[str, Field(examples=["2026-01-29T18:45:49+00:00"])] + status: Annotated[str, Field(examples=["ok"])] + upgradeCount: Annotated[int, Field(examples=[0])] + uptime: Annotated[str, Field(examples=["1h30m"])] + uptimeSeconds: Annotated[float, Field(examples=[5400.5])] + version: Annotated[str, Field(examples=["v0.1.0"])] + + +class MultipartListUploadsResponse(BaseModel): + uploads: list[FilesystemMultipartUpload] | None = None + + +class QuiesceStatus(BaseModel): + export: Annotated[ + ExportProgress | None, + Field( + description="Export reports the export started asynchronously, if there was one. It is\nhow a caller that did not wait for the export learns that the archive is\non the storage, or why it is not." + ), + ] = None + readOnlyRoot: Annotated[ + bool | None, + Field( + description="ReadOnlyRoot reports whether the root mount was remounted read-only, which\nis what actually stops writes; false means the freeze relies only on the\nAPI refusing calls, and the reason says why.", + examples=[True], + ), + ] = None + reason: Annotated[ + str | None, + Field( + description="Reason is a human readable explanation of why the sandbox is frozen.", + examples=["archive export"], + ), + ] = None + restore: Annotated[ + RestoreProgress | None, + Field( + description="Restore reports the archive this sandbox was started from, if it was\nstarted from one: how far its restore has got, and how it ended." + ), + ] = None + since: Annotated[ + str | None, Field(description="Since is when the sandbox left StateActive.") + ] = None + state: Annotated[ArchiveQuiesceState, Field(examples=["quiesced"])] + stoppedProcesses: Annotated[ + list[str] | None, + Field( + description="StoppedProcesses are the process identifiers stopped while quiescing." + ), + ] = None diff --git a/pyproject.toml b/pyproject.toml index e628519..3342aa0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "baseten" -version = "0.11.0" +version = "0.12.0" description = "Baseten Python SDK" readme = "README.md" license = "MIT" diff --git a/scripts/apigen/__main__.py b/scripts/apigen/__main__.py index 93d924b..764facc 100644 --- a/scripts/apigen/__main__.py +++ b/scripts/apigen/__main__.py @@ -7,20 +7,27 @@ import argparse import ast +import json import subprocess import sys import urllib.request +from datetime import datetime from pathlib import Path +import yaml + from scripts.apigen.clientgen import generate_client from scripts.apigen.postprocess import postprocess_models from scripts.apigen.preprocess import preprocess_spec, preprocess_truss_config_schema -MANAGEMENT_SPEC_URL = "https://api.baseten.co/v1/spec" +# Staging, not prod: the /v1/sandboxes surface ships there first. Switch back +# once api.baseten.co/v1/spec serves it too. +MANAGEMENT_SPEC_URL = "https://api.staging.baseten.co/v1/spec" INFERENCE_SPEC_URL = "https://api.baseten.co/inference-spec" TRUSS_CONFIG_SCHEMA_URL = ( "https://raw.githubusercontent.com/basetenlabs/truss/main/truss/config.schema.json" ) +SANDBOX_SPEC_URL = "https://raw.githubusercontent.com/blaxel-ai/sandbox/main/sandbox-api/docs/openapi.yml" APIGEN_DIR = Path(__file__).parent SPECS_DIR = APIGEN_DIR / "specs" @@ -42,11 +49,18 @@ def main() -> None: download_spec(MANAGEMENT_SPEC_URL, SPECS_DIR / "management.json") download_spec(INFERENCE_SPEC_URL, SPECS_DIR / "inference.json") download_spec(TRUSS_CONFIG_SCHEMA_URL, SPECS_DIR / "config.schema.json") + download_spec(SANDBOX_SPEC_URL, SPECS_DIR / "sandbox.yml") generate_api( SPECS_DIR / "management.json", CLIENT_DIR / "managementapi", "Management" ) generate_api(SPECS_DIR / "inference.json", CLIENT_DIR / "inferenceapi", "Inference") + generate_api( + SPECS_DIR / "sandbox.yml", + CLIENT_DIR / "sandboxapi", + "Sandbox", + allow_query_and_body=True, + ) generate_modelconfig(SPECS_DIR / "config.schema.json", CLIENT_DIR / "modelconfig") @@ -56,11 +70,29 @@ def download_spec(url: str, dest: Path) -> None: dest.write_bytes(resp.read()) -def generate_api(spec_file: Path, out_dir: Path, display_name: str) -> None: +def _read_spec(spec_file: Path) -> bytes: + # YAML specs are committed exactly as upstream serves them and converted + # here rather than at download time. Timestamp scalars are serialized back + # to ISO strings, matching how js-yaml keeps them for the JS SDK. + if spec_file.suffix in (".yml", ".yaml"): + doc = yaml.safe_load(spec_file.read_text()) + return json.dumps(doc, default=datetime.isoformat).encode() + return spec_file.read_bytes() + + +def generate_api( + spec_file: Path, + out_dir: Path, + display_name: str, + *, + allow_query_and_body: bool = False, +) -> None: print(f"Generating {out_dir.name} from {spec_file}") out_dir.mkdir(parents=True, exist_ok=True) - preprocessed = preprocess_spec(spec_file.read_bytes()) + preprocessed = preprocess_spec( + _read_spec(spec_file), allow_query_and_body=allow_query_and_body + ) models_file = out_dir / "_models.py" run_datamodel_codegen(preprocessed, models_file) diff --git a/scripts/apigen/clientgen.py b/scripts/apigen/clientgen.py index b321dca..ba78bdc 100644 --- a/scripts/apigen/clientgen.py +++ b/scripts/apigen/clientgen.py @@ -13,6 +13,9 @@ def generate_client(spec_data: bytes, out_file: Path) -> None: _PATH_PARAM_RE = re.compile(r"\{(\w+)\}") +_JSON_CONTENT = "application/json" +_MULTIPART_CONTENT = "multipart/form-data" + @dataclass class _Operation: @@ -20,14 +23,16 @@ class _Operation: http_method: str path: str path_params: list[str] + query_ref: str + query_required: bool has_body: bool req_body_ref: str - resp_ref: str - success_code: int + body_content_type: str + json_responses: list[tuple[int, str]] + raw_accepts: list[str] + success_codes: list[int] error_codes: dict[int, str] | None summary: str - query_ref: str - query_required: bool def resolve_method_names(spec: dict) -> dict[tuple[str, str], str]: @@ -66,9 +71,14 @@ def resolve_method_names(spec: dict) -> dict[tuple[str, str], str]: return result -def query_request_model_name(method_name: str) -> str: +def query_params_model_name(method_name: str) -> str: """Model name for an operation's injected query-parameter schema.""" - return _snake_to_pascal(method_name) + "Request" + return _snake_to_pascal(method_name) + "Params" + + +def response_type_model_name(method_name: str) -> str: + """Model name for an operation's injected inline response schema.""" + return _snake_to_pascal(method_name) + "Response" def _snake_to_pascal(s: str) -> str: @@ -90,36 +100,36 @@ def _extract_operations(spec: dict) -> list[_Operation]: for p in op_data.get("parameters", []) if isinstance(p, dict) and p.get("in") == "query" ] - query_ref = query_request_model_name(name) if query_params else "" - query_required = any(p.get("required") for p in query_params) ops.append( _Operation( name=name, http_method=http_method.upper(), path=path, path_params=_PATH_PARAM_RE.findall(path), + query_ref=query_params_model_name(name) if query_params else "", + query_required=any(p.get("required") for p in query_params), has_body="requestBody" in op_data, req_body_ref=_body_schema_ref(spec, op_data), - resp_ref=_response_schema_ref(spec, op_data), - success_code=_extract_success_code(op_data, http_method, path), + body_content_type=_body_content_type(spec, op_data), + json_responses=_json_response_refs(spec, op_data), + raw_accepts=_raw_response_accepts(spec, op_data), + success_codes=_extract_success_codes(op_data, http_method, path), error_codes=_error_code_map(spec, op_data), summary=op_data.get("summary", ""), - query_ref=query_ref, - query_required=query_required, ) ) ops.sort(key=lambda o: o.name) return ops -def _extract_success_code(op: dict, http_method: str, path: str) -> int: +def _extract_success_codes(op: dict, http_method: str, path: str) -> list[int]: responses = op.get("responses", {}) - codes = [int(c) for c in responses if c.isdigit() and 200 <= int(c) < 300] - if len(codes) != 1: + codes = sorted(int(c) for c in responses if c.isdigit() and 200 <= int(c) < 300) + if not codes: raise ValueError( - f"expected exactly one 2xx response for {http_method.upper()} {path}, got {codes}" + f"expected at least one 2xx response for {http_method.upper()} {path}" ) - return codes[0] + return codes def _derive_method_name( @@ -161,10 +171,7 @@ def _json_content_schema_ref(node: dict | None) -> str: if node is None: return "" ref = ( - node.get("content", {}) - .get("application/json", {}) - .get("schema", {}) - .get("$ref", "") + node.get("content", {}).get(_JSON_CONTENT, {}).get("schema", {}).get("$ref", "") ) return ref.rsplit("/", 1)[-1] if ref else "" @@ -176,26 +183,58 @@ def _body_schema_ref(spec: dict, op: dict) -> str: return _json_content_schema_ref(_resolve_ref(spec, rb)) -def _response_schema_ref(spec: dict, op: dict) -> str: +def _body_content_type(spec: dict, op: dict) -> str: + """Non-JSON request body content type, or "" for JSON or no body. + + JSON is preferred when an operation declares several body encodings. + """ + rb = _resolve_ref(spec, op.get("requestBody")) + if rb is None: + return "" + content_types = list(rb.get("content", {})) + if _JSON_CONTENT in content_types: + return "" + return content_types[0] if content_types else "" + + +def _success_responses(op: dict) -> dict[str, dict]: responses = op.get("responses", {}) - for code in ("200", "201", "202"): - resp_node = responses.get(code) - if not isinstance(resp_node, dict): - continue + return { + code: resp + for code, resp in responses.items() + if code.isdigit() and 200 <= int(code) < 300 and isinstance(resp, dict) + } + + +def _json_response_refs(spec: dict, op: dict) -> list[tuple[int, str]]: + result: list[tuple[int, str]] = [] + for code, resp_node in _success_responses(op).items(): resolved = _resolve_ref(spec, resp_node) if ref := _json_content_schema_ref(resolved): - return ref - # If the response was a $ref to components/responses and has JSON - # content, use the response component name as the type. - if resp_node.get("$ref") and _has_json_content(resolved): - return resp_node["$ref"].rsplit("/", 1)[-1] - return "" + result.append((int(code), ref)) + elif resp_node.get("$ref") and _has_json_content(resolved): + # A $ref to components/responses with JSON content: use the + # response component name as the type. + result.append((int(code), resp_node["$ref"].rsplit("/", 1)[-1])) + return result + + +def _raw_response_accepts(spec: dict, op: dict) -> list[str]: + accepts: set[str] = set() + for resp_node in _success_responses(op).values(): + resolved = _resolve_ref(spec, resp_node) + if resolved is None: + continue + for content_type in resolved.get("content", {}): + if content_type != _JSON_CONTENT: + accepts.add(content_type) + return sorted(accepts) def _has_json_content(node: dict | None) -> bool: if node is None: return False - return "application/json" in node.get("content", {}) + return _JSON_CONTENT in node.get("content", {}) def _error_code_map(spec: dict, op: dict) -> dict[int, str] | None: @@ -218,8 +257,9 @@ def _path_fmt(path: str) -> str: def _render_client(ops: list[_Operation]) -> str: - has_typed_resp = any(op.resp_ref for op in ops) - has_no_resp = any(not op.resp_ref for op in ops) + has_typed_resp = any(op.json_responses for op in ops) + has_status_resp = any(len(op.json_responses) > 1 for op in ops) + has_no_resp = any(not op.json_responses and not op.raw_accepts for op in ops) error_refs = sorted({ref for op in ops for ref in (op.error_codes or {}).values()}) @@ -229,8 +269,8 @@ def _render_client(ops: list[_Operation]) -> str: model_imports.add(op.req_body_ref) if op.query_ref: model_imports.add(op.query_ref) - if op.resp_ref: - model_imports.add(op.resp_ref) + for _, ref in op.json_responses: + model_imports.add(ref) for ref in (op.error_codes or {}).values(): model_imports.add(ref) @@ -241,8 +281,9 @@ def _render_client(ops: list[_Operation]) -> str: import contextlib import urllib.parse +from collections.abc import Mapping from dataclasses import dataclass -from typing import Any, TypeVar +from typing import Any, IO, Literal, TypeVar import httpx from pydantic import BaseModel, ValidationError @@ -297,15 +338,17 @@ class _ApiRequest: path_args: list[str] body: Any query: Any - success_code: int + success_codes: list[int] error_codes: dict[int, str] | None + body_content_type: str | None = None + accept: str | None = None """ src += "\n\n" + _render_client_class( - ops, has_typed_resp, has_no_resp, is_async=False + ops, has_typed_resp, has_status_resp, has_no_resp, is_async=False ) src += "\n\n" + _render_client_class( - ops, has_typed_resp, has_no_resp, is_async=True + ops, has_typed_resp, has_status_resp, has_no_resp, is_async=True ) src += "\n" return src @@ -314,6 +357,7 @@ class _ApiRequest: def _render_client_class( ops: list[_Operation], has_typed_resp: bool, + has_status_resp: bool, has_no_resp: bool, *, is_async: bool, @@ -338,7 +382,14 @@ def __init__(self, http_client: {http_cls}) -> None: """ for op in ops: - src += "\n" + _render_method(op, is_async=is_async) + if op.json_responses: + src += "\n" + _render_method(op, is_async=is_async, is_raw=False) + if op.raw_accepts: + src += "\n" + _render_method(op, is_async=is_async, is_raw=True) + elif op.raw_accepts: + src += "\n" + _render_method(op, is_async=is_async, is_raw=True) + else: + src += "\n" + _render_method(op, is_async=is_async, is_raw=False) error_dispatch = "" if any(op.error_codes for op in ops): @@ -365,14 +416,26 @@ def __init__(self, http_client: {http_cls}) -> None: *[urllib.parse.quote(a, safe="") for a in request.path_args] ) json_body = None + content_body = None + files_body = None + headers: dict[str, str] = {{}} + if request.accept is not None: + headers["Accept"] = request.accept if request.body is not None: - if isinstance(request.body, BaseModel): - # Only fields the caller set are sent, so unset fields fall - # back to the server default rather than being reset here. - # An explicit None is kept, since null can mean "clear". - json_body = request.body.model_dump(mode="json", exclude_unset=True) + if request.body_content_type is None: + if isinstance(request.body, BaseModel): + # Only fields the caller set are sent, so unset fields fall + # back to the server default rather than being reset here. + # An explicit None is kept, since null can mean "clear". + json_body = request.body.model_dump(mode="json", exclude_unset=True) + else: + json_body = request.body + elif request.body_content_type == "{_MULTIPART_CONTENT}": + # httpx derives the multipart Content-Type, boundary included. + files_body = request.body else: - json_body = request.body + headers["Content-Type"] = request.body_content_type + content_body = request.body params = None if request.query is not None: if isinstance(request.query, BaseModel): @@ -383,8 +446,16 @@ def __init__(self, http_client: {http_cls}) -> None: ) else: params = request.query - response = {aw}self._http_client.request(request.method, path, json=json_body, params=params) - if response.status_code != request.success_code: + response = {aw}self._http_client.request( + request.method, + path, + json=json_body, + content=content_body, + files=files_body, + params=params, + headers=headers, + ) + if response.status_code not in request.success_codes: {error_dispatch}\ raise ResponseError(status_code=response.status_code, body=response.text) return response @@ -400,6 +471,21 @@ def __init__(self, http_client: {http_cls}) -> None: return response_type.model_validate_json(response.content) """ + if has_status_resp: + src += f""" + {adef} _do_json_with_status( + self, response_types: Mapping[int, type[_T]], request: _ApiRequest + ) -> _T: + response = {aw}self._do(request) + response_type = response_types.get(response.status_code) + if response_type is None: + raise ValueError(f"no JSON response schema declared for HTTP {{response.status_code}}") + content_type = response.headers.get("content-type", "") + if not content_type.startswith("application/json"): + raise ValueError(f"unexpected content type {{content_type!r}}, expected application/json") + return response_type.model_validate_json(response.content) +""" + if has_no_resp: src += f""" {adef} _do_no_response(self, request: _ApiRequest) -> None: @@ -409,40 +495,52 @@ def __init__(self, http_client: {http_cls}) -> None: return src -def _render_method(op: _Operation, *, is_async: bool) -> str: +def _render_method(op: _Operation, *, is_async: bool, is_raw: bool) -> str: adef = "async def" if is_async else "def" aw = "await " if is_async else "" - # An operation carries at most one input model: a request body (any - # method other than GET) or query parameters (GET only). Both surface - # as a single keyword-only `request` argument. Query requests with no - # required fields are optional so callers can omit them entirely; body - # requests are always required so an empty body still sends `{}`. + # Query params go on `params`, request bodies on `request` (JSON) or + # `files`/`content` for non-JSON bodies. A request body is always + # required so an empty body still sends `{{}}`. Query params are + # optional unless the spec marks one required. + kwargs: list[str] = [f"{_camel_to_snake(p)}: str" for p in op.path_params] if op.query_ref: - input_type = op.query_ref - input_required = op.query_required - elif op.has_body: - input_type = op.req_body_ref if op.req_body_ref else "Any" - input_required = True - else: - input_type = "" - input_required = False - - params = ["self"] - if op.path_params or input_type: - params.append("*") - for p in op.path_params: - params.append(f"{p}: str") - if input_type: - if input_required: - params.append(f"request: {input_type}") + if op.query_required: + kwargs.append(f"params: {op.query_ref}") + else: + kwargs.append(f"params: {op.query_ref} | None = None") + if op.has_body: + if op.body_content_type == _MULTIPART_CONTENT: + kwargs.append("files: Any") + elif op.body_content_type: + kwargs.append("content: bytes | IO[bytes] | str") + elif op.req_body_ref: + kwargs.append(f"request: {op.req_body_ref}") else: - params.append(f"request: {input_type} | None = None") + kwargs.append("request: Any") + + # Every content type the success responses can produce. More than one + # means the caller has to say which it wants via `accept`. + content_types = ([_JSON_CONTENT] if op.json_responses else []) + op.raw_accepts + if is_raw and len(content_types) > 1: + accept_type = "Literal[" + ", ".join(repr(c) for c in content_types) + "]" + kwargs.append(f"accept: {accept_type}") + accept_expr = "accept" + elif is_raw: + accept_expr = repr(content_types[0]) + else: + accept_expr = "None" - ret = f" -> {op.resp_ref}" if op.resp_ref else " -> None" - path_args = f"[{', '.join(op.path_params)}]" if op.path_params else "[]" - body_arg = "request" if (input_type and not op.query_ref) else "None" - query_arg = "request" if op.query_ref else "None" + if op.has_body: + if op.body_content_type == _MULTIPART_CONTENT: + body_arg = "files" + elif op.body_content_type: + body_arg = "content" + else: + body_arg = "request" + else: + body_arg = "None" + query_arg = "params" if op.query_ref else "None" if op.error_codes: codes = sorted(op.error_codes.items()) @@ -450,22 +548,51 @@ def _render_method(op: _Operation, *, is_async: bool) -> str: else: error_expr = "None" - req = ( - f"_ApiRequest(" - f"method={op.http_method!r}, " - f"path_fmt={_path_fmt(op.path)!r}, " - f"path_args={path_args}, " - f"body={body_arg}, " - f"query={query_arg}, " - f"success_code={op.success_code}, " - f"error_codes={error_expr})" - ) + req_parts = [ + f"method={op.http_method!r}", + f"path_fmt={_path_fmt(op.path)!r}", + "path_args=[" + ", ".join(_camel_to_snake(p) for p in op.path_params) + "]" + if op.path_params + else "path_args=[]", + f"body={body_arg}", + f"query={query_arg}", + f"success_codes={op.success_codes!r}", + f"error_codes={error_expr}", + ] + if op.body_content_type: + req_parts.append(f"body_content_type={op.body_content_type!r}") + if accept_expr != "None": + req_parts.append(f"accept={accept_expr}") + req = "_ApiRequest(" + ", ".join(req_parts) + ")" + + # The suffix marks the sibling of a JSON method, so a raw-only operation, + # having no sibling to be confused with, keeps the plain name. + name = f"{op.name}_raw" if is_raw and op.json_responses else op.name + sig_args = ["self"] + if kwargs: + sig_args.append("*") + + if is_raw: + ret = "httpx.Response" + body = f"return {aw}self._do({req})" + elif len(op.json_responses) > 1: + types_expr = ( + "{" + ", ".join(f"{code}: {ref}" for code, ref in op.json_responses) + "}" + ) + union = " | ".join(dict.fromkeys(ref for _, ref in op.json_responses)) + ret = union + body = f"return {aw}self._do_json_with_status({types_expr}, {req})" + elif op.json_responses: + ret = op.json_responses[0][1] + body = f"return {aw}self._do_json({op.json_responses[0][1]}, {req})" + else: + ret = "None" + body = f"{aw}self._do_no_response({req})" - sig = f" {adef} {op.name}({', '.join(params)}){ret}:" + sig = f" {adef} {name}({', '.join(sig_args + kwargs)}) -> {ret}:" if op.summary: - sig += f'\n """{op.summary}"""' - - if op.resp_ref: - return f"{sig}\n return {aw}self._do_json({op.resp_ref}, {req})\n" - else: - return f"{sig}\n {aw}self._do_no_response({req})\n" + summary = op.summary + if is_raw: + summary += ". Returns the response unread, in the requested content type." + sig += f'\n """{summary}"""' + return f"{sig}\n {body}\n" diff --git a/scripts/apigen/preprocess.py b/scripts/apigen/preprocess.py index 7213ada..6525b90 100644 --- a/scripts/apigen/preprocess.py +++ b/scripts/apigen/preprocess.py @@ -4,7 +4,11 @@ import json import re -from scripts.apigen.clientgen import query_request_model_name, resolve_method_names +from scripts.apigen.clientgen import ( + query_params_model_name, + resolve_method_names, + response_type_model_name, +) def preprocess_truss_config_schema(data: bytes) -> bytes: @@ -47,7 +51,7 @@ def _rename_defs_refs(node: object, renames: dict[str, str]) -> None: _rename_defs_refs(child, renames) -def preprocess_spec(data: bytes) -> bytes: +def preprocess_spec(data: bytes, *, allow_query_and_body: bool = False) -> bytes: doc = json.loads(data) # datamodel-code-generator has --openapi-scopes for schemas and @@ -64,12 +68,19 @@ def preprocess_spec(data: bytes) -> bytes: # dropped, and the query schemas we add next are never at risk. _prune_unused_schemas(doc) - # Synthesize a request schema per GET operation's query parameters so + # Synthesize a params schema per operation's query parameters so # datamodel-code-generator emits a typed model for them (it only # generates query-parameter models under the paths scope, which drags # in unwanted per-operation wrappers). Injected before the V1 rename # below so their $refs to enums are rewritten with everything else. - _inject_query_request_schemas(doc) + _inject_query_params_schemas(doc, allow_query_and_body=allow_query_and_body) + + # Hoist inline 2xx application/json response schemas into + # components/schemas so datamodel-code-generator emits a named model the + # client can return. Without this, an operation whose success response is + # an inline oneOf, array, or free-form object has no resolvable type name. + # Injected before the V1 rename, for the same reason as the query schemas. + _inject_response_schemas(doc) # datamodel-code-generator generates empty BaseModel classes for # schemas that are bare type: object with no properties (e.g. @@ -77,8 +88,9 @@ def preprocess_spec(data: bytes) -> bytes: # generate dict[str, Any] instead. _fix_bare_object_schemas(doc) - # Management API schemas are suffixed with V1 (e.g. ModelV1). Strip - # the suffix so generated class names are cleaner (e.g. Model). + # Schema renames: a trailing V1 is stripped (ModelV1 -> Model) and names + # that are not valid Python identifiers are folded to PascalCase + # (archive.Change -> ArchiveChange). schema_renames = _build_v1_renames(doc) if schema_renames: _rename_refs(doc, schema_renames) @@ -169,13 +181,12 @@ def _collect_schema_refs(node: object, out: set[str]) -> None: _collect_schema_refs(child, out) -def _inject_query_request_schemas(doc: dict) -> None: +def _inject_query_params_schemas(doc: dict, *, allow_query_and_body: bool) -> None: # Build an object schema whose properties are the operation's query # parameters, named to match its client method (e.g. get_users -> - # GetUsersRequest). Each parameter's own schema (enum $refs, arrays, + # GetUsersParams). Each parameter's own schema (enum $refs, arrays, # nullable wrappers, constraints) is reused verbatim so the third - # party types every field. GET carries only query params and every - # other method only a body, so this name never collides with a body. + # party types every field. schemas = doc.setdefault("components", {}).setdefault("schemas", {}) method_names = resolve_method_names(doc) @@ -190,13 +201,14 @@ def _inject_query_request_schemas(doc: dict) -> None: ] if not query_params: continue - if "requestBody" in op: + if "requestBody" in op and not allow_query_and_body: + # Management and inference enforce query-XOR-body as a + # structural invariant; only the sandbox API allows both. raise ValueError( f"{http_method.upper()} {path} has both a request body and " - "query parameters; the client generator assumes GET carries " - "only query parameters and other methods only a body" + "query parameters, which this API does not allow" ) - name = query_request_model_name(method_names[(path, http_method)]) + name = query_params_model_name(method_names[(path, http_method)]) if name in schemas: raise ValueError( f"injected query schema {name} collides with an existing schema" @@ -216,6 +228,46 @@ def _inject_query_request_schemas(doc: dict) -> None: schemas[name] = obj +def _inject_response_schemas(doc: dict) -> None: + schemas = doc.setdefault("components", {}).setdefault("schemas", {}) + method_names = resolve_method_names(doc) + + for path, path_item in doc.get("paths", {}).items(): + for http_method, op in path_item.items(): + if http_method == "parameters" or not isinstance(op, dict): + continue + responses = op.get("responses", {}) + success_codes = sorted( + c + for c in responses + if c.isdigit() + and 200 <= int(c) < 300 + and isinstance(responses[c], dict) + ) + for code in success_codes: + json_content = ( + responses[code].get("content", {}).get("application/json") + ) + schema = ( + json_content.get("schema") + if isinstance(json_content, dict) + else None + ) + if not isinstance(schema, dict) or "$ref" in schema: + continue + base = response_type_model_name(method_names[(path, http_method)]) + # Only the first success code gets the bare name, so an + # operation with several 2xx bodies yields one schema per + # code rather than colliding. + schema_name = base if code == success_codes[0] else f"{base}{code}" + if schema_name in schemas: + raise ValueError( + f"injected response schema {schema_name} collides with an existing schema" + ) + schemas[schema_name] = schema + json_content["schema"] = {"$ref": f"#/components/schemas/{schema_name}"} + + def _fix_bare_object_schemas(doc: dict) -> None: schemas = doc.get("components", {}).get("schemas", {}) for schema in schemas.values(): @@ -233,15 +285,32 @@ def _fix_bare_object_schemas(doc: dict) -> None: def _build_v1_renames(doc: dict) -> dict[str, str]: + # A trailing V1 is dropped, and a name that is not a valid Python + # identifier (e.g. archive.Change) is folded into PascalCase so it can + # be emitted and imported by name. schemas = doc.get("components", {}).get("schemas", {}) - renames = {} + renames: dict[str, str] = {} for name in schemas: - if name.endswith("V1"): - renames[name] = name[:-2] + renamed = name.removesuffix("V1") + if not re.fullmatch(r"[A-Za-z_]\w*", renamed): + renamed = "".join( + part[0].upper() + part[1:] + for part in re.split(r"[.-]", renamed) + if part + ) + if renamed != name: + renames[name] = renamed + taken = {n for n in schemas if n not in renames} + for old, new in renames.items(): + if new in taken: + raise ValueError( + f"schema rename {old} -> {new} collides with an existing schema name" + ) + taken.add(new) return renames -_REF_PATTERN = re.compile(r"#/components/schemas/(\w+)") +_REF_PATTERN = re.compile(r"#/components/schemas/([^/]+)") def _rename_refs(node: object, renames: dict[str, str]) -> None: diff --git a/scripts/apigen/specs/sandbox.yml b/scripts/apigen/specs/sandbox.yml new file mode 100644 index 0000000..f669352 --- /dev/null +++ b/scripts/apigen/specs/sandbox.yml @@ -0,0 +1,2794 @@ +openapi: 3.0.0 +info: + contact: {} + description: API for manipulating filesystem, processes and network. + title: Sandbox API + version: 0.0.1 +paths: + /archive/export: + post: + description: >- + Archives everything the sandbox changed on top of its base image and streams it, uncompressed, to a presigned S3 PUT URL. The memory of the sandbox is not archived. + + The sandbox is quiesced first: the process list is saved (unless saveProcesses is false), every process is stopped, and the API then refuses the calls that would write to the filesystem. The freeze is not lifted afterwards, since an exported sandbox is meant to be restored elsewhere; call POST /archive/resume to lift it. + + Use dryRun to get the archive's content and exact size without stopping anything and without uploading. + + Set async to start the export and answer immediately, which is what archiving a large filesystem needs: the export then reports itself through GET /archive/status. + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/ExportOptions" + description: Export options + required: true + responses: + "200": + description: Export result + content: + application/json: + schema: + $ref: "#/components/schemas/ExportResult" + "202": + description: The export was started and runs in the background + content: + application/json: + schema: + $ref: "#/components/schemas/ExportProgress" + "400": + description: Invalid request + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "409": + description: An export is already in progress + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "500": + description: Export failed + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + summary: Export the filesystem changes to a presigned URL + tags: + - archive + /archive/resume: + post: + description: "Makes the API serve every route again after an export. The processes stopped for the export are not relaunched: this exists so a failed or aborted export does not leave the sandbox unusable." + responses: + "200": + description: Archive status + content: + application/json: + schema: + $ref: "#/components/schemas/QuiesceStatus" + "409": + description: An export or a restore is in progress + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "500": + description: The root filesystem could not be made writable again + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + summary: Lift the archive freeze + tags: + - archive + /archive/status: + get: + description: Reports whether the sandbox is frozen for an archive export, and which processes were stopped for it. + responses: + "200": + description: Archive status + content: + application/json: + schema: + $ref: "#/components/schemas/QuiesceStatus" + summary: Get the archive status + tags: + - archive + "/codegen/fastapply/{path}": + put: + description: >- + Uses the configured LLM provider (Relace or Morph) to apply a code edit to the original content. + + + To use this endpoint as an agent tool, follow these guidelines: + + + Use this tool to make an edit to an existing file. This will be read by a less intelligent model, which will quickly apply the edit. You should make it clear what the edit is, while also minimizing the unchanged code you write. + + + When writing the edit, you should specify each edit in sequence, with the special comment "// ... existing code ..." to represent unchanged code in between edited lines. + + + Example format: + + // ... existing code ... + + FIRST_EDIT + + // ... existing code ... + + SECOND_EDIT + + // ... existing code ... + + THIRD_EDIT + + // ... existing code ... + + + You should still bias towards repeating as few lines of the original file as possible to convey the change. But, each edit should contain minimally sufficient context of unchanged lines around the code you're editing to resolve ambiguity. + + + DO NOT omit spans of pre-existing code (or comments) without using the "// ... existing code ..." comment to indicate its absence. If you omit the existing code comment, the model may inadvertently delete these lines. + + + If you plan on deleting a section, you must provide context before and after to delete it. If the initial code is "Block 1\nBlock 2\nBlock 3", and you want to remove Block 2, you would output "// ... existing code ...\nBlock 1\nBlock 3\n// ... existing code ...". + + + Make sure it is clear what the edit should be, and where it should be applied. Make edits to a file in a single edit_file call instead of multiple edit_file calls to the same file. The apply model can handle many distinct edits at once. + parameters: + - description: Path to the file to edit (relative to workspace) + in: path + name: path + required: true + schema: + type: string + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/ApplyEditRequest" + description: Code edit request + required: true + responses: + "200": + description: Code edit applied successfully + content: + application/json: + schema: + $ref: "#/components/schemas/ApplyEditResponse" + "400": + description: Invalid request + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "422": + description: Unprocessable entity - failed to process the request + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "503": + description: Service unavailable - no provider configured + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + summary: Apply code edit + tags: + - fastapply + "/codegen/reranking/{path}": + get: + description: >- + Uses Relace's code reranking model to find the most relevant files for a given query. This is useful as a first pass in agentic exploration to narrow down the search space. + + + Based on: https://docs.relace.ai/docs/code-reranker/agent + + + Query Construction: The query can be a short question or a more detailed conversation with the user request included. For a first pass, use the full conversation; for subsequent calls, use more targeted questions. + + + Token Limit and Score Threshold: For 200k token context models like Claude 4 Sonnet, recommended defaults are scoreThreshold=0.5 and tokenLimit=30000. + + + The response will be a list of file paths and contents ordered from most relevant to least relevant. + parameters: + - description: Path to search in (relative to workspace) + in: path + name: path + required: true + schema: + type: string + - description: Natural language query to search for + in: query + name: query + required: true + schema: + type: string + - description: "Minimum relevance score (default: 0.5)" + in: query + name: scoreThreshold + schema: + type: number + - description: "Maximum tokens to return (default: 30000)" + in: query + name: tokenLimit + schema: + type: integer + - description: Regex pattern to filter files (e.g., .*\\.ts$ for TypeScript files) + in: query + name: filePattern + schema: + type: string + responses: + "200": + description: Relevant files found + content: + application/json: + schema: + $ref: "#/components/schemas/RerankingResponse" + "400": + description: Invalid request + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "422": + description: Unprocessable entity - failed to process the request + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "503": + description: Service unavailable - Relace not configured + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + summary: Code reranking/semantic search + tags: + - codegen + /drives/mount: + get: + description: Returns a list of all currently mounted drives managed by blfs + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: "#/components/schemas/DriveListResponse" + "500": + description: Internal Server Error + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + security: + - BearerAuth: [] + summary: List currently mounted drives + tags: + - drive + post: + description: Mounts an agent drive using the blfs binary to a local path, optionally mounting a subpath within the drive. Supports optional UID/GID mapping to remap file ownership between the local sandbox and the filer (always mapped to filer UID/GID 0). Mapping values can be set per-request via uidMap/gidMap fields, or globally via BLFS_UID_MAP/BLFS_GID_MAP environment variables (request values take precedence). + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/DriveMountRequest" + description: Drive attachment parameters + required: true + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: "#/components/schemas/DriveMountResponse" + "400": + description: Bad Request + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "403": + description: Forbidden + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "409": + description: Conflict + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "500": + description: Internal Server Error + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + security: + - BearerAuth: [] + summary: Attach a drive to a local path + tags: + - drive + "/drives/mount/{mountPath}": + delete: + description: Unmounts a previously mounted drive from the specified local path + parameters: + - description: Mount path to detach (must start with /, e.g. /mnt/test) + in: path + name: mountPath + required: true + schema: + type: string + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: "#/components/schemas/DriveUnmountResponse" + "400": + description: Bad Request + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "500": + description: Internal Server Error + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + security: + - BearerAuth: [] + summary: Detach a drive from a local path + tags: + - drive + /environment/reload: + post: + description: Re-reads /bl/metadata and applies its environment to the sandbox-api process, so this process and every process started afterwards see the current values. Called by the guest init after an environment update; safe to call manually. + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: "#/components/schemas/handler.ReloadResponse" + "404": + description: Not Found + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "500": + description: Internal Server Error + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + summary: Reload environment from guest metadata + tags: + - system + "/filesystem-content-search/{path}": + get: + description: Searches for text content inside files using ripgrep. Returns matching lines with context. + parameters: + - description: Directory path to search in + in: path + name: path + required: true + schema: + type: string + - description: Text to search for + in: query + name: query + required: true + schema: + type: string + - description: "Case sensitive search (default: false)" + in: query + name: caseSensitive + schema: + type: boolean + - description: "Maximum number of results to return (default: 100)" + in: query + name: maxResults + schema: + type: integer + - description: File pattern to include (e.g., *.go) + in: query + name: filePattern + schema: + type: string + - description: "Comma-separated directory names to skip (default: node_modules,vendor,.git,dist,build,target,__pycache__,.venv,.next,coverage)" + in: query + name: excludeDirs + schema: + type: string + responses: + "200": + description: Content search results + content: + application/json: + schema: + $ref: "#/components/schemas/ContentSearchResponse" + "400": + description: Bad request + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "422": + description: Unprocessable entity + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "500": + description: Internal server error + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + summary: Search for text content in files + tags: + - filesystem + "/filesystem-find/{path}": + get: + description: Finds files and directories using the find command. + parameters: + - description: Path to search in (e.g., /home/user/projects) + in: path + name: path + required: true + schema: + type: string + - description: Type of search (file or directory) + in: query + name: type + schema: + type: string + - description: Comma-separated file patterns to include (e.g., *.go,*.js) + in: query + name: patterns + schema: + type: string + - description: "Maximum number of results to return (default: 20). If set to 0, all results will be returned." + in: query + name: maxResults + schema: + type: integer + - description: "Comma-separated directory names to skip (default: node_modules,vendor,.git,dist,build,target,__pycache__,.venv,.next,coverage). Use empty string to skip no directories." + in: query + name: excludeDirs + schema: + type: string + - description: "Exclude hidden files and directories (default: true)" + in: query + name: excludeHidden + schema: + type: boolean + responses: + "200": + description: Find results + content: + application/json: + schema: + $ref: "#/components/schemas/FindResponse" + "400": + description: Bad request + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "422": + description: Unprocessable entity + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "500": + description: Internal server error + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + summary: Find files and directories + tags: + - filesystem + /filesystem-multipart: + get: + description: List all active multipart uploads + responses: + "200": + description: List of active uploads + content: + application/json: + schema: + $ref: "#/components/schemas/MultipartListUploadsResponse" + "500": + description: Internal server error + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + summary: List multipart uploads + tags: + - filesystem + "/filesystem-multipart/{uploadId}/abort": + delete: + description: Abort a multipart upload and clean up all parts + parameters: + - description: Upload ID + in: path + name: uploadId + required: true + schema: + type: string + responses: + "200": + description: Upload aborted + content: + application/json: + schema: + $ref: "#/components/schemas/SuccessResponse" + "400": + description: Bad request + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "404": + description: Upload not found + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "500": + description: Internal server error + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + summary: Abort multipart upload + tags: + - filesystem + "/filesystem-multipart/{uploadId}/complete": + post: + description: Complete a multipart upload by assembling all parts + parameters: + - description: Upload ID + in: path + name: uploadId + required: true + schema: + type: string + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/MultipartCompleteRequest" + description: List of parts + required: true + responses: + "200": + description: Upload completed + content: + application/json: + schema: + $ref: "#/components/schemas/SuccessResponse" + "400": + description: Bad request + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "404": + description: Upload not found + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "500": + description: Internal server error + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + summary: Complete multipart upload + tags: + - filesystem + "/filesystem-multipart/{uploadId}/part": + put: + description: Upload a single part of a multipart upload + parameters: + - description: Upload ID + in: path + name: uploadId + required: true + schema: + type: string + - description: Part number (1-10000) + in: query + name: partNumber + required: true + schema: + type: integer + requestBody: + content: + multipart/form-data: + schema: + type: object + properties: + file: + description: Part data + type: string + format: binary + required: + - file + required: true + responses: + "200": + description: Part uploaded + content: + application/json: + schema: + $ref: "#/components/schemas/MultipartUploadPartResponse" + "400": + description: Bad request + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "404": + description: Upload not found + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "500": + description: Internal server error + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + summary: Upload part + tags: + - filesystem + "/filesystem-multipart/{uploadId}/parts": + get: + description: List all uploaded parts for a multipart upload + parameters: + - description: Upload ID + in: path + name: uploadId + required: true + schema: + type: string + responses: + "200": + description: List of parts + content: + application/json: + schema: + $ref: "#/components/schemas/MultipartListPartsResponse" + "400": + description: Bad request + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "404": + description: Upload not found + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "500": + description: Internal server error + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + summary: List parts + tags: + - filesystem + "/filesystem-multipart/initiate/{path}": + post: + description: Initiate a multipart upload session for a file + parameters: + - description: File path + in: path + name: path + required: true + schema: + type: string + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/MultipartInitiateRequest" + description: Optional permissions + responses: + "200": + description: Upload session created + content: + application/json: + schema: + $ref: "#/components/schemas/MultipartInitiateResponse" + "400": + description: Bad request + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "500": + description: Internal server error + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + summary: Initiate multipart upload + tags: + - filesystem + "/filesystem-search/{path}": + get: + description: Performs fuzzy search on filesystem paths using fuzzy matching algorithm. Optimized alternative to find and grep commands. + parameters: + - description: Path to search in (e.g., /home/user/projects) + in: path + name: path + required: true + schema: + type: string + - description: "Maximum number of results to return (default: 20)" + in: query + name: maxResults + schema: + type: integer + - description: Comma-separated file patterns to include (e.g., *.go,*.js) + in: query + name: patterns + schema: + type: string + - description: "Comma-separated directory names to skip (default: node_modules,vendor,.git,dist,build,target,__pycache__,.venv,.next,coverage). Use empty string to skip no directories." + in: query + name: excludeDirs + schema: + type: string + - description: "Exclude hidden files and directories (default: true)" + in: query + name: excludeHidden + schema: + type: boolean + responses: + "200": + description: Fuzzy search results + content: + application/json: + schema: + $ref: "#/components/schemas/FuzzySearchResponse" + "400": + description: Bad request + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "422": + description: Unprocessable entity + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "500": + description: Internal server error + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + summary: Fuzzy search for files and directories + tags: + - filesystem + "/filesystem/{path}": + delete: + description: Delete a file or directory + parameters: + - description: File or directory path + in: path + name: path + required: true + schema: + type: string + - description: Delete directory recursively + in: query + name: recursive + schema: + type: boolean + responses: + "200": + description: Success message + content: + application/json: + schema: + $ref: "#/components/schemas/SuccessResponse" + "404": + description: File or directory not found + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "422": + description: Unprocessable entity + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "500": + description: Internal server error + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + summary: Delete file or directory + tags: + - filesystem + get: + description: Get content of a file or listing of a directory. Use Accept header to control response format for files. + parameters: + - description: File or directory path + in: path + name: path + required: true + schema: + type: string + - description: Force download mode for files + in: query + name: download + schema: + type: boolean + responses: + "200": + description: Directory listing + content: + application/json: + schema: + oneOf: + - $ref: "#/components/schemas/Directory" + - $ref: "#/components/schemas/FileWithContent" + - type: string + format: binary + application/octet-stream: + schema: + oneOf: + - $ref: "#/components/schemas/Directory" + - $ref: "#/components/schemas/FileWithContent" + - type: string + format: binary + "404": + description: File or directory not found + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + application/octet-stream: + schema: + $ref: "#/components/schemas/ErrorResponse" + "422": + description: Unprocessable entity + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + application/octet-stream: + schema: + $ref: "#/components/schemas/ErrorResponse" + "500": + description: Internal server error + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + application/octet-stream: + schema: + $ref: "#/components/schemas/ErrorResponse" + summary: Get file or directory information + tags: + - filesystem + put: + description: Create or update a file or directory + parameters: + - description: File or directory path + in: path + name: path + required: true + schema: + type: string + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/FileRequest" + description: File or directory details + required: true + responses: + "200": + description: Success message + content: + application/json: + schema: + $ref: "#/components/schemas/SuccessResponse" + "400": + description: Bad request + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "422": + description: Unprocessable entity + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "500": + description: Internal server error + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + summary: Create or update a file or directory + tags: + - filesystem + "/filesystem/tree/{path}": + delete: + description: Delete a directory tree recursively + parameters: + - description: Root directory path + in: path + name: path + required: true + schema: + type: string + - description: Delete directory recursively + in: query + name: recursive + schema: + type: boolean + responses: + "200": + description: Directory deleted successfully + content: + application/json: + schema: + $ref: "#/components/schemas/SuccessResponse" + "400": + description: Bad request + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "422": + description: Unprocessable entity + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "500": + description: Internal server error + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + summary: Delete directory tree + tags: + - filesystem + get: + description: Get a recursive directory tree structure starting from the specified path + parameters: + - description: Root directory path + in: path + name: path + required: true + schema: + type: string + responses: + "200": + description: Directory tree + content: + application/json: + schema: + oneOf: + - $ref: "#/components/schemas/Directory" + - $ref: "#/components/schemas/FileWithContent" + - type: string + format: binary + "400": + description: Bad request + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "422": + description: Unprocessable entity + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "500": + description: Internal server error + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + summary: Get directory tree + tags: + - filesystem + put: + description: Create or update multiple files within a directory tree structure + parameters: + - description: Root directory path + in: path + name: path + required: true + schema: + type: string + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/TreeRequest" + description: Map of file paths to content + required: true + responses: + "200": + description: Updated directory tree + content: + application/json: + schema: + oneOf: + - $ref: "#/components/schemas/Directory" + - $ref: "#/components/schemas/FileWithContent" + - type: string + format: binary + "400": + description: Bad request + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "422": + description: Unprocessable entity + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "500": + description: Internal server error + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + summary: Create or update directory tree + tags: + - filesystem + /health: + get: + description: >- + Returns health status and system information including upgrade count and binary details + + Also includes last upgrade attempt status with detailed error information if available + responses: + "200": + description: Health status + content: + application/json: + schema: + $ref: "#/components/schemas/HealthResponse" + summary: Health check + tags: + - system + "/network/process/{pid}/monitor": + delete: + description: Stop monitoring for new ports opened by a process + parameters: + - description: Process ID + in: path + name: pid + required: true + schema: + type: integer + responses: + "200": + description: Object containing PID and success message + content: + application/json: + schema: + additionalProperties: true + type: object + "400": + description: Invalid process ID + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "422": + description: Unprocessable entity + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "500": + description: Internal server error + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + summary: Stop monitoring ports for a process + tags: + - network + post: + description: Start monitoring for new ports opened by a process + parameters: + - description: Process ID + in: path + name: pid + required: true + schema: + type: integer + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/PortMonitorRequest" + description: Port monitor configuration + required: true + responses: + "200": + description: Object containing PID and success message + content: + application/json: + schema: + additionalProperties: true + type: object + "400": + description: Invalid request + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "422": + description: Unprocessable entity + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "500": + description: Internal server error + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + summary: Start monitoring ports for a process + tags: + - network + "/network/process/{pid}/ports": + get: + description: Get a list of all open ports for a process + parameters: + - description: Process ID + in: path + name: pid + required: true + schema: + type: integer + responses: + "200": + description: Object containing PID and array of network.PortInfo + content: + application/json: + schema: + additionalProperties: true + type: object + "400": + description: Invalid process ID + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "422": + description: Unprocessable entity + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "500": + description: Internal server error + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + summary: Get open ports for a process + tags: + - network + /network/tunnel: + delete: + description: "Stop the network tunnel and restore the original network configuration. WARNING: After disconnecting, the sandbox will lose all outbound internet connectivity (no egress). Inbound connections to the sandbox will still work. Use PUT /network/tunnel/config to re-establish the tunnel." + responses: + "200": + description: Tunnel disconnected + content: + application/json: + schema: + $ref: "#/components/schemas/SuccessResponse" + "400": + description: No tunnel is running + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "500": + description: Failed to stop tunnel + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + summary: Disconnect tunnel + tags: + - network + /network/tunnel/config: + put: + description: Apply a new tunnel configuration on the fly. The existing tunnel is torn down and a new one is established. This endpoint is write-only; there is no corresponding GET to read the config back. + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/TunnelConfigRequest" + description: Base64-encoded tunnel configuration + required: true + responses: + "200": + description: Configuration applied + content: + application/json: + schema: + $ref: "#/components/schemas/SuccessResponse" + "400": + description: Invalid request body + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "422": + description: Invalid tunnel configuration + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "500": + description: Failed to apply configuration + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + summary: Update tunnel configuration + tags: + - network + /process: + get: + description: Get a list of all running and completed processes + responses: + "200": + description: Process list + content: + application/json: + schema: + items: + $ref: "#/components/schemas/ProcessResponse" + type: array + summary: List all processes + tags: + - process + post: + description: Execute a command and return process information. If Accept header is text/event-stream, streams logs in SSE format and returns the process response as a final event. + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/ProcessRequest" + description: Process execution request + required: true + responses: + "200": + description: Process information + content: + application/json: + schema: + $ref: "#/components/schemas/ProcessResponse" + text/event-stream: + schema: + $ref: "#/components/schemas/ProcessResponse" + "400": + description: Invalid request + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + text/event-stream: + schema: + $ref: "#/components/schemas/ErrorResponse" + "422": + description: Unprocessable entity + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + text/event-stream: + schema: + $ref: "#/components/schemas/ErrorResponse" + "500": + description: Internal server error + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + text/event-stream: + schema: + $ref: "#/components/schemas/ErrorResponse" + summary: Execute a command + tags: + - process + "/process/{identifier}": + delete: + description: Gracefully stop a running process + parameters: + - description: Process identifier (PID or name) + in: path + name: identifier + required: true + schema: + type: string + responses: + "200": + description: Process stopped + content: + application/json: + schema: + $ref: "#/components/schemas/SuccessResponse" + "404": + description: Process not found + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "422": + description: Unprocessable entity + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "500": + description: Internal server error + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + summary: Stop a process + tags: + - process + get: + description: Get information about a process by its PID or name + parameters: + - description: Process identifier (PID or name) + in: path + name: identifier + required: true + schema: + type: string + responses: + "200": + description: Process information + content: + application/json: + schema: + $ref: "#/components/schemas/ProcessResponse" + "404": + description: Process not found + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + summary: Get process by identifier + tags: + - process + "/process/{identifier}/kill": + delete: + description: Forcefully kill a running process + parameters: + - description: Process identifier (PID or name) + in: path + name: identifier + required: true + schema: + type: string + responses: + "200": + description: Process killed + content: + application/json: + schema: + $ref: "#/components/schemas/SuccessResponse" + "404": + description: Process not found + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "422": + description: Unprocessable entity + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "500": + description: Internal server error + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + summary: Kill a process + tags: + - process + "/process/{identifier}/logs": + get: + description: Get the stdout and stderr output of a process + parameters: + - description: Process identifier (PID or name) + in: path + name: identifier + required: true + schema: + type: string + responses: + "200": + description: Process logs + content: + application/json: + schema: + $ref: "#/components/schemas/ProcessLogs" + "404": + description: Process not found + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "422": + description: Unprocessable entity + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "500": + description: Internal server error + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + summary: Get process logs + tags: + - process + "/process/{identifier}/logs/stream": + get: + description: Streams the stdout and stderr output of a process in real time, one line per log, prefixed with 'stdout:' or 'stderr:'. Closes when the process exits or the client disconnects. + parameters: + - description: Process identifier (PID or name) + in: path + name: identifier + required: true + schema: + type: string + responses: + "200": + description: Stream of process logs, one line per log (prefixed with stdout:/stderr:) + content: + text/plain: + schema: + type: string + "404": + description: Process not found + content: + text/plain: + schema: + $ref: "#/components/schemas/ErrorResponse" + "422": + description: Unprocessable entity + content: + text/plain: + schema: + $ref: "#/components/schemas/ErrorResponse" + "500": + description: Internal server error + content: + text/plain: + schema: + $ref: "#/components/schemas/ErrorResponse" + summary: Stream process logs in real time + tags: + - process + "/process/{identifier}/stdin": + delete: + description: Send EOF to the process by closing its stdin pipe. Idempotent. For stdio protocols such as MCP this is the clean shutdown path. + parameters: + - description: Process identifier (PID or name) + in: path + name: identifier + required: true + schema: + type: string + responses: + "200": + description: Stdin closed + content: + application/json: + schema: + $ref: "#/components/schemas/SuccessResponse" + "404": + description: Process not found + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "409": + description: Process has no stdin + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + summary: Close a process's stdin + tags: + - process + post: + description: 'Write the raw request body to the stdin of a process started with "stdin": true. Bytes are forwarded verbatim, so include the trailing newline your protocol expects. Sequential requests keep their order; each body is written atomically with respect to other writers. The pipe does not survive a sandbox-api restart: once it is gone this returns 409 and the process must be restarted.' + parameters: + - description: Process identifier (PID or name) + in: path + name: identifier + required: true + schema: + type: string + requestBody: + content: + application/octet-stream: + schema: + type: string + description: Raw bytes to write + required: true + responses: + "200": + description: Bytes written + content: + application/json: + schema: + $ref: "#/components/schemas/SuccessResponse" + "404": + description: Process not found + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "409": + description: Process has no stdin, or stdin is closed + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "413": + description: Body over 8 MiB + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "500": + description: Write failed + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + "503": + description: Process stopped reading its stdin + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + summary: Write to a process's stdin + tags: + - process + /upgrade: + post: + description: >- + Triggers an upgrade of the sandbox-api process. Returns 200 immediately before upgrading. + + The upgrade will: download the specified binary from GitHub releases, validate it, and restart. + + All running processes will be preserved across the upgrade. + + Available versions: "latest" (default, most recent release), "develop", "main", or specific tag like "v1.0.0" + + You can also specify a custom baseUrl for forks (defaults to https://github.com/blaxel-ai/sandbox/releases) + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/UpgradeRequest" + description: Upgrade options + responses: + "200": + description: Upgrade initiated + content: + application/json: + schema: + $ref: "#/components/schemas/SuccessResponse" + "500": + description: Internal server error + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + summary: Upgrade the sandbox-api + tags: + - system + "/watch/filesystem/{path}": + get: + description: Streams the path of modified files (one per line) in the given directory. Closes when the client disconnects. + parameters: + - description: Ignore patterns (comma-separated) + in: query + name: ignore + schema: + type: string + - description: Directory path to watch + in: path + name: path + required: true + schema: + type: string + responses: + "200": + description: Stream of modified file paths, one per line + content: + text/plain: + schema: + type: string + "400": + description: Invalid path + content: + text/plain: + schema: + $ref: "#/components/schemas/ErrorResponse" + "500": + description: Internal server error + content: + text/plain: + schema: + $ref: "#/components/schemas/ErrorResponse" + summary: Stream file modification events in a directory + tags: + - filesystem +servers: + - url: https://sbx-{sandbox_id}-{workspace_id}.{region}.bl.run + variables: + sandbox_id: + default: unknown + workspace_id: + default: unknown + region: + default: unknown +components: + securitySchemes: + BearerAuth: + type: http + scheme: bearer + bearerFormat: JWT + schemas: + ApplyEditRequest: + properties: + codeEdit: + example: |- + // Add world parameter + function hello(world) { + console.log('Hello', world); + } + type: string + model: + example: relace-apply-3 + type: string + required: + - codeEdit + type: object + ApplyEditResponse: + properties: + message: + example: Code edit applied successfully + type: string + originalContent: + example: |- + function hello() { + console.log('Hello'); + } + type: string + path: + example: src/main.js + type: string + provider: + example: Relace + type: string + success: + example: true + type: boolean + updatedContent: + example: |- + function hello(world) { + console.log('Hello', world); + } + type: string + type: object + ArchiveManifest: + properties: + added: + description: Added and Modified count the archive's payload members. + example: 11 + type: integer + apiVersion: + description: APIVersion is the sandbox-api build that produced the archive. + example: v0.1.0 + type: string + createdAt: + type: string + deleted: + description: >- + Deleted are paths the image has and the sandbox deleted. Tar cannot carry + + a deletion, so import applies these from the manifest. + items: + type: string + type: array + excludes: + description: Excludes are the paths left out of the comparison. + items: + type: string + type: array + imageDevice: + description: >- + ImageDevice is the device the pristine image was read from, for the record: + + it says where the sandbox that exported the archive found its image. + example: /dev/vda + type: string + modified: + example: 3 + type: integer + payloadBytes: + description: PayloadBytes is the total content size of the payload members. + example: 3073449 + type: integer + processes: + description: Processes tells whether ProcessesName is present. + example: true + type: boolean + root: + description: Root is the directory the paths are relative to. + example: / + type: string + version: + example: 1 + type: integer + required: + - createdAt + - root + - version + type: object + ContentSearchMatch: + properties: + column: + example: 10 + type: integer + context: + example: |- + previous line + current line + next line + type: string + line: + example: 42 + type: integer + path: + example: src/main.go + type: string + text: + example: const searchText = 'example' + type: string + required: + - column + - line + - path + - text + type: object + ContentSearchResponse: + properties: + matches: + items: + $ref: "#/components/schemas/ContentSearchMatch" + type: array + query: + example: searchText + type: string + total: + example: 5 + type: integer + required: + - matches + - query + - total + type: object + Directory: + properties: + files: + items: + $ref: "#/components/schemas/File" + type: array + name: + type: string + path: + type: string + subdirectories: + description: "@name Subdirectories" + items: + $ref: "#/components/schemas/Subdirectory" + type: array + required: + - files + - name + - path + - subdirectories + type: object + DriveListResponse: + properties: + mounts: + items: + $ref: "#/components/schemas/DriveMountInfo" + type: array + type: object + DriveMountInfo: + properties: + driveName: + type: string + drivePath: + type: string + gidMap: + description: The local GID used for this mount + type: string + mountPath: + type: string + readOnly: + type: boolean + uidMap: + description: The local UID used for this mount + type: string + type: object + DriveMountRequest: + properties: + driveName: + type: string + drivePath: + description: Optional, defaults to "/" + type: string + gidMap: + description: Optional, local GID to map (filer GID is always 0) + type: string + mountPath: + type: string + readOnly: + description: Optional, defaults to false + type: boolean + uidMap: + description: Optional, local UID to map (filer UID is always 0) + type: string + required: + - driveName + - mountPath + type: object + DriveMountResponse: + properties: + driveName: + type: string + drivePath: + type: string + gidMap: + description: The local GID used for this mount + type: string + message: + type: string + mountPath: + type: string + readOnly: + type: boolean + success: + type: boolean + uidMap: + description: The local UID used for this mount + type: string + type: object + DriveUnmountResponse: + properties: + message: + type: string + mountPath: + type: string + success: + type: boolean + type: object + ErrorResponse: + properties: + error: + example: Error message + type: string + required: + - error + type: object + ExportOptions: + properties: + async: + description: >- + Async starts the export and answers immediately, leaving it to run: an + + archive of a large filesystem takes longer than a request may be held + + open. Its progress is reported by /archive/status. + example: false + type: boolean + dryRun: + description: |- + DryRun reports what would be archived, and its exact size, without + stopping anything and without uploading. + example: false + type: boolean + excludes: + description: Excludes are added to the paths excluded by default. + items: + type: string + type: array + headers: + additionalProperties: + type: string + description: >- + Headers are sent with the upload request as given. A presigned URL only + + accepts the headers it was signed for, so these have to match what the + + caller signed: sending one that was not signed, or signing one that is not + + sent, is rejected as a signature mismatch. Typical use is a storage class, + + x-amz-storage-class: GLACIER_IR. + type: object + imageDevice: + description: >- + ImageDevice is the device holding the pristine image. It is found on its + + own, wherever the sandbox booted from attached it, and naming one here + + only overrides that. + example: /dev/vda + type: string + imageMountPoint: + description: >- + ImageMountPoint is a directory where the pristine image is already mounted. + + When set the image device is neither mounted nor unmounted. + example: /mnt/lower + type: string + multipart: + allOf: + - $ref: "#/components/schemas/MultipartUpload" + description: >- + Multipart uploads the archive part by part instead, which is how an + + archive larger than the 5 GB a single PUT accepts is stored. It takes + + precedence over URL. + saveProcesses: + description: |- + SaveProcesses stores the process list in the archive so restore can + relaunch the workload. Defaults to true; set it to false to archive + storage only. + example: true + type: boolean + stopTimeoutSeconds: + description: StopTimeoutSeconds bounds the graceful stop of each process. + example: 30 + type: integer + url: + description: >- + URL is a presigned S3 PUT URL the archive is streamed to. Empty is only + + valid with DryRun, or with Multipart. + example: https://bucket.s3.amazonaws.com/key?... + type: string + type: object + ExportProgress: + properties: + error: + description: Error is why the export failed, without the presigned URL it used. + type: string + finishedAt: + type: string + size: + description: Size is the archive's exact size, known once the filesystem is scanned. + example: 3074211 + type: integer + startedAt: + type: string + state: + allOf: + - $ref: "#/components/schemas/archive.ExportState" + example: running + uploaded: + description: Uploaded reports whether the storage holds the archive. + example: false + type: boolean + type: object + ExportResult: + properties: + changes: + description: |- + Changes lists every path in the archive. Only filled for a dry run, + where it is the point of the call. + items: + $ref: "#/components/schemas/archive.Change" + type: array + duration: + example: 4.2s + type: string + manifest: + $ref: "#/components/schemas/ArchiveManifest" + size: + description: |- + Size is the exact number of bytes uploaded, known before the upload + starts since the archive is not compressed. + example: 3074211 + type: integer + stoppedProcesses: + description: StoppedProcesses are the processes stopped to freeze the filesystem. + items: + type: string + type: array + uploaded: + description: Uploaded is false for a dry run. + example: true + type: boolean + required: + - manifest + type: object + File: + properties: + group: + type: string + lastModified: + type: string + name: + type: string + owner: + type: string + path: + type: string + permissions: + type: string + size: + type: integer + required: + - group + - lastModified + - name + - owner + - path + - permissions + - size + type: object + FileRequest: + properties: + content: + example: file contents here + type: string + isDirectory: + example: false + type: boolean + permissions: + example: "0644" + type: string + type: object + FileWithContent: + properties: + content: + type: string + group: + type: string + lastModified: + type: string + name: + type: string + owner: + type: string + path: + type: string + permissions: + type: string + size: + type: integer + required: + - content + - group + - lastModified + - name + - owner + - path + - permissions + - size + type: object + FindMatch: + properties: + path: + example: src/main.go + type: string + type: + description: '"file" or "directory"' + example: file + type: string + required: + - path + - type + type: object + FindResponse: + properties: + matches: + items: + $ref: "#/components/schemas/FindMatch" + type: array + total: + example: 5 + type: integer + required: + - matches + - total + type: object + FuzzySearchMatch: + properties: + path: + example: src/main.go + type: string + score: + example: 100 + type: integer + type: + description: '"file" or "directory"' + example: file + type: string + required: + - path + - score + - type + type: object + FuzzySearchResponse: + properties: + matches: + items: + $ref: "#/components/schemas/FuzzySearchMatch" + type: array + total: + example: 5 + type: integer + required: + - matches + - total + type: object + HealthResponse: + properties: + arch: + example: amd64 + type: string + buildTime: + example: 2026-01-29T17:36:52Z + type: string + gitCommit: + example: abc123 + type: string + goVersion: + example: go1.25.0 + type: string + lastUpgrade: + $ref: "#/components/schemas/UpgradeStatus" + os: + example: linux + type: string + startedAt: + example: 2026-01-29T18:45:49Z + type: string + status: + example: ok + type: string + upgradeCount: + example: 0 + type: integer + uptime: + example: 1h30m + type: string + uptimeSeconds: + example: 5400.5 + type: number + version: + example: v0.1.0 + type: string + required: + - arch + - buildTime + - gitCommit + - goVersion + - lastUpgrade + - os + - startedAt + - status + - upgradeCount + - uptime + - uptimeSeconds + - version + type: object + MultipartCompleteRequest: + properties: + parts: + items: + $ref: "#/components/schemas/MultipartPartInfo" + type: array + type: object + MultipartInitiateRequest: + properties: + permissions: + example: "0644" + type: string + type: object + MultipartInitiateResponse: + properties: + path: + example: /tmp/largefile.dat + type: string + uploadId: + example: 550e8400-e29b-41d4-a716-446655440000 + type: string + type: object + MultipartListPartsResponse: + properties: + parts: + items: + $ref: "#/components/schemas/filesystem.UploadedPart" + type: array + uploadId: + example: 550e8400-e29b-41d4-a716-446655440000 + type: string + type: object + MultipartListUploadsResponse: + properties: + uploads: + items: + $ref: "#/components/schemas/filesystem.MultipartUpload" + type: array + type: object + MultipartPartInfo: + properties: + etag: + example: 5d41402abc4b2a76b9719d911017c592 + type: string + partNumber: + example: 1 + type: integer + type: object + MultipartUpload: + properties: + abortUrl: + description: >- + AbortURL is a presigned DELETE URL that discards the parts already + + uploaded. Without it a failed export leaves them on the storage until a + + lifecycle rule removes them. + type: string + completeUrl: + description: CompleteURL is a presigned POST URL that assembles the parts. + type: string + partSize: + description: PartSize is the number of bytes sent to every part but the last. + example: 536870912 + type: integer + partUrls: + description: >- + PartURLs are presigned PUT URLs, one per part, in order. Extra ones are + + left unused. + items: + type: string + type: array + type: object + MultipartUploadPartResponse: + properties: + etag: + example: 5d41402abc4b2a76b9719d911017c592 + type: string + partNumber: + example: 1 + type: integer + size: + example: 5242880 + type: integer + type: object + PortMonitorRequest: + properties: + callback: + description: URL to call when a new port is detected + example: http://localhost:3000/callback + type: string + type: object + ProcessLogs: + properties: + logs: + example: logs output + type: string + stderr: + example: stderr output + type: string + stdout: + example: stdout output + type: string + required: + - logs + - stderr + - stdout + type: object + ProcessRequest: + properties: + command: + example: ls -la + type: string + env: + additionalProperties: + type: string + example: + "{\"PORT\"": ' "3000"}' + type: object + keepAlive: + description: Disable scale-to-zero while process runs. Default timeout is 600s (10 minutes). Set timeout to 0 for infinite. + example: false + type: boolean + maxRestarts: + description: Maximum number of restarts on failure. Set to a negative value (e.g. -1) for unlimited restarts. + example: 3 + type: integer + name: + example: my-process + type: string + restartOnFailure: + example: true + type: boolean + stdin: + description: "Open a writable stdin pipe, fed via POST /process/{identifier}/stdin and closed via DELETE. The pipe does not survive a sandbox-api restart: the process then sees EOF." + example: false + type: boolean + timeout: + description: Timeout in seconds. When keepAlive is true, defaults to 600s (10 minutes). Set to 0 for infinite (no auto-kill). + example: 30 + type: integer + waitForCompletion: + example: false + type: boolean + waitForPorts: + example: + - 3000 + - 8080 + items: + type: integer + type: array + workingDir: + example: /home/user + type: string + required: + - command + type: object + ProcessResponse: + properties: + command: + example: ls -la + type: string + completedAt: + example: Wed, 01 Jan 2023 12:01:00 GMT + type: string + exitCode: + example: 0 + type: integer + keepAlive: + description: Whether scale-to-zero is disabled for this process + example: false + type: boolean + logs: + example: logs output + type: string + maxRestarts: + example: 3 + type: integer + name: + example: my-process + type: string + pid: + example: "1234" + type: string + restartCount: + example: 2 + type: integer + restartOnFailure: + example: true + type: boolean + startedAt: + example: Wed, 01 Jan 2023 12:00:00 GMT + type: string + status: + enum: + - failed + - killed + - stopped + - running + - completed + example: running + type: string + stderr: + example: stderr output + type: string + stdin: + description: Whether the process was started with a writable stdin pipe + example: false + type: boolean + stdout: + example: stdout output + type: string + workingDir: + example: /home/user + type: string + required: + - command + - completedAt + - exitCode + - logs + - name + - pid + - startedAt + - status + - stderr + - stdout + - workingDir + type: object + QuiesceStatus: + properties: + export: + allOf: + - $ref: "#/components/schemas/ExportProgress" + description: >- + Export reports the export started asynchronously, if there was one. It is + + how a caller that did not wait for the export learns that the archive is + + on the storage, or why it is not. + readOnlyRoot: + description: >- + ReadOnlyRoot reports whether the root mount was remounted read-only, which + + is what actually stops writes; false means the freeze relies only on the + + API refusing calls, and the reason says why. + example: true + type: boolean + reason: + description: Reason is a human readable explanation of why the sandbox is frozen. + example: archive export + type: string + restore: + allOf: + - $ref: "#/components/schemas/RestoreProgress" + description: |- + Restore reports the archive this sandbox was started from, if it was + started from one: how far its restore has got, and how it ended. + since: + description: Since is when the sandbox left StateActive. + type: string + state: + allOf: + - $ref: "#/components/schemas/archive.QuiesceState" + example: quiesced + stoppedProcesses: + description: StoppedProcesses are the process identifiers stopped while quiescing. + items: + type: string + type: array + required: + - state + type: object + RankedFile: + properties: + content: + type: string + path: + type: string + score: + type: number + type: object + RerankingResponse: + properties: + files: + items: + $ref: "#/components/schemas/RankedFile" + type: array + message: + example: Found 5 relevant files + type: string + success: + example: true + type: boolean + type: object + RestoreProgress: + properties: + deleted: + example: 3 + type: integer + downloaded: + description: Downloaded is how much of the archive has been read so far. + example: 1048576 + type: integer + error: + description: Error is why the restore failed, without the presigned URL it used. + type: string + finishedAt: + type: string + restored: + description: Restored and Deleted count what the archive changed on the filesystem. + example: 1204 + type: integer + size: + description: >- + Size is the archive's size as the storage announced it, and zero when it + + announced none - a client showing a percentage has to allow for that. + example: 3074211 + type: integer + startedAt: + type: string + state: + allOf: + - $ref: "#/components/schemas/archive.RestoreState" + example: extracting + type: object + Subdirectory: + properties: + name: + type: string + path: + type: string + required: + - name + - path + type: object + SuccessResponse: + properties: + message: + example: File created successfully + type: string + path: + example: /path/to/file + type: string + required: + - message + type: object + TreeRequest: + properties: + files: + additionalProperties: + type: string + example: + '"dir/file2.txt"': '"content2"}' + "{\"file1.txt\"": '"content1"' + type: object + type: object + TunnelConfigRequest: + properties: + config: + description: Base64-encoded tunnel config JSON + example: eyJsb2NhbF9pcCI6ICIxMC4wLjAuMS8zMiIsIC4uLn0= + type: string + required: + - config + type: object + UpgradeRequest: + properties: + baseUrl: + description: Base URL for releases (useful for forks) + example: https://github.com/blaxel-ai/sandbox/releases + type: string + version: + description: 'Version to upgrade to: "latest" (default), "develop", "main", or specific tag like "v1.0.0"' + example: latest + type: string + type: object + UpgradeStatus: + properties: + binaryPath: + description: Path to downloaded binary + example: /tmp/sandbox-api-new + type: string + bytesDownloaded: + description: Bytes downloaded + example: 25034936 + type: integer + downloadUrl: + description: URL used for download + example: https://github.com/... + type: string + error: + description: Error message if failed + example: Failed to download binary + type: string + lastAttempt: + description: When the upgrade was attempted + type: string + status: + allOf: + - $ref: "#/components/schemas/process.UpgradeState" + description: Current state (idle, running, completed, failed) + example: running + step: + description: Current/last step (none, starting, download, validate, replace, completed, skipped) + example: download + type: string + version: + description: Version being upgraded to + example: latest + type: string + required: + - status + - step + - version + type: object + archive.Change: + properties: + kind: + allOf: + - $ref: "#/components/schemas/archive.ChangeKind" + example: added + path: + description: Path is relative to the root, without a leading slash. + example: usr/bin/curl + type: string + size: + description: Size is the file content size in bytes, 0 for anything but a regular file. + example: 256216 + type: integer + required: + - kind + - path + type: object + archive.ChangeKind: + enum: + - added + - modified + - deleted + type: string + x-enum-varnames: + - ChangeAdded + - ChangeModified + - ChangeDeleted + archive.ExportState: + enum: + - running + - succeeded + - failed + type: string + x-enum-varnames: + - ExportRunning + - ExportSucceeded + - ExportFailed + archive.QuiesceState: + enum: + - active + - quiescing + - quiesced + - restoring + type: string + x-enum-varnames: + - StateActive + - StateQuiescing + - StateQuiesced + - StateRestoring + archive.RestoreState: + enum: + - downloading + - extracting + - relaunching + - succeeded + - failed + type: string + x-enum-varnames: + - RestoreDownloading + - RestoreExtracting + - RestoreRelaunching + - RestoreSucceeded + - RestoreFailed + filesystem.MultipartUpload: + properties: + initiatedAt: + type: string + parts: + additionalProperties: + $ref: "#/components/schemas/filesystem.UploadedPart" + type: object + path: + example: /tmp/largefile.dat + type: string + permissions: + example: 420 + type: integer + uploadId: + example: 550e8400-e29b-41d4-a716-446655440000 + type: string + type: object + filesystem.UploadedPart: + properties: + etag: + example: 5d41402abc4b2a76b9719d911017c592 + type: string + partNumber: + example: 1 + type: integer + size: + example: 5242880 + type: integer + uploadedAt: + type: string + type: object + handler.ReloadResponse: + properties: + applied: + type: integer + generation: + type: integer + removed: + type: integer + type: object + process.UpgradeState: + enum: + - idle + - running + - completed + - failed + type: string + x-enum-comments: + UpgradeStateCompleted: Upgrade completed successfully + UpgradeStateFailed: Upgrade failed + UpgradeStateIdle: No upgrade in progress + UpgradeStateRunning: Upgrade is currently running + x-enum-descriptions: + - No upgrade in progress + - Upgrade is currently running + - Upgrade completed successfully + - Upgrade failed + x-enum-varnames: + - UpgradeStateIdle + - UpgradeStateRunning + - UpgradeStateCompleted + - UpgradeStateFailed +security: + - BearerAuth: [] diff --git a/scripts/docgen/conf.py b/scripts/docgen/conf.py index b7571ab..3888bd0 100644 --- a/scripts/docgen/conf.py +++ b/scripts/docgen/conf.py @@ -53,6 +53,7 @@ NAV_ONLY = { "baseten.client.managementapi": ["ApiClient", "AsyncApiClient"], "baseten.client.inferenceapi": ["ApiClient", "AsyncApiClient"], + "baseten.client.sandboxapi": ["ApiClient", "AsyncApiClient"], "baseten.client.modelconfig": ["ModelConfig"], } diff --git a/tests/client/test_management.py b/tests/client/test_management.py index 9aff422..5899d2c 100644 --- a/tests/client/test_management.py +++ b/tests/client/test_management.py @@ -84,7 +84,7 @@ def test_get_with_query_params() -> None: client = make_sync_client(fake) client.api.get_model_apis( - request=baseten.client.managementapi.GetModelApisRequest(added_only=True) + params=baseten.client.managementapi.GetModelApisParams(added_only=True) ) path, _, query = fake.capture.path.partition("?") diff --git a/tests/client/test_sandbox.py b/tests/client/test_sandbox.py new file mode 100644 index 0000000..c952a05 --- /dev/null +++ b/tests/client/test_sandbox.py @@ -0,0 +1,200 @@ +from __future__ import annotations + +import httpx +import pytest + +import baseten.client.sandboxapi +from baseten.client._sandbox import AsyncSandboxClient, SandboxClient +from tests.conftest import FakeTransport + +SANDBOX_URL = "https://sb-123.b10.co" + + +def make_sync_client(fake: FakeTransport) -> SandboxClient: + client = SandboxClient(token="test-token", base_url=SANDBOX_URL) + client.http_client._transport = fake.sync_transport # type: ignore[attr-defined] + return client + + +def make_async_client(fake: FakeTransport) -> AsyncSandboxClient: + client = AsyncSandboxClient(token="test-token", base_url=SANDBOX_URL) + client.http_client._transport = fake.async_transport # type: ignore[attr-defined] + return client + + +def test_bearer_token_sent() -> None: + fake = FakeTransport(200, {"message": "deleted"}) + client = make_sync_client(fake) + + client.api.delete_process(identifier="proc-1") + + assert fake.capture.path == "/process/proc-1" + assert fake.capture.headers["authorization"] == "Bearer test-token" + client.close() + + +def test_empty_token_omits_authorization() -> None: + fake = FakeTransport(200, {"message": "deleted"}) + client = SandboxClient(token="", base_url=SANDBOX_URL) + client.http_client._transport = fake.sync_transport # type: ignore[attr-defined] + + client.api.delete_process(identifier="proc-1") + + assert "authorization" not in fake.capture.headers + client.close() + + +def test_multipart_files_upload() -> None: + fake = FakeTransport(200, {"etag": "abc", "partNumber": 3, "size": 9}) + client = make_sync_client(fake) + + resp = client.api.put_filesystem_multipart_part( + upload_id="upload-1", + params=baseten.client.sandboxapi.PutFilesystemMultipartPartParams(partNumber=3), + files={"file": ("part.bin", b"part data")}, + ) + + assert resp.etag == "abc" + path, _, query = fake.capture.path.partition("?") + assert path == "/filesystem-multipart/upload-1/part" + assert query == "partNumber=3" + # httpx derives the multipart Content-Type, boundary included. + assert fake.capture.headers["content-type"].startswith("multipart/form-data") + assert b"part data" in fake.capture.body_bytes + client.close() + + +def test_octet_stream_body_sent_unmodified() -> None: + fake = FakeTransport(200, {"message": "written"}) + client = make_sync_client(fake) + + client.api.post_process_stdin(identifier="proc-1", content=b"raw stdin") + + assert fake.capture.path == "/process/proc-1/stdin" + assert fake.capture.headers["content-type"] == "application/octet-stream" + assert fake.capture.body_bytes == b"raw stdin" + client.close() + + +def test_raw_returns_response_unread_with_accept() -> None: + fake = FakeTransport( + 200, raw_content=b"file bytes", content_type="application/octet-stream" + ) + client = make_sync_client(fake) + + response = client.api.get_filesystem_raw( + path="file.txt", accept="application/octet-stream" + ) + + assert isinstance(response, httpx.Response) + assert response.content == b"file bytes" + assert fake.capture.headers["accept"] == "application/octet-stream" + client.close() + + +def test_raw_only_stream_keeps_plain_name() -> None: + fake = FakeTransport(200, raw_content=b"log line\n", content_type="text/plain") + client = make_sync_client(fake) + + response = client.api.get_process_logs_stream(identifier="proc-1") + + assert response.content == b"log line\n" + assert fake.capture.headers["accept"] == "text/plain" + client.close() + + +def test_export_narrows_on_status_code() -> None: + fake = FakeTransport( + 200, {"manifest": {"createdAt": "now", "root": "/", "version": 1}, "size": 1024} + ) + client = make_sync_client(fake) + + resp = client.api.post_archive_export( + request=baseten.client.sandboxapi.ExportOptions() + ) + + assert isinstance(resp, baseten.client.sandboxapi.ExportResult) + client.close() + + fake = FakeTransport(202, {}) + client = make_sync_client(fake) + + resp = client.api.post_archive_export( + request=baseten.client.sandboxapi.ExportOptions() + ) + + assert isinstance(resp, baseten.client.sandboxapi.ExportProgress) + client.close() + + +def test_query_params_serialize() -> None: + fake = FakeTransport(200, {"message": "watching"}) + client = make_sync_client(fake) + + client.api.get_watch_filesystem( + path="dir", + params=baseten.client.sandboxapi.GetWatchFilesystemParams(ignore="*.log"), + ) + + path, _, query = fake.capture.path.partition("?") + assert path == "/watch/filesystem/dir" + assert query == "ignore=%2A.log" + client.close() + + +def test_typed_error_keeps_status() -> None: + fake = FakeTransport(400, {"error": "boom"}) + client = make_sync_client(fake) + + with pytest.raises(baseten.client.sandboxapi.ResponseErrorResponse) as exc_info: + client.api.post_process( + request=baseten.client.sandboxapi.ProcessRequest(command="ls") + ) + + assert exc_info.value.status_code == 400 + assert exc_info.value.error_response.error == "boom" + client.close() + + +def test_untyped_error_on_non_schema_body() -> None: + fake = FakeTransport( + 400, raw_content=b"proxy error", content_type="text/html" + ) + client = make_sync_client(fake) + + with pytest.raises(baseten.client.sandboxapi.ResponseError) as exc_info: + client.api.post_process( + request=baseten.client.sandboxapi.ProcessRequest(command="ls") + ) + + assert exc_info.value.status_code == 400 + client.close() + + +@pytest.mark.asyncio +async def test_async_client_round_trip() -> None: + fake = FakeTransport(200, {"message": "deleted"}) + client = make_async_client(fake) + + resp = await client.api.delete_process(identifier="proc-1") + + assert resp.message == "deleted" + assert fake.capture.headers["authorization"] == "Bearer test-token" + await client.close() + + +@pytest.mark.asyncio +async def test_async_raw_sibling() -> None: + fake = FakeTransport( + 200, raw_content=b"event: done", content_type="text/event-stream" + ) + client = make_async_client(fake) + + response = await client.api.post_process_raw( + request=baseten.client.sandboxapi.ProcessRequest(command="ls"), + accept="text/event-stream", + ) + + assert response.content == b"event: done" + assert fake.capture.headers["accept"] == "text/event-stream" + await client.close() diff --git a/tests/conftest.py b/tests/conftest.py index 133a5e7..6ceb3ef 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -13,14 +13,27 @@ class CapturedRequest: path: str = "" headers: dict[str, str] = field(default_factory=dict) body: str = "" + body_bytes: bytes = b"" class FakeTransport: - """Mock HTTP transport that captures requests and returns fixed responses.""" + """Mock HTTP transport that captures requests and returns fixed responses. - def __init__(self, status_code: int = 200, response: Any = None) -> None: + Set *response* for a JSON body, or *raw_content* (with *content_type*) + for a non-JSON body. + """ + + def __init__( + self, + status_code: int = 200, + response: Any = None, + raw_content: bytes | None = None, + content_type: str = "", + ) -> None: self.status_code = status_code self.response = response + self.raw_content = raw_content + self.content_type = content_type self.capture = CapturedRequest() def _build_response(self, request: httpx.Request) -> httpx.Response: @@ -28,11 +41,16 @@ def _build_response(self, request: httpx.Request) -> httpx.Response: method=request.method, path=str(request.url.raw_path, "ascii"), headers={k: v for k, v in request.headers.items()}, - body=request.content.decode() if request.content else "", + body=request.content.decode(errors="replace") if request.content else "", + body_bytes=request.content, ) body = b"" headers: dict[str, str] = {} - if self.response is not None: + if self.raw_content is not None: + body = self.raw_content + if self.content_type: + headers["content-type"] = self.content_type + elif self.response is not None: body = json.dumps(self.response).encode() headers["content-type"] = "application/json" return httpx.Response( From 9554c446bf697300eea495abe9d19668af46dd35 Mon Sep 17 00:00:00 2001 From: "Marius F. Killinger" Date: Tue, 29 Sep 2026 17:19:55 -0700 Subject: [PATCH 03/15] Resolve $ref'd and path-item parameters into operations Query parameters referenced via components/parameters, and parameters inherited from the path item, were dropped silently. The sandbox management operations take their team selector (and cursor/limit on listings) that way, so they generated without any way to pass a team. The query-XOR-body invariant is now path-scoped: operations under /v1/sandboxes may carry query parameters alongside a request body, the rest of the management and inference APIs may not. Co-Authored-By: Claude Code --- baseten/client/managementapi/__init__.py | 18 +++ baseten/client/managementapi/_client.py | 135 ++++++++++++++----- baseten/client/managementapi/_models.py | 165 +++++++++++++++++++++++ scripts/apigen/__main__.py | 15 ++- scripts/apigen/preprocess.py | 50 ++++++- uv.lock | 2 +- 6 files changed, 338 insertions(+), 47 deletions(-) diff --git a/baseten/client/managementapi/__init__.py b/baseten/client/managementapi/__init__.py index f794eb8..de2aa74 100644 --- a/baseten/client/managementapi/__init__.py +++ b/baseten/client/managementapi/__init__.py @@ -125,6 +125,7 @@ CheckpointFile, Checkpoints, CheckpointSyncStatus, + CleanupImagesParams, CleanupImagesResponse, Component, ComputeCost, @@ -156,6 +157,7 @@ CreateModelDeploymentRequest, CreateModelRequest, CreateRouteRequest, + CreateSandboxParams, CreateSandboxRequest, CreateTokenRequest, CreateTrainingJob, @@ -180,6 +182,9 @@ DeactivateResponse, DedicatedItem, DedicatedUsage, + DeleteImageParams, + DeleteImageTagParams, + DeleteSandboxParams, DeleteVolumeRequest, DeleteVolumeResponse, DeleteVolumeVersionRequest, @@ -254,6 +259,7 @@ GetDeploymentPatchesStateResponse, GetExploreMetadataParams, GetGatewayEventsParams, + GetImageParams, GetLogsResponse, GetLoopsCapabilitiesParams, GetLoopsCapabilitiesResponse, @@ -284,6 +290,7 @@ GetModelsParams, GetRoutesParams, GetRoutesUsageParams, + GetSandboxParams, GetTeamsLoopsRunsParams, GetTeamsLoopsSamplersParams, GetTeamsModelsParams, @@ -428,6 +435,7 @@ PromotionCleanupStrategy, PromotionSettings, Protocol, + PushImageParams, PushImageRequest, PushImageResponse, QueueEvent, @@ -566,6 +574,7 @@ UpdateRequestBackpressureSettings, UpdateRollingDeployConfig, UpdateRouteRequest, + UpdateSandboxParams, UpdateSandboxRequest, UpdateTrainingJobRequest, UpdateTrainingJobResponse, @@ -726,6 +735,7 @@ "CheckpointFile", "CheckpointSyncStatus", "Checkpoints", + "CleanupImagesParams", "CleanupImagesResponse", "Component", "ComputeCost", @@ -756,6 +766,7 @@ "CreateModelDeploymentRequest", "CreateModelRequest", "CreateRouteRequest", + "CreateSandboxParams", "CreateSandboxRequest", "CreateTokenRequest", "CreateTrainingJob", @@ -781,6 +792,9 @@ "DeactivateResponse", "DedicatedItem", "DedicatedUsage", + "DeleteImageParams", + "DeleteImageTagParams", + "DeleteSandboxParams", "DeleteVolumeRequest", "DeleteVolumeResponse", "DeleteVolumeVersionRequest", @@ -855,6 +869,7 @@ "GetDeploymentPatchesStateResponse", "GetExploreMetadataParams", "GetGatewayEventsParams", + "GetImageParams", "GetLogsResponse", "GetLoopsCapabilitiesParams", "GetLoopsCapabilitiesResponse", @@ -885,6 +900,7 @@ "GetModelsParams", "GetRoutesParams", "GetRoutesUsageParams", + "GetSandboxParams", "GetTeamsLoopsRunsParams", "GetTeamsLoopsSamplersParams", "GetTeamsModelsParams", @@ -1029,6 +1045,7 @@ "PromotionCleanupStrategy", "PromotionSettings", "Protocol", + "PushImageParams", "PushImageRequest", "PushImageResponse", "QueueEvent", @@ -1168,6 +1185,7 @@ "UpdateRequestBackpressureSettings", "UpdateRollingDeployConfig", "UpdateRouteRequest", + "UpdateSandboxParams", "UpdateSandboxRequest", "UpdateTrainingJobRequest", "UpdateTrainingJobResponse", diff --git a/baseten/client/managementapi/_client.py b/baseten/client/managementapi/_client.py index 6d8e021..feec815 100644 --- a/baseten/client/managementapi/_client.py +++ b/baseten/client/managementapi/_client.py @@ -22,6 +22,7 @@ ChainEnvironment, Chains, ChainTombstone, + CleanupImagesParams, CleanupImagesResponse, CreateApiKeyForGroupRequest, CreateApiKeyForGroupResponse, @@ -45,6 +46,7 @@ CreateModelDeploymentRequest, CreateModelRequest, CreateRouteRequest, + CreateSandboxParams, CreateSandboxRequest, CreateTokenRequest, CreateTrainingJobRequest, @@ -55,6 +57,9 @@ DeactivateLoopsDeploymentResponse, DeactivateLoopsRunResponse, DeactivateResponse, + DeleteImageParams, + DeleteImageTagParams, + DeleteSandboxParams, DeleteVolumeRequest, DeleteVolumeResponse, DeleteVolumeVersionRequest, @@ -90,6 +95,7 @@ GetDeploymentPatchesStateResponse, GetExploreMetadataParams, GetGatewayEventsParams, + GetImageParams, GetLogsResponse, GetLoopsCapabilitiesParams, GetLoopsCapabilitiesResponse, @@ -120,6 +126,7 @@ GetModelsParams, GetRoutesParams, GetRoutesUsageParams, + GetSandboxParams, GetTeamsLoopsRunsParams, GetTeamsLoopsSamplersParams, GetTeamsModelsParams, @@ -192,6 +199,7 @@ PromoteRequest, PromoteToChainEnvironmentRequest, PromoteToEnvironmentRequest, + PushImageParams, PushImageRequest, PushImageResponse, RecreateTrainingJobResponse, @@ -244,6 +252,7 @@ UpdateModelRequest, UpdateRequestBackpressureSettings, UpdateRouteRequest, + UpdateSandboxParams, UpdateSandboxRequest, UpdateTrainingJobRequest, UpdateTrainingJobResponse, @@ -298,7 +307,9 @@ def __init__(self, http_client: httpx.Client) -> None: """Create a new client. The caller is responsible for closing *http_client*.""" self._http_client = http_client - def cleanup_images(self) -> CleanupImagesResponse: + def cleanup_images( + self, *, params: CleanupImagesParams | None = None + ) -> CleanupImagesResponse: """Clean up unused images""" return self._do_json( CleanupImagesResponse, @@ -307,13 +318,18 @@ def cleanup_images(self) -> CleanupImagesResponse: path_fmt="/v1/sandboxes/cleanup_images", path_args=[], body=None, - query=None, + query=params, success_codes=[200], error_codes=None, ), ) - def create_sandbox(self, *, request: CreateSandboxRequest) -> Sandbox: + def create_sandbox( + self, + *, + params: CreateSandboxParams | None = None, + request: CreateSandboxRequest, + ) -> Sandbox: """Create a sandbox""" return self._do_json( Sandbox, @@ -322,7 +338,7 @@ def create_sandbox(self, *, request: CreateSandboxRequest) -> Sandbox: path_fmt="/v1/sandboxes/instances", path_args=[], body=request, - query=None, + query=params, success_codes=[201], error_codes=None, ), @@ -390,7 +406,9 @@ def delete_gateway_endpoints(self, *, endpoint_id: str) -> EndpointTombstone: ), ) - def delete_image(self, *, image_name: str) -> Image: + def delete_image( + self, *, image_name: str, params: DeleteImageParams | None = None + ) -> Image: """Delete a sandbox image""" return self._do_json( Image, @@ -399,13 +417,19 @@ def delete_image(self, *, image_name: str) -> Image: path_fmt="/v1/sandboxes/images/{}", path_args=[image_name], body=None, - query=None, + query=params, success_codes=[200], error_codes=None, ), ) - def delete_image_tag(self, *, image_name: str, tag_name: str) -> Image: + def delete_image_tag( + self, + *, + image_name: str, + tag_name: str, + params: DeleteImageTagParams | None = None, + ) -> Image: """Delete an image tag""" return self._do_json( Image, @@ -414,7 +438,7 @@ def delete_image_tag(self, *, image_name: str, tag_name: str) -> Image: path_fmt="/v1/sandboxes/images/{}/tags/{}", path_args=[image_name, tag_name], body=None, - query=None, + query=params, success_codes=[200], error_codes=None, ), @@ -535,7 +559,9 @@ def delete_routes(self, *, route_id: str) -> RouteTombstone: ), ) - def delete_sandbox(self, *, sandbox_name: str) -> Sandbox: + def delete_sandbox( + self, *, sandbox_name: str, params: DeleteSandboxParams | None = None + ) -> Sandbox: """Delete a sandbox""" return self._do_json( Sandbox, @@ -544,7 +570,7 @@ def delete_sandbox(self, *, sandbox_name: str) -> Sandbox: path_fmt="/v1/sandboxes/instances/{}", path_args=[sandbox_name], body=None, - query=None, + query=params, success_codes=[202], error_codes=None, ), @@ -1057,7 +1083,9 @@ def get_gateway_groups_group_id(self, *, group_id: str) -> Group: ), ) - def get_image(self, *, image_name: str) -> Image: + def get_image( + self, *, image_name: str, params: GetImageParams | None = None + ) -> Image: """Get a sandbox image""" return self._do_json( Image, @@ -1066,7 +1094,7 @@ def get_image(self, *, image_name: str) -> Image: path_fmt="/v1/sandboxes/images/{}", path_args=[image_name], body=None, - query=None, + query=params, success_codes=[200], error_codes=None, ), @@ -1814,7 +1842,9 @@ def get_routes_usage( ), ) - def get_sandbox(self, *, sandbox_name: str) -> Sandbox: + def get_sandbox( + self, *, sandbox_name: str, params: GetSandboxParams | None = None + ) -> Sandbox: """Get a sandbox""" return self._do_json( Sandbox, @@ -1823,7 +1853,7 @@ def get_sandbox(self, *, sandbox_name: str) -> Sandbox: path_fmt="/v1/sandboxes/instances/{}", path_args=[sandbox_name], body=None, - query=None, + query=params, success_codes=[200], error_codes=None, ), @@ -4022,7 +4052,9 @@ def post_volumes_versions_restore( ), ) - def push_image(self, *, request: PushImageRequest) -> PushImageResponse: + def push_image( + self, *, params: PushImageParams | None = None, request: PushImageRequest + ) -> PushImageResponse: """Push a sandbox image""" return self._do_json( PushImageResponse, @@ -4031,14 +4063,18 @@ def push_image(self, *, request: PushImageRequest) -> PushImageResponse: path_fmt="/v1/sandboxes/images", path_args=[], body=request, - query=None, + query=params, success_codes=[202], error_codes=None, ), ) def update_sandbox( - self, *, sandbox_name: str, request: UpdateSandboxRequest + self, + *, + sandbox_name: str, + params: UpdateSandboxParams | None = None, + request: UpdateSandboxRequest, ) -> Sandbox: """Update a sandbox""" return self._do_json( @@ -4048,7 +4084,7 @@ def update_sandbox( path_fmt="/v1/sandboxes/instances/{}", path_args=[sandbox_name], body=request, - query=None, + query=params, success_codes=[200], error_codes=None, ), @@ -4124,7 +4160,9 @@ def __init__(self, http_client: httpx.AsyncClient) -> None: """Create a new client. The caller is responsible for closing *http_client*.""" self._http_client = http_client - async def cleanup_images(self) -> CleanupImagesResponse: + async def cleanup_images( + self, *, params: CleanupImagesParams | None = None + ) -> CleanupImagesResponse: """Clean up unused images""" return await self._do_json( CleanupImagesResponse, @@ -4133,13 +4171,18 @@ async def cleanup_images(self) -> CleanupImagesResponse: path_fmt="/v1/sandboxes/cleanup_images", path_args=[], body=None, - query=None, + query=params, success_codes=[200], error_codes=None, ), ) - async def create_sandbox(self, *, request: CreateSandboxRequest) -> Sandbox: + async def create_sandbox( + self, + *, + params: CreateSandboxParams | None = None, + request: CreateSandboxRequest, + ) -> Sandbox: """Create a sandbox""" return await self._do_json( Sandbox, @@ -4148,7 +4191,7 @@ async def create_sandbox(self, *, request: CreateSandboxRequest) -> Sandbox: path_fmt="/v1/sandboxes/instances", path_args=[], body=request, - query=None, + query=params, success_codes=[201], error_codes=None, ), @@ -4216,7 +4259,9 @@ async def delete_gateway_endpoints(self, *, endpoint_id: str) -> EndpointTombsto ), ) - async def delete_image(self, *, image_name: str) -> Image: + async def delete_image( + self, *, image_name: str, params: DeleteImageParams | None = None + ) -> Image: """Delete a sandbox image""" return await self._do_json( Image, @@ -4225,13 +4270,19 @@ async def delete_image(self, *, image_name: str) -> Image: path_fmt="/v1/sandboxes/images/{}", path_args=[image_name], body=None, - query=None, + query=params, success_codes=[200], error_codes=None, ), ) - async def delete_image_tag(self, *, image_name: str, tag_name: str) -> Image: + async def delete_image_tag( + self, + *, + image_name: str, + tag_name: str, + params: DeleteImageTagParams | None = None, + ) -> Image: """Delete an image tag""" return await self._do_json( Image, @@ -4240,7 +4291,7 @@ async def delete_image_tag(self, *, image_name: str, tag_name: str) -> Image: path_fmt="/v1/sandboxes/images/{}/tags/{}", path_args=[image_name, tag_name], body=None, - query=None, + query=params, success_codes=[200], error_codes=None, ), @@ -4361,7 +4412,9 @@ async def delete_routes(self, *, route_id: str) -> RouteTombstone: ), ) - async def delete_sandbox(self, *, sandbox_name: str) -> Sandbox: + async def delete_sandbox( + self, *, sandbox_name: str, params: DeleteSandboxParams | None = None + ) -> Sandbox: """Delete a sandbox""" return await self._do_json( Sandbox, @@ -4370,7 +4423,7 @@ async def delete_sandbox(self, *, sandbox_name: str) -> Sandbox: path_fmt="/v1/sandboxes/instances/{}", path_args=[sandbox_name], body=None, - query=None, + query=params, success_codes=[202], error_codes=None, ), @@ -4887,7 +4940,9 @@ async def get_gateway_groups_group_id(self, *, group_id: str) -> Group: ), ) - async def get_image(self, *, image_name: str) -> Image: + async def get_image( + self, *, image_name: str, params: GetImageParams | None = None + ) -> Image: """Get a sandbox image""" return await self._do_json( Image, @@ -4896,7 +4951,7 @@ async def get_image(self, *, image_name: str) -> Image: path_fmt="/v1/sandboxes/images/{}", path_args=[image_name], body=None, - query=None, + query=params, success_codes=[200], error_codes=None, ), @@ -5646,7 +5701,9 @@ async def get_routes_usage( ), ) - async def get_sandbox(self, *, sandbox_name: str) -> Sandbox: + async def get_sandbox( + self, *, sandbox_name: str, params: GetSandboxParams | None = None + ) -> Sandbox: """Get a sandbox""" return await self._do_json( Sandbox, @@ -5655,7 +5712,7 @@ async def get_sandbox(self, *, sandbox_name: str) -> Sandbox: path_fmt="/v1/sandboxes/instances/{}", path_args=[sandbox_name], body=None, - query=None, + query=params, success_codes=[200], error_codes=None, ), @@ -7872,7 +7929,9 @@ async def post_volumes_versions_restore( ), ) - async def push_image(self, *, request: PushImageRequest) -> PushImageResponse: + async def push_image( + self, *, params: PushImageParams | None = None, request: PushImageRequest + ) -> PushImageResponse: """Push a sandbox image""" return await self._do_json( PushImageResponse, @@ -7881,14 +7940,18 @@ async def push_image(self, *, request: PushImageRequest) -> PushImageResponse: path_fmt="/v1/sandboxes/images", path_args=[], body=request, - query=None, + query=params, success_codes=[202], error_codes=None, ), ) async def update_sandbox( - self, *, sandbox_name: str, request: UpdateSandboxRequest + self, + *, + sandbox_name: str, + params: UpdateSandboxParams | None = None, + request: UpdateSandboxRequest, ) -> Sandbox: """Update a sandbox""" return await self._do_json( @@ -7898,7 +7961,7 @@ async def update_sandbox( path_fmt="/v1/sandboxes/instances/{}", path_args=[sandbox_name], body=request, - query=None, + query=params, success_codes=[200], error_codes=None, ), diff --git a/baseten/client/managementapi/_models.py b/baseten/client/managementapi/_models.py index 8d48aee..ebc9236 100644 --- a/baseten/client/managementapi/_models.py +++ b/baseten/client/managementapi/_models.py @@ -908,6 +908,31 @@ class StatusItem(RootModel[str]): class ListSandboxesParams(BaseModel): + team_id: Annotated[ + str | None, + Field( + description="Optional team ID. Must match X-Team-Id when both are supplied. If neither selector is supplied, defaults to the caller's only accessible team. Callers with multiple accessible teams must select a team. Requests without access to any team are forbidden.", + min_length=1, + ), + ] = None + cursor: Annotated[ + str | None, + Field( + description="Opaque cursor from the previous page; omit for the first page.", + examples=[ + "eyJ2IjoxLCJsYXN0X2tleSI6ImJhc2V0ZW4tYXBpLXJldmlldy0wOTE2Iiwic29ydCI6ImRlc2MifQ" + ], + ), + ] = None + limit: Annotated[ + int, + Field( + description="Maximum number of items to return.", + examples=[20], + ge=1, + le=100, + ), + ] = 20 q: Annotated[ str | None, Field( @@ -932,7 +957,72 @@ class ListSandboxesParams(BaseModel): ] = None +class CreateSandboxParams(BaseModel): + team_id: Annotated[ + str | None, + Field( + description="Optional team ID. Must match X-Team-Id when both are supplied. If neither selector is supplied, defaults to the caller's only accessible team. Callers with multiple accessible teams must select a team. Requests without access to any team are forbidden.", + min_length=1, + ), + ] = None + + +class GetSandboxParams(BaseModel): + team_id: Annotated[ + str | None, + Field( + description="Optional team ID. Must match X-Team-Id when both are supplied. If neither selector is supplied, defaults to the caller's only accessible team. Callers with multiple accessible teams must select a team. Requests without access to any team are forbidden.", + min_length=1, + ), + ] = None + + +class UpdateSandboxParams(BaseModel): + team_id: Annotated[ + str | None, + Field( + description="Optional team ID. Must match X-Team-Id when both are supplied. If neither selector is supplied, defaults to the caller's only accessible team. Callers with multiple accessible teams must select a team. Requests without access to any team are forbidden.", + min_length=1, + ), + ] = None + + +class DeleteSandboxParams(BaseModel): + team_id: Annotated[ + str | None, + Field( + description="Optional team ID. Must match X-Team-Id when both are supplied. If neither selector is supplied, defaults to the caller's only accessible team. Callers with multiple accessible teams must select a team. Requests without access to any team are forbidden.", + min_length=1, + ), + ] = None + + class ListImagesParams(BaseModel): + team_id: Annotated[ + str | None, + Field( + description="Optional team ID. Must match X-Team-Id when both are supplied. If neither selector is supplied, defaults to the caller's only accessible team. Callers with multiple accessible teams must select a team. Requests without access to any team are forbidden.", + min_length=1, + ), + ] = None + cursor: Annotated[ + str | None, + Field( + description="Opaque cursor from the previous page; omit for the first page.", + examples=[ + "eyJ2IjoxLCJsYXN0X2tleSI6ImJhc2V0ZW4tYXBpLXJldmlldy0wOTE2Iiwic29ydCI6ImRlc2MifQ" + ], + ), + ] = None + limit: Annotated[ + int, + Field( + description="Maximum number of items to return.", + examples=[20], + ge=1, + le=100, + ), + ] = 20 sort: Annotated[ str, Field( @@ -947,7 +1037,72 @@ class ListImagesParams(BaseModel): ] = None +class PushImageParams(BaseModel): + team_id: Annotated[ + str | None, + Field( + description="Optional team ID. Must match X-Team-Id when both are supplied. If neither selector is supplied, defaults to the caller's only accessible team. Callers with multiple accessible teams must select a team. Requests without access to any team are forbidden.", + min_length=1, + ), + ] = None + + +class CleanupImagesParams(BaseModel): + team_id: Annotated[ + str | None, + Field( + description="Optional team ID. Must match X-Team-Id when both are supplied. If neither selector is supplied, defaults to the caller's only accessible team. Callers with multiple accessible teams must select a team. Requests without access to any team are forbidden.", + min_length=1, + ), + ] = None + + +class GetImageParams(BaseModel): + team_id: Annotated[ + str | None, + Field( + description="Optional team ID. Must match X-Team-Id when both are supplied. If neither selector is supplied, defaults to the caller's only accessible team. Callers with multiple accessible teams must select a team. Requests without access to any team are forbidden.", + min_length=1, + ), + ] = None + + +class DeleteImageParams(BaseModel): + team_id: Annotated[ + str | None, + Field( + description="Optional team ID. Must match X-Team-Id when both are supplied. If neither selector is supplied, defaults to the caller's only accessible team. Callers with multiple accessible teams must select a team. Requests without access to any team are forbidden.", + min_length=1, + ), + ] = None + + class ListImageTagsParams(BaseModel): + team_id: Annotated[ + str | None, + Field( + description="Optional team ID. Must match X-Team-Id when both are supplied. If neither selector is supplied, defaults to the caller's only accessible team. Callers with multiple accessible teams must select a team. Requests without access to any team are forbidden.", + min_length=1, + ), + ] = None + cursor: Annotated[ + str | None, + Field( + description="Opaque cursor from the previous page; omit for the first page.", + examples=[ + "eyJ2IjoxLCJsYXN0X2tleSI6ImJhc2V0ZW4tYXBpLXJldmlldy0wOTE2Iiwic29ydCI6ImRlc2MifQ" + ], + ), + ] = None + limit: Annotated[ + int, + Field( + description="Maximum number of items to return.", + examples=[20], + ge=1, + le=100, + ), + ] = 20 sort: Annotated[ str, Field( @@ -968,6 +1123,16 @@ class ListImageTagsParams(BaseModel): ] = None +class DeleteImageTagParams(BaseModel): + team_id: Annotated[ + str | None, + Field( + description="Optional team ID. Must match X-Team-Id when both are supplied. If neither selector is supplied, defaults to the caller's only accessible team. Callers with multiple accessible teams must select a team. Requests without access to any team are forbidden.", + min_length=1, + ), + ] = None + + class PaginationResponse(BaseModel): has_more: Annotated[ bool, diff --git a/scripts/apigen/__main__.py b/scripts/apigen/__main__.py index 764facc..9f207d3 100644 --- a/scripts/apigen/__main__.py +++ b/scripts/apigen/__main__.py @@ -11,6 +11,7 @@ import subprocess import sys import urllib.request +from collections.abc import Callable from datetime import datetime from pathlib import Path @@ -52,14 +53,20 @@ def main() -> None: download_spec(SANDBOX_SPEC_URL, SPECS_DIR / "sandbox.yml") generate_api( - SPECS_DIR / "management.json", CLIENT_DIR / "managementapi", "Management" + SPECS_DIR / "management.json", + CLIENT_DIR / "managementapi", + "Management", + # Sandbox management operations take a team selector as a query + # parameter alongside the request body; the rest of the management + # API keeps query parameters and request bodies separated. + query_and_body_allowed=lambda path: path.startswith("/v1/sandboxes"), ) generate_api(SPECS_DIR / "inference.json", CLIENT_DIR / "inferenceapi", "Inference") generate_api( SPECS_DIR / "sandbox.yml", CLIENT_DIR / "sandboxapi", "Sandbox", - allow_query_and_body=True, + query_and_body_allowed=lambda path: True, ) generate_modelconfig(SPECS_DIR / "config.schema.json", CLIENT_DIR / "modelconfig") @@ -85,13 +92,13 @@ def generate_api( out_dir: Path, display_name: str, *, - allow_query_and_body: bool = False, + query_and_body_allowed: Callable[[str], bool] | None = None, ) -> None: print(f"Generating {out_dir.name} from {spec_file}") out_dir.mkdir(parents=True, exist_ok=True) preprocessed = preprocess_spec( - _read_spec(spec_file), allow_query_and_body=allow_query_and_body + _read_spec(spec_file), query_and_body_allowed=query_and_body_allowed ) models_file = out_dir / "_models.py" diff --git a/scripts/apigen/preprocess.py b/scripts/apigen/preprocess.py index 6525b90..1a98675 100644 --- a/scripts/apigen/preprocess.py +++ b/scripts/apigen/preprocess.py @@ -3,6 +3,7 @@ import copy import json import re +from collections.abc import Callable from scripts.apigen.clientgen import ( query_params_model_name, @@ -51,9 +52,15 @@ def _rename_defs_refs(node: object, renames: dict[str, str]) -> None: _rename_defs_refs(child, renames) -def preprocess_spec(data: bytes, *, allow_query_and_body: bool = False) -> bytes: +def preprocess_spec( + data: bytes, + *, + query_and_body_allowed: Callable[[str], bool] | None = None, +) -> bytes: doc = json.loads(data) + _flatten_parameters(doc) + # datamodel-code-generator has --openapi-scopes for schemas and # requestbodies, but not for responses. Hoist inline schemas from # both responses and requestBodies into components/schemas so they @@ -73,7 +80,7 @@ def preprocess_spec(data: bytes, *, allow_query_and_body: bool = False) -> bytes # generates query-parameter models under the paths scope, which drags # in unwanted per-operation wrappers). Injected before the V1 rename # below so their $refs to enums are rewritten with everything else. - _inject_query_params_schemas(doc, allow_query_and_body=allow_query_and_body) + _inject_query_params_schemas(doc, query_and_body_allowed=query_and_body_allowed) # Hoist inline 2xx application/json response schemas into # components/schemas so datamodel-code-generator emits a named model the @@ -101,6 +108,35 @@ def preprocess_spec(data: bytes, *, allow_query_and_body: bool = False) -> bytes return json.dumps(doc, indent=2).encode() +def _flatten_parameters(doc: dict) -> None: + # Operations inherit path-item parameters, and either level may reference + # components/parameters. Inline both so every downstream step (query + # schema injection, client generation) sees concrete parameter objects. + component_params = doc.get("components", {}).get("parameters", {}) + + def resolve(param: dict) -> dict: + ref = param.get("$ref") + if ref is None: + return param + resolved = component_params.get(ref.rsplit("/", 1)[-1]) + if resolved is None: + raise ValueError(f"unresolved parameter reference {ref}") + return copy.deepcopy(resolved) + + for path_item in doc.get("paths", {}).values(): + if not isinstance(path_item, dict): + continue + item_params = [ + resolve(p) for p in path_item.pop("parameters", []) if isinstance(p, dict) + ] + for http_method, op in path_item.items(): + if http_method == "parameters" or not isinstance(op, dict): + continue + op["parameters"] = copy.deepcopy(item_params) + [ + resolve(p) for p in op.get("parameters", []) if isinstance(p, dict) + ] + + def _hoist_component_schemas(doc: dict) -> None: # Hoist inline JSON schemas from components/responses and # components/requestBodies into components/schemas. Entries that are @@ -181,7 +217,9 @@ def _collect_schema_refs(node: object, out: set[str]) -> None: _collect_schema_refs(child, out) -def _inject_query_params_schemas(doc: dict, *, allow_query_and_body: bool) -> None: +def _inject_query_params_schemas( + doc: dict, *, query_and_body_allowed: Callable[[str], bool] | None +) -> None: # Build an object schema whose properties are the operation's query # parameters, named to match its client method (e.g. get_users -> # GetUsersParams). Each parameter's own schema (enum $refs, arrays, @@ -201,9 +239,9 @@ def _inject_query_params_schemas(doc: dict, *, allow_query_and_body: bool) -> No ] if not query_params: continue - if "requestBody" in op and not allow_query_and_body: - # Management and inference enforce query-XOR-body as a - # structural invariant; only the sandbox API allows both. + if "requestBody" in op and not ( + query_and_body_allowed and query_and_body_allowed(path) + ): raise ValueError( f"{http_method.upper()} {path} has both a request body and " "query parameters, which this API does not allow" diff --git a/uv.lock b/uv.lock index 0d9b198..9dbab2f 100644 --- a/uv.lock +++ b/uv.lock @@ -84,7 +84,7 @@ wheels = [ [[package]] name = "baseten" -version = "0.11.0" +version = "0.12.0" source = { editable = "." } dependencies = [ { name = "httpx" }, From f11199d54b5b5be0f013da7622ca051550cf0cc9 Mon Sep 17 00:00:00 2001 From: "Marius F. Killinger" Date: Tue, 29 Sep 2026 17:37:51 -0700 Subject: [PATCH 04/15] Fix review findings: alias handling, streaming raw responses, status dispatch - Generated classes with aliased fields get populate_by_name=True, and request models serialize by_alias, so a field renamed for Python (async_ for "async") is passable by its Python name and reaches the API under its own. - Raw methods stream: build_request + send(stream=True) via a new _do_raw; error paths read the body first, and the docstring says the caller closes the response. - An operation with several success codes and at least one JSON schema always dispatches by status; bodyless codes (e.g. 204 beside a JSON 200) yield None. Co-Authored-By: Claude Code --- baseten/client/inferenceapi/_client.py | 114 ++++++++++++++++------ baseten/client/managementapi/_client.py | 30 ++++-- baseten/client/sandboxapi/_client.py | 122 ++++++++++++++++++------ baseten/client/sandboxapi/_models.py | 2 + scripts/apigen/clientgen.py | 62 +++++++++--- scripts/apigen/postprocess.py | 69 ++++++++++++++ tests/client/test_sandbox.py | 26 +++++ 7 files changed, 344 insertions(+), 81 deletions(-) diff --git a/baseten/client/inferenceapi/_client.py b/baseten/client/inferenceapi/_client.py index 8b50a43..1ed8bbe 100644 --- a/baseten/client/inferenceapi/_client.py +++ b/baseten/client/inferenceapi/_client.py @@ -439,8 +439,8 @@ def predict_raw( request: PredictInput, accept: Literal["application/json", "application/octet-stream"], ) -> httpx.Response: - """Call the model deployment associated with a specified environment.. Returns the response unread, in the requested content type.""" - return self._do( + """Call the model deployment associated with a specified environment.. Returns the response unread, in the requested content type. The caller must close the response.""" + return self._do_raw( _ApiRequest( method="POST", path_fmt="/environments/{}/predict", @@ -491,8 +491,8 @@ def predict_deployment_raw( request: PredictInput, accept: Literal["application/json", "application/octet-stream"], ) -> httpx.Response: - """Call a specific deployment of a model by deployment ID.. Returns the response unread, in the requested content type.""" - return self._do( + """Call a specific deployment of a model by deployment ID.. Returns the response unread, in the requested content type. The caller must close the response.""" + return self._do_raw( _ApiRequest( method="POST", path_fmt="/deployment/{}/predict", @@ -540,8 +540,8 @@ def predict_development_raw( request: PredictInput, accept: Literal["application/json", "application/octet-stream"], ) -> httpx.Response: - """Call the development deployment of a model.. Returns the response unread, in the requested content type.""" - return self._do( + """Call the development deployment of a model.. Returns the response unread, in the requested content type. The caller must close the response.""" + return self._do_raw( _ApiRequest( method="POST", path_fmt="/development/predict", @@ -589,8 +589,8 @@ def predict_production_raw( request: PredictInput, accept: Literal["application/json", "application/octet-stream"], ) -> httpx.Response: - """Call the production environment of a model.. Returns the response unread, in the requested content type.""" - return self._do( + """Call the production environment of a model.. Returns the response unread, in the requested content type. The caller must close the response.""" + return self._do_raw( _ApiRequest( method="POST", path_fmt="/production/predict", @@ -638,8 +638,8 @@ def predict_regional_raw( request: PredictInput, accept: Literal["application/json", "application/octet-stream"], ) -> httpx.Response: - """Call a regional environment of a model.. Returns the response unread, in the requested content type.""" - return self._do( + """Call a regional environment of a model.. Returns the response unread, in the requested content type. The caller must close the response.""" + return self._do_raw( _ApiRequest( method="POST", path_fmt="/predict", @@ -841,7 +841,7 @@ def wake_regional(self) -> None: ) ) - def _do(self, request: _ApiRequest) -> httpx.Response: + def _build_request(self, request: _ApiRequest) -> httpx.Request: path = request.path_fmt.format( *[urllib.parse.quote(a, safe="") for a in request.path_args] ) @@ -857,7 +857,11 @@ def _do(self, request: _ApiRequest) -> httpx.Response: # Only fields the caller set are sent, so unset fields fall # back to the server default rather than being reset here. # An explicit None is kept, since null can mean "clear". - json_body = request.body.model_dump(mode="json", exclude_unset=True) + # by_alias: a field renamed for Python (e.g. async_ for + # "async") must serialize under its API name. + json_body = request.body.model_dump( + mode="json", exclude_unset=True, by_alias=True + ) else: json_body = request.body elif request.body_content_type == "multipart/form-data": @@ -872,11 +876,11 @@ def _do(self, request: _ApiRequest) -> httpx.Response: # As above, plus dropping None: a null query parameter is # meaningless and would otherwise serialize as an empty string. params = request.query.model_dump( - mode="json", exclude_unset=True, exclude_none=True + mode="json", exclude_unset=True, exclude_none=True, by_alias=True ) else: params = request.query - response = self._http_client.request( + return self._http_client.build_request( request.method, path, json=json_body, @@ -885,7 +889,31 @@ def _do(self, request: _ApiRequest) -> httpx.Response: params=params, headers=headers, ) + + def _do(self, request: _ApiRequest) -> httpx.Response: + response = self._http_client.send(self._build_request(request)) + if response.status_code not in request.success_codes: + if request.error_codes and response.status_code in request.error_codes: + error_name = request.error_codes[response.status_code] + if error_name in _ERROR_TYPES: + model_cls, exc_cls, field_name = _ERROR_TYPES[error_name] + # A body that does not match the declared error schema + # falls through to the generic ResponseError below. + model = None + with contextlib.suppress(ValidationError): + model = model_cls.model_validate_json(response.content) + if model is not None: + raise exc_cls( + status_code=response.status_code, # ty: ignore[unknown-argument] + **{field_name: model}, + ) + raise ResponseError(status_code=response.status_code, body=response.text) + return response + + def _do_raw(self, request: _ApiRequest) -> httpx.Response: + response = self._http_client.send(self._build_request(request), stream=True) if response.status_code not in request.success_codes: + response.read() if request.error_codes and response.status_code in request.error_codes: error_name = request.error_codes[response.status_code] if error_name in _ERROR_TYPES: @@ -1295,8 +1323,8 @@ async def predict_raw( request: PredictInput, accept: Literal["application/json", "application/octet-stream"], ) -> httpx.Response: - """Call the model deployment associated with a specified environment.. Returns the response unread, in the requested content type.""" - return await self._do( + """Call the model deployment associated with a specified environment.. Returns the response unread, in the requested content type. The caller must close the response.""" + return await self._do_raw( _ApiRequest( method="POST", path_fmt="/environments/{}/predict", @@ -1347,8 +1375,8 @@ async def predict_deployment_raw( request: PredictInput, accept: Literal["application/json", "application/octet-stream"], ) -> httpx.Response: - """Call a specific deployment of a model by deployment ID.. Returns the response unread, in the requested content type.""" - return await self._do( + """Call a specific deployment of a model by deployment ID.. Returns the response unread, in the requested content type. The caller must close the response.""" + return await self._do_raw( _ApiRequest( method="POST", path_fmt="/deployment/{}/predict", @@ -1396,8 +1424,8 @@ async def predict_development_raw( request: PredictInput, accept: Literal["application/json", "application/octet-stream"], ) -> httpx.Response: - """Call the development deployment of a model.. Returns the response unread, in the requested content type.""" - return await self._do( + """Call the development deployment of a model.. Returns the response unread, in the requested content type. The caller must close the response.""" + return await self._do_raw( _ApiRequest( method="POST", path_fmt="/development/predict", @@ -1445,8 +1473,8 @@ async def predict_production_raw( request: PredictInput, accept: Literal["application/json", "application/octet-stream"], ) -> httpx.Response: - """Call the production environment of a model.. Returns the response unread, in the requested content type.""" - return await self._do( + """Call the production environment of a model.. Returns the response unread, in the requested content type. The caller must close the response.""" + return await self._do_raw( _ApiRequest( method="POST", path_fmt="/production/predict", @@ -1494,8 +1522,8 @@ async def predict_regional_raw( request: PredictInput, accept: Literal["application/json", "application/octet-stream"], ) -> httpx.Response: - """Call a regional environment of a model.. Returns the response unread, in the requested content type.""" - return await self._do( + """Call a regional environment of a model.. Returns the response unread, in the requested content type. The caller must close the response.""" + return await self._do_raw( _ApiRequest( method="POST", path_fmt="/predict", @@ -1703,7 +1731,7 @@ async def wake_regional(self) -> None: ) ) - async def _do(self, request: _ApiRequest) -> httpx.Response: + def _build_request(self, request: _ApiRequest) -> httpx.Request: path = request.path_fmt.format( *[urllib.parse.quote(a, safe="") for a in request.path_args] ) @@ -1719,7 +1747,11 @@ async def _do(self, request: _ApiRequest) -> httpx.Response: # Only fields the caller set are sent, so unset fields fall # back to the server default rather than being reset here. # An explicit None is kept, since null can mean "clear". - json_body = request.body.model_dump(mode="json", exclude_unset=True) + # by_alias: a field renamed for Python (e.g. async_ for + # "async") must serialize under its API name. + json_body = request.body.model_dump( + mode="json", exclude_unset=True, by_alias=True + ) else: json_body = request.body elif request.body_content_type == "multipart/form-data": @@ -1734,11 +1766,11 @@ async def _do(self, request: _ApiRequest) -> httpx.Response: # As above, plus dropping None: a null query parameter is # meaningless and would otherwise serialize as an empty string. params = request.query.model_dump( - mode="json", exclude_unset=True, exclude_none=True + mode="json", exclude_unset=True, exclude_none=True, by_alias=True ) else: params = request.query - response = await self._http_client.request( + return self._http_client.build_request( request.method, path, json=json_body, @@ -1747,7 +1779,33 @@ async def _do(self, request: _ApiRequest) -> httpx.Response: params=params, headers=headers, ) + + async def _do(self, request: _ApiRequest) -> httpx.Response: + response = await self._http_client.send(self._build_request(request)) + if response.status_code not in request.success_codes: + if request.error_codes and response.status_code in request.error_codes: + error_name = request.error_codes[response.status_code] + if error_name in _ERROR_TYPES: + model_cls, exc_cls, field_name = _ERROR_TYPES[error_name] + # A body that does not match the declared error schema + # falls through to the generic ResponseError below. + model = None + with contextlib.suppress(ValidationError): + model = model_cls.model_validate_json(response.content) + if model is not None: + raise exc_cls( + status_code=response.status_code, # ty: ignore[unknown-argument] + **{field_name: model}, + ) + raise ResponseError(status_code=response.status_code, body=response.text) + return response + + async def _do_raw(self, request: _ApiRequest) -> httpx.Response: + response = await self._http_client.send( + self._build_request(request), stream=True + ) if response.status_code not in request.success_codes: + await response.aread() if request.error_codes and response.status_code in request.error_codes: error_name = request.error_codes[response.status_code] if error_name in _ERROR_TYPES: diff --git a/baseten/client/managementapi/_client.py b/baseten/client/managementapi/_client.py index feec815..89399e1 100644 --- a/baseten/client/managementapi/_client.py +++ b/baseten/client/managementapi/_client.py @@ -4090,7 +4090,7 @@ def update_sandbox( ), ) - def _do(self, request: _ApiRequest) -> httpx.Response: + def _build_request(self, request: _ApiRequest) -> httpx.Request: path = request.path_fmt.format( *[urllib.parse.quote(a, safe="") for a in request.path_args] ) @@ -4106,7 +4106,11 @@ def _do(self, request: _ApiRequest) -> httpx.Response: # Only fields the caller set are sent, so unset fields fall # back to the server default rather than being reset here. # An explicit None is kept, since null can mean "clear". - json_body = request.body.model_dump(mode="json", exclude_unset=True) + # by_alias: a field renamed for Python (e.g. async_ for + # "async") must serialize under its API name. + json_body = request.body.model_dump( + mode="json", exclude_unset=True, by_alias=True + ) else: json_body = request.body elif request.body_content_type == "multipart/form-data": @@ -4121,11 +4125,11 @@ def _do(self, request: _ApiRequest) -> httpx.Response: # As above, plus dropping None: a null query parameter is # meaningless and would otherwise serialize as an empty string. params = request.query.model_dump( - mode="json", exclude_unset=True, exclude_none=True + mode="json", exclude_unset=True, exclude_none=True, by_alias=True ) else: params = request.query - response = self._http_client.request( + return self._http_client.build_request( request.method, path, json=json_body, @@ -4134,6 +4138,9 @@ def _do(self, request: _ApiRequest) -> httpx.Response: params=params, headers=headers, ) + + def _do(self, request: _ApiRequest) -> httpx.Response: + response = self._http_client.send(self._build_request(request)) if response.status_code not in request.success_codes: raise ResponseError(status_code=response.status_code, body=response.text) return response @@ -7967,7 +7974,7 @@ async def update_sandbox( ), ) - async def _do(self, request: _ApiRequest) -> httpx.Response: + def _build_request(self, request: _ApiRequest) -> httpx.Request: path = request.path_fmt.format( *[urllib.parse.quote(a, safe="") for a in request.path_args] ) @@ -7983,7 +7990,11 @@ async def _do(self, request: _ApiRequest) -> httpx.Response: # Only fields the caller set are sent, so unset fields fall # back to the server default rather than being reset here. # An explicit None is kept, since null can mean "clear". - json_body = request.body.model_dump(mode="json", exclude_unset=True) + # by_alias: a field renamed for Python (e.g. async_ for + # "async") must serialize under its API name. + json_body = request.body.model_dump( + mode="json", exclude_unset=True, by_alias=True + ) else: json_body = request.body elif request.body_content_type == "multipart/form-data": @@ -7998,11 +8009,11 @@ async def _do(self, request: _ApiRequest) -> httpx.Response: # As above, plus dropping None: a null query parameter is # meaningless and would otherwise serialize as an empty string. params = request.query.model_dump( - mode="json", exclude_unset=True, exclude_none=True + mode="json", exclude_unset=True, exclude_none=True, by_alias=True ) else: params = request.query - response = await self._http_client.request( + return self._http_client.build_request( request.method, path, json=json_body, @@ -8011,6 +8022,9 @@ async def _do(self, request: _ApiRequest) -> httpx.Response: params=params, headers=headers, ) + + async def _do(self, request: _ApiRequest) -> httpx.Response: + response = await self._http_client.send(self._build_request(request)) if response.status_code not in request.success_codes: raise ResponseError(status_code=response.status_code, body=response.text) return response diff --git a/baseten/client/sandboxapi/_client.py b/baseten/client/sandboxapi/_client.py index 62aba21..bb71c22 100644 --- a/baseten/client/sandboxapi/_client.py +++ b/baseten/client/sandboxapi/_client.py @@ -6,7 +6,7 @@ import urllib.parse from collections.abc import Mapping from dataclasses import dataclass -from typing import IO, Any, Literal, TypeVar +from typing import IO, Any, Literal, TypeVar, cast import httpx from pydantic import BaseModel, ValidationError @@ -357,8 +357,8 @@ def get_filesystem_raw( params: GetFilesystemParams | None = None, accept: Literal["application/json", "application/octet-stream"], ) -> httpx.Response: - """Get file or directory information. Returns the response unread, in the requested content type.""" - return self._do( + """Get file or directory information. Returns the response unread, in the requested content type. The caller must close the response.""" + return self._do_raw( _ApiRequest( method="GET", path_fmt="/filesystem/{}", @@ -577,8 +577,8 @@ def get_process_logs(self, *, identifier: str) -> ProcessLogs: ) def get_process_logs_stream(self, *, identifier: str) -> httpx.Response: - """Stream process logs in real time. Returns the response unread, in the requested content type.""" - return self._do( + """Stream process logs in real time. Returns the response unread, in the requested content type. The caller must close the response.""" + return self._do_raw( _ApiRequest( method="GET", path_fmt="/process/{}/logs/stream", @@ -594,8 +594,8 @@ def get_process_logs_stream(self, *, identifier: str) -> httpx.Response: def get_watch_filesystem( self, *, path: str, params: GetWatchFilesystemParams | None = None ) -> httpx.Response: - """Stream file modification events in a directory. Returns the response unread, in the requested content type.""" - return self._do( + """Stream file modification events in a directory. Returns the response unread, in the requested content type. The caller must close the response.""" + return self._do_raw( _ApiRequest( method="GET", path_fmt="/watch/filesystem/{}", @@ -763,8 +763,8 @@ def post_process_raw( request: ProcessRequest, accept: Literal["application/json", "text/event-stream"], ) -> httpx.Response: - """Execute a command. Returns the response unread, in the requested content type.""" - return self._do( + """Execute a command. Returns the response unread, in the requested content type. The caller must close the response.""" + return self._do_raw( _ApiRequest( method="POST", path_fmt="/process", @@ -924,7 +924,7 @@ def put_network_tunnel_config( ), ) - def _do(self, request: _ApiRequest) -> httpx.Response: + def _build_request(self, request: _ApiRequest) -> httpx.Request: path = request.path_fmt.format( *[urllib.parse.quote(a, safe="") for a in request.path_args] ) @@ -940,7 +940,11 @@ def _do(self, request: _ApiRequest) -> httpx.Response: # Only fields the caller set are sent, so unset fields fall # back to the server default rather than being reset here. # An explicit None is kept, since null can mean "clear". - json_body = request.body.model_dump(mode="json", exclude_unset=True) + # by_alias: a field renamed for Python (e.g. async_ for + # "async") must serialize under its API name. + json_body = request.body.model_dump( + mode="json", exclude_unset=True, by_alias=True + ) else: json_body = request.body elif request.body_content_type == "multipart/form-data": @@ -955,11 +959,11 @@ def _do(self, request: _ApiRequest) -> httpx.Response: # As above, plus dropping None: a null query parameter is # meaningless and would otherwise serialize as an empty string. params = request.query.model_dump( - mode="json", exclude_unset=True, exclude_none=True + mode="json", exclude_unset=True, exclude_none=True, by_alias=True ) else: params = request.query - response = self._http_client.request( + return self._http_client.build_request( request.method, path, json=json_body, @@ -968,7 +972,31 @@ def _do(self, request: _ApiRequest) -> httpx.Response: params=params, headers=headers, ) + + def _do(self, request: _ApiRequest) -> httpx.Response: + response = self._http_client.send(self._build_request(request)) + if response.status_code not in request.success_codes: + if request.error_codes and response.status_code in request.error_codes: + error_name = request.error_codes[response.status_code] + if error_name in _ERROR_TYPES: + model_cls, exc_cls, field_name = _ERROR_TYPES[error_name] + # A body that does not match the declared error schema + # falls through to the generic ResponseError below. + model = None + with contextlib.suppress(ValidationError): + model = model_cls.model_validate_json(response.content) + if model is not None: + raise exc_cls( + status_code=response.status_code, # ty: ignore[unknown-argument] + **{field_name: model}, + ) + raise ResponseError(status_code=response.status_code, body=response.text) + return response + + def _do_raw(self, request: _ApiRequest) -> httpx.Response: + response = self._http_client.send(self._build_request(request), stream=True) if response.status_code not in request.success_codes: + response.read() if request.error_codes and response.status_code in request.error_codes: error_name = request.error_codes[response.status_code] if error_name in _ERROR_TYPES: @@ -1001,9 +1029,10 @@ def _do_json_with_status( response = self._do(request) response_type = response_types.get(response.status_code) if response_type is None: - raise ValueError( - f"no JSON response schema declared for HTTP {response.status_code}" - ) + # A bodyless success code, such as 204 alongside a JSON 200. The + # call site's return type includes None only when one is declared, + # so this cast is unreachable otherwise. + return cast(_T, None) content_type = response.headers.get("content-type", "") if not content_type.startswith("application/json"): raise ValueError( @@ -1270,8 +1299,8 @@ async def get_filesystem_raw( params: GetFilesystemParams | None = None, accept: Literal["application/json", "application/octet-stream"], ) -> httpx.Response: - """Get file or directory information. Returns the response unread, in the requested content type.""" - return await self._do( + """Get file or directory information. Returns the response unread, in the requested content type. The caller must close the response.""" + return await self._do_raw( _ApiRequest( method="GET", path_fmt="/filesystem/{}", @@ -1492,8 +1521,8 @@ async def get_process_logs(self, *, identifier: str) -> ProcessLogs: ) async def get_process_logs_stream(self, *, identifier: str) -> httpx.Response: - """Stream process logs in real time. Returns the response unread, in the requested content type.""" - return await self._do( + """Stream process logs in real time. Returns the response unread, in the requested content type. The caller must close the response.""" + return await self._do_raw( _ApiRequest( method="GET", path_fmt="/process/{}/logs/stream", @@ -1509,8 +1538,8 @@ async def get_process_logs_stream(self, *, identifier: str) -> httpx.Response: async def get_watch_filesystem( self, *, path: str, params: GetWatchFilesystemParams | None = None ) -> httpx.Response: - """Stream file modification events in a directory. Returns the response unread, in the requested content type.""" - return await self._do( + """Stream file modification events in a directory. Returns the response unread, in the requested content type. The caller must close the response.""" + return await self._do_raw( _ApiRequest( method="GET", path_fmt="/watch/filesystem/{}", @@ -1680,8 +1709,8 @@ async def post_process_raw( request: ProcessRequest, accept: Literal["application/json", "text/event-stream"], ) -> httpx.Response: - """Execute a command. Returns the response unread, in the requested content type.""" - return await self._do( + """Execute a command. Returns the response unread, in the requested content type. The caller must close the response.""" + return await self._do_raw( _ApiRequest( method="POST", path_fmt="/process", @@ -1843,7 +1872,7 @@ async def put_network_tunnel_config( ), ) - async def _do(self, request: _ApiRequest) -> httpx.Response: + def _build_request(self, request: _ApiRequest) -> httpx.Request: path = request.path_fmt.format( *[urllib.parse.quote(a, safe="") for a in request.path_args] ) @@ -1859,7 +1888,11 @@ async def _do(self, request: _ApiRequest) -> httpx.Response: # Only fields the caller set are sent, so unset fields fall # back to the server default rather than being reset here. # An explicit None is kept, since null can mean "clear". - json_body = request.body.model_dump(mode="json", exclude_unset=True) + # by_alias: a field renamed for Python (e.g. async_ for + # "async") must serialize under its API name. + json_body = request.body.model_dump( + mode="json", exclude_unset=True, by_alias=True + ) else: json_body = request.body elif request.body_content_type == "multipart/form-data": @@ -1874,11 +1907,11 @@ async def _do(self, request: _ApiRequest) -> httpx.Response: # As above, plus dropping None: a null query parameter is # meaningless and would otherwise serialize as an empty string. params = request.query.model_dump( - mode="json", exclude_unset=True, exclude_none=True + mode="json", exclude_unset=True, exclude_none=True, by_alias=True ) else: params = request.query - response = await self._http_client.request( + return self._http_client.build_request( request.method, path, json=json_body, @@ -1887,6 +1920,9 @@ async def _do(self, request: _ApiRequest) -> httpx.Response: params=params, headers=headers, ) + + async def _do(self, request: _ApiRequest) -> httpx.Response: + response = await self._http_client.send(self._build_request(request)) if response.status_code not in request.success_codes: if request.error_codes and response.status_code in request.error_codes: error_name = request.error_codes[response.status_code] @@ -1905,6 +1941,29 @@ async def _do(self, request: _ApiRequest) -> httpx.Response: raise ResponseError(status_code=response.status_code, body=response.text) return response + async def _do_raw(self, request: _ApiRequest) -> httpx.Response: + response = await self._http_client.send( + self._build_request(request), stream=True + ) + if response.status_code not in request.success_codes: + await response.aread() + if request.error_codes and response.status_code in request.error_codes: + error_name = request.error_codes[response.status_code] + if error_name in _ERROR_TYPES: + model_cls, exc_cls, field_name = _ERROR_TYPES[error_name] + # A body that does not match the declared error schema + # falls through to the generic ResponseError below. + model = None + with contextlib.suppress(ValidationError): + model = model_cls.model_validate_json(response.content) + if model is not None: + raise exc_cls( + status_code=response.status_code, # ty: ignore[unknown-argument] + **{field_name: model}, + ) + raise ResponseError(status_code=response.status_code, body=response.text) + return response + async def _do_json(self, response_type: type[_T], request: _ApiRequest) -> _T: response = await self._do(request) content_type = response.headers.get("content-type", "") @@ -1920,9 +1979,10 @@ async def _do_json_with_status( response = await self._do(request) response_type = response_types.get(response.status_code) if response_type is None: - raise ValueError( - f"no JSON response schema declared for HTTP {response.status_code}" - ) + # A bodyless success code, such as 204 alongside a JSON 200. The + # call site's return type includes None only when one is declared, + # so this cast is unreachable otherwise. + return cast(_T, None) content_type = response.headers.get("content-type", "") if not content_type.startswith("application/json"): raise ValueError( diff --git a/baseten/client/sandboxapi/_models.py b/baseten/client/sandboxapi/_models.py index f81b964..8edfe99 100644 --- a/baseten/client/sandboxapi/_models.py +++ b/baseten/client/sandboxapi/_models.py @@ -619,6 +619,8 @@ class DriveListResponse(BaseModel): class ExportOptions(BaseModel): + model_config = ConfigDict(populate_by_name=True) + async_: Annotated[ bool | None, Field( diff --git a/scripts/apigen/clientgen.py b/scripts/apigen/clientgen.py index ba78bdc..99ce476 100644 --- a/scripts/apigen/clientgen.py +++ b/scripts/apigen/clientgen.py @@ -258,7 +258,10 @@ def _path_fmt(path: str) -> str: def _render_client(ops: list[_Operation]) -> str: has_typed_resp = any(op.json_responses for op in ops) - has_status_resp = any(len(op.json_responses) > 1 for op in ops) + # Status dispatch covers an operation with more than one success code and + # at least one JSON schema among them, since the others may be bodyless. + has_status_resp = any(op.json_responses and len(op.success_codes) > 1 for op in ops) + has_raw = any(op.raw_accepts for op in ops) has_no_resp = any(not op.json_responses and not op.raw_accepts for op in ops) error_refs = sorted({ref for op in ops for ref in (op.error_codes or {}).values()}) @@ -283,7 +286,7 @@ def _render_client(ops: list[_Operation]) -> str: import urllib.parse from collections.abc import Mapping from dataclasses import dataclass -from typing import Any, IO, Literal, TypeVar +from typing import Any, IO, Literal, TypeVar, cast import httpx from pydantic import BaseModel, ValidationError @@ -345,10 +348,10 @@ class _ApiRequest: """ src += "\n\n" + _render_client_class( - ops, has_typed_resp, has_status_resp, has_no_resp, is_async=False + ops, has_typed_resp, has_status_resp, has_raw, has_no_resp, is_async=False ) src += "\n\n" + _render_client_class( - ops, has_typed_resp, has_status_resp, has_no_resp, is_async=True + ops, has_typed_resp, has_status_resp, has_raw, has_no_resp, is_async=True ) src += "\n" return src @@ -358,6 +361,7 @@ def _render_client_class( ops: list[_Operation], has_typed_resp: bool, has_status_resp: bool, + has_raw: bool, has_no_resp: bool, *, is_async: bool, @@ -411,7 +415,7 @@ def __init__(self, http_client: {http_cls}) -> None: """ src += f""" - {adef} _do(self, request: _ApiRequest) -> httpx.Response: + def _build_request(self, request: _ApiRequest) -> httpx.Request: path = request.path_fmt.format( *[urllib.parse.quote(a, safe="") for a in request.path_args] ) @@ -427,7 +431,11 @@ def __init__(self, http_client: {http_cls}) -> None: # Only fields the caller set are sent, so unset fields fall # back to the server default rather than being reset here. # An explicit None is kept, since null can mean "clear". - json_body = request.body.model_dump(mode="json", exclude_unset=True) + # by_alias: a field renamed for Python (e.g. async_ for + # "async") must serialize under its API name. + json_body = request.body.model_dump( + mode="json", exclude_unset=True, by_alias=True + ) else: json_body = request.body elif request.body_content_type == "{_MULTIPART_CONTENT}": @@ -442,11 +450,11 @@ def __init__(self, http_client: {http_cls}) -> None: # As above, plus dropping None: a null query parameter is # meaningless and would otherwise serialize as an empty string. params = request.query.model_dump( - mode="json", exclude_unset=True, exclude_none=True + mode="json", exclude_unset=True, exclude_none=True, by_alias=True ) else: params = request.query - response = {aw}self._http_client.request( + return self._http_client.build_request( request.method, path, json=json_body, @@ -455,12 +463,27 @@ def __init__(self, http_client: {http_cls}) -> None: params=params, headers=headers, ) + + {adef} _do(self, request: _ApiRequest) -> httpx.Response: + response = {aw}self._http_client.send(self._build_request(request)) if response.status_code not in request.success_codes: {error_dispatch}\ raise ResponseError(status_code=response.status_code, body=response.text) return response """ + if has_raw: + resp_read = "await response.aread()" if is_async else "response.read()" + src += f""" + {adef} _do_raw(self, request: _ApiRequest) -> httpx.Response: + response = {aw}self._http_client.send(self._build_request(request), stream=True) + if response.status_code not in request.success_codes: + {resp_read} +{error_dispatch}\ + raise ResponseError(status_code=response.status_code, body=response.text) + return response +""" + if has_typed_resp: src += f""" {adef} _do_json(self, response_type: type[_T], request: _ApiRequest) -> _T: @@ -479,7 +502,10 @@ def __init__(self, http_client: {http_cls}) -> None: response = {aw}self._do(request) response_type = response_types.get(response.status_code) if response_type is None: - raise ValueError(f"no JSON response schema declared for HTTP {{response.status_code}}") + # A bodyless success code, such as 204 alongside a JSON 200. The + # call site's return type includes None only when one is declared, + # so this cast is unreachable otherwise. + return cast(_T, None) content_type = response.headers.get("content-type", "") if not content_type.startswith("application/json"): raise ValueError(f"unexpected content type {{content_type!r}}, expected application/json") @@ -574,13 +600,18 @@ def _render_method(op: _Operation, *, is_async: bool, is_raw: bool) -> str: if is_raw: ret = "httpx.Response" - body = f"return {aw}self._do({req})" - elif len(op.json_responses) > 1: + body = f"return {aw}self._do_raw({req})" + elif op.json_responses and len(op.success_codes) > 1: + # Success codes without a JSON schema (e.g. a 204 alongside a JSON + # 200) yield None. + json_refs = dict(op.json_responses) types_expr = ( "{" + ", ".join(f"{code}: {ref}" for code, ref in op.json_responses) + "}" ) - union = " | ".join(dict.fromkeys(ref for _, ref in op.json_responses)) - ret = union + refs = list(dict.fromkeys(ref for _, ref in op.json_responses)) + if any(code not in json_refs for code in op.success_codes): + refs.append("None") + ret = " | ".join(refs) body = f"return {aw}self._do_json_with_status({types_expr}, {req})" elif op.json_responses: ret = op.json_responses[0][1] @@ -593,6 +624,9 @@ def _render_method(op: _Operation, *, is_async: bool, is_raw: bool) -> str: if op.summary: summary = op.summary if is_raw: - summary += ". Returns the response unread, in the requested content type." + summary += ( + ". Returns the response unread, in the requested content" + " type. The caller must close the response." + ) sig += f'\n """{summary}"""' return f"{sig}\n {body}\n" diff --git a/scripts/apigen/postprocess.py b/scripts/apigen/postprocess.py index 300dc1d..78ce911 100644 --- a/scripts/apigen/postprocess.py +++ b/scripts/apigen/postprocess.py @@ -43,9 +43,78 @@ def postprocess_models(src: str) -> str: src = src.replace(", RootModel, constr", ", RootModel") src = src.replace(", constr,", ",") src = src.replace(", constr\n", "\n") + src = _allow_population_by_field_name(src) return _validate_literal_model_defaults(src) +def _allow_population_by_field_name(src: str) -> str: + # Pydantic accepts only a field's alias by default, so a field renamed for + # Python (e.g. async_ for the API's "async") could not be passed by its + # Python name. Generated classes with aliased fields accept both. + tree = ast.parse(src) + lines = src.splitlines(keepends=True) + for node in reversed(tree.body): + if not (isinstance(node, ast.ClassDef) and _has_aliased_field(node)): + continue + config_assign = next( + ( + stmt + for stmt in node.body + if isinstance(stmt, ast.Assign) + and isinstance(stmt.targets[0], ast.Name) + and stmt.targets[0].id == "model_config" + ), + None, + ) + if config_assign is not None: + start = config_assign.lineno - 1 + end = config_assign.end_lineno + if "populate_by_name" in "".join(lines[start:end]): + continue + lines[start:end] = [ + "".join(lines[start:end]).replace( + "ConfigDict(", "ConfigDict(populate_by_name=True, ", 1 + ) + ] + else: + insert_at = node.body[0].lineno - 1 + indent = " " * node.body[0].col_offset + lines.insert( + insert_at, + f"{indent}model_config = ConfigDict(populate_by_name=True)\n\n", + ) + result = "".join(lines) + if "ConfigDict(" in result and not re.search( + r"^from pydantic import .*\bConfigDict\b", result, re.MULTILINE + ): + # An injected model_config is the file's first ConfigDict use. + result, substitutions = re.subn( + r"^from pydantic import ", + "from pydantic import ConfigDict, ", + result, + count=1, + ) + if substitutions == 0: + raise ValueError("injected model_config needs a pydantic import line") + return result + + +def _has_aliased_field(class_node: ast.ClassDef) -> bool: + for stmt in class_node.body: + if not isinstance(stmt, ast.AnnAssign): + continue + for subnode in ast.walk(stmt): + if not ( + isinstance(subnode, ast.Call) + and isinstance(subnode.func, ast.Name) + and subnode.func.id == "Field" + ): + continue + if any(keyword.arg == "alias" for keyword in subnode.keywords): + return True + return False + + def _validate_literal_model_defaults(src: str) -> str: # datamodel-code-generator emits a schema default verbatim even when the # field is model-typed, e.g. `x: Model = {"a": 1}` or `x: Limit | None = diff --git a/tests/client/test_sandbox.py b/tests/client/test_sandbox.py index c952a05..0e7afac 100644 --- a/tests/client/test_sandbox.py +++ b/tests/client/test_sandbox.py @@ -1,5 +1,7 @@ from __future__ import annotations +import json + import httpx import pytest @@ -87,7 +89,12 @@ def test_raw_returns_response_unread_with_accept() -> None: ) assert isinstance(response, httpx.Response) + # MockTransport responses are buffered, so the unread-ness of a streamed + # response (send(stream=True) in the generated _do_raw) is not + # observable here; the caller contract of read + close still holds. + response.read() assert response.content == b"file bytes" + response.close() assert fake.capture.headers["accept"] == "application/octet-stream" client.close() @@ -98,11 +105,28 @@ def test_raw_only_stream_keeps_plain_name() -> None: response = client.api.get_process_logs_stream(identifier="proc-1") + response.read() assert response.content == b"log line\n" + response.close() assert fake.capture.headers["accept"] == "text/plain" client.close() +def test_aliased_field_passed_and_sent_by_api_name() -> None: + fake = FakeTransport( + 200, {"manifest": {"createdAt": "now", "root": "/", "version": 1}} + ) + client = make_sync_client(fake) + + client.api.post_archive_export( + request=baseten.client.sandboxapi.ExportOptions(async_=True) + ) + + # The field renamed for Python (async_) serializes under its API name. + assert json.loads(fake.capture.body) == {"async": True} + client.close() + + def test_export_narrows_on_status_code() -> None: fake = FakeTransport( 200, {"manifest": {"createdAt": "now", "root": "/", "version": 1}, "size": 1024} @@ -195,6 +219,8 @@ async def test_async_raw_sibling() -> None: accept="text/event-stream", ) + await response.aread() assert response.content == b"event: done" + await response.aclose() assert fake.capture.headers["accept"] == "text/event-stream" await client.close() From e667289b5207af96d550f26eefc312371385b0d2 Mon Sep 17 00:00:00 2001 From: "Marius F. Killinger" Date: Tue, 29 Sep 2026 18:05:05 -0700 Subject: [PATCH 05/15] Trim comment bloat in the generator scripts Co-Authored-By: Claude Code --- scripts/apigen/__main__.py | 5 ++--- scripts/apigen/clientgen.py | 5 ++--- scripts/apigen/postprocess.py | 6 +++--- scripts/apigen/preprocess.py | 11 +++++------ 4 files changed, 12 insertions(+), 15 deletions(-) diff --git a/scripts/apigen/__main__.py b/scripts/apigen/__main__.py index 9f207d3..a30d1e4 100644 --- a/scripts/apigen/__main__.py +++ b/scripts/apigen/__main__.py @@ -56,9 +56,8 @@ def main() -> None: SPECS_DIR / "management.json", CLIENT_DIR / "managementapi", "Management", - # Sandbox management operations take a team selector as a query - # parameter alongside the request body; the rest of the management - # API keeps query parameters and request bodies separated. + # Sandbox management ops carry a team selector query param beside the + # body; the rest of the management API keeps query and body separated. query_and_body_allowed=lambda path: path.startswith("/v1/sandboxes"), ) generate_api(SPECS_DIR / "inference.json", CLIENT_DIR / "inferenceapi", "Inference") diff --git a/scripts/apigen/clientgen.py b/scripts/apigen/clientgen.py index 99ce476..2be4c0c 100644 --- a/scripts/apigen/clientgen.py +++ b/scripts/apigen/clientgen.py @@ -526,9 +526,8 @@ def _render_method(op: _Operation, *, is_async: bool, is_raw: bool) -> str: aw = "await " if is_async else "" # Query params go on `params`, request bodies on `request` (JSON) or - # `files`/`content` for non-JSON bodies. A request body is always - # required so an empty body still sends `{{}}`. Query params are - # optional unless the spec marks one required. + # `files`/`content` for non-JSON. Bodies are always required so an empty + # body still sends `{{}}`; query params only when the spec marks one. kwargs: list[str] = [f"{_camel_to_snake(p)}: str" for p in op.path_params] if op.query_ref: if op.query_required: diff --git a/scripts/apigen/postprocess.py b/scripts/apigen/postprocess.py index 78ce911..6d17433 100644 --- a/scripts/apigen/postprocess.py +++ b/scripts/apigen/postprocess.py @@ -48,9 +48,9 @@ def postprocess_models(src: str) -> str: def _allow_population_by_field_name(src: str) -> str: - # Pydantic accepts only a field's alias by default, so a field renamed for - # Python (e.g. async_ for the API's "async") could not be passed by its - # Python name. Generated classes with aliased fields accept both. + # Pydantic accepts only the alias by default, so a Python-renamed field + # (async_ for the API's "async") was not passable; generated classes with + # aliased fields accept both names. tree = ast.parse(src) lines = src.splitlines(keepends=True) for node in reversed(tree.body): diff --git a/scripts/apigen/preprocess.py b/scripts/apigen/preprocess.py index 1a98675..9010d7c 100644 --- a/scripts/apigen/preprocess.py +++ b/scripts/apigen/preprocess.py @@ -109,9 +109,9 @@ def preprocess_spec( def _flatten_parameters(doc: dict) -> None: - # Operations inherit path-item parameters, and either level may reference - # components/parameters. Inline both so every downstream step (query - # schema injection, client generation) sees concrete parameter objects. + # Operations inherit path-item parameters, and either level may $ref + # components/parameters; inline both so downstream steps see concrete + # parameter objects. component_params = doc.get("components", {}).get("parameters", {}) def resolve(param: dict) -> dict: @@ -294,9 +294,8 @@ def _inject_response_schemas(doc: dict) -> None: if not isinstance(schema, dict) or "$ref" in schema: continue base = response_type_model_name(method_names[(path, http_method)]) - # Only the first success code gets the bare name, so an - # operation with several 2xx bodies yields one schema per - # code rather than colliding. + # Only the first success code gets the bare name, so several + # 2xx bodies yield one schema per code, not a collision. schema_name = base if code == success_codes[0] else f"{base}{code}" if schema_name in schemas: raise ValueError( From 54f7026ec9d77a88cfa6786cef9858f644a47e8e Mon Sep 17 00:00:00 2001 From: "Marius F. Killinger" Date: Tue, 29 Sep 2026 18:21:05 -0700 Subject: [PATCH 06/15] Export SandboxClient and AsyncSandboxClient from baseten.client The thin per-sandbox wrapper is the advanced-user entry to the generated execution-plane client, mirroring the JS SDK's @basetenlabs/client export. The higher-level surface stays in baseten.sandbox. Co-Authored-By: Claude Code --- baseten/client/__init__.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/baseten/client/__init__.py b/baseten/client/__init__.py index ca1f663..a866705 100644 --- a/baseten/client/__init__.py +++ b/baseten/client/__init__.py @@ -2,7 +2,9 @@ Use :class:`ManagementClient` or :class:`AsyncManagementClient` for the management API, and :class:`InferenceClient` or :class:`AsyncInferenceClient` -for the inference API. +for the inference API. :class:`SandboxClient` and :class:`AsyncSandboxClient` +reach one sandbox's execution API directly; the higher-level surface lives in +:mod:`baseten.sandbox`. """ from baseten.client._inference import ( @@ -15,12 +17,20 @@ ManagementClient, ManagementClientOptions, ) +from baseten.client._sandbox import ( + AsyncSandboxClient, + SandboxClient, + SandboxClientOptions, +) __all__ = [ "AsyncInferenceClient", "AsyncManagementClient", + "AsyncSandboxClient", "InferenceClient", "InferenceClientOptions", "ManagementClient", "ManagementClientOptions", + "SandboxClient", + "SandboxClientOptions", ] From 643c03cea0bf7e3018f3e6ccc76be2467a4b4413 Mon Sep 17 00:00:00 2001 From: "Marius F. Killinger" Date: Wed, 30 Sep 2026 09:53:59 -0700 Subject: [PATCH 07/15] Address review: restore prod URLs in the management spec The staging pull had swapped every api.baseten.co URL in servers and examples for the staging host; the snapshot is hand-curated from staging until prod serves the sandbox paths, but its URLs should stay prod. The spec download URL reverts to prod to match the JS SDK, and the README keeps its shape as before this PR. Co-Authored-By: Claude Code --- README.md | 13 - scripts/apigen/__main__.py | 4 +- scripts/apigen/specs/management.json | 846 +++++++++++++-------------- 3 files changed, 424 insertions(+), 439 deletions(-) diff --git a/README.md b/README.md index da4203d..b4e386e 100644 --- a/README.md +++ b/README.md @@ -38,16 +38,3 @@ async with AsyncManagementClient(api_key="my-api-key") as client: Version 0.9.0 is a rewrite and shares no API with the earlier `baseten` releases. Code written against 0.8.2 or earlier will not work. Pin `baseten<0.9` to keep it. - -## Upgrading from 0.11.0 and earlier - -Version 0.12.0 splits request arguments. Query parameters now go on `params`, and -request bodies stay on `request`. Before, both used `request`. Rename the keyword on -calls that pass query parameters: - -```python -# 0.11.0 and earlier -client.api.get_model_apis(request=GetModelApisRequest(added_only=True)) -# 0.12.0 -client.api.get_model_apis(params=GetModelApisParams(added_only=True)) -``` \ No newline at end of file diff --git a/scripts/apigen/__main__.py b/scripts/apigen/__main__.py index a30d1e4..35cbd54 100644 --- a/scripts/apigen/__main__.py +++ b/scripts/apigen/__main__.py @@ -21,9 +21,7 @@ from scripts.apigen.postprocess import postprocess_models from scripts.apigen.preprocess import preprocess_spec, preprocess_truss_config_schema -# Staging, not prod: the /v1/sandboxes surface ships there first. Switch back -# once api.baseten.co/v1/spec serves it too. -MANAGEMENT_SPEC_URL = "https://api.staging.baseten.co/v1/spec" +MANAGEMENT_SPEC_URL = "https://api.baseten.co/v1/spec" INFERENCE_SPEC_URL = "https://api.baseten.co/inference-spec" TRUSS_CONFIG_SCHEMA_URL = ( "https://raw.githubusercontent.com/basetenlabs/truss/main/truss/config.schema.json" diff --git a/scripts/apigen/specs/management.json b/scripts/apigen/specs/management.json index 80e474c..68b1942 100644 --- a/scripts/apigen/specs/management.json +++ b/scripts/apigen/specs/management.json @@ -6,7 +6,7 @@ }, "servers": [ { - "url": "https://api.staging.baseten.co" + "url": "https://api.baseten.co" } ], "security": [ @@ -21,11 +21,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/volumes \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/volumes \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/volumes\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'cursor': None, 'namespace': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/volumes\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'cursor': None, 'namespace': None}\n)\n\nprint(response.text)" } ], "description": "Returns one row per volume in the namespace, each with its tags, head version, version counts, and any scheduled expiry. Pass namespace to choose the namespace, which is required because the volume service has no cross-namespace inventory. Versions live on the versions sub-resource, so this response stays a fixed size per volume no matter how long a volume's history is. A volume with no live versions left, whether deleted or expired, is not listed.", @@ -93,11 +93,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/volumes/token \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"scopes\": null,\n \"namespaces\": null,\n \"volumes\": null,\n \"correlation_id\": null\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/volumes/token \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"scopes\": null,\n \"namespaces\": null,\n \"volumes\": null,\n \"correlation_id\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/volumes/token\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'scopes': None, 'namespaces': None, 'volumes': None, 'correlation_id': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/volumes/token\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'scopes': None, 'namespaces': None, 'volumes': None, 'correlation_id': None}\n)\n\nprint(response.text)" } ], "description": "Exchanges your API key for a short-lived token that authenticates against Baseten volume storage. A volume token is needed only to push and pull volume data; other volume operations use your API key directly. Tokens expire after one hour and cannot be renewed; exchange again for a fresh token. Push and tag capabilities require organization-level model management permission. Pass correlation_id to link the issued token to a client operation in server logs.", @@ -132,11 +132,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/volumes/namespaces \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/volumes/namespaces \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/volumes/namespaces\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'cursor': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/volumes/namespaces\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'cursor': None}\n)\n\nprint(response.text)" } ], "description": "Returns the namespaces that hold volumes your API key can read, in lowercase. Namespaces are not created directly: a namespace comes into existence when the first volume is pushed into it.", @@ -194,11 +194,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/volumes/syncs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/volumes/syncs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/volumes/syncs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'cursor': None, 'ref': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/volumes/syncs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'cursor': None, 'ref': None}\n)\n\nprint(response.text)" } ], "description": "Lists volume syncs in the active workspace, newest first. Results may be narrowed by an exact destination ref.", @@ -272,11 +272,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/volumes/syncs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"source\": null,\n \"destination\": {\n \"ref\": null\n }\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/volumes/syncs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"source\": null,\n \"destination\": {\n \"ref\": null\n }\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/volumes/syncs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'source': None, 'destination': {'ref': None}}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/volumes/syncs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'source': None, 'destination': {'ref': None}}\n)\n\nprint(response.text)" } ], "description": "Starts one durable asynchronous transfer from a remote source into a BDN volume.", @@ -311,11 +311,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/volumes/syncs/{volume_sync_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/volumes/syncs/{volume_sync_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/volumes/syncs/{volume_sync_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/volumes/syncs/{volume_sync_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "responses": { @@ -344,11 +344,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/volumes/syncs/{volume_sync_id}/cancel \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/volumes/syncs/{volume_sync_id}/cancel \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/volumes/syncs/{volume_sync_id}/cancel\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/volumes/syncs/{volume_sync_id}/cancel\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Requests cancellation of a pending or running sync. Repeated cancellation and cancellation of terminal syncs return the existing state. Once cancellation is accepted, a later completion callback cannot replace the CANCELED state.", @@ -378,11 +378,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request DELETE \\\n--url https://api.staging.baseten.co/v1/volumes/{volume_namespace}/{volume_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"expected_sequence\": null\n}'" + "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/volumes/{volume_namespace}/{volume_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"expected_sequence\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/volumes/{volume_namespace}/{volume_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={'expected_sequence': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/volumes/{volume_namespace}/{volume_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={'expected_sequence': None}\n)\n\nprint(response.text)" } ], "description": "Deletes every live version of the volume, after which the volume stops appearing in listings. The data is not erased: each version stays restorable until its recovery deadline passes, and the versions sub-resource still reports them when you pass include_tombstoned. Deleting a volume that has no live versions left succeeds and reports zero versions deleted.", @@ -423,11 +423,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/volumes/{volume_namespace}/{volume_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/volumes/{volume_namespace}/{volume_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/volumes/{volume_namespace}/{volume_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/volumes/{volume_namespace}/{volume_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Returns a volume with its tags, head version, version counts, and any scheduled expiry. Versions live on the versions sub-resource so they can be paged separately. A volume whose versions have all been deleted or have expired is still returned, with zero live versions.", @@ -452,11 +452,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/volumes/{volume_namespace}/{volume_name}/versions \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/volumes/{volume_namespace}/{volume_name}/versions \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/volumes/{volume_namespace}/{volume_name}/versions\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/volumes/{volume_namespace}/{volume_name}/versions\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={}\n)\n\nprint(response.text)" } ], "description": "Returns every live version of the volume, newest first, each with its digest, size, lifecycle, the tags pointing at it, and any scheduled expiry. Pass include_tombstoned to list deleted and expired versions alongside them.", @@ -502,11 +502,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request DELETE \\\n--url https://api.staging.baseten.co/v1/volumes/{volume_namespace}/{volume_name}/versions/{volume_version} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"expected_sequence\": null\n}'" + "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/volumes/{volume_namespace}/{volume_name}/versions/{volume_version} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"expected_sequence\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/volumes/{volume_namespace}/{volume_name}/versions/{volume_version}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={'expected_sequence': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/volumes/{volume_namespace}/{volume_name}/versions/{volume_version}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={'expected_sequence': None}\n)\n\nprint(response.text)" } ], "description": "Deletes the version the address names, along with every tag pointing at it. Addressing the version by tag deletes the version the tag points at, not the tag. The data is not erased: the version stays restorable until the recovery deadline in the response passes. Deleting a version that is already deleted is a conflict, not a repeat success.", @@ -550,11 +550,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/volumes/{volume_namespace}/{volume_name}/versions/{volume_version} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/volumes/{volume_namespace}/{volume_name}/versions/{volume_version} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/volumes/{volume_namespace}/{volume_name}/versions/{volume_version}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/volumes/{volume_namespace}/{volume_name}/versions/{volume_version}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Returns a single version of the volume. Address it with `:` for a tag, `@` for a full content digest or a prefix of at least 12 hexadecimal characters, or `head` for the version a reference with no tag or digest resolves to. A digest prefix that matches more than one version is rejected: supply more characters.", @@ -579,11 +579,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/volumes/{volume_namespace}/{volume_name}/versions/{volume_version}/restore \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"expected_sequence\": null\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/volumes/{volume_namespace}/{volume_name}/versions/{volume_version}/restore \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"expected_sequence\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/volumes/{volume_namespace}/{volume_name}/versions/{volume_version}/restore\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'expected_sequence': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/volumes/{volume_namespace}/{volume_name}/versions/{volume_version}/restore\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'expected_sequence': None}\n)\n\nprint(response.text)" } ], "description": "Returns a deleted or expired version to service, provided its recovery deadline has not passed. The tags the version carried are not restored with it, so re-tag it if anything depended on those, and a restored version never expires until something sets a new expiry. Address the version by digest: a tombstoned version has no tags left to name it by.", @@ -629,11 +629,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/token \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"scopes\": [\n \"sandboxes\"\n ]\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/token \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"scopes\": [\n \"sandboxes\"\n ]\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/token\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'scopes': ['sandboxes']}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/token\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'scopes': ['sandboxes']}\n)\n\nprint(response.text)" } ], "description": "Exchanges your Baseten credentials for a short-lived token that authenticates against the sandbox API. The token carries every team you belong to. Tokens expire after two hours and cannot be renewed; request a new one when needed. This endpoint is experimental and may change or be removed without notice.", @@ -668,11 +668,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/secrets \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/secrets \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/secrets\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/secrets\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "responses": { @@ -693,11 +693,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/secrets \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"name\": \"my_secret\",\n \"value\": \"my_secret_value\"\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/secrets \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"name\": \"my_secret\",\n \"value\": \"my_secret_value\"\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/secrets\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'name': 'my_secret', 'value': 'my_secret_value'}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/secrets\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'name': 'my_secret', 'value': 'my_secret_value'}\n)\n\nprint(response.text)" } ], "description": "Creates or updates a secret by name. Scoped to the caller's primary team; use the team-scoped variant to target a specific team.", @@ -731,11 +731,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request DELETE \\\n--url https://api.staging.baseten.co/v1/secrets/{secret_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/secrets/{secret_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/secrets/{secret_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/secrets/{secret_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Deletes a secret by name in the specified team, or in the caller's organization default team when no team is specified.", @@ -764,11 +764,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/teams/{team_id}/secrets \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/teams/{team_id}/secrets \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/teams/{team_id}/secrets\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}/secrets\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "responses": { @@ -794,11 +794,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/teams/{team_id}/secrets \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"name\": \"my_secret\",\n \"value\": \"my_secret_value\"\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/teams/{team_id}/secrets \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"name\": \"my_secret\",\n \"value\": \"my_secret_value\"\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/teams/{team_id}/secrets\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'name': 'my_secret', 'value': 'my_secret_value'}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}/secrets\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'name': 'my_secret', 'value': 'my_secret_value'}\n)\n\nprint(response.text)" } ], "description": "Creates a new secret or updates an existing secret if one with the provided name already exists. The name and creation date of the created or updated secret is returned. This secret belongs to the specified team", @@ -832,11 +832,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request DELETE \\\n--url https://api.staging.baseten.co/v1/teams/{team_id}/secrets/{secret_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/teams/{team_id}/secrets/{secret_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/teams/{team_id}/secrets/{secret_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}/secrets/{secret_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Deletes a secret by name in the specified team, or in the caller's organization default team when no team is specified.", @@ -868,11 +868,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/environment_groups \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/environment_groups \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/environment_groups\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/environment_groups\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Lists environment groups. The team-scoped path targets the team in the path; the top-level path targets the caller's organization default team.", @@ -896,11 +896,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/environment_groups/{env_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/environment_groups/{env_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/environment_groups/{env_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/environment_groups/{env_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Gets a single environment group by name. The team-scoped path targets the team in the path; the top-level path targets the caller's organization default team.", @@ -927,11 +927,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request PATCH \\\n--url https://api.staging.baseten.co/v1/environment_groups/{env_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"manage_access\": null\n}'" + "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/environment_groups/{env_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"manage_access\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/environment_groups/{env_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'manage_access': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/environment_groups/{env_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'manage_access': None}\n)\n\nprint(response.text)" } ], "description": "Sets whether the environment is restricted and replaces the list of users granted manage access. The team-scoped path targets the team in the path; the top-level path targets the caller's organization default team.", @@ -965,11 +965,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/teams/{team_id}/environment_groups \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/teams/{team_id}/environment_groups \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/teams/{team_id}/environment_groups\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}/environment_groups\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Lists environment groups. The team-scoped path targets the team in the path; the top-level path targets the caller's organization default team.", @@ -998,11 +998,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/teams/{team_id}/environment_groups/{env_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/teams/{team_id}/environment_groups/{env_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/teams/{team_id}/environment_groups/{env_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}/environment_groups/{env_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Gets a single environment group by name. The team-scoped path targets the team in the path; the top-level path targets the caller's organization default team.", @@ -1032,11 +1032,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request PATCH \\\n--url https://api.staging.baseten.co/v1/teams/{team_id}/environment_groups/{env_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"manage_access\": null\n}'" + "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/teams/{team_id}/environment_groups/{env_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"manage_access\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/teams/{team_id}/environment_groups/{env_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'manage_access': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}/environment_groups/{env_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'manage_access': None}\n)\n\nprint(response.text)" } ], "description": "Sets whether the environment is restricted and replaces the list of users granted manage access. The team-scoped path targets the team in the path; the top-level path targets the caller's organization default team.", @@ -1070,11 +1070,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/teams \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/teams \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/teams\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'name': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'name': None}\n)\n\nprint(response.text)" } ], "description": "Returns a list of all teams the authenticated user has access to.", @@ -1118,11 +1118,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/teams/{team_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/teams/{team_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/teams/{team_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Returns a team the authenticated user has access to.", @@ -1151,11 +1151,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/regions \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/regions \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/regions\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/regions\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Lists the regions available for new deployments in the caller's organization.", @@ -1180,11 +1180,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/teams/{team_id}/regions \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/teams/{team_id}/regions \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/teams/{team_id}/regions\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}/regions\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Lists the regions the team specified in the path can place deployments in.", @@ -1214,11 +1214,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/instance_types \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/instance_types \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/instance_types\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/instance_types\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "responses": { @@ -1241,11 +1241,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/loops/user_config \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/loops/user_config \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/loops/user_config\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/user_config\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Returns the caller's Loops user config (per-user accelerator priorities). Null fields mean 'inherit the org-level allowlist'.", @@ -1267,11 +1267,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request PATCH \\\n--url https://api.staging.baseten.co/v1/loops/user_config \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"trainer_accelerator_priority\": [\n \"H100\",\n \"H200\"\n ],\n \"sampler_accelerator_priority\": [\n \"H100\",\n \"H200\"\n ]\n}'" + "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/loops/user_config \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"trainer_accelerator_priority\": [\n \"H100\",\n \"H200\"\n ],\n \"sampler_accelerator_priority\": [\n \"H100\",\n \"H200\"\n ]\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/loops/user_config\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'trainer_accelerator_priority': ['H100', 'H200'], 'sampler_accelerator_priority': ['H100', 'H200']}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/user_config\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'trainer_accelerator_priority': ['H100', 'H200'], 'sampler_accelerator_priority': ['H100', 'H200']}\n)\n\nprint(response.text)" } ], "description": "Updates the caller's Loops user config using JSON Merge Patch (RFC 7396) semantics per field: omit a field to leave it unchanged, send null to clear (inherit the org-level allowlist), or send a list to set the allowlist. Empty lists are rejected.", @@ -1305,11 +1305,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/instance_type_prices \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/instance_type_prices \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/instance_type_prices\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/instance_type_prices\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "responses": { @@ -1332,11 +1332,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/prepare_model_upload \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"deployment\": {\n \"config\": null,\n \"raw_config\": null,\n \"user_env\": null,\n \"environment_name\": null,\n \"region\": null,\n \"deploy_timeout_minutes\": null,\n \"deployment_name\": null,\n \"labels\": null\n },\n \"name\": null,\n \"team_id\": null,\n \"model_id\": null\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/prepare_model_upload \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"deployment\": {\n \"config\": null,\n \"raw_config\": null,\n \"user_env\": null,\n \"environment_name\": null,\n \"region\": null,\n \"deploy_timeout_minutes\": null,\n \"deployment_name\": null,\n \"labels\": null\n },\n \"name\": null,\n \"team_id\": null,\n \"model_id\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/prepare_model_upload\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'deployment': {'config': None, 'raw_config': None, 'user_env': None, 'environment_name': None, 'region': None, 'deploy_timeout_minutes': None, 'deployment_name': None, 'labels': None}, 'name': None, 'team_id': None, 'model_id': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/prepare_model_upload\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'deployment': {'config': None, 'raw_config': None, 'user_env': None, 'environment_name': None, 'region': None, 'deploy_timeout_minutes': None, 'deployment_name': None, 'labels': None}, 'name': None, 'team_id': None, 'model_id': None}\n)\n\nprint(response.text)" } ], "requestBody": { @@ -1369,11 +1369,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/audit_logs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/audit_logs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/audit_logs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'cursor': None, 'direction': 'DESC', 'search': None, 'start_epoch_millis': None, 'end_epoch_millis': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/audit_logs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'cursor': None, 'direction': 'DESC', 'search': None, 'start_epoch_millis': None, 'end_epoch_millis': None}\n)\n\nprint(response.text)" } ], "description": "Returns audit-log entries across the workspace, newest first, covering models, chains, and workspace-level actions. Use the filters to narrow by event type, actor, resource, environment, source, or time window, and the cursor to page. In workspaces with multiple teams, only organization admins can read the workspace audit log.", @@ -1572,11 +1572,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/models \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'name': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'name': None}\n)\n\nprint(response.text)" } ], "parameters": [ @@ -1617,11 +1617,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/models \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"source\": null\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"source\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'source': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'source': None}\n)\n\nprint(response.text)" } ], "description": "Creates a new model in the caller's organization. The `source` field selects how the model is constructed (currently `library_listing`, which forks an accessible listing from `GET /v1/library_models`). The deployment isn't instantly ready; poll the GET endpoint until status is ACTIVE.", @@ -1655,11 +1655,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/teams/{team_id}/models \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/teams/{team_id}/models \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/teams/{team_id}/models\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'name': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}/models\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'name': None}\n)\n\nprint(response.text)" } ], "parameters": [ @@ -1705,11 +1705,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/teams/{team_id}/models \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"source\": null\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/teams/{team_id}/models \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"source\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/teams/{team_id}/models\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'source': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}/models\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'source': None}\n)\n\nprint(response.text)" } ], "description": "Creates a new model in the caller's organization. The `source` field selects how the model is constructed (currently `library_listing`, which forks an accessible listing from `GET /v1/library_models`). The deployment isn't instantly ready; poll the GET endpoint until status is ACTIVE.", @@ -1743,11 +1743,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request DELETE \\\n--url https://api.staging.baseten.co/v1/models/{model_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/models/{model_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "responses": { @@ -1773,11 +1773,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/models/{model_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models/{model_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "responses": { @@ -1798,11 +1798,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request PATCH \\\n--url https://api.staging.baseten.co/v1/models/{model_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"name\": \"my-model\"\n}'" + "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/models/{model_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"name\": \"my-model\"\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'name': 'my-model'}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'name': 'my-model'}\n)\n\nprint(response.text)" } ], "description": "Updates the mutable fields of a model and returns the updated model. Renaming does not change the model ID, endpoints, or deployments. Pushes that still use the old model_name create another model or target a model that now uses that name, so update config.yaml after renaming.", @@ -1836,11 +1836,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/audit_logs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models/{model_id}/audit_logs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/audit_logs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'cursor': None, 'direction': 'DESC', 'search': None, 'start_epoch_millis': None, 'end_epoch_millis': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/audit_logs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'cursor': None, 'direction': 'DESC', 'search': None, 'start_epoch_millis': None, 'end_epoch_millis': None}\n)\n\nprint(response.text)" } ], "description": "Returns audit-log entries for a single model, newest first. Use the filters to narrow by event type, actor, deployment, environment, source, or time window, and the cursor to page.", @@ -2044,11 +2044,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'name': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'name': None}\n)\n\nprint(response.text)" } ], "parameters": [ @@ -2094,11 +2094,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"source\": null\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"source\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'source': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'source': None}\n)\n\nprint(response.text)" } ], "requestBody": { @@ -2131,11 +2131,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/development \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/development \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/development\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/development\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Gets a model's development deployment and returns the deployment.", @@ -2164,11 +2164,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/production \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/production \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/production\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/production\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Gets a model's production deployment and returns the deployment.", @@ -2197,11 +2197,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request DELETE \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Deletes a model's deployment by ID and returns the tombstone of the deployment.", @@ -2231,11 +2231,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Gets a model's deployment by ID and returns the deployment.", @@ -2257,11 +2257,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request PATCH \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"name\": \"my-deployment\"\n}'" + "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"name\": \"my-deployment\"\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'name': 'my-deployment'}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'name': 'my-deployment'}\n)\n\nprint(response.text)" } ], "description": "Updates the mutable fields of a deployment and returns the updated deployment.", @@ -2295,11 +2295,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request PATCH \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/development/autoscaling_settings \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"min_replica\": 0,\n \"max_replica\": 7,\n \"autoscaling_window\": 600,\n \"scale_down_delay\": 120,\n \"concurrency_target\": 2,\n \"target_utilization_percentage\": 70,\n \"target_in_flight_tokens\": 40000,\n \"max_scale_down_rate\": 20\n}'" + "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/development/autoscaling_settings \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"min_replica\": 0,\n \"max_replica\": 7,\n \"autoscaling_window\": 600,\n \"scale_down_delay\": 120,\n \"concurrency_target\": 2,\n \"target_utilization_percentage\": 70,\n \"target_in_flight_tokens\": 40000,\n \"max_scale_down_rate\": 20\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/development/autoscaling_settings\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'min_replica': 0, 'max_replica': 7, 'autoscaling_window': 600, 'scale_down_delay': 120, 'concurrency_target': 2, 'target_utilization_percentage': 70, 'target_in_flight_tokens': 40000, 'max_scale_down_rate': 20}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/development/autoscaling_settings\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'min_replica': 0, 'max_replica': 7, 'autoscaling_window': 600, 'scale_down_delay': 120, 'concurrency_target': 2, 'target_utilization_percentage': 70, 'target_in_flight_tokens': 40000, 'max_scale_down_rate': 20}\n)\n\nprint(response.text)" } ], "description": "Updates a development deployment's autoscaling settings and returns the update status.", @@ -2338,11 +2338,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request PATCH \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/production/autoscaling_settings \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"min_replica\": 0,\n \"max_replica\": 7,\n \"autoscaling_window\": 600,\n \"scale_down_delay\": 120,\n \"concurrency_target\": 2,\n \"target_utilization_percentage\": 70,\n \"target_in_flight_tokens\": 40000,\n \"max_scale_down_rate\": 20\n}'" + "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/production/autoscaling_settings \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"min_replica\": 0,\n \"max_replica\": 7,\n \"autoscaling_window\": 600,\n \"scale_down_delay\": 120,\n \"concurrency_target\": 2,\n \"target_utilization_percentage\": 70,\n \"target_in_flight_tokens\": 40000,\n \"max_scale_down_rate\": 20\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/production/autoscaling_settings\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'min_replica': 0, 'max_replica': 7, 'autoscaling_window': 600, 'scale_down_delay': 120, 'concurrency_target': 2, 'target_utilization_percentage': 70, 'target_in_flight_tokens': 40000, 'max_scale_down_rate': 20}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/production/autoscaling_settings\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'min_replica': 0, 'max_replica': 7, 'autoscaling_window': 600, 'scale_down_delay': 120, 'concurrency_target': 2, 'target_utilization_percentage': 70, 'target_in_flight_tokens': 40000, 'max_scale_down_rate': 20}\n)\n\nprint(response.text)" } ], "description": "Updates a production deployment's autoscaling settings and returns the update status.", @@ -2381,11 +2381,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request PATCH \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/autoscaling_settings \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"min_replica\": 0,\n \"max_replica\": 7,\n \"autoscaling_window\": 600,\n \"scale_down_delay\": 120,\n \"concurrency_target\": 2,\n \"target_utilization_percentage\": 70,\n \"target_in_flight_tokens\": 40000,\n \"max_scale_down_rate\": 20\n}'" + "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/autoscaling_settings \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"min_replica\": 0,\n \"max_replica\": 7,\n \"autoscaling_window\": 600,\n \"scale_down_delay\": 120,\n \"concurrency_target\": 2,\n \"target_utilization_percentage\": 70,\n \"target_in_flight_tokens\": 40000,\n \"max_scale_down_rate\": 20\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/autoscaling_settings\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'min_replica': 0, 'max_replica': 7, 'autoscaling_window': 600, 'scale_down_delay': 120, 'concurrency_target': 2, 'target_utilization_percentage': 70, 'target_in_flight_tokens': 40000, 'max_scale_down_rate': 20}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/autoscaling_settings\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'min_replica': 0, 'max_replica': 7, 'autoscaling_window': 600, 'scale_down_delay': 120, 'concurrency_target': 2, 'target_utilization_percentage': 70, 'target_in_flight_tokens': 40000, 'max_scale_down_rate': 20}\n)\n\nprint(response.text)" } ], "description": "Updates a deployment's autoscaling settings and returns the update status.", @@ -2427,11 +2427,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request PATCH \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/request_backpressure_settings \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"policy\": \"REJECT_ON_FULL\"\n}'" + "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/request_backpressure_settings \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"policy\": \"REJECT_ON_FULL\"\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/request_backpressure_settings\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'policy': 'REJECT_ON_FULL'}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/request_backpressure_settings\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'policy': 'REJECT_ON_FULL'}\n)\n\nprint(response.text)" } ], "requestBody": { @@ -2472,11 +2472,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/development/promote \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"scale_down_previous_production\": true,\n \"preserve_env_instance_type\": true\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/development/promote \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"scale_down_previous_production\": true,\n \"preserve_env_instance_type\": true\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/development/promote\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'scale_down_previous_production': True, 'preserve_env_instance_type': True}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/development/promote\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'scale_down_previous_production': True, 'preserve_env_instance_type': True}\n)\n\nprint(response.text)" } ], "description": "Creates a new production deployment from the development deployment and returns the deployment that is building.", @@ -2515,11 +2515,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/promote \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"scale_down_previous_production\": true,\n \"preserve_env_instance_type\": true\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/promote \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"scale_down_previous_production\": true,\n \"preserve_env_instance_type\": true\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/promote\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'scale_down_previous_production': True, 'preserve_env_instance_type': True}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/promote\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'scale_down_previous_production': True, 'preserve_env_instance_type': True}\n)\n\nprint(response.text)" } ], "description": "Promotes an existing deployment to production and returns the same deployment.", @@ -2561,11 +2561,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/development/activate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/development/activate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/development/activate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/development/activate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Activates a development deployment if not already activated.", @@ -2594,11 +2594,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/production/activate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/production/activate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/production/activate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/production/activate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Activates a production deployment if not already activated.", @@ -2627,11 +2627,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/activate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/activate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/activate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/activate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Activates a deployment if not already activated.", @@ -2663,11 +2663,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/development/deactivate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/development/deactivate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/development/deactivate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/development/deactivate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Deactivates a development deployment if not already deactivated.", @@ -2696,11 +2696,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/production/deactivate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/production/deactivate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/production/deactivate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/production/deactivate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Deactivates a production deployment if not already deactivated.", @@ -2729,11 +2729,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/deactivate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/deactivate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/deactivate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/deactivate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Deactivates a deployment if not already deactivated.", @@ -2765,11 +2765,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/development/retry \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/development/retry \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/development/retry\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/development/retry\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Retries a failed development deployment and returns the retry status and updated deployment.", @@ -2798,11 +2798,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/production/retry \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/production/retry \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/production/retry\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/production/retry\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Retries a failed production deployment and returns the retry status and updated deployment.", @@ -2831,11 +2831,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/retry \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/retry \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/retry\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/retry\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Retries a failed deployment and returns the retry status and updated deployment.", @@ -2867,11 +2867,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/download \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/download \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/download\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/download\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Gets a presigned URL to download the truss tar file for a deployment.", @@ -2903,11 +2903,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/config \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/config \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/config\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'output_format': 'raw'}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/config\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'output_format': 'raw'}\n)\n\nprint(response.text)" } ], "description": "Returns the deployment's config. `output_format` query param picks the shape: 'raw' (config.yaml text), 'parsed' (dict with defaults), or 'both' (default).", @@ -2951,11 +2951,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/logs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/logs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/logs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'start_epoch_millis': None, 'end_epoch_millis': None, 'direction': None, 'limit': None, 'min_level': None, 'replica': None, 'request_id': None, 'component': None, 'search_pattern': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/logs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'start_epoch_millis': None, 'end_epoch_millis': None, 'direction': None, 'limit': None, 'min_level': None, 'replica': None, 'request_id': None, 'component': None, 'search_pattern': None}\n)\n\nprint(response.text)" } ], "description": "Gets all the logs for a model deployment in the given time range, which defaults to the last 30 minutes. A failed or older deployment may only have logs from before that window; pass `start_epoch_millis` to widen it back to the build/deploy time.", @@ -3181,11 +3181,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/logs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"start_epoch_millis\": null,\n \"end_epoch_millis\": null,\n \"direction\": null,\n \"limit\": null,\n \"min_level\": null,\n \"replica\": null,\n \"request_id\": null,\n \"component\": null,\n \"search_pattern\": null\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/logs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"start_epoch_millis\": null,\n \"end_epoch_millis\": null,\n \"direction\": null,\n \"limit\": null,\n \"min_level\": null,\n \"replica\": null,\n \"request_id\": null,\n \"component\": null,\n \"search_pattern\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/logs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'start_epoch_millis': None, 'end_epoch_millis': None, 'direction': None, 'limit': None, 'min_level': None, 'replica': None, 'request_id': None, 'component': None, 'search_pattern': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/logs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'start_epoch_millis': None, 'end_epoch_millis': None, 'direction': None, 'limit': None, 'min_level': None, 'replica': None, 'request_id': None, 'component': None, 'search_pattern': None}\n)\n\nprint(response.text)" } ], "description": "Use the GET form on this path instead.", @@ -3221,11 +3221,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/patches \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"prev_patch_hash\": null,\n \"next_patch_point\": {\n \"content_hashes\": null,\n \"config\": null\n },\n \"patch_ops\": null\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/patches \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"prev_patch_hash\": null,\n \"next_patch_point\": {\n \"content_hashes\": null,\n \"config\": null\n },\n \"patch_ops\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/patches\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'prev_patch_hash': None, 'next_patch_point': {'content_hashes': None, 'config': None}, 'patch_ops': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/patches\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'prev_patch_hash': None, 'next_patch_point': {'content_hashes': None, 'config': None}, 'patch_ops': None}\n)\n\nprint(response.text)" } ], "description": "Persists a patch durably without applying it; call the sync endpoint to apply staged patches to the running deployment. The target must be a development deployment (its archive created with `is_development` set to `true`); patching any other deployment is rejected.", @@ -3268,11 +3268,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/patches/state \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/patches/state \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/patches/state\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/patches/state\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Returns the patch point the deployment is recorded as running and the latest staged-but-unsynced point, if any. The watch client computes its next patch off the pending point when present, else the running point.", @@ -3305,11 +3305,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/patches/sync \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/patches/sync \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/patches/sync\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/patches/sync\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Applies any staged patches to the running deployment. A 2xx response means the sync reached a verdict: in sync, or a full push is required (needs_full_deploy_reason). A 503 means the sync was not attempted or failed recoverably and should be retried; any other error is terminal.", @@ -3352,11 +3352,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/metrics \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/metrics \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/metrics\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'mode': 'CURRENT', 'start_epoch_millis': None, 'end_epoch_millis': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/metrics\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'mode': 'CURRENT', 'start_epoch_millis': None, 'end_epoch_millis': None}\n)\n\nprint(response.text)" } ], "description": "Gets the metrics for a model deployment in the given time range.", @@ -3450,11 +3450,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request DELETE \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/replicas/{replica_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/replicas/{replica_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/replicas/{replica_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/replicas/{replica_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Terminates a deployment replica and returns the termination status.", @@ -3489,11 +3489,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/ssh/sign \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"public_key\": null,\n \"replica_id\": null\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/ssh/sign \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"public_key\": null,\n \"replica_id\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/ssh/sign\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'public_key': None, 'replica_id': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/deployments/{deployment_id}/ssh/sign\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'public_key': None, 'replica_id': None}\n)\n\nprint(response.text)" } ], "description": "Signs a short-lived SSH certificate granting access to a running inference model pod. Returns the signed SSH certificate, a JWT token for SSH proxy authentication, the proxy address to connect through, and the certificate expiry time.", @@ -3535,11 +3535,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/environments \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models/{model_id}/environments \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/environments\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/environments\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Gets all environments for a given model.", @@ -3566,11 +3566,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/environments \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"name\": \"staging\",\n \"autoscaling_settings\": {\n \"autoscaling_window\": 800,\n \"concurrency_target\": 3,\n \"max_replica\": 2,\n \"max_scale_down_rate\": null,\n \"min_replica\": 1,\n \"scale_down_delay\": 60,\n \"target_in_flight_tokens\": null,\n \"target_utilization_percentage\": null\n },\n \"promotion_settings\": {\n \"promotion_cleanup_strategy\": null,\n \"ramp_up_duration_seconds\": 600,\n \"ramp_up_while_promoting\": true,\n \"redeploy_on_promotion\": true,\n \"rolling_deploy\": false,\n \"rolling_deploy_config\": null\n },\n \"request_backpressure_settings\": null\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/environments \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"name\": \"staging\",\n \"autoscaling_settings\": {\n \"autoscaling_window\": 800,\n \"concurrency_target\": 3,\n \"max_replica\": 2,\n \"max_scale_down_rate\": null,\n \"min_replica\": 1,\n \"scale_down_delay\": 60,\n \"target_in_flight_tokens\": null,\n \"target_utilization_percentage\": null\n },\n \"promotion_settings\": {\n \"promotion_cleanup_strategy\": null,\n \"ramp_up_duration_seconds\": 600,\n \"ramp_up_while_promoting\": true,\n \"redeploy_on_promotion\": true,\n \"rolling_deploy\": false,\n \"rolling_deploy_config\": null\n },\n \"request_backpressure_settings\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/environments\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'name': 'staging', 'autoscaling_settings': {'autoscaling_window': 800, 'concurrency_target': 3, 'max_replica': 2, 'max_scale_down_rate': None, 'min_replica': 1, 'scale_down_delay': 60, 'target_in_flight_tokens': None, 'target_utilization_percentage': None}, 'promotion_settings': {'promotion_cleanup_strategy': None, 'ramp_up_duration_seconds': 600, 'ramp_up_while_promoting': True, 'redeploy_on_promotion': True, 'rolling_deploy': False, 'rolling_deploy_config': None}, 'request_backpressure_settings': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/environments\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'name': 'staging', 'autoscaling_settings': {'autoscaling_window': 800, 'concurrency_target': 3, 'max_replica': 2, 'max_scale_down_rate': None, 'min_replica': 1, 'scale_down_delay': 60, 'target_in_flight_tokens': None, 'target_utilization_percentage': None}, 'promotion_settings': {'promotion_cleanup_strategy': None, 'ramp_up_duration_seconds': 600, 'ramp_up_while_promoting': True, 'redeploy_on_promotion': True, 'rolling_deploy': False, 'rolling_deploy_config': None}, 'request_backpressure_settings': None}\n)\n\nprint(response.text)" } ], "description": "Creates an environment for the specified model and returns the environment.", @@ -3604,11 +3604,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request DELETE \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/environments/{env_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/models/{model_id}/environments/{env_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/environments/{env_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/environments/{env_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Deletes an environment and returns its tombstone. Any in-progress promotion to the environment is canceled, and the deployment currently serving the environment is scaled down to zero replicas rather than deleted. The production environment cannot be deleted.", @@ -3638,11 +3638,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/environments/{env_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models/{model_id}/environments/{env_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/environments/{env_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/environments/{env_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Gets an environment's details and returns the environment.", @@ -3664,11 +3664,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request PATCH \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/environments/{env_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"autoscaling_settings\": {\n \"autoscaling_window\": 800,\n \"concurrency_target\": 3,\n \"max_replica\": 2,\n \"max_scale_down_rate\": null,\n \"min_replica\": 1,\n \"scale_down_delay\": 60,\n \"target_in_flight_tokens\": null,\n \"target_utilization_percentage\": null\n },\n \"promotion_settings\": {\n \"promotion_cleanup_strategy\": null,\n \"ramp_up_duration_seconds\": 600,\n \"ramp_up_while_promoting\": true,\n \"redeploy_on_promotion\": true,\n \"rolling_deploy\": null,\n \"rolling_deploy_config\": null\n },\n \"autoscaling_schedule_settings\": {\n \"schedules\": [\n {\n \"autoscaling_settings\": {\n \"autoscaling_window\": null,\n \"concurrency_target\": null,\n \"max_replica\": 8,\n \"max_scale_down_rate\": null,\n \"min_replica\": 2,\n \"scale_down_delay\": null,\n \"target_in_flight_tokens\": null,\n \"target_utilization_percentage\": null\n },\n \"cadence\": \"DAILY\",\n \"enabled\": true,\n \"end_hour\": 10,\n \"end_minute\": 0,\n \"name\": \"weekday-peak\",\n \"start_hour\": 8,\n \"start_minute\": 0,\n \"weekdays\": [\n \"MONDAY\",\n \"TUESDAY\",\n \"WEDNESDAY\",\n \"THURSDAY\",\n \"FRIDAY\"\n ]\n }\n ],\n \"timezone\": \"America/Los_Angeles\"\n },\n \"request_backpressure_settings\": {\n \"policy\": \"REJECT_ON_FULL\"\n }\n}'" + "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/models/{model_id}/environments/{env_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"autoscaling_settings\": {\n \"autoscaling_window\": 800,\n \"concurrency_target\": 3,\n \"max_replica\": 2,\n \"max_scale_down_rate\": null,\n \"min_replica\": 1,\n \"scale_down_delay\": 60,\n \"target_in_flight_tokens\": null,\n \"target_utilization_percentage\": null\n },\n \"promotion_settings\": {\n \"promotion_cleanup_strategy\": null,\n \"ramp_up_duration_seconds\": 600,\n \"ramp_up_while_promoting\": true,\n \"redeploy_on_promotion\": true,\n \"rolling_deploy\": null,\n \"rolling_deploy_config\": null\n },\n \"autoscaling_schedule_settings\": {\n \"schedules\": [\n {\n \"autoscaling_settings\": {\n \"autoscaling_window\": null,\n \"concurrency_target\": null,\n \"max_replica\": 8,\n \"max_scale_down_rate\": null,\n \"min_replica\": 2,\n \"scale_down_delay\": null,\n \"target_in_flight_tokens\": null,\n \"target_utilization_percentage\": null\n },\n \"cadence\": \"DAILY\",\n \"enabled\": true,\n \"end_hour\": 10,\n \"end_minute\": 0,\n \"name\": \"weekday-peak\",\n \"start_hour\": 8,\n \"start_minute\": 0,\n \"weekdays\": [\n \"MONDAY\",\n \"TUESDAY\",\n \"WEDNESDAY\",\n \"THURSDAY\",\n \"FRIDAY\"\n ]\n }\n ],\n \"timezone\": \"America/Los_Angeles\"\n },\n \"request_backpressure_settings\": {\n \"policy\": \"REJECT_ON_FULL\"\n }\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/environments/{env_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'autoscaling_settings': {'autoscaling_window': 800, 'concurrency_target': 3, 'max_replica': 2, 'max_scale_down_rate': None, 'min_replica': 1, 'scale_down_delay': 60, 'target_in_flight_tokens': None, 'target_utilization_percentage': None}, 'promotion_settings': {'promotion_cleanup_strategy': None, 'ramp_up_duration_seconds': 600, 'ramp_up_while_promoting': True, 'redeploy_on_promotion': True, 'rolling_deploy': None, 'rolling_deploy_config': None}, 'autoscaling_schedule_settings': {'schedules': [{'autoscaling_settings': {'autoscaling_window': None, 'concurrency_target': None, 'max_replica': 8, 'max_scale_down_rate': None, 'min_replica': 2, 'scale_down_delay': None, 'target_in_flight_tokens': None, 'target_utilization_percentage': None}, 'cadence': 'DAILY', 'enabled': True, 'end_hour': 10, 'end_minute': 0, 'name': 'weekday-peak', 'start_hour': 8, 'start_minute': 0, 'weekdays': ['MONDAY', 'TUESDAY', 'WEDNESDAY', 'THURSDAY', 'FRIDAY']}], 'timezone': 'America/Los_Angeles'}, 'request_backpressure_settings': {'policy': 'REJECT_ON_FULL'}}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/environments/{env_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'autoscaling_settings': {'autoscaling_window': 800, 'concurrency_target': 3, 'max_replica': 2, 'max_scale_down_rate': None, 'min_replica': 1, 'scale_down_delay': 60, 'target_in_flight_tokens': None, 'target_utilization_percentage': None}, 'promotion_settings': {'promotion_cleanup_strategy': None, 'ramp_up_duration_seconds': 600, 'ramp_up_while_promoting': True, 'redeploy_on_promotion': True, 'rolling_deploy': None, 'rolling_deploy_config': None}, 'autoscaling_schedule_settings': {'schedules': [{'autoscaling_settings': {'autoscaling_window': None, 'concurrency_target': None, 'max_replica': 8, 'max_scale_down_rate': None, 'min_replica': 2, 'scale_down_delay': None, 'target_in_flight_tokens': None, 'target_utilization_percentage': None}, 'cadence': 'DAILY', 'enabled': True, 'end_hour': 10, 'end_minute': 0, 'name': 'weekday-peak', 'start_hour': 8, 'start_minute': 0, 'weekdays': ['MONDAY', 'TUESDAY', 'WEDNESDAY', 'THURSDAY', 'FRIDAY']}], 'timezone': 'America/Los_Angeles'}, 'request_backpressure_settings': {'policy': 'REJECT_ON_FULL'}}\n)\n\nprint(response.text)" } ], "description": "Asynchronously updates an environment's settings. Poll the GET endpoint for the applied state.", @@ -3702,11 +3702,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/environments/{env_name}/logs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/logs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/environments/{env_name}/logs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'start_epoch_millis': None, 'end_epoch_millis': None, 'direction': None, 'limit': None, 'min_level': None, 'replica': None, 'request_id': None, 'component': None, 'search_pattern': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/logs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'start_epoch_millis': None, 'end_epoch_millis': None, 'direction': None, 'limit': None, 'min_level': None, 'replica': None, 'request_id': None, 'component': None, 'search_pattern': None}\n)\n\nprint(response.text)" } ], "description": "Gets logs across all deployments that were active on the environment in the given time range, which defaults to the last 30 minutes. Pass `start_epoch_millis` to widen the window back to an earlier deployment's build/deploy time.", @@ -3934,11 +3934,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/environments/{env_name}/metrics \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/metrics \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/environments/{env_name}/metrics\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'mode': 'CURRENT', 'start_epoch_millis': None, 'end_epoch_millis': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/metrics\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'mode': 'CURRENT', 'start_epoch_millis': None, 'end_epoch_millis': None}\n)\n\nprint(response.text)" } ], "description": "Gets metrics aggregated across every deployment that was active on the environment in the given time range. In series mode the window is split at each promotion so that every point reflects the deployment(s) serving the environment at that time.", @@ -4032,11 +4032,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/environments/{env_name}/activate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/activate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/environments/{env_name}/activate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/activate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Activates a deployment associated with an environment if not already activated.", @@ -4068,11 +4068,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/environments/{env_name}/deactivate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/deactivate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/environments/{env_name}/deactivate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/deactivate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Deactivates a deployment associated with an environment if not already deactivated.", @@ -4104,11 +4104,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/environments/{env_name}/promote \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"scale_down_previous_deployment\": true,\n \"deployment_id\": null,\n \"preserve_env_instance_type\": true\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/promote \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"scale_down_previous_deployment\": true,\n \"deployment_id\": null,\n \"preserve_env_instance_type\": true\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/environments/{env_name}/promote\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'scale_down_previous_deployment': True, 'deployment_id': None, 'preserve_env_instance_type': True}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/promote\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'scale_down_previous_deployment': True, 'deployment_id': None, 'preserve_env_instance_type': True}\n)\n\nprint(response.text)" } ], "description": "Promotes an existing deployment to an environment and returns the promoted deployment.", @@ -4150,11 +4150,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/environments/{env_name}/cancel_promotion \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/cancel_promotion \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/environments/{env_name}/cancel_promotion\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/cancel_promotion\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Cancels an ongoing promotion to an environment and returns the cancellation status.", @@ -4186,11 +4186,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/environments/{env_name}/pause_promotion \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/pause_promotion \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/environments/{env_name}/pause_promotion\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/pause_promotion\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Pauses an in-progress rolling promotion after the current step completes. No further scaling changes are made until resumed.", @@ -4222,11 +4222,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/environments/{env_name}/resume_promotion \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/resume_promotion \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/environments/{env_name}/resume_promotion\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/resume_promotion\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Resumes a paused rolling promotion, continuing from where it was paused.", @@ -4258,11 +4258,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/environments/{env_name}/force_cancel_promotion \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/force_cancel_promotion \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/environments/{env_name}/force_cancel_promotion\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/force_cancel_promotion\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Immediately cancels an in-progress rolling promotion and triggers rollback to the previous version.", @@ -4294,11 +4294,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/models/{model_id}/environments/{env_name}/force_roll_forward_promotion \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/force_roll_forward_promotion \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/models/{model_id}/environments/{env_name}/force_roll_forward_promotion\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/models/{model_id}/environments/{env_name}/force_roll_forward_promotion\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Immediately completes the rolling promotion, shifting all traffic to the new version. This works even if the promotion is in the process of rolling back.", @@ -4330,11 +4330,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/chains \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/chains \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/chains\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "responses": { @@ -4357,11 +4357,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request DELETE \\\n--url https://api.staging.baseten.co/v1/chains/{chain_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/chains/{chain_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/chains/{chain_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "responses": { @@ -4387,11 +4387,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/chains/{chain_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/chains/{chain_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/chains/{chain_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "responses": { @@ -4414,11 +4414,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/chains/{chain_id}/audit_logs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/chains/{chain_id}/audit_logs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/chains/{chain_id}/audit_logs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'cursor': None, 'direction': 'DESC', 'search': None, 'start_epoch_millis': None, 'end_epoch_millis': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}/audit_logs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'cursor': None, 'direction': 'DESC', 'search': None, 'start_epoch_millis': None, 'end_epoch_millis': None}\n)\n\nprint(response.text)" } ], "description": "Returns audit-log entries for a single chain, newest first. Use the filters to narrow by event type, actor, chain deployment, environment, source, or time window, and the cursor to page.", @@ -4622,11 +4622,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/chains/{chain_id}/deployments \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/chains/{chain_id}/deployments \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/chains/{chain_id}/deployments\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}/deployments\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "responses": { @@ -4654,11 +4654,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request DELETE \\\n--url https://api.staging.baseten.co/v1/chains/{chain_id}/deployments/{chain_deployment_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/chains/{chain_id}/deployments/{chain_deployment_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/chains/{chain_id}/deployments/{chain_deployment_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}/deployments/{chain_deployment_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "responses": { @@ -4687,11 +4687,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/chains/{chain_id}/deployments/{chain_deployment_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/chains/{chain_id}/deployments/{chain_deployment_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/chains/{chain_id}/deployments/{chain_deployment_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}/deployments/{chain_deployment_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "responses": { @@ -4714,11 +4714,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/chains/{chain_id}/deployments/{chain_deployment_id}/deactivate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/chains/{chain_id}/deployments/{chain_deployment_id}/deactivate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/chains/{chain_id}/deployments/{chain_deployment_id}/deactivate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}/deployments/{chain_deployment_id}/deactivate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Deactivates a chain deployment and returns the deactivation status.", @@ -4750,11 +4750,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/chains/{chain_id}/deployments/{chain_deployment_id}/chainlets/{chainlet_id}/logs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/chains/{chain_id}/deployments/{chain_deployment_id}/chainlets/{chainlet_id}/logs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/chains/{chain_id}/deployments/{chain_deployment_id}/chainlets/{chainlet_id}/logs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'start_epoch_millis': None, 'end_epoch_millis': None, 'direction': None, 'limit': None, 'min_level': None, 'replica': None, 'request_id': None, 'component': None, 'search_pattern': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}/deployments/{chain_deployment_id}/chainlets/{chainlet_id}/logs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'start_epoch_millis': None, 'end_epoch_millis': None, 'direction': None, 'limit': None, 'min_level': None, 'replica': None, 'request_id': None, 'component': None, 'search_pattern': None}\n)\n\nprint(response.text)" } ], "description": "Resolves the chainlet (by ID, scoped to the given chain deployment) to its underlying model deployment and returns its logs in the given time range.", @@ -4985,11 +4985,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/chains/{chain_id}/environments \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/chains/{chain_id}/environments \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/chains/{chain_id}/environments\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}/environments\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Gets all chain environments for a given chain.", @@ -5016,11 +5016,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/chains/{chain_id}/environments \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"name\": \"staging\",\n \"promotion_settings\": {\n \"promotion_cleanup_strategy\": null,\n \"ramp_up_duration_seconds\": 600,\n \"ramp_up_while_promoting\": true,\n \"redeploy_on_promotion\": true,\n \"rolling_deploy\": null,\n \"rolling_deploy_config\": null\n },\n \"chainlet_settings\": [\n {\n \"autoscaling_settings\": {\n \"autoscaling_window\": 800,\n \"concurrency_target\": 4,\n \"max_replica\": 3,\n \"max_scale_down_rate\": null,\n \"min_replica\": 2,\n \"scale_down_delay\": 63,\n \"target_in_flight_tokens\": null,\n \"target_utilization_percentage\": null\n },\n \"chainlet_name\": \"HelloWorld\",\n \"instance_type_id\": \"2x8\"\n },\n {\n \"autoscaling_settings\": {\n \"autoscaling_window\": null,\n \"concurrency_target\": null,\n \"max_replica\": 3,\n \"max_scale_down_rate\": null,\n \"min_replica\": 3,\n \"scale_down_delay\": null,\n \"target_in_flight_tokens\": null,\n \"target_utilization_percentage\": null\n },\n \"chainlet_name\": \"RandInt\",\n \"instance_type_id\": \"A10Gx8x32\"\n }\n ]\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/chains/{chain_id}/environments \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"name\": \"staging\",\n \"promotion_settings\": {\n \"promotion_cleanup_strategy\": null,\n \"ramp_up_duration_seconds\": 600,\n \"ramp_up_while_promoting\": true,\n \"redeploy_on_promotion\": true,\n \"rolling_deploy\": null,\n \"rolling_deploy_config\": null\n },\n \"chainlet_settings\": [\n {\n \"autoscaling_settings\": {\n \"autoscaling_window\": 800,\n \"concurrency_target\": 4,\n \"max_replica\": 3,\n \"max_scale_down_rate\": null,\n \"min_replica\": 2,\n \"scale_down_delay\": 63,\n \"target_in_flight_tokens\": null,\n \"target_utilization_percentage\": null\n },\n \"chainlet_name\": \"HelloWorld\",\n \"instance_type_id\": \"2x8\"\n },\n {\n \"autoscaling_settings\": {\n \"autoscaling_window\": null,\n \"concurrency_target\": null,\n \"max_replica\": 3,\n \"max_scale_down_rate\": null,\n \"min_replica\": 3,\n \"scale_down_delay\": null,\n \"target_in_flight_tokens\": null,\n \"target_utilization_percentage\": null\n },\n \"chainlet_name\": \"RandInt\",\n \"instance_type_id\": \"A10Gx8x32\"\n }\n ]\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/chains/{chain_id}/environments\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'name': 'staging', 'promotion_settings': {'promotion_cleanup_strategy': None, 'ramp_up_duration_seconds': 600, 'ramp_up_while_promoting': True, 'redeploy_on_promotion': True, 'rolling_deploy': None, 'rolling_deploy_config': None}, 'chainlet_settings': [{'autoscaling_settings': {'autoscaling_window': 800, 'concurrency_target': 4, 'max_replica': 3, 'max_scale_down_rate': None, 'min_replica': 2, 'scale_down_delay': 63, 'target_in_flight_tokens': None, 'target_utilization_percentage': None}, 'chainlet_name': 'HelloWorld', 'instance_type_id': '2x8'}, {'autoscaling_settings': {'autoscaling_window': None, 'concurrency_target': None, 'max_replica': 3, 'max_scale_down_rate': None, 'min_replica': 3, 'scale_down_delay': None, 'target_in_flight_tokens': None, 'target_utilization_percentage': None}, 'chainlet_name': 'RandInt', 'instance_type_id': 'A10Gx8x32'}]}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}/environments\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'name': 'staging', 'promotion_settings': {'promotion_cleanup_strategy': None, 'ramp_up_duration_seconds': 600, 'ramp_up_while_promoting': True, 'redeploy_on_promotion': True, 'rolling_deploy': None, 'rolling_deploy_config': None}, 'chainlet_settings': [{'autoscaling_settings': {'autoscaling_window': 800, 'concurrency_target': 4, 'max_replica': 3, 'max_scale_down_rate': None, 'min_replica': 2, 'scale_down_delay': 63, 'target_in_flight_tokens': None, 'target_utilization_percentage': None}, 'chainlet_name': 'HelloWorld', 'instance_type_id': '2x8'}, {'autoscaling_settings': {'autoscaling_window': None, 'concurrency_target': None, 'max_replica': 3, 'max_scale_down_rate': None, 'min_replica': 3, 'scale_down_delay': None, 'target_in_flight_tokens': None, 'target_utilization_percentage': None}, 'chainlet_name': 'RandInt', 'instance_type_id': 'A10Gx8x32'}]}\n)\n\nprint(response.text)" } ], "description": "Creates a chain environment. Returns the resulting environment.", @@ -5054,11 +5054,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/chains/{chain_id}/environments/{env_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/chains/{chain_id}/environments/{env_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/chains/{chain_id}/environments/{env_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}/environments/{env_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Gets a chain environment's details and returns the chain environment.", @@ -5088,11 +5088,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request PATCH \\\n--url https://api.staging.baseten.co/v1/chains/{chain_id}/environments/{env_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"promotion_settings\": {\n \"promotion_cleanup_strategy\": null,\n \"ramp_up_duration_seconds\": 600,\n \"ramp_up_while_promoting\": true,\n \"redeploy_on_promotion\": null,\n \"rolling_deploy\": null,\n \"rolling_deploy_config\": null\n }\n}'" + "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/chains/{chain_id}/environments/{env_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"promotion_settings\": {\n \"promotion_cleanup_strategy\": null,\n \"ramp_up_duration_seconds\": 600,\n \"ramp_up_while_promoting\": true,\n \"redeploy_on_promotion\": null,\n \"rolling_deploy\": null,\n \"rolling_deploy_config\": null\n }\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/chains/{chain_id}/environments/{env_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'promotion_settings': {'promotion_cleanup_strategy': None, 'ramp_up_duration_seconds': 600, 'ramp_up_while_promoting': True, 'redeploy_on_promotion': None, 'rolling_deploy': None, 'rolling_deploy_config': None}}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}/environments/{env_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'promotion_settings': {'promotion_cleanup_strategy': None, 'ramp_up_duration_seconds': 600, 'ramp_up_while_promoting': True, 'redeploy_on_promotion': None, 'rolling_deploy': None, 'rolling_deploy_config': None}}\n)\n\nprint(response.text)" } ], "description": "Updates a chain environment's settings and returns the chain environment.", @@ -5126,11 +5126,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/chains/{chain_id}/environments/{env_name}/promote \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"scale_down_previous_deployment\": true,\n \"deployment_id\": null\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/chains/{chain_id}/environments/{env_name}/promote \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"scale_down_previous_deployment\": true,\n \"deployment_id\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/chains/{chain_id}/environments/{env_name}/promote\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'scale_down_previous_deployment': True, 'deployment_id': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}/environments/{env_name}/promote\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'scale_down_previous_deployment': True, 'deployment_id': None}\n)\n\nprint(response.text)" } ], "description": "Promotes an existing chain deployment to an environment and returns the promoted chain deployment.", @@ -5172,11 +5172,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request PATCH \\\n--url https://api.staging.baseten.co/v1/chains/{chain_id}/environments/{env_name}/chainlet_settings/autoscaling_settings \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"updates\": [\n {\n \"autoscaling_settings\": {\n \"autoscaling_window\": 800,\n \"concurrency_target\": 4,\n \"max_replica\": 3,\n \"max_scale_down_rate\": null,\n \"min_replica\": 2,\n \"scale_down_delay\": 63,\n \"target_in_flight_tokens\": null,\n \"target_utilization_percentage\": null\n },\n \"chainlet_name\": \"HelloWorld\"\n }\n ]\n}'" + "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/chains/{chain_id}/environments/{env_name}/chainlet_settings/autoscaling_settings \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"updates\": [\n {\n \"autoscaling_settings\": {\n \"autoscaling_window\": 800,\n \"concurrency_target\": 4,\n \"max_replica\": 3,\n \"max_scale_down_rate\": null,\n \"min_replica\": 2,\n \"scale_down_delay\": 63,\n \"target_in_flight_tokens\": null,\n \"target_utilization_percentage\": null\n },\n \"chainlet_name\": \"HelloWorld\"\n }\n ]\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/chains/{chain_id}/environments/{env_name}/chainlet_settings/autoscaling_settings\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'updates': [{'autoscaling_settings': {'autoscaling_window': 800, 'concurrency_target': 4, 'max_replica': 3, 'max_scale_down_rate': None, 'min_replica': 2, 'scale_down_delay': 63, 'target_in_flight_tokens': None, 'target_utilization_percentage': None}, 'chainlet_name': 'HelloWorld'}]}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}/environments/{env_name}/chainlet_settings/autoscaling_settings\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'updates': [{'autoscaling_settings': {'autoscaling_window': 800, 'concurrency_target': 4, 'max_replica': 3, 'max_scale_down_rate': None, 'min_replica': 2, 'scale_down_delay': 63, 'target_in_flight_tokens': None, 'target_utilization_percentage': None}, 'chainlet_name': 'HelloWorld'}]}\n)\n\nprint(response.text)" } ], "description": "Updates a chainlet environment's autoscaling settings and returns the updated chainlet environment settings.", @@ -5218,11 +5218,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/chains/{chain_id}/environments/{env_name}/chainlet_settings/instance_types/update \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"updates\": [\n {\n \"chainlet_name\": \"HelloWorld\",\n \"instance_type_id\": \"1x4\"\n },\n {\n \"chainlet_name\": \"RandInt\",\n \"instance_type_id\": \"A10G:2x24x96\"\n }\n ]\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/chains/{chain_id}/environments/{env_name}/chainlet_settings/instance_types/update \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"updates\": [\n {\n \"chainlet_name\": \"HelloWorld\",\n \"instance_type_id\": \"1x4\"\n },\n {\n \"chainlet_name\": \"RandInt\",\n \"instance_type_id\": \"A10G:2x24x96\"\n }\n ]\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/chains/{chain_id}/environments/{env_name}/chainlet_settings/instance_types/update\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'updates': [{'chainlet_name': 'HelloWorld', 'instance_type_id': '1x4'}, {'chainlet_name': 'RandInt', 'instance_type_id': 'A10G:2x24x96'}]}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/chains/{chain_id}/environments/{env_name}/chainlet_settings/instance_types/update\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'updates': [{'chainlet_name': 'HelloWorld', 'instance_type_id': '1x4'}, {'chainlet_name': 'RandInt', 'instance_type_id': 'A10G:2x24x96'}]}\n)\n\nprint(response.text)" } ], "description": "Updates a chainlet environment's instance type settings. The chainlet environment setting must exist. When updated, a new chain deployment is created and deployed. It is promoted to the chain environment according to promotion settings on the environment.", @@ -5264,11 +5264,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/teams/{team_id}/training_projects \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"training_project\": {\n \"name\": \"My Training Project\"\n }\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/teams/{team_id}/training_projects \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"training_project\": {\n \"name\": \"My Training Project\"\n }\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/teams/{team_id}/training_projects\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'training_project': {'name': 'My Training Project'}}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}/training_projects\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'training_project': {'name': 'My Training Project'}}\n)\n\nprint(response.text)" } ], "description": "Upserts a training project with the specified metadata for a team.", @@ -5307,11 +5307,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/training_projects \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/training_projects \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/training_projects\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Lists all training projects for the organization.", @@ -5333,11 +5333,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/training_projects \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"training_project\": {\n \"name\": \"My Training Project\"\n }\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/training_projects \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"training_project\": {\n \"name\": \"My Training Project\"\n }\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/training_projects\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'training_project': {'name': 'My Training Project'}}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'training_project': {'name': 'My Training Project'}}\n)\n\nprint(response.text)" } ], "description": "Upserts a training project with the specified metadata.", @@ -5371,11 +5371,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Lists all training jobs for the training project.", @@ -5402,11 +5402,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"training_job\": {\n \"image\": {\n \"base_image\": \"hello-world\",\n \"docker_auth\": null\n },\n \"compute\": {\n \"node_count\": 1,\n \"cpu_count\": 1,\n \"memory\": \"2Gi\",\n \"accelerator\": {\n \"accelerator\": \"H100\",\n \"count\": 2\n },\n \"availability_model\": \"spot\"\n },\n \"runtime\": {\n \"start_commands\": [\n \"python main.py\"\n ],\n \"environment_variables\": {\n \"API_KEY\": \"your_api_key_here\",\n \"PATH\": \"/usr/bin\"\n },\n \"enable_cache\": true,\n \"cache_config\": {\n \"enable_legacy_hf_mount\": true,\n \"enabled\": true,\n \"mount_base_path\": \"/root/.cache\",\n \"require_cache_affinity\": true\n },\n \"checkpointing_config\": {\n \"enabled\": true,\n \"checkpoint_path\": \"/mnt/ckpts\",\n \"volume_size_gib\": 10\n },\n \"load_checkpoint_config\": null\n },\n \"name\": \"gpt-oss-job\",\n \"truss_user_env\": null,\n \"interactive_session\": null,\n \"weights\": [\n {\n \"allow_patterns\": null,\n \"auth\": null,\n \"auth_secret_name\": null,\n \"ignore_patterns\": null,\n \"mount_location\": \"/app/models/base\",\n \"source\": \"hf://meta-llama/Llama-3-8B@main\"\n }\n ],\n \"enable_baseten_workdir\": false,\n \"priority\": 0\n }\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"training_job\": {\n \"image\": {\n \"base_image\": \"hello-world\",\n \"docker_auth\": null\n },\n \"compute\": {\n \"node_count\": 1,\n \"cpu_count\": 1,\n \"memory\": \"2Gi\",\n \"accelerator\": {\n \"accelerator\": \"H100\",\n \"count\": 2\n },\n \"availability_model\": \"spot\"\n },\n \"runtime\": {\n \"start_commands\": [\n \"python main.py\"\n ],\n \"environment_variables\": {\n \"API_KEY\": \"your_api_key_here\",\n \"PATH\": \"/usr/bin\"\n },\n \"enable_cache\": true,\n \"cache_config\": {\n \"enable_legacy_hf_mount\": true,\n \"enabled\": true,\n \"mount_base_path\": \"/root/.cache\",\n \"require_cache_affinity\": true\n },\n \"checkpointing_config\": {\n \"enabled\": true,\n \"checkpoint_path\": \"/mnt/ckpts\",\n \"volume_size_gib\": 10\n },\n \"load_checkpoint_config\": null\n },\n \"name\": \"gpt-oss-job\",\n \"truss_user_env\": null,\n \"interactive_session\": null,\n \"weights\": [\n {\n \"allow_patterns\": null,\n \"auth\": null,\n \"auth_secret_name\": null,\n \"ignore_patterns\": null,\n \"mount_location\": \"/app/models/base\",\n \"source\": \"hf://meta-llama/Llama-3-8B@main\"\n }\n ],\n \"enable_baseten_workdir\": false,\n \"priority\": 0\n }\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'training_job': {'image': {'base_image': 'hello-world', 'docker_auth': None}, 'compute': {'node_count': 1, 'cpu_count': 1, 'memory': '2Gi', 'accelerator': {'accelerator': 'H100', 'count': 2}, 'availability_model': 'spot'}, 'runtime': {'start_commands': ['python main.py'], 'environment_variables': {'API_KEY': 'your_api_key_here', 'PATH': '/usr/bin'}, 'enable_cache': True, 'cache_config': {'enable_legacy_hf_mount': True, 'enabled': True, 'mount_base_path': '/root/.cache', 'require_cache_affinity': True}, 'checkpointing_config': {'enabled': True, 'checkpoint_path': '/mnt/ckpts', 'volume_size_gib': 10}, 'load_checkpoint_config': None}, 'name': 'gpt-oss-job', 'truss_user_env': None, 'interactive_session': None, 'weights': [{'allow_patterns': None, 'auth': None, 'auth_secret_name': None, 'ignore_patterns': None, 'mount_location': '/app/models/base', 'source': 'hf://meta-llama/Llama-3-8B@main'}], 'enable_baseten_workdir': False, 'priority': 0}}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'training_job': {'image': {'base_image': 'hello-world', 'docker_auth': None}, 'compute': {'node_count': 1, 'cpu_count': 1, 'memory': '2Gi', 'accelerator': {'accelerator': 'H100', 'count': 2}, 'availability_model': 'spot'}, 'runtime': {'start_commands': ['python main.py'], 'environment_variables': {'API_KEY': 'your_api_key_here', 'PATH': '/usr/bin'}, 'enable_cache': True, 'cache_config': {'enable_legacy_hf_mount': True, 'enabled': True, 'mount_base_path': '/root/.cache', 'require_cache_affinity': True}, 'checkpointing_config': {'enabled': True, 'checkpoint_path': '/mnt/ckpts', 'volume_size_gib': 10}, 'load_checkpoint_config': None}, 'name': 'gpt-oss-job', 'truss_user_env': None, 'interactive_session': None, 'weights': [{'allow_patterns': None, 'auth': None, 'auth_secret_name': None, 'ignore_patterns': None, 'mount_location': '/app/models/base', 'source': 'hf://meta-llama/Llama-3-8B@main'}], 'enable_baseten_workdir': False, 'priority': 0}}\n)\n\nprint(response.text)" } ], "description": "Creates a training job with the specified configuration.", @@ -5440,11 +5440,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request DELETE \\\n--url https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Deletes a training job. Stops it first if still running.", @@ -5474,11 +5474,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Gets the details of an existing training job.", @@ -5500,11 +5500,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request PATCH \\\n--url https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"priority\": 0,\n \"availability_model\": \"spot\"\n}'" + "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"priority\": 0,\n \"availability_model\": \"spot\"\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'priority': 0, 'availability_model': 'spot'}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'priority': 0, 'availability_model': 'spot'}\n)\n\nprint(response.text)" } ], "description": "Updates mutable fields on a PENDING training job: the queue priority (higher priorities are dequeued first) and the availability model (dedicated or spot capacity). Changes take effect on the next queue evaluation, which is triggered immediately.", @@ -5538,11 +5538,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/download \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/download \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/download\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/download\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Returns presigned S3 URLs for the artifacts uploaded by a training job.", @@ -5574,11 +5574,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/recreate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/recreate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/recreate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/recreate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Creates a new training job with the same configuration as an existing training job.", @@ -5610,11 +5610,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/logs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/logs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/logs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'start_epoch_millis': None, 'end_epoch_millis': None, 'direction': None, 'limit': None, 'min_level': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/logs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'start_epoch_millis': None, 'end_epoch_millis': None, 'direction': None, 'limit': None, 'min_level': None}\n)\n\nprint(response.text)" } ], "description": "Gets the logs for a training job with the provided filters.", @@ -5736,11 +5736,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/logs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"start_epoch_millis\": null,\n \"end_epoch_millis\": null,\n \"direction\": null,\n \"limit\": null,\n \"min_level\": null\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/logs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"start_epoch_millis\": null,\n \"end_epoch_millis\": null,\n \"direction\": null,\n \"limit\": null,\n \"min_level\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/logs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'start_epoch_millis': None, 'end_epoch_millis': None, 'direction': None, 'limit': None, 'min_level': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/logs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'start_epoch_millis': None, 'end_epoch_millis': None, 'direction': None, 'limit': None, 'min_level': None}\n)\n\nprint(response.text)" } ], "description": "Use the GET form on this path instead.", @@ -5776,11 +5776,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/metrics \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/metrics \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/metrics\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'end_epoch_millis': None, 'start_epoch_millis': None, 'step_seconds': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/metrics\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'end_epoch_millis': None, 'start_epoch_millis': None, 'step_seconds': None}\n)\n\nprint(response.text)" } ], "description": "Gets the metrics for a training job.", @@ -5866,11 +5866,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/metrics \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"end_epoch_millis\": null,\n \"start_epoch_millis\": null,\n \"step_seconds\": null\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/metrics \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"end_epoch_millis\": null,\n \"start_epoch_millis\": null,\n \"step_seconds\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/metrics\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'end_epoch_millis': None, 'start_epoch_millis': None, 'step_seconds': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/metrics\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'end_epoch_millis': None, 'start_epoch_millis': None, 'step_seconds': None}\n)\n\nprint(response.text)" } ], "description": "Use the GET form on this path instead.", @@ -5906,11 +5906,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/stop \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/stop \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/stop\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/stop\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Stops a training job.", @@ -5952,11 +5952,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/checkpoints \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/checkpoints \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/checkpoints\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/checkpoints\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Gets the checkpoints for a training job.", @@ -5988,11 +5988,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/checkpoint_files \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/checkpoint_files \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/checkpoint_files\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/checkpoint_files\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={}\n)\n\nprint(response.text)" } ], "description": "Gets presigned URLs for all checkpoint files for a training job.", @@ -6050,11 +6050,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/auth_codes \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/auth_codes \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/auth_codes\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/auth_codes\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Gets authentication codes for all nodes of a training job's interactive sessions.", @@ -6086,11 +6086,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request PATCH \\\n--url https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/interactive_sessions/{session_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"timeout_minutes\": null,\n \"trigger\": null\n}'" + "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/interactive_sessions/{session_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"timeout_minutes\": null,\n \"trigger\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/interactive_sessions/{session_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'timeout_minutes': None, 'trigger': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/interactive_sessions/{session_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'timeout_minutes': None, 'trigger': None}\n)\n\nprint(response.text)" } ], "description": "Updates specific fields on a training job's interactive session. Only provided (non-null) fields are updated.", @@ -6135,11 +6135,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/ssh/sign \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"public_key\": null,\n \"replica_id\": null\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/ssh/sign \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"public_key\": null,\n \"replica_id\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/ssh/sign\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'public_key': None, 'replica_id': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/jobs/{training_job_id}/ssh/sign\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'public_key': None, 'replica_id': None}\n)\n\nprint(response.text)" } ], "description": "Signs a short-lived SSH certificate granting access to a specific training job pod. Returns the signed SSH certificate, a JWT token for SSH proxy authentication, the proxy address to connect through, and the certificate expiry time.", @@ -6181,11 +6181,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/training_projects/{training_project_id}/cache/summary \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id}/cache/summary \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/training_projects/{training_project_id}/cache/summary\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}/cache/summary\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Gets the cache summary for the most recent training job in the project.", @@ -6214,11 +6214,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request DELETE \\\n--url https://api.staging.baseten.co/v1/training_projects/{training_project_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/training_projects/{training_project_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Deletes a training project and all associated training jobs.", @@ -6245,11 +6245,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/training_projects/{training_project_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/training_projects/{training_project_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/training_projects/{training_project_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_projects/{training_project_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Gets the details of an existing training project.", @@ -6273,11 +6273,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/training_jobs/search \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"project_id\": \"n4q95w5\",\n \"job_id\": \"p7qr9qv\",\n \"statuses\": [\n \"TRAINING_JOB_RUNNING\",\n \"TRAINING_JOB_COMPLETED\"\n ]\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/training_jobs/search \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"project_id\": \"n4q95w5\",\n \"job_id\": \"p7qr9qv\",\n \"statuses\": [\n \"TRAINING_JOB_RUNNING\",\n \"TRAINING_JOB_COMPLETED\"\n ]\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/training_jobs/search\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'project_id': 'n4q95w5', 'job_id': 'p7qr9qv', 'statuses': ['TRAINING_JOB_RUNNING', 'TRAINING_JOB_COMPLETED']}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training_jobs/search\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'project_id': 'n4q95w5', 'job_id': 'p7qr9qv', 'statuses': ['TRAINING_JOB_RUNNING', 'TRAINING_JOB_COMPLETED']}\n)\n\nprint(response.text)" } ], "description": "Searches training jobs for the organization.", @@ -6311,11 +6311,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/loops/capabilities \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/loops/capabilities \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/loops/capabilities\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'model': 'Qwen/Qwen3-8B', 'use_case': 'rl', 'max_seq_len': 32768}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/capabilities\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'model': 'Qwen/Qwen3-8B', 'use_case': 'rl', 'max_seq_len': 32768}\n)\n\nprint(response.text)" } ], "description": "Returns the list of models supported by the Loops server, including each model's maximum context length and whether it supports vision-language inputs. Each entry carries an 'enabled' flag saying whether this workspace can run it now, and 'enablement_details' explaining why when it cannot; filter on 'enabled' for the usable set. Capacity is resolved when the run is created, not here. Pass ?model= to ask about one model \u2014 an empty list means Baseten does not support it. Pass ?use_case=sft for a run that needs no sampler, and ?max_seq_len= to check a specific sequence length.", @@ -6397,11 +6397,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/loops/sessions \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/loops/sessions \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/loops/sessions\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/sessions\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Creates a Loops session scoped to the calling org.", @@ -6425,11 +6425,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/loops/sessions/{session_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/loops/sessions/{session_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/loops/sessions/{session_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/sessions/{session_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Fetches a Loops session by ID.", @@ -6458,11 +6458,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/loops/runs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/loops/runs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/loops/runs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'run_id': 'k4q95w5', 'base_model': 'Qwen/Qwen3-8B', 'scope': 'org'}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/runs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'run_id': 'k4q95w5', 'base_model': 'Qwen/Qwen3-8B', 'scope': 'org'}\n)\n\nprint(response.text)" } ], "description": "Lists Loops runs visible to the requesting user, optionally filtered by run id and/or base model. Defaults to the caller's own runs; pass ?scope=org to list every run in the caller's organization.", @@ -6549,11 +6549,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/loops/runs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"session_id\": null,\n \"base_model\": null,\n \"name\": null,\n \"max_seq_len\": null,\n \"seed\": null,\n \"availability_model\": \"spot\",\n \"path\": \"bt://loops:k4q95w5/weights/step-100\",\n \"reuse_from_run_id\": null,\n \"reuse_from_session_id\": null\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/loops/runs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"session_id\": null,\n \"base_model\": null,\n \"name\": null,\n \"max_seq_len\": null,\n \"seed\": null,\n \"availability_model\": \"spot\",\n \"path\": \"bt://loops:k4q95w5/weights/step-100\",\n \"reuse_from_run_id\": null,\n \"reuse_from_session_id\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/loops/runs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'session_id': None, 'base_model': None, 'name': None, 'max_seq_len': None, 'seed': None, 'availability_model': 'spot', 'path': 'bt://loops:k4q95w5/weights/step-100', 'reuse_from_run_id': None, 'reuse_from_session_id': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/runs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'session_id': None, 'base_model': None, 'name': None, 'max_seq_len': None, 'seed': None, 'availability_model': 'spot', 'path': 'bt://loops:k4q95w5/weights/step-100', 'reuse_from_run_id': None, 'reuse_from_session_id': None}\n)\n\nprint(response.text)" } ], "description": "Creates a Loops run with an associated sampler in the given session.", @@ -6587,11 +6587,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/loops/runs/{run_id}/deactivate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/loops/runs/{run_id}/deactivate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/loops/runs/{run_id}/deactivate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/runs/{run_id}/deactivate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Shuts down a Loops run by ID, tearing down both the run and its paired sampler. Saved checkpoints remain accessible.", @@ -6620,11 +6620,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/loops/runs/{run_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/loops/runs/{run_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/loops/runs/{run_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/runs/{run_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Fetches a Loops run by ID.", @@ -6653,11 +6653,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/loops/trainers \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"session_id\": null,\n \"base_model\": null,\n \"name\": null,\n \"max_seq_len\": null,\n \"seed\": null,\n \"availability_model\": \"spot\",\n \"path\": \"bt://loops:k4q95w5/weights/step-100\",\n \"reuse_from_run_id\": null,\n \"reuse_from_session_id\": null\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/loops/trainers \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"session_id\": null,\n \"base_model\": null,\n \"name\": null,\n \"max_seq_len\": null,\n \"seed\": null,\n \"availability_model\": \"spot\",\n \"path\": \"bt://loops:k4q95w5/weights/step-100\",\n \"reuse_from_run_id\": null,\n \"reuse_from_session_id\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/loops/trainers\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'session_id': None, 'base_model': None, 'name': None, 'max_seq_len': None, 'seed': None, 'availability_model': 'spot', 'path': 'bt://loops:k4q95w5/weights/step-100', 'reuse_from_run_id': None, 'reuse_from_session_id': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/trainers\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'session_id': None, 'base_model': None, 'name': None, 'max_seq_len': None, 'seed': None, 'availability_model': 'spot', 'path': 'bt://loops:k4q95w5/weights/step-100', 'reuse_from_run_id': None, 'reuse_from_session_id': None}\n)\n\nprint(response.text)" } ], "description": "Creates a trainer-only Loops run in the given session, without a sampler. To sample from it, create a sampler with POST /v1/loops/samplers and pass this run's ID as run_id to pair the two. List and read the trainer through the /v1/loops/runs endpoints.", @@ -6691,11 +6691,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/loops/samplers \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/loops/samplers \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/loops/samplers\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'scope': 'org'}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/samplers\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'scope': 'org'}\n)\n\nprint(response.text)" } ], "description": "Lists Loops samplers (paired and standalone). Defaults to the caller's own; pass ?scope=org to list every sampler in the caller's organization.", @@ -6740,11 +6740,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/loops/samplers \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"availability_model\": null,\n \"session_id\": null,\n \"base_model\": null,\n \"run_id\": null,\n \"max_seq_length\": null,\n \"model_path\": \"bt://loops:k4q95w5/sampler_weights/step-100\",\n \"reuse_from_session_id\": null\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/loops/samplers \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"availability_model\": null,\n \"session_id\": null,\n \"base_model\": null,\n \"run_id\": null,\n \"max_seq_length\": null,\n \"model_path\": \"bt://loops:k4q95w5/sampler_weights/step-100\",\n \"reuse_from_session_id\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/loops/samplers\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'availability_model': None, 'session_id': None, 'base_model': None, 'run_id': None, 'max_seq_length': None, 'model_path': 'bt://loops:k4q95w5/sampler_weights/step-100', 'reuse_from_session_id': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/samplers\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'availability_model': None, 'session_id': None, 'base_model': None, 'run_id': None, 'max_seq_length': None, 'model_path': 'bt://loops:k4q95w5/sampler_weights/step-100', 'reuse_from_session_id': None}\n)\n\nprint(response.text)" } ], "description": "Creates a standalone Loops sampler not linked to a run.", @@ -6778,11 +6778,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/loops/samplers/{sampler_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/loops/samplers/{sampler_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/loops/samplers/{sampler_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/samplers/{sampler_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Fetches a Loops sampler by ID.", @@ -6811,11 +6811,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/loops/checkpoints \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/loops/checkpoints \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/loops/checkpoints\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'run_id': 'k4q95w5', 'base_model': 'Qwen/Qwen3-8B', 'checkpoint_path': 'bt://loops:k4q95w5/sampler_weights/step-100'}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/checkpoints\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'run_id': 'k4q95w5', 'base_model': 'Qwen/Qwen3-8B', 'checkpoint_path': 'bt://loops:k4q95w5/sampler_weights/step-100'}\n)\n\nprint(response.text)" } ], "description": "Lists Loops checkpoints filtered by run id, base model, or bt:// URI. Provide exactly one filter.", @@ -6904,11 +6904,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/loops/checkpoints/validate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"checkpoint_path\": \"bt://loops:k4q95w5/sampler_weights/step-100\"\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/loops/checkpoints/validate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"checkpoint_path\": \"bt://loops:k4q95w5/sampler_weights/step-100\"\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/loops/checkpoints/validate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'checkpoint_path': 'bt://loops:k4q95w5/sampler_weights/step-100'}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/checkpoints/validate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'checkpoint_path': 'bt://loops:k4q95w5/sampler_weights/step-100'}\n)\n\nprint(response.text)" } ], "description": "Returns whether the caller can manage and use this checkpoint.", @@ -6942,11 +6942,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/loops/checkpoints/{checkpoint_id}/files \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/loops/checkpoints/{checkpoint_id}/files \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/loops/checkpoints/{checkpoint_id}/files\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/checkpoints/{checkpoint_id}/files\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={}\n)\n\nprint(response.text)" } ], "description": "Gets presigned URLs for the files under a Loops checkpoint. Returns a paginated list.", @@ -7001,11 +7001,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/loops/checkpoints/{checkpoint_id}/source \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/loops/checkpoints/{checkpoint_id}/source \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/loops/checkpoints/{checkpoint_id}/source\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/checkpoints/{checkpoint_id}/source\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Reports how to fetch a checkpoint's files: `s3` when the files endpoint serves presigned URLs for it, or `volume` with the ref to pull. Clients that download checkpoints should ask here first.", @@ -7034,11 +7034,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/loops/deployments \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/loops/deployments \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/loops/deployments\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'scope': 'org'}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/deployments\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'scope': 'org'}\n)\n\nprint(response.text)" } ], "description": "Lists Loops deployments. Defaults to the caller's own; pass ?scope=org to list every deployment in the caller's organization. Returns every deployment regardless of status; clients filter terminal states.", @@ -7085,11 +7085,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/loops/deployments/{deployment_id}/deactivate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/loops/deployments/{deployment_id}/deactivate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/loops/deployments/{deployment_id}/deactivate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/deployments/{deployment_id}/deactivate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Shuts down a Loops deployment by ID. Saved checkpoints remain accessible. Resolving the base model to a deployment ID is the caller's responsibility: list deployments and pick the active one.", @@ -7118,11 +7118,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/loops/deployments/{deployment_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/loops/deployments/{deployment_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/loops/deployments/{deployment_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/deployments/{deployment_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Fetches a Loops deployment by ID, including its latest status.", @@ -7151,11 +7151,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/loops/deployments/{deployment_id}/debug_archive/files \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/loops/deployments/{deployment_id}/debug_archive/files \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/loops/deployments/{deployment_id}/debug_archive/files\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'page_token': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/deployments/{deployment_id}/debug_archive/files\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'page_token': None}\n)\n\nprint(response.text)" } ], "description": "Gets presigned download URLs for a Loops deployment's debug archive.", @@ -7217,11 +7217,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/loops/deployments/{deployment_id}/metrics \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"end_epoch_millis\": null,\n \"start_epoch_millis\": null,\n \"step_seconds\": null,\n \"time_divisor_seconds\": null\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/loops/deployments/{deployment_id}/metrics \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"end_epoch_millis\": null,\n \"start_epoch_millis\": null,\n \"step_seconds\": null,\n \"time_divisor_seconds\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/loops/deployments/{deployment_id}/metrics\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'end_epoch_millis': None, 'start_epoch_millis': None, 'step_seconds': None, 'time_divisor_seconds': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/deployments/{deployment_id}/metrics\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'end_epoch_millis': None, 'start_epoch_millis': None, 'step_seconds': None, 'time_divisor_seconds': None}\n)\n\nprint(response.text)" } ], "description": "Returns per-node GPU/CPU/memory utilization and Knative queue-proxy request rate / concurrency / latency for the trainer pods. The sampler half of a Loops deployment is an OracleVersion and uses the existing model-metrics endpoint.", @@ -7260,11 +7260,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/loops/deployments/{deployment_id}/logs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/loops/deployments/{deployment_id}/logs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/loops/deployments/{deployment_id}/logs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'start_epoch_millis': None, 'end_epoch_millis': None, 'direction': None, 'limit': None, 'min_level': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/deployments/{deployment_id}/logs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'start_epoch_millis': None, 'end_epoch_millis': None, 'direction': None, 'limit': None, 'min_level': None}\n)\n\nprint(response.text)" } ], "description": "Fetches logs from the trainer pods of a Loops deployment. Visible to any member of the deployment's team.", @@ -7385,11 +7385,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/teams/{team_id}/loops/sessions \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/teams/{team_id}/loops/sessions \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/teams/{team_id}/loops/sessions\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}/loops/sessions\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Creates a Loops session scoped to the calling org.", @@ -7418,11 +7418,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/teams/{team_id}/loops/runs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/teams/{team_id}/loops/runs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/teams/{team_id}/loops/runs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'run_id': 'k4q95w5', 'base_model': 'Qwen/Qwen3-8B', 'scope': 'org'}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}/loops/runs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'run_id': 'k4q95w5', 'base_model': 'Qwen/Qwen3-8B', 'scope': 'org'}\n)\n\nprint(response.text)" } ], "description": "Lists Loops runs in the given team, visible to the requesting user, optionally filtered by run id and/or base model.", @@ -7514,11 +7514,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/teams/{team_id}/loops/runs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"session_id\": null,\n \"base_model\": null,\n \"name\": null,\n \"max_seq_len\": null,\n \"seed\": null,\n \"availability_model\": \"spot\",\n \"path\": \"bt://loops:k4q95w5/weights/step-100\",\n \"reuse_from_run_id\": null,\n \"reuse_from_session_id\": null\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/teams/{team_id}/loops/runs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"session_id\": null,\n \"base_model\": null,\n \"name\": null,\n \"max_seq_len\": null,\n \"seed\": null,\n \"availability_model\": \"spot\",\n \"path\": \"bt://loops:k4q95w5/weights/step-100\",\n \"reuse_from_run_id\": null,\n \"reuse_from_session_id\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/teams/{team_id}/loops/runs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'session_id': None, 'base_model': None, 'name': None, 'max_seq_len': None, 'seed': None, 'availability_model': 'spot', 'path': 'bt://loops:k4q95w5/weights/step-100', 'reuse_from_run_id': None, 'reuse_from_session_id': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}/loops/runs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'session_id': None, 'base_model': None, 'name': None, 'max_seq_len': None, 'seed': None, 'availability_model': 'spot', 'path': 'bt://loops:k4q95w5/weights/step-100', 'reuse_from_run_id': None, 'reuse_from_session_id': None}\n)\n\nprint(response.text)" } ], "description": "Creates a Loops run with an associated sampler in the given session; the run's infrastructure belongs to the given team.", @@ -7552,11 +7552,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/teams/{team_id}/loops/trainers \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"session_id\": null,\n \"base_model\": null,\n \"name\": null,\n \"max_seq_len\": null,\n \"seed\": null,\n \"availability_model\": \"spot\",\n \"path\": \"bt://loops:k4q95w5/weights/step-100\",\n \"reuse_from_run_id\": null,\n \"reuse_from_session_id\": null\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/teams/{team_id}/loops/trainers \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"session_id\": null,\n \"base_model\": null,\n \"name\": null,\n \"max_seq_len\": null,\n \"seed\": null,\n \"availability_model\": \"spot\",\n \"path\": \"bt://loops:k4q95w5/weights/step-100\",\n \"reuse_from_run_id\": null,\n \"reuse_from_session_id\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/teams/{team_id}/loops/trainers\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'session_id': None, 'base_model': None, 'name': None, 'max_seq_len': None, 'seed': None, 'availability_model': 'spot', 'path': 'bt://loops:k4q95w5/weights/step-100', 'reuse_from_run_id': None, 'reuse_from_session_id': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}/loops/trainers\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'session_id': None, 'base_model': None, 'name': None, 'max_seq_len': None, 'seed': None, 'availability_model': 'spot', 'path': 'bt://loops:k4q95w5/weights/step-100', 'reuse_from_run_id': None, 'reuse_from_session_id': None}\n)\n\nprint(response.text)" } ], "description": "Creates a trainer-only Loops run in the given session, without a sampler. To sample from it, create a sampler with POST /v1/loops/samplers and pass this run's ID as run_id to pair the two. List and read the trainer through the /v1/loops/runs endpoints.", @@ -7595,11 +7595,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/teams/{team_id}/loops/samplers \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/teams/{team_id}/loops/samplers \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/teams/{team_id}/loops/samplers\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'scope': 'org'}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}/loops/samplers\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'scope': 'org'}\n)\n\nprint(response.text)" } ], "description": "Lists Loops samplers (paired and standalone) in the given team, visible to the requesting user. Defaults to the caller's own; pass ?scope=org to list every sampler in the team.", @@ -7649,11 +7649,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/teams/{team_id}/loops/samplers \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"availability_model\": null,\n \"session_id\": null,\n \"base_model\": null,\n \"run_id\": null,\n \"max_seq_length\": null,\n \"model_path\": \"bt://loops:k4q95w5/sampler_weights/step-100\",\n \"reuse_from_session_id\": null\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/teams/{team_id}/loops/samplers \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"availability_model\": null,\n \"session_id\": null,\n \"base_model\": null,\n \"run_id\": null,\n \"max_seq_length\": null,\n \"model_path\": \"bt://loops:k4q95w5/sampler_weights/step-100\",\n \"reuse_from_session_id\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/teams/{team_id}/loops/samplers\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'availability_model': None, 'session_id': None, 'base_model': None, 'run_id': None, 'max_seq_length': None, 'model_path': 'bt://loops:k4q95w5/sampler_weights/step-100', 'reuse_from_session_id': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}/loops/samplers\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'availability_model': None, 'session_id': None, 'base_model': None, 'run_id': None, 'max_seq_length': None, 'model_path': 'bt://loops:k4q95w5/sampler_weights/step-100', 'reuse_from_session_id': None}\n)\n\nprint(response.text)" } ], "description": "Creates a standalone Loops sampler not linked to a run; the sampler belongs to the given team.", @@ -7687,11 +7687,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/training/capacity \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/training/capacity \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/training/capacity\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training/capacity\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Returns GPU capacity limits (baseline and peak) and current usage for the organization.", @@ -7713,11 +7713,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request PATCH \\\n--url https://api.staging.baseten.co/v1/training/capacity \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"team_id\": null,\n \"gpu_type\": null,\n \"max_gpus\": 8\n}'" + "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/training/capacity \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"team_id\": null,\n \"gpu_type\": null,\n \"max_gpus\": 8\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/training/capacity\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'team_id': None, 'gpu_type': None, 'max_gpus': 8}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training/capacity\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'team_id': None, 'gpu_type': None, 'max_gpus': 8}\n)\n\nprint(response.text)" } ], "description": "Sets the max concurrent GPUs of a given type a team may use. Creates the limit if one doesn't exist for this (team, gpu_type) pair, otherwise updates it in place. Org-admin only: this is a ceiling the org imposes on the team, not something the team manages for itself.", @@ -7751,11 +7751,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/training/jobs/{training_job_id}/queue_context \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/training/jobs/{training_job_id}/queue_context \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/training/jobs/{training_job_id}/queue_context\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/training/jobs/{training_job_id}/queue_context\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Returns the (org, gpu_type) capacity pool the job was gated by, jobs that were holding GPU capacity in that pool when this job was submitted, and every TrainingJobStatus event in [submitted_at, released_at] for those jobs, useful for understanding why a job sat in PENDING. Caller must be an org admin and the job must belong to the caller's org.", @@ -7785,11 +7785,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/blobs/credentials/model \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/blobs/credentials/model \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/blobs/credentials/model\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/blobs/credentials/model\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "responses": { @@ -7812,11 +7812,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/blobs/credentials/train \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/blobs/credentials/train \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/blobs/credentials/train\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/blobs/credentials/train\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "responses": { @@ -7839,11 +7839,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/teams/{team_id}/api_keys \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"name\": \"my-api-key\",\n \"type\": \"PERSONAL\"\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/teams/{team_id}/api_keys \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"name\": \"my-api-key\",\n \"type\": \"PERSONAL\"\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/teams/{team_id}/api_keys\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'name': 'my-api-key', 'type': 'PERSONAL'}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}/api_keys\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'name': 'my-api-key', 'type': 'PERSONAL'}\n)\n\nprint(response.text)" } ], "description": "Creates a team API key with the provided name and type. The API key is returned in the response.", @@ -7882,11 +7882,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/api_keys \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/api_keys \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/api_keys\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'type': 'WORKSPACE_INVOKE'}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/api_keys\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'type': 'WORKSPACE_INVOKE'}\n)\n\nprint(response.text)" } ], "description": "Returns metadata for your personal API keys and the workspace and team API keys you can manage. Organization admins also receive every member's personal API keys, each with an owner identifying the member it belongs to.", @@ -7938,11 +7938,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/api_keys \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"name\": \"my-api-key\",\n \"type\": \"PERSONAL\"\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/api_keys \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"name\": \"my-api-key\",\n \"type\": \"PERSONAL\"\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/api_keys\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'name': 'my-api-key', 'type': 'PERSONAL'}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/api_keys\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'name': 'my-api-key', 'type': 'PERSONAL'}\n)\n\nprint(response.text)" } ], "description": "Creates an API key with the provided name and type. The API key is returned in the response.", @@ -7976,11 +7976,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request DELETE \\\n--url https://api.staging.baseten.co/v1/api_keys/{api_key_prefix} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/api_keys/{api_key_prefix} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/api_keys/{api_key_prefix}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/api_keys/{api_key_prefix}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Deletes an API key by prefix and returns info about the API key.", @@ -8009,11 +8009,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/model_apis \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/model_apis \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/model_apis\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'cursor': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/model_apis\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'cursor': None}\n)\n\nprint(response.text)" } ], "description": "Lists Model APIs visible to the caller. By default returns the full catalog; pass `added_only=true` to restrict to Model APIs the workspace has added.", @@ -8081,11 +8081,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/model_apis/usage \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/model_apis/usage \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/model_apis/usage\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'start_time': None, 'end_time': None, 'bucket_width': '1m', 'limit': None, 'cursor': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/model_apis/usage\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'start_time': None, 'end_time': None, 'bucket_width': '1m', 'limit': None, 'cursor': None}\n)\n\nprint(response.text)" } ], "description": "Returns your organization's Model APIs token usage as a series of contiguous time buckets, broken down by the dimensions you pass in group_by. Buckets with no usage are included, so the series has no gaps. Usage is retained for 92 days, so buckets older than that are returned with no results.", @@ -8247,11 +8247,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/model_apis/{model_api_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/model_apis/{model_api_name} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/model_apis/{model_api_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/model_apis/{model_api_name}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Fetches a Model API by name, with workspace overlay when added.", @@ -8280,11 +8280,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/llm_models \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"resources\": null,\n \"region\": null,\n \"llm_version\": null,\n \"model_metadata\": null,\n \"autoscaling_settings\": {\n \"autoscaling_window\": 600,\n \"concurrency_target\": null,\n \"max_replica\": 5,\n \"max_scale_down_rate\": null,\n \"min_replica\": 1,\n \"scale_down_delay\": 300,\n \"target_in_flight_tokens\": null,\n \"target_utilization_percentage\": null\n },\n \"additional_autoscaling_config\": {\n \"metrics\": [\n {\n \"name\": \"in_flight_tokens\",\n \"target\": 40000\n }\n ]\n },\n \"metadata\": {\n \"environment\": \"production\",\n \"git_sha\": \"abc123\"\n },\n \"weights\": [\n {\n \"mount_location\": \"/models/base\",\n \"source\": \"hf://meta-llama/Llama-3-8B\"\n }\n ],\n \"name\": null\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/llm_models \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"resources\": null,\n \"region\": null,\n \"llm_version\": null,\n \"model_metadata\": null,\n \"autoscaling_settings\": {\n \"autoscaling_window\": 600,\n \"concurrency_target\": null,\n \"max_replica\": 5,\n \"max_scale_down_rate\": null,\n \"min_replica\": 1,\n \"scale_down_delay\": 300,\n \"target_in_flight_tokens\": null,\n \"target_utilization_percentage\": null\n },\n \"additional_autoscaling_config\": {\n \"metrics\": [\n {\n \"name\": \"in_flight_tokens\",\n \"target\": 40000\n }\n ]\n },\n \"metadata\": {\n \"environment\": \"production\",\n \"git_sha\": \"abc123\"\n },\n \"weights\": [\n {\n \"mount_location\": \"/models/base\",\n \"source\": \"hf://meta-llama/Llama-3-8B\"\n }\n ],\n \"name\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/llm_models\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'resources': None, 'region': None, 'llm_version': None, 'model_metadata': None, 'autoscaling_settings': {'autoscaling_window': 600, 'concurrency_target': None, 'max_replica': 5, 'max_scale_down_rate': None, 'min_replica': 1, 'scale_down_delay': 300, 'target_in_flight_tokens': None, 'target_utilization_percentage': None}, 'additional_autoscaling_config': {'metrics': [{'name': 'in_flight_tokens', 'target': 40000}]}, 'metadata': {'environment': 'production', 'git_sha': 'abc123'}, 'weights': [{'mount_location': '/models/base', 'source': 'hf://meta-llama/Llama-3-8B'}], 'name': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/llm_models\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'resources': None, 'region': None, 'llm_version': None, 'model_metadata': None, 'autoscaling_settings': {'autoscaling_window': 600, 'concurrency_target': None, 'max_replica': 5, 'max_scale_down_rate': None, 'min_replica': 1, 'scale_down_delay': 300, 'target_in_flight_tokens': None, 'target_utilization_percentage': None}, 'additional_autoscaling_config': {'metrics': [{'name': 'in_flight_tokens', 'target': 40000}]}, 'metadata': {'environment': 'production', 'git_sha': 'abc123'}, 'weights': [{'mount_location': '/models/base', 'source': 'hf://meta-llama/Llama-3-8B'}], 'name': None}\n)\n\nprint(response.text)" } ], "requestBody": { @@ -8317,11 +8317,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/teams/{team_id}/llm_models \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"resources\": null,\n \"region\": null,\n \"llm_version\": null,\n \"model_metadata\": null,\n \"autoscaling_settings\": {\n \"autoscaling_window\": 600,\n \"concurrency_target\": null,\n \"max_replica\": 5,\n \"max_scale_down_rate\": null,\n \"min_replica\": 1,\n \"scale_down_delay\": 300,\n \"target_in_flight_tokens\": null,\n \"target_utilization_percentage\": null\n },\n \"additional_autoscaling_config\": {\n \"metrics\": [\n {\n \"name\": \"in_flight_tokens\",\n \"target\": 40000\n }\n ]\n },\n \"metadata\": {\n \"environment\": \"production\",\n \"git_sha\": \"abc123\"\n },\n \"weights\": [\n {\n \"mount_location\": \"/models/base\",\n \"source\": \"hf://meta-llama/Llama-3-8B\"\n }\n ],\n \"name\": null\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/teams/{team_id}/llm_models \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"resources\": null,\n \"region\": null,\n \"llm_version\": null,\n \"model_metadata\": null,\n \"autoscaling_settings\": {\n \"autoscaling_window\": 600,\n \"concurrency_target\": null,\n \"max_replica\": 5,\n \"max_scale_down_rate\": null,\n \"min_replica\": 1,\n \"scale_down_delay\": 300,\n \"target_in_flight_tokens\": null,\n \"target_utilization_percentage\": null\n },\n \"additional_autoscaling_config\": {\n \"metrics\": [\n {\n \"name\": \"in_flight_tokens\",\n \"target\": 40000\n }\n ]\n },\n \"metadata\": {\n \"environment\": \"production\",\n \"git_sha\": \"abc123\"\n },\n \"weights\": [\n {\n \"mount_location\": \"/models/base\",\n \"source\": \"hf://meta-llama/Llama-3-8B\"\n }\n ],\n \"name\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/teams/{team_id}/llm_models\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'resources': None, 'region': None, 'llm_version': None, 'model_metadata': None, 'autoscaling_settings': {'autoscaling_window': 600, 'concurrency_target': None, 'max_replica': 5, 'max_scale_down_rate': None, 'min_replica': 1, 'scale_down_delay': 300, 'target_in_flight_tokens': None, 'target_utilization_percentage': None}, 'additional_autoscaling_config': {'metrics': [{'name': 'in_flight_tokens', 'target': 40000}]}, 'metadata': {'environment': 'production', 'git_sha': 'abc123'}, 'weights': [{'mount_location': '/models/base', 'source': 'hf://meta-llama/Llama-3-8B'}], 'name': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/teams/{team_id}/llm_models\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'resources': None, 'region': None, 'llm_version': None, 'model_metadata': None, 'autoscaling_settings': {'autoscaling_window': 600, 'concurrency_target': None, 'max_replica': 5, 'max_scale_down_rate': None, 'min_replica': 1, 'scale_down_delay': 300, 'target_in_flight_tokens': None, 'target_utilization_percentage': None}, 'additional_autoscaling_config': {'metrics': [{'name': 'in_flight_tokens', 'target': 40000}]}, 'metadata': {'environment': 'production', 'git_sha': 'abc123'}, 'weights': [{'mount_location': '/models/base', 'source': 'hf://meta-llama/Llama-3-8B'}], 'name': None}\n)\n\nprint(response.text)" } ], "requestBody": { @@ -8359,11 +8359,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/llm_models/{model_id}/deployments \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"resources\": null,\n \"region\": null,\n \"llm_version\": null,\n \"model_metadata\": null,\n \"autoscaling_settings\": {\n \"autoscaling_window\": 600,\n \"concurrency_target\": null,\n \"max_replica\": 5,\n \"max_scale_down_rate\": null,\n \"min_replica\": 1,\n \"scale_down_delay\": 300,\n \"target_in_flight_tokens\": null,\n \"target_utilization_percentage\": null\n },\n \"additional_autoscaling_config\": {\n \"metrics\": [\n {\n \"name\": \"in_flight_tokens\",\n \"target\": 40000\n }\n ]\n },\n \"metadata\": {\n \"environment\": \"production\",\n \"git_sha\": \"abc123\"\n },\n \"weights\": [\n {\n \"mount_location\": \"/models/base\",\n \"source\": \"hf://meta-llama/Llama-3-8B\"\n }\n ]\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/llm_models/{model_id}/deployments \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"resources\": null,\n \"region\": null,\n \"llm_version\": null,\n \"model_metadata\": null,\n \"autoscaling_settings\": {\n \"autoscaling_window\": 600,\n \"concurrency_target\": null,\n \"max_replica\": 5,\n \"max_scale_down_rate\": null,\n \"min_replica\": 1,\n \"scale_down_delay\": 300,\n \"target_in_flight_tokens\": null,\n \"target_utilization_percentage\": null\n },\n \"additional_autoscaling_config\": {\n \"metrics\": [\n {\n \"name\": \"in_flight_tokens\",\n \"target\": 40000\n }\n ]\n },\n \"metadata\": {\n \"environment\": \"production\",\n \"git_sha\": \"abc123\"\n },\n \"weights\": [\n {\n \"mount_location\": \"/models/base\",\n \"source\": \"hf://meta-llama/Llama-3-8B\"\n }\n ]\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/llm_models/{model_id}/deployments\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'resources': None, 'region': None, 'llm_version': None, 'model_metadata': None, 'autoscaling_settings': {'autoscaling_window': 600, 'concurrency_target': None, 'max_replica': 5, 'max_scale_down_rate': None, 'min_replica': 1, 'scale_down_delay': 300, 'target_in_flight_tokens': None, 'target_utilization_percentage': None}, 'additional_autoscaling_config': {'metrics': [{'name': 'in_flight_tokens', 'target': 40000}]}, 'metadata': {'environment': 'production', 'git_sha': 'abc123'}, 'weights': [{'mount_location': '/models/base', 'source': 'hf://meta-llama/Llama-3-8B'}]}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/llm_models/{model_id}/deployments\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'resources': None, 'region': None, 'llm_version': None, 'model_metadata': None, 'autoscaling_settings': {'autoscaling_window': 600, 'concurrency_target': None, 'max_replica': 5, 'max_scale_down_rate': None, 'min_replica': 1, 'scale_down_delay': 300, 'target_in_flight_tokens': None, 'target_utilization_percentage': None}, 'additional_autoscaling_config': {'metrics': [{'name': 'in_flight_tokens', 'target': 40000}]}, 'metadata': {'environment': 'production', 'git_sha': 'abc123'}, 'weights': [{'mount_location': '/models/base', 'source': 'hf://meta-llama/Llama-3-8B'}]}\n)\n\nprint(response.text)" } ], "requestBody": { @@ -8401,11 +8401,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/library_listings \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/library_listings \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/library_listings\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/library_listings\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Returns all library listings for the authenticated user's organization.", @@ -8427,11 +8427,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/library_listings \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"display_name\": null,\n \"user_defined_id\": null\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/library_listings \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"display_name\": null,\n \"user_defined_id\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/library_listings\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'display_name': None, 'user_defined_id': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/library_listings\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'display_name': None, 'user_defined_id': None}\n)\n\nprint(response.text)" } ], "description": "Creates a new library listing for the authenticated user's organization.", @@ -8465,11 +8465,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request DELETE \\\n--url https://api.staging.baseten.co/v1/library_listings/{user_defined_listing_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/library_listings/{user_defined_listing_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/library_listings/{user_defined_listing_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/library_listings/{user_defined_listing_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Deletes a library listing and all of its associated versions. Any versions that are currently live will also be removed.", @@ -8496,11 +8496,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/library_listings/{user_defined_listing_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/library_listings/{user_defined_listing_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/library_listings/{user_defined_listing_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/library_listings/{user_defined_listing_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Returns a specific library listing by its user-defined identifier.", @@ -8522,11 +8522,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request PATCH \\\n--url https://api.staging.baseten.co/v1/library_listings/{user_defined_listing_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"display_name\": null,\n \"is_public\": null,\n \"trending\": null,\n \"metadata\": null\n}'" + "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/library_listings/{user_defined_listing_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"display_name\": null,\n \"is_public\": null,\n \"trending\": null,\n \"metadata\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/library_listings/{user_defined_listing_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'display_name': None, 'is_public': None, 'trending': None, 'metadata': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/library_listings/{user_defined_listing_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'display_name': None, 'is_public': None, 'trending': None, 'metadata': None}\n)\n\nprint(response.text)" } ], "description": "Updates a library listing. Supported fields are the display name, public visibility, trending status, and the model-level metadata. When metadata is provided, it replaces the stored metadata.", @@ -8560,11 +8560,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/library_listings/{user_defined_listing_id}/versions \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/library_listings/{user_defined_listing_id}/versions \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/library_listings/{user_defined_listing_id}/versions\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/library_listings/{user_defined_listing_id}/versions\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Returns all versions for a specific library listing.", @@ -8591,11 +8591,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/library_listings/{user_defined_listing_id}/versions \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"display_name\": null,\n \"oracle_version_id\": null,\n \"version_tag\": null\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/library_listings/{user_defined_listing_id}/versions \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"display_name\": null,\n \"oracle_version_id\": null,\n \"version_tag\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/library_listings/{user_defined_listing_id}/versions\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'display_name': None, 'oracle_version_id': None, 'version_tag': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/library_listings/{user_defined_listing_id}/versions\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'display_name': None, 'oracle_version_id': None, 'version_tag': None}\n)\n\nprint(response.text)" } ], "description": "Creates a new library listing version from an existing model version. The model version must be fully built (have an image_uri). If a listing with the given id already exists for the org, a new version is added. Otherwise, a new listing is created.", @@ -8629,11 +8629,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request DELETE \\\n--url https://api.staging.baseten.co/v1/library_listings/{user_defined_listing_id}/versions/{version_tag} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/library_listings/{user_defined_listing_id}/versions/{version_tag} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/library_listings/{user_defined_listing_id}/versions/{version_tag}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/library_listings/{user_defined_listing_id}/versions/{version_tag}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Deletes a specific version of a library listing. Deleting a live version will fail with a 400 error; demote the version first by setting another version as live.", @@ -8663,11 +8663,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/library_listings/{user_defined_listing_id}/versions/{version_tag} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/library_listings/{user_defined_listing_id}/versions/{version_tag} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/library_listings/{user_defined_listing_id}/versions/{version_tag}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/library_listings/{user_defined_listing_id}/versions/{version_tag}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Returns a specific version of a library listing.", @@ -8689,11 +8689,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request PATCH \\\n--url https://api.staging.baseten.co/v1/library_listings/{user_defined_listing_id}/versions/{version_tag} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"is_live\": null,\n \"allow_truss_download\": null,\n \"benchmark\": null\n}'" + "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/library_listings/{user_defined_listing_id}/versions/{version_tag} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"is_live\": null,\n \"allow_truss_download\": null,\n \"benchmark\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/library_listings/{user_defined_listing_id}/versions/{version_tag}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'is_live': None, 'allow_truss_download': None, 'benchmark': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/library_listings/{user_defined_listing_id}/versions/{version_tag}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'is_live': None, 'allow_truss_download': None, 'benchmark': None}\n)\n\nprint(response.text)" } ], "description": "Updates a library listing version. Setting is_live to true will demote the current live version. When a benchmark is provided, it replaces the stored benchmark.", @@ -8727,11 +8727,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/billing/model_apis \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/billing/model_apis \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/billing/model_apis\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'cursor': None, 'start_date': None, 'end_date': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/billing/model_apis\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'cursor': None, 'start_date': None, 'end_date': None}\n)\n\nprint(response.text)" } ], "description": "Returns daily Model API costs in USD for your organization, with optional filtering and grouping by API key, user, model, and service tier. Results may differ from finalized invoice amounts. Cost history is available from August 5, 2026 at 20:45 UTC. August 5 is a partial day; earlier dates are unavailable.", @@ -8891,11 +8891,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/billing/usage_summary \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/billing/usage_summary \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/billing/usage_summary\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'start_date': None, 'end_date': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/billing/usage_summary\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'start_date': None, 'end_date': None}\n)\n\nprint(response.text)" } ], "description": "Returns billing usage data within the specified date range. Includes dedicated model serving, training, and model APIs usage. The date range must not exceed 31 days.", @@ -8943,11 +8943,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/billing/tool_call_usage \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/billing/tool_call_usage \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/billing/tool_call_usage\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'start_date': None, 'end_date': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/billing/tool_call_usage\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'start_date': None, 'end_date': None}\n)\n\nprint(response.text)" } ], "description": "Returns your organization's server-side tool call usage (web search and fetch tools Baseten executes on your behalf) as daily rows grouped by provider, charge unit (sku), and model.", @@ -9003,11 +9003,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/users \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/users \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/users\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'cursor': None, 'email': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/users\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'cursor': None, 'email': None}\n)\n\nprint(response.text)" } ], "description": "Returns the workspace's members. Only actual joined members are returned; service accounts, invited users, and pending join requests are excluded.", @@ -9083,11 +9083,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/users/me \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/users/me \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/users/me\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/users/me\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Returns info about the user making the request.", @@ -9112,11 +9112,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/users/{user_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/users/{user_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/users/{user_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/users/{user_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Returns info about a user in the caller's workspace.", @@ -9146,11 +9146,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/organizations/me \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/organizations/me \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/organizations/me\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/organizations/me\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "description": "Returns info about the organization of the user making the request.", @@ -9175,11 +9175,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/gateway/events \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/gateway/events \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/gateway/events\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'start_time': None, 'end_time': None, 'limit': None, 'cursor': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/gateway/events\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'start_time': None, 'end_time': None, 'limit': None, 'cursor': None}\n)\n\nprint(response.text)" } ], "parameters": [ @@ -9306,11 +9306,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/explore/metadata \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/explore/metadata \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/explore/metadata\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'cursor': None, 'provider': None, 'q': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/explore/metadata\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'cursor': None, 'provider': None, 'q': None}\n)\n\nprint(response.text)" } ], "description": "Lists all live model metadata rows, e.g. for model pickers.", @@ -9404,11 +9404,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/routes \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/routes \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/routes\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'cursor': None, 'team_id': None, 'name': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/routes\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'cursor': None, 'team_id': None, 'name': None}\n)\n\nprint(response.text)" } ], "description": "Lists routes you can invoke, newest first, optionally filtered by team and exact name.", @@ -9500,11 +9500,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/routes \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"team_id\": \"abc1234\",\n \"display_name\": \"Assistant\",\n \"target\": {\n \"model\": \"zai-org/GLM-5.3\",\n \"type\": \"BASETEN_MODEL_API\"\n },\n \"description\": \"Assistant for code review and debugging.\"\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/routes \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"team_id\": \"abc1234\",\n \"display_name\": \"Assistant\",\n \"target\": {\n \"model\": \"zai-org/GLM-5.3\",\n \"type\": \"BASETEN_MODEL_API\"\n },\n \"description\": \"Assistant for code review and debugging.\"\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/routes\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'team_id': 'abc1234', 'display_name': 'Assistant', 'target': {'model': 'zai-org/GLM-5.3', 'type': 'BASETEN_MODEL_API'}, 'description': 'Assistant for code review and debugging.'}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/routes\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'team_id': 'abc1234', 'display_name': 'Assistant', 'target': {'model': 'zai-org/GLM-5.3', 'type': 'BASETEN_MODEL_API'}, 'description': 'Assistant for code review and debugging.'}\n)\n\nprint(response.text)" } ], "description": "Creates and derives a name for the provided route configuration", @@ -9539,11 +9539,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/routes/usage \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/routes/usage \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/routes/usage\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'cursor': None, 'start_date': None, 'end_date': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/routes/usage\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'cursor': None, 'start_date': None, 'end_date': None}\n)\n\nprint(response.text)" } ], "description": "Buckets are UTC days, and days with no usage are included. Organization admins see all route usage in the organization. Other members, including viewers, see only usage from Routes keys they created, including keys that have since expired, been revoked, or been deleted. Usage is metered every 15 minutes, so the current hour can lag. Model API costs use your prices at the time of each request and include tool calls. xAI costs are the charges xAI reports. OpenAI and Anthropic costs are estimated from Baseten's reference prices and may differ from your provider's bill. Vertex and OpenAI-compatible usage is not included. Costs for OpenAI, Anthropic, and xAI estimate what you pay those providers; they are not Baseten charges. Usage is retained for 92 days.", @@ -9691,11 +9691,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request DELETE \\\n--url https://api.staging.baseten.co/v1/routes/{route_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/routes/{route_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/routes/{route_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/routes/{route_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "responses": { @@ -9722,11 +9722,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/routes/{route_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/routes/{route_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/routes/{route_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/routes/{route_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "responses": { @@ -9748,11 +9748,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request PATCH \\\n--url https://api.staging.baseten.co/v1/routes/{route_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"description\": \"Assistant for code review and debugging.\",\n \"display_name\": \"Assistant\"\n}'" + "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/routes/{route_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"description\": \"Assistant for code review and debugging.\",\n \"display_name\": \"Assistant\"\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/routes/{route_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'description': 'Assistant for code review and debugging.', 'display_name': 'Assistant'}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/routes/{route_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'description': 'Assistant for code review and debugging.', 'display_name': 'Assistant'}\n)\n\nprint(response.text)" } ], "description": "The route name, target, and owning team are immutable.", @@ -9787,11 +9787,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/gateway/endpoints \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/gateway/endpoints \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/gateway/endpoints\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/gateway/endpoints\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "responses": { @@ -9812,11 +9812,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/gateway/endpoints \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"slug\": \"baseten/mymodel-4\",\n \"region\": \"UNRESTRICTED\",\n \"targets\": [\n {\n \"environment_name\": \"staging\",\n \"model_id\": \"3kZ9xqd\",\n \"provider\": \"BASETEN\",\n \"target_model\": \"custom/model-name\"\n }\n ]\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/gateway/endpoints \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"slug\": \"baseten/mymodel-4\",\n \"region\": \"UNRESTRICTED\",\n \"targets\": [\n {\n \"environment_name\": \"staging\",\n \"model_id\": \"3kZ9xqd\",\n \"provider\": \"BASETEN\",\n \"target_model\": \"custom/model-name\"\n }\n ]\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/gateway/endpoints\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'slug': 'baseten/mymodel-4', 'region': 'UNRESTRICTED', 'targets': [{'environment_name': 'staging', 'model_id': '3kZ9xqd', 'provider': 'BASETEN', 'target_model': 'custom/model-name'}]}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/gateway/endpoints\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'slug': 'baseten/mymodel-4', 'region': 'UNRESTRICTED', 'targets': [{'environment_name': 'staging', 'model_id': '3kZ9xqd', 'provider': 'BASETEN', 'target_model': 'custom/model-name'}]}\n)\n\nprint(response.text)" } ], "description": "Provisions an endpoint for the given slug and its upstream target. Exactly one target is supported at this time. The slug's prefix must be one your organization owns.", @@ -9850,11 +9850,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request DELETE \\\n--url https://api.staging.baseten.co/v1/gateway/endpoints/{endpoint_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/gateway/endpoints/{endpoint_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/gateway/endpoints/{endpoint_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/gateway/endpoints/{endpoint_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "responses": { @@ -9880,11 +9880,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/gateway/endpoints/{endpoint_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/gateway/endpoints/{endpoint_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/gateway/endpoints/{endpoint_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/gateway/endpoints/{endpoint_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "responses": { @@ -9905,11 +9905,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request PATCH \\\n--url https://api.staging.baseten.co/v1/gateway/endpoints/{endpoint_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"targets\": [\n {\n \"environment_name\": \"staging\",\n \"model_id\": \"3kZ9xqd\",\n \"provider\": \"BASETEN\",\n \"target_model\": \"custom/model-name\"\n }\n ]\n}'" + "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/gateway/endpoints/{endpoint_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"targets\": [\n {\n \"environment_name\": \"staging\",\n \"model_id\": \"3kZ9xqd\",\n \"provider\": \"BASETEN\",\n \"target_model\": \"custom/model-name\"\n }\n ]\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/gateway/endpoints/{endpoint_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'targets': [{'environment_name': 'staging', 'model_id': '3kZ9xqd', 'provider': 'BASETEN', 'target_model': 'custom/model-name'}]}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/gateway/endpoints/{endpoint_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'targets': [{'environment_name': 'staging', 'model_id': '3kZ9xqd', 'provider': 'BASETEN', 'target_model': 'custom/model-name'}]}\n)\n\nprint(response.text)" } ], "description": "Updates the endpoint's provided mutable fields. If targets are provided, the full target list is replaced. Exactly one target is supported at this time.", @@ -9943,11 +9943,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/gateway/groups \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/gateway/groups \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/gateway/groups\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/gateway/groups\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "responses": { @@ -9968,11 +9968,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/gateway/groups \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"metadata\": {\n \"name\": \"Acme prod\",\n \"external_entity_id\": \"cust_42\"\n },\n \"models\": [\n {\n \"slug\": \"my-org/claude\"\n }\n ],\n \"hierarchy\": {\n \"limit_enforcement\": \"INDEPENDENT\",\n \"parent_group_id\": \"abc123\"\n }\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/gateway/groups \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"metadata\": {\n \"name\": \"Acme prod\",\n \"external_entity_id\": \"cust_42\"\n },\n \"models\": [\n {\n \"slug\": \"my-org/claude\"\n }\n ],\n \"hierarchy\": {\n \"limit_enforcement\": \"INDEPENDENT\",\n \"parent_group_id\": \"abc123\"\n }\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/gateway/groups\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'metadata': {'name': 'Acme prod', 'external_entity_id': 'cust_42'}, 'models': [{'slug': 'my-org/claude'}], 'hierarchy': {'limit_enforcement': 'INDEPENDENT', 'parent_group_id': 'abc123'}}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/gateway/groups\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'metadata': {'name': 'Acme prod', 'external_entity_id': 'cust_42'}, 'models': [{'slug': 'my-org/claude'}], 'hierarchy': {'limit_enforcement': 'INDEPENDENT', 'parent_group_id': 'abc123'}}\n)\n\nprint(response.text)" } ], "description": "Creates a group and its endpoint configuration.", @@ -10006,11 +10006,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/gateway/groups/{group_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/gateway/groups/{group_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/gateway/groups/{group_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/gateway/groups/{group_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "responses": { @@ -10036,11 +10036,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request PATCH \\\n--url https://api.staging.baseten.co/v1/gateway/groups/{group_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"metadata\": {\n \"name\": \"Acme Prod\"\n },\n \"models\": null\n}'" + "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/gateway/groups/{group_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"metadata\": {\n \"name\": \"Acme Prod\"\n },\n \"models\": null\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/gateway/groups/{group_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'metadata': {'name': 'Acme Prod'}, 'models': None}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/gateway/groups/{group_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'metadata': {'name': 'Acme Prod'}, 'models': None}\n)\n\nprint(response.text)" } ], "description": "Updates the group's mutable fields.", @@ -10074,11 +10074,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/gateway/groups/{group_id}/api_keys \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/gateway/groups/{group_id}/api_keys \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/gateway/groups/{group_id}/api_keys\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/gateway/groups/{group_id}/api_keys\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "responses": { @@ -10104,11 +10104,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/gateway/groups/{group_id}/api_keys \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"name\": \"prod-key-1\"\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/gateway/groups/{group_id}/api_keys \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"name\": \"prod-key-1\"\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/gateway/groups/{group_id}/api_keys\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'name': 'prod-key-1'}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/gateway/groups/{group_id}/api_keys\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'name': 'prod-key-1'}\n)\n\nprint(response.text)" } ], "description": "Creates a new API key for the given group.", @@ -10142,11 +10142,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request POST \\\n--url https://api.staging.baseten.co/v1/gateway/groups/{group_id}/api_keys/register \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"name\": \"my-model-api-key\",\n \"key\": \"my-secure-api-key-value\"\n}'" + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/gateway/groups/{group_id}/api_keys/register \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"name\": \"my-model-api-key\",\n \"key\": \"my-secure-api-key-value\"\n}'" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/gateway/groups/{group_id}/api_keys/register\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'name': 'my-model-api-key', 'key': 'my-secure-api-key-value'}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/gateway/groups/{group_id}/api_keys/register\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'name': 'my-model-api-key', 'key': 'my-secure-api-key-value'}\n)\n\nprint(response.text)" } ], "description": "Registers a Gateway API key with the provided value and name.", @@ -10185,11 +10185,11 @@ "x-codeSamples": [ { "lang": "bash", - "source": "curl --request GET \\\n--url https://api.staging.baseten.co/v1/gateway/groups/{group_id}/api_keys/{api_key_prefix} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/gateway/groups/{group_id}/api_keys/{api_key_prefix} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" }, { "lang": "python", - "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.staging.baseten.co/v1/gateway/groups/{group_id}/api_keys/{api_key_prefix}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/gateway/groups/{group_id}/api_keys/{api_key_prefix}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], "responses": { From b710216b08663e5ae87c9a25b1c85dfed05ab37f Mon Sep 17 00:00:00 2001 From: "Marius F. Killinger" Date: Wed, 30 Sep 2026 09:59:23 -0700 Subject: [PATCH 08/15] Accept query and body on every API, matching the JS generator The generated client already handled both uniformly; the gate was only a build-time spec lint, and it needed a /v1/sandboxes carve-out to accept the current spec, so it guarded nothing. Server-side conventions like query-XOR-body belong to the server's spec tests, not the SDK build. Co-Authored-By: Claude Code --- scripts/apigen/__main__.py | 27 ++++----------------------- scripts/apigen/preprocess.py | 20 +++----------------- 2 files changed, 7 insertions(+), 40 deletions(-) diff --git a/scripts/apigen/__main__.py b/scripts/apigen/__main__.py index 35cbd54..cc9a55e 100644 --- a/scripts/apigen/__main__.py +++ b/scripts/apigen/__main__.py @@ -11,7 +11,6 @@ import subprocess import sys import urllib.request -from collections.abc import Callable from datetime import datetime from pathlib import Path @@ -51,20 +50,10 @@ def main() -> None: download_spec(SANDBOX_SPEC_URL, SPECS_DIR / "sandbox.yml") generate_api( - SPECS_DIR / "management.json", - CLIENT_DIR / "managementapi", - "Management", - # Sandbox management ops carry a team selector query param beside the - # body; the rest of the management API keeps query and body separated. - query_and_body_allowed=lambda path: path.startswith("/v1/sandboxes"), + SPECS_DIR / "management.json", CLIENT_DIR / "managementapi", "Management" ) generate_api(SPECS_DIR / "inference.json", CLIENT_DIR / "inferenceapi", "Inference") - generate_api( - SPECS_DIR / "sandbox.yml", - CLIENT_DIR / "sandboxapi", - "Sandbox", - query_and_body_allowed=lambda path: True, - ) + generate_api(SPECS_DIR / "sandbox.yml", CLIENT_DIR / "sandboxapi", "Sandbox") generate_modelconfig(SPECS_DIR / "config.schema.json", CLIENT_DIR / "modelconfig") @@ -84,19 +73,11 @@ def _read_spec(spec_file: Path) -> bytes: return spec_file.read_bytes() -def generate_api( - spec_file: Path, - out_dir: Path, - display_name: str, - *, - query_and_body_allowed: Callable[[str], bool] | None = None, -) -> None: +def generate_api(spec_file: Path, out_dir: Path, display_name: str) -> None: print(f"Generating {out_dir.name} from {spec_file}") out_dir.mkdir(parents=True, exist_ok=True) - preprocessed = preprocess_spec( - _read_spec(spec_file), query_and_body_allowed=query_and_body_allowed - ) + preprocessed = preprocess_spec(_read_spec(spec_file)) models_file = out_dir / "_models.py" run_datamodel_codegen(preprocessed, models_file) diff --git a/scripts/apigen/preprocess.py b/scripts/apigen/preprocess.py index 9010d7c..8f0ade6 100644 --- a/scripts/apigen/preprocess.py +++ b/scripts/apigen/preprocess.py @@ -3,7 +3,6 @@ import copy import json import re -from collections.abc import Callable from scripts.apigen.clientgen import ( query_params_model_name, @@ -52,11 +51,7 @@ def _rename_defs_refs(node: object, renames: dict[str, str]) -> None: _rename_defs_refs(child, renames) -def preprocess_spec( - data: bytes, - *, - query_and_body_allowed: Callable[[str], bool] | None = None, -) -> bytes: +def preprocess_spec(data: bytes) -> bytes: doc = json.loads(data) _flatten_parameters(doc) @@ -80,7 +75,7 @@ def preprocess_spec( # generates query-parameter models under the paths scope, which drags # in unwanted per-operation wrappers). Injected before the V1 rename # below so their $refs to enums are rewritten with everything else. - _inject_query_params_schemas(doc, query_and_body_allowed=query_and_body_allowed) + _inject_query_params_schemas(doc) # Hoist inline 2xx application/json response schemas into # components/schemas so datamodel-code-generator emits a named model the @@ -217,9 +212,7 @@ def _collect_schema_refs(node: object, out: set[str]) -> None: _collect_schema_refs(child, out) -def _inject_query_params_schemas( - doc: dict, *, query_and_body_allowed: Callable[[str], bool] | None -) -> None: +def _inject_query_params_schemas(doc: dict) -> None: # Build an object schema whose properties are the operation's query # parameters, named to match its client method (e.g. get_users -> # GetUsersParams). Each parameter's own schema (enum $refs, arrays, @@ -239,13 +232,6 @@ def _inject_query_params_schemas( ] if not query_params: continue - if "requestBody" in op and not ( - query_and_body_allowed and query_and_body_allowed(path) - ): - raise ValueError( - f"{http_method.upper()} {path} has both a request body and " - "query parameters, which this API does not allow" - ) name = query_params_model_name(method_names[(path, http_method)]) if name in schemas: raise ValueError( From 25fed3271682a393010692adfb0919caa5b41272 Mon Sep 17 00:00:00 2001 From: "Marius F. Killinger" Date: Wed, 30 Sep 2026 10:15:59 -0700 Subject: [PATCH 09/15] Fix review findings: date-only YAML scalars, raw docstring periods yaml.safe_load yields datetime.date for date-only scalars, which the unbound datetime.isoformat default rejects; serialize with the value's own isoformat. Raw-sibling docstrings appended a sentence after summaries that already end in a period, producing a doubled period. Co-Authored-By: Claude Code --- baseten/client/inferenceapi/_client.py | 20 ++++++++++---------- scripts/apigen/__main__.py | 3 +-- scripts/apigen/clientgen.py | 1 + 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/baseten/client/inferenceapi/_client.py b/baseten/client/inferenceapi/_client.py index 1ed8bbe..b60ddae 100644 --- a/baseten/client/inferenceapi/_client.py +++ b/baseten/client/inferenceapi/_client.py @@ -439,7 +439,7 @@ def predict_raw( request: PredictInput, accept: Literal["application/json", "application/octet-stream"], ) -> httpx.Response: - """Call the model deployment associated with a specified environment.. Returns the response unread, in the requested content type. The caller must close the response.""" + """Call the model deployment associated with a specified environment. Returns the response unread, in the requested content type. The caller must close the response.""" return self._do_raw( _ApiRequest( method="POST", @@ -491,7 +491,7 @@ def predict_deployment_raw( request: PredictInput, accept: Literal["application/json", "application/octet-stream"], ) -> httpx.Response: - """Call a specific deployment of a model by deployment ID.. Returns the response unread, in the requested content type. The caller must close the response.""" + """Call a specific deployment of a model by deployment ID. Returns the response unread, in the requested content type. The caller must close the response.""" return self._do_raw( _ApiRequest( method="POST", @@ -540,7 +540,7 @@ def predict_development_raw( request: PredictInput, accept: Literal["application/json", "application/octet-stream"], ) -> httpx.Response: - """Call the development deployment of a model.. Returns the response unread, in the requested content type. The caller must close the response.""" + """Call the development deployment of a model. Returns the response unread, in the requested content type. The caller must close the response.""" return self._do_raw( _ApiRequest( method="POST", @@ -589,7 +589,7 @@ def predict_production_raw( request: PredictInput, accept: Literal["application/json", "application/octet-stream"], ) -> httpx.Response: - """Call the production environment of a model.. Returns the response unread, in the requested content type. The caller must close the response.""" + """Call the production environment of a model. Returns the response unread, in the requested content type. The caller must close the response.""" return self._do_raw( _ApiRequest( method="POST", @@ -638,7 +638,7 @@ def predict_regional_raw( request: PredictInput, accept: Literal["application/json", "application/octet-stream"], ) -> httpx.Response: - """Call a regional environment of a model.. Returns the response unread, in the requested content type. The caller must close the response.""" + """Call a regional environment of a model. Returns the response unread, in the requested content type. The caller must close the response.""" return self._do_raw( _ApiRequest( method="POST", @@ -1323,7 +1323,7 @@ async def predict_raw( request: PredictInput, accept: Literal["application/json", "application/octet-stream"], ) -> httpx.Response: - """Call the model deployment associated with a specified environment.. Returns the response unread, in the requested content type. The caller must close the response.""" + """Call the model deployment associated with a specified environment. Returns the response unread, in the requested content type. The caller must close the response.""" return await self._do_raw( _ApiRequest( method="POST", @@ -1375,7 +1375,7 @@ async def predict_deployment_raw( request: PredictInput, accept: Literal["application/json", "application/octet-stream"], ) -> httpx.Response: - """Call a specific deployment of a model by deployment ID.. Returns the response unread, in the requested content type. The caller must close the response.""" + """Call a specific deployment of a model by deployment ID. Returns the response unread, in the requested content type. The caller must close the response.""" return await self._do_raw( _ApiRequest( method="POST", @@ -1424,7 +1424,7 @@ async def predict_development_raw( request: PredictInput, accept: Literal["application/json", "application/octet-stream"], ) -> httpx.Response: - """Call the development deployment of a model.. Returns the response unread, in the requested content type. The caller must close the response.""" + """Call the development deployment of a model. Returns the response unread, in the requested content type. The caller must close the response.""" return await self._do_raw( _ApiRequest( method="POST", @@ -1473,7 +1473,7 @@ async def predict_production_raw( request: PredictInput, accept: Literal["application/json", "application/octet-stream"], ) -> httpx.Response: - """Call the production environment of a model.. Returns the response unread, in the requested content type. The caller must close the response.""" + """Call the production environment of a model. Returns the response unread, in the requested content type. The caller must close the response.""" return await self._do_raw( _ApiRequest( method="POST", @@ -1522,7 +1522,7 @@ async def predict_regional_raw( request: PredictInput, accept: Literal["application/json", "application/octet-stream"], ) -> httpx.Response: - """Call a regional environment of a model.. Returns the response unread, in the requested content type. The caller must close the response.""" + """Call a regional environment of a model. Returns the response unread, in the requested content type. The caller must close the response.""" return await self._do_raw( _ApiRequest( method="POST", diff --git a/scripts/apigen/__main__.py b/scripts/apigen/__main__.py index cc9a55e..db43a5a 100644 --- a/scripts/apigen/__main__.py +++ b/scripts/apigen/__main__.py @@ -11,7 +11,6 @@ import subprocess import sys import urllib.request -from datetime import datetime from pathlib import Path import yaml @@ -69,7 +68,7 @@ def _read_spec(spec_file: Path) -> bytes: # to ISO strings, matching how js-yaml keeps them for the JS SDK. if spec_file.suffix in (".yml", ".yaml"): doc = yaml.safe_load(spec_file.read_text()) - return json.dumps(doc, default=datetime.isoformat).encode() + return json.dumps(doc, default=lambda value: value.isoformat()).encode() return spec_file.read_bytes() diff --git a/scripts/apigen/clientgen.py b/scripts/apigen/clientgen.py index 2be4c0c..0213516 100644 --- a/scripts/apigen/clientgen.py +++ b/scripts/apigen/clientgen.py @@ -623,6 +623,7 @@ def _render_method(op: _Operation, *, is_async: bool, is_raw: bool) -> str: if op.summary: summary = op.summary if is_raw: + summary = summary.rstrip(".") summary += ( ". Returns the response unread, in the requested content" " type. The caller must close the response." From df2f82bfc0ee69770f9f381e72768270a36a3021 Mon Sep 17 00:00:00 2001 From: "Marius F. Killinger" Date: Wed, 30 Sep 2026 12:58:15 -0700 Subject: [PATCH 10/15] Advertise only sendable stdin types on the async client AsyncClient cannot send a sync file object, so the async octet-stream body signature accepts bytes and str, while the sync one keeps IO[bytes]. Co-Authored-By: Claude Code --- baseten/client/sandboxapi/_client.py | 2 +- scripts/apigen/clientgen.py | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/baseten/client/sandboxapi/_client.py b/baseten/client/sandboxapi/_client.py index bb71c22..048df45 100644 --- a/baseten/client/sandboxapi/_client.py +++ b/baseten/client/sandboxapi/_client.py @@ -1728,7 +1728,7 @@ async def post_process_raw( ) async def post_process_stdin( - self, *, identifier: str, content: bytes | IO[bytes] | str + self, *, identifier: str, content: bytes | str ) -> SuccessResponse: """Write to a process's stdin""" return await self._do_json( diff --git a/scripts/apigen/clientgen.py b/scripts/apigen/clientgen.py index 0213516..ea02569 100644 --- a/scripts/apigen/clientgen.py +++ b/scripts/apigen/clientgen.py @@ -538,7 +538,10 @@ def _render_method(op: _Operation, *, is_async: bool, is_raw: bool) -> str: if op.body_content_type == _MULTIPART_CONTENT: kwargs.append("files: Any") elif op.body_content_type: - kwargs.append("content: bytes | IO[bytes] | str") + # AsyncClient cannot send a sync file object, so the async + # signature advertises only what it can deliver. + content_type = "bytes | str" if is_async else "bytes | IO[bytes] | str" + kwargs.append(f"content: {content_type}") elif op.req_body_ref: kwargs.append(f"request: {op.req_body_ref}") else: From d4e6df27adc4c161787ecb14cd9c12005da41a0e Mon Sep 17 00:00:00 2001 From: "Marius F. Killinger" Date: Thu, 1 Oct 2026 11:56:24 -0700 Subject: [PATCH 11/15] Add the sandbox hub image catalog to the spec and client Forward-patches the spec snapshot with GET /v0/sandbox/hub and the SandboxHubImage/SandboxHubImageList schemas, shaped from the live Blaxel spec, and regenerates the typed client. Co-Authored-By: Claude Code --- baseten/client/managementapi/__init__.py | 6 ++ baseten/client/managementapi/_client.py | 31 ++++++ baseten/client/managementapi/_models.py | 71 +++++++++++++ scripts/apigen/specs/management.json | 130 ++++++++++++++++++++++- 4 files changed, 237 insertions(+), 1 deletion(-) diff --git a/baseten/client/managementapi/__init__.py b/baseten/client/managementapi/__init__.py index de2aa74..aeb1ff8 100644 --- a/baseten/client/managementapi/__init__.py +++ b/baseten/client/managementapi/__init__.py @@ -427,6 +427,7 @@ PatchTeamTrainingGpuCapacityRequest, PatchTeamTrainingGpuCapacityResponse, PendingJobAheadAtSubmit, + Port, PrepareModelUploadRequest, PrepareModelUploadResponse, PromoteRequest, @@ -477,6 +478,8 @@ SandboxDuration, SandboxEnv, SandboxExpirationPolicy, + SandboxHubImage, + SandboxHubImageList, SandboxLifecycle, SandboxMetadataLabels, SandboxNetwork, @@ -1037,6 +1040,7 @@ "PatchTeamTrainingGpuCapacityRequest", "PatchTeamTrainingGpuCapacityResponse", "PendingJobAheadAtSubmit", + "Port", "PrepareModelUploadRequest", "PrepareModelUploadResponse", "PromoteRequest", @@ -1088,6 +1092,8 @@ "SandboxDuration", "SandboxEnv", "SandboxExpirationPolicy", + "SandboxHubImage", + "SandboxHubImageList", "SandboxLifecycle", "SandboxMetadataLabels", "SandboxNetwork", diff --git a/baseten/client/managementapi/_client.py b/baseten/client/managementapi/_client.py index 89399e1..1932034 100644 --- a/baseten/client/managementapi/_client.py +++ b/baseten/client/managementapi/_client.py @@ -215,6 +215,7 @@ RoutesUsageResponse, RouteTombstone, Sandbox, + SandboxHubImageList, SearchTrainingJobsRequest, SearchTrainingJobsResponse, Secret, @@ -2444,6 +2445,21 @@ def list_images( ), ) + def list_sandbox_hub_images(self) -> SandboxHubImageList: + """List starter sandbox images""" + return self._do_json( + SandboxHubImageList, + _ApiRequest( + method="GET", + path_fmt="/v0/sandbox/hub", + path_args=[], + body=None, + query=None, + success_codes=[200], + error_codes=None, + ), + ) + def list_sandboxes( self, *, params: ListSandboxesParams | None = None ) -> ListSandboxesResponse: @@ -6312,6 +6328,21 @@ async def list_images( ), ) + async def list_sandbox_hub_images(self) -> SandboxHubImageList: + """List starter sandbox images""" + return await self._do_json( + SandboxHubImageList, + _ApiRequest( + method="GET", + path_fmt="/v0/sandbox/hub", + path_args=[], + body=None, + query=None, + success_codes=[200], + error_codes=None, + ), + ) + async def list_sandboxes( self, *, params: ListSandboxesParams | None = None ) -> ListSandboxesResponse: diff --git a/baseten/client/managementapi/_models.py b/baseten/client/managementapi/_models.py index ebc9236..ccba38c 100644 --- a/baseten/client/managementapi/_models.py +++ b/baseten/client/managementapi/_models.py @@ -309,6 +309,77 @@ class GatewayProvider(StrEnum): OPENAI_COMPATIBLE = "OPENAI_COMPATIBLE" +class Port(BaseModel): + name: Annotated[str | None, Field(description="Name of the port.")] = None + target: Annotated[ + int | None, Field(description="Port number inside the sandbox.") + ] = None + protocol: Annotated[str | None, Field(description="Protocol the port serves.")] = ( + None + ) + + +class SandboxHubImage(BaseModel): + name: Annotated[str, Field(description="Stable identifier of the starter image.")] + displayName: Annotated[ + str | None, Field(description="Human-readable name for display.") + ] = None + image: Annotated[ + str, + Field( + description="Image reference including its tag. Pass it as image when creating a sandbox.", + examples=["blaxel/expo:latest"], + ), + ] + description: Annotated[ + str | None, Field(description="One-line summary of what the image contains.") + ] = None + longDescription: Annotated[ + str | None, Field(description="Longer description of the image's contents.") + ] = None + memory: Annotated[ + int | None, Field(description="Default memory allocation in megabytes.") + ] = None + categories: Annotated[ + list[str] | None, + Field(description="Categories the image is filed under, for filtering."), + ] = None + tags: Annotated[list[str] | None, Field(description="Free-form tags.")] = None + ports: Annotated[ + list[Port] | None, + Field( + description="Ports the image's services listen on, for reference in a sandbox's ports list." + ), + ] = None + icon: Annotated[str | None, Field(description="Icon for display.")] = None + iconLight: Annotated[ + str | None, Field(description="Light-mode icon for display.") + ] = None + iconDark: Annotated[ + str | None, Field(description="Dark-mode icon for display.") + ] = None + url: Annotated[ + str | None, Field(description="Project page for the image's stack.") + ] = None + enterprise: Annotated[ + bool | None, + Field(description="Whether the image is gated to enterprise workspaces."), + ] = None + hidden: Annotated[ + bool | None, Field(description="Whether the entry is hidden from catalogs.") + ] = None + coming_soon: Annotated[ + bool | None, + Field(description="Whether the image is announced but not yet available."), + ] = None + + +class SandboxHubImageList(RootModel[list[SandboxHubImage]]): + root: Annotated[ + list[SandboxHubImage], Field(description="The starter-image catalog.") + ] + + class GetVolumesParams(BaseModel): cursor: Annotated[ str | None, diff --git a/scripts/apigen/specs/management.json b/scripts/apigen/specs/management.json index 68b1942..5f9dd54 100644 --- a/scripts/apigen/specs/management.json +++ b/scripts/apigen/specs/management.json @@ -11030,6 +11030,28 @@ }, "x-stability": "unstable" } + }, + "/v0/sandbox/hub": { + "get": { + "operationId": "ListSandboxHubImages", + "summary": "List starter sandbox images", + "description": "Lists the platform's starter images from the sandbox hub catalog, available to any sandbox without building or pushing. The catalog is workspace-global. Hidden and coming-soon entries arrive unfiltered; callers that display catalogs drop them. Pass an entry's image as image when creating a sandbox.", + "responses": { + "200": { + "description": "The starter-image catalog.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SandboxHubImageList" + } + } + } + }, + "401": { + "$ref": "#/components/responses/SandboxError401" + } + } + } } }, "openapi": "3.1.0", @@ -34684,6 +34706,112 @@ "deleted": 3, "message": "Removed 3 unused image versions. Image versions used by active sandboxes were retained." } + }, + "SandboxHubImage": { + "type": "object", + "required": [ + "name", + "image" + ], + "properties": { + "name": { + "type": "string", + "description": "Stable identifier of the starter image." + }, + "displayName": { + "type": "string", + "description": "Human-readable name for display." + }, + "image": { + "type": "string", + "description": "Image reference including its tag. Pass it as image when creating a sandbox.", + "examples": [ + "blaxel/expo:latest" + ] + }, + "description": { + "type": "string", + "description": "One-line summary of what the image contains." + }, + "longDescription": { + "type": "string", + "description": "Longer description of the image's contents." + }, + "memory": { + "type": "integer", + "description": "Default memory allocation in megabytes." + }, + "categories": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Categories the image is filed under, for filtering." + }, + "tags": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Free-form tags." + }, + "ports": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Name of the port." + }, + "target": { + "type": "integer", + "description": "Port number inside the sandbox." + }, + "protocol": { + "type": "string", + "description": "Protocol the port serves." + } + } + }, + "description": "Ports the image's services listen on, for reference in a sandbox's ports list." + }, + "icon": { + "type": "string", + "description": "Icon for display." + }, + "iconLight": { + "type": "string", + "description": "Light-mode icon for display." + }, + "iconDark": { + "type": "string", + "description": "Dark-mode icon for display." + }, + "url": { + "type": "string", + "description": "Project page for the image's stack." + }, + "enterprise": { + "type": "boolean", + "description": "Whether the image is gated to enterprise workspaces." + }, + "hidden": { + "type": "boolean", + "description": "Whether the entry is hidden from catalogs." + }, + "coming_soon": { + "type": "boolean", + "description": "Whether the image is announced but not yet available." + } + } + }, + "SandboxHubImageList": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SandboxHubImage" + }, + "description": "The starter-image catalog." } }, "parameters": { @@ -35863,4 +35991,4 @@ } } } -} \ No newline at end of file +} From c3b9786f62fee52d2d66a04bf37c9615a8c0cc26 Mon Sep 17 00:00:00 2001 From: "Marius F. Killinger" Date: Thu, 1 Oct 2026 12:36:03 -0700 Subject: [PATCH 12/15] Rename the starter-image catalog types to library vocabulary SandboxHubImage -> SandboxLibraryImage and ListSandboxLibraryImages in the spec snapshot, matching the library_models naming of the consumer catalog. Type and operation names are client-side only; the wire path stays /v0/sandbox/hub. Co-Authored-By: Claude Code --- baseten/client/managementapi/__init__.py | 8 ++++---- baseten/client/managementapi/_client.py | 10 +++++----- baseten/client/managementapi/_models.py | 6 +++--- scripts/apigen/specs/management.json | 10 +++++----- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/baseten/client/managementapi/__init__.py b/baseten/client/managementapi/__init__.py index aeb1ff8..4e44358 100644 --- a/baseten/client/managementapi/__init__.py +++ b/baseten/client/managementapi/__init__.py @@ -478,8 +478,8 @@ SandboxDuration, SandboxEnv, SandboxExpirationPolicy, - SandboxHubImage, - SandboxHubImageList, + SandboxLibraryImage, + SandboxLibraryImageList, SandboxLifecycle, SandboxMetadataLabels, SandboxNetwork, @@ -1092,8 +1092,8 @@ "SandboxDuration", "SandboxEnv", "SandboxExpirationPolicy", - "SandboxHubImage", - "SandboxHubImageList", + "SandboxLibraryImage", + "SandboxLibraryImageList", "SandboxLifecycle", "SandboxMetadataLabels", "SandboxNetwork", diff --git a/baseten/client/managementapi/_client.py b/baseten/client/managementapi/_client.py index 1932034..95504e9 100644 --- a/baseten/client/managementapi/_client.py +++ b/baseten/client/managementapi/_client.py @@ -215,7 +215,7 @@ RoutesUsageResponse, RouteTombstone, Sandbox, - SandboxHubImageList, + SandboxLibraryImageList, SearchTrainingJobsRequest, SearchTrainingJobsResponse, Secret, @@ -2445,10 +2445,10 @@ def list_images( ), ) - def list_sandbox_hub_images(self) -> SandboxHubImageList: + def list_sandbox_library_images(self) -> SandboxLibraryImageList: """List starter sandbox images""" return self._do_json( - SandboxHubImageList, + SandboxLibraryImageList, _ApiRequest( method="GET", path_fmt="/v0/sandbox/hub", @@ -6328,10 +6328,10 @@ async def list_images( ), ) - async def list_sandbox_hub_images(self) -> SandboxHubImageList: + async def list_sandbox_library_images(self) -> SandboxLibraryImageList: """List starter sandbox images""" return await self._do_json( - SandboxHubImageList, + SandboxLibraryImageList, _ApiRequest( method="GET", path_fmt="/v0/sandbox/hub", diff --git a/baseten/client/managementapi/_models.py b/baseten/client/managementapi/_models.py index ccba38c..24ab286 100644 --- a/baseten/client/managementapi/_models.py +++ b/baseten/client/managementapi/_models.py @@ -319,7 +319,7 @@ class Port(BaseModel): ) -class SandboxHubImage(BaseModel): +class SandboxLibraryImage(BaseModel): name: Annotated[str, Field(description="Stable identifier of the starter image.")] displayName: Annotated[ str | None, Field(description="Human-readable name for display.") @@ -374,9 +374,9 @@ class SandboxHubImage(BaseModel): ] = None -class SandboxHubImageList(RootModel[list[SandboxHubImage]]): +class SandboxLibraryImageList(RootModel[list[SandboxLibraryImage]]): root: Annotated[ - list[SandboxHubImage], Field(description="The starter-image catalog.") + list[SandboxLibraryImage], Field(description="The starter-image catalog.") ] diff --git a/scripts/apigen/specs/management.json b/scripts/apigen/specs/management.json index 5f9dd54..a2e8994 100644 --- a/scripts/apigen/specs/management.json +++ b/scripts/apigen/specs/management.json @@ -11033,7 +11033,7 @@ }, "/v0/sandbox/hub": { "get": { - "operationId": "ListSandboxHubImages", + "operationId": "ListSandboxLibraryImages", "summary": "List starter sandbox images", "description": "Lists the platform's starter images from the sandbox hub catalog, available to any sandbox without building or pushing. The catalog is workspace-global. Hidden and coming-soon entries arrive unfiltered; callers that display catalogs drop them. Pass an entry's image as image when creating a sandbox.", "responses": { @@ -11042,7 +11042,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboxHubImageList" + "$ref": "#/components/schemas/SandboxLibraryImageList" } } } @@ -34707,7 +34707,7 @@ "message": "Removed 3 unused image versions. Image versions used by active sandboxes were retained." } }, - "SandboxHubImage": { + "SandboxLibraryImage": { "type": "object", "required": [ "name", @@ -34806,10 +34806,10 @@ } } }, - "SandboxHubImageList": { + "SandboxLibraryImageList": { "type": "array", "items": { - "$ref": "#/components/schemas/SandboxHubImage" + "$ref": "#/components/schemas/SandboxLibraryImage" }, "description": "The starter-image catalog." } From 0d275b479d73ea1ff90592b69a1113ac3b1c92c7 Mon Sep 17 00:00:00 2001 From: "Marius F. Killinger" Date: Fri, 2 Oct 2026 10:03:57 -0700 Subject: [PATCH 13/15] Swap the starter-image catalog to the served library_images endpoint Replaces the Blaxel hub forward-patch with GET /v1/sandboxes/library _images from the served management spec (baseten#31334), matching baseten-go 7b8c438. The server drops hidden and coming-soon entries. Co-Authored-By: Claude Code --- baseten/client/managementapi/__init__.py | 12 +- baseten/client/managementapi/_client.py | 27 +-- baseten/client/managementapi/_models.py | 195 +++++++++++++-------- scripts/apigen/specs/management.json | 209 ++++++++++++++++------- 4 files changed, 293 insertions(+), 150 deletions(-) diff --git a/baseten/client/managementapi/__init__.py b/baseten/client/managementapi/__init__.py index 4e44358..a779787 100644 --- a/baseten/client/managementapi/__init__.py +++ b/baseten/client/managementapi/__init__.py @@ -355,6 +355,8 @@ ListLoopsSamplersResponse, ListSandboxesParams, ListSandboxesResponse, + ListSandboxLibraryImagesParams, + ListSandboxLibraryImagesResponse, ListTrainingJobsResponse, ListTrainingProjectsResponse, ListVolumeNamespacesResponse, @@ -427,7 +429,6 @@ PatchTeamTrainingGpuCapacityRequest, PatchTeamTrainingGpuCapacityResponse, PendingJobAheadAtSubmit, - Port, PrepareModelUploadRequest, PrepareModelUploadResponse, PromoteRequest, @@ -479,7 +480,8 @@ SandboxEnv, SandboxExpirationPolicy, SandboxLibraryImage, - SandboxLibraryImageList, + SandboxLibraryImageCreationOptions, + SandboxLibraryImageVolume, SandboxLifecycle, SandboxMetadataLabels, SandboxNetwork, @@ -968,6 +970,8 @@ "ListLoopsDeploymentsResponse", "ListLoopsRunsResponse", "ListLoopsSamplersResponse", + "ListSandboxLibraryImagesParams", + "ListSandboxLibraryImagesResponse", "ListSandboxesParams", "ListSandboxesResponse", "ListTrainingJobsResponse", @@ -1040,7 +1044,6 @@ "PatchTeamTrainingGpuCapacityRequest", "PatchTeamTrainingGpuCapacityResponse", "PendingJobAheadAtSubmit", - "Port", "PrepareModelUploadRequest", "PrepareModelUploadResponse", "PromoteRequest", @@ -1093,7 +1096,8 @@ "SandboxEnv", "SandboxExpirationPolicy", "SandboxLibraryImage", - "SandboxLibraryImageList", + "SandboxLibraryImageCreationOptions", + "SandboxLibraryImageVolume", "SandboxLifecycle", "SandboxMetadataLabels", "SandboxNetwork", diff --git a/baseten/client/managementapi/_client.py b/baseten/client/managementapi/_client.py index 95504e9..ac41904 100644 --- a/baseten/client/managementapi/_client.py +++ b/baseten/client/managementapi/_client.py @@ -171,6 +171,8 @@ ListLoopsSamplersResponse, ListSandboxesParams, ListSandboxesResponse, + ListSandboxLibraryImagesParams, + ListSandboxLibraryImagesResponse, ListTrainingJobsResponse, ListTrainingProjectsResponse, ListVolumeNamespacesResponse, @@ -215,7 +217,6 @@ RoutesUsageResponse, RouteTombstone, Sandbox, - SandboxLibraryImageList, SearchTrainingJobsRequest, SearchTrainingJobsResponse, Secret, @@ -2445,16 +2446,18 @@ def list_images( ), ) - def list_sandbox_library_images(self) -> SandboxLibraryImageList: - """List starter sandbox images""" + def list_sandbox_library_images( + self, *, params: ListSandboxLibraryImagesParams | None = None + ) -> ListSandboxLibraryImagesResponse: + """List built-in sandbox images""" return self._do_json( - SandboxLibraryImageList, + ListSandboxLibraryImagesResponse, _ApiRequest( method="GET", - path_fmt="/v0/sandbox/hub", + path_fmt="/v1/sandboxes/library_images", path_args=[], body=None, - query=None, + query=params, success_codes=[200], error_codes=None, ), @@ -6328,16 +6331,18 @@ async def list_images( ), ) - async def list_sandbox_library_images(self) -> SandboxLibraryImageList: - """List starter sandbox images""" + async def list_sandbox_library_images( + self, *, params: ListSandboxLibraryImagesParams | None = None + ) -> ListSandboxLibraryImagesResponse: + """List built-in sandbox images""" return await self._do_json( - SandboxLibraryImageList, + ListSandboxLibraryImagesResponse, _ApiRequest( method="GET", - path_fmt="/v0/sandbox/hub", + path_fmt="/v1/sandboxes/library_images", path_args=[], body=None, - query=None, + query=params, success_codes=[200], error_codes=None, ), diff --git a/baseten/client/managementapi/_models.py b/baseten/client/managementapi/_models.py index 24ab286..b774235 100644 --- a/baseten/client/managementapi/_models.py +++ b/baseten/client/managementapi/_models.py @@ -309,77 +309,6 @@ class GatewayProvider(StrEnum): OPENAI_COMPATIBLE = "OPENAI_COMPATIBLE" -class Port(BaseModel): - name: Annotated[str | None, Field(description="Name of the port.")] = None - target: Annotated[ - int | None, Field(description="Port number inside the sandbox.") - ] = None - protocol: Annotated[str | None, Field(description="Protocol the port serves.")] = ( - None - ) - - -class SandboxLibraryImage(BaseModel): - name: Annotated[str, Field(description="Stable identifier of the starter image.")] - displayName: Annotated[ - str | None, Field(description="Human-readable name for display.") - ] = None - image: Annotated[ - str, - Field( - description="Image reference including its tag. Pass it as image when creating a sandbox.", - examples=["blaxel/expo:latest"], - ), - ] - description: Annotated[ - str | None, Field(description="One-line summary of what the image contains.") - ] = None - longDescription: Annotated[ - str | None, Field(description="Longer description of the image's contents.") - ] = None - memory: Annotated[ - int | None, Field(description="Default memory allocation in megabytes.") - ] = None - categories: Annotated[ - list[str] | None, - Field(description="Categories the image is filed under, for filtering."), - ] = None - tags: Annotated[list[str] | None, Field(description="Free-form tags.")] = None - ports: Annotated[ - list[Port] | None, - Field( - description="Ports the image's services listen on, for reference in a sandbox's ports list." - ), - ] = None - icon: Annotated[str | None, Field(description="Icon for display.")] = None - iconLight: Annotated[ - str | None, Field(description="Light-mode icon for display.") - ] = None - iconDark: Annotated[ - str | None, Field(description="Dark-mode icon for display.") - ] = None - url: Annotated[ - str | None, Field(description="Project page for the image's stack.") - ] = None - enterprise: Annotated[ - bool | None, - Field(description="Whether the image is gated to enterprise workspaces."), - ] = None - hidden: Annotated[ - bool | None, Field(description="Whether the entry is hidden from catalogs.") - ] = None - coming_soon: Annotated[ - bool | None, - Field(description="Whether the image is announced but not yet available."), - ] = None - - -class SandboxLibraryImageList(RootModel[list[SandboxLibraryImage]]): - root: Annotated[ - list[SandboxLibraryImage], Field(description="The starter-image catalog.") - ] - - class GetVolumesParams(BaseModel): cursor: Annotated[ str | None, @@ -1204,6 +1133,16 @@ class DeleteImageTagParams(BaseModel): ] = None +class ListSandboxLibraryImagesParams(BaseModel): + team_id: Annotated[ + str | None, + Field( + description="Optional team ID. Must match X-Team-Id when both are supplied. If neither selector is supplied, defaults to the caller's only accessible team. Callers with multiple accessible teams must select a team. Requests without access to any team are forbidden.", + min_length=1, + ), + ] = None + + class PaginationResponse(BaseModel): has_more: Annotated[ bool, @@ -8977,6 +8916,49 @@ class CleanupImagesResponse(BaseModel): ] +class SandboxLibraryImageVolume(BaseModel): + name: Annotated[ + str, + Field( + description="Volume name, or an internal identifier for ephemeral volumes.", + examples=["scratch"], + ), + ] + mount_path: Annotated[ + str, + Field( + description="Absolute filesystem path where the volume is mounted.", + examples=["/mnt/data"], + ), + ] + type: Annotated[ + str | None, + Field( + description="Volume type, persistent when empty.", examples=["ephemeral"] + ), + ] = None + size_mb: Annotated[ + int | None, + Field( + description="Storage capacity in megabytes for ephemeral volumes.", + examples=[10240], + ), + ] = None + read_only: Annotated[ + bool | None, + Field(description="Whether the volume is mounted read-only.", examples=[False]), + ] = None + + +class SandboxLibraryImageCreationOptions(BaseModel): + extra_args: Annotated[ + dict[str, str] | None, Field(description="Kernel selection arguments.") + ] = None + volumes: Annotated[ + list[SandboxLibraryImageVolume] | None, Field(description="Volume attachments.") + ] = None + + class Checkpoints( RootModel[ BasetenLatestCheckpointConfig @@ -12177,6 +12159,77 @@ class ListImageTagsResponse(BaseModel): pagination: SandboxApiPagination +class SandboxLibraryImage(BaseModel): + name: Annotated[ + str, + Field( + description="Stable identifier of the built-in image.", + examples=["base-image"], + ), + ] + display_name: Annotated[ + str | None, Field(description="Human-readable name.", examples=["Base Image"]) + ] = None + description: Annotated[ + str | None, + Field( + description="Short description.", + examples=["A minimal sandbox environment with the sandbox execution API."], + ), + ] = None + long_description: Annotated[ + str | None, Field(description="Detailed description.") + ] = None + image: Annotated[ + str, + Field( + description="Image reference including its tag, usable as the image of a sandbox.", + examples=["baseten/base-image:latest"], + ), + ] + memory: Annotated[ + int | None, + Field( + description="Recommended memory allocation in megabytes.", examples=[4096] + ), + ] = None + ports: SandboxPorts | None = None + categories: Annotated[ + list[str] | None, Field(description="Categories of the image.") + ] = None + tags: Annotated[list[str] | None, Field(description="Tags of the image.")] = None + url: Annotated[str | None, Field(description="Documentation URL.")] = None + icon: Annotated[str | None, Field(description="Icon URL.")] = None + icon_light: Annotated[str | None, Field(description="Light-mode icon URL.")] = None + icon_dark: Annotated[str | None, Field(description="Dark-mode icon URL.")] = None + enterprise: Annotated[ + bool | None, + Field( + description="Whether the image requires an enterprise plan.", + examples=[False], + ), + ] = None + hidden: Annotated[ + bool | None, + Field( + description="Whether the image is hidden. Always false in listings.", + examples=[False], + ), + ] = None + coming_soon: Annotated[ + bool | None, + Field( + description="Whether the image is not yet available. Always false in listings.", + examples=[False], + ), + ] = None + creation_options: SandboxLibraryImageCreationOptions | None = None + + +class ListSandboxLibraryImagesResponse(BaseModel): + items: Annotated[list[SandboxLibraryImage], Field(description="Built-in images.")] + + class AuditLogEntry(BaseModel): id: Annotated[ str, Field(description="Unique identifier of the audit-log entry.", title="Id") diff --git a/scripts/apigen/specs/management.json b/scripts/apigen/specs/management.json index a2e8994..5f633b0 100644 --- a/scripts/apigen/specs/management.json +++ b/scripts/apigen/specs/management.json @@ -11031,26 +11031,52 @@ "x-stability": "unstable" } }, - "/v0/sandbox/hub": { + "/v1/sandboxes/library_images": { "get": { "operationId": "ListSandboxLibraryImages", - "summary": "List starter sandbox images", - "description": "Lists the platform's starter images from the sandbox hub catalog, available to any sandbox without building or pushing. The catalog is workspace-global. Hidden and coming-soon entries arrive unfiltered; callers that display catalogs drop them. Pass an entry's image as image when creating a sandbox.", + "summary": "List built-in sandbox images", + "description": "Return the built-in sandbox images available to every team. Use the image field directly as the image of a sandbox, without building or pushing it. Hidden and upcoming images are excluded.", + "tags": [ + "Images" + ], + "parameters": [ + { + "$ref": "#/components/parameters/TeamId" + }, + { + "$ref": "#/components/parameters/TeamIdHeader" + } + ], "responses": { "200": { - "description": "The starter-image catalog.", + "description": "Successful operation.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SandboxLibraryImageList" + "$ref": "#/components/schemas/ListSandboxLibraryImagesResponseV1" + }, + "examples": { + "complete": { + "$ref": "#/components/examples/SandboxLibraryImages" + } } } } }, "401": { "$ref": "#/components/responses/SandboxError401" + }, + "403": { + "$ref": "#/components/responses/SandboxError403" + }, + "429": { + "$ref": "#/components/responses/SandboxError429" + }, + "500": { + "$ref": "#/components/responses/SandboxError500" } - } + }, + "x-stability": "unstable" } } }, @@ -34707,111 +34733,166 @@ "message": "Removed 3 unused image versions. Image versions used by active sandboxes were retained." } }, - "SandboxLibraryImage": { + "SandboxLibraryImageVolumeV1": { "type": "object", + "description": "Volume attachment suggested by a built-in image.", + "properties": { + "name": { + "type": "string", + "description": "Volume name, or an internal identifier for ephemeral volumes.", + "example": "scratch" + }, + "mount_path": { + "type": "string", + "description": "Absolute filesystem path where the volume is mounted.", + "example": "/mnt/data" + }, + "type": { + "type": "string", + "description": "Volume type, persistent when empty.", + "example": "ephemeral" + }, + "size_mb": { + "type": "integer", + "description": "Storage capacity in megabytes for ephemeral volumes.", + "example": 10240 + }, + "read_only": { + "type": "boolean", + "description": "Whether the volume is mounted read-only.", + "example": false + } + }, "required": [ "name", - "image" - ], + "mount_path" + ] + }, + "SandboxLibraryImageCreationOptionsV1": { + "type": "object", + "description": "Optional settings suggested when creating a sandbox from this image.", + "properties": { + "extra_args": { + "type": "object", + "description": "Kernel selection arguments.", + "additionalProperties": { + "type": "string" + } + }, + "volumes": { + "type": "array", + "description": "Volume attachments.", + "items": { + "$ref": "#/components/schemas/SandboxLibraryImageVolumeV1" + } + } + } + }, + "SandboxLibraryImageV1": { + "type": "object", + "description": "Built-in sandbox image usable directly as a sandbox image.", "properties": { "name": { "type": "string", - "description": "Stable identifier of the starter image." + "description": "Stable identifier of the built-in image.", + "example": "base-image" }, - "displayName": { + "display_name": { "type": "string", - "description": "Human-readable name for display." + "description": "Human-readable name.", + "example": "Base Image" }, - "image": { + "description": { "type": "string", - "description": "Image reference including its tag. Pass it as image when creating a sandbox.", - "examples": [ - "blaxel/expo:latest" - ] + "description": "Short description.", + "example": "A minimal sandbox environment with the sandbox execution API." }, - "description": { + "long_description": { "type": "string", - "description": "One-line summary of what the image contains." + "description": "Detailed description." }, - "longDescription": { + "image": { "type": "string", - "description": "Longer description of the image's contents." + "description": "Image reference including its tag, usable as the image of a sandbox.", + "example": "baseten/base-image:latest" }, "memory": { "type": "integer", - "description": "Default memory allocation in megabytes." + "description": "Recommended memory allocation in megabytes.", + "example": 4096 + }, + "ports": { + "$ref": "#/components/schemas/SandboxPortsV1" }, "categories": { "type": "array", + "description": "Categories of the image.", "items": { "type": "string" - }, - "description": "Categories the image is filed under, for filtering." + } }, "tags": { "type": "array", + "description": "Tags of the image.", "items": { "type": "string" - }, - "description": "Free-form tags." - }, - "ports": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "Name of the port." - }, - "target": { - "type": "integer", - "description": "Port number inside the sandbox." - }, - "protocol": { - "type": "string", - "description": "Protocol the port serves." - } - } - }, - "description": "Ports the image's services listen on, for reference in a sandbox's ports list." + } }, - "icon": { + "url": { "type": "string", - "description": "Icon for display." + "description": "Documentation URL." }, - "iconLight": { + "icon": { "type": "string", - "description": "Light-mode icon for display." + "description": "Icon URL." }, - "iconDark": { + "icon_light": { "type": "string", - "description": "Dark-mode icon for display." + "description": "Light-mode icon URL." }, - "url": { + "icon_dark": { "type": "string", - "description": "Project page for the image's stack." + "description": "Dark-mode icon URL." }, "enterprise": { "type": "boolean", - "description": "Whether the image is gated to enterprise workspaces." + "description": "Whether the image requires an enterprise plan.", + "example": false }, "hidden": { "type": "boolean", - "description": "Whether the entry is hidden from catalogs." + "description": "Whether the image is hidden. Always false in listings.", + "example": false }, "coming_soon": { "type": "boolean", - "description": "Whether the image is announced but not yet available." + "description": "Whether the image is not yet available. Always false in listings.", + "example": false + }, + "creation_options": { + "$ref": "#/components/schemas/SandboxLibraryImageCreationOptionsV1" } - } + }, + "required": [ + "name", + "image" + ] }, - "SandboxLibraryImageList": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SandboxLibraryImage" + "ListSandboxLibraryImagesResponseV1": { + "type": "object", + "description": "Built-in sandbox images.", + "properties": { + "items": { + "type": "array", + "description": "Built-in images.", + "items": { + "$ref": "#/components/schemas/SandboxLibraryImageV1" + } + } }, - "description": "The starter-image catalog." + "required": [ + "items" + ] } }, "parameters": { From 35faa2762909fa0c89a87d92a67ea2175ddc72e8 Mon Sep 17 00:00:00 2001 From: "Marius F. Killinger" Date: Fri, 2 Oct 2026 10:41:42 -0700 Subject: [PATCH 14/15] Forward-patch the sandbox record to the served shape Matches what baseten#31334 will serve, per baseten-go 7b8c438: state and display_name drop from the sandbox record and create/update requests, create_if_not_exists arrives on create. Co-Authored-By: Claude Code --- baseten/client/managementapi/__init__.py | 2 -- baseten/client/managementapi/_models.py | 41 ++++-------------------- scripts/apigen/specs/management.json | 32 +++--------------- 3 files changed, 10 insertions(+), 65 deletions(-) diff --git a/baseten/client/managementapi/__init__.py b/baseten/client/managementapi/__init__.py index a779787..0eb83a5 100644 --- a/baseten/client/managementapi/__init__.py +++ b/baseten/client/managementapi/__init__.py @@ -506,7 +506,6 @@ SignSSHCertificateRequest, SignSSHCertificateResponse, SortOrder, - State, StatusItem, StopTrainingJobRequest, StopTrainingJobResponse, @@ -1122,7 +1121,6 @@ "SignSSHCertificateResponse", "SignalPromotionResponse", "SortOrder", - "State", "StatusItem", "StopTrainingJobRequest", "StopTrainingJobResponse", diff --git a/baseten/client/managementapi/_models.py b/baseten/client/managementapi/_models.py index b774235..5039af5 100644 --- a/baseten/client/managementapi/_models.py +++ b/baseten/client/managementapi/_models.py @@ -8701,11 +8701,6 @@ class SandboxMetadataLabels(RootModel[dict[str, str]]): root: dict[str, str] -class State(StrEnum): - RUNNING = "RUNNING" - STANDBY = "STANDBY" - - class SandboxStatus(StrEnum): DEPLOYING = "DEPLOYING" DEPLOYED = "DEPLOYED" @@ -12754,14 +12749,6 @@ class SandboxConfiguration(BaseModel): examples=[[{"name": "http", "protocol": "HTTP", "target": 3000}]], ), ] = None - display_name: Annotated[ - str | None, - Field( - description="Human-readable name for display in the UI. Can contain spaces and special characters, max 63 characters.", - examples=["Baseten API review"], - max_length=63, - ), - ] = None external_id: Annotated[ str | None, Field( @@ -12885,14 +12872,6 @@ class CreateSandboxRequest(BaseModel): examples=[[{"name": "http", "protocol": "HTTP", "target": 3000}]], ), ] = None - display_name: Annotated[ - str | None, - Field( - description="Human-readable name for display in the UI. Can contain spaces and special characters, max 63 characters.", - examples=["Baseten API review"], - max_length=63, - ), - ] = None external_id: Annotated[ str | None, Field( @@ -12911,6 +12890,12 @@ class CreateSandboxRequest(BaseModel): ], ), ] = None + create_if_not_exists: Annotated[ + bool | None, + Field( + description="When true, return the existing live sandbox with this name or recreate it if it is failed, terminated, or being deleted. The server handles concurrent creation and deletion races with a bounded wait; persistent contention returns a conflict. Requires name. Existing configuration is preserved. Defaults to false when omitted." + ), + ] = None class UpdateSandboxRequest(BaseModel): @@ -12974,14 +12959,6 @@ class UpdateSandboxRequest(BaseModel): examples=[[{"name": "http", "protocol": "HTTP", "target": 3000}]], ), ] = None - display_name: Annotated[ - str | None, - Field( - description="Human-readable name for display in the UI. Can contain spaces and special characters, max 63 characters.", - examples=["Baseten API review - revised"], - max_length=63, - ), - ] = None external_id: Annotated[ str | None, Field( @@ -13026,12 +13003,6 @@ class Sandbox(SandboxConfiguration): SandboxStatus, Field(description="Sandbox deployment status.", examples=["DEPLOYED"]), ] - state: Annotated[ - State | None, - Field( - description="Current execution state when available.", examples=["RUNNING"] - ), - ] = None created_at: Annotated[ AwareDatetime, Field( diff --git a/scripts/apigen/specs/management.json b/scripts/apigen/specs/management.json index 5f633b0..c692998 100644 --- a/scripts/apigen/specs/management.json +++ b/scripts/apigen/specs/management.json @@ -33447,12 +33447,6 @@ } ] }, - "display_name": { - "type": "string", - "description": "Human-readable name for display in the UI. Can contain spaces and special characters, max 63 characters.", - "example": "Baseten API review", - "maxLength": 63 - }, "external_id": { "type": "string", "description": "Caller-owned identifier for external lookups. Max 64 chars, alphanumeric + dash.", @@ -33691,12 +33685,6 @@ } ] }, - "display_name": { - "type": "string", - "description": "Human-readable name for display in the UI. Can contain spaces and special characters, max 63 characters.", - "example": "Baseten API review", - "maxLength": 63 - }, "external_id": { "type": "string", "description": "Caller-owned identifier for external lookups. Max 64 chars, alphanumeric + dash.", @@ -33716,6 +33704,10 @@ "project": "api-review", "team": "engineering" } + }, + "create_if_not_exists": { + "type": "boolean", + "description": "When true, return the existing live sandbox with this name or recreate it if it is failed, terminated, or being deleted. The server handles concurrent creation and deletion races with a bounded wait; persistent contention returns a conflict. Requires name. Existing configuration is preserved. Defaults to false when omitted." } }, "example": { @@ -33886,12 +33878,6 @@ } ] }, - "display_name": { - "type": "string", - "description": "Human-readable name for display in the UI. Can contain spaces and special characters, max 63 characters.", - "example": "Baseten API review - revised", - "maxLength": 63 - }, "external_id": { "type": "string", "description": "Caller-owned identifier for external lookups. Max 64 chars, alphanumeric + dash.", @@ -34000,16 +33986,6 @@ ], "example": "DEPLOYED" }, - "state": { - "type": "string", - "description": "Current execution state when available.", - "enum": [ - "RUNNING", - "STANDBY" - ], - "readOnly": true, - "example": "RUNNING" - }, "created_at": { "type": "string", "description": "Time the sandbox was created.", From 82ab9293a7490b26b36a7c4c909327d9b33c828b Mon Sep 17 00:00:00 2001 From: Chad Retz Date: Mon, 5 Oct 2026 10:52:33 -0500 Subject: [PATCH 15/15] Use shared management spec and tidy generated docstrings --- baseten/client/managementapi/__init__.py | 66 + baseten/client/managementapi/_client.py | 316 +++++ baseten/client/managementapi/_models.py | 652 +++++++++- baseten/client/sandboxapi/_client.py | 12 +- scripts/apigen/clientgen.py | 22 +- scripts/apigen/specs/management.json | 1482 +++++++++++++++++++--- 6 files changed, 2289 insertions(+), 261 deletions(-) diff --git a/baseten/client/managementapi/__init__.py b/baseten/client/managementapi/__init__.py index 0eb83a5..3b0d0f6 100644 --- a/baseten/client/managementapi/__init__.py +++ b/baseten/client/managementapi/__init__.py @@ -100,6 +100,9 @@ AWSCredentials, AwsIamDockerAuth, AwsOidcDockerAuth, + Background, + Background1, + BackgroundHarnessModels, BasetenLatestCheckpointConfig, BasetenNamedCheckpointConfig, BenchmarkSnapshot, @@ -179,16 +182,20 @@ DailyTrainingUsage, DeactivateLoopsDeploymentResponse, DeactivateLoopsRunResponse, + DeactivateLoopsSamplerResponse, DeactivateResponse, DedicatedItem, DedicatedUsage, DeleteImageParams, DeleteImageTagParams, + DeleteRoutesHarnessConfigsParams, DeleteSandboxParams, DeleteVolumeRequest, DeleteVolumeResponse, DeleteVolumeVersionRequest, DeleteVolumeVersionResponse, + DeployLoopsCheckpointRequest, + DeployLoopsCheckpointResponse, Deployment, DeploymentArchivePayload, DeploymentArchiveSource, @@ -259,6 +266,7 @@ GetDeploymentPatchesStateResponse, GetExploreMetadataParams, GetGatewayEventsParams, + GetImageBuildLogsParams, GetImageParams, GetLogsResponse, GetLoopsCapabilitiesParams, @@ -288,6 +296,7 @@ GetModelsEnvironmentsLogsParams, GetModelsEnvironmentsMetricsParams, GetModelsParams, + GetRoutesHarnessConfigsParams, GetRoutesParams, GetRoutesUsageParams, GetSandboxParams, @@ -318,6 +327,8 @@ GroupMetadata, GroupsResponse, Image, + ImageBuildLog, + ImageBuildLogsResponse, ImageStatus, ImageTag, InferenceVolumeByStatusDatapoint, @@ -431,6 +442,9 @@ PendingJobAheadAtSubmit, PrepareModelUploadRequest, PrepareModelUploadResponse, + Primary, + Primary2, + PrimaryHarnessModels, PromoteRequest, PromoteToChainEnvironmentRequest, PromoteToEnvironmentRequest, @@ -461,7 +475,15 @@ RollingDeployConfig, RollingDeployStrategy, Route, + RouteHarness, + RouteHarnessConfig, + RouteHarnessConfigsResponse, + RouteHarnessConfigTombstone, + RouteHarnessModel, + RouteHarnessModelSource, + RouteHarnessRole, RouteProvider, + RouteSpendLimit, RoutesResponse, RoutesUsageBucket, RoutesUsageResponse, @@ -501,6 +523,10 @@ SecretReference, Secrets, SecretTombstone, + SetClaudeCodeHarnessConfig, + SetCodexHarnessConfig, + SetOpenCodeHarnessConfig, + SetRouteHarnessConfigRequest, SharedEndpointRegion, SignalPromotionResponse, SignSSHCertificateRequest, @@ -558,11 +584,14 @@ UpdateAutoscalingSettings, UpdateAutoscalingSettingsResponse, UpdateAutoscalingSettingsStatus, + UpdateBackgroundHarnessModels, UpdateChainEnvironmentRequest, UpdateChainEnvironmentResponse, UpdateChainletEnvironmentAutoscalingSettingsRequest, UpdateChainletEnvironmentInstanceTypeRequest, UpdateChainletEnvironmentInstanceTypeResponse, + UpdateClaudeCodeHarnessConfig, + UpdateCodexHarnessConfig, UpdateDeploymentRequest, UpdateEndpointRequest, UpdateEnvironmentGroupManageAccess, @@ -574,10 +603,14 @@ UpdateLibraryListingRequest, UpdateLibraryListingVersionRequest, UpdateModelRequest, + UpdateOpenCodeHarnessConfig, + UpdatePrimaryHarnessModels, UpdatePromotionSettings, UpdateRequestBackpressureSettings, UpdateRollingDeployConfig, + UpdateRouteHarnessConfigRequest, UpdateRouteRequest, + UpdateRouteSpendLimitRequest, UpdateSandboxParams, UpdateSandboxRequest, UpdateTrainingJobRequest, @@ -714,6 +747,9 @@ "AwsAssumeRoleDockerAuth", "AwsIamDockerAuth", "AwsOidcDockerAuth", + "Background", + "Background1", + "BackgroundHarnessModels", "BasetenLatestCheckpointConfig", "BasetenNamedCheckpointConfig", "BenchmarkSnapshot", @@ -793,16 +829,20 @@ "DailyTrainingUsage", "DeactivateLoopsDeploymentResponse", "DeactivateLoopsRunResponse", + "DeactivateLoopsSamplerResponse", "DeactivateResponse", "DedicatedItem", "DedicatedUsage", "DeleteImageParams", "DeleteImageTagParams", + "DeleteRoutesHarnessConfigsParams", "DeleteSandboxParams", "DeleteVolumeRequest", "DeleteVolumeResponse", "DeleteVolumeVersionRequest", "DeleteVolumeVersionResponse", + "DeployLoopsCheckpointRequest", + "DeployLoopsCheckpointResponse", "Deployment", "DeploymentArchivePayload", "DeploymentArchiveSource", @@ -873,6 +913,7 @@ "GetDeploymentPatchesStateResponse", "GetExploreMetadataParams", "GetGatewayEventsParams", + "GetImageBuildLogsParams", "GetImageParams", "GetLogsResponse", "GetLoopsCapabilitiesParams", @@ -902,6 +943,7 @@ "GetModelsEnvironmentsLogsParams", "GetModelsEnvironmentsMetricsParams", "GetModelsParams", + "GetRoutesHarnessConfigsParams", "GetRoutesParams", "GetRoutesUsageParams", "GetSandboxParams", @@ -932,6 +974,8 @@ "GroupMetadata", "GroupsResponse", "Image", + "ImageBuildLog", + "ImageBuildLogsResponse", "ImageStatus", "ImageTag", "InProgressPromotion", @@ -1045,6 +1089,9 @@ "PendingJobAheadAtSubmit", "PrepareModelUploadRequest", "PrepareModelUploadResponse", + "Primary", + "Primary2", + "PrimaryHarnessModels", "PromoteRequest", "PromoteToChainEnvironmentRequest", "PromoteToEnvironmentRequest", @@ -1076,7 +1123,15 @@ "RollingDeployConfig", "RollingDeployStrategy", "Route", + "RouteHarness", + "RouteHarnessConfig", + "RouteHarnessConfigTombstone", + "RouteHarnessConfigsResponse", + "RouteHarnessModel", + "RouteHarnessModelSource", + "RouteHarnessRole", "RouteProvider", + "RouteSpendLimit", "RouteTargetAnthropic", "RouteTargetBasetenModelAPI", "RouteTargetOpenAI", @@ -1116,6 +1171,10 @@ "SecretReference", "SecretTombstone", "Secrets", + "SetClaudeCodeHarnessConfig", + "SetCodexHarnessConfig", + "SetOpenCodeHarnessConfig", + "SetRouteHarnessConfigRequest", "SharedEndpointRegion", "SignSSHCertificateRequest", "SignSSHCertificateResponse", @@ -1173,11 +1232,14 @@ "UpdateAutoscalingSettings", "UpdateAutoscalingSettingsResponse", "UpdateAutoscalingSettingsStatus", + "UpdateBackgroundHarnessModels", "UpdateChainEnvironmentRequest", "UpdateChainEnvironmentResponse", "UpdateChainletEnvironmentAutoscalingSettingsRequest", "UpdateChainletEnvironmentInstanceTypeRequest", "UpdateChainletEnvironmentInstanceTypeResponse", + "UpdateClaudeCodeHarnessConfig", + "UpdateCodexHarnessConfig", "UpdateDeploymentRequest", "UpdateEndpointRequest", "UpdateEnvironmentGroupManageAccess", @@ -1189,10 +1251,14 @@ "UpdateLibraryListingRequest", "UpdateLibraryListingVersionRequest", "UpdateModelRequest", + "UpdateOpenCodeHarnessConfig", + "UpdatePrimaryHarnessModels", "UpdatePromotionSettings", "UpdateRequestBackpressureSettings", "UpdateRollingDeployConfig", + "UpdateRouteHarnessConfigRequest", "UpdateRouteRequest", + "UpdateRouteSpendLimitRequest", "UpdateSandboxParams", "UpdateSandboxRequest", "UpdateTrainingJobRequest", diff --git a/baseten/client/managementapi/_client.py b/baseten/client/managementapi/_client.py index ac41904..1e083e6 100644 --- a/baseten/client/managementapi/_client.py +++ b/baseten/client/managementapi/_client.py @@ -56,14 +56,18 @@ CreateVolumeTokenResponse, DeactivateLoopsDeploymentResponse, DeactivateLoopsRunResponse, + DeactivateLoopsSamplerResponse, DeactivateResponse, DeleteImageParams, DeleteImageTagParams, + DeleteRoutesHarnessConfigsParams, DeleteSandboxParams, DeleteVolumeRequest, DeleteVolumeResponse, DeleteVolumeVersionRequest, DeleteVolumeVersionResponse, + DeployLoopsCheckpointRequest, + DeployLoopsCheckpointResponse, Deployment, DeploymentConfigResponse, Deployments, @@ -95,6 +99,7 @@ GetDeploymentPatchesStateResponse, GetExploreMetadataParams, GetGatewayEventsParams, + GetImageBuildLogsParams, GetImageParams, GetLogsResponse, GetLoopsCapabilitiesParams, @@ -124,6 +129,7 @@ GetModelsEnvironmentsLogsParams, GetModelsEnvironmentsMetricsParams, GetModelsParams, + GetRoutesHarnessConfigsParams, GetRoutesParams, GetRoutesUsageParams, GetSandboxParams, @@ -151,6 +157,7 @@ Group, GroupsResponse, Image, + ImageBuildLogsResponse, InstanceTypePrices, InstanceTypes, KeysForGroupResponse, @@ -213,6 +220,10 @@ RestoreVolumeVersionResponse, RetryDeploymentResponse, Route, + RouteHarnessConfig, + RouteHarnessConfigsResponse, + RouteHarnessConfigTombstone, + RouteSpendLimit, RoutesResponse, RoutesUsageResponse, RouteTombstone, @@ -222,6 +233,7 @@ Secret, Secrets, SecretTombstone, + SetRouteHarnessConfigRequest, SignalPromotionResponse, SignSSHCertificateRequest, SignSSHCertificateResponse, @@ -253,7 +265,9 @@ UpdateLibraryListingVersionRequest, UpdateModelRequest, UpdateRequestBackpressureSettings, + UpdateRouteHarnessConfigRequest, UpdateRouteRequest, + UpdateRouteSpendLimitRequest, UpdateSandboxParams, UpdateSandboxRequest, UpdateTrainingJobRequest, @@ -561,6 +575,23 @@ def delete_routes(self, *, route_id: str) -> RouteTombstone: ), ) + def delete_routes_harness_configs( + self, *, harness: str, params: DeleteRoutesHarnessConfigsParams + ) -> RouteHarnessConfigTombstone: + """Clears default models for a coding harness""" + return self._do_json( + RouteHarnessConfigTombstone, + _ApiRequest( + method="DELETE", + path_fmt="/v1/routes/harness-configs/{}", + path_args=[harness], + body=None, + query=params, + success_codes=[200], + error_codes=None, + ), + ) + def delete_sandbox( self, *, sandbox_name: str, params: DeleteSandboxParams | None = None ) -> Sandbox: @@ -1102,6 +1133,23 @@ def get_image( ), ) + def get_image_build_logs( + self, *, image_name: str, params: GetImageBuildLogsParams | None = None + ) -> ImageBuildLogsResponse: + """Get image build logs""" + return self._do_json( + ImageBuildLogsResponse, + _ApiRequest( + method="GET", + path_fmt="/v1/sandboxes/images/{}/logs", + path_args=[image_name], + body=None, + query=params, + success_codes=[200], + error_codes=None, + ), + ) + def get_instance_type_prices(self) -> InstanceTypePrices: """Gets prices for available instance types""" return self._do_json( @@ -1812,6 +1860,23 @@ def get_routes(self, *, params: GetRoutesParams | None = None) -> RoutesResponse ), ) + def get_routes_harness_configs( + self, *, params: GetRoutesHarnessConfigsParams + ) -> RouteHarnessConfigsResponse: + """Lists default models for coding harnesses""" + return self._do_json( + RouteHarnessConfigsResponse, + _ApiRequest( + method="GET", + path_fmt="/v1/routes/harness-configs", + path_args=[], + body=None, + query=params, + success_codes=[200], + error_codes=None, + ), + ) + def get_routes_route_id(self, *, route_id: str) -> Route: """Gets a route""" return self._do_json( @@ -1827,6 +1892,21 @@ def get_routes_route_id(self, *, route_id: str) -> Route: ), ) + def get_routes_spend_limits(self, *, user_id: str) -> RouteSpendLimit: + """Gets a user's spend limits""" + return self._do_json( + RouteSpendLimit, + _ApiRequest( + method="GET", + path_fmt="/v1/routes/spend_limits/{}", + path_args=[user_id], + body=None, + query=None, + success_codes=[200], + error_codes=None, + ), + ) + def get_routes_usage( self, *, params: GetRoutesUsageParams | None = None ) -> RoutesUsageResponse: @@ -2760,6 +2840,40 @@ def patch_routes(self, *, route_id: str, request: UpdateRouteRequest) -> Route: ), ) + def patch_routes_harness_configs( + self, *, request: UpdateRouteHarnessConfigRequest + ) -> RouteHarnessConfig: + """Updates default models for a coding harness""" + return self._do_json( + RouteHarnessConfig, + _ApiRequest( + method="PATCH", + path_fmt="/v1/routes/harness-configs", + path_args=[], + body=request, + query=None, + success_codes=[200], + error_codes=None, + ), + ) + + def patch_routes_spend_limits( + self, *, user_id: str, request: UpdateRouteSpendLimitRequest + ) -> RouteSpendLimit: + """Updates a user's spend limits""" + return self._do_json( + RouteSpendLimit, + _ApiRequest( + method="PATCH", + path_fmt="/v1/routes/spend_limits/{}", + path_args=[user_id], + body=request, + query=None, + success_codes=[200], + error_codes=None, + ), + ) + def patch_teams_environment_groups( self, *, team_id: str, env_name: str, request: UpdateEnvironmentGroupRequest ) -> EnvironmentGroup: @@ -3057,6 +3171,23 @@ def post_llm_models_deployments( ), ) + def post_loops_checkpoints_deploy( + self, *, request: DeployLoopsCheckpointRequest + ) -> DeployLoopsCheckpointResponse: + """Deploys Loops checkpoints""" + return self._do_json( + DeployLoopsCheckpointResponse, + _ApiRequest( + method="POST", + path_fmt="/v1/loops/checkpoints/deploy", + path_args=[], + body=request, + query=None, + success_codes=[200], + error_codes=None, + ), + ) + def post_loops_checkpoints_validate( self, *, request: ValidateLoopsCheckpointRequest ) -> ValidateLoopsCheckpointResponse: @@ -3157,6 +3288,23 @@ def post_loops_samplers( ), ) + def post_loops_samplers_deactivate( + self, *, sampler_id: str + ) -> DeactivateLoopsSamplerResponse: + """Deactivates a standalone Loops sampler""" + return self._do_json( + DeactivateLoopsSamplerResponse, + _ApiRequest( + method="POST", + path_fmt="/v1/loops/samplers/{}/deactivate", + path_args=[sampler_id], + body=None, + query=None, + success_codes=[200], + error_codes=None, + ), + ) + def post_loops_sessions(self) -> CreateLoopsSessionResponse: """Creates a Loops session""" return self._do_json( @@ -4088,6 +4236,23 @@ def push_image( ), ) + def put_routes_harness_configs( + self, *, request: SetRouteHarnessConfigRequest + ) -> RouteHarnessConfig: + """Sets default models for a coding harness""" + return self._do_json( + RouteHarnessConfig, + _ApiRequest( + method="PUT", + path_fmt="/v1/routes/harness-configs", + path_args=[], + body=request, + query=None, + success_codes=[200], + error_codes=None, + ), + ) + def update_sandbox( self, *, @@ -4438,6 +4603,23 @@ async def delete_routes(self, *, route_id: str) -> RouteTombstone: ), ) + async def delete_routes_harness_configs( + self, *, harness: str, params: DeleteRoutesHarnessConfigsParams + ) -> RouteHarnessConfigTombstone: + """Clears default models for a coding harness""" + return await self._do_json( + RouteHarnessConfigTombstone, + _ApiRequest( + method="DELETE", + path_fmt="/v1/routes/harness-configs/{}", + path_args=[harness], + body=None, + query=params, + success_codes=[200], + error_codes=None, + ), + ) + async def delete_sandbox( self, *, sandbox_name: str, params: DeleteSandboxParams | None = None ) -> Sandbox: @@ -4983,6 +5165,23 @@ async def get_image( ), ) + async def get_image_build_logs( + self, *, image_name: str, params: GetImageBuildLogsParams | None = None + ) -> ImageBuildLogsResponse: + """Get image build logs""" + return await self._do_json( + ImageBuildLogsResponse, + _ApiRequest( + method="GET", + path_fmt="/v1/sandboxes/images/{}/logs", + path_args=[image_name], + body=None, + query=params, + success_codes=[200], + error_codes=None, + ), + ) + async def get_instance_type_prices(self) -> InstanceTypePrices: """Gets prices for available instance types""" return await self._do_json( @@ -5695,6 +5894,23 @@ async def get_routes( ), ) + async def get_routes_harness_configs( + self, *, params: GetRoutesHarnessConfigsParams + ) -> RouteHarnessConfigsResponse: + """Lists default models for coding harnesses""" + return await self._do_json( + RouteHarnessConfigsResponse, + _ApiRequest( + method="GET", + path_fmt="/v1/routes/harness-configs", + path_args=[], + body=None, + query=params, + success_codes=[200], + error_codes=None, + ), + ) + async def get_routes_route_id(self, *, route_id: str) -> Route: """Gets a route""" return await self._do_json( @@ -5710,6 +5926,21 @@ async def get_routes_route_id(self, *, route_id: str) -> Route: ), ) + async def get_routes_spend_limits(self, *, user_id: str) -> RouteSpendLimit: + """Gets a user's spend limits""" + return await self._do_json( + RouteSpendLimit, + _ApiRequest( + method="GET", + path_fmt="/v1/routes/spend_limits/{}", + path_args=[user_id], + body=None, + query=None, + success_codes=[200], + error_codes=None, + ), + ) + async def get_routes_usage( self, *, params: GetRoutesUsageParams | None = None ) -> RoutesUsageResponse: @@ -6649,6 +6880,40 @@ async def patch_routes( ), ) + async def patch_routes_harness_configs( + self, *, request: UpdateRouteHarnessConfigRequest + ) -> RouteHarnessConfig: + """Updates default models for a coding harness""" + return await self._do_json( + RouteHarnessConfig, + _ApiRequest( + method="PATCH", + path_fmt="/v1/routes/harness-configs", + path_args=[], + body=request, + query=None, + success_codes=[200], + error_codes=None, + ), + ) + + async def patch_routes_spend_limits( + self, *, user_id: str, request: UpdateRouteSpendLimitRequest + ) -> RouteSpendLimit: + """Updates a user's spend limits""" + return await self._do_json( + RouteSpendLimit, + _ApiRequest( + method="PATCH", + path_fmt="/v1/routes/spend_limits/{}", + path_args=[user_id], + body=request, + query=None, + success_codes=[200], + error_codes=None, + ), + ) + async def patch_teams_environment_groups( self, *, team_id: str, env_name: str, request: UpdateEnvironmentGroupRequest ) -> EnvironmentGroup: @@ -6950,6 +7215,23 @@ async def post_llm_models_deployments( ), ) + async def post_loops_checkpoints_deploy( + self, *, request: DeployLoopsCheckpointRequest + ) -> DeployLoopsCheckpointResponse: + """Deploys Loops checkpoints""" + return await self._do_json( + DeployLoopsCheckpointResponse, + _ApiRequest( + method="POST", + path_fmt="/v1/loops/checkpoints/deploy", + path_args=[], + body=request, + query=None, + success_codes=[200], + error_codes=None, + ), + ) + async def post_loops_checkpoints_validate( self, *, request: ValidateLoopsCheckpointRequest ) -> ValidateLoopsCheckpointResponse: @@ -7052,6 +7334,23 @@ async def post_loops_samplers( ), ) + async def post_loops_samplers_deactivate( + self, *, sampler_id: str + ) -> DeactivateLoopsSamplerResponse: + """Deactivates a standalone Loops sampler""" + return await self._do_json( + DeactivateLoopsSamplerResponse, + _ApiRequest( + method="POST", + path_fmt="/v1/loops/samplers/{}/deactivate", + path_args=[sampler_id], + body=None, + query=None, + success_codes=[200], + error_codes=None, + ), + ) + async def post_loops_sessions(self) -> CreateLoopsSessionResponse: """Creates a Loops session""" return await self._do_json( @@ -7989,6 +8288,23 @@ async def push_image( ), ) + async def put_routes_harness_configs( + self, *, request: SetRouteHarnessConfigRequest + ) -> RouteHarnessConfig: + """Sets default models for a coding harness""" + return await self._do_json( + RouteHarnessConfig, + _ApiRequest( + method="PUT", + path_fmt="/v1/routes/harness-configs", + path_args=[], + body=request, + query=None, + success_codes=[200], + error_codes=None, + ), + ) + async def update_sandbox( self, *, diff --git a/baseten/client/managementapi/_models.py b/baseten/client/managementapi/_models.py index 5039af5..200f447 100644 --- a/baseten/client/managementapi/_models.py +++ b/baseten/client/managementapi/_models.py @@ -299,6 +299,22 @@ class ResourceKind(StrEnum): CHAINLET = "CHAINLET" +class RouteHarness(StrEnum): + claude_code = "claude-code" + opencode = "opencode" + codex = "codex" + + +class RouteHarnessModelSource(StrEnum): + team = "team" + baseten = "baseten" + + +class RouteHarnessRole(StrEnum): + primary = "primary" + background = "background" + + class GatewayProvider(StrEnum): ANTHROPIC = "ANTHROPIC" OPENAI = "OPENAI" @@ -903,6 +919,28 @@ class GetRoutesParams(BaseModel): ] = None +class GetRoutesHarnessConfigsParams(BaseModel): + team_id: Annotated[ + str, + Field( + description="Identifier of the team whose default models to list.", + min_length=1, + title="Team Id", + ), + ] + + +class DeleteRoutesHarnessConfigsParams(BaseModel): + team_id: Annotated[ + str, + Field( + description="Identifier of the team whose default models to clear.", + min_length=1, + title="Team Id", + ), + ] + + class StatusItem(RootModel[str]): root: Annotated[str, Field(min_length=1)] @@ -975,6 +1013,12 @@ class GetSandboxParams(BaseModel): min_length=1, ), ] = None + show_secrets: Annotated[ + bool, + Field( + description="Reveal environment variable values for workspace administrators. Defaults to false. Callers without the admin role receive masked values even when true." + ), + ] = False class UpdateSandboxParams(BaseModel): @@ -997,6 +1041,16 @@ class DeleteSandboxParams(BaseModel): ] = None +class ListSandboxLibraryImagesParams(BaseModel): + team_id: Annotated[ + str | None, + Field( + description="Optional team ID. Must match X-Team-Id when both are supplied. If neither selector is supplied, defaults to the caller's only accessible team. Callers with multiple accessible teams must select a team. Requests without access to any team are forbidden.", + min_length=1, + ), + ] = None + + class ListImagesParams(BaseModel): team_id: Annotated[ str | None, @@ -1077,6 +1131,38 @@ class DeleteImageParams(BaseModel): ] = None +class GetImageBuildLogsParams(BaseModel): + team_id: Annotated[ + str | None, + Field( + description="Optional team ID. Must match X-Team-Id when both are supplied. If neither selector is supplied, defaults to the caller's only accessible team. Callers with multiple accessible teams must select a team. Requests without access to any team are forbidden.", + min_length=1, + ), + ] = None + start_time: Annotated[ + AwareDatetime | None, + Field( + description="Inclusive RFC 3339 start time. Defaults to 24 hours before end_time." + ), + ] = None + end_time: Annotated[ + AwareDatetime | None, + Field(description="RFC 3339 end time. Defaults to the current time."), + ] = None + limit: Annotated[ + int, + Field(description="Maximum number of log entries to return.", ge=1, le=1000), + ] = 100 + offset: Annotated[ + int, + Field( + description="Number of log entries to skip. Narrow the time range beyond 10000 entries.", + ge=0, + le=10000, + ), + ] = 0 + + class ListImageTagsParams(BaseModel): team_id: Annotated[ str | None, @@ -1133,16 +1219,6 @@ class DeleteImageTagParams(BaseModel): ] = None -class ListSandboxLibraryImagesParams(BaseModel): - team_id: Annotated[ - str | None, - Field( - description="Optional team ID. Must match X-Team-Id when both are supplied. If neither selector is supplied, defaults to the caller's only accessible team. Callers with multiple accessible teams must select a team. Requests without access to any team are forbidden.", - min_length=1, - ), - ] = None - - class PaginationResponse(BaseModel): has_more: Annotated[ bool, @@ -6082,6 +6158,20 @@ class CreateLoopsSamplerResponse(BaseModel): sampler: LoopsSampler +class DeactivateLoopsSamplerResponse(BaseModel): + id: Annotated[ + str, Field(description="The deactivated Loops sampler ID.", title="Id") + ] + base_model: Annotated[ + str, + Field( + description="The base model the deactivated sampler was serving.", + title="Base Model", + ), + ] + user: Annotated[User, Field(description="The user who owns the Loops sampler.")] + + class GetLoopsSamplerResponse(BaseModel): sampler: Annotated[LoopsSampler, Field(description="The Loops sampler.")] @@ -6160,6 +6250,50 @@ class ValidateLoopsCheckpointResponse(BaseModel): pass +class DeployLoopsCheckpointRequest(BaseModel): + checkpoint_ids: Annotated[ + list[str], + Field( + description="Sampler checkpoint IDs to deploy together.", + min_length=1, + title="Checkpoint Ids", + ), + ] + model_name: Annotated[ + str, + Field( + description="Name for the created model.", min_length=1, title="Model Name" + ), + ] + instance_type_id: Annotated[ + str, + Field( + description="Instance type ID for the deployment.", title="Instance Type Id" + ), + ] + hf_secret_name: Annotated[ + str, + Field( + description="Name of the team-scoped secret that supplies HF_TOKEN.", + min_length=1, + title="Hf Secret Name", + ), + ] + + +class DeployLoopsCheckpointResponse(BaseModel): + model_id: Annotated[ + str, Field(description="ID of the created or updated model.", title="Model Id") + ] + deployment_id: Annotated[ + str, + Field( + description="ID of the created model version deployment.", + title="Deployment Id", + ), + ] + + class LoopsCheckpointFilesResponse(BaseModel): presigned_urls: Annotated[ list[CheckpointFile], @@ -7635,7 +7769,7 @@ class ModelApiItem(BaseModel): model_name: Annotated[str, Field(description="Model name", title="Model Name")] model_family: Annotated[ str | None, - Field(description="Model family (e.g., llama, mistral)", title="Model Family"), + Field(description="Model family (e.g., Meta, DeepSeek)", title="Model Family"), ] = None subtotal: Annotated[ float | Subtotal5, @@ -8139,6 +8273,321 @@ class RouteUsageDimension(StrEnum): PROVIDER = "PROVIDER" +class RouteSpendLimit(BaseModel): + user_id: Annotated[ + str, Field(description="ID of the user.", examples=["abc1234"], title="User Id") + ] + email: Annotated[ + str | None, + Field( + description="Email address of the user.", + examples=["dev@example.com"], + title="Email", + ), + ] + monthly_limit_usd: Annotated[ + str | None, + Field( + description="Standing spend limit in USD for each UTC calendar month, returned as an exact decimal string. Null when the user has no standing limit.", + examples=["200"], + title="Monthly Limit Usd", + ), + ] + + +class UpdateRouteSpendLimitRequest(BaseModel): + model_config = ConfigDict( + extra="forbid", + ) + monthly_limit_usd: Annotated[ + str | None, + Field( + description="Standing spend limit in USD for each UTC calendar month, as a non-negative decimal string with at most 9 decimal places. Send null to remove the limit; omit to leave it unchanged.", + examples=["200"], + title="Monthly Limit Usd", + ), + ] = None + + +class Primary(RootModel[str]): + root: Annotated[ + str | None, + Field( + description="Route ID for the primary model, which new sessions use. Omit to keep the current route, or pass null to use Baseten's default.", + examples=["abc1234"], + min_length=1, + title="Primary", + ), + ] = None + + +class Background(RootModel[str]): + root: Annotated[ + str | None, + Field( + description="Route ID for background tasks, such as session titles. Omit to keep the current route, or pass null to use Baseten's default.", + examples=["def5678"], + min_length=1, + title="Background", + ), + ] = None + + +class UpdateBackgroundHarnessModels(BaseModel): + model_config = ConfigDict( + extra="forbid", + ) + primary: Annotated[ + Primary | None, + Field( + description="Route ID for the primary model, which new sessions use. Omit to keep the current route, or pass null to use Baseten's default.", + examples=["abc1234"], + title="Primary", + ), + ] = None + background: Annotated[ + Background | None, + Field( + description="Route ID for background tasks, such as session titles. Omit to keep the current route, or pass null to use Baseten's default.", + examples=["def5678"], + title="Background", + ), + ] = None + + +class UpdateClaudeCodeHarnessConfig(BaseModel): + model_config = ConfigDict( + extra="forbid", + ) + team_id: Annotated[ + str, + Field( + description="Identifier of the team whose default models to set. Every route must belong to this team.", + min_length=1, + title="Team Id", + ), + ] + harness: Annotated[ + Literal["claude-code"], + Field( + description="Claude Code, which supports the `primary` and `background` roles.", + title="Harness", + ), + ] + models: Annotated[ + UpdateBackgroundHarnessModels, + Field( + description="Route IDs for the model roles to change. Roles left out are unchanged." + ), + ] + + +class UpdateOpenCodeHarnessConfig(BaseModel): + model_config = ConfigDict( + extra="forbid", + ) + team_id: Annotated[ + str, + Field( + description="Identifier of the team whose default models to set. Every route must belong to this team.", + min_length=1, + title="Team Id", + ), + ] + harness: Annotated[ + Literal["opencode"], + Field( + description="OpenCode, which supports the `primary` and `background` roles.", + title="Harness", + ), + ] + models: Annotated[ + UpdateBackgroundHarnessModels, + Field( + description="Route IDs for the model roles to change. Roles left out are unchanged." + ), + ] + + +class UpdatePrimaryHarnessModels(BaseModel): + model_config = ConfigDict( + extra="forbid", + ) + primary: Annotated[ + Primary | None, + Field( + description="Route ID for the primary model, which new sessions use. Omit to keep the current route, or pass null to use Baseten's default.", + examples=["abc1234"], + title="Primary", + ), + ] = None + + +class Primary2(RootModel[str]): + root: Annotated[ + str | None, + Field( + description="Route ID for the primary model, which new sessions use. Omit to use Baseten's default.", + examples=["abc1234"], + min_length=1, + title="Primary", + ), + ] = None + + +class Background1(RootModel[str]): + root: Annotated[ + str | None, + Field( + description="Route ID for background tasks, such as session titles. Omit to use Baseten's default.", + examples=["def5678"], + min_length=1, + title="Background", + ), + ] = None + + +class BackgroundHarnessModels(BaseModel): + model_config = ConfigDict( + extra="forbid", + ) + primary: Annotated[ + Primary2 | None, + Field( + description="Route ID for the primary model, which new sessions use. Omit to use Baseten's default.", + examples=["abc1234"], + title="Primary", + ), + ] = None + background: Annotated[ + Background1 | None, + Field( + description="Route ID for background tasks, such as session titles. Omit to use Baseten's default.", + examples=["def5678"], + title="Background", + ), + ] = None + + +class PrimaryHarnessModels(BaseModel): + model_config = ConfigDict( + extra="forbid", + ) + primary: Annotated[ + Primary2 | None, + Field( + description="Route ID for the primary model, which new sessions use. Omit to use Baseten's default.", + examples=["abc1234"], + title="Primary", + ), + ] = None + + +class SetClaudeCodeHarnessConfig(BaseModel): + model_config = ConfigDict( + extra="forbid", + ) + team_id: Annotated[ + str, + Field( + description="Identifier of the team whose default models to set. Every route must belong to this team.", + min_length=1, + title="Team Id", + ), + ] + harness: Annotated[ + Literal["claude-code"], + Field( + description="Claude Code, which supports the `primary` and `background` roles.", + title="Harness", + ), + ] + models: Annotated[ + BackgroundHarnessModels, + Field( + description="Route ID for each model role. Roles left out use Baseten's defaults." + ), + ] + + +class SetCodexHarnessConfig(BaseModel): + model_config = ConfigDict( + extra="forbid", + ) + team_id: Annotated[ + str, + Field( + description="Identifier of the team whose default models to set. Every route must belong to this team.", + min_length=1, + title="Team Id", + ), + ] + harness: Annotated[ + Literal["codex"], + Field( + description="Codex, which supports only the `primary` role.", + title="Harness", + ), + ] + models: Annotated[ + PrimaryHarnessModels, + Field( + description="Route ID for each model role. Roles left out use Baseten's defaults." + ), + ] + + +class SetOpenCodeHarnessConfig(BaseModel): + model_config = ConfigDict( + extra="forbid", + ) + team_id: Annotated[ + str, + Field( + description="Identifier of the team whose default models to set. Every route must belong to this team.", + min_length=1, + title="Team Id", + ), + ] + harness: Annotated[ + Literal["opencode"], + Field( + description="OpenCode, which supports the `primary` and `background` roles.", + title="Harness", + ), + ] + models: Annotated[ + BackgroundHarnessModels, + Field( + description="Route ID for each model role. Roles left out use Baseten's defaults." + ), + ] + + +class SetRouteHarnessConfigRequest( + RootModel[ + SetClaudeCodeHarnessConfig | SetOpenCodeHarnessConfig | SetCodexHarnessConfig + ] +): + root: Annotated[ + SetClaudeCodeHarnessConfig | SetOpenCodeHarnessConfig | SetCodexHarnessConfig, + Field(discriminator="harness", title="SetRouteHarnessConfigRequestV1"), + ] + + +class RouteHarnessConfigTombstone(BaseModel): + harness: Annotated[ + RouteHarness, Field(description="Harness whose default models were cleared.") + ] + team_id: Annotated[ + str, + Field( + description="Identifier of the team whose default models were cleared.", + title="Team Id", + ), + ] + + class RouteTombstone(BaseModel): id: Annotated[ str, Field(description="Stable identifier of the deleted route.", title="Id") @@ -8583,6 +9032,22 @@ class RegisterAPIKeyResponse(BaseModel): ] +class ImageBuildLog(BaseModel): + timestamp: AwareDatetime + message: str + severity: Annotated[int, Field(description="Numeric OpenTelemetry severity level.")] + + +class ImageBuildLogsResponse(BaseModel): + logs: list[ImageBuildLog] + total_count: Annotated[ + int, + Field( + description="Number of matching log entries in the requested time range." + ), + ] + + class SandboxDuration(RootModel[str]): root: Annotated[ str, @@ -8665,9 +9130,12 @@ class SandboxEnv(BaseModel): Field(description="Name of the environment variable", examples=["NODE_ENV"]), ] = None secret: Annotated[ - bool | None, - Field(description="Whether the value is a secret", examples=[False]), - ] = None + bool, + Field( + description='Whether the value is a secret. Defaults to true; secret values are returned as "****". Set false explicitly to return the original value.', + examples=[False], + ), + ] = True value: Annotated[ str | None, Field(description="Value of the environment variable", examples=["production"]), @@ -8768,13 +9236,6 @@ class Image(BaseModel): examples=["base-image"], ), ] - display_name: Annotated[ - str | None, - Field( - description="Human-readable image repository name.", - examples=["b10/base-image"], - ), - ] = None status: Annotated[ ImageStatus, Field( @@ -8852,7 +9313,7 @@ class PushImageRequest(BaseModel): image: Annotated[ str | None, Field( - description="Optional source registry image reference including a registry hostname. When omitted, the response provides an archive upload URL.", + description="Optional source registry image reference including a registry hostname. When omitted, the response provides an archive upload URL. The uploaded ZIP archive must not exceed 5 GB.", examples=["docker.io/b10/base-image:latest"], ), ] = None @@ -8881,7 +9342,7 @@ class PushImageResponse(BaseModel): upload_url: Annotated[ AnyUrl | None, Field( - description="Temporary signed URL for uploading the source ZIP archive with HTTP PUT. Present only when no source image was supplied. Uploading starts asynchronous processing. This storage upload is separate from the API endpoints.", + description="Temporary signed URL for uploading the source ZIP archive with HTTP PUT. Present only when no source image was supplied. The uploaded ZIP archive must not exceed 5 GB. Uploading starts asynchronous processing. This storage upload is separate from the API endpoints.", examples=[ "https://uploads.b10.run/images/base-image/20260916212658/source.zip?expires=2026-09-16T22%3A26%3A58Z&signature=demo-not-a-valid-upload-signature" ], @@ -8896,21 +9357,6 @@ class PushImageResponse(BaseModel): ] = None -class CleanupImagesResponse(BaseModel): - deleted: Annotated[ - int, Field(description="Number of image versions removed.", examples=[3], ge=0) - ] - message: Annotated[ - str, - Field( - description="Human-readable cleanup result.", - examples=[ - "Removed 3 unused image versions. Image versions used by active sandboxes were retained." - ], - ), - ] - - class SandboxLibraryImageVolume(BaseModel): name: Annotated[ str, @@ -8954,6 +9400,21 @@ class SandboxLibraryImageCreationOptions(BaseModel): ] = None +class CleanupImagesResponse(BaseModel): + deleted: Annotated[ + int, Field(description="Number of image versions removed.", examples=[3], ge=0) + ] + message: Annotated[ + str, + Field( + description="Human-readable cleanup result.", + examples=[ + "Removed 3 unused image versions. Image versions used by active sandboxes were retained." + ], + ), + ] + + class Checkpoints( RootModel[ BasetenLatestCheckpointConfig @@ -11329,7 +11790,7 @@ class ModelAPI(BaseModel): str | None, Field( description="Family the underlying model belongs to.", - examples=["META", "DEEPSEEK", "QWEN"], + examples=["Meta", "DeepSeek", "Qwen"], title="Model Family", ), ] = None @@ -11920,6 +12381,58 @@ class RoutesUsageResponse(BaseModel): ] +class RouteHarnessModel(BaseModel): + source: Annotated[ + RouteHarnessModelSource, + Field( + description="Who chose this role's route: `team` if a team admin set it, or `baseten` if it is Baseten's default, chosen from the team's Model API routes." + ), + ] + route: Annotated[Route, Field(description="Route to use for this role.")] + + +class UpdateCodexHarnessConfig(BaseModel): + model_config = ConfigDict( + extra="forbid", + ) + team_id: Annotated[ + str, + Field( + description="Identifier of the team whose default models to set. Every route must belong to this team.", + min_length=1, + title="Team Id", + ), + ] + harness: Annotated[ + Literal["codex"], + Field( + description="Codex, which supports only the `primary` role.", + title="Harness", + ), + ] + models: Annotated[ + UpdatePrimaryHarnessModels, + Field( + description="Route IDs for the model roles to change. Roles left out are unchanged." + ), + ] + + +class UpdateRouteHarnessConfigRequest( + RootModel[ + UpdateClaudeCodeHarnessConfig + | UpdateOpenCodeHarnessConfig + | UpdateCodexHarnessConfig + ] +): + root: Annotated[ + UpdateClaudeCodeHarnessConfig + | UpdateOpenCodeHarnessConfig + | UpdateCodexHarnessConfig, + Field(discriminator="harness", title="UpdateRouteHarnessConfigRequestV1"), + ] + + class EndpointTarget(BaseModel): provider: Annotated[GatewayProvider, Field(description="Upstream provider.")] secret_id: Annotated[ @@ -12538,6 +13051,23 @@ class GetLoopsDeploymentMetricsResponse(BaseModel): ] +class RouteHarnessConfig(BaseModel): + models: Annotated[ + dict[RouteHarnessRole, RouteHarnessModel], + Field(description="Route for each model role, keyed by role.", title="Models"), + ] + + +class RouteHarnessConfigsResponse(BaseModel): + harness_configs: Annotated[ + dict[RouteHarness, RouteHarnessConfig], + Field( + description="Default models for each harness, keyed by harness. A harness is omitted when none of its roles has a route.", + title="Harness Configs", + ), + ] + + class EffectiveModelConfig(BaseModel): slug: Annotated[str, Field(description="Shared endpoint slug.", title="Slug")] rate_limits: Annotated[ @@ -12730,8 +13260,8 @@ class SandboxConfiguration(BaseModel): image: Annotated[ str | None, Field( - description="Image reference including its tag. Use blaxel/base-image:latest to get started with the built-in sandbox execution API. This image is available directly without building, pushing, or listing images through GET /v1/sandboxes/images.", - examples=["blaxel/base-image:latest"], + description="Image reference including its tag. Built-in image references are returned in the canonical baseten/ namespace. Use baseten/base-image:latest to get started with the built-in sandbox execution API. This image is available directly without building, pushing, or listing images through GET /v1/sandboxes/images.", + examples=["baseten/base-image:latest"], ), ] = None memory: Annotated[ @@ -12770,6 +13300,12 @@ class SandboxConfiguration(BaseModel): class CreateSandboxRequest(BaseModel): + create_if_not_exists: Annotated[ + bool | None, + Field( + description="When true, return the existing live sandbox with this name or recreate it if it is failed, terminated, or being deleted. The server handles concurrent creation and deletion races with a bounded wait; persistent contention returns a conflict. Requires name. Existing configuration is preserved. Defaults to false when omitted." + ), + ] = None name: Annotated[ str | None, Field( @@ -12851,20 +13387,20 @@ class CreateSandboxRequest(BaseModel): ), ] = None image: Annotated[ - str | None, + str, Field( - description="Image reference including its tag. Use blaxel/base-image:latest to get started with the built-in sandbox execution API. This image is available directly without building, pushing, or listing images through GET /v1/sandboxes/images.", - examples=["blaxel/base-image:latest"], + description="Image reference including its tag. Defaults to baseten/base-image:latest, the built-in sandbox execution API. This image is available directly without building, pushing, or listing images through GET /v1/sandboxes/images.", + examples=["baseten/base-image:latest"], ), - ] = None + ] = "baseten/base-image:latest" memory: Annotated[ - int | None, + int, Field( - description="Memory allocation in megabytes. Also determines CPU allocation (CPU cores = memory in MB / 2048, e.g., 4096MB = 2 CPUs).", + description="Memory allocation in megabytes. Also determines CPU allocation (CPU cores = memory in MB / 2048, e.g., 4096MB = 2 CPUs). Defaults to 4096.", examples=[4096], ge=1, ), - ] = None + ] = 4096 ports: Annotated[ SandboxPorts | None, Field( @@ -12890,12 +13426,6 @@ class CreateSandboxRequest(BaseModel): ], ), ] = None - create_if_not_exists: Annotated[ - bool | None, - Field( - description="When true, return the existing live sandbox with this name or recreate it if it is failed, terminated, or being deleted. The server handles concurrent creation and deletion races with a bounded wait; persistent contention returns a conflict. Requires name. Existing configuration is preserved. Defaults to false when omitted." - ), - ] = None class UpdateSandboxRequest(BaseModel): @@ -12948,8 +13478,8 @@ class UpdateSandboxRequest(BaseModel): image: Annotated[ str | None, Field( - description="Image reference including its tag. Use blaxel/base-image:latest to get started with the built-in sandbox execution API. This image is available directly without building, pushing, or listing images through GET /v1/sandboxes/images.", - examples=["blaxel/base-image:latest"], + description="Image reference including its tag. Built-in image references are returned in the canonical baseten/ namespace. Use baseten/base-image:latest to get started with the built-in sandbox execution API. This image is available directly without building, pushing, or listing images through GET /v1/sandboxes/images.", + examples=["baseten/base-image:latest"], ), ] = None ports: Annotated[ @@ -12993,12 +13523,12 @@ class Sandbox(SandboxConfiguration): ), ] url: Annotated[ - AnyUrl | None, + AnyUrl, Field( - description='Base URL of this sandbox\'s execution API. Use this exact returned URL; do not reconstruct its hostname. Authenticate requests with the same Authorization: Bearer header used to create the sandbox. No additional routing headers are required. Fetch GET {url}/swagger/doc.json with that header for the API reference served by this sandbox. For example, POST {url}/process with Content-Type: application/json and {"command":"echo hello","waitForCompletion":true} executes a command and waits for its result. Execution API fields use camelCase, independently of this API\'s snake_case fields.', + description='Base URL of this sandbox\'s execution API, always present on successful creation. The URL is assigned before deployment completes; inspect status for readiness. Use this exact returned URL; do not reconstruct its hostname. Authenticate requests with your authentication token using Authorization: Bearer . Do not send the Baseten API key directly. No additional routing headers are required. Fetch GET {url}/swagger/doc.json with that header for the API reference served by this sandbox. For example, POST {url}/process with Content-Type: application/json and {"command":"echo hello","waitForCompletion":true} executes a command and waits for its result. Execution API fields use camelCase, independently of this API\'s snake_case fields.', examples=["https://sbx-baseten-api-review-0916-esb1qo.us-pdx-1.b10.run"], ), - ] = None + ] status: Annotated[ SandboxStatus, Field(description="Sandbox deployment status.", examples=["DEPLOYED"]), @@ -13108,10 +13638,9 @@ class ListSandboxesResponse(BaseModel): }, {"name": "PORT", "secret": False, "value": "3000"}, ], - "image": "blaxel/base-image:latest", + "image": "baseten/base-image:latest", "memory": 4096, "ports": [{"name": "http", "protocol": "HTTP", "target": 3000}], - "display_name": "Baseten API review", "external_id": "api-review-20260916-001", "labels": { "env": "development", @@ -13121,7 +13650,6 @@ class ListSandboxesResponse(BaseModel): "name": "baseten-api-review-0916", "url": "https://sbx-baseten-api-review-0916-esb1qo.us-pdx-1.b10.run", "status": "DEPLOYED", - "state": "RUNNING", "created_at": "2026-09-16T21:26:58.545765901Z", "updated_at": "2026-09-16T21:31:13Z", "created_by": "sandbox-automation", diff --git a/baseten/client/sandboxapi/_client.py b/baseten/client/sandboxapi/_client.py index 048df45..261162e 100644 --- a/baseten/client/sandboxapi/_client.py +++ b/baseten/client/sandboxapi/_client.py @@ -577,7 +577,7 @@ def get_process_logs(self, *, identifier: str) -> ProcessLogs: ) def get_process_logs_stream(self, *, identifier: str) -> httpx.Response: - """Stream process logs in real time. Returns the response unread, in the requested content type. The caller must close the response.""" + """Stream process logs in real time. Returns the response unread. The caller must close the response.""" return self._do_raw( _ApiRequest( method="GET", @@ -594,7 +594,7 @@ def get_process_logs_stream(self, *, identifier: str) -> httpx.Response: def get_watch_filesystem( self, *, path: str, params: GetWatchFilesystemParams | None = None ) -> httpx.Response: - """Stream file modification events in a directory. Returns the response unread, in the requested content type. The caller must close the response.""" + """Stream file modification events in a directory. Returns the response unread. The caller must close the response.""" return self._do_raw( _ApiRequest( method="GET", @@ -863,7 +863,7 @@ def put_filesystem(self, *, path: str, request: FileRequest) -> SuccessResponse: def put_filesystem_multipart_part( self, *, upload_id: str, params: PutFilesystemMultipartPartParams, files: Any ) -> MultipartUploadPartResponse: - """Upload part""" + """Upload part. *files* is sent as httpx ``files``.""" return self._do_json( MultipartUploadPartResponse, _ApiRequest( @@ -1521,7 +1521,7 @@ async def get_process_logs(self, *, identifier: str) -> ProcessLogs: ) async def get_process_logs_stream(self, *, identifier: str) -> httpx.Response: - """Stream process logs in real time. Returns the response unread, in the requested content type. The caller must close the response.""" + """Stream process logs in real time. Returns the response unread. The caller must close the response.""" return await self._do_raw( _ApiRequest( method="GET", @@ -1538,7 +1538,7 @@ async def get_process_logs_stream(self, *, identifier: str) -> httpx.Response: async def get_watch_filesystem( self, *, path: str, params: GetWatchFilesystemParams | None = None ) -> httpx.Response: - """Stream file modification events in a directory. Returns the response unread, in the requested content type. The caller must close the response.""" + """Stream file modification events in a directory. Returns the response unread. The caller must close the response.""" return await self._do_raw( _ApiRequest( method="GET", @@ -1811,7 +1811,7 @@ async def put_filesystem( async def put_filesystem_multipart_part( self, *, upload_id: str, params: PutFilesystemMultipartPartParams, files: Any ) -> MultipartUploadPartResponse: - """Upload part""" + """Upload part. *files* is sent as httpx ``files``.""" return await self._do_json( MultipartUploadPartResponse, _ApiRequest( diff --git a/scripts/apigen/clientgen.py b/scripts/apigen/clientgen.py index ea02569..f00246b 100644 --- a/scripts/apigen/clientgen.py +++ b/scripts/apigen/clientgen.py @@ -100,6 +100,15 @@ def _extract_operations(spec: dict) -> list[_Operation]: for p in op_data.get("parameters", []) if isinstance(p, dict) and p.get("in") == "query" ] + json_responses = _json_response_refs(spec, op_data) + # Several JSON success codes return a union narrowed by type, so a + # schema shared by two codes would hide which code was returned. + json_refs = [ref for _, ref in json_responses] + if len(json_refs) != len(set(json_refs)): + raise ValueError( + f"{http_method.upper()} {path} shares a response schema " + f"across success codes: {json_responses}" + ) ops.append( _Operation( name=name, @@ -111,7 +120,7 @@ def _extract_operations(spec: dict) -> list[_Operation]: has_body="requestBody" in op_data, req_body_ref=_body_schema_ref(spec, op_data), body_content_type=_body_content_type(spec, op_data), - json_responses=_json_response_refs(spec, op_data), + json_responses=json_responses, raw_accepts=_raw_response_accepts(spec, op_data), success_codes=_extract_success_codes(op_data, http_method, path), error_codes=_error_code_map(spec, op_data), @@ -626,10 +635,11 @@ def _render_method(op: _Operation, *, is_async: bool, is_raw: bool) -> str: if op.summary: summary = op.summary if is_raw: - summary = summary.rstrip(".") - summary += ( - ". Returns the response unread, in the requested content" - " type. The caller must close the response." - ) + summary = summary.rstrip(".") + ". Returns the response unread" + if accept_expr == "accept": + summary += ", in the requested content type" + summary += ". The caller must close the response." + if body_arg == "files": + summary = summary.rstrip(".") + ". *files* is sent as httpx ``files``." sig += f'\n """{summary}"""' return f"{sig}\n {body}\n" diff --git a/scripts/apigen/specs/management.json b/scripts/apigen/specs/management.json index c692998..7e1635c 100644 --- a/scripts/apigen/specs/management.json +++ b/scripts/apigen/specs/management.json @@ -6594,7 +6594,7 @@ "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/runs/{run_id}/deactivate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" } ], - "description": "Shuts down a Loops run by ID, tearing down both the run and its paired sampler. Saved checkpoints remain accessible.", + "description": "Shuts down a Loops run by ID, tearing down both the run and its paired sampler. Succeeds if the run is already inactive. Saved checkpoints remain accessible.", "responses": { "200": { "description": "", @@ -6772,6 +6772,39 @@ } } }, + "/v1/loops/samplers/{sampler_id}/deactivate": { + "post": { + "summary": "Deactivates a standalone Loops sampler", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/loops/samplers/{sampler_id}/deactivate \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/samplers/{sampler_id}/deactivate\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + } + ], + "description": "Shuts down a standalone Loops sampler by ID. Succeeds if it is already inactive. A sampler paired to a run always returns 409 with the run's ID, even if it is inactive.", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeactivateLoopsSamplerResponseV1" + } + } + } + } + } + }, + "parameters": [ + { + "$ref": "#/components/parameters/sampler_id" + } + ] + }, "/v1/loops/samplers/{sampler_id}": { "get": { "summary": "Gets a Loops sampler", @@ -6936,6 +6969,44 @@ } } }, + "/v1/loops/checkpoints/deploy": { + "post": { + "summary": "Deploys Loops checkpoints", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request POST \\\n--url https://api.baseten.co/v1/loops/checkpoints/deploy \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"checkpoint_ids\": null,\n \"model_name\": null,\n \"instance_type_id\": null,\n \"hf_secret_name\": null\n}'" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/loops/checkpoints/deploy\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"POST\",\n url,\n headers=headers,\n json={'checkpoint_ids': None, 'model_name': None, 'instance_type_id': None, 'hf_secret_name': None}\n)\n\nprint(response.text)" + } + ], + "description": "Creates an inference deployment from one or more Loops sampler checkpoints. Confirm the user intends to create billable resources before calling it. This operation is not idempotent; repeating the request can create another deployment.", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeployLoopsCheckpointRequestV1" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeployLoopsCheckpointResponseV1" + } + } + } + } + } + } + }, "/v1/loops/checkpoints/{checkpoint_id}/files": { "get": { "summary": "Gets Loops checkpoint files", @@ -9685,6 +9756,240 @@ "x-stability": "unstable" } }, + "/v1/routes/spend_limits/{user_id}": { + "get": { + "summary": "Gets a user's spend limits", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/routes/spend_limits/{user_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/routes/spend_limits/{user_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n json={}\n)\n\nprint(response.text)" + } + ], + "description": "Spend limits cap what a Baseten Code user can spend each month. Personal API keys are not limited. Users can read their own spend limits; only organization admins can read other users' spend limits or change them.", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RouteSpendLimitV1" + } + } + } + } + }, + "x-stability": "unstable" + }, + "parameters": [ + { + "$ref": "#/components/parameters/user_id" + } + ], + "patch": { + "summary": "Updates a user's spend limits", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/routes/spend_limits/{user_id} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"monthly_limit_usd\": \"200\"\n}'" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/routes/spend_limits/{user_id}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'monthly_limit_usd': '200'}\n)\n\nprint(response.text)" + } + ], + "description": "Once the user's metered spend in a month reaches the limit, requests with Routes keys they created are rejected until the limit is raised or the next month starts. A limit of 0 blocks the user after their first metered request. Spend is metered every 15 minutes and can lag, so a user can go over the limit. If the user has spend this month, changes take effect within seconds; otherwise at the next metering run.", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateRouteSpendLimitRequestV1" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RouteSpendLimitV1" + } + } + } + } + }, + "x-stability": "unstable" + } + }, + "/v1/routes/harness-configs": { + "get": { + "summary": "Lists default models for coding harnesses", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request GET \\\n--url https://api.baseten.co/v1/routes/harness-configs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/routes/harness-configs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"GET\",\n url,\n headers=headers,\n params={'team_id': None}\n)\n\nprint(response.text)" + } + ], + "description": "Each role uses the route a team admin set for it (`source` is `team`). A role with no route set uses Baseten's default (`source` is `baseten`), chosen from the team's Model API routes: the recommended model for `primary` and the lowest-priced model for `background`. Baseten's defaults never use external-provider routes.", + "parameters": [ + { + "name": "team_id", + "in": "query", + "required": true, + "description": "Identifier of the team whose default models to list.", + "schema": { + "minLength": 1, + "title": "Team Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RouteHarnessConfigsResponseV1" + } + } + } + } + }, + "x-stability": "unstable" + }, + "patch": { + "summary": "Updates default models for a coding harness", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request PATCH \\\n--url https://api.baseten.co/v1/routes/harness-configs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"team_id\": \"abc1234\",\n \"harness\": \"claude-code\",\n \"models\": {\n \"background\": \"ghi9012\"\n }\n}'" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/routes/harness-configs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PATCH\",\n url,\n headers=headers,\n json={'team_id': 'abc1234', 'harness': 'claude-code', 'models': {'background': 'ghi9012'}}\n)\n\nprint(response.text)" + } + ], + "description": "Changes only the model roles in the request and leaves the others unchanged. Set a role to null to use Baseten's default. Requires team admin, and every route must belong to the team.", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateRouteHarnessConfigRequestV1" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RouteHarnessConfigV1" + } + } + } + } + }, + "x-stability": "unstable" + }, + "put": { + "summary": "Sets default models for a coding harness", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request PUT \\\n--url https://api.baseten.co/v1/routes/harness-configs \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\" \\\n--data '{\n \"team_id\": \"abc1234\",\n \"harness\": \"claude-code\",\n \"models\": {\n \"primary\": \"def5678\",\n \"background\": \"ghi9012\"\n }\n}'" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/routes/harness-configs\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"PUT\",\n url,\n headers=headers,\n json={'team_id': 'abc1234', 'harness': 'claude-code', 'models': {'primary': 'def5678', 'background': 'ghi9012'}}\n)\n\nprint(response.text)" + } + ], + "description": "Replaces every model role of one harness. Roles left out use Baseten's defaults. Requires team admin, and every route must belong to the team. The `harness` in the request body determines which roles are accepted.", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SetRouteHarnessConfigRequestV1" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RouteHarnessConfigV1" + } + } + } + } + }, + "x-stability": "unstable" + } + }, + "/v1/routes/harness-configs/{harness}": { + "delete": { + "summary": "Clears default models for a coding harness", + "x-codeSamples": [ + { + "lang": "bash", + "source": "curl --request DELETE \\\n--url https://api.baseten.co/v1/routes/harness-configs/{harness} \\\n--header \"Authorization: Bearer $BASETEN_API_KEY\"\n" + }, + { + "lang": "python", + "source": "import requests\nimport os\nAPI_KEY = os.environ.get(\"BASETEN_API_KEY\", \"\")\nurl = \"https://api.baseten.co/v1/routes/harness-configs/{harness}\"\n\nheaders = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nresponse = requests.request(\n \"DELETE\",\n url,\n headers=headers,\n params={'team_id': None}\n)\n\nprint(response.text)" + } + ], + "description": "Removes the team's routes for every role of the harness, so each role uses Baseten's default. Requires team admin.", + "parameters": [ + { + "name": "team_id", + "in": "query", + "required": true, + "description": "Identifier of the team whose default models to clear.", + "schema": { + "minLength": 1, + "title": "Team Id", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RouteHarnessConfigTombstoneV1" + } + } + } + } + }, + "x-stability": "unstable" + }, + "parameters": [ + { + "$ref": "#/components/parameters/harness" + } + ] + }, "/v1/routes/{route_id}": { "delete": { "summary": "Deletes a route", @@ -10324,12 +10629,12 @@ ], "operationId": "CreateSandbox", "summary": "Create a sandbox", - "description": "Create a sandbox with an optional client-provided name, generated by the server when omitted. The request waits briefly for deployment, then returns the created resource. Deployment may continue after the response; inspect status to determine readiness. Names belonging to failed or terminated sandboxes can be reused; an active sandbox reserves its name. To get started, set image to blaxel/base-image:latest, the built-in image with the sandbox execution API ready to use. It is available directly; no image build, push, or GET /v1/sandboxes/images is needed. Use the returned url to execute commands with the same Bearer API key.", + "description": "Create a sandbox with an optional client-provided name, generated by the server when omitted. The request waits briefly for deployment, then returns the created resource. Deployment may continue after the response; inspect status to determine readiness. Names belonging to failed or terminated sandboxes can be reused; an active sandbox reserves its name. Every field is optional. The server applies image and memory defaults; SDKs should omit fields the caller did not set. A request with no body creates a sandbox from baseten/base-image:latest, the built-in image with the sandbox execution API ready to use, with 4096 MB of memory. It is available directly; no image build, push, or GET /v1/sandboxes/images is needed. Use the returned url to execute commands with your authentication token as a Bearer token, not your Baseten API key.", "tags": [ "Sandboxes" ], "requestBody": { - "required": true, + "required": false, "content": { "application/json": { "schema": { @@ -10404,7 +10709,7 @@ "get": { "operationId": "GetSandbox", "summary": "Get a sandbox", - "description": "Return the sandbox configuration and current state.", + "description": "Return the sandbox configuration and status.", "tags": [ "Sandboxes" ], @@ -10414,6 +10719,15 @@ }, { "$ref": "#/components/parameters/TeamIdHeader" + }, + { + "name": "show_secrets", + "in": "query", + "description": "Reveal environment variable values for workspace administrators. Defaults to false. Callers without the admin role receive masked values even when true.", + "schema": { + "type": "boolean", + "default": false + } } ], "responses": { @@ -10581,7 +10895,55 @@ "x-stability": "unstable" } }, - "/v1/sandboxes/images": { + "/v1/sandboxes/library_images": { + "get": { + "operationId": "ListSandboxLibraryImages", + "summary": "List built-in sandbox images", + "description": "Return the built-in sandbox images available to every team. Use the image field directly as the image of a sandbox, without building or pushing it. Hidden and upcoming images are excluded.", + "tags": [ + "Images" + ], + "parameters": [ + { + "$ref": "#/components/parameters/TeamId" + }, + { + "$ref": "#/components/parameters/TeamIdHeader" + } + ], + "responses": { + "200": { + "description": "Successful operation.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ListSandboxLibraryImagesResponseV1" + }, + "examples": { + "complete": { + "$ref": "#/components/examples/SandboxLibraryImages" + } + } + } + } + }, + "401": { + "$ref": "#/components/responses/SandboxError401" + }, + "403": { + "$ref": "#/components/responses/SandboxError403" + }, + "429": { + "$ref": "#/components/responses/SandboxError429" + }, + "500": { + "$ref": "#/components/responses/SandboxError500" + } + }, + "x-stability": "unstable" + } + }, + "/v1/sandboxes/images": { "get": { "operationId": "ListImages", "summary": "List sandbox images", @@ -10665,7 +11027,7 @@ ], "operationId": "PushImage", "summary": "Push a sandbox image", - "description": "With image supplied, import the registry image asynchronously. Otherwise return an upload URL for a ZIP source archive containing its Dockerfile and build context. Processing starts after upload. No sandbox is created. Poll the image until BUILT or FAILED.", + "description": "With image supplied, import the registry image asynchronously. Otherwise return an upload URL for a ZIP source archive containing its Dockerfile and build context. The uploaded ZIP archive must not exceed 5 GB. Processing starts after upload. No sandbox is created. Poll the image until BUILT or FAILED.", "tags": [ "Images" ], @@ -10884,6 +11246,113 @@ "x-stability": "unstable" } }, + "/v1/sandboxes/images/{image_name}/logs": { + "parameters": [ + { + "$ref": "#/components/parameters/ImageName" + } + ], + "get": { + "operationId": "GetImageBuildLogs", + "summary": "Get image build logs", + "description": "Return one page of logs from the latest recorded build of this image, including failed builds, newest first. Logs may take a short time to appear. Defaults to the last 24 hours; the requested time range must not exceed 7 days. Keep start_time and end_time fixed when paging with offset. A new build changes the log source; this endpoint does not retrieve a historical build by ID. While a new upload is waiting to start, logs may still refer to the preceding build. Older builds without a recorded environment use image-level build logs within the requested time range.", + "tags": [ + "Images" + ], + "parameters": [ + { + "$ref": "#/components/parameters/TeamId" + }, + { + "$ref": "#/components/parameters/TeamIdHeader" + }, + { + "name": "start_time", + "in": "query", + "description": "Inclusive RFC 3339 start time. Defaults to 24 hours before end_time.", + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "end_time", + "in": "query", + "description": "RFC 3339 end time. Defaults to the current time.", + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "limit", + "in": "query", + "description": "Maximum number of log entries to return.", + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 1000, + "default": 100 + } + }, + { + "name": "offset", + "in": "query", + "description": "Number of log entries to skip. Narrow the time range beyond 10000 entries.", + "schema": { + "type": "integer", + "minimum": 0, + "maximum": 10000, + "default": 0 + } + } + ], + "responses": { + "200": { + "description": "Build logs in the requested time range. An empty array means no logs are available in that range.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ImageBuildLogsResponseV1" + }, + "example": { + "logs": [ + { + "timestamp": "2026-09-29T12:00:00Z", + "message": "Step 1/2: loading build context", + "severity": 9 + } + ], + "total_count": 1 + } + } + } + }, + "400": { + "$ref": "#/components/responses/SandboxError400" + }, + "401": { + "$ref": "#/components/responses/SandboxError401" + }, + "403": { + "$ref": "#/components/responses/SandboxError403" + }, + "404": { + "$ref": "#/components/responses/SandboxError404" + }, + "429": { + "$ref": "#/components/responses/SandboxError429" + }, + "500": { + "$ref": "#/components/responses/SandboxError500" + }, + "503": { + "description": "Build log service is temporarily unavailable. Returns a JSON error with code and message." + } + }, + "x-stability": "unstable" + } + }, "/v1/sandboxes/images/{image_name}/tags": { "parameters": [ { @@ -11030,54 +11499,6 @@ }, "x-stability": "unstable" } - }, - "/v1/sandboxes/library_images": { - "get": { - "operationId": "ListSandboxLibraryImages", - "summary": "List built-in sandbox images", - "description": "Return the built-in sandbox images available to every team. Use the image field directly as the image of a sandbox, without building or pushing it. Hidden and upcoming images are excluded.", - "tags": [ - "Images" - ], - "parameters": [ - { - "$ref": "#/components/parameters/TeamId" - }, - { - "$ref": "#/components/parameters/TeamIdHeader" - } - ], - "responses": { - "200": { - "description": "Successful operation.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ListSandboxLibraryImagesResponseV1" - }, - "examples": { - "complete": { - "$ref": "#/components/examples/SandboxLibraryImages" - } - } - } - } - }, - "401": { - "$ref": "#/components/responses/SandboxError401" - }, - "403": { - "$ref": "#/components/responses/SandboxError403" - }, - "429": { - "$ref": "#/components/responses/SandboxError429" - }, - "500": { - "$ref": "#/components/responses/SandboxError500" - } - }, - "x-stability": "unstable" - } } }, "openapi": "3.1.0", @@ -25697,6 +26118,32 @@ "title": "CreateLoopsSamplerResponseV1", "type": "object" }, + "DeactivateLoopsSamplerResponseV1": { + "description": "Response for ``POST /v1/loops/samplers//deactivate``.", + "properties": { + "id": { + "description": "The deactivated Loops sampler ID.", + "title": "Id", + "type": "string" + }, + "base_model": { + "description": "The base model the deactivated sampler was serving.", + "title": "Base Model", + "type": "string" + }, + "user": { + "$ref": "#/components/schemas/UserV1", + "description": "The user who owns the Loops sampler." + } + }, + "required": [ + "id", + "base_model", + "user" + ], + "title": "DeactivateLoopsSamplerResponseV1", + "type": "object" + }, "GetLoopsSamplerResponseV1": { "description": "Response for ``GET /v1/loops/samplers/``.", "properties": { @@ -25908,6 +26355,64 @@ "title": "ValidateLoopsCheckpointResponseV1", "type": "object" }, + "DeployLoopsCheckpointRequestV1": { + "properties": { + "checkpoint_ids": { + "description": "Sampler checkpoint IDs to deploy together.", + "items": { + "type": "string" + }, + "minItems": 1, + "title": "Checkpoint Ids", + "type": "array" + }, + "model_name": { + "description": "Name for the created model.", + "minLength": 1, + "title": "Model Name", + "type": "string" + }, + "instance_type_id": { + "description": "Instance type ID for the deployment.", + "title": "Instance Type Id", + "type": "string" + }, + "hf_secret_name": { + "description": "Name of the team-scoped secret that supplies HF_TOKEN.", + "minLength": 1, + "title": "Hf Secret Name", + "type": "string" + } + }, + "required": [ + "checkpoint_ids", + "model_name", + "instance_type_id", + "hf_secret_name" + ], + "title": "DeployLoopsCheckpointRequestV1", + "type": "object" + }, + "DeployLoopsCheckpointResponseV1": { + "properties": { + "model_id": { + "description": "ID of the created or updated model.", + "title": "Model Id", + "type": "string" + }, + "deployment_id": { + "description": "ID of the created model version deployment.", + "title": "Deployment Id", + "type": "string" + } + }, + "required": [ + "model_id", + "deployment_id" + ], + "title": "DeployLoopsCheckpointResponseV1", + "type": "object" + }, "LoopsCheckpointFilesResponseV1": { "description": "Response with presigned URLs for files under a Loops checkpoint.", "properties": { @@ -27640,9 +28145,9 @@ "default": null, "description": "Family the underlying model belongs to.", "examples": [ - "META", - "DEEPSEEK", - "QWEN" + "Meta", + "DeepSeek", + "Qwen" ], "title": "Model Family" }, @@ -29944,7 +30449,7 @@ } ], "default": null, - "description": "Model family (e.g., llama, mistral)", + "description": "Model family (e.g., Meta, DeepSeek)", "title": "Model Family" }, "subtotal": { @@ -31627,10 +32132,439 @@ "title": "Limit", "type": "integer" }, - "start_date": { + "start_date": { + "anyOf": [ + { + "format": "date", + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Inclusive UTC calendar day at the start of the query range. Defaults to the previous UTC date, and is ignored when you pass a cursor.", + "title": "Start Date" + }, + "end_date": { + "anyOf": [ + { + "format": "date", + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Exclusive UTC calendar day at the end of the query range. Defaults to the day after the current UTC date so current-day usage is included.", + "title": "End Date" + }, + "group_by": { + "description": "Dimensions to break usage down by, repeated once per dimension: USER, MODEL, or PROVIDER. Each result represents one observed combination of the requested dimensions within that day, and results are sorted by those values. Combinations without usage are omitted, so result counts can differ between days. Defaults to MODEL.", + "items": { + "$ref": "#/components/schemas/RouteUsageDimensionV1" + }, + "title": "Group By", + "type": "array" + }, + "user_ids": { + "description": "Return only usage from Routes keys created by these user IDs, repeated once per ID.", + "items": { + "type": "string" + }, + "title": "User Ids", + "type": "array" + }, + "models": { + "description": "Return only usage for these exact model names, repeated once per model.", + "items": { + "type": "string" + }, + "title": "Models", + "type": "array" + }, + "providers": { + "description": "Return only usage for these providers, repeated once per provider.", + "items": { + "$ref": "#/components/schemas/RouteProviderV1" + }, + "title": "Providers", + "type": "array" + } + }, + "title": "RoutesUsageRequestV1", + "type": "object" + }, + "RouteSpendLimitV1": { + "properties": { + "user_id": { + "description": "ID of the user.", + "examples": [ + "abc1234" + ], + "title": "User Id", + "type": "string" + }, + "email": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Email address of the user.", + "examples": [ + "dev@example.com" + ], + "title": "Email" + }, + "monthly_limit_usd": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Standing spend limit in USD for each UTC calendar month, returned as an exact decimal string. Null when the user has no standing limit.", + "examples": [ + "200" + ], + "title": "Monthly Limit Usd" + } + }, + "required": [ + "user_id", + "email", + "monthly_limit_usd" + ], + "title": "RouteSpendLimitV1", + "type": "object" + }, + "UpdateRouteSpendLimitRequestV1": { + "additionalProperties": false, + "minProperties": 1, + "properties": { + "monthly_limit_usd": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Standing spend limit in USD for each UTC calendar month, as a non-negative decimal string with at most 9 decimal places. Send null to remove the limit; omit to leave it unchanged.", + "examples": [ + "200" + ], + "title": "Monthly Limit Usd", + "x-null-distinct": true + } + }, + "title": "UpdateRouteSpendLimitRequestV1", + "type": "object" + }, + "RouteHarness": { + "enum": [ + "claude-code", + "opencode", + "codex" + ], + "title": "RouteHarness", + "type": "string" + }, + "RouteHarnessConfigV1": { + "properties": { + "models": { + "additionalProperties": { + "$ref": "#/components/schemas/RouteHarnessModelV1" + }, + "description": "Route for each model role, keyed by role.", + "propertyNames": { + "$ref": "#/components/schemas/RouteHarnessRole" + }, + "title": "Models", + "type": "object" + } + }, + "required": [ + "models" + ], + "title": "RouteHarnessConfigV1", + "type": "object" + }, + "RouteHarnessModelSource": { + "enum": [ + "team", + "baseten" + ], + "title": "RouteHarnessModelSource", + "type": "string" + }, + "RouteHarnessModelV1": { + "properties": { + "source": { + "$ref": "#/components/schemas/RouteHarnessModelSource", + "description": "Who chose this role's route: `team` if a team admin set it, or `baseten` if it is Baseten's default, chosen from the team's Model API routes." + }, + "route": { + "$ref": "#/components/schemas/RouteV1", + "description": "Route to use for this role." + } + }, + "required": [ + "source", + "route" + ], + "title": "RouteHarnessModelV1", + "type": "object" + }, + "RouteHarnessRole": { + "enum": [ + "primary", + "background" + ], + "title": "RouteHarnessRole", + "type": "string" + }, + "RouteHarnessConfigsResponseV1": { + "properties": { + "harness_configs": { + "additionalProperties": { + "$ref": "#/components/schemas/RouteHarnessConfigV1" + }, + "description": "Default models for each harness, keyed by harness. A harness is omitted when none of its roles has a route.", + "propertyNames": { + "$ref": "#/components/schemas/RouteHarness" + }, + "title": "Harness Configs", + "type": "object" + } + }, + "required": [ + "harness_configs" + ], + "title": "RouteHarnessConfigsResponseV1", + "type": "object" + }, + "RouteHarnessConfigsRequestV1": { + "properties": { + "team_id": { + "description": "Identifier of the team whose default models to list.", + "minLength": 1, + "title": "Team Id", + "type": "string" + } + }, + "required": [ + "team_id" + ], + "title": "RouteHarnessConfigsRequestV1", + "type": "object" + }, + "UpdateBackgroundHarnessModelsV1": { + "additionalProperties": false, + "minProperties": 1, + "properties": { + "primary": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Route ID for the primary model, which new sessions use. Omit to keep the current route, or pass null to use Baseten's default.", + "examples": [ + "abc1234" + ], + "title": "Primary" + }, + "background": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Route ID for background tasks, such as session titles. Omit to keep the current route, or pass null to use Baseten's default.", + "examples": [ + "def5678" + ], + "title": "Background" + } + }, + "title": "UpdateBackgroundHarnessModelsV1", + "type": "object" + }, + "UpdateClaudeCodeHarnessConfigV1": { + "additionalProperties": false, + "properties": { + "team_id": { + "description": "Identifier of the team whose default models to set. Every route must belong to this team.", + "minLength": 1, + "title": "Team Id", + "type": "string" + }, + "harness": { + "const": "claude-code", + "description": "Claude Code, which supports the `primary` and `background` roles.", + "title": "Harness", + "type": "string" + }, + "models": { + "$ref": "#/components/schemas/UpdateBackgroundHarnessModelsV1", + "description": "Route IDs for the model roles to change. Roles left out are unchanged." + } + }, + "required": [ + "team_id", + "harness", + "models" + ], + "title": "UpdateClaudeCodeHarnessConfigV1", + "type": "object" + }, + "UpdateCodexHarnessConfigV1": { + "additionalProperties": false, + "properties": { + "team_id": { + "description": "Identifier of the team whose default models to set. Every route must belong to this team.", + "minLength": 1, + "title": "Team Id", + "type": "string" + }, + "harness": { + "const": "codex", + "description": "Codex, which supports only the `primary` role.", + "title": "Harness", + "type": "string" + }, + "models": { + "$ref": "#/components/schemas/UpdatePrimaryHarnessModelsV1", + "description": "Route IDs for the model roles to change. Roles left out are unchanged." + } + }, + "required": [ + "team_id", + "harness", + "models" + ], + "title": "UpdateCodexHarnessConfigV1", + "type": "object" + }, + "UpdateOpenCodeHarnessConfigV1": { + "additionalProperties": false, + "properties": { + "team_id": { + "description": "Identifier of the team whose default models to set. Every route must belong to this team.", + "minLength": 1, + "title": "Team Id", + "type": "string" + }, + "harness": { + "const": "opencode", + "description": "OpenCode, which supports the `primary` and `background` roles.", + "title": "Harness", + "type": "string" + }, + "models": { + "$ref": "#/components/schemas/UpdateBackgroundHarnessModelsV1", + "description": "Route IDs for the model roles to change. Roles left out are unchanged." + } + }, + "required": [ + "team_id", + "harness", + "models" + ], + "title": "UpdateOpenCodeHarnessConfigV1", + "type": "object" + }, + "UpdatePrimaryHarnessModelsV1": { + "additionalProperties": false, + "minProperties": 1, + "properties": { + "primary": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Route ID for the primary model, which new sessions use. Omit to keep the current route, or pass null to use Baseten's default.", + "examples": [ + "abc1234" + ], + "title": "Primary" + } + }, + "title": "UpdatePrimaryHarnessModelsV1", + "type": "object" + }, + "UpdateRouteHarnessConfigRequestV1": { + "discriminator": { + "mapping": { + "claude-code": "#/components/schemas/UpdateClaudeCodeHarnessConfigV1", + "codex": "#/components/schemas/UpdateCodexHarnessConfigV1", + "opencode": "#/components/schemas/UpdateOpenCodeHarnessConfigV1" + }, + "propertyName": "harness" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/UpdateClaudeCodeHarnessConfigV1" + }, + { + "$ref": "#/components/schemas/UpdateOpenCodeHarnessConfigV1" + }, + { + "$ref": "#/components/schemas/UpdateCodexHarnessConfigV1" + } + ], + "title": "UpdateRouteHarnessConfigRequestV1" + }, + "BackgroundHarnessModelsV1": { + "additionalProperties": false, + "properties": { + "primary": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Route ID for the primary model, which new sessions use. Omit to use Baseten's default.", + "examples": [ + "abc1234" + ], + "title": "Primary" + }, + "background": { "anyOf": [ { - "format": "date", + "minLength": 1, "type": "string" }, { @@ -31638,13 +32572,23 @@ } ], "default": null, - "description": "Inclusive UTC calendar day at the start of the query range. Defaults to the previous UTC date, and is ignored when you pass a cursor.", - "title": "Start Date" - }, - "end_date": { + "description": "Route ID for background tasks, such as session titles. Omit to use Baseten's default.", + "examples": [ + "def5678" + ], + "title": "Background" + } + }, + "title": "BackgroundHarnessModelsV1", + "type": "object" + }, + "PrimaryHarnessModelsV1": { + "additionalProperties": false, + "properties": { + "primary": { "anyOf": [ { - "format": "date", + "minLength": 1, "type": "string" }, { @@ -31652,43 +32596,154 @@ } ], "default": null, - "description": "Exclusive UTC calendar day at the end of the query range. Defaults to the day after the current UTC date so current-day usage is included.", - "title": "End Date" + "description": "Route ID for the primary model, which new sessions use. Omit to use Baseten's default.", + "examples": [ + "abc1234" + ], + "title": "Primary" + } + }, + "title": "PrimaryHarnessModelsV1", + "type": "object" + }, + "SetClaudeCodeHarnessConfigV1": { + "additionalProperties": false, + "properties": { + "team_id": { + "description": "Identifier of the team whose default models to set. Every route must belong to this team.", + "minLength": 1, + "title": "Team Id", + "type": "string" }, - "group_by": { - "description": "Dimensions to break usage down by, repeated once per dimension: USER, MODEL, or PROVIDER. Each result represents one observed combination of the requested dimensions within that day, and results are sorted by those values. Combinations without usage are omitted, so result counts can differ between days. Defaults to MODEL.", - "items": { - "$ref": "#/components/schemas/RouteUsageDimensionV1" - }, - "title": "Group By", - "type": "array" + "harness": { + "const": "claude-code", + "description": "Claude Code, which supports the `primary` and `background` roles.", + "title": "Harness", + "type": "string" }, - "user_ids": { - "description": "Return only usage from Routes keys created by these user IDs, repeated once per ID.", - "items": { - "type": "string" - }, - "title": "User Ids", - "type": "array" + "models": { + "$ref": "#/components/schemas/BackgroundHarnessModelsV1", + "description": "Route ID for each model role. Roles left out use Baseten's defaults." + } + }, + "required": [ + "team_id", + "harness", + "models" + ], + "title": "SetClaudeCodeHarnessConfigV1", + "type": "object" + }, + "SetCodexHarnessConfigV1": { + "additionalProperties": false, + "properties": { + "team_id": { + "description": "Identifier of the team whose default models to set. Every route must belong to this team.", + "minLength": 1, + "title": "Team Id", + "type": "string" + }, + "harness": { + "const": "codex", + "description": "Codex, which supports only the `primary` role.", + "title": "Harness", + "type": "string" }, "models": { - "description": "Return only usage for these exact model names, repeated once per model.", - "items": { - "type": "string" - }, - "title": "Models", - "type": "array" + "$ref": "#/components/schemas/PrimaryHarnessModelsV1", + "description": "Route ID for each model role. Roles left out use Baseten's defaults." + } + }, + "required": [ + "team_id", + "harness", + "models" + ], + "title": "SetCodexHarnessConfigV1", + "type": "object" + }, + "SetOpenCodeHarnessConfigV1": { + "additionalProperties": false, + "properties": { + "team_id": { + "description": "Identifier of the team whose default models to set. Every route must belong to this team.", + "minLength": 1, + "title": "Team Id", + "type": "string" }, - "providers": { - "description": "Return only usage for these providers, repeated once per provider.", - "items": { - "$ref": "#/components/schemas/RouteProviderV1" - }, - "title": "Providers", - "type": "array" + "harness": { + "const": "opencode", + "description": "OpenCode, which supports the `primary` and `background` roles.", + "title": "Harness", + "type": "string" + }, + "models": { + "$ref": "#/components/schemas/BackgroundHarnessModelsV1", + "description": "Route ID for each model role. Roles left out use Baseten's defaults." } }, - "title": "RoutesUsageRequestV1", + "required": [ + "team_id", + "harness", + "models" + ], + "title": "SetOpenCodeHarnessConfigV1", + "type": "object" + }, + "SetRouteHarnessConfigRequestV1": { + "discriminator": { + "mapping": { + "claude-code": "#/components/schemas/SetClaudeCodeHarnessConfigV1", + "codex": "#/components/schemas/SetCodexHarnessConfigV1", + "opencode": "#/components/schemas/SetOpenCodeHarnessConfigV1" + }, + "propertyName": "harness" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/SetClaudeCodeHarnessConfigV1" + }, + { + "$ref": "#/components/schemas/SetOpenCodeHarnessConfigV1" + }, + { + "$ref": "#/components/schemas/SetCodexHarnessConfigV1" + } + ], + "title": "SetRouteHarnessConfigRequestV1" + }, + "RouteHarnessConfigTombstoneV1": { + "properties": { + "harness": { + "$ref": "#/components/schemas/RouteHarness", + "description": "Harness whose default models were cleared." + }, + "team_id": { + "description": "Identifier of the team whose default models were cleared.", + "title": "Team Id", + "type": "string" + } + }, + "required": [ + "harness", + "team_id" + ], + "title": "RouteHarnessConfigTombstoneV1", + "type": "object" + }, + "ClearRouteHarnessConfigRequestV1": { + "properties": { + "team_id": { + "description": "Identifier of the team whose default models to clear.", + "minLength": 1, + "title": "Team Id", + "type": "string" + } + }, + "required": [ + "team_id" + ], + "title": "ClearRouteHarnessConfigRequestV1", "type": "object" }, "RouteTombstoneV1": { @@ -32822,6 +33877,47 @@ "title": "RegisterAPIKeyResponseV1", "type": "object" }, + "ImageBuildLogV1": { + "type": "object", + "required": [ + "timestamp", + "message", + "severity" + ], + "properties": { + "timestamp": { + "type": "string", + "format": "date-time" + }, + "message": { + "type": "string" + }, + "severity": { + "type": "integer", + "description": "Numeric OpenTelemetry severity level." + } + } + }, + "ImageBuildLogsResponseV1": { + "type": "object", + "required": [ + "logs", + "total_count" + ], + "properties": { + "logs": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ImageBuildLogV1" + } + }, + "total_count": { + "type": "integer", + "format": "int64", + "description": "Number of matching log entries in the requested time range." + } + } + }, "SandboxLifecycleV1": { "type": "object", "description": "Lifecycle configuration controlling automatic sandbox deletion based on idle time, max age, or specific dates", @@ -33239,7 +34335,8 @@ }, "secret": { "type": "boolean", - "description": "Whether the value is a secret", + "description": "Whether the value is a secret. Defaults to true; secret values are returned as \"****\". Set false explicitly to return the original value.", + "default": true, "example": false }, "value": { @@ -33423,8 +34520,8 @@ }, "image": { "type": "string", - "description": "Image reference including its tag. Use blaxel/base-image:latest to get started with the built-in sandbox execution API. This image is available directly without building, pushing, or listing images through GET /v1/sandboxes/images.", - "example": "blaxel/base-image:latest" + "description": "Image reference including its tag. Built-in image references are returned in the canonical baseten/ namespace. Use baseten/base-image:latest to get started with the built-in sandbox execution API. This image is available directly without building, pushing, or listing images through GET /v1/sandboxes/images.", + "example": "baseten/base-image:latest" }, "memory": { "type": "integer", @@ -33537,7 +34634,7 @@ "value": "3000" } ], - "image": "blaxel/base-image:latest", + "image": "baseten/base-image:latest", "memory": 4096, "ports": [ { @@ -33546,7 +34643,6 @@ "target": 3000 } ], - "display_name": "Baseten API review", "external_id": "api-review-20260916-001", "labels": { "env": "development", @@ -33559,6 +34655,10 @@ "type": "object", "description": "Configuration for a new sandbox. The client may provide a name; otherwise the server generates one. The name is immutable after creation.", "properties": { + "create_if_not_exists": { + "type": "boolean", + "description": "When true, return the existing live sandbox with this name or recreate it if it is failed, terminated, or being deleted. The server handles concurrent creation and deletion races with a bounded wait; persistent contention returns a conflict. Requires name. Existing configuration is preserved. Defaults to false when omitted." + }, "name": { "type": "string", "description": "Optional unique sandbox name. Generated by the server when omitted; immutable after creation.", @@ -33661,12 +34761,14 @@ }, "image": { "type": "string", - "description": "Image reference including its tag. Use blaxel/base-image:latest to get started with the built-in sandbox execution API. This image is available directly without building, pushing, or listing images through GET /v1/sandboxes/images.", - "example": "blaxel/base-image:latest" + "description": "Image reference including its tag. Defaults to baseten/base-image:latest, the built-in sandbox execution API. This image is available directly without building, pushing, or listing images through GET /v1/sandboxes/images.", + "default": "baseten/base-image:latest", + "example": "baseten/base-image:latest" }, "memory": { "type": "integer", - "description": "Memory allocation in megabytes. Also determines CPU allocation (CPU cores = memory in MB / 2048, e.g., 4096MB = 2 CPUs).", + "description": "Memory allocation in megabytes. Also determines CPU allocation (CPU cores = memory in MB / 2048, e.g., 4096MB = 2 CPUs). Defaults to 4096.", + "default": 4096, "example": 4096, "minimum": 1 }, @@ -33704,10 +34806,6 @@ "project": "api-review", "team": "engineering" } - }, - "create_if_not_exists": { - "type": "boolean", - "description": "When true, return the existing live sandbox with this name or recreate it if it is failed, terminated, or being deleted. The server handles concurrent creation and deletion races with a bounded wait; persistent contention returns a conflict. Requires name. Existing configuration is preserved. Defaults to false when omitted." } }, "example": { @@ -33779,7 +34877,7 @@ "value": "3000" } ], - "image": "blaxel/base-image:latest", + "image": "baseten/base-image:latest", "memory": 4096, "ports": [ { @@ -33788,7 +34886,6 @@ "target": 3000 } ], - "display_name": "Baseten API review", "external_id": "api-review-20260916-001", "labels": { "env": "development", @@ -33860,8 +34957,8 @@ }, "image": { "type": "string", - "description": "Image reference including its tag. Use blaxel/base-image:latest to get started with the built-in sandbox execution API. This image is available directly without building, pushing, or listing images through GET /v1/sandboxes/images.", - "example": "blaxel/base-image:latest" + "description": "Image reference including its tag. Built-in image references are returned in the canonical baseten/ namespace. Use baseten/base-image:latest to get started with the built-in sandbox execution API. This image is available directly without building, pushing, or listing images through GET /v1/sandboxes/images.", + "example": "baseten/base-image:latest" }, "ports": { "description": "Set of ports for a resource", @@ -33936,7 +35033,7 @@ "value": "3000" } ], - "image": "blaxel/base-image:latest", + "image": "baseten/base-image:latest", "ports": [ { "name": "http", @@ -33944,7 +35041,6 @@ "target": 3000 } ], - "display_name": "Baseten API review - revised", "external_id": "api-review-20260916-001", "labels": { "env": "development", @@ -33972,7 +35068,7 @@ }, "url": { "type": "string", - "description": "Base URL of this sandbox's execution API. Use this exact returned URL; do not reconstruct its hostname. Authenticate requests with the same Authorization: Bearer header used to create the sandbox. No additional routing headers are required. Fetch GET {url}/swagger/doc.json with that header for the API reference served by this sandbox. For example, POST {url}/process with Content-Type: application/json and {\"command\":\"echo hello\",\"waitForCompletion\":true} executes a command and waits for its result. Execution API fields use camelCase, independently of this API's snake_case fields.", + "description": "Base URL of this sandbox's execution API, always present on successful creation. The URL is assigned before deployment completes; inspect status for readiness. Use this exact returned URL; do not reconstruct its hostname. Authenticate requests with your authentication token using Authorization: Bearer . Do not send the Baseten API key directly. No additional routing headers are required. Fetch GET {url}/swagger/doc.json with that header for the API reference served by this sandbox. For example, POST {url}/process with Content-Type: application/json and {\"command\":\"echo hello\",\"waitForCompletion\":true} executes a command and waits for its result. Execution API fields use camelCase, independently of this API's snake_case fields.", "format": "uri", "readOnly": true, "example": "https://sbx-baseten-api-review-0916-esb1qo.us-pdx-1.b10.run" @@ -34029,6 +35125,7 @@ }, "required": [ "name", + "url", "status", "created_at" ], @@ -34036,7 +35133,6 @@ "name": "baseten-api-review-0916", "url": "https://sbx-baseten-api-review-0916-esb1qo.us-pdx-1.b10.run", "status": "DEPLOYED", - "state": "RUNNING", "created_at": "2026-09-16T21:26:58.545765901Z", "updated_at": "2026-09-16T21:31:13Z", "created_by": "sandbox-automation", @@ -34112,7 +35208,7 @@ "value": "3000" } ], - "image": "blaxel/base-image:latest", + "image": "baseten/base-image:latest", "memory": 4096, "ports": [ { @@ -34121,7 +35217,6 @@ "target": 3000 } ], - "display_name": "Baseten API review", "external_id": "api-review-20260916-001", "labels": { "env": "development", @@ -34131,7 +35226,6 @@ "name": "baseten-api-review-0916", "url": "https://sbx-baseten-api-review-0916-esb1qo.us-pdx-1.b10.run", "status": "DEPLOYED", - "state": "RUNNING", "created_at": "2026-09-16T21:26:58.545765901Z", "updated_at": "2026-09-16T21:31:13Z", "created_by": "sandbox-automation", @@ -34142,7 +35236,7 @@ }, "SandboxStatusV1": { "type": "string", - "description": "Sandbox deployment status.", + "description": "Sandbox deployment status, always uppercase. This tracks provisioning and differs from the execution API state, whose values such as running are lowercase.", "enum": [ "DEPLOYING", "DEPLOYED", @@ -34261,7 +35355,7 @@ "value": "3000" } ], - "image": "blaxel/base-image:latest", + "image": "baseten/base-image:latest", "memory": 4096, "ports": [ { @@ -34270,7 +35364,6 @@ "target": 3000 } ], - "display_name": "Baseten API review", "external_id": "api-review-20260916-001", "labels": { "env": "development", @@ -34280,7 +35373,6 @@ "name": "baseten-api-review-0916", "url": "https://sbx-baseten-api-review-0916-esb1qo.us-pdx-1.b10.run", "status": "DEPLOYED", - "state": "RUNNING", "created_at": "2026-09-16T21:26:58.545765901Z", "updated_at": "2026-09-16T21:31:13Z", "created_by": "sandbox-automation", @@ -34375,7 +35467,7 @@ "value": "3000" } ], - "image": "blaxel/base-image:latest", + "image": "baseten/base-image:latest", "memory": 4096, "ports": [ { @@ -34384,7 +35476,6 @@ "target": 3000 } ], - "display_name": "Baseten API review", "external_id": "api-review-20260916-001", "labels": { "env": "development", @@ -34394,7 +35485,6 @@ "name": "baseten-api-review-0916", "url": "https://sbx-baseten-api-review-0916-esb1qo.us-pdx-1.b10.run", "status": "DEPLOYED", - "state": "RUNNING", "created_at": "2026-09-16T21:26:58.545765901Z", "updated_at": "2026-09-16T21:31:13Z", "created_by": "sandbox-automation", @@ -34511,11 +35601,6 @@ "description": "Stable repository name supplied when pushing the image.", "example": "base-image" }, - "display_name": { - "type": "string", - "description": "Human-readable image repository name.", - "example": "b10/base-image" - }, "status": { "description": "Image processing status. Only BUILT images are ready to use.", "allOf": [ @@ -34591,7 +35676,6 @@ ], "example": { "name": "base-image", - "display_name": "b10/base-image", "status": "BUILT", "created_at": "2026-09-15T21:20:00Z", "updated_at": "2026-09-16T21:25:00Z", @@ -34625,7 +35709,7 @@ }, "image": { "type": "string", - "description": "Optional source registry image reference including a registry hostname. When omitted, the response provides an archive upload URL.", + "description": "Optional source registry image reference including a registry hostname. When omitted, the response provides an archive upload URL. The uploaded ZIP archive must not exceed 5 GB.", "example": "docker.io/b10/base-image:latest" }, "docker_config": { @@ -34664,7 +35748,7 @@ }, "upload_url": { "type": "string", - "description": "Temporary signed URL for uploading the source ZIP archive with HTTP PUT. Present only when no source image was supplied. Uploading starts asynchronous processing. This storage upload is separate from the API endpoints.", + "description": "Temporary signed URL for uploading the source ZIP archive with HTTP PUT. Present only when no source image was supplied. The uploaded ZIP archive must not exceed 5 GB. Uploading starts asynchronous processing. This storage upload is separate from the API endpoints.", "format": "uri", "example": "https://uploads.b10.run/images/base-image/20260916212658/source.zip?expires=2026-09-16T22%3A26%3A58Z&signature=demo-not-a-valid-upload-signature" }, @@ -34684,31 +35768,6 @@ "image": "b10/base-image:latest" } }, - "CleanupImagesResponseV1": { - "type": "object", - "description": "Result of cleaning up unused sandbox images.", - "properties": { - "deleted": { - "type": "integer", - "description": "Number of image versions removed.", - "minimum": 0, - "example": 3 - }, - "message": { - "type": "string", - "description": "Human-readable cleanup result.", - "example": "Removed 3 unused image versions. Image versions used by active sandboxes were retained." - } - }, - "required": [ - "deleted", - "message" - ], - "example": { - "deleted": 3, - "message": "Removed 3 unused image versions. Image versions used by active sandboxes were retained." - } - }, "SandboxLibraryImageVolumeV1": { "type": "object", "description": "Volume attachment suggested by a built-in image.", @@ -34869,6 +35928,31 @@ "required": [ "items" ] + }, + "CleanupImagesResponseV1": { + "type": "object", + "description": "Result of cleaning up unused sandbox images.", + "properties": { + "deleted": { + "type": "integer", + "description": "Number of image versions removed.", + "minimum": 0, + "example": 3 + }, + "message": { + "type": "string", + "description": "Human-readable cleanup result.", + "example": "Removed 3 unused image versions. Image versions used by active sandboxes were retained." + } + }, + "required": [ + "deleted", + "message" + ], + "example": { + "deleted": 3, + "message": "Removed 3 unused image versions. Image versions used by active sandboxes were retained." + } } }, "parameters": { @@ -35064,6 +36148,14 @@ "in": "path", "required": true }, + "harness": { + "schema": { + "type": "string" + }, + "name": "harness", + "in": "path", + "required": true + }, "route_id": { "schema": { "type": "string" @@ -35193,7 +36285,7 @@ "application/json": { "example": { "code": "UNAUTHORIZED", - "message": "Provide a valid API key in the Authorization header.", + "message": "Provide a valid authentication token in the Authorization header.", "details": { "header": "Authorization" } @@ -35207,7 +36299,7 @@ "application/json": { "example": { "code": "FORBIDDEN", - "message": "This API key does not have permission to perform this operation.", + "message": "This authentication token does not grant permission to perform this operation.", "details": { "request_id": "a3b7c4d2-91e6-4f08-9b5a-2c6d7e8f1043" } @@ -35275,10 +36367,11 @@ "examples": { "CreateSandboxQuickstart": { "summary": "Run code with the built-in image", - "description": "Create directly with the built-in image; no image discovery, build, or push is needed. Use the returned url to call the sandbox execution API with the same Bearer API key.", + "description": "Create directly with the built-in image; no image discovery, build, or push is needed. Use the returned url to call the sandbox execution API with your authentication token as a Bearer token, not your Baseten API key.", "value": { - "image": "blaxel/base-image:latest", - "memory": 2048 + "image": "baseten/base-image:latest", + "memory": 2048, + "region": "us-was-1" } }, "CreateSandbox": { @@ -35352,7 +36445,7 @@ "value": "3000" } ], - "image": "blaxel/base-image:latest", + "image": "baseten/base-image:latest", "memory": 4096, "ports": [ { @@ -35361,7 +36454,6 @@ "target": 3000 } ], - "display_name": "Baseten API review", "external_id": "api-review-20260916-001", "labels": { "env": "development", @@ -35408,7 +36500,7 @@ "value": "3000" } ], - "image": "blaxel/base-image:latest", + "image": "baseten/base-image:latest", "ports": [ { "name": "http", @@ -35416,7 +36508,6 @@ "target": 3000 } ], - "display_name": "Baseten API review - revised", "external_id": "api-review-20260916-001", "labels": { "env": "development", @@ -35495,7 +36586,7 @@ "value": "3000" } ], - "image": "blaxel/base-image:latest", + "image": "baseten/base-image:latest", "memory": 4096, "ports": [ { @@ -35504,7 +36595,6 @@ "target": 3000 } ], - "display_name": "Baseten API review", "external_id": "api-review-20260916-001", "labels": { "env": "development", @@ -35514,7 +36604,6 @@ "name": "baseten-api-review-0916", "url": "https://sbx-baseten-api-review-0916-esb1qo.us-pdx-1.b10.run", "status": "DEPLOYED", - "state": "RUNNING", "created_at": "2026-09-16T21:26:58.545765901Z", "updated_at": "2026-09-16T21:31:13Z", "created_by": "sandbox-automation", @@ -35592,7 +36681,7 @@ "value": "3000" } ], - "image": "blaxel/base-image:latest", + "image": "baseten/base-image:latest", "memory": 4096, "ports": [ { @@ -35601,7 +36690,6 @@ "target": 3000 } ], - "display_name": "Baseten API review - revised", "external_id": "api-review-20260916-001", "labels": { "env": "development", @@ -35612,7 +36700,6 @@ "name": "baseten-api-review-0916", "url": "https://sbx-baseten-api-review-0916-esb1qo.us-pdx-1.b10.run", "status": "DEPLOYED", - "state": "RUNNING", "created_at": "2026-09-16T21:26:58.545765901Z", "updated_at": "2026-09-16T21:36:13Z", "created_by": "sandbox-automation", @@ -35689,7 +36776,7 @@ "value": "3000" } ], - "image": "blaxel/base-image:latest", + "image": "baseten/base-image:latest", "memory": 4096, "ports": [ { @@ -35698,7 +36785,6 @@ "target": 3000 } ], - "display_name": "Baseten API review", "external_id": "api-review-20260916-001", "labels": { "env": "development", @@ -35708,7 +36794,6 @@ "name": "baseten-api-review-0916", "url": "https://sbx-baseten-api-review-0916-esb1qo.us-pdx-1.b10.run", "status": "DELETING", - "state": "RUNNING", "created_at": "2026-09-16T21:26:58.545765901Z", "updated_at": "2026-09-16T21:41:13Z", "created_by": "sandbox-automation", @@ -35787,7 +36872,7 @@ "value": "3000" } ], - "image": "blaxel/base-image:latest", + "image": "baseten/base-image:latest", "memory": 4096, "ports": [ { @@ -35796,7 +36881,6 @@ "target": 3000 } ], - "display_name": "Baseten API review", "external_id": "api-review-20260916-001", "labels": { "env": "development", @@ -35806,7 +36890,6 @@ "name": "baseten-api-review-0916", "url": "https://sbx-baseten-api-review-0916-esb1qo.us-pdx-1.b10.run", "status": "DEPLOYED", - "state": "RUNNING", "created_at": "2026-09-16T21:26:58.545765901Z", "updated_at": "2026-09-16T21:31:13Z", "created_by": "sandbox-automation", @@ -35892,7 +36975,7 @@ "value": "3000" } ], - "image": "blaxel/base-image:latest", + "image": "baseten/base-image:latest", "memory": 4096, "ports": [ { @@ -35901,7 +36984,6 @@ "target": 3000 } ], - "display_name": "Baseten API review", "external_id": "api-review-20260916-001", "labels": { "env": "development", @@ -35911,7 +36993,6 @@ "name": "baseten-api-review-0916", "url": "https://sbx-baseten-api-review-0916-esb1qo.us-pdx-1.b10.run", "status": "DEPLOYED", - "state": "RUNNING", "created_at": "2026-09-16T21:26:58.545765901Z", "updated_at": "2026-09-16T21:31:13Z", "created_by": "sandbox-automation", @@ -35929,7 +37010,6 @@ "summary": "Built image with all metadata and tags", "value": { "name": "base-image", - "display_name": "b10/base-image", "status": "BUILT", "created_at": "2026-09-15T21:20:00Z", "updated_at": "2026-09-16T21:25:00Z", @@ -35956,7 +37036,6 @@ "summary": "Image after deleting its older tag", "value": { "name": "base-image", - "display_name": "b10/base-image", "status": "BUILT", "created_at": "2026-09-15T21:20:00Z", "updated_at": "2026-09-16T21:41:13Z", @@ -35976,7 +37055,6 @@ "summary": "Image repository summary", "value": { "name": "base-image", - "display_name": "b10/base-image", "status": "BUILT", "created_at": "2026-09-15T21:20:00Z", "size": 260046848, @@ -35990,7 +37068,6 @@ "items": [ { "name": "base-image", - "display_name": "b10/base-image", "status": "BUILT", "created_at": "2026-09-15T21:20:00Z", "updated_at": "2026-09-16T21:25:00Z", @@ -36039,6 +37116,37 @@ }, "description": "No upload_url is returned for registry imports." }, + "SandboxLibraryImages": { + "summary": "Built-in sandbox images", + "value": { + "items": [ + { + "name": "base-image", + "display_name": "Base Image", + "description": "A minimal sandbox environment with the sandbox execution API.", + "long_description": "", + "image": "baseten/base-image:latest", + "memory": 4096, + "ports": [ + { + "name": "sandbox-api", + "protocol": "HTTP", + "target": 8080 + } + ], + "categories": [], + "tags": [], + "url": "", + "icon": "https://example.com/base-image.png", + "icon_light": "https://example.com/base-image.png", + "icon_dark": "https://example.com/base-image.png", + "enterprise": false, + "hidden": false, + "coming_soon": false + } + ] + } + }, "CleanupImages": { "summary": "Unused image versions removed", "value": { @@ -36048,4 +37156,4 @@ } } } -} +} \ No newline at end of file