diff --git a/bun.lock b/bun.lock index 618e037..fd69efe 100644 --- a/bun.lock +++ b/bun.lock @@ -1,5 +1,6 @@ { "lockfileVersion": 1, + "configVersion": 0, "workspaces": { "": { "name": "sf-cli", diff --git a/src/index.ts b/src/index.ts index c8699fa..dec9f51 100644 --- a/src/index.ts +++ b/src/index.ts @@ -19,6 +19,7 @@ import { getAppBanner } from "./lib/app-banner.ts"; import { registerBalance } from "./lib/balance.ts"; import { registerContracts } from "./lib/contracts/index.tsx"; import { registerDev } from "./lib/dev.ts"; +import { registerImages } from "./lib/images/index.ts"; import { registerLogin } from "./lib/login.ts"; import { registerMe } from "./lib/me.ts"; import { registerNodes } from "./lib/nodes/index.ts"; @@ -51,6 +52,7 @@ async function main() { registerMe(program); await registerVM(program); await registerNodes(program); + registerImages(program); await registerZones(program); // (development commands) diff --git a/src/lib/images/get.tsx b/src/lib/images/get.tsx new file mode 100644 index 0000000..6dae00c --- /dev/null +++ b/src/lib/images/get.tsx @@ -0,0 +1,141 @@ +import console from "node:console"; +import { Command } from "@commander-js/extra-typings"; +import chalk from "chalk"; +import dayjs from "dayjs"; +import advanced from "dayjs/plugin/advancedFormat"; +import timezone from "dayjs/plugin/timezone"; +import utc from "dayjs/plugin/utc"; +import { Box, render, Text } from "ink"; +import Link from "ink-link"; +import { apiClient } from "../../apiClient.ts"; +import { logAndQuit } from "../../helpers/errors.ts"; +import { formatDate } from "../../helpers/format-time.ts"; +import { Row } from "../Row.tsx"; + +dayjs.extend(utc); +dayjs.extend(advanced); +dayjs.extend(timezone); + +function ImageDisplay({ + image, + download, +}: { + image: { + name: string; + id: string; + upload_status: string; + sha256_hash: string | null; + }; + download: { download_url: string; expires_at: number } | null; +}) { + const expiresAt = download?.expires_at + ? new Date(download.expires_at * 1000) + : null; + const isExpired = expiresAt ? expiresAt < new Date() : false; + + return ( + + + + Image: {image.name} ({image.id}) + + + + + + {image.sha256_hash && } + {download && ( + <> + + Use curl or wget to download. + + {download.download_url} + + + } + /> + {expiresAt && ( + + + {expiresAt.toISOString()}{" "} + {chalk.blackBright( + `(${formatDate(dayjs(expiresAt).toDate())} ${dayjs( + expiresAt, + ).format("z")})`, + )} + + {isExpired && (Expired)} + + } + /> + )} + + )} + + + ); +} + +function formatStatusInk(status: string): React.ReactElement { + switch (status) { + case "started": + return Started; + case "uploading": + return Uploading; + case "completed": + return Completed; + case "failed": + return Failed; + default: + return Unknown; + } +} + +const get = new Command("get") + .description("Get image details and download URL") + .argument("", "Image ID or name") + .option("--json", "Output JSON") + .action(async (id, opts) => { + const client = await apiClient(); + + const { data: image, response } = await client.GET("/v2/images/{id}", { + params: { path: { id } }, + }); + if (!response.ok || !image) { + logAndQuit( + `Failed to get image: ${response.status} ${response.statusText}`, + ); + } + + // Fetch download URL if image is completed + let download = null; + if (image.upload_status === "completed") { + const { data: downloadData } = await client.GET( + "/v2/images/{id}/download", + { params: { path: { id } } }, + ); + if (downloadData) { + download = downloadData; + } + } + + if (opts.json) { + console.log(JSON.stringify({ ...image, download }, null, 2)); + return; + } + + render( + , + ); + }); + +export default get; diff --git a/src/lib/images/index.ts b/src/lib/images/index.ts new file mode 100644 index 0000000..e845f79 --- /dev/null +++ b/src/lib/images/index.ts @@ -0,0 +1,32 @@ +import type { Command } from "@commander-js/extra-typings"; +import get from "./get.tsx"; +import list from "./list.ts"; +import upload from "./upload.ts"; + +export function registerImages(program: Command) { + const images = program + .command("images") + .alias("image") + .description("Manage images") + .showHelpAfterError() + .addHelpText( + "after", + ` +Examples:\n + \x1b[2m# Upload an image file\x1b[0m + $ sf images upload -f ./my-image.raw -n my-image + + \x1b[2m# List all images\x1b[0m + $ sf images list + + \x1b[2m# Get image details and download URL\x1b[0m + $ sf images get +`, + ) + .addCommand(list) + .addCommand(upload) + .addCommand(get) + .action(() => { + images.help(); + }); +} diff --git a/src/lib/images/list.ts b/src/lib/images/list.ts new file mode 100644 index 0000000..83c13a1 --- /dev/null +++ b/src/lib/images/list.ts @@ -0,0 +1,122 @@ +import console from "node:console"; +import { Command } from "@commander-js/extra-typings"; +import chalk from "chalk"; +import Table from "cli-table3"; +import ora from "ora"; +import { apiClient } from "../../apiClient.ts"; +import { logAndQuit } from "../../helpers/errors.ts"; +import { formatDate } from "../../helpers/format-time.ts"; + +const list = new Command("list") + .alias("ls") + .description("List images") + .showHelpAfterError() + .option("--json", "Output in JSON format") + .addHelpText( + "after", + ` +Examples:\n + \x1b[2m# List all images\x1b[0m + $ sf images list + + \x1b[2m# Get detailed info for a specific image\x1b[0m + $ sf images get + + \x1b[2m# List images in JSON format\x1b[0m + $ sf images list --json +`, + ) + .action(async (options) => { + const client = await apiClient(); + + const spinner = ora("Fetching images...").start(); + const { data: result, response } = await client.GET("/v2/images"); + spinner.stop(); + + if (!response.ok || !result) { + logAndQuit( + `Failed to list images: ${response.status} ${response.statusText}`, + ); + } + + if (options.json) { + console.log(JSON.stringify(result, null, 2)); + return; + } + + const images = result.data; + + if (images.length === 0) { + console.log("No images found."); + console.log(chalk.gray("\nUpload your first image:")); + console.log(" sf images upload -f ./my-image.img -n my-image"); + return; + } + + // Sort images by created_at (newest first) + const sortedImages = [...images].sort((a, b) => { + return (b.created_at || 0) - (a.created_at || 0); + }); + const imagesToShow = sortedImages.slice(0, 5); + + const table = new Table({ + head: [ + chalk.cyan("NAME"), + chalk.cyan("ID"), + chalk.cyan("STATUS"), + chalk.cyan("CREATED"), + ], + style: { + head: [], + border: ["gray"], + }, + }); + + for (const image of imagesToShow) { + const createdAt = image.created_at + ? formatDate(new Date(image.created_at * 1000)) + : "Unknown"; + + const status = formatStatus(image.upload_status); + + table.push([image.name, image.id, status, createdAt]); + } + + if (images.length > 5) { + table.push([ + { + colSpan: 4, + content: chalk.blackBright( + `${images.length - 5} older ${ + images.length - 5 === 1 ? "image" : "images" + } not shown. Use sf images list --json to list all images.`, + ), + }, + ]); + } + + console.log(table.toString()); + + console.log(chalk.gray("\nNext steps:")); + const firstImage = sortedImages[0]; + if (firstImage) { + console.log(` sf images get ${chalk.cyan(firstImage.id)}`); + } + }); + +function formatStatus(status: string): string { + switch (status) { + case "started": + return chalk.green("Started"); + case "uploading": + return chalk.yellow("Uploading"); + case "completed": + return chalk.cyan("Completed"); + case "failed": + return chalk.red("Failed"); + default: + return chalk.gray("Unknown"); + } +} + +export default list; diff --git a/src/lib/images/upload.ts b/src/lib/images/upload.ts new file mode 100644 index 0000000..2a1c563 --- /dev/null +++ b/src/lib/images/upload.ts @@ -0,0 +1,409 @@ +import console from "node:console"; +import crypto from "node:crypto"; +import fs from "node:fs"; +import { open, stat } from "node:fs/promises"; +import process from "node:process"; +import { clearInterval, setInterval } from "node:timers"; +import { Command } from "@commander-js/extra-typings"; +import retry from "async-retry"; +import chalk from "chalk"; +import cliProgress from "cli-progress"; +import cliSpinners from "cli-spinners"; +import ora, { type Ora } from "ora"; +import { apiClient } from "../../apiClient.ts"; +import { logAndQuit } from "../../helpers/errors.ts"; + +async function readChunk( + filePath: string, + start: number, + length: number, + onProgress?: (bytesRead: number) => void, +): Promise { + const fileHandle = await open(filePath, "r"); + try { + const buffer = new Uint8Array(length); + let offset = 0; + + while (offset < length) { + const { bytesRead } = await fileHandle.read( + buffer, + offset, + length - offset, + start + offset, + ); + if (bytesRead === 0) { + break; + } + offset += bytesRead; + if (onProgress) { + onProgress(bytesRead); + } + } + + if (offset !== length) { + throw new Error( + `Short read: expected ${length} bytes, got ${offset} bytes`, + ); + } + + return buffer; + } finally { + await fileHandle.close(); + } +} + +const upload = new Command("upload") + .description("Upload an image file (multipart)") + .requiredOption("-f, --file ", "Path to the image file") + .requiredOption("-n, --name ", "Image name") + .option( + "-c, --concurrency ", + "Number of parts to upload concurrently", + (value) => { + const parsed = Number.parseInt(value, 10); + if (Number.isNaN(parsed) || parsed < 1) { + throw new Error("Concurrency must be a positive integer"); + } + return parsed; + }, + 1, + ) + .action(async ({ name, file: filePath, concurrency: concurrencyLimit }) => { + let preparingSpinner: Ora | undefined; + let finalizingSpinner: Ora | undefined; + let spinnerTimer: NodeJS.Timeout | undefined; + let progressBar: cliProgress.SingleBar | undefined; + + try { + const client = await apiClient(); + + preparingSpinner = ora(`Preparing upload for ${name}...`).start(); + + // Create image via v2 API + const startResponse = await client.POST("/v2/images", { + body: { name }, + }); + + if (!startResponse.response.ok || !startResponse.data) { + const errorText = await startResponse.response.text().catch(() => ""); + throw new Error( + `Failed to start upload: ${startResponse.response.status} ${startResponse.response.statusText}${errorText ? ` - ${errorText}` : ""}`, + ); + } + + const imageId = startResponse.data.id; + + preparingSpinner.succeed( + `Started upload for image ${chalk.cyan(name)} (${chalk.blackBright( + imageId, + )})`, + ); + + // Get file info + const fileInfo = await stat(filePath); + const fileSize = fileInfo.size; + + // Check file size limit (128 GiB) + const maxFileSize = 128 * 1024 * 1024 * 1024; + if (fileSize > maxFileSize) { + logAndQuit( + `File size exceeds maximum allowed size of 128 GiB. File size: ${( + fileSize / (1024 * 1024 * 1024) + ).toFixed(2)} GiB`, + ); + } + + // Calculate parts + const minChunk = 5 * 1024 * 1024; // 5 MiB + const defaultChunk = 64 * 1024 * 1024; // 64 MiB + const maxParts = 10000; + + const chunkSize = + fileSize <= defaultChunk + ? Math.max(fileSize, minChunk) + : Math.max(minChunk, Math.ceil(fileSize / maxParts), defaultChunk); + + const totalParts = Math.ceil(fileSize / chunkSize); + + const uploadParts: Array<{ + part: number; + start: number; + end: number; + }> = []; + + for (let idx = 0; idx < totalParts; idx++) { + const part = idx + 1; + const start = idx * chunkSize; + const end = Math.min(start + chunkSize, fileSize); + uploadParts.push({ part, start, end }); + } + + // Progress tracking + const startTime = Date.now(); + const partProgress = new Map(); + + const getTotalBytesUploaded = () => { + let total = 0; + for (const bytes of partProgress.values()) { + total += bytes; + } + return total; + }; + + const spinner = cliSpinners.dots; + let spinnerIndex = 0; + + progressBar = new cliProgress.SingleBar({ + format: + "{spinner} Uploading [{bar}] {percentage}% | {uploadedMB}/{totalMB} MB | {speed}", + barCompleteChar: "\u2588", + barIncompleteChar: "\u2591", + hideCursor: true, + forceRedraw: false, + }); + + progressBar.start(fileSize, 0, { + spinner: spinner.frames[0], + speed: "0 B/s", + uploadedMB: "0.0", + totalMB: (fileSize / (1024 * 1024)).toFixed(1), + }); + + const UI_UPDATE_INTERVAL_MS = 200; + let lastUIUpdate = 0; + + const renderProgress = () => { + const totalBytesUploaded = getTotalBytesUploaded(); + const elapsedTime = (Date.now() - startTime) / 1000; + const speed = totalBytesUploaded / elapsedTime; + + let speedStr: string; + if (speed > 1024 * 1024) { + speedStr = `${(speed / (1024 * 1024)).toFixed(1)} MB/s`; + } else if (speed > 1024) { + speedStr = `${(speed / 1024).toFixed(1)} KB/s`; + } else { + speedStr = `${speed.toFixed(0)} B/s`; + } + + progressBar?.update(totalBytesUploaded, { + spinner: spinner.frames[spinnerIndex % spinner.frames.length], + speed: speedStr, + uploadedMB: (totalBytesUploaded / (1024 * 1024)).toFixed(1), + totalMB: (fileSize / (1024 * 1024)).toFixed(1), + }); + }; + + spinnerTimer = setInterval(() => { + spinnerIndex++; + const now = Date.now(); + if (now - lastUIUpdate >= UI_UPDATE_INTERVAL_MS) { + renderProgress(); + lastUIUpdate = now; + } + }, spinner.interval); + + const updateProgress = (part: number, bytesUploaded: number) => { + const previousBytes = partProgress.get(part) || 0; + partProgress.set(part, previousBytes + bytesUploaded); + }; + + const resetPartProgress = (part: number) => { + partProgress.set(part, 0); + }; + + // Upload parts + const uploadPart = async ({ + part, + start, + end, + }: { + part: number; + start: number; + end: number; + }) => { + const partSize = end - start; + + await retry( + async (bail: (e: Error) => void, attemptNumber: number) => { + if (attemptNumber > 1) { + resetPartProgress(part); + } + + // Get presigned URL via v2 API + const partResponse = await client.POST("/v2/images/{id}/parts", { + params: { path: { id: imageId } }, + body: { part_id: part }, + }); + + if (!partResponse.response.ok || !partResponse.data) { + const status = partResponse.response.status; + const errorText = await partResponse.response + .text() + .catch(() => ""); + + if ( + status >= 400 && + status < 500 && + status !== 408 && + status !== 429 + ) { + bail( + new Error( + `Failed to get upload URL for part ${part}: ${status} ${partResponse.response.statusText} - ${errorText}`, + ), + ); + return; + } + + throw new Error( + `Failed to get upload URL for part ${part}: ${status} ${partResponse.response.statusText} - ${errorText}`, + ); + } + + const url = partResponse.data.upload_url; + + // Read chunk from disk with progress tracking + const payload = await readChunk( + filePath, + start, + partSize, + (bytesRead) => { + updateProgress(part, bytesRead); + }, + ); + + const res = await fetch(url, { + method: "PUT", + headers: { + "Content-Type": "application/octet-stream", + }, + body: payload as BodyInit, + }); + + if (!res.ok) { + if ( + res.status >= 400 && + res.status < 500 && + res.status !== 408 && + res.status !== 429 + ) { + bail( + new Error( + `Part ${part} upload failed: ${res.status} ${res.statusText}`, + ), + ); + return; + } + + throw new Error( + `Part ${part} upload failed: ${res.status} ${res.statusText}`, + ); + } + }, + { + retries: 5, + factor: 2, + randomize: true, + }, + ); + + return part; + }; + + // Process uploads with concurrency limit + const results: number[] = []; + try { + for (let i = 0; i < uploadParts.length; i += concurrencyLimit) { + const batch = uploadParts.slice(i, i + concurrencyLimit); + const batchResults = await Promise.allSettled(batch.map(uploadPart)); + + for (const result of batchResults) { + if (result.status === "fulfilled") { + results.push(result.value); + } else { + throw new Error(`Upload failed: ${result.reason}`); + } + } + } + } finally { + if (spinnerTimer) { + clearInterval(spinnerTimer); + spinnerTimer = undefined; + } + } + + progressBar.update(fileSize, { + spinner: chalk.green("\u2714"), + speed: "0 B/s", + uploadedMB: (fileSize / (1024 * 1024)).toFixed(1), + totalMB: (fileSize / (1024 * 1024)).toFixed(1), + }); + progressBar.stop(); + + finalizingSpinner = ora("Validating upload...").start(); + + // Calculate SHA256 hash + const hash = crypto.createHash("sha256"); + const fileStream = fs.createReadStream(filePath); + for await (const chunk of fileStream) { + hash.update(chunk); + } + + const sha256Hash = hash.digest("hex"); + + // Complete upload via v2 API + const completeResponse = await client.POST("/v2/images/{id}/complete", { + params: { path: { id: imageId } }, + body: { sha256_hash: sha256Hash }, + }); + + if (!completeResponse.response.ok || !completeResponse.data) { + const errorText = await completeResponse.response + .text() + .catch(() => ""); + throw new Error( + `Failed to complete upload: ${completeResponse.response.status} ${completeResponse.response.statusText}${errorText ? ` - ${errorText}` : ""}`, + ); + } + + finalizingSpinner.succeed("Image uploaded and verified"); + + console.log(chalk.gray("\nNext steps:")); + console.log(` sf images get ${chalk.cyan(completeResponse.data.id)}`); + } catch (err) { + if (spinnerTimer) { + clearInterval(spinnerTimer); + spinnerTimer = undefined; + } + + try { + progressBar?.stop(); + } catch { + // Ignore if progress bar not started + } + + if (preparingSpinner?.isSpinning) { + preparingSpinner.fail( + `Upload preparation failed: ${ + err instanceof Error ? err.message : String(err) + }`, + ); + } else if (finalizingSpinner?.isSpinning) { + finalizingSpinner.fail( + `Failed to finalize upload: ${ + err instanceof Error ? err.message : String(err) + }`, + ); + } else { + console.error( + `\n${chalk.red("\u2717")} ${ + err instanceof Error ? err.message : String(err) + }`, + ); + } + process.exit(1); + } + }); + +export default upload; diff --git a/src/lib/nodes/image/upload.ts b/src/lib/nodes/image/upload.ts index fba9749..9099564 100644 --- a/src/lib/nodes/image/upload.ts +++ b/src/lib/nodes/image/upload.ts @@ -399,7 +399,7 @@ const upload = new Command("upload") const object = completeResponse.data; console.log(chalk.gray("\nNext steps:")); - console.log(` sf nodes images show ${chalk.cyan(object.image_id)}`); + console.log(` sf nodes images show ${chalk.cyan(object.id)}`); } catch (err) { // Clean up spinner timer if (spinnerTimer) { diff --git a/src/schema.ts b/src/schema.ts index 3dea346..2a93bd0 100644 --- a/src/schema.ts +++ b/src/schema.ts @@ -4,41 +4,6 @@ */ export interface paths { - "/v0/balance": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description The balance of the account. */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["San_Francisco_Compute_Documentation_AccountBalance"]; - }; - }; - }; - }; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; "/v0/me": { parameters: { query?: never; @@ -525,7 +490,7 @@ export interface paths { * List Images * @description List all VM Images for the authenticated account */ - get: operations["list_images"]; + get: operations["list_vms_images"]; put?: never; post?: never; delete?: never; @@ -602,6 +567,202 @@ export interface paths { patch?: never; trace?: never; }; + "/v2/images": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List Images + * @description List all VM Images for the authenticated account + */ + get: operations["list_images_v2"]; + put?: never; + /** + * Create image + * @description Start a new image upload. Returns the created image metadata. + */ + post: operations["start_upload"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v2/images/{id}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get Image + * @description Get metadata for a VM image by ID + */ + get: operations["get_image"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v2/images/{id}/complete": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["complete_upload"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v2/images/{id}/download": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Download Image + * @description Get a presigned download URL for a completed VM image + */ + get: operations["download_image_v2"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v2/images/{id}/parts": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["upload_part"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v2/nodes": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List nodes + * @description List nodes + */ + get: operations["list_nodes"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v2/nodes/{id}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get node + * @description Retrieve details of a specific node by ID. + */ + get: operations["get_node"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v2/nodes/{id}/logs": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get node logs + * @description Retrieve log chunks for a specific node, with optional filtering by sequence number and timestamp. + */ + get: operations["get_node_logs"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v2/nodes/{id}/replace": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Replace node + * @description Replace a node by destroying the existing one and creating a new node in the same capacity. Optionally specify a new image and cloud-init user data. + */ + post: operations["replace_node"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v2/nodes/{id}/ssh": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get node SSH info + * @description Get SSH connection details for a specific node, including hostname, port, and host keys. + */ + get: operations["get_node_ssh"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; "/v0/zones": { parameters: { query?: never; @@ -671,7 +832,7 @@ export interface paths { }; /** * List nodes - * @description List all VM nodes for the authenticated account + * @description List all nodes for the authenticated account */ get: operations["list_nodes_handler"]; put?: never; @@ -700,7 +861,11 @@ export interface paths { get: operations["get_node_handler"]; put?: never; post?: never; - delete?: never; + /** + * Delete node + * @description Delete a node by id. The node cannot be deleted if it has active or pending VMs. + */ + delete: operations["delete_node_handler"]; options?: never; head?: never; patch?: never; @@ -726,6 +891,26 @@ export interface paths { patch: operations["extend_node_handler"]; trace?: never; }; + "/v1/nodes/{id}/redeploy": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + /** + * Redeploy a node + * @description Redeploy a node by replacing its current VM with a new one. Optionally update the VM image and cloud init user data. + */ + put: operations["redeploy_node_handler"]; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; "/v1/nodes/{id}/release": { parameters: { query?: never; @@ -913,26 +1098,6 @@ export interface paths { patch: operations["updateProcurement"]; trace?: never; }; - "/v0/refunds": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get refunds - * @description Get status of refunds - */ - get: operations["getRefunds"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; "/v1/account/me": { parameters: { query?: never; @@ -984,32 +1149,6 @@ export interface paths { patch?: never; trace?: never; }; - "/v1/credits": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * Get current credit balance - * @description Retrieves the current credit balance for the authenticated user's account. - * - * This endpoint returns: - * - The current balance in cents - * - The available prepaid credits in cents - * - The amount due for the next billing period in cents - * - */ - get: operations["getCredits"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; "/v1/credits/migrate": { parameters: { query?: never; @@ -1041,36 +1180,276 @@ export interface paths { patch?: never; trace?: never; }; - "/v1/transactions": { + "/v1/invoices/calculate_pricing": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - /** - * Get transactions - * @description Lists transaction history. Provide either `starting_after_cursor` or `ending_before_cursor` (not both) for cursor-based pagination. - */ - get: operations["getTransactions"]; + get?: never; put?: never; - post?: never; + post: operations["post_calculate_invoice_pricing"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; - "/v1/inference/batches": { + "/v1/invoices/create_draft": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; + get?: never; + put?: never; + post: operations["post_create_draft_invoice"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/invoices/finalize": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["post_finalize_invoice"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/provider/node_ids": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["get_node_ids"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/provider/orders": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List provider orders + * @description Lists executed orders for a provider within a time window. + * Orders are sorted by execution time (most recent first) and use cursor-based pagination. Use `starting_after` or `ending_before` with a cursor to paginate through results. + */ + get: operations["list_provider_orders"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/transactions": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get transactions + * @description Lists transaction history. Provide either `starting_after_cursor` or `ending_before_cursor` (not both) for cursor-based pagination. + */ + get: operations["getTransactions"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v2/capacities": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List capacities + * @description List all capacities owned by the authenticated user. + */ + get: operations["list_capacities_handler"]; + put?: never; + /** + * Create capacity + * @description Create a new capacity with optional requirements, node template, and scheduler. + */ + post: operations["create_capacity_handler"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v2/capacities/{id}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get capacity by ID or name + * @description Retrieve a capacity including its compute schedule and scheduler configuration. + */ + get: operations["get_capacity_handler"]; + put?: never; + post?: never; + /** + * Delete capacity + * @description Delete a capacity. The capacity must be empty and the scheduler must be disabled or absent. + */ + delete: operations["delete_capacity_handler"]; + options?: never; + head?: never; + /** + * Update capacity + * @description Update a capacity. Only provided fields are changed; omitted fields are left unchanged. + */ + patch: operations["patch_capacity_handler"]; + trace?: never; + }; + "/v2/node_templates": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List node templates + * @description List all node templates accessible by the authenticated user. + */ + get: operations["list_node_templates_handler"]; + put?: never; + /** + * Create node template + * @description Create a new node template with reusable VM configuration. + */ + post: operations["create_node_template_handler"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v2/node_templates/{id}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get node template by ID or name + * @description Get detailed information about a specific node template. + */ + get: operations["get_node_template_handler"]; + put?: never; + post?: never; + /** + * Delete node template + * @description Delete a node template. The template must not be in use by any capacity. + */ + delete: operations["delete_node_template_handler"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v2/orders": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List orders + * @description List all orders for the authenticated user. + */ + get: operations["list_orders"]; + put?: never; + /** + * Create order + * @description Place a buy or sell order on the market for a specific capacity. + */ + post: operations["post_order"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v2/orders/{id}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get order details + * @description Retrieve details of a specific order by ID. + */ + get: operations["get_order"]; + put?: never; + post?: never; + /** + * Cancel an order + * @description Request cancellation of an order. This is asynchronous — poll `GET /v2/orders/{id}` to confirm the status has changed to cancelled. + */ + delete: operations["cancel_order"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/inference/batches": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List all batches + * @description Returns all batches for your account. Archived batches are excluded. Use `limit` and `after` parameters for pagination. + */ get: operations["list_batches"]; put?: never; - /** Create a batch job. */ + /** + * Create batch jobs + * @description Creates a new batch job. Accepts a single batch request or multiple requests. Make sure to follow the [expected file structure for batches](large-scale-inference#large-scale-inference__input-file-format). The batch starts in `accepted` status. + */ post: operations["create_batches"]; delete?: never; options?: never; @@ -1085,16 +1464,20 @@ export interface paths { path?: never; cookie?: never; }; + /** + * Get a batch + * @description Returns details for a specific batch identified by `batch_id`. + */ get: operations["get_batch"]; put?: never; - post: operations["archive_batch"]; + post?: never; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; - "/v1/inference/batches/{batch_id}/cancel": { + "/v1/inference/batches/{batch_id}/archive": { parameters: { query?: never; header?: never; @@ -1103,53 +1486,69 @@ export interface paths { }; get?: never; put?: never; - post: operations["cancel_batch"]; + /** + * Archive a batch + * @description Archives a batch identified by `batch_id`. Archived batches are excluded from list results. + */ + post: operations["archive_batch"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; - "/v1/inference/health": { + "/v1/inference/batches/{batch_id}/cancel": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - get: operations["health_check"]; + get?: never; put?: never; - post?: never; + /** + * Cancel a batch + * @description Cancels a batch that is in `accepted` status. Batches in other states cannot be cancelled. + */ + post: operations["cancel_batch"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; - "/v1/inference/models": { + "/v1/inference/batches/{batch_id}/retry": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - get: operations["get_models"]; + get?: never; put?: never; - post?: never; + /** + * Retry a batch + * @description Retries a batch that is `failed`, `cancelled`, `expired`, or `completed` status. Presigned URLs must still be valid. Maximum `2` retries per batch. + */ + post: operations["retry_batch"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; - "/v1/inference/models/{model_id}/history": { + "/v1/inference/models": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - get: operations["get_model_history"]; + /** + * List available models + * @description Returns all available models. Use `model_id` values when creating batches. If you don't see a model you need, please [contact us](https://sfcompute.com/inference/contact). + */ + get: operations["get_models"]; put?: never; post?: never; delete?: never; @@ -1178,37 +1577,6 @@ export interface paths { export type webhooks = Record; export interface components { schemas: { - San_Francisco_Compute_Documentation_AccountBalance: { - /** - * @example balance - * @enum {string} - */ - object: "balance"; - available: { - /** - * @description Funds available to spend or withdraw. - * @example 1000000 - */ - amount: number; - /** - * @example usd - * @enum {string} - */ - currency: "usd"; - }; - reserved: { - /** - * @description Funds held in reserve for pending withdrawals & open buy orders. - * @example 1000000 - */ - amount: number; - /** - * @example usd - * @enum {string} - */ - currency: "usd"; - }; - }; San_Francisco_Compute_Documentation_Account: { /** * @example account @@ -1492,8 +1860,6 @@ export interface components { end_time: string; /** @description The sell order that was executed. */ order_id: string; - /** @description The backing contract that was sold from. */ - backing_contract_id: string; } | { /** @enum {string} */ @@ -1757,27 +2123,60 @@ export interface components { pubkey?: string; username?: string; }; - /** @description Request body for completing a multipart upload */ + /** + * @description Unique identifier with prefix 'cap_'. + * @example cap_k3R-nX9vLm7Qp2Yw5Jd8F + */ + vmorch_CapacityId: string; vmorch_CompleteUploadRequest: { - /** @description SHA256 hash of the uploaded file for integrity verification */ sha256_hash: string; }; - /** @description Response body for completing a multipart upload */ vmorch_CompleteUploadResponse: { - /** @description The image ID */ - image_id: string; - object: components["schemas"]["vmorch_ImageDiscriminator"]; - /** @description Status of the upload verification */ - upload_status: string; + /** + * @example image + * @enum {string} + */ + object?: "image"; + upload_status: components["schemas"]["vmorch_ImageUploadStatus"]; + id: components["schemas"]["vmorch_ImageId"]; + }; + vmorch_ErrorDetail: { + /** @description The field that caused the error (for validation errors) */ + field?: string | null; + /** @description Specific error code for this detail */ + code: string; + /** @description Human-readable error message */ + message: string; }; + /** @enum {string} */ + vmorch_ErrorType: + | "api_error" + | "invalid_request_error" + | "authentication_error" + | "idempotency_error" + | "conflict" + | "not_found" + | "request_timed_out" + | "forbidden" + | "not_implemented" + | "upgrade_required" + | "payment_required" + | "service_unavailable" + | "unprocessable_entity"; vmorch_GetInstancesResponse: { data: components["schemas"]["vmorch_VmInstance"][]; }; vmorch_GetSshResponse: { - ssh_host_keys?: components["schemas"]["vmorch_SshHostKeyInfo"][] | null; ssh_hostname: string; /** Format: u-int16 */ ssh_port: number; + ssh_host_keys?: components["schemas"]["vmorch_SshHostKeyInfo"][] | null; + last_successful_key_update?: + | null + | components["schemas"]["vmorch_UnixEpoch"]; + last_attempted_key_update?: + | null + | components["schemas"]["vmorch_UnixEpoch"]; }; vmorch_GetUserDataResponse: { script: components["schemas"]["vmorch_UserData"]; @@ -1787,44 +2186,41 @@ export interface components { * @enum {string} */ vmorch_ImageDiscriminator: "image"; - /** @description Response body for image download presigned URL generation */ vmorch_ImageDownloadResponse: { - /** @description The presigned URL that can be used to download the image */ download_url: string; - /** @description Timestamp when the presigned URL expires (RFC 3339 format) */ - expires_at: string; - /** @description The image ID */ - image_id: string; - /** @description Human readable name of the image */ - name: string; - /** - * @example image - * @enum {string} - */ - object: "image"; - /** @description SHA256 hash of the image file for integrity verification */ + expires_at: components["schemas"]["vmorch_UnixEpoch"]; sha256_hash: string; + /** Format: u-int64 */ + object_size: number; }; - /** @description Response body for individual image info (used in lists) */ + /** + * @description Unique identifier with prefix 'image_'. + * @example image_k3R-nX9vLm7Qp2Yw5Jd8F + */ + vmorch_ImageId: string; vmorch_ImageInfo: { /** - * Format: int64 - * @description Creation timestamp as Unix timestamp in seconds + * @example image + * @enum {string} */ - created_at: number; - /** @description The image ID */ - image_id: string; - /** @description Client given name of the image */ - name: string; + object?: "image"; + id: components["schemas"]["vmorch_ImageId"]; + name: components["schemas"]["vmorch_Name"]; + upload_status: components["schemas"]["vmorch_ImageUploadStatus"]; + sha256_hash?: string | null; + created_at: components["schemas"]["vmorch_UnixEpoch"]; + }; + vmorch_ImageResponse: { /** * @example image * @enum {string} */ - object: "image"; - /** @description SHA256 hash of the image file for integrity verification */ + object?: "image"; + id: components["schemas"]["vmorch_ImageId"]; + name: components["schemas"]["vmorch_Name"]; + upload_status: components["schemas"]["vmorch_ImageUploadStatus"]; sha256_hash?: string | null; - /** @description Upload status of the image */ - upload_status: string; + created_at: components["schemas"]["vmorch_UnixEpoch"]; }; /** @description Request body for image upload presigned URL generation */ vmorch_ImageUploadRequest: { @@ -1836,21 +2232,127 @@ export interface components { }; /** @description Response body for image upload presigned URL generation */ vmorch_ImageUploadResponse: { - /** @description Timestamp when the presigned URL expires (RFC 3339 format) */ - expires_at: string; /** @description The presigned URL that can be used to upload the image part */ upload_url: string; + /** @description Timestamp when the presigned URL expires (RFC 3339 format) */ + expires_at: string; }; - /** @description Response body for listing images */ + /** @enum {string} */ + vmorch_ImageUploadStatus: "started" | "uploading" | "completed" | "failed"; + /** + * @description Opaque pagination cursor for ImagesCursor. Wire format: `imgc_{base64url}`. + * @example imgc_gqXR7s0Kj5mHvE2wNpLc4Q + */ + vmorch_ImagesCursor: string; vmorch_ListImagesResponse: { + /** + * @example list + * @enum {string} + */ + object: "list"; + cursor?: null | components["schemas"]["vmorch_ImagesCursor"]; + has_more: boolean; data: components["schemas"]["vmorch_ImageInfo"][]; + }; + vmorch_ListNodesResponse: { + /** + * @example list + * @enum {string} + */ + object: "list"; + cursor?: null | components["schemas"]["vmorch_NodesCursor"]; has_more: boolean; + data: components["schemas"]["vmorch_NodeResponse"][]; + }; + /** + * @description A validated resource name. Must start with alphanumeric, followed by alphanumeric, '.', '_', or '-'. Max 255 characters. + * @example my-resource-name + */ + vmorch_Name: string; + /** + * @description Unique identifier with prefix 'node_'. + * @example node_k3R-nX9vLm7Qp2Yw5Jd8F + */ + vmorch_NodeId: string; + vmorch_NodeLogChunk: { + /** + * @example logs_chunk + * @enum {string} + */ + object?: "logs_chunk"; + node_id: components["schemas"]["vmorch_NodeId"]; + /** @description Wall-clock time as a unix timestamp (seconds). */ + timestamp_realtime: components["schemas"]["vmorch_UnixEpoch"]; + /** + * Format: int64 + * @description Monotonic clock seconds. + */ + timestamp_monotonic_secs: number; + /** + * Format: u-int32 + * @description Nanosecond component of the monotonic clock. + */ + timestamp_monotonic_nanos: number; + /** Format: u-int64 */ + seqnum: number; + data: number[]; + }; + vmorch_NodeLogsResponse: { /** * @example list * @enum {string} */ object: "list"; + data: components["schemas"]["vmorch_NodeLogChunk"][]; + }; + vmorch_NodeResponse: { + /** + * @example node + * @enum {string} + */ + object?: "node"; + id: components["schemas"]["vmorch_NodeId"]; + status: components["schemas"]["vmorch_NodeStatus"]; + capacity: components["schemas"]["vmorch_CapacityId"]; + template: components["schemas"]["vmorch_NodeTemplateId"]; + }; + vmorch_NodeSshHostKey: { + /** + * @description Key algorithm (e.g. `ssh-ed25519`, `ssh-rsa`). + * @example ssh-ed25519 + * @example ssh-rsa + */ + key_type: string; + base64_encoded_key: string; + }; + vmorch_NodeSshInfo: { + /** @example 24.125.89.203 */ + ssh_hostname: string; + /** + * Format: u-int16 + * @example 22 + */ + ssh_port: number; + ssh_host_keys: components["schemas"]["vmorch_NodeSshHostKey"][]; + last_successful_key_update?: + | null + | components["schemas"]["vmorch_UnixEpoch"]; + last_attempted_key_update?: + | null + | components["schemas"]["vmorch_UnixEpoch"]; }; + /** @enum {string} */ + vmorch_NodeStatus: "pending" | "running" | "terminated" | "node_failure"; + /** + * @description Unique identifier with prefix 'ntmpl_'. + * @example ntmpl_k3R-nX9vLm7Qp2Yw5Jd8F + */ + vmorch_NodeTemplateId: string; + /** + * @description Opaque pagination cursor for NodesCursor. Wire format: `nodec_{base64url}`. + * @example nodec_gqXR7s0Kj5mHvE2wNpLc4Q + */ + vmorch_NodesCursor: string; vmorch_PostReplaceRequest: { vm_id: string; }; @@ -1864,40 +2366,71 @@ export interface components { vmorch_PostUserDataResponse: { script: components["schemas"]["vmorch_UserData"]; }; + vmorch_ReplaceNodeRequest: { + /** @description Image to boot the replacement node. Defaults to the capacity's configured image. */ + template?: string | null; + }; + /** @description SFC standard error response */ + vmorch_SerdeErrorProxy: { + /** @description The error type identifier */ + type: components["schemas"]["vmorch_ErrorType"]; + /** @description Human-readable error message */ + message: string; + /** @description Array of detailed error information when applicable */ + details: components["schemas"]["vmorch_ErrorDetail"][]; + }; vmorch_SshHostKeyInfo: { - base64_encoded_key: string; key_type: string; + /** Format: byte */ + base64_encoded_key: string; }; /** @description Request body for starting a multipart upload */ vmorch_StartMultipartUploadRequest: { - /** @description Name of the image file */ + /** @description Name of the image file. Must be unique per account. */ name: string; }; /** @description Response body for starting a multipart upload */ vmorch_StartMultipartUploadResponse: { + object: components["schemas"]["vmorch_ImageDiscriminator"]; /** @description The image ID for the created image */ image_id: string; - object: components["schemas"]["vmorch_ImageDiscriminator"]; + }; + vmorch_StartUploadRequest: { + name: components["schemas"]["vmorch_Name"]; + }; + /** + * Format: int64 + * @description Unix timestamp in seconds since epoch + * @example 1738972800 + */ + vmorch_UnixEpoch: number; + vmorch_UploadPartRequest: { + /** Format: int32 */ + part_id: number; + }; + vmorch_UploadPartResponse: { + upload_url: string; + expires_at: components["schemas"]["vmorch_UnixEpoch"]; }; /** @description if the script is valid utf8 then the response may be in either string, or byte form and the client must handle both */ vmorch_UserData: string | number[]; vmorch_VmInstance: { + id: string; cluster_id: string; current_status: string; - id: string; last_updated_at: string; }; vmorch_VmsLogChunk: { - data: number[]; instance_id: string; - /** Format: u-int32 */ - monotonic_timestamp_nano_sec: number; - /** Format: u-int64 */ - monotonic_timestamp_sec: number; /** @description In RFC 3339 format */ realtime_timestamp: string; /** Format: u-int64 */ + monotonic_timestamp_sec: number; + /** Format: u-int32 */ + monotonic_timestamp_nano_sec: number; + /** Format: u-int64 */ seqnum: number; + data: number[]; }; vmorch_VmsLogsResponse: { data: components["schemas"]["vmorch_VmsLogChunk"][]; @@ -1905,142 +2438,161 @@ export interface components { /** @enum {string} */ "node-api_AcceleratorType": "H100" | "H200"; "node-api_AvailabilityRectangle": { + start_timestamp: components["schemas"]["node-api_UnixEpoch"]; end_timestamp: components["schemas"]["node-api_UnixEpoch"]; /** * Format: u-int64 * @description The number of nodes available during this time period */ quantity: number; - start_timestamp: components["schemas"]["node-api_UnixEpoch"]; }; "node-api_CreateNodesRequest": { - /** @description User script to be executed during the VM's boot process */ - cloud_init_user_data?: number[]; /** * Format: u-int32 * @example 1 */ desired_count: number; /** - * Format: int64 - * @description End time as Unix timestamp in seconds. - * If provided, end time must be aligned to the hour. - * If not provided, the node will be created as an autoreserved node. + * @description Zone to create the nodes in. Required for auto reserved nodes if any_zone is false. + * @example hayesvalley */ - end_at?: number | null; + zone?: string; /** - * @description Custom image ID to use for the VM instances - * @example vmi_1234567890abcdef + * @description Allow auto reserved nodes to be created in any zone that meets the requirements + * @default false + * @example false */ - image_id?: string; + any_zone: boolean; /** * Format: int64 * @description Max price per hour for a node in cents - * @example 1000 + * @example 1600 */ max_price_per_node_hour: number; /** - * @description Custom node names. - * Names cannot follow the vm_{alpha_numeric_chars} as this is reserved for system-generated IDs. - * Names cannot be numeric strings. + * Format: int64 + * @description Start time as Unix timestamp in seconds + * Optional for reserved nodes. If not provided, defaults to now + * @example 1640995200 + */ + start_at?: number; + /** + * Format: int64 + * @description End time as Unix timestamp in seconds + * If provided, end time must be aligned to the hour + * If not provided, the node will be created as an autoreserved node + */ + end_at?: number | null; + /** @default autoreserved */ + node_type: null | components["schemas"]["node-api_NodeType"]; + /** + * @description Custom node names + * Names cannot begin with 'vm_' or 'n_' as this is reserved for system-generated IDs + * Names cannot be numeric strings + * Names cannot exceed 128 characters * @example [ * "cuda-crunch" * ] */ names?: string[]; - /** @default autoreserved */ - node_type: null | components["schemas"]["node-api_NodeType"]; /** - * Format: int64 - * @description Start time as Unix timestamp in seconds - * @example 1640995200 + * Format: byte + * @description User script to be executed during the VM's boot process + * Data should be base64 encoded + * @example aGVsbG8gd29ybGQ= */ - start_at?: number | null; + cloud_init_user_data?: string; /** - * @description Zone to create the nodes in - * @example hayesvalley + * @description Custom image ID to use for the VM instances + * @example vmi_1234567890abcdef */ - zone: string; + image_id?: string; + /** + * @description (Optional) If set, enables forwarding to the VM on port 443. + * @default false + * @example false + */ + forward_443: boolean; }; /** @enum {string} */ "node-api_DeliveryType": "K8s" | "VM"; "node-api_ErrorContent": { - details?: components["schemas"]["node-api_ErrorDetail"][]; - message: string; type: components["schemas"]["node-api_ErrorType"]; + message: string; + details?: components["schemas"]["node-api_ErrorDetail"][]; }; "node-api_ErrorDetail": { - /** @description Specific error code for this detail */ - code: string; /** @description The field that caused the error (for validation errors) */ field?: string | null; - /** @description Detailed error message */ + /** @description Specific error code for this detail */ + code: string; + /** @description Human-readable error message */ message: string; }; "node-api_ErrorKind": | { - details?: components["schemas"]["node-api_ErrorDetail"][]; message: string; + details?: components["schemas"]["node-api_ErrorDetail"][]; /** @enum {string} */ type: "api_error"; } | { - details?: components["schemas"]["node-api_ErrorDetail"][]; message: string; + details?: components["schemas"]["node-api_ErrorDetail"][]; /** @enum {string} */ type: "invalid_request_error"; } | { - details?: components["schemas"]["node-api_ErrorDetail"][]; message: string; + details?: components["schemas"]["node-api_ErrorDetail"][]; /** @enum {string} */ type: "authentication_error"; } | { - details?: components["schemas"]["node-api_ErrorDetail"][]; message: string; + details?: components["schemas"]["node-api_ErrorDetail"][]; /** @enum {string} */ type: "idempotency_error"; } | { - details?: components["schemas"]["node-api_ErrorDetail"][]; message: string; + details?: components["schemas"]["node-api_ErrorDetail"][]; /** @enum {string} */ type: "conflict"; } | { - details?: components["schemas"]["node-api_ErrorDetail"][]; message: string; + details?: components["schemas"]["node-api_ErrorDetail"][]; /** @enum {string} */ type: "not_found"; } | { - details?: components["schemas"]["node-api_ErrorDetail"][]; message: string; + details?: components["schemas"]["node-api_ErrorDetail"][]; /** @enum {string} */ type: "request_timed_out"; } | { - details?: components["schemas"]["node-api_ErrorDetail"][]; message: string; + details?: components["schemas"]["node-api_ErrorDetail"][]; /** @enum {string} */ type: "forbidden"; } | { - details?: components["schemas"]["node-api_ErrorDetail"][]; message: string; + details?: components["schemas"]["node-api_ErrorDetail"][]; /** @enum {string} */ type: "not_implemented"; } | { - details?: components["schemas"]["node-api_ErrorDetail"][]; message: string; + details?: components["schemas"]["node-api_ErrorDetail"][]; /** @enum {string} */ type: "upgrade_required"; } | { - details?: components["schemas"]["node-api_ErrorDetail"][]; message: string; + details?: components["schemas"]["node-api_ErrorDetail"][]; /** @enum {string} */ type: "payment_required"; }; @@ -2060,7 +2612,8 @@ export interface components { | "not_implemented" | "upgrade_required" | "payment_required" - | "service_unavailable"; + | "service_unavailable" + | "unprocessable_entity"; "node-api_ExtendNodeRequest": { /** * Format: int64 @@ -2079,7 +2632,21 @@ export interface components { /** @enum {string} */ "node-api_InterconnectType": "Infiniband" | "None"; "node-api_ListResponse_Node": { + /** @example list */ + object: string; data: { + /** @example node */ + object: string; + /** @example n_b1dc52505c6db142 */ + id: string; + /** @example cuda-crunch */ + name: string; + /** @example hayesvalley */ + zone?: string | null; + gpu_type: components["schemas"]["node-api_AcceleratorType"]; + /** @example sfcompute */ + owner: string; + status: components["schemas"]["node-api_Status"]; /** * Format: int64 * @description Creation time as Unix timestamp in seconds @@ -2088,125 +2655,142 @@ export interface components { created_at?: number | null; /** * Format: int64 - * @description Deletion time as Unix timestamp in seconds + * @description Last updated time as Unix timestamp in seconds * @example 1640995200 */ - deleted_at?: number | null; + updated_at?: number | null; /** * Format: int64 - * @description End time as Unix timestamp in seconds + * @description Start time as Unix timestamp in seconds * @example 1640995200 */ - end_at?: number | null; - gpu_type: components["schemas"]["node-api_AcceleratorType"]; - /** @example n_b1dc52505c6db142 */ - id: string; + start_at?: number | null; /** * Format: int64 - * @description Max price per hour you're willing to pay for a node in cents - * @example 1000 + * @description End time as Unix timestamp in seconds + * @example 1640995200 */ - max_price_per_node_hour?: number | null; - /** @example cuda-crunch */ - name: string; - node_type: components["schemas"]["node-api_NodeType"]; - /** @example node */ - object: string; - /** @example sfcompute */ - owner: string; - /** @example proc_b1dc52505c6de142 */ - procurement_id?: string | null; + end_at?: number | null; /** * Format: int64 - * @description Start time as Unix timestamp in seconds + * @description Deletion time as Unix timestamp in seconds * @example 1640995200 */ - start_at?: number | null; - status: components["schemas"]["node-api_Status"]; + deleted_at?: number | null; + /** @example proc_b1dc52505c6de142 */ + procurement_id?: string | null; /** * Format: int64 - * @description Last updated time as Unix timestamp in seconds - * @example 1640995200 + * @description Max price per hour you're willing to pay for a node in cents + * @example 1000 */ - updated_at?: number | null; + max_price_per_node_hour?: number | null; + node_type: components["schemas"]["node-api_NodeType"]; vms?: null | components["schemas"]["node-api_VmList"]; - /** @example hayesvalley */ - zone?: string | null; + current_vm?: null | components["schemas"]["node-api_Vm"]; }[]; - /** @example list */ - object: string; }; "node-api_ListResponse_ZoneInfo": { + /** @example list */ + object: string; data: { - /** @description The available capacity on this cluster, in the - * shape of consecutive "availability rectangles". */ + object: string; + name: string; + /** @description User-facing zone name (e.g., "Hayes Valley", "Land's End") */ + display_name?: string | null; + /** + * @description The available capacity on this cluster, in the + * shape of consecutive "availability rectangles". + */ available_capacity: components["schemas"]["node-api_AvailabilityRectangle"][]; - delivery_type: components["schemas"]["node-api_DeliveryType"]; + region: components["schemas"]["node-api_Region"]; hardware_type: components["schemas"]["node-api_AcceleratorType"]; interconnect_type: components["schemas"]["node-api_InterconnectType"]; - name: string; - object: string; - region: components["schemas"]["node-api_Region"]; + delivery_type: components["schemas"]["node-api_DeliveryType"]; }[]; - /** @example list */ - object: string; }; "node-api_Node": { + /** @example node */ + object: string; + /** @example n_b1dc52505c6db142 */ + id: string; + /** @example cuda-crunch */ + name: string; + /** @example hayesvalley */ + zone?: string | null; + gpu_type: components["schemas"]["node-api_AcceleratorType"]; + /** @example sfcompute */ + owner: string; + status: components["schemas"]["node-api_Status"]; /** * Format: int64 - * @description Creation time as Unix timestamp in seconds - * @example 1640995200 - */ - created_at?: number | null; - /** - * Format: int64 - * @description Deletion time as Unix timestamp in seconds - * @example 1640995200 - */ - deleted_at?: number | null; - /** - * Format: int64 - * @description End time as Unix timestamp in seconds + * @description Creation time as Unix timestamp in seconds * @example 1640995200 */ - end_at?: number | null; - gpu_type: components["schemas"]["node-api_AcceleratorType"]; - /** @example n_b1dc52505c6db142 */ - id: string; + created_at?: number | null; /** * Format: int64 - * @description Max price per hour you're willing to pay for a node in cents - * @example 1000 + * @description Last updated time as Unix timestamp in seconds + * @example 1640995200 */ - max_price_per_node_hour?: number | null; - /** @example cuda-crunch */ - name: string; - node_type: components["schemas"]["node-api_NodeType"]; - /** @example node */ - object: string; - /** @example sfcompute */ - owner: string; - /** @example proc_b1dc52505c6de142 */ - procurement_id?: string | null; + updated_at?: number | null; /** * Format: int64 * @description Start time as Unix timestamp in seconds * @example 1640995200 */ start_at?: number | null; - status: components["schemas"]["node-api_Status"]; /** * Format: int64 - * @description Last updated time as Unix timestamp in seconds + * @description End time as Unix timestamp in seconds * @example 1640995200 */ - updated_at?: number | null; + end_at?: number | null; + /** + * Format: int64 + * @description Deletion time as Unix timestamp in seconds + * @example 1640995200 + */ + deleted_at?: number | null; + /** @example proc_b1dc52505c6de142 */ + procurement_id?: string | null; + /** + * Format: int64 + * @description Max price per hour you're willing to pay for a node in cents + * @example 1000 + */ + max_price_per_node_hour?: number | null; + node_type: components["schemas"]["node-api_NodeType"]; vms?: null | components["schemas"]["node-api_VmList"]; - /** @example hayesvalley */ - zone?: string | null; + current_vm?: null | components["schemas"]["node-api_Vm"]; }; /** @enum {string} */ "node-api_NodeType": "autoreserved" | "reserved"; + "node-api_RedeployNodeRequest": { + /** + * @description Redeploy node with this VM image ID + * @example vmi_1234567890abcdef + */ + image_id?: string; + /** + * Format: byte + * @description Update the cloud init user data for VMs running on this node + * Data should be base64 encoded + * @example aGVsbG8gd29ybGQ= + */ + cloud_init_user_data?: string; + /** + * @description If false, then the new VM will inherit any configuration (like image_id, + * cloud_init_user_data) that is left empty in this request from the current VM. + * + * If true, then any configuration left empty will be set as empty in the new VM. + * E.g if cloud_init_user_data is left unset and override_empty is true, then the new VM will not + * have any cloud init user data. + * override_empty defaults to false. + * @default false + */ + override_empty: boolean; + }; /** @enum {string} */ "node-api_Region": | "NorthAmerica" @@ -2228,9 +2812,15 @@ export interface components { /** * Format: int64 * @description Unix timestamp in seconds since epoch + * @example 1738972800 */ "node-api_UnixEpoch": number; "node-api_Vm": { + /** @example vm */ + object: string; + /** @example vm_myOZZXw4pfcp7H9DQOldd */ + id: string; + status: components["schemas"]["node-api_VmStatus"]; /** * Format: int64 * @example 1640995200 @@ -2238,31 +2828,28 @@ export interface components { created_at: number; /** * Format: int64 - * @example 1640998200 + * @example 1640995200 */ - end_at: number | null; - /** @example vm_myOZZXw4pfcp7H9DQOldd */ - id: string; - /** @example vmi_myOZZXw4pfcp7H9DQOldd */ - image_id?: string | null; - /** @example vm */ - object: string; + updated_at: number; /** * Format: int64 * @example 1640995200 */ start_at: number | null; - status: components["schemas"]["node-api_VmStatus"]; /** * Format: int64 - * @example 1640995200 + * @example 1640998200 */ - updated_at: number; + end_at: number | null; + /** @example vmi_myOZZXw4pfcp7H9DQOldd */ + image_id?: string | null; + /** @example hayesvalley */ + zone: string; }; "node-api_VmList": { - data: components["schemas"]["node-api_Vm"][]; /** @example list */ object: string; + data: components["schemas"]["node-api_Vm"][]; }; /** @enum {string} */ "node-api_VmStatus": @@ -2272,29 +2859,32 @@ export interface components { | "NodeFailure" | "Unspecified"; "node-api_ZoneInfo": { - /** @description The available capacity on this cluster, in the - * shape of consecutive "availability rectangles". */ + object: string; + name: string; + /** @description User-facing zone name (e.g., "Hayes Valley", "Land's End") */ + display_name?: string | null; + /** + * @description The available capacity on this cluster, in the + * shape of consecutive "availability rectangles". + */ available_capacity: components["schemas"]["node-api_AvailabilityRectangle"][]; - delivery_type: components["schemas"]["node-api_DeliveryType"]; + region: components["schemas"]["node-api_Region"]; hardware_type: components["schemas"]["node-api_AcceleratorType"]; interconnect_type: components["schemas"]["node-api_InterconnectType"]; - name: string; - object: string; - region: components["schemas"]["node-api_Region"]; + delivery_type: components["schemas"]["node-api_DeliveryType"]; }; /** @description Response body for the account/me endpoint. */ "market-api_AccountMeResponse": { - /** - * Format: u-int64 - * @description When the account was created as a epoch unix timestamp - * @example 1749704176 - */ - created_at: number; /** * @description The unique identifier for the account * @example gmail-com-name */ id: string; + /** + * @description The role assigned to this account + * @example user + */ + role: string; /** * @description Whether the account is currently frozen * @example false @@ -2305,16 +2895,6 @@ export interface components { * @example basic */ kyc: string; - /** - * @description Whether the KYC-B form has been submitted - * @example false - */ - kycb_form_submitted: boolean; - /** - * @description The role assigned to this account - * @example user - */ - role: string; /** * @description Whether the user has submitted the waitlist form * @example true @@ -2325,23 +2905,150 @@ export interface components { * @example false */ waitlist: boolean; + /** + * @description Whether the KYC-B form has been submitted + * @example false + */ + kycb_form_submitted: boolean; + /** + * Format: u-int64 + * @description When the account was created as a epoch unix timestamp + * @example 1749704176 + */ + created_at: number; + }; + "market-api_AddressPayload": { + country: string; + postal_code?: string | null; + state?: string | null; + city?: string | null; + line1?: string | null; + line2?: string | null; + }; + "market-api_BaseCapacityDetails": { + /** + * @example capacity + * @enum {string} + */ + object: "capacity"; + id: components["schemas"]["market-api_CapacityId"]; + name?: null | components["schemas"]["market-api_Name"]; + node_template?: null | components["schemas"]["market-api_NodeTemplateId"]; + /** @description Automatically start and stop nodes when this capacity has compute available. Requires a node template. */ + start_nodes_automatically: boolean; + /** @description Zone requirements for this capacity. */ + requirements: { + zones: components["schemas"]["market-api_ZoneName"][]; + /** @enum {string} */ + type: "zones"; + }; + created_at: components["schemas"]["market-api_UnixEpoch"]; + }; + "market-api_CalculateInvoicePricingRequest": { + invoice_id: string; + payment_method_type: string; + /** Format: int64 */ + credit_amount_cents?: number | null; + address?: null | components["schemas"]["market-api_AddressPayload"]; + /** @default false */ + should_update_customer_address: boolean; }; - "market-api_AccountRefundsResponse": { + "market-api_CalculateInvoicePricingResponse": { /** - * @example refunds + * @example pricing * @enum {string} */ - object: "refunds"; - refunds: components["schemas"]["market-api_RefundResponse"][]; + object: "pricing"; + /** Format: int64 */ + credit_amount_cents: number; + /** Format: int64 */ + platform_fee_cents: number; + /** Format: int64 */ + actual_fee_cents: number; + /** Format: int64 */ + adjustment_cents: number; + /** Format: int64 */ + subtotal_cents: number; + /** Format: int64 */ + tax_cents: number; + /** Format: int64 */ + total_with_tax_cents: number; + payment_method_type: string; + updated: boolean; }; "market-api_CancelOrderResponse": { object: components["schemas"]["market-api_CancelOrderStatus"]; }; /** @enum {string} */ "market-api_CancelOrderStatus": "pending"; - /** @description string with format '"clus"_{base62_encoded_id}' used for referencing a ClusterId resource. Never user-generated. */ + /** + * @description Opaque pagination cursor for CapacitiesCursor. Wire format: `capc_{base64url}`. + * @example capc_gqXR7s0Kj5mHvE2wNpLc4Q + */ + "market-api_CapacitiesCursor": string; + "market-api_CapacityDetails": { + /** + * @example capacity + * @enum {string} + */ + object: "capacity"; + id: components["schemas"]["market-api_CapacityId"]; + name?: null | components["schemas"]["market-api_Name"]; + node_template?: null | components["schemas"]["market-api_NodeTemplateId"]; + /** @description Automatically start and stop nodes when this capacity has compute available. Requires a node template. */ + start_nodes_automatically: boolean; + /** @description Zone requirements for this capacity. */ + requirements: { + zones: components["schemas"]["market-api_ZoneName"][]; + /** @enum {string} */ + type: "zones"; + }; + created_at: components["schemas"]["market-api_UnixEpoch"]; + } & { + /** @description Compute schedule for this capacity, per zone and aggregated. */ + schedule_info: { + /** @description Future schedule of allocated compute per zone. Does not include historical data. */ + zone_schedules: { + [key: string]: components["schemas"]["market-api_Schedule"]; + }; + /** @description Combined schedule across all zones. */ + total_schedule: components["schemas"]["market-api_Schedule"]; + }; + /** @description Scheduler configuration for this capacity. */ + scheduler: components["schemas"]["market-api_SchedulerDetails"]; + }; + /** + * @description Unique identifier with prefix 'cap_'. + * @example cap_k3R-nX9vLm7Qp2Yw5Jd8F + */ + "market-api_CapacityId": string; + "market-api_CapacityListEntry": { + /** + * @example capacity + * @enum {string} + */ + object: "capacity"; + id: components["schemas"]["market-api_CapacityId"]; + name?: null | components["schemas"]["market-api_Name"]; + node_template?: null | components["schemas"]["market-api_NodeTemplateId"]; + /** @description Automatically start and stop nodes when this capacity has compute available. Requires a node template. */ + start_nodes_automatically: boolean; + /** @description Zone requirements for this capacity. */ + requirements: { + zones: components["schemas"]["market-api_ZoneName"][]; + /** @enum {string} */ + type: "zones"; + }; + created_at: components["schemas"]["market-api_UnixEpoch"]; + } & { + /** @description Whether an active scheduler exists for this capacity */ + scheduler_enabled: boolean; + }; + /** + * @description Unique identifier with prefix 'clus_' that references a resource. + * @example clus_k3R-nX9vLm7Qp2Yw5Jd8F + */ "market-api_ClusterId": string; - "market-api_ClusterName": string; "market-api_ColocationStrategy": | { /** @enum {string} */ @@ -2356,106 +3063,139 @@ export interface components { type: "colocate-pinned"; } | { - cluster_name: components["schemas"]["market-api_ClusterName"]; + cluster_name: components["schemas"]["market-api_ZoneName"]; /** @enum {string} */ type: "pinned"; }; - /** @description string with format '"cont"_{base62_encoded_id}' used for referencing a ContractId resource. Never user-generated. */ + /** + * @description Unique identifier with prefix 'cont_' that references a resource. + * @example cont_k3R-nX9vLm7Qp2Yw5Jd8F + */ "market-api_ContractId": string; "market-api_ContractResponse": { - cluster_id?: null | components["schemas"]["market-api_ClusterId"]; - colocate_with?: components["schemas"]["market-api_ContractId"][]; - created_at: components["schemas"]["market-api_ISO8601DateTime"]; - id: components["schemas"]["market-api_ContractId"]; - instance_type: components["schemas"]["market-api_Ticker"]; /** * @example contract * @enum {string} */ object: "contract"; - shape: components["schemas"]["market-api_ContractShape"]; - state: components["schemas"]["market-api_ContractState"]; status: components["schemas"]["market-api_ContractStatus"]; - }; - "market-api_ContractShape": { - intervals: components["schemas"]["market-api_ISO8601DateTime"][]; - quantities: number[]; + id: components["schemas"]["market-api_ContractId"]; + created_at: components["schemas"]["market-api_ISO8601DateTime"]; + instance_type: components["schemas"]["market-api_Ticker"]; + shape: components["schemas"]["market-api_ExternalShape"]; + /** @deprecated */ + colocate_with?: components["schemas"]["market-api_ContractId"][]; + cluster_id?: null | components["schemas"]["market-api_ClusterId"]; + zone?: null | components["schemas"]["market-api_ZoneName"]; + state: components["schemas"]["market-api_ContractState"]; + /** + * @description Specifies whether this contract is managed by the Nodes API + * @example true + */ + is_node: boolean; + /** + * @description The procurement which ordered this contract, if any + * @example proc_1234567890abcdef + */ + procurement_id?: string | null; }; /** @enum {string} */ "market-api_ContractState": "Upcoming" | "Active" | "Expired"; /** @enum {string} */ "market-api_ContractStatus": "active" | "pending"; - "market-api_CreateOrderRequest": - | { - cluster?: null | components["schemas"]["market-api_ClusterName"]; - /** @description A contract to colocate with. This overrides the instance_type if specified. */ - colocate_with?: components["schemas"]["market-api_ContractId"][]; - end_at: components["schemas"]["market-api_NowOrISO8601DateTime"]; - flags?: components["schemas"]["market-api_OrderFlags"]; - instance_type?: null | components["schemas"]["market-api_Ticker"]; - /** - * Format: int64 - * @description Price in cents - * @example 5000 - */ - price: number; - /** - * Format: int32 - * @example 10 - */ - quantity: number; - /** @enum {string} */ - side: "buy"; - start_at: components["schemas"]["market-api_NowOrISO8601DateTime"]; - } - | { - contract_id: components["schemas"]["market-api_ContractId"]; - end_at: components["schemas"]["market-api_NowOrISO8601DateTime"]; - flags?: components["schemas"]["market-api_OrderFlags"]; - /** - * Format: int64 - * @description Price in cents - * @example 4500 - */ - price: number; - /** - * Format: int32 - * @example 5 - */ - quantity: number; - reprice?: unknown; - /** @enum {string} */ - side: "sell"; - start_at: components["schemas"]["market-api_NowOrISO8601DateTime"]; - }; - /** @example { + /** @description Create a new capacity to hold and manage compute. */ + "market-api_CreateCapacityRequest": { + name?: null | components["schemas"]["market-api_Name"]; + /** @description Requirements applied to compute acquired into this capacity (from orders or the scheduler). */ + requirements: { + zones: components["schemas"]["market-api_ZoneName"][]; + /** @enum {string} */ + type: "zones"; + }; + /** + * @description Default node template (ID, name, or inline definition). Used when starting nodes automatically or when no template is specified during node creation. + * It is the caller's responsibility to ensure the node template supports all zones listed in `requirements`. + */ + node_template?: components["schemas"]["market-api_ResourceRef_NodeTemplateId"]; + /** @description Automatically start and stop nodes when this capacity has compute available. Requires `node_template`. */ + start_nodes_automatically: boolean; + /** @description Scheduler that automatically places buy and sell orders for this capacity. */ + scheduler?: components["schemas"]["market-api_SchedulerDetails"]; + }; + "market-api_CreateDraftInvoiceRequest": { + /** Format: int64 */ + credit_amount_cents: number; + idempotency_key: string; + }; + "market-api_CreateDraftInvoiceResponse": { + /** + * @example invoice_draft + * @enum {string} + */ + object: "invoice_draft"; + invoice_id: string; + }; + /** @description Create a new node template defining the image and cloud-init config for nodes. */ + "market-api_CreateNodeTemplateRequest": { + /** @description User-defined name for the node template. Must be unique per owner. */ + name: components["schemas"]["market-api_Name"]; + /** @description Image ID or name for VMs using this template. */ + image: string; + /** + * Format: byte + * @description Cloud-init user data for VMs using this template. + * Data should be base64 encoded. + */ + cloud_init_user_data?: string; + }; + "market-api_CreateOrderRequest": { + /** @description Order side: "buy" or "sell" */ + side: components["schemas"]["market-api_Side"]; + instance_type?: null | components["schemas"]["market-api_Ticker"]; + /** + * Format: int32 + * @example 10 + */ + quantity: number; + start_at: components["schemas"]["market-api_NowOrISO8601DateTime"]; + end_at: components["schemas"]["market-api_NowOrISO8601DateTime"]; + /** + * Format: int64 + * @description Price in cents + * @example 1600 + */ + price: number; + flags?: components["schemas"]["market-api_OrderFlags"]; + /** @description A contract to colocate with. This overrides the instance_type if specified. */ + colocate_with?: components["schemas"]["market-api_ContractId"][]; + cluster?: null | components["schemas"]["market-api_ZoneName"]; + }; + /** + * @example { * "object": "order", * "status": "pending", * "id": "order_xyz789", * "idempotency_key": "key_123" - * } */ + * } + */ "market-api_CreateOrderResponse": { - id: components["schemas"]["market-api_OrderId"]; - /** @example key_123 */ - idempotency_key?: string | null; /** * @example order * @enum {string} */ object: "order"; status: components["schemas"]["market-api_CreateOrderStatus"]; + id: components["schemas"]["market-api_OrderId"]; + /** @example key_123 */ + idempotency_key?: string | null; }; /** @enum {string} */ "market-api_CreateOrderStatus": "pending" | "filled" | "cancelled"; "market-api_CreateProcurementRequest": { - /** - * Format: int32 - * @description Maximum price per GPU hour in cents - * @example 250 - */ - buy_limit_price_per_gpu_hour?: number; - /** @description Colocation strategy for the procurement */ - colocation_strategy?: components["schemas"]["market-api_ColocationStrategy"]; + /** @description Procurement status (active or disabled) */ + status?: components["schemas"]["market-api_ProcurementStatus"]; + /** @description Instance type to procure */ + instance_type: components["schemas"]["market-api_Ticker"]; /** * Format: int32 * @description Desired quantity of nodes @@ -2464,29 +3204,46 @@ export interface components { desired_quantity: number; /** * Format: int32 - * @description Planning horizon in minutes - * @example 60 + * @description Maximum price per GPU hour in cents + * @example 250 */ - horizon?: number; - /** @description Instance type to procure */ - instance_type: components["schemas"]["market-api_Ticker"]; + buy_limit_price_per_gpu_hour?: number; /** * Format: int32 * @description Minimum price per GPU hour in cents when selling back * @example 25 */ sell_limit_price_per_gpu_hour?: number; - /** @description Procurement status (active or disabled) */ - status?: components["schemas"]["market-api_ProcurementStatus"]; + /** + * Format: int32 + * @description Planning horizon in minutes + * @example 60 + */ + horizon?: number; + /** @description Colocation strategy for the procurement */ + colocation_strategy?: components["schemas"]["market-api_ColocationStrategy"]; + }; + /** + * @description Price rate in dollars per node-hour, encoded as a decimal string. Must contain a decimal point (e.g. "1.50"). Returns 6 decimal places of precision (e.g. "1.500000"). + * @example 2.500000 + */ + "market-api_DollarsPerNodeHour": string; + "market-api_ErrorContent": { + type: components["schemas"]["market-api_ErrorType"]; + message: string; + details?: components["schemas"]["market-api_ErrorDetail"][]; }; "market-api_ErrorDetail": { - /** @description Specific error code for this detail */ - code: string; /** @description The field that caused the error (for validation errors) */ field?: string | null; - /** @description Detailed error message */ + /** @description Specific error code for this detail */ + code: string; + /** @description Human-readable error message */ message: string; }; + "market-api_ErrorObject": { + error: components["schemas"]["market-api_ErrorContent"]; + }; /** @enum {string} */ "market-api_ErrorType": | "api_error" @@ -2500,7 +3257,33 @@ export interface components { | "not_implemented" | "upgrade_required" | "payment_required" - | "service_unavailable"; + | "service_unavailable" + | "unprocessable_entity"; + /** + * @description A schedule representing a change of a quantity over time. The schedule changes at + * intervals[i] to quantity[i]. Intervals are sorted from first to last change. + */ + "market-api_ExternalShape": { + /** @description The times at which changes in quantity occur */ + intervals: components["schemas"]["market-api_ISO8601DateTime"][]; + /** @description The quantity changed to at that time */ + quantities: number[]; + }; + "market-api_FinalizeInvoiceRequest": { + invoice_id: string; + }; + "market-api_FinalizeInvoiceResponse": { + /** + * @example payment + * @enum {string} + */ + object: "payment"; + success: boolean; + invoice_id: string; + payment_intent_id: string; + client_secret: string; + status: string; + }; /** * @description Response body for getting account balance from the credit ledger. * @example { @@ -2513,6 +3296,11 @@ export interface components { * } */ "market-api_GetBalanceResponse": { + /** + * @example balances + * @enum {string} + */ + object: "balances"; /** * Format: u-int64 * @description Available balance in cents: sum(credit) - sum(debit) - sum(committed holds) @@ -2531,11 +3319,6 @@ export interface components { * @example 0 */ current_overage_cents: number; - /** - * @example balances - * @enum {string} - */ - object: "balances"; /** * Format: u-int64 * @description The maximum amount of overages the account can incur before they are blocked from buying compute. @@ -2549,35 +3332,6 @@ export interface components { */ updated_at: number; }; - /** - * @description TODO rename route to "balance"? - * Response body for getting account credits. - * @example { - * "current_balance_cents": 150000, - * "available_credits_cents": 150000, - * "amount_due_next_billing_period_cents": 0 - * } - */ - "market-api_GetCreditsResponse": { - /** - * Format: int64 - * @description The amount due for the next billing period in cents (positive means customer owes, 0 or negative means no payment due) - * @example 0 - */ - amount_due_next_billing_period_cents: number; - /** - * Format: int64 - * @description The available prepaid credits in cents (always positive) - * @example 150000 - */ - available_credits_cents: number; - /** - * Format: int64 - * @description The current balance in cents (from customer account) - * @example 150000 - */ - current_balance_cents: number; - }; /** @description string with format 'txc_base62_encoded_id' used for paginating a query to GET /v1/transactions */ "market-api_GetTransactionsCursor": string; /** @@ -2586,65 +3340,90 @@ export interface components { * @example 2025-07-11T20:41:37.423Z */ "market-api_ISO8601DateTime": string; + /** + * @description Unique identifier with prefix 'image_'. + * @example image_k3R-nX9vLm7Qp2Yw5Jd8F + */ + "market-api_ImageId": string; "market-api_KubernetesClusterResponse": { - contract?: null | components["schemas"]["market-api_ContractResponse"]; + /** + * @example kubernetes_cluster + * @enum {string} + */ + object: "kubernetes_cluster"; /** @example https://cluster.example.com */ kubernetes_api_url?: string | null; - /** @example -----BEGIN CERTIFICATE-----... */ - kubernetes_ca_cert?: string | null; + name: components["schemas"]["market-api_ZoneName"]; /** @example sf-user123 */ kubernetes_namespace: string; - name: components["schemas"]["market-api_ClusterName"]; + /** @example -----BEGIN CERTIFICATE-----... */ + kubernetes_ca_cert?: string | null; + contract?: null | components["schemas"]["market-api_ContractResponse"]; + }; + "market-api_ListCapacitiesResponse": { /** - * @example kubernetes_cluster + * @example list * @enum {string} */ - object: "kubernetes_cluster"; + object: "list"; + cursor?: null | components["schemas"]["market-api_CapacitiesCursor"]; + has_more: boolean; + data: components["schemas"]["market-api_CapacityListEntry"][]; }; "market-api_ListClustersResponse": { - data: components["schemas"]["market-api_KubernetesClusterResponse"][]; - has_more: boolean; /** * @example list * @enum {string} */ object: "list"; + data: components["schemas"]["market-api_KubernetesClusterResponse"][]; + has_more: boolean; }; "market-api_ListContractsResponse": { + /** + * @example list + * @enum {string} + */ + object: "list"; data: components["schemas"]["market-api_ContractResponse"][]; has_more: boolean; + }; + "market-api_ListNodeTemplatesResponse": { /** * @example list * @enum {string} */ object: "list"; + cursor?: null | components["schemas"]["market-api_NodeTemplatesCursor"]; + has_more: boolean; + data: components["schemas"]["market-api_NodeTemplateDetails"][]; }; "market-api_ListOrdersResponse": { - data: components["schemas"]["market-api_OrderResponse"][]; - has_more: boolean; /** * @example list * @enum {string} */ object: "list"; + data: components["schemas"]["market-api_OrderResponse"][]; + has_more: boolean; }; "market-api_ListProcurementsResponse": { - data: components["schemas"]["market-api_ProcurementResponse"][]; - has_more: boolean; /** * @example list * @enum {string} */ object: "list"; + data: components["schemas"]["market-api_ProcurementResponse"][]; + has_more: boolean; }; "market-api_ListTransactionsResponse": { - data: components["schemas"]["market-api_TransactionResponse"][]; - has_more: boolean; /** * @example list * @enum {string} */ object: "list"; + has_more: boolean; + data: components["schemas"]["market-api_TransactionResponse"][]; }; /** * @description Request body for migrating an account to the new billing system. @@ -2677,6 +3456,55 @@ export interface components { "market-api_MigrateAccountResponse": | "migrated" | "requires_manual_migration"; + /** + * @description A validated resource name. Must start with alphanumeric, followed by alphanumeric, '.', '_', or '-'. Max 255 characters. + * @example my-resource-name + */ + "market-api_Name": string; + "market-api_NodeIdEntry": { + current_status: string; + product_uuid?: string | null; + internal_ipv4?: string | null; + source?: null | components["schemas"]["market-api_NodeSource"]; + }; + "market-api_NodeIdResponse": { + /** Format: u-int32 */ + count: number; + /** Format: date-time */ + request_timestamp: string; + data: components["schemas"]["market-api_NodeIdEntry"][]; + }; + /** @enum {string} */ + "market-api_NodeSource": "vm"; + "market-api_NodeTemplateDetails": { + /** + * @example node_template + * @enum {string} + */ + object?: "node_template"; + id: components["schemas"]["market-api_NodeTemplateId"]; + /** @description User-defined name for this node template. */ + name: components["schemas"]["market-api_Name"]; + /** @description Image ID for VMs using this template. */ + image: components["schemas"]["market-api_ImageId"]; + /** + * Format: byte + * @description Cloud-init user data for VMs using this template. + * Data should be base64 encoded. + */ + cloud_init_user_data?: string; + created_at: components["schemas"]["market-api_UnixEpoch"]; + }; + /** + * @description Unique identifier with prefix 'ntmpl_'. + * @example ntmpl_k3R-nX9vLm7Qp2Yw5Jd8F + */ + "market-api_NodeTemplateId": string; + /** + * @description Opaque pagination cursor for NodeTemplatesCursor. Wire format: `ntplc_{base64url}`. + * @example ntplc_gqXR7s0Kj5mHvE2wNpLc4Q + */ + "market-api_NodeTemplatesCursor": string; /** * @description A date/time value that can be either "NOW" or an ISO 8601 datetime string * @example NOW @@ -2685,126 +3513,263 @@ export interface components { "market-api_NowOrISO8601DateTime": string; /** @description Configure more fine grained order behavior. */ "market-api_OrderFlags": { - /** @description If true, the order will be automatically cancelled if it doesn't - * immediately fill when being placed. */ + /** + * @description If true, the order will be automatically cancelled if it doesn't + * immediately fill when being placed. + */ ioc?: boolean; + /** + * @description If true, places the order straight into the book without trying to match + * against existing orders. + */ + post_only?: boolean; /** @description If true, ignores the set limit price and matches any price that is available. */ market?: boolean; - /** @description If true, places the order straight into the book without trying to match - * against existing orders. */ - post_only?: boolean; - /** @description If the order start time should be automatically changed to "now" once + /** + * @description If the order start time should be automatically changed to "now" once * start time < "now", proportionally changing it's limit price to reflect - * it's shorter duration. */ + * it's shorter duration. + */ prorate?: boolean; }; - /** @description string with format '"ordr"_{base62_encoded_id}' used for referencing a OrderId resource. Never user-generated. */ + /** + * @description Unique identifier with prefix 'ordr_' that references a resource. + * @example ordr_k3R-nX9vLm7Qp2Yw5Jd8F + */ "market-api_OrderId": string; "market-api_OrderResponse": { - cancelled: boolean; - cancelled_at?: null | components["schemas"]["market-api_ISO8601DateTime"]; - cluster?: null | components["schemas"]["market-api_ClusterName"]; - colocate_with?: components["schemas"]["market-api_ContractId"][]; - created_at: components["schemas"]["market-api_ISO8601DateTime"]; - duration: components["schemas"]["market-api_UnixEpoch"]; - end_at: components["schemas"]["market-api_ISO8601DateTime"]; - executed: boolean; - executed_at?: null | components["schemas"]["market-api_ISO8601DateTime"]; - /** Format: int64 */ - execution_price?: number | null; - flags: components["schemas"]["market-api_OrderFlags"]; - id: components["schemas"]["market-api_OrderId"]; - instance_type: components["schemas"]["market-api_Ticker"]; /** * @example order * @enum {string} */ object: "order"; + id: components["schemas"]["market-api_OrderId"]; + side: components["schemas"]["market-api_OrderSide"]; + status: components["schemas"]["market-api_OrderStatus"]; + instance_type: components["schemas"]["market-api_Ticker"]; + /** + * Format: int32 + * @example 4 + */ + quantity: number; + start_at: components["schemas"]["market-api_ISO8601DateTime"]; + end_at: components["schemas"]["market-api_ISO8601DateTime"]; /** * Format: int64 * @description Price in cents * @example 2850000 */ price: number; - /** - * Format: int32 - * @example 4 - */ - quantity: number; + flags: components["schemas"]["market-api_OrderFlags"]; + executed: boolean; + executed_at?: null | components["schemas"]["market-api_ISO8601DateTime"]; + /** Format: int64 */ + execution_price?: number | null; + cancelled: boolean; + cancelled_at?: null | components["schemas"]["market-api_ISO8601DateTime"]; + colocate_with?: components["schemas"]["market-api_ContractId"][]; + created_at: components["schemas"]["market-api_ISO8601DateTime"]; rejected: boolean; rejected_reason?: string | null; - side: components["schemas"]["market-api_OrderSide"]; - start_at: components["schemas"]["market-api_ISO8601DateTime"]; - status: components["schemas"]["market-api_OrderStatus"]; + cluster?: null | components["schemas"]["market-api_ZoneName"]; + duration: components["schemas"]["market-api_UnixEpoch"]; }; /** @enum {string} */ "market-api_OrderSide": "buy" | "sell"; /** @enum {string} */ "market-api_OrderStatus": "open" | "filled" | "cancelled" | "rejected"; + /** + * @description Opaque pagination cursor for OrdersCursor. Wire format: `orc_{base64url}`. + * @example orc_gqXR7s0Kj5mHvE2wNpLc4Q + */ + "market-api_OrdersCursor": string; + "market-api_PatchCapacityRequest": { + /** @description Human-readable name for the capacity. Must be unique per owner. Set to null to clear. */ + name?: string | null; + /** @description Requirements applied to compute acquired into this capacity. Replaces existing requirements. */ + requirements?: null | { + zones: components["schemas"]["market-api_ZoneName"][]; + /** @enum {string} */ + type: "zones"; + }; + /** @description Default node template (ID or name). Must belong to the same owner. */ + node_template?: string | null; + /** @description Automatically start and stop nodes when this capacity has compute available. Requires `node_template`. */ + start_nodes_automatically?: boolean | null; + /** @description Scheduler that automatically places buy and sell orders for this capacity. Replaces the existing scheduler. Omit to leave unchanged. */ + scheduler?: components["schemas"]["market-api_SchedulerDetails"]; + }; /** @enum {string} */ "market-api_ProcurementMessage": "insufficient_balance" | "running"; "market-api_ProcurementResponse": { + /** + * @example procurement + * @enum {string} + */ + object: "procurement"; + /** @example proc_W9TRG */ + id: string; + instance_type: components["schemas"]["market-api_Ticker"]; + status: components["schemas"]["market-api_ProcurementStatus"]; + /** + * Format: int32 + * @example 1 + */ + desired_quantity: number; /** * Format: int32 * @example 250 */ buy_limit_price_per_gpu_hour: number; - colocation_strategy: components["schemas"]["market-api_ColocationStrategy"]; /** * Format: int32 - * @example 1 + * @example 25 */ - desired_quantity: number; + sell_limit_price_per_gpu_hour: number; /** * Format: int32 * @example 60 */ horizon: number; - /** @example proc_W9TRG */ - id: string; - instance_type: components["schemas"]["market-api_Ticker"]; + colocation_strategy: components["schemas"]["market-api_ColocationStrategy"]; last_message: components["schemas"]["market-api_ProcurementMessage"]; + }; + /** @enum {string} */ + "market-api_ProcurementStatus": "active" | "disabled"; + "market-api_ProviderOrderResource": { /** - * @example procurement + * @example provider_order * @enum {string} */ - object: "procurement"; + object: "provider_order"; + cursor: components["schemas"]["market-api_ProviderOrdersCursor"]; + id: string; + /** Format: date-time */ + start_time: string; + /** Format: date-time */ + end_time: string; + /** Format: date-time */ + created_at: string; + /** Format: date-time */ + executed_at?: string | null; + /** Format: date-time */ + cancelled_at?: string | null; + executed: boolean; + cancelled: boolean; + quantity: string; + duration_hours: string; + tcv: string; + executed_gpu_hour_price?: string | null; + market: string; + accelerator_type: string; + sender: string; + was_repriced?: boolean | null; + }; + /** @description Opaque cursor string with format 'poc_base62_encoded_data' used for paginating provider orders */ + "market-api_ProviderOrdersCursor": string; + "market-api_ProviderOrdersResponse": { /** - * Format: int32 - * @example 25 + * @example list + * @enum {string} */ - sell_limit_price_per_gpu_hour: number; - status: components["schemas"]["market-api_ProcurementStatus"]; + object: "list"; + data: components["schemas"]["market-api_ProviderOrderResource"][]; + summary: components["schemas"]["market-api_ProviderOrdersSummary"]; + has_more: boolean; }; - /** @enum {string} */ - "market-api_ProcurementStatus": "active" | "disabled"; - "market-api_RefundResponse": { - memo_amount?: string | null; - refund_timestamp?: - | null - | components["schemas"]["market-api_ISO8601DateTime"]; - report_cluster_id: components["schemas"]["market-api_ClusterId"]; - report_created_at: components["schemas"]["market-api_ISO8601DateTime"]; - report_end_time: components["schemas"]["market-api_ISO8601DateTime"]; + "market-api_ProviderOrdersSummary": { + /** + * @example provider_orders_summary + * @enum {string} + */ + object: "provider_orders_summary"; /** Format: int64 */ - report_id: number; - report_memo: string; + total_revenue_cents: number; + total_revenue_usd: string; + order_count: number; + /** Format: double */ + average_gpu_hour_price_cents?: number | null; + average_gpu_hour_price_usd?: string | null; + /** Format: date-time */ + period_start: string; + /** Format: date-time */ + period_end: string; + /** Format: date-time */ + generated_at: string; + }; + "market-api_Requirements": { + zones: components["schemas"]["market-api_ZoneName"][]; + /** @enum {string} */ + type: "zones"; + }; + /** @description Pass an ID or name string to reference an existing resource. Pass an object to create a new resource inline. */ + "market-api_ResourceRef_CapacityId": + | string + | { + name?: null | components["schemas"]["market-api_Name"]; + /** @description Requirements applied to compute acquired into this capacity (from orders or the scheduler). */ + requirements: { + zones: components["schemas"]["market-api_ZoneName"][]; + /** @enum {string} */ + type: "zones"; + }; + /** + * @description Default node template (ID, name, or inline definition). Used when starting nodes automatically or when no template is specified during node creation. + * It is the caller's responsibility to ensure the node template supports all zones listed in `requirements`. + */ + node_template?: components["schemas"]["market-api_ResourceRef_NodeTemplateId"]; + /** @description Automatically start and stop nodes when this capacity has compute available. Requires `node_template`. */ + start_nodes_automatically: boolean; + /** @description Scheduler that automatically places buy and sell orders for this capacity. */ + scheduler?: components["schemas"]["market-api_SchedulerDetails"]; + }; + /** @description Pass an ID or name string to reference an existing resource. Pass an object to create a new resource inline. */ + "market-api_ResourceRef_NodeTemplateId": + | string + | { + /** @description User-defined name for the node template. Must be unique per owner. */ + name: components["schemas"]["market-api_Name"]; + /** @description Image ID or name for VMs using this template. */ + image: string; + /** + * Format: byte + * @description Cloud-init user data for VMs using this template. + * Data should be base64 encoded. + */ + cloud_init_user_data?: string; + }; + /** @description Denotes previous and upcoming capacity availability over time. */ + "market-api_Schedule": { + object: components["schemas"]["market-api_ScheduleDiscriminator"]; + data: components["schemas"]["market-api_ScheduleEntry"][]; + }; + /** + * @example schedule + * @enum {string} + */ + "market-api_ScheduleDiscriminator": "schedule"; + "market-api_ScheduleEntry": { + timestamp: components["schemas"]["market-api_UnixEpoch"]; /** Format: int32 */ - report_nodes_affected: number; - report_start_time: components["schemas"]["market-api_ISO8601DateTime"]; - status: components["schemas"]["market-api_RefundStatus"]; + quantity: number; }; - /** @enum {string} */ - "market-api_RefundStatus": "in_review" | "approved" | "refunded" | "denied"; - /** @description Standard error response format following API guidelines. */ + /** @description Scheduler that automatically places buy and sell orders for this capacity. */ + "market-api_SchedulerDetails": { + spot_scaler: components["schemas"]["market-api_SpotScalerConfig"]; + /** @enum {string} */ + type: "spot_scaler"; + }; + /** @description SFC standard error response */ "market-api_SerdeErrorProxy": { - /** @description Array of detailed error information when applicable */ - details: components["schemas"]["market-api_ErrorDetail"][]; - /** @description Human-readable error message */ - message: string; /** @description The error type identifier */ type: components["schemas"]["market-api_ErrorType"]; + /** @description Human-readable error message */ + message: string; + /** @description Array of detailed error information when applicable */ + details: components["schemas"]["market-api_ErrorDetail"][]; }; + /** @enum {string} */ + "market-api_Side": "sell" | "buy"; /** * @description Sort field for listing orders * @example created_at @@ -2819,6 +3784,24 @@ export interface components { * @enum {string} */ "market-api_SortDirection": "ASC" | "DESC"; + "market-api_SpotScalerConfig": { + /** @description Floor price for selling compute out of this capacity (dollars/node-hour). */ + min_sell_price_dollars_per_node_hour: components["schemas"]["market-api_DollarsPerNodeHour"]; + /** @description Ceiling price for buying compute into this capacity (dollars/node-hour). */ + max_buy_price_dollars_per_node_hour: components["schemas"]["market-api_DollarsPerNodeHour"]; + /** + * Format: u-int64 + * @description Target number of nodes to maintain in this capacity. + */ + desired_quantity: number; + /** + * Format: u-int64 + * @description Maximum time ahead (in minutes) the scheduler buys and sells compute for this capacity. Higher values secure compute further in advance but commit to longer windows that may need to be sold when scaling down, potentially at a loss. Lower values reduce waste but increase the risk of desired compute being unavailable. Orders are placed in 1-hour blocks within this window, so the furthest hour is secured up to `managed_window_minutes - 60` minutes before it begins. Range: 60 -- 1440. + */ + managed_window_minutes: number; + /** @description Whether the scheduler actively places orders */ + enabled: boolean; + }; /** * @example h100i * @example h100v @@ -2827,35 +3810,35 @@ export interface components { "market-api_Ticker": string; "market-api_TransactionDetails": | { - card_brand: string; - card_funding: string; - card_last4: string; /** * @example transaction_details * @enum {string} */ object: "transaction_details"; + card_last4: string; + card_brand: string; + card_funding: string; receipt_url: string; /** @enum {string} */ type: "stripe_card_payment"; } | { - description: string; /** * @example transaction_details * @enum {string} */ object: "transaction_details"; + description: string; /** @enum {string} */ type: "manual_payment"; } | { - memo: string; /** * @example transaction_details * @enum {string} */ object: "transaction_details"; + memo: string; /** @enum {string} */ type: "credit_grant"; } @@ -2875,10 +3858,115 @@ export interface components { */ object: "transaction_details"; order_id: components["schemas"]["market-api_OrderId"]; + order?: null | { + /** + * @example order + * @enum {string} + */ + object: "order"; + id: components["schemas"]["market-api_OrderId"]; + side: components["schemas"]["market-api_OrderSide"]; + status: components["schemas"]["market-api_OrderStatus"]; + instance_type: components["schemas"]["market-api_Ticker"]; + /** + * Format: int32 + * @example 4 + */ + quantity: number; + start_at: components["schemas"]["market-api_ISO8601DateTime"]; + end_at: components["schemas"]["market-api_ISO8601DateTime"]; + /** + * Format: int64 + * @description Price in cents + * @example 2850000 + */ + price: number; + flags: components["schemas"]["market-api_OrderFlags"]; + executed: boolean; + executed_at?: + | null + | components["schemas"]["market-api_ISO8601DateTime"]; + /** Format: int64 */ + execution_price?: number | null; + cancelled: boolean; + cancelled_at?: + | null + | components["schemas"]["market-api_ISO8601DateTime"]; + colocate_with?: components["schemas"]["market-api_ContractId"][]; + created_at: components["schemas"]["market-api_ISO8601DateTime"]; + rejected: boolean; + rejected_reason?: string | null; + cluster?: null | components["schemas"]["market-api_ZoneName"]; + duration: components["schemas"]["market-api_UnixEpoch"]; + }; /** @enum {string} */ type: "buy_order"; + } + | { + /** + * @example transaction_details + * @enum {string} + */ + object: "transaction_details"; + order_id: components["schemas"]["market-api_OrderId"]; + order?: null | { + /** + * @example order + * @enum {string} + */ + object: "order"; + id: components["schemas"]["market-api_OrderId"]; + side: components["schemas"]["market-api_OrderSide"]; + status: components["schemas"]["market-api_OrderStatus"]; + instance_type: components["schemas"]["market-api_Ticker"]; + /** + * Format: int32 + * @example 4 + */ + quantity: number; + start_at: components["schemas"]["market-api_ISO8601DateTime"]; + end_at: components["schemas"]["market-api_ISO8601DateTime"]; + /** + * Format: int64 + * @description Price in cents + * @example 2850000 + */ + price: number; + flags: components["schemas"]["market-api_OrderFlags"]; + executed: boolean; + executed_at?: + | null + | components["schemas"]["market-api_ISO8601DateTime"]; + /** Format: int64 */ + execution_price?: number | null; + cancelled: boolean; + cancelled_at?: + | null + | components["schemas"]["market-api_ISO8601DateTime"]; + colocate_with?: components["schemas"]["market-api_ContractId"][]; + created_at: components["schemas"]["market-api_ISO8601DateTime"]; + rejected: boolean; + rejected_reason?: string | null; + cluster?: null | components["schemas"]["market-api_ZoneName"]; + duration: components["schemas"]["market-api_UnixEpoch"]; + }; + /** @enum {string} */ + type: "sell_order"; }; "market-api_TransactionResponse": { + /** + * @example transaction + * @enum {string} + */ + object: "transaction"; + /** @description Opaque cursor for use in pagination */ + cursor: components["schemas"]["market-api_GetTransactionsCursor"]; + /** + * Format: int64 + * @description Time the transaction took place as UNIX timestamp in seconds. + * @example 1640995200 + */ + transaction_time: number; /** * Format: int64 * @description Transaction amount in cents (e.g., 50000 = $500.00) @@ -2890,28 +3978,32 @@ export interface components { * @description Balance immediately after this transaction took place, in cents (e.g., 50000 = $500.00). */ balance: number; - /** @description Opaque cursor for use in pagination */ - cursor: components["schemas"]["market-api_GetTransactionsCursor"]; /** @description Transaction details */ details: components["schemas"]["market-api_TransactionDetails"]; - /** - * @example transaction - * @enum {string} - */ - object: "transaction"; - /** - * Format: int64 - * @description Time the transaction took place as UNIX timestamp in seconds. - * @example 1640995200 - */ - transaction_time: number; }; + /** @enum {string} */ + "market-api_TransactionTypeFilter": + | "stripe_card_payment" + | "manual_payment" + | "credit_grant" + | "refund" + | "buy_order" + | "sell_order"; /** * Format: int64 * @description Unix timestamp in seconds since epoch + * @example 1738972800 */ "market-api_UnixEpoch": number; "market-api_UpdateProcurementRequest": { + status?: null | components["schemas"]["market-api_ProcurementStatus"]; + instance_type?: null | components["schemas"]["market-api_Ticker"]; + /** + * Format: int32 + * @description Desired quantity of nodes + * @example 5 + */ + desired_quantity?: number | null; /** * Format: int32 * @description Maximum price per GPU hour in cents @@ -2920,10 +4012,10 @@ export interface components { buy_limit_price_per_gpu_hour?: number | null; /** * Format: int32 - * @description Desired quantity of nodes - * @example 5 + * @description Minimum price per GPU hour in cents when selling back + * @example 50 */ - desired_quantity?: number | null; + sell_limit_price_per_gpu_hour?: number | null; /** * Format: int32 * @description Planning horizon in minutes. The procurement will try to buy compute @@ -2932,52 +4024,194 @@ export interface components { * @example 120 */ horizon?: number | null; - instance_type?: null | components["schemas"]["market-api_Ticker"]; + }; + /** + * @description A physically colocated datacenter. + * @example hayesvalley + */ + "market-api_ZoneName": string; + "market-api_v2.CreateOrderRequest": { + /** @description The capacity to place the order for. Either a capacity ID or an inline capacity definition. */ + capacity: components["schemas"]["market-api_ResourceRef_CapacityId"]; + /** @description Order side: "buy" or "sell" */ + side: components["schemas"]["market-api_Side"]; + /** + * @description If true, allow the order to remain on the book if not immediately filled. + * If false (default), the order is immediate-or-cancel. + */ + allow_standing: boolean; /** * Format: int32 - * @description Minimum price per GPU hour in cents when selling back - * @example 50 + * @description Number of nodes to order. */ - sell_limit_price_per_gpu_hour?: number | null; - status?: null | components["schemas"]["market-api_ProcurementStatus"]; + quantity_nodes: number; + /** + * Format: int64 + * @description Order start time as a unix timestamp (seconds). + * Must be approximately now or on a future hour boundary. + */ + start_at: number; + /** + * Format: int64 + * @description Order end time as a unix timestamp (seconds). Must be on an hour boundary. + */ + end_at: number; + /** @description Limit price in dollars per node-hour. */ + limit_price_dollars_per_node_hour: components["schemas"]["market-api_DollarsPerNodeHour"]; + }; + "market-api_v2.ListOrdersResponse": { + /** + * @example list + * @enum {string} + */ + object: "list"; + cursor?: null | components["schemas"]["market-api_OrdersCursor"]; + has_more: boolean; + data: components["schemas"]["market-api_v2.OrderResponse"][]; + }; + "market-api_v2.OrderResponse": { + /** + * @example order + * @enum {string} + */ + object: "order"; + /** @description The order ID. */ + id: components["schemas"]["market-api_OrderId"]; + /** @description The capacity this order is for. */ + capacity: components["schemas"]["market-api_CapacityId"]; + /** @description Order side: "buy" or "sell". */ + side: components["schemas"]["market-api_Side"]; + /** + * @description If true, the order can remain on the book if not immediately filled. + * If false (default), the order is immediate-or-cancel. + */ + allow_standing: boolean; + /** @description Order requirements. */ + requirements: { + zones: components["schemas"]["market-api_ZoneName"][]; + /** @enum {string} */ + type: "zones"; + }; + /** + * Format: int32 + * @description Number of nodes. + */ + quantity_nodes: number; + /** + * Format: int64 + * @description Order start time as a unix timestamp (seconds). + */ + start_at: number; + /** + * Format: int64 + * @description Order end time as a unix timestamp (seconds). + */ + end_at: number; + /** @description Limit price in dollars per node-hour. */ + limit_price_dollars_per_node_hour: components["schemas"]["market-api_DollarsPerNodeHour"]; + /** @description Order status. */ + status: components["schemas"]["market-api_v2.OrderStatus"]; + /** + * Format: int64 + * @description Unix timestamp when the order was placed. Present only if not pending or rejected. + */ + placed_at?: number | null; + /** + * Format: int64 + * @description Unix timestamp when the order was filled. Present only if filled. + */ + filled_at?: number | null; + fill_price_dollars_per_node_hour?: + | null + | components["schemas"]["market-api_DollarsPerNodeHour"]; + /** + * Format: int64 + * @description Unix timestamp when the order was cancelled. Present only if cancelled. + */ + cancelled_at?: number | null; }; + /** @enum {string} */ + "market-api_v2.OrderStatus": + | "pending" + | "filled" + | "rejected" + | "cancelled" + | "standing"; + /** + * @example { + * "id": "batch_bea1aa2c-fa2f-4ea5-b84f-d41320f2ec51", + * "account_id": "sfcompute-com-waylon", + * "object": "batch", + * "endpoint": "/v1/chat/completions", + * "errors": null, + * "input_file_uri": "https://add-input-file-uri.com", + * "completion_window": "7d", + * "status": "accepted", + * "output_file_uri": "https://add-output-file-uri.com", + * "created_at": "2025-07-28T19:48:54.687148Z", + * "in_progress_at": null, + * "expires_at": null, + * "finalizing_at": null, + * "completed_at": null, + * "failed_at": null, + * "cancelling_at": null, + * "expired_at": null, + * "cancelled_at": null, + * "request_counts": { + * "total": 0, + * "completed": 0, + * "failed": 0 + * }, + * "metadata": { + * "input_token_usage": null, + * "output_token_usage": null + * }, + * "deadline_at": "2025-07-29T19:48:54.687148Z", + * "model_id": "Qwen/Qwen2.5-VL-32B-Instruct", + * "retry_count": 0, + * "is_retry": false + * } + */ large_scale_inference_Batch: { + id: string; account_id: string; - /** Format: date-time */ - cancelled_at?: string | null; - /** Format: date-time */ - cancelling_at?: string | null; - /** Format: date-time */ - completed_at?: string | null; - completion_window: string; - /** Format: date-time */ - created_at: string; - /** Format: date-time */ - deadline_at: string; + object: string; endpoint: string; errors?: | null | components["schemas"]["large_scale_inference_BatchErrors"]; + input_file_uri: string; + completion_window: string; + status: components["schemas"]["large_scale_inference_BatchStatus"]; + output_file_uri: string; /** Format: date-time */ - expired_at?: string | null; + created_at: string; + /** Format: date-time */ + in_progress_at?: string | null; /** Format: date-time */ expires_at?: string | null; /** Format: date-time */ + finalizing_at?: string | null; + /** Format: date-time */ + completed_at?: string | null; + /** Format: date-time */ failed_at?: string | null; /** Format: date-time */ - finalizing_at?: string | null; - id: string; + cancelling_at?: string | null; /** Format: date-time */ - in_progress_at?: string | null; - input_file_uri: string; - metadata?: - | null - | components["schemas"]["large_scale_inference_BatchMetadata"]; - model_id: string; - object: string; - output_file_uri: string; + expired_at?: string | null; + /** Format: date-time */ + cancelled_at?: string | null; request_counts: components["schemas"]["large_scale_inference_RequestCounts"]; - status: components["schemas"]["large_scale_inference_BatchStatus"]; + metadata: { + [key: string]: string; + }; + /** Format: date-time */ + deadline_at: string; + model_id: string; + /** Format: int32 */ + retry_count: number; + is_retry: boolean; }; large_scale_inference_BatchErrorData: { code: string; @@ -2990,20 +4224,26 @@ export interface components { data: components["schemas"]["large_scale_inference_BatchErrorData"][]; object: string; }; - large_scale_inference_BatchMetadata: { - input_token_usage?: string | null; - output_token_usage?: string | null; - }; + /** + * @example { + * "input_file_uri": "https://add-input-file-uri.com", + * "output_file_uri": "https://add-output-file-uri.com", + * "endpoint": "/v1/chat/completions", + * "model_id": "Qwen/Qwen2.5-VL-32B-Instruct", + * "completion_window": "7d", + * "store": "s3" + * } + */ large_scale_inference_BatchRequest: { - completion_window: string; - endpoint: string; input_file_uri: string; - metadata?: - | null - | components["schemas"]["large_scale_inference_BatchMetadata"]; - model_id: string; output_file_uri: string; + endpoint: string; + model_id: string; store: string; + completion_window: string; + metadata?: { + [key: string]: string; + }; }; large_scale_inference_BatchRequests: | components["schemas"]["large_scale_inference_BatchRequest"] @@ -3022,17 +4262,14 @@ export interface components { | "expired" | "cancelling" | "cancelled" - | "waiting"; - large_scale_inference_BlendedPrice: { - /** Format: double */ - cents_per_million_tokens: number; - }; + | "waiting" + | "retrying"; large_scale_inference_ErrorDetail: { - /** @description Specific error code for this detail */ - code: string; /** @description The field that caused the error (for validation errors) */ field?: string | null; - /** @description Detailed error message */ + /** @description Specific error code for this detail */ + code: string; + /** @description Human-readable error message */ message: string; }; /** @enum {string} */ @@ -3048,101 +4285,79 @@ export interface components { | "not_implemented" | "upgrade_required" | "payment_required" - | "service_unavailable"; + | "service_unavailable" + | "unprocessable_entity"; large_scale_inference_Model: { + id: string; + display_name: string; /** Format: date-time */ created_at: string; - external_reference: string; - id: string; - name: string; /** Format: date-time */ retired_at?: string | null; + retired: boolean; + size: string; }; - large_scale_inference_Price: - | { - Blended: components["schemas"]["large_scale_inference_BlendedPrice"]; - } - | { - Specific: components["schemas"]["large_scale_inference_SpecificPrice"]; - }; large_scale_inference_RequestCounts: { + /** Format: u-int32 */ + total: number; /** Format: u-int32 */ completed: number; /** Format: u-int32 */ failed: number; - /** Format: u-int32 */ - total: number; }; - /** @description Standard error response format following API guidelines. */ + /** @description SFC standard error response */ large_scale_inference_SerdeErrorProxy: { - /** @description Array of detailed error information when applicable */ - details: components["schemas"]["large_scale_inference_ErrorDetail"][]; - /** @description Human-readable error message */ - message: string; /** @description The error type identifier */ type: components["schemas"]["large_scale_inference_ErrorType"]; + /** @description Human-readable error message */ + message: string; + /** @description Array of detailed error information when applicable */ + details: components["schemas"]["large_scale_inference_ErrorDetail"][]; }; - large_scale_inference_SpecificPrice: { - /** Format: double */ - cents_per_million_input_tokens: number; - /** Format: double */ - cents_per_million_output_tokens: number; - }; - /** @description Quote details with side-specific fields + /** + * @description Quote details with side-specific fields * * The response structure differs based on order side: * - Buy orders include `instance_type` - * - Sell orders include `contract_id` */ - quoter_ApiQuoteDetails: - | { - /** @description End time: ISO 8601 */ - end_at: components["schemas"]["quoter_NowOrISO8601DateTime"]; - /** @description Instance type being quoted */ - instance_type: string; - /** - * Format: u-int64 - * @description Total price in cents (USD) - */ - price: number; - /** - * Format: u-int64 - * @description Number of nodes - */ - quantity: number; - /** @description Start time: ISO 8601 or "NOW" */ - start_at: components["schemas"]["quoter_NowOrISO8601DateTime"]; - zone: string; - } - | { - /** @description Contract being sold from */ - contract_id: components["schemas"]["quoter_ContractId"]; - /** @description End time: ISO 8601 */ - end_at: components["schemas"]["quoter_NowOrISO8601DateTime"]; - /** - * Format: u-int64 - * @description Total price in cents (USD) - */ - price: number; - /** - * Format: u-int64 - * @description Number of nodes - */ - quantity: number; - /** @description Start time: ISO 8601 or "NOW" */ - start_at: components["schemas"]["quoter_NowOrISO8601DateTime"]; - }; - /** @description Response format for GET /v0/quote + * - Sell orders include `contract_id` + */ + quoter_ApiQuoteDetails: { + /** + * Format: u-int64 + * @description Total price in cents (USD) + */ + price: number; + /** + * Format: u-int64 + * @description Number of nodes + */ + quantity: number; + /** @description Start time: ISO 8601 or "NOW" */ + start_at: components["schemas"]["quoter_NowOrISO8601DateTime"]; + /** @description End time: ISO 8601 */ + end_at: components["schemas"]["quoter_NowOrISO8601DateTime"]; + /** @description Instance type being quoted */ + instance_type: string; + zone: string; + }; + /** + * @description Response format for GET /v0/quote * * Returns a quote object with side-specific details. - * If no quote is available, the `quote` field will be `None`. */ + * If no quote is available, the `quote` field will be `None`. + */ quoter_ApiQuoteResponse: { /** @description Always "quote" */ object: string; - quote?: null | components["schemas"]["quoter_ApiQuoteDetails"]; /** @description Matches the requested side: "buy" or "sell" */ side: string; + quote?: null | components["schemas"]["quoter_ApiQuoteDetails"]; + no_quote_reason?: null | components["schemas"]["quoter_NoQuoteReason"]; }; - /** @description string with format '"cont"_{base62_encoded_id}' used for referencing a ContractId resource. Never user-generated. */ + /** + * @description Unique identifier with prefix 'cont_' that references a resource. + * @example cont_k3R-nX9vLm7Qp2Yw5Jd8F + */ quoter_ContractId: string; /** @enum {string} */ quoter_ErrorType: @@ -3157,31 +4372,26 @@ export interface components { | "not_implemented" | "upgrade_required" | "payment_required" - | "service_unavailable"; + | "service_unavailable" + | "unprocessable_entity"; + /** + * @description Reason why a quote could not be provided. + * @enum {string} + */ + quoter_NoQuoteReason: + | "no_matching_clusters" + | "no_availability" + | "bid_price_too_low" + | "ask_price_too_high" + | "internal_solver_error"; /** * @description A date/time value that can be either "NOW" or an ISO 8601 datetime string * @example NOW * @example 2025-07-11T20:41:37.423Z */ quoter_NowOrISO8601DateTime: string; - /** @description Side-specific parameters for quote requests */ - quoter_OrderSideParams: - | { - /** @description Cluster constraint (optional) - hostname to resolve to cluster_id */ - cluster?: string | null; - colocate_with?: null | components["schemas"]["quoter_ContractId"]; - /** @description Instance type for buy orders: "h100i", "h100v", or "h200ki" */ - instance_type?: string | null; - /** @enum {string} */ - side: "buy"; - } - | { - /** @description Contract ID for sell orders (must be owned by user) */ - contract_id: components["schemas"]["quoter_ContractId"]; - /** @enum {string} */ - side: "sell"; - }; - /** @description Query parameters for GET /v0/quote + /** + * @description Query parameters for GET /v0/quote * * # Validation Rules * @@ -3214,38 +4424,44 @@ export interface components { * * ### Sell Orders * - **Required**: `contract_id` (must be owned by authenticated user) - * - **Forbidden**: `instance_type`, `cluster`, `colocate_with` */ - quoter_QuoteRequestParams: components["schemas"]["quoter_OrderSideParams"] & - components["schemas"]["quoter_SpatialQuoteParams"]; - /** @description Spatial parameters for quote requests (time, quantity, duration) */ - quoter_SpatialQuoteParams: { + * - **Forbidden**: `instance_type`, `cluster`, `colocate_with` + */ + quoter_QuoteRequestParams: { + side: components["schemas"]["quoter_Side"]; + /** @description Instance type for buy orders: "h100i", "h100v", or "h200ki" */ + instance_type?: string | null; + colocate_with?: null | components["schemas"]["quoter_ContractId"]; + /** @description Cluster constraint (optional) - hostname to resolve to cluster_id */ + cluster?: string | null; + min_start_date?: + | null + | components["schemas"]["quoter_NowOrISO8601DateTime"]; + max_start_date?: + | null + | components["schemas"]["quoter_NowOrISO8601DateTime"]; /** * Format: u-int64 - * @description Exact duration in seconds (mutually exclusive with min_duration/max_duration) + * @description Number of nodes (1-1024) */ - duration?: number | null; + quantity: number; /** * Format: u-int64 - * @description Maximum duration in seconds (must be used with min_duration) + * @description Exact duration in seconds (mutually exclusive with min_duration/max_duration) */ - max_duration?: number | null; - max_start_date?: - | null - | components["schemas"]["quoter_NowOrISO8601DateTime"]; + duration?: number | null; /** * Format: u-int64 * @description Minimum duration in seconds (must be used with max_duration) */ min_duration?: number | null; - min_start_date?: - | null - | components["schemas"]["quoter_NowOrISO8601DateTime"]; /** * Format: u-int64 - * @description Number of nodes (1-1024) + * @description Maximum duration in seconds (must be used with min_duration) */ - quantity: number; + max_duration?: number | null; }; + /** @enum {string} */ + quoter_Side: "sell" | "buy"; }; responses: never; parameters: never; @@ -3501,7 +4717,7 @@ export interface operations { }; }; }; - list_images: { + list_vms_images: { parameters: { query?: never; header?: never; @@ -3541,6 +4757,7 @@ export interface operations { }; }; responses: { + /** @description Image upload started successfully */ 200: { headers: { [name: string]: unknown; @@ -3745,812 +4962,470 @@ export interface operations { }; }; }; - list_zones_handler: { + list_images_v2: { parameters: { - query?: never; + query?: { + /** @description Maximum number of results to return (1-200, default 50). */ + limit?: number; + /** @description Cursor for forward pagination (from a previous response's `cursor` field). */ + starting_after?: components["schemas"]["vmorch_ImagesCursor"]; + /** @description Cursor for backward pagination. */ + ending_before?: components["schemas"]["vmorch_ImagesCursor"]; + }; header?: never; path?: never; cookie?: never; }; requestBody?: never; responses: { - /** @description List of zones */ + /** @description List of images */ 200: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["node-api_ListResponse_ZoneInfo"]; - }; - }; - /** @description Unauthorized request */ - 401: { - headers: { - [name: string]: unknown; - }; - content: { - /** @example { - * "error": { - * "type": "authentication_error", - * "message": "Unauthorized: missing or invalid authentication token", - * "request_id": "req_1234567890" - * } - * } */ - "application/json": components["schemas"]["node-api_ErrorObject"]; + "application/json": components["schemas"]["vmorch_ListImagesResponse"]; }; }; - /** @description Internal server error */ - 500: { + /** @description Features not enabled */ + 403: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "api_error", - * "message": "Internal server error", - * "request_id": "req_1234567890" - * } - * } */ - "application/json": components["schemas"]["node-api_ErrorObject"]; + "application/json": components["schemas"]["vmorch_SerdeErrorProxy"]; }; }; }; }; - get_zone_handler: { + start_upload: { parameters: { query?: never; header?: never; - path: { - /** @description Zone ID */ - id: string; - }; + path?: never; cookie?: never; }; - requestBody?: never; + requestBody: { + content: { + "application/json": components["schemas"]["vmorch_StartUploadRequest"]; + }; + }; responses: { - /** @description Zone information */ - 200: { + 201: { headers: { [name: string]: unknown; }; content: { - "application/json": components["schemas"]["node-api_ZoneInfo"]; + "application/json": components["schemas"]["vmorch_ImageResponse"]; + }; + }; + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["vmorch_SerdeErrorProxy"]; }; }; - /** @description Unauthorized request */ 401: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "authentication_error", - * "message": "Unauthorized: missing or invalid authentication token", - * "request_id": "req_1234567890" - * } - * } */ - "application/json": components["schemas"]["node-api_ErrorObject"]; + "application/json": components["schemas"]["vmorch_SerdeErrorProxy"]; }; }; - /** @description Forbidden */ 403: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "forbidden", - * "message": "You do not have permission to get zones" - * } - * } */ - "application/json": components["schemas"]["node-api_ErrorObject"]; + "application/json": components["schemas"]["vmorch_SerdeErrorProxy"]; }; }; - /** @description Zone not found */ - 404: { + 409: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "not_found", - * "message": "Zone not found", - * "request_id": "req_1234567890" - * } - * } */ - "application/json": components["schemas"]["node-api_ErrorObject"]; + "application/json": components["schemas"]["vmorch_SerdeErrorProxy"]; }; }; - /** @description Internal server error */ 500: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "api_error", - * "message": "Internal server error", - * "request_id": "req_1234567890" - * } - * } */ - "application/json": components["schemas"]["node-api_ErrorObject"]; + "application/json": components["schemas"]["vmorch_SerdeErrorProxy"]; }; }; }; }; - health_handler: { + get_image: { parameters: { query?: never; header?: never; - path?: never; + path: { + id: string; + }; cookie?: never; }; requestBody?: never; responses: { - /** @description Health check successful */ 200: { headers: { [name: string]: unknown; }; content: { - /** @example OK */ - "text/plain": string; + "application/json": components["schemas"]["vmorch_ImageResponse"]; }; }; - /** @description Health check failed */ - 500: { + 401: { headers: { [name: string]: unknown; }; content: { - /** @example Internal Server Error */ - "text/plain": string; + "application/json": components["schemas"]["vmorch_SerdeErrorProxy"]; + }; + }; + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["vmorch_SerdeErrorProxy"]; }; }; }; }; - list_nodes_handler: { + complete_upload: { parameters: { - query?: { - /** @description Filter nodes by node_id - * Use ?id=n_b1dc52505c6db142&id=n_b1dc52505c6db133 to specify multiple IDs. - * Cannot be used with name */ - id?: string[]; - /** - * @description Filter nodes by their names - * Use ?name=val1&name=val2 to specify multiple names. - * Cannot be used with id - * @example [ - * "cuda-crunch" - * ] - */ - name?: string[]; - }; + query?: never; header?: never; - path?: never; + path: { + id: string; + }; cookie?: never; }; - requestBody?: never; + requestBody: { + content: { + "application/json": components["schemas"]["vmorch_CompleteUploadRequest"]; + }; + }; responses: { - /** @description List of nodes */ 200: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "object": "list", - * "data": [ - * { - * "object": "node", - * "id": "n_b1dc52505c6db142", - * "name": "cuda-crunch", - * "zone": "hayesvalley", - * "gpu_type": "H100", - * "owner": "sfcompute", - * "status": "running", - * "created_at": 1640995200, - * "updated_at": 1640995200, - * "start_at": 1640995200, - * "procurement_id": "proc_b1dc52505c6de142", - * "max_price_per_node_hour": 1000, - * "node_type": "autoreserved", - * "vms": { - * "object": "list", - * "data": [ - * { - * "object": "vm", - * "id": "vm_myOZZXw4pfcp7H9DQOldd", - * "status": "running", - * "created_at": 1640995200, - * "updated_at": 1640995200, - * "start_at": 1640995200, - * "end_at": 1641007200 - * } - * ] - * } - * } - * ] - * } */ - "application/json": components["schemas"]["node-api_ListResponse_Node"]; + "application/json": components["schemas"]["vmorch_CompleteUploadResponse"]; }; }; - /** @description Bad request */ 400: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "invalid_request_error", - * "message": "Invalid query parameters", - * "details": [ - * { - * "field": "node_id|name", - * "code": "invalid_value", - * "message": "Cannot specify both node_id and name parameters" - * } - * ] - * } - * } */ - "application/json": components["schemas"]["node-api_ErrorObject"]; + "application/json": components["schemas"]["vmorch_SerdeErrorProxy"]; }; }; - /** @description Unauthorized request */ 401: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "authentication_error", - * "message": "Unauthorized: missing or invalid authentication token" - * } - * } */ - "application/json": components["schemas"]["node-api_ErrorObject"]; + "application/json": components["schemas"]["vmorch_SerdeErrorProxy"]; }; }; - /** @description Forbidden */ 403: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "forbidden", - * "message": "You do not have permission to list nodes" - * } - * } */ - "application/json": components["schemas"]["node-api_ErrorObject"]; + "application/json": components["schemas"]["vmorch_SerdeErrorProxy"]; + }; + }; + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["vmorch_SerdeErrorProxy"]; }; }; - /** @description Internal server error */ 500: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "api_error", - * "message": "Internal server error" - * } - * } */ - "application/json": components["schemas"]["node-api_ErrorObject"]; + "application/json": components["schemas"]["vmorch_SerdeErrorProxy"]; }; }; }; }; - create_nodes_handler: { + download_image_v2: { parameters: { query?: never; header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": components["schemas"]["node-api_CreateNodesRequest"]; + path: { + id: string; }; + cookie?: never; }; + requestBody?: never; responses: { - /** @description Nodes created successfully */ - 201: { + 200: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "object": "list", - * "data": [ - * { - * "object": "node", - * "id": "n_b1dc52505c6db142", - * "name": "cuda-crunch", - * "zone": "hayesvalley", - * "gpu_type": "H100", - * "owner": "sfcompute", - * "status": "running", - * "created_at": 1640995200, - * "updated_at": 1640995200, - * "start_at": 1640995200, - * "procurement_id": "proc_b1dc52505c6de142", - * "max_price_per_node_hour": 1000, - * "node_type": "autoreserved" - * } - * ] - * } */ - "application/json": components["schemas"]["node-api_ListResponse_Node"]; + "application/json": components["schemas"]["vmorch_ImageDownloadResponse"]; }; }; - /** @description Bad request */ - 400: { + 401: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "invalid_request_error", - * "message": "One or more fields are invalid", - * "details": [ - * { - * "field": "start_at", - * "code": "invalid_value", - * "message": "start_at time must be in the future" - * }, - * { - * "field": "names", - * "code": "invalid_value", - * "message": "node name 'vm_test' cannot follow the vm_id pattern vm_{16_hex_chars} as this prefix is reserved for system-generated IDs" - * }, - * { - * "field": "names", - * "code": "invalid_value", - * "message": "node name cannot be a numeric string" - * } - * ] - * } - * } */ - "application/json": components["schemas"]["node-api_ErrorObject"]; + "application/json": components["schemas"]["vmorch_SerdeErrorProxy"]; }; }; - /** @description Unauthorized request */ - 401: { + 404: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "authentication_error", - * "message": "Unauthorized: missing or invalid authentication token" - * } - * } */ - "application/json": components["schemas"]["node-api_ErrorObject"]; + "application/json": components["schemas"]["vmorch_SerdeErrorProxy"]; }; }; - /** @description Forbidden */ - 403: { + 409: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "forbidden", - * "message": "You do not have permission to create nodes" - * } - * } */ - "application/json": components["schemas"]["node-api_ErrorObject"]; + "application/json": components["schemas"]["vmorch_SerdeErrorProxy"]; }; }; - /** @description Internal server error */ 500: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "api_error", - * "message": "Internal server error" - * } - * } */ - "application/json": components["schemas"]["node-api_ErrorObject"]; + "application/json": components["schemas"]["vmorch_SerdeErrorProxy"]; }; }; }; }; - get_node_handler: { + upload_part: { parameters: { query?: never; header?: never; path: { - /** @description Node ID or name */ id: string; }; cookie?: never; }; - requestBody?: never; + requestBody: { + content: { + "application/json": components["schemas"]["vmorch_UploadPartRequest"]; + }; + }; responses: { - /** @description Node details */ 200: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "object": "node", - * "id": "n_b1dc52505c6db142", - * "name": "cuda-crunch", - * "zone": "hayesvalley", - * "gpu_type": "H100", - * "owner": "sfcompute", - * "status": "running", - * "created_at": 1640995200, - * "updated_at": 1640995200, - * "start_at": 1640995200, - * "procurement_id": "proc_b1dc52505c6de142", - * "max_price_per_node_hour": 1000, - * "node_type": "autoreserved", - * "vms": { - * "object": "list", - * "data": [ - * { - * "object": "vm", - * "id": "vm_myOZZXw4pfcp7H9DQOldd", - * "status": "running", - * "created_at": 1640995200, - * "updated_at": 1640995200, - * "start_at": 1640995200, - * "end_at": 1641007200 - * } - * ] - * } - * } */ - "application/json": components["schemas"]["node-api_Node"]; + "application/json": components["schemas"]["vmorch_UploadPartResponse"]; }; }; - /** @description Bad request */ 400: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "invalid_request_error", - * "message": "Invalid node identifier", - * "details": [ - * { - * "field": "id", - * "code": "invalid_value", - * "message": "Numeric strings are not supported as node identifiers" - * } - * ] - * } - * } */ - "application/json": components["schemas"]["node-api_ErrorObject"]; + "application/json": components["schemas"]["vmorch_SerdeErrorProxy"]; }; }; - /** @description Unauthorized request */ 401: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "authentication_error", - * "message": "Unauthorized: missing or invalid authentication token" - * } - * } */ - "application/json": components["schemas"]["node-api_ErrorObject"]; + "application/json": components["schemas"]["vmorch_SerdeErrorProxy"]; }; }; - /** @description Forbidden */ 403: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "forbidden", - * "message": "You do not have permission to access this node" - * } - * } */ - "application/json": components["schemas"]["node-api_ErrorObject"]; + "application/json": components["schemas"]["vmorch_SerdeErrorProxy"]; }; }; - /** @description Node not found */ 404: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "not_found", - * "message": "Node not found" - * } - * } */ - "application/json": components["schemas"]["node-api_ErrorObject"]; + "application/json": components["schemas"]["vmorch_SerdeErrorProxy"]; }; }; - /** @description Internal server error */ 500: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "api_error", - * "message": "Internal server error" - * } - * } */ - "application/json": components["schemas"]["node-api_ErrorObject"]; + "application/json": components["schemas"]["vmorch_SerdeErrorProxy"]; }; }; }; }; - extend_node_handler: { + list_nodes: { parameters: { - query?: never; - header?: never; - path: { - /** @description Node ID or name */ - id: string; + query?: { + /** @description Filter by node ID (can be repeated, e.g. `?id=&id=`). */ + id?: components["schemas"]["vmorch_NodeId"][]; + capacity?: components["schemas"]["vmorch_CapacityId"]; + /** @description Filter by node status. When not specified, destroyed nodes are excluded. */ + status?: components["schemas"]["vmorch_NodeStatus"][]; + /** @description Maximum number of results to return (1–200, default 50). */ + limit?: number; + /** @description Cursor for forward pagination (from a previous response's `cursor` field). */ + starting_after?: components["schemas"]["vmorch_NodesCursor"]; + /** @description Cursor for backward pagination. */ + ending_before?: components["schemas"]["vmorch_NodesCursor"]; }; + header?: never; + path?: never; cookie?: never; }; - requestBody: { - content: { - "application/json": components["schemas"]["node-api_ExtendNodeRequest"]; - }; - }; + requestBody?: never; responses: { - /** @description Node extended successfully */ + /** @description List of nodes */ 200: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "object": "node", - * "id": "n_b1dc52505c6db142", - * "name": "cuda-crunch", - * "zone": "hayesvalley", - * "gpu_type": "H100", - * "owner": "sfcompute", - * "status": "running", - * "created_at": 1640995200, - * "updated_at": 1640995200, - * "start_at": 1640995200, - * "end_at": 1641007200, - * "max_price_per_node_hour": 1000, - * "node_type": "reserved", - * "vms": { - * "object": "list", - * "data": [ - * { - * "object": "vm", - * "id": "vm_myOZZXw4pfcp7H9DQOldd", - * "status": "running", - * "created_at": 1640995200, - * "updated_at": 1640995200, - * "start_at": 1640995200, - * "end_at": 1641007200 - * } - * ] - * } - * } */ - "application/json": components["schemas"]["node-api_Node"]; + "application/json": components["schemas"]["vmorch_ListNodesResponse"]; }; }; - /** @description Bad request */ + /** @description Invalid request */ 400: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "invalid_request_error", - * "message": "Node is Auto Reserved not Reserved - only reservation nodes can be extended", - * "details": [ - * { - * "field": "duration_seconds", - * "code": "invalid_value", - * "message": "duration must be at least 1 hour (3600 seconds)" - * } - * ] - * } - * } */ - "application/json": components["schemas"]["node-api_ErrorObject"]; + "application/json": components["schemas"]["vmorch_SerdeErrorProxy"]; }; }; - /** @description Unauthorized request */ + /** @description Unauthorized */ 401: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "authentication_error", - * "message": "Unauthorized: missing or invalid authentication token" - * } - * } */ - "application/json": components["schemas"]["node-api_ErrorObject"]; + "application/json": components["schemas"]["vmorch_SerdeErrorProxy"]; }; }; - /** @description Forbidden */ - 403: { - headers: { - [name: string]: unknown; - }; - content: { - /** @example { - * "error": { - * "type": "forbidden", - * "message": "Account is frozen or node is not associated with this account" - * } - * } */ - "application/json": components["schemas"]["node-api_ErrorObject"]; - }; + }; + }; + get_node: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Node ID */ + id: components["schemas"]["vmorch_NodeId"]; }; - /** @description Node not found */ - 404: { + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Node details */ + 200: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "not_found", - * "message": "Node not found" - * } - * } */ - "application/json": components["schemas"]["node-api_ErrorObject"]; + "application/json": components["schemas"]["vmorch_NodeResponse"]; }; }; - /** @description Extension failed due to capacity */ - 422: { + /** @description Unauthorized */ + 401: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "invalid_request_error", - * "message": "Extension failed: No capacity available for the requested time period" - * } - * } */ - "application/json": components["schemas"]["node-api_ErrorObject"]; + "application/json": components["schemas"]["vmorch_SerdeErrorProxy"]; }; }; - /** @description Internal server error */ - 500: { + /** @description Node not found */ + 404: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "api_error", - * "message": "Internal server error" - * } - * } */ - "application/json": components["schemas"]["node-api_ErrorObject"]; + "application/json": components["schemas"]["vmorch_SerdeErrorProxy"]; }; }; }; }; - release_node_handler: { + get_node_logs: { parameters: { - query?: never; + query?: { + /** @description Return logs with seqnum <= this value. */ + before_seqnum?: number; + /** @description Return logs with seqnum >= this value. */ + since_seqnum?: number; + /** + * @description Return logs before this unix timestamp (seconds). Due to clock synchronization, + * some earlier log messages may have a realtime timestamp after this value. + */ + before_realtime_timestamp?: components["schemas"]["vmorch_UnixEpoch"]; + /** + * @description Return logs after this unix timestamp (seconds). Due to clock synchronization, + * some later log messages may have a realtime timestamp before this value. + */ + since_realtime_timestamp?: components["schemas"]["vmorch_UnixEpoch"]; + sort_by?: "seqnum" | "-seqnum"; + limit?: number; + }; header?: never; path: { - /** @description Node ID or name */ - id: string; + /** @description Node ID */ + id: components["schemas"]["vmorch_NodeId"]; }; cookie?: never; }; requestBody?: never; responses: { - /** @description Node released successfully */ + /** @description Log chunks */ 200: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "object": "node", - * "id": "n_b1dc52505c6db142", - * "name": "cuda-crunch", - * "zone": "hayesvalley", - * "gpu_type": "H100", - * "owner": "sfcompute", - * "status": "terminated", - * "created_at": 1640995200, - * "updated_at": 1640995200, - * "start_at": 1640995200, - * "end_at": 1641000000, - * "max_price_per_node_hour": 1000, - * "node_type": "autoreserved", - * "procurement_id": "proc_b1dc52505c6de142", - * "vms": { - * "object": "list", - * "data": [ - * { - * "object": "vm", - * "id": "vm_myOZZXw4pfcp7H9DQOldd", - * "status": "running", - * "created_at": 1640995200, - * "updated_at": 1640995200, - * "start_at": 1640995200, - * "end_at": 1641007200 - * } - * ] - * } - * } */ - "application/json": components["schemas"]["node-api_Node"]; + "application/json": components["schemas"]["vmorch_NodeLogsResponse"]; }; }; - /** @description Bad request */ + /** @description Invalid request */ 400: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "invalid_request_error", - * "message": "Node is Reserved not Auto Reserved - only autoreserved nodes can be released" - * } - * } */ - "application/json": components["schemas"]["node-api_ErrorObject"]; + "application/json": components["schemas"]["vmorch_SerdeErrorProxy"]; }; }; - /** @description Unauthorized request */ + /** @description Unauthorized */ 401: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "authentication_error", - * "message": "Unauthorized: missing or invalid authentication token" - * } - * } */ - "application/json": components["schemas"]["node-api_ErrorObject"]; - }; - }; - /** @description Forbidden */ - 403: { - headers: { - [name: string]: unknown; - }; - content: { - /** @example { - * "error": { - * "type": "forbidden", - * "message": "Account is frozen or node is not associated with this account" - * } - * } */ - "application/json": components["schemas"]["node-api_ErrorObject"]; + "application/json": components["schemas"]["vmorch_SerdeErrorProxy"]; }; }; /** @description Node not found */ @@ -4559,175 +5434,903 @@ export interface operations { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "not_found", - * "message": "Node not found" - * } - * } */ - "application/json": components["schemas"]["node-api_ErrorObject"]; - }; - }; - /** @description Internal server error */ - 500: { - headers: { - [name: string]: unknown; - }; - content: { - /** @example { - * "error": { - * "type": "api_error", - * "message": "Internal server error" - * } - * } */ - "application/json": components["schemas"]["node-api_ErrorObject"]; + "application/json": components["schemas"]["vmorch_SerdeErrorProxy"]; }; }; }; }; - listClusters: { + replace_node: { parameters: { query?: never; header?: never; - path?: never; + path: { + /** @description Node ID */ + id: components["schemas"]["vmorch_NodeId"]; + }; cookie?: never; }; - requestBody?: never; + requestBody: { + content: { + "application/json": components["schemas"]["vmorch_ReplaceNodeRequest"]; + }; + }; responses: { - /** @description List of Kubernetes clusters */ + /** @description Replacement node */ 200: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "object": "list", - * "data": [ - * { - * "object": "kubernetes_cluster", - * "name": "starlight", - * "kubernetes_namespace": "sf-user123", - * "kubernetes_api_url": "https://starlight.sf-k8s.com", - * "kubernetes_ca_cert": "-----BEGIN CERTIFICATE-----...", - * "contract": { - * "object": "contract", - * "status": "active", - * "id": "cont_xyz123", - * "created_at": "2024-07-15T22:30:17.426Z", - * "instance_type": "h100i", - * "shape": { - * "intervals": [ - * "2024-07-16T00:00:00Z", - * "2024-07-17T00:00:00Z" - * ], - * "quantities": [ - * 4, - * 0 - * ] - * }, - * "colocate_with": [], - * "cluster_id": "clstr_abc456", - * "state": "Active" - * } - * } - * ], - * "has_more": false - * } */ - "application/json": components["schemas"]["market-api_ListClustersResponse"]; + "application/json": components["schemas"]["vmorch_NodeResponse"]; }; }; - /** @description Unauthorized - missing or invalid authentication token */ + /** @description Unauthorized */ 401: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "authentication_error", - * "message": "missing authentication token" - * } - * } */ - "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + "application/json": components["schemas"]["vmorch_SerdeErrorProxy"]; }; }; - /** @description Forbidden - account frozen */ + /** @description Feature not enabled */ 403: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "forbidden", - * "message": "Account is frozen" - * } - * } */ - "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + "application/json": components["schemas"]["vmorch_SerdeErrorProxy"]; }; }; - /** @description Internal server error */ - 500: { + /** @description Node not found */ + 404: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "api_error", - * "message": "An internal server error occurred" - * } - * } */ - "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + "application/json": components["schemas"]["vmorch_SerdeErrorProxy"]; }; }; }; }; - listContracts: { + get_node_ssh: { parameters: { - query?: { - /** - * @description Filter by instance type - * @example h100i - */ - instance_type?: components["schemas"]["market-api_Ticker"]; - /** - * @description Start of interval to find active contracts. Must be used with active_within_interval_end - * @example 2024-01-01T00:00:00Z - */ - active_within_interval_start?: components["schemas"]["market-api_ISO8601DateTime"]; - /** - * @description End of interval to find active contracts. Must be used with active_within_interval_start - * @example 2024-01-02T00:00:00Z - */ - active_within_interval_end?: components["schemas"]["market-api_ISO8601DateTime"]; - /** - * @description Filter by contract state. Options: "All", "Upcoming", "Active", "Expired". Default excludes expired contracts - * @example Active - */ - state?: string; - }; + query?: never; header?: never; - path?: never; + path: { + /** @description Node ID */ + id: components["schemas"]["vmorch_NodeId"]; + }; cookie?: never; }; requestBody?: never; responses: { - /** @description List of contracts */ + /** @description SSH connection details */ 200: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "object": "list", - * "data": [ - * { - * "object": "contract", - * "status": "active", - * "id": "cont_xyz789", - * "created_at": "2024-07-15T22:30:17.426Z", - * "instance_type": "h100i", + "application/json": components["schemas"]["vmorch_NodeSshInfo"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["vmorch_SerdeErrorProxy"]; + }; + }; + /** @description SSH details not available */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["vmorch_SerdeErrorProxy"]; + }; + }; + }; + }; + list_zones_handler: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description List of zones */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["node-api_ListResponse_ZoneInfo"]; + }; + }; + /** @description Unauthorized request */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["node-api_ErrorObject"]; + }; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["node-api_ErrorObject"]; + }; + }; + }; + }; + get_zone_handler: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Zone ID */ + id: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Zone information */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["node-api_ZoneInfo"]; + }; + }; + /** @description Unauthorized request */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["node-api_ErrorObject"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["node-api_ErrorObject"]; + }; + }; + /** @description Zone not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["node-api_ErrorObject"]; + }; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["node-api_ErrorObject"]; + }; + }; + }; + }; + health_handler: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Health check successful */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "text/plain": string; + }; + }; + /** @description Health check failed */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "text/plain": string; + }; + }; + }; + }; + list_nodes_handler: { + parameters: { + query?: { + /** + * @description Filter nodes by node_id + * Use ?id=n_b1dc52505c6db142&id=n_b1dc52505c6db133 to specify multiple IDs. + * Cannot combine with name or node_type + */ + id?: string[]; + /** + * @description Filter nodes by their names + * Use ?name=val1&name=val2 to specify multiple names. + * Cannot combine with id or node_type + */ + name?: string[]; + /** + * @description Filter nodes by their type + * Cannot combine with id or name + * @example autoreserved + */ + type?: components["schemas"]["node-api_NodeType"]; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description List of nodes */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["node-api_ListResponse_Node"]; + }; + }; + /** @description Bad request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["node-api_ErrorObject"]; + }; + }; + /** @description Unauthorized request */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["node-api_ErrorObject"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["node-api_ErrorObject"]; + }; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["node-api_ErrorObject"]; + }; + }; + }; + }; + create_nodes_handler: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["node-api_CreateNodesRequest"]; + }; + }; + responses: { + /** @description Nodes created successfully */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["node-api_ListResponse_Node"]; + }; + }; + /** @description Bad request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["node-api_ErrorObject"]; + }; + }; + /** @description Unauthorized request */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["node-api_ErrorObject"]; + }; + }; + /** @description Payment Required */ + 402: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["node-api_ErrorObject"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["node-api_ErrorObject"]; + }; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["node-api_ErrorObject"]; + }; + }; + }; + }; + get_node_handler: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Node ID or name */ + id: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Node details */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["node-api_Node"]; + }; + }; + /** @description Bad request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["node-api_ErrorObject"]; + }; + }; + /** @description Unauthorized request */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["node-api_ErrorObject"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["node-api_ErrorObject"]; + }; + }; + /** @description Node not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["node-api_ErrorObject"]; + }; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["node-api_ErrorObject"]; + }; + }; + }; + }; + delete_node_handler: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Node ID or name */ + id: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Node deleted successfully */ + 204: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Bad request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["node-api_ErrorObject"]; + }; + }; + /** @description Unauthorized request */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["node-api_ErrorObject"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["node-api_ErrorObject"]; + }; + }; + /** @description Node not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["node-api_ErrorObject"]; + }; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["node-api_ErrorObject"]; + }; + }; + }; + }; + extend_node_handler: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Node ID or name */ + id: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["node-api_ExtendNodeRequest"]; + }; + }; + responses: { + /** @description Node extended successfully */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["node-api_Node"]; + }; + }; + /** @description Bad request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["node-api_ErrorObject"]; + }; + }; + /** @description Unauthorized request */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["node-api_ErrorObject"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["node-api_ErrorObject"]; + }; + }; + /** @description Node not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["node-api_ErrorObject"]; + }; + }; + /** @description Extension failed due to capacity */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["node-api_ErrorObject"]; + }; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["node-api_ErrorObject"]; + }; + }; + }; + }; + redeploy_node_handler: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Node ID or name */ + id: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["node-api_RedeployNodeRequest"]; + }; + }; + responses: { + /** @description Node redeployed successfully */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["node-api_Node"]; + }; + }; + /** @description Bad request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["node-api_ErrorObject"]; + }; + }; + /** @description Unauthorized request */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["node-api_ErrorObject"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["node-api_ErrorObject"]; + }; + }; + /** @description Node not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["node-api_ErrorObject"]; + }; + }; + /** @description Redeploy failed due to invalid state */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["node-api_ErrorObject"]; + }; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["node-api_ErrorObject"]; + }; + }; + }; + }; + release_node_handler: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Node ID or name */ + id: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Node released successfully */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["node-api_Node"]; + }; + }; + /** @description Bad request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["node-api_ErrorObject"]; + }; + }; + /** @description Unauthorized request */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["node-api_ErrorObject"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["node-api_ErrorObject"]; + }; + }; + /** @description Node not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["node-api_ErrorObject"]; + }; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["node-api_ErrorObject"]; + }; + }; + }; + }; + listClusters: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description List of Kubernetes clusters */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "object": "list", + * "data": [ + * { + * "object": "kubernetes_cluster", + * "name": "starlight", + * "kubernetes_namespace": "sf-user123", + * "kubernetes_api_url": "https://starlight.sf-k8s.com", + * "kubernetes_ca_cert": "-----BEGIN CERTIFICATE-----...", + * "contract": { + * "object": "contract", + * "status": "active", + * "id": "cont_xyz123", + * "created_at": "2024-07-15T22:30:17.426Z", + * "instance_type": "h100i", + * "shape": { + * "intervals": [ + * "2024-07-16T00:00:00Z", + * "2024-07-17T00:00:00Z" + * ], + * "quantities": [ + * 4, + * 0 + * ] + * }, + * "colocate_with": [], + * "cluster_id": "clstr_abc456", + * "state": "Active", + * "is_node": false + * } + * } + * ], + * "has_more": false + * } + */ + "application/json": components["schemas"]["market-api_ListClustersResponse"]; + }; + }; + /** @description Unauthorized - missing or invalid authentication token */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "error": { + * "type": "authentication_error", + * "message": "missing authentication token" + * } + * } + */ + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + /** @description Forbidden - account frozen */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "error": { + * "type": "forbidden", + * "message": "Account is frozen" + * } + * } + */ + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "error": { + * "type": "api_error", + * "message": "An internal server error occurred" + * } + * } + */ + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + }; + }; + listContracts: { + parameters: { + query?: { + /** + * @description Filter by instance type + * @example h100i + */ + instance_type?: components["schemas"]["market-api_Ticker"]; + /** + * @description Start of interval to find active contracts. Must be used with active_within_interval_end + * @example 2024-01-01T00:00:00Z + */ + active_within_interval_start?: components["schemas"]["market-api_ISO8601DateTime"]; + /** + * @description End of interval to find active contracts. Must be used with active_within_interval_start + * @example 2024-01-02T00:00:00Z + */ + active_within_interval_end?: components["schemas"]["market-api_ISO8601DateTime"]; + /** + * @description Filter by contract state. Options: "All", "Upcoming", "Active", "Expired". Default excludes expired contracts + * @example Active + */ + state?: string; + /** + * @description Include contracts managed by the Nodes API + * @example true + */ + include_nodes?: boolean; + /** + * @description Include contracts associated with procurements + * @example true + */ + include_procurements?: boolean; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description List of contracts */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "object": "list", + * "data": [ + * { + * "object": "contract", + * "status": "active", + * "id": "cont_xyz789", + * "created_at": "2024-07-15T22:30:17.426Z", + * "instance_type": "h100i", * "shape": { * "intervals": [ * "2024-07-16T00:00:00Z", @@ -4738,56 +6341,1652 @@ export interface operations { * 0 * ] * }, - * "state": "Active" + * "state": "Active", + * "is_node": false, + * "procurement_id": "proc_1234567890abcdef" + * } + * ], + * "has_more": false + * } + */ + "application/json": components["schemas"]["market-api_ListContractsResponse"]; + }; + }; + /** @description Bad request - invalid query parameters */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "error": { + * "type": "invalid_request_error", + * "message": "must provide both active_within_interval_start and active_within_interval_end or none of them" + * } + * } + */ + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + /** @description Unauthorized - missing or invalid authentication token */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "error": { + * "type": "authentication_error", + * "message": "missing authentication token" + * } + * } + */ + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + /** @description Forbidden - account frozen */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "error": { + * "type": "forbidden", + * "message": "Account is frozen" + * } + * } + */ + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "error": { + * "type": "api_error", + * "message": "An internal server error occurred" + * } + * } + */ + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + }; + }; + getContract: { + parameters: { + query?: never; + header?: never; + path: { + /** + * @description Contract ID + * @example cont_xyz789 + */ + id: components["schemas"]["market-api_ContractId"]; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Contract details */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "object": "contract", + * "status": "active", + * "id": "cont_xyz789", + * "created_at": "2024-07-15T22:30:17.426Z", + * "instance_type": "h100i", + * "shape": { + * "intervals": [ + * "2024-07-16T22:30:16Z", + * "2024-07-17T22:30:16Z", + * "2024-07-18T22:30:16Z" + * ], + * "quantities": [ + * 10, + * 20, + * 0 + * ] + * }, + * "colocate_with": [ + * "cont_abc456" + * ], + * "cluster_id": "clus_xyz123", + * "state": "Active", + * "is_node": false, + * "procurement_id": "proc_1234567890abcdef" + * } + */ + "application/json": components["schemas"]["market-api_ContractResponse"]; + }; + }; + /** @description Unauthorized - missing or invalid authentication token */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "error": { + * "type": "authentication_error", + * "message": "missing authentication token" + * } + * } + */ + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + /** @description Forbidden - account frozen */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "error": { + * "type": "forbidden", + * "message": "Account is frozen" + * } + * } + */ + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + /** @description Contract not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "error": { + * "type": "not_found", + * "message": "Contract not found" + * } + * } + */ + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "error": { + * "type": "api_error", + * "message": "An internal server error occurred" + * } + * } + */ + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + }; + }; + listOrders: { + parameters: { + query?: { + /** @description Filter by order side (buy or sell) */ + side?: components["schemas"]["market-api_OrderSide"]; + /** @description Filter by instance type */ + instance_type?: components["schemas"]["market-api_Ticker"]; + /** @description Minimum price in cents */ + min_price?: number; + /** @description Maximum price in cents */ + max_price?: number; + /** @description Minimum start date */ + min_start_date?: components["schemas"]["market-api_ISO8601DateTime"]; + /** @description Maximum start date */ + max_start_date?: components["schemas"]["market-api_ISO8601DateTime"]; + /** @description Minimum duration in seconds */ + min_duration?: components["schemas"]["market-api_UnixEpoch"]; + /** @description Maximum duration in seconds */ + max_duration?: components["schemas"]["market-api_UnixEpoch"]; + /** @description Minimum quantity */ + min_quantity?: number; + /** @description Maximum quantity */ + max_quantity?: number; + /** @description Filter by contract ID */ + contract_id?: components["schemas"]["market-api_ContractId"]; + /** @description Show only open orders */ + only_open?: boolean; + /** @description Exclude filled orders */ + exclude_filled?: boolean; + /** @description Show only filled orders */ + only_filled?: boolean; + /** @description Minimum filled at date */ + min_filled_at?: components["schemas"]["market-api_ISO8601DateTime"]; + /** @description Maximum filled at date */ + max_filled_at?: components["schemas"]["market-api_ISO8601DateTime"]; + /** @description Minimum fill price in cents */ + min_fill_price?: number; + /** @description Maximum fill price in cents */ + max_fill_price?: number; + /** @description Exclude cancelled orders */ + exclude_cancelled?: boolean; + /** @description Show only cancelled orders */ + only_cancelled?: boolean; + /** @description Minimum cancelled at date */ + min_cancelled_at?: components["schemas"]["market-api_ISO8601DateTime"]; + /** @description Maximum cancelled at date */ + max_cancelled_at?: components["schemas"]["market-api_ISO8601DateTime"]; + /** @description Minimum placed at date */ + min_placed_at?: components["schemas"]["market-api_ISO8601DateTime"]; + /** @description Maximum placed at date */ + max_placed_at?: components["schemas"]["market-api_ISO8601DateTime"]; + /** @description Maximum number of results to return (default: 100, max: 100) */ + limit?: number; + /** @description Number of results to skip */ + offset?: number; + /** @description Sort field */ + sort_by?: components["schemas"]["market-api_SortBy"]; + /** @description Sort direction */ + sort_direction?: components["schemas"]["market-api_SortDirection"]; + include_public?: unknown; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description List of orders */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "object": "list", + * "data": [ + * { + * "object": "order", + * "id": "ordr_xyz123", + * "side": "buy", + * "instance_type": "h100i", + * "price": 1600, + * "quantity": 2, + * "status": "open", + * "created_at": "2024-07-15T22:30:17.426Z", + * "start_at": "2024-07-16T00:00:00Z", + * "end_at": "2024-07-17T00:00:00Z", + * "flags": { + * "ioc": false, + * "post_only": false, + * "market": false, + * "prorate": false + * } + * } + * ], + * "has_more": false + * } + */ + "application/json": components["schemas"]["market-api_ListOrdersResponse"]; + }; + }; + /** @description Invalid request parameters */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "error": { + * "type": "invalid_request_error", + * "message": "Cannot specify both 'only_filled' and 'only_cancelled'" + * } + * } + */ + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + /** @description Unauthorized - missing or invalid authentication token */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "error": { + * "type": "authentication_error", + * "message": "missing authentication token" + * } + * } + */ + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + /** @description Forbidden - account frozen */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "error": { + * "type": "forbidden", + * "message": "Account is frozen" + * } + * } + */ + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "error": { + * "type": "api_error", + * "message": "An internal server error occurred" + * } + * } + */ + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + }; + }; + createOrder: { + parameters: { + query?: never; + header?: { + /** @description Optional key to ensure idempotent order creation */ + "Idempotency-Key"?: string | null; + }; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["market-api_CreateOrderRequest"]; + }; + }; + responses: { + /** @description Order created successfully */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "object": "order", + * "status": "pending", + * "id": "order_xyz789", + * "idempotency_key": "key_123" + * } + */ + "application/json": components["schemas"]["market-api_CreateOrderResponse"]; + }; + }; + /** @description Invalid request parameters */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "type": "invalid_request_error", + * "message": "Start time must be within +/- 1 minute of now, on a future hour, or the string literal 'NOW'", + * "details": [] + * } + */ + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + /** @description Unauthorized - missing or invalid authentication token */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "type": "authentication_error", + * "message": "missing authentication token", + * "details": [] + * } + */ + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + /** @description Forbidden - account frozen, insufficient credits, unauthorized seller, or trading halted */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "type": "forbidden", + * "message": "Account is frozen", + * "details": [] + * } + */ + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + /** @description Not found - contract or cluster not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "type": "not_found", + * "message": "Contract not found", + * "details": [] + * } + */ + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + /** @description Upgrade required - legacy account needs migration */ + 426: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "type": "invalid_request_error", + * "message": "Legacy account must be upgraded before placing orders", + * "details": [] + * } + */ + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "type": "api_error", + * "message": "An internal server error occurred", + * "details": [] + * } + */ + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + }; + }; + getOrder: { + parameters: { + query?: never; + header?: never; + path: { + /** + * @description Order ID + * @example order_xyz789 + */ + id: components["schemas"]["market-api_OrderId"]; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Order details */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "object": "order", + * "id": "order_xyz789", + * "side": "buy", + * "status": "open", + * "instance_type": "h100i", + * "quantity": 4, + * "start_at": "2021-01-01T00:00:00Z", + * "end_at": "2021-01-01T01:00:00Z", + * "price": 2850000, + * "flags": { + * "market": false, + * "post_only": false, + * "ioc": false + * }, + * "executed": false, + * "cancelled": false, + * "colocate_with": [], + * "created_at": "2021-01-01T00:00:00Z", + * "rejected": false + * } + */ + "application/json": components["schemas"]["market-api_OrderResponse"]; + }; + }; + /** @description Unauthorized - missing or invalid authentication token */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "type": "authentication_error", + * "message": "missing authentication token", + * "details": [] + * } + */ + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + /** @description Forbidden - user not authorized to view this order */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "type": "forbidden", + * "message": "User not authorized to view this order", + * "details": [] + * } + */ + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + /** @description Order not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "type": "not_found", + * "message": "Order not found", + * "details": [] + * } + */ + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "type": "api_error", + * "message": "An internal server error occurred", + * "details": [] + * } + */ + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + }; + }; + cancelOrder: { + parameters: { + query?: never; + header?: never; + path: { + /** + * @description Order ID + * @example ordr_xyz789 + */ + id: components["schemas"]["market-api_OrderId"]; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Order cancelled successfully */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "object": "pending" + * } + */ + "application/json": components["schemas"]["market-api_CancelOrderResponse"]; + }; + }; + /** @description Order already cancelled */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "type": "validation_error", + * "message": "Order already cancelled", + * "details": [] + * } + */ + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + /** @description Order not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "type": "not_found", + * "message": "Order not found", + * "details": [] + * } + */ + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "type": "api_error", + * "message": "An internal server error occurred", + * "details": [] + * } + */ + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + }; + }; + getOrderClusters: { + parameters: { + query?: never; + header?: never; + path: { + /** + * @description Order ID + * @example ordr_W9TRG + */ + id: components["schemas"]["market-api_OrderId"]; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description List of clusters associated with the order */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "object": "list", + * "data": [ + * { + * "object": "kubernetes_cluster", + * "name": "starlight", + * "kubernetes_namespace": "sf-user123", + * "kubernetes_api_url": "https://starlight.sf-k8s.com", + * "kubernetes_ca_cert": "-----BEGIN CERTIFICATE-----...", + * "contract": { + * "object": "contract", + * "status": "active", + * "id": "cont_xyz123", + * "created_at": "2024-07-15T22:30:17.426Z", + * "instance_type": "h100i", + * "shape": { + * "intervals": [ + * "2024-07-16T00:00:00Z", + * "2024-07-17T00:00:00Z" + * ], + * "quantities": [ + * 4, + * 0 + * ] + * }, + * "colocate_with": [], + * "cluster_id": "clstr_abc456", + * "state": "Active", + * "is_node": false + * } + * } + * ], + * "has_more": false + * } + */ + "application/json": components["schemas"]["market-api_ListClustersResponse"]; + }; + }; + /** @description Unauthorized - missing or invalid authentication token */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "error": { + * "type": "authentication_error", + * "message": "missing authentication token" + * } + * } + */ + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + /** @description Forbidden - account frozen */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "error": { + * "type": "forbidden", + * "message": "Account is frozen" + * } + * } + */ + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + /** @description Order not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "error": { + * "type": "not_found", + * "message": "Order not found" + * } + * } + */ + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "error": { + * "type": "api_error", + * "message": "An internal server error occurred" + * } + * } + */ + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + }; + }; + listProcurements: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description List of procurements */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "object": "list", + * "data": [ + * { + * "object": "procurement", + * "id": "proc_test123", + * "status": "active", + * "instance_type": "h100i", + * "desired_quantity": 5, + * "buy_limit_price_per_gpu_hour": 250, + * "sell_limit_price_per_gpu_hour": 25, + * "horizon": 60, + * "colocation_strategy": "colocate_pinned", + * "actual_quantity": 5, + * "active_order_count": 2, + * "last_message": "Running" * } * ], * "has_more": false - * } */ - "application/json": components["schemas"]["market-api_ListContractsResponse"]; + * } + */ + "application/json": components["schemas"]["market-api_ListProcurementsResponse"]; + }; + }; + /** @description Unauthorized - missing or invalid authentication token */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "error": { + * "type": "authentication_error", + * "message": "missing authentication token" + * } + * } + */ + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + /** @description Forbidden - account frozen */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "error": { + * "type": "forbidden", + * "message": "Account is frozen" + * } + * } + */ + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "error": { + * "type": "api_error", + * "message": "An internal server error occurred" + * } + * } + */ + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + }; + }; + createProcurement: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["market-api_CreateProcurementRequest"]; + }; + }; + responses: { + /** @description Successfully created procurement */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "object": "procurement", + * "id": "proc_xyz123", + * "status": "active", + * "instance_type": "h100i", + * "desired_quantity": 5, + * "buy_limit_price_per_gpu_hour": 250, + * "sell_limit_price_per_gpu_hour": 25, + * "horizon": 60, + * "colocation_strategy": "colocate_pinned", + * "actual_quantity": 0, + * "active_order_count": 0 + * } + */ + "application/json": components["schemas"]["market-api_ProcurementResponse"]; + }; + }; + /** @description Bad request - invalid field values */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "error": { + * "type": "invalid_request_error", + * "message": "desired_quantity must be non-negative" + * } + * } + */ + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + /** @description Unauthorized - missing or invalid authentication token */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "error": { + * "type": "authentication_error", + * "message": "missing authentication token" + * } + * } + */ + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + /** @description Payment required - insufficient funds */ + 402: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "error": { + * "type": "payment_required", + * "message": "insufficient funds" + * } + * } + */ + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + /** @description Forbidden - account frozen */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "error": { + * "type": "forbidden", + * "message": "Account is frozen" + * } + * } + */ + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + /** @description Not found - cluster not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "error": { + * "type": "not_found", + * "message": "cluster starlight not found" + * } + * } + */ + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "error": { + * "type": "api_error", + * "message": "An internal server error occurred" + * } + * } + */ + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + }; + }; + getProcurement: { + parameters: { + query?: never; + header?: never; + path: { + /** + * @description Procurement ID + * @example proc_xyz123 + */ + id: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Procurement details */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "object": "procurement", + * "id": "proc_xyz123", + * "status": "active", + * "instance_type": "h100i", + * "desired_quantity": 5, + * "buy_limit_price_per_gpu_hour": 250, + * "sell_limit_price_per_gpu_hour": 25, + * "horizon": 60, + * "colocation_strategy": "colocate_pinned", + * "actual_quantity": 5, + * "active_order_count": 2, + * "last_message": "Running" + * } + */ + "application/json": components["schemas"]["market-api_ProcurementResponse"]; + }; + }; + /** @description Unauthorized - missing or invalid authentication token */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "error": { + * "type": "authentication_error", + * "message": "missing authentication token" + * } + * } + */ + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + /** @description Forbidden - account frozen */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "error": { + * "type": "forbidden", + * "message": "Account is frozen" + * } + * } + */ + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + /** @description Procurement not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "error": { + * "type": "not_found", + * "message": "Procurement proc_xyz123 not found" + * } + * } + */ + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "error": { + * "type": "api_error", + * "message": "An internal server error occurred" + * } + * } + */ + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + }; + }; + updateProcurement: { + parameters: { + query?: never; + header?: never; + path: { + /** + * @description Procurement ID + * @example proc_xyz123 + */ + id: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["market-api_UpdateProcurementRequest"]; + }; + }; + responses: { + /** @description Successfully updated procurement */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "object": "procurement", + * "id": "proc_xyz123", + * "status": "disabled", + * "instance_type": "h100i", + * "desired_quantity": 5, + * "buy_limit_price_per_gpu_hour": 400, + * "sell_limit_price_per_gpu_hour": 100, + * "horizon": 120, + * "colocation_strategy": "colocate_pinned", + * "actual_quantity": 3, + * "active_order_count": 1 + * } + */ + "application/json": components["schemas"]["market-api_ProcurementResponse"]; + }; + }; + /** @description Bad request - invalid field values */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "error": { + * "type": "invalid_request_error", + * "message": "desired_quantity must be non-negative" + * } + * } + */ + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + /** @description Unauthorized - missing or invalid authentication token */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "error": { + * "type": "authentication_error", + * "message": "missing authentication token" + * } + * } + */ + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + /** @description Payment required - insufficient funds */ + 402: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "error": { + * "type": "payment_required", + * "message": "insufficient funds" + * } + * } + */ + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + /** @description Forbidden - account frozen */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "error": { + * "type": "forbidden", + * "message": "Account is frozen" + * } + * } + */ + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + /** @description Procurement not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "error": { + * "type": "not_found", + * "message": "procurement proc_xyz123 not found" + * } + * } + */ + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "error": { + * "type": "api_error", + * "message": "An internal server error occurred" + * } + * } + */ + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + }; + }; + getAccountMe: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Account information retrieved successfully */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "id": "gmail-com-name", + * "role": "user", + * "is_frozen": false, + * "kyc": "basic", + * "submitted_waitlist": true, + * "waitlist": false, + * "kycb_form_submitted": false, + * "created_at": "2024-01-15T10:30:00Z" + * } + */ + "application/json": components["schemas"]["market-api_AccountMeResponse"]; + }; + }; + /** @description Unauthorized - missing or invalid authentication token */ + 401: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Account not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "error": { + * "type": "not_found", + * "message": "account not found", + * "details": [], + * "request_id": "req_550e8400-e29b-41d4-a716-446655440000" + * } + * } + */ + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + }; + }; + getBalance: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Successfully retrieved balance */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "object": "balance", + * "available_cents": 150000, + * "current_cents": 180000, + * "current_overage_cents": 150000, + * "current_hold_cents": 180000, + * "updated_at": 1640995200 + * } + */ + "application/json": components["schemas"]["market-api_GetBalanceResponse"]; + }; + }; + /** @description Unauthorized - missing or invalid authentication token */ + 401: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + migrateAccount: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** @description Migration request specifying the desired migration method */ + requestBody: { + content: { + "application/json": components["schemas"]["market-api_MigrateAccountRequest"]; + }; + }; + responses: { + /** @description Account successfully migrated */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "status": "migrated" + * } + */ + "application/json": components["schemas"]["market-api_MigrateAccountResponse"]; + }; + }; + /** @description Unauthorized - missing or invalid authentication token */ + 401: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Account already migrated */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "error": { + * "type": "account_already_migrated", + * "message": "Account has already been migrated", + * "details": [], + * "request_id": "req_550e8400-e29b-41d4-a716-446655440000" + * } + * } + */ + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + /** + * @example { + * "error": { + * "type": "internal_server_error", + * "message": "An internal server error occurred", + * "details": [], + * "request_id": "req_550e8400-e29b-41d4-a716-446655440000" + * } + * } + */ + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + }; + }; + post_calculate_invoice_pricing: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["market-api_CalculateInvoicePricingRequest"]; + }; + }; + responses: { + /** @description Invoice pricing recalculated */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["market-api_CalculateInvoicePricingResponse"]; + }; + }; + /** @description Bad request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + /** @description Invoice not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + }; + }; + post_create_draft_invoice: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["market-api_CreateDraftInvoiceRequest"]; + }; + }; + responses: { + /** @description Draft invoice created */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["market-api_CreateDraftInvoiceResponse"]; + }; + }; + /** @description Bad request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; + }; + }; + }; + post_finalize_invoice: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["market-api_FinalizeInvoiceRequest"]; + }; + }; + responses: { + /** @description Invoice finalized */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["market-api_FinalizeInvoiceResponse"]; }; }; - /** @description Bad request - invalid query parameters */ + /** @description Bad request */ 400: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "invalid_request_error", - * "message": "must provide both active_within_interval_start and active_within_interval_end or none of them" - * } - * } */ "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; }; }; - /** @description Unauthorized - missing or invalid authentication token */ - 401: { + /** @description Forbidden */ + 403: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "authentication_error", - * "message": "missing authentication token" - * } - * } */ "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; }; }; - /** @description Forbidden - account frozen */ - 403: { + /** @description Invoice not found */ + 404: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "forbidden", - * "message": "Account is frozen" - * } - * } */ "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; }; }; @@ -4797,107 +7996,49 @@ export interface operations { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "api_error", - * "message": "An internal server error occurred" - * } - * } */ "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; }; }; }; }; - getContract: { + get_node_ids: { parameters: { - query?: never; - header?: never; - path: { - /** - * @description Contract ID - * @example cont_xyz789 - */ - id: components["schemas"]["market-api_ContractId"]; + query?: { + /** @description Optional provider identifier filter */ + provider_id?: string; + /** @description Include source details (VM or Kubernetes) */ + details?: boolean; }; + header?: never; + path?: never; cookie?: never; }; requestBody?: never; responses: { - /** @description Contract details */ + /** @description Node assignment list */ 200: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "object": "contract", - * "status": "active", - * "id": "cont_xyz789", - * "created_at": "2024-07-15T22:30:17.426Z", - * "instance_type": "h100i", - * "shape": { - * "intervals": [ - * "2024-07-16T22:30:16Z", - * "2024-07-17T22:30:16Z", - * "2024-07-18T22:30:16Z" - * ], - * "quantities": [ - * 10, - * 20, - * 0 - * ] - * }, - * "colocate_with": [ - * "cont_abc456" - * ], - * "cluster_id": "clus_xyz123", - * "state": "Active" - * } */ - "application/json": components["schemas"]["market-api_ContractResponse"]; + "application/json": components["schemas"]["market-api_NodeIdResponse"]; }; }; - /** @description Unauthorized - missing or invalid authentication token */ + /** @description Unauthorized */ 401: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "authentication_error", - * "message": "missing authentication token" - * } - * } */ "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; }; }; - /** @description Forbidden - account frozen */ + /** @description Forbidden - not a vendor */ 403: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "forbidden", - * "message": "Account is frozen" - * } - * } */ - "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; - }; - }; - /** @description Contract not found */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - /** @example { - * "error": { - * "type": "not_found", - * "message": "Contract not found" - * } - * } */ "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; }; }; @@ -4907,77 +8048,26 @@ export interface operations { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "api_error", - * "message": "An internal server error occurred" - * } - * } */ "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; }; }; }; }; - listOrders: { + list_provider_orders: { parameters: { query?: { - /** @description Filter by order side (buy or sell) */ - side?: components["schemas"]["market-api_OrderSide"]; - /** @description Filter by instance type */ - instance_type?: components["schemas"]["market-api_Ticker"]; - /** @description Minimum price in cents */ - min_price?: number; - /** @description Maximum price in cents */ - max_price?: number; - /** @description Minimum start date */ - min_start_date?: components["schemas"]["market-api_ISO8601DateTime"]; - /** @description Maximum start date */ - max_start_date?: components["schemas"]["market-api_ISO8601DateTime"]; - /** @description Minimum duration in seconds */ - min_duration?: components["schemas"]["market-api_UnixEpoch"]; - /** @description Maximum duration in seconds */ - max_duration?: components["schemas"]["market-api_UnixEpoch"]; - /** @description Minimum quantity */ - min_quantity?: number; - /** @description Maximum quantity */ - max_quantity?: number; - /** @description Filter by contract ID */ - contract_id?: components["schemas"]["market-api_ContractId"]; - /** @description Show only open orders */ - only_open?: boolean; - /** @description Exclude filled orders */ - exclude_filled?: boolean; - /** @description Show only filled orders */ - only_filled?: boolean; - /** @description Minimum filled at date */ - min_filled_at?: components["schemas"]["market-api_ISO8601DateTime"]; - /** @description Maximum filled at date */ - max_filled_at?: components["schemas"]["market-api_ISO8601DateTime"]; - /** @description Minimum fill price in cents */ - min_fill_price?: number; - /** @description Maximum fill price in cents */ - max_fill_price?: number; - /** @description Exclude cancelled orders */ - exclude_cancelled?: boolean; - /** @description Show only cancelled orders */ - only_cancelled?: boolean; - /** @description Minimum cancelled at date */ - min_cancelled_at?: components["schemas"]["market-api_ISO8601DateTime"]; - /** @description Maximum cancelled at date */ - max_cancelled_at?: components["schemas"]["market-api_ISO8601DateTime"]; - /** @description Minimum placed at date */ - min_placed_at?: components["schemas"]["market-api_ISO8601DateTime"]; - /** @description Maximum placed at date */ - max_placed_at?: components["schemas"]["market-api_ISO8601DateTime"]; - /** @description Maximum number of results to return (default: 100, max: 100) */ + /** @description Optional provider identifier (admins only) */ + provider_id?: string; + /** @description Inclusive start of the time window (ISO8601, UTC) */ + start_time?: string; + /** @description Exclusive end of the time window (ISO8601, UTC). Defaults to now. */ + end_time?: string; + /** @description Number of orders to return (1-500, default 50) */ limit?: number; - /** @description Number of results to skip */ - offset?: number; - /** @description Sort field */ - sort_by?: components["schemas"]["market-api_SortBy"]; - /** @description Sort direction */ - sort_direction?: components["schemas"]["market-api_SortDirection"]; - include_public?: unknown; + /** @description Cursor for forward pagination */ + starting_after?: components["schemas"]["market-api_ProviderOrdersCursor"]; + /** @description Cursor for backward pagination */ + ending_before?: components["schemas"]["market-api_ProviderOrdersCursor"]; }; header?: never; path?: never; @@ -4985,37 +8075,36 @@ export interface operations { }; requestBody?: never; responses: { - /** @description List of orders */ + /** @description Successfully retrieved provider orders */ 200: { headers: { [name: string]: unknown; }; content: { - /** @example { + /** + * @example { * "object": "list", * "data": [ * { - * "object": "order", - * "id": "ordr_xyz123", - * "side": "buy", - * "instance_type": "h100i", - * "price": 5000, - * "quantity": 2, - * "status": "open", - * "created_at": "2024-07-15T22:30:17.426Z", - * "start_at": "2024-07-16T00:00:00Z", - * "end_at": "2024-07-17T00:00:00Z", - * "flags": { - * "ioc": false, - * "post_only": false, - * "market": false, - * "prorate": false - * } + * "object": "provider_order", + * "cursor": "poc_3kTh9P2mN8xQ7vB1dF5wE", + * "id": "ordr_Y3qN8pL2kX9vB1dF5wE4Z", + * "quantity": "2", + * "tcv": "500.00", + * "executed": true, + * "cancelled": false * } * ], + * "summary": { + * "object": "provider_orders_summary", + * "total_revenue_cents": 50000, + * "total_revenue_usd": "500.00", + * "order_count": 1 + * }, * "has_more": false - * } */ - "application/json": components["schemas"]["market-api_ListOrdersResponse"]; + * } + */ + "application/json": components["schemas"]["market-api_ProviderOrdersResponse"]; }; }; /** @description Invalid request parameters */ @@ -5024,42 +8113,24 @@ export interface operations { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "invalid_request_error", - * "message": "Cannot specify both 'only_filled' and 'only_cancelled'" - * } - * } */ "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; }; }; - /** @description Unauthorized - missing or invalid authentication token */ + /** @description Unauthorized */ 401: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "authentication_error", - * "message": "missing authentication token" - * } - * } */ "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; }; }; - /** @description Forbidden - account frozen */ + /** @description Forbidden - not a vendor or admin */ 403: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "forbidden", - * "message": "Account is frozen" - * } - * } */ "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; }; }; @@ -5069,46 +8140,74 @@ export interface operations { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "api_error", - * "message": "An internal server error occurred" - * } - * } */ "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; }; }; }; }; - createOrder: { + getTransactions: { parameters: { - query?: never; - header?: { - /** @description Optional key to ensure idempotent order creation */ - "Idempotency-Key"?: string | null; + query?: { + /** @description Number of transactions to return (1-100, default 10) */ + limit?: number; + /** + * @description Filter for transactions after this UNIX timestamp (exclusive) + * @example 1640995200 + */ + after_time?: number; + /** + * @description Filter for transactions before this UNIX timestamp (exclusive) + * @example 1640995200 + */ + before_time?: number; + /** + * @description Cursor for forward pagination + * @example 1640995200 + */ + starting_after_cursor?: components["schemas"]["market-api_GetTransactionsCursor"]; + /** + * @description Cursor for backward pagination + * @example 1640995200 + */ + ending_before_cursor?: components["schemas"]["market-api_GetTransactionsCursor"]; + sort?: "transaction_time" | "-transaction_time" | "amount" | "-amount"; + /** + * @description Filter transactions by type (e.g. `buy_order`) + * @example buy_order + */ + transaction_type?: components["schemas"]["market-api_TransactionTypeFilter"]; }; + header?: never; path?: never; cookie?: never; }; - requestBody: { - content: { - "application/json": components["schemas"]["market-api_CreateOrderRequest"]; - }; - }; + requestBody?: never; responses: { - /** @description Order created successfully */ - 201: { + /** @description Successfully retrieved transactions */ + 200: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "object": "order", - * "status": "pending", - * "id": "order_xyz789", - * "idempotency_key": "key_123" - * } */ - "application/json": components["schemas"]["market-api_CreateOrderResponse"]; + /** + * @example { + * "object": "list", + * "data": [ + * { + * "object": "transaction", + * "transaction_time": 1640995200, + * "amount_cents": 25000, + * "details": { + * "object": "transaction_details", + * "type": "credit_grant", + * "memo": "Promotional credit" + * } + * } + * ], + * "has_more": false + * } + */ + "application/json": components["schemas"]["market-api_ListTransactionsResponse"]; }; }; /** @description Invalid request parameters */ @@ -5117,11 +8216,6 @@ export interface operations { [name: string]: unknown; }; content: { - /** @example { - * "type": "invalid_request_error", - * "message": "Start time must be within +/- 1 minute of now, on a future hour, or the string literal 'NOW'", - * "details": [] - * } */ "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; }; }; @@ -5131,54 +8225,54 @@ export interface operations { [name: string]: unknown; }; content: { - /** @example { - * "type": "authentication_error", - * "message": "missing authentication token", - * "details": [] - * } */ "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; }; }; - /** @description Forbidden - account frozen, insufficient credits, unauthorized seller, or trading halted */ - 403: { + /** @description Internal server error */ + 500: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "type": "forbidden", - * "message": "Account is frozen", - * "details": [] - * } */ "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; }; }; - /** @description Not found - contract or cluster not found */ - 404: { + }; + }; + list_capacities_handler: { + parameters: { + query?: { + /** @description Maximum number of results to return (1–200, default 50). */ + limit?: number; + /** @description Cursor for forward pagination (from a previous response's `cursor` field). */ + starting_after?: components["schemas"]["market-api_CapacitiesCursor"]; + /** @description Cursor for backward pagination. */ + ending_before?: components["schemas"]["market-api_CapacitiesCursor"]; + /** @description Include deleted capacities. Defaults to false. */ + include_deleted?: boolean; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Paginated list of capacities */ + 200: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "type": "not_found", - * "message": "Contract not found", - * "details": [] - * } */ - "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + "application/json": components["schemas"]["market-api_ListCapacitiesResponse"]; }; }; - /** @description Upgrade required - legacy account needs migration */ - 426: { + /** @description Unauthorized request */ + 401: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "type": "invalid_request_error", - * "message": "Legacy account must be upgraded before placing orders", - * "details": [] - * } */ - "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + "application/json": components["schemas"]["market-api_ErrorObject"]; }; }; /** @description Internal server error */ @@ -5187,101 +8281,49 @@ export interface operations { [name: string]: unknown; }; content: { - /** @example { - * "type": "api_error", - * "message": "An internal server error occurred", - * "details": [] - * } */ - "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + "application/json": components["schemas"]["market-api_ErrorObject"]; }; }; }; }; - getOrder: { + create_capacity_handler: { parameters: { query?: never; header?: never; - path: { - /** - * @description Order ID - * @example order_xyz789 - */ - id: components["schemas"]["market-api_OrderId"]; - }; + path?: never; cookie?: never; }; - requestBody?: never; - responses: { - /** @description Order details */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - /** @example { - * "object": "order", - * "id": "order_xyz789", - * "side": "buy", - * "status": "open", - * "instance_type": "h100i", - * "quantity": 4, - * "start_at": "2021-01-01T00:00:00Z", - * "end_at": "2021-01-01T01:00:00Z", - * "price": 2850000, - * "flags": { - * "market": false, - * "post_only": false, - * "ioc": false - * }, - * "executed": false, - * "cancelled": false, - * "colocate_with": [], - * "created_at": "2021-01-01T00:00:00Z", - * "rejected": false - * } */ - "application/json": components["schemas"]["market-api_OrderResponse"]; - }; + requestBody: { + content: { + "application/json": components["schemas"]["market-api_CreateCapacityRequest"]; }; - /** @description Unauthorized - missing or invalid authentication token */ - 401: { + }; + responses: { + /** @description Capacity created successfully */ + 201: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "type": "authentication_error", - * "message": "missing authentication token", - * "details": [] - * } */ - "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + "application/json": components["schemas"]["market-api_CapacityDetails"]; }; }; - /** @description Forbidden - user not authorized to view this order */ - 403: { + /** @description Validation failed (e.g., duplicate name or missing node template) */ + 400: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "type": "forbidden", - * "message": "User not authorized to view this order", - * "details": [] - * } */ - "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + "application/json": components["schemas"]["market-api_ErrorObject"]; }; }; - /** @description Order not found */ - 404: { + /** @description Unauthorized request */ + 401: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "type": "not_found", - * "message": "Order not found", - * "details": [] - * } */ - "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + "application/json": components["schemas"]["market-api_ErrorObject"]; }; }; /** @description Internal server error */ @@ -5290,69 +8332,47 @@ export interface operations { [name: string]: unknown; }; content: { - /** @example { - * "type": "api_error", - * "message": "An internal server error occurred", - * "details": [] - * } */ - "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + "application/json": components["schemas"]["market-api_ErrorObject"]; }; }; }; }; - cancelOrder: { + get_capacity_handler: { parameters: { query?: never; header?: never; path: { - /** - * @description Order ID - * @example ordr_xyz789 - */ - id: components["schemas"]["market-api_OrderId"]; + id: string; }; cookie?: never; }; requestBody?: never; responses: { - /** @description Order cancelled successfully */ + /** @description Capacity details */ 200: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "object": "pending" - * } */ - "application/json": components["schemas"]["market-api_CancelOrderResponse"]; + "application/json": components["schemas"]["market-api_CapacityDetails"]; }; }; - /** @description Order already cancelled */ - 400: { + /** @description Unauthorized request */ + 401: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "type": "validation_error", - * "message": "Order already cancelled", - * "details": [] - * } */ - "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + "application/json": components["schemas"]["market-api_ErrorObject"]; }; }; - /** @description Order not found */ + /** @description Capacity not found */ 404: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "type": "not_found", - * "message": "Order not found", - * "details": [] - * } */ - "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + "application/json": components["schemas"]["market-api_ErrorObject"]; }; }; /** @description Internal server error */ @@ -5361,116 +8381,54 @@ export interface operations { [name: string]: unknown; }; content: { - /** @example { - * "type": "api_error", - * "message": "An internal server error occurred", - * "details": [] - * } */ - "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + "application/json": components["schemas"]["market-api_ErrorObject"]; }; }; }; }; - getOrderClusters: { + delete_capacity_handler: { parameters: { query?: never; header?: never; path: { - /** - * @description Order ID - * @example ordr_W9TRG - */ - id: components["schemas"]["market-api_OrderId"]; + id: string; }; cookie?: never; }; requestBody?: never; responses: { - /** @description List of clusters associated with the order */ - 200: { + /** @description Capacity deleted successfully */ + 204: { headers: { [name: string]: unknown; }; - content: { - /** @example { - * "object": "list", - * "data": [ - * { - * "object": "kubernetes_cluster", - * "name": "starlight", - * "kubernetes_namespace": "sf-user123", - * "kubernetes_api_url": "https://starlight.sf-k8s.com", - * "kubernetes_ca_cert": "-----BEGIN CERTIFICATE-----...", - * "contract": { - * "object": "contract", - * "status": "active", - * "id": "cont_xyz123", - * "created_at": "2024-07-15T22:30:17.426Z", - * "instance_type": "h100i", - * "shape": { - * "intervals": [ - * "2024-07-16T00:00:00Z", - * "2024-07-17T00:00:00Z" - * ], - * "quantities": [ - * 4, - * 0 - * ] - * }, - * "colocate_with": [], - * "cluster_id": "clstr_abc456", - * "state": "Active" - * } - * } - * ], - * "has_more": false - * } */ - "application/json": components["schemas"]["market-api_ListClustersResponse"]; - }; + content?: never; }; - /** @description Unauthorized - missing or invalid authentication token */ - 401: { + /** @description Capacity is not empty or has an enabled scheduler */ + 400: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "authentication_error", - * "message": "missing authentication token" - * } - * } */ - "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + "application/json": components["schemas"]["market-api_ErrorObject"]; }; }; - /** @description Forbidden - account frozen */ - 403: { + /** @description Unauthorized request */ + 401: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "forbidden", - * "message": "Account is frozen" - * } - * } */ - "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + "application/json": components["schemas"]["market-api_ErrorObject"]; }; }; - /** @description Order not found */ + /** @description Capacity not found */ 404: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "not_found", - * "message": "Order not found" - * } - * } */ - "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + "application/json": components["schemas"]["market-api_ErrorObject"]; }; }; /** @description Internal server error */ @@ -5479,83 +8437,60 @@ export interface operations { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "api_error", - * "message": "An internal server error occurred" - * } - * } */ - "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + "application/json": components["schemas"]["market-api_ErrorObject"]; }; }; }; }; - listProcurements: { + patch_capacity_handler: { parameters: { query?: never; header?: never; - path?: never; + path: { + id: string; + }; cookie?: never; }; - requestBody?: never; + requestBody: { + content: { + "application/json": components["schemas"]["market-api_PatchCapacityRequest"]; + }; + }; responses: { - /** @description List of procurements */ + /** @description Capacity updated successfully */ 200: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "object": "list", - * "data": [ - * { - * "object": "procurement", - * "id": "proc_test123", - * "status": "active", - * "instance_type": "h100i", - * "desired_quantity": 5, - * "buy_limit_price_per_gpu_hour": 250, - * "sell_limit_price_per_gpu_hour": 25, - * "horizon": 60, - * "colocation_strategy": "colocate_pinned", - * "actual_quantity": 5, - * "active_order_count": 2, - * "last_message": "Running" - * } - * ], - * "has_more": false - * } */ - "application/json": components["schemas"]["market-api_ListProcurementsResponse"]; + "application/json": components["schemas"]["market-api_CapacityDetails"]; }; }; - /** @description Unauthorized - missing or invalid authentication token */ - 401: { + /** @description Validation failed (e.g., duplicate name or missing node template) */ + 400: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "authentication_error", - * "message": "missing authentication token" - * } - * } */ - "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + "application/json": components["schemas"]["market-api_ErrorObject"]; + }; + }; + /** @description Unauthorized request */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["market-api_ErrorObject"]; }; }; - /** @description Forbidden - account frozen */ - 403: { + /** @description Capacity or referenced node template not found */ + 404: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "forbidden", - * "message": "Account is frozen" - * } - * } */ - "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + "application/json": components["schemas"]["market-api_ErrorObject"]; }; }; /** @description Internal server error */ @@ -5564,125 +8499,96 @@ export interface operations { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "api_error", - * "message": "An internal server error occurred" - * } - * } */ - "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + "application/json": components["schemas"]["market-api_ErrorObject"]; }; }; }; }; - createProcurement: { + list_node_templates_handler: { parameters: { - query?: never; + query?: { + /** @description Maximum number of results to return (1-200, default 50). */ + limit?: number; + /** @description Cursor for forward pagination (from a previous response's `cursor` field). */ + starting_after?: components["schemas"]["market-api_NodeTemplatesCursor"]; + /** @description Cursor for backward pagination. */ + ending_before?: components["schemas"]["market-api_NodeTemplatesCursor"]; + /** @description Include deleted node templates. Defaults to false. */ + include_deleted?: boolean; + }; header?: never; path?: never; cookie?: never; }; - requestBody: { - content: { - "application/json": components["schemas"]["market-api_CreateProcurementRequest"]; - }; - }; + requestBody?: never; responses: { - /** @description Successfully created procurement */ - 201: { + /** @description List of node templates */ + 200: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "object": "procurement", - * "id": "proc_xyz123", - * "status": "active", - * "instance_type": "h100i", - * "desired_quantity": 5, - * "buy_limit_price_per_gpu_hour": 250, - * "sell_limit_price_per_gpu_hour": 25, - * "horizon": 60, - * "colocation_strategy": "colocate_pinned", - * "actual_quantity": 0, - * "active_order_count": 0 - * } */ - "application/json": components["schemas"]["market-api_ProcurementResponse"]; + "application/json": components["schemas"]["market-api_ListNodeTemplatesResponse"]; }; }; - /** @description Bad request - invalid field values */ - 400: { + /** @description Unauthorized request */ + 401: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "invalid_request_error", - * "message": "desired_quantity must be non-negative" - * } - * } */ - "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + "application/json": components["schemas"]["market-api_ErrorObject"]; }; }; - /** @description Unauthorized - missing or invalid authentication token */ - 401: { + /** @description Internal server error */ + 500: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "authentication_error", - * "message": "missing authentication token" - * } - * } */ - "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + "application/json": components["schemas"]["market-api_ErrorObject"]; }; }; - /** @description Payment required - insufficient funds */ - 402: { + }; + }; + create_node_template_handler: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["market-api_CreateNodeTemplateRequest"]; + }; + }; + responses: { + /** @description Node template created */ + 201: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "payment_required", - * "message": "insufficient funds" - * } - * } */ - "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + "application/json": components["schemas"]["market-api_NodeTemplateDetails"]; }; }; - /** @description Forbidden - account frozen */ - 403: { + /** @description Invalid request */ + 400: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "forbidden", - * "message": "Account is frozen" - * } - * } */ - "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + "application/json": components["schemas"]["market-api_ErrorObject"]; }; }; - /** @description Not found - cluster not found */ - 404: { + /** @description Unauthorized request */ + 401: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "not_found", - * "message": "cluster starlight not found" - * } - * } */ - "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + "application/json": components["schemas"]["market-api_ErrorObject"]; }; }; /** @description Internal server error */ @@ -5691,98 +8597,47 @@ export interface operations { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "api_error", - * "message": "An internal server error occurred" - * } - * } */ - "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + "application/json": components["schemas"]["market-api_ErrorObject"]; }; }; }; }; - getProcurement: { + get_node_template_handler: { parameters: { query?: never; header?: never; path: { - /** - * @description Procurement ID - * @example proc_xyz123 - */ id: string; }; cookie?: never; }; requestBody?: never; responses: { - /** @description Procurement details */ + /** @description Node template information */ 200: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "object": "procurement", - * "id": "proc_xyz123", - * "status": "active", - * "instance_type": "h100i", - * "desired_quantity": 5, - * "buy_limit_price_per_gpu_hour": 250, - * "sell_limit_price_per_gpu_hour": 25, - * "horizon": 60, - * "colocation_strategy": "colocate_pinned", - * "actual_quantity": 5, - * "active_order_count": 2, - * "last_message": "Running" - * } */ - "application/json": components["schemas"]["market-api_ProcurementResponse"]; + "application/json": components["schemas"]["market-api_NodeTemplateDetails"]; }; }; - /** @description Unauthorized - missing or invalid authentication token */ + /** @description Unauthorized request */ 401: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "authentication_error", - * "message": "missing authentication token" - * } - * } */ - "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; - }; - }; - /** @description Forbidden - account frozen */ - 403: { - headers: { - [name: string]: unknown; - }; - content: { - /** @example { - * "error": { - * "type": "forbidden", - * "message": "Account is frozen" - * } - * } */ - "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + "application/json": components["schemas"]["market-api_ErrorObject"]; }; }; - /** @description Procurement not found */ + /** @description Node template not found */ 404: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "not_found", - * "message": "Procurement proc_xyz123 not found" - * } - * } */ - "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + "application/json": components["schemas"]["market-api_ErrorObject"]; }; }; /** @description Internal server error */ @@ -5791,131 +8646,54 @@ export interface operations { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "api_error", - * "message": "An internal server error occurred" - * } - * } */ - "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + "application/json": components["schemas"]["market-api_ErrorObject"]; }; }; }; }; - updateProcurement: { + delete_node_template_handler: { parameters: { query?: never; header?: never; path: { - /** - * @description Procurement ID - * @example proc_xyz123 - */ id: string; }; cookie?: never; }; - requestBody: { - content: { - "application/json": components["schemas"]["market-api_UpdateProcurementRequest"]; - }; - }; + requestBody?: never; responses: { - /** @description Successfully updated procurement */ - 200: { + /** @description Node template deleted successfully */ + 204: { headers: { [name: string]: unknown; }; - content: { - /** @example { - * "object": "procurement", - * "id": "proc_xyz123", - * "status": "disabled", - * "instance_type": "h100i", - * "desired_quantity": 5, - * "buy_limit_price_per_gpu_hour": 400, - * "sell_limit_price_per_gpu_hour": 100, - * "horizon": 120, - * "colocation_strategy": "colocate_pinned", - * "actual_quantity": 3, - * "active_order_count": 1 - * } */ - "application/json": components["schemas"]["market-api_ProcurementResponse"]; - }; + content?: never; }; - /** @description Bad request - invalid field values */ + /** @description Node template cannot be deleted (in use by a capacity) */ 400: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "invalid_request_error", - * "message": "desired_quantity must be non-negative" - * } - * } */ - "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + "application/json": components["schemas"]["market-api_ErrorObject"]; }; }; - /** @description Unauthorized - missing or invalid authentication token */ + /** @description Unauthorized request */ 401: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "authentication_error", - * "message": "missing authentication token" - * } - * } */ - "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; - }; - }; - /** @description Payment required - insufficient funds */ - 402: { - headers: { - [name: string]: unknown; - }; - content: { - /** @example { - * "error": { - * "type": "payment_required", - * "message": "insufficient funds" - * } - * } */ - "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; - }; - }; - /** @description Forbidden - account frozen */ - 403: { - headers: { - [name: string]: unknown; - }; - content: { - /** @example { - * "error": { - * "type": "forbidden", - * "message": "Account is frozen" - * } - * } */ - "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + "application/json": components["schemas"]["market-api_ErrorObject"]; }; }; - /** @description Procurement not found */ + /** @description Node template not found */ 404: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "not_found", - * "message": "procurement proc_xyz123 not found" - * } - * } */ - "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + "application/json": components["schemas"]["market-api_ErrorObject"]; }; }; /** @description Internal server error */ @@ -5924,79 +8702,52 @@ export interface operations { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "api_error", - * "message": "An internal server error occurred" - * } - * } */ - "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + "application/json": components["schemas"]["market-api_ErrorObject"]; }; }; }; }; - getRefunds: { + list_orders: { parameters: { - query?: never; + query?: { + /** @description Filter by capacity. */ + capacity?: components["schemas"]["market-api_CapacityId"]; + /** @description Filter by status (can be repeated, e.g. `?status=filled&status=cancelled`). */ + status?: components["schemas"]["market-api_v2.OrderStatus"][]; + /** @description Only return orders placed at or after this Unix timestamp (seconds). */ + placed_after?: number; + /** @description Only return orders placed at or before this Unix timestamp (seconds). */ + placed_before?: number; + /** @description Sort field and direction. Prefix with `-` for descending. One of: `placed_at`, `-placed_at`, `start_time`, `-start_time`, `total_price_cents`, `-total_price_cents`. Default: `-placed_at`. */ + sort_by?: string; + /** @description Maximum number of results to return (1–200, default 50). */ + limit?: number; + /** @description Cursor for forward pagination (from a previous response's `cursor` field). */ + starting_after?: components["schemas"]["market-api_OrdersCursor"]; + /** @description Cursor for backward pagination. */ + ending_before?: components["schemas"]["market-api_OrdersCursor"]; + }; header?: never; path?: never; cookie?: never; }; requestBody?: never; responses: { - /** @description List of refund requests and their statuses for the account */ + /** @description List of orders */ 200: { - headers: { - [name: string]: unknown; - }; - content: { - /** @example { - * "object": "refunds", - * "refunds": [ - * { - * "report_id": 12345, - * "report_start_time": "2024-03-15T00:00:00Z", - * "report_end_time": "2024-03-15T02:00:00Z", - * "report_nodes_affected": 4, - * "report_cluster_id": "cluster_us_west_1", - * "report_memo": "Network connectivity issues in US-West-1", - * "report_created_at": "2024-03-15T00:30:00Z", - * "memo_amount": "500.00", - * "refund_timestamp": "2024-03-16T00:00:00Z", - * "status": "refunded" - * } - * ] - * } */ - "application/json": components["schemas"]["market-api_AccountRefundsResponse"]; - }; - }; - /** @description Unauthorized - missing or invalid authentication token */ - 401: { - headers: { - [name: string]: unknown; - }; - content: { - /** @example { - * "error": { - * "type": "authentication_error", - * "message": "missing authentication token" - * } - * } */ - "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["market-api_v2.ListOrdersResponse"]; }; }; - /** @description Forbidden - account frozen */ - 403: { + /** @description Unauthorized */ + 401: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "forbidden", - * "message": "Account is frozen" - * } - * } */ "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; }; }; @@ -6006,162 +8757,111 @@ export interface operations { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "api_error", - * "message": "An internal server error occurred" - * } - * } */ "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; }; }; }; }; - getAccountMe: { + post_order: { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - requestBody?: never; + requestBody: { + content: { + "application/json": components["schemas"]["market-api_v2.CreateOrderRequest"]; + }; + }; responses: { - /** @description Account information retrieved successfully */ - 200: { + /** @description Order created */ + 201: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "id": "gmail-com-name", - * "role": "user", - * "is_frozen": false, - * "kyc": "basic", - * "submitted_waitlist": true, - * "waitlist": false, - * "kycb_form_submitted": false, - * "created_at": "2024-01-15T10:30:00Z" - * } */ - "application/json": components["schemas"]["market-api_AccountMeResponse"]; + "application/json": components["schemas"]["market-api_v2.OrderResponse"]; }; }; - /** @description Unauthorized - missing or invalid authentication token */ - 401: { + /** @description Invalid request */ + 400: { headers: { [name: string]: unknown; }; - content?: never; + content: { + "application/json": components["schemas"]["market-api_ErrorObject"]; + }; }; - /** @description Account not found */ - 404: { + /** @description Unauthorized */ + 401: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "not_found", - * "message": "account not found", - * "details": [], - * "request_id": "req_550e8400-e29b-41d4-a716-446655440000" - * } - * } */ - "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + "application/json": components["schemas"]["market-api_ErrorObject"]; }; }; - }; - }; - getBalance: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Successfully retrieved balance */ - 200: { + /** @description Insufficient balance */ + 402: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "object": "balance", - * "available_cents": 150000, - * "current_cents": 180000, - * "current_overage_cents": 150000, - * "current_hold_cents": 180000, - * "updated_at": 1640995200 - * } */ - "application/json": components["schemas"]["market-api_GetBalanceResponse"]; + "application/json": components["schemas"]["market-api_ErrorObject"]; }; }; - /** @description Unauthorized - missing or invalid authentication token */ - 401: { + /** @description Forbidden */ + 403: { headers: { [name: string]: unknown; }; - content?: never; + content: { + "application/json": components["schemas"]["market-api_ErrorObject"]; + }; }; - }; - }; - getCredits: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Successfully retrieved credit balance */ - 200: { + /** @description Capacity not found */ + 404: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "current_balance_cents": 150000, - * "available_credits_cents": 150000, - * "amount_due_next_billing_period_cents": 0 - * } */ - "application/json": components["schemas"]["market-api_GetCreditsResponse"]; + "application/json": components["schemas"]["market-api_ErrorObject"]; }; }; - /** @description Unauthorized - missing or invalid authentication token */ - 401: { + /** @description Internal server error */ + 500: { headers: { [name: string]: unknown; }; - content?: never; + content: { + "application/json": components["schemas"]["market-api_ErrorObject"]; + }; }; }; }; - migrateAccount: { + get_order: { parameters: { query?: never; header?: never; - path?: never; - cookie?: never; - }; - /** @description Migration request specifying the desired migration method */ - requestBody: { - content: { - "application/json": components["schemas"]["market-api_MigrateAccountRequest"]; + path: { + /** + * @description Order ID + * @example ordr_xyz789 + */ + id: components["schemas"]["market-api_OrderId"]; }; + cookie?: never; }; + requestBody?: never; responses: { - /** @description Account successfully migrated */ + /** @description Order details */ 200: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "status": "migrated" - * } */ - "application/json": components["schemas"]["market-api_MigrateAccountResponse"]; + "application/json": components["schemas"]["market-api_v2.OrderResponse"]; }; }; /** @description Unauthorized - missing or invalid authentication token */ @@ -6169,22 +8869,30 @@ export interface operations { headers: { [name: string]: unknown; }; - content?: never; + content: { + /** + * @example { + * "type": "authentication_error", + * "message": "missing authentication token", + * "details": [] + * } + */ + "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; + }; }; - /** @description Account already migrated */ - 409: { + /** @description Order not found */ + 404: { headers: { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "account_already_migrated", - * "message": "Account has already been migrated", - * "details": [], - * "request_id": "req_550e8400-e29b-41d4-a716-446655440000" - * } - * } */ + /** + * @example { + * "type": "not_found", + * "message": "Order not found", + * "details": [] + * } + */ "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; }; }; @@ -6194,77 +8902,41 @@ export interface operations { [name: string]: unknown; }; content: { - /** @example { - * "error": { - * "type": "internal_server_error", - * "message": "An internal server error occurred", - * "details": [], - * "request_id": "req_550e8400-e29b-41d4-a716-446655440000" - * } - * } */ + /** + * @example { + * "type": "api_error", + * "message": "An internal server error occurred", + * "details": [] + * } + */ "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; }; }; }; }; - getTransactions: { + cancel_order: { parameters: { - query?: { - /** @description Number of transactions to return (1-100, default 10) */ - limit?: number; - /** - * @description Filter for transactions after this UNIX timestamp (exclusive) - * @example 1640995200 - */ - after_time?: number; - /** - * @description Filter for transactions before this UNIX timestamp (exclusive) - * @example 1640995200 - */ - before_time?: number; - /** - * @description Cursor for forward pagination - * @example 1640995200 - */ - starting_after_cursor?: components["schemas"]["market-api_GetTransactionsCursor"]; + query?: never; + header?: never; + path: { /** - * @description Cursor for backward pagination - * @example 1640995200 + * @description Order ID + * @example ordr_xyz789 */ - ending_before_cursor?: components["schemas"]["market-api_GetTransactionsCursor"]; + id: components["schemas"]["market-api_OrderId"]; }; - header?: never; - path?: never; cookie?: never; }; requestBody?: never; responses: { - /** @description Successfully retrieved transactions */ - 200: { + /** @description Order cancellation initiated */ + 204: { headers: { [name: string]: unknown; }; - content: { - /** @example { - * "object": "list", - * "data": [ - * { - * "object": "transaction", - * "transaction_time": 1640995200, - * "amount_cents": 25000, - * "details": { - * "object": "transaction_details", - * "type": "credit_grant", - * "memo": "Promotional credit" - * } - * } - * ], - * "has_more": false - * } */ - "application/json": components["schemas"]["market-api_ListTransactionsResponse"]; - }; + content?: never; }; - /** @description Invalid request parameters */ + /** @description Order cannot be cancelled */ 400: { headers: { [name: string]: unknown; @@ -6273,8 +8945,8 @@ export interface operations { "application/json": components["schemas"]["market-api_SerdeErrorProxy"]; }; }; - /** @description Unauthorized - missing or invalid authentication token */ - 401: { + /** @description Order not found */ + 404: { headers: { [name: string]: unknown; }; @@ -6296,7 +8968,7 @@ export interface operations { list_batches: { parameters: { query: { - /** @description Max items to return */ + /** @description Maximum number of items to return */ limit: number; /** @description Pagination offset */ after: number; @@ -6349,6 +9021,15 @@ export interface operations { "application/json": components["schemas"]["large_scale_inference_SerdeErrorProxy"]; }; }; + /** @description Rate limit exceeded */ + 429: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["large_scale_inference_SerdeErrorProxy"]; + }; + }; /** @description Internal server error */ 500: { headers: { @@ -6365,7 +9046,7 @@ export interface operations { query?: never; header?: never; path: { - /** @description Batch identifier */ + /** @description The batch identifier */ batch_id: string; }; cookie?: never; @@ -6406,7 +9087,7 @@ export interface operations { query?: never; header?: never; path: { - /** @description Batch identifier */ + /** @description The batch identifier */ batch_id: string; }; cookie?: never; @@ -6481,22 +9162,43 @@ export interface operations { }; }; }; - health_check: { + retry_batch: { parameters: { query?: never; header?: never; - path?: never; + path: { + /** @description The batch identifier */ + batch_id: string; + }; cookie?: never; }; requestBody?: never; responses: { - /** @description Service is healthy */ + /** @description Batch retried */ 200: { headers: { [name: string]: unknown; }; content: { - "application/json": unknown; + "application/json": components["schemas"]["large_scale_inference_Batch"]; + }; + }; + /** @description Batch not found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["large_scale_inference_SerdeErrorProxy"]; + }; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["large_scale_inference_SerdeErrorProxy"]; }; }; }; @@ -6521,27 +9223,6 @@ export interface operations { }; }; }; - get_model_history: { - parameters: { - query?: never; - header?: never; - path: { - /** @description Model identifier */ - model_id: string; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description Not implemented */ - 501: { - headers: { - [name: string]: unknown; - }; - content?: never; - }; - }; - }; handle_quote: { parameters: { query: { @@ -6551,8 +9232,6 @@ export interface operations { quantity: number; /** @description Instance type for buy orders (h100i, h100v, h200ki) */ instance_type?: string; - /** @description Contract ID for sell orders */ - contract_id?: string; /** @description Cluster constraint (hostname) */ cluster?: string; /** @description Contract ID to colocate with */