Operations
Errors and retries
Error responses use FastAPI's standard JSON shape with a detail field. Clients should inspect both HTTP status and detail.
Status codes
| Code | Meaning |
|---|---|
200 | Request succeeded. |
400 | The request was malformed, unsupported, too large, or failed validation. |
401 | The API key is missing, malformed, revoked, or invalid. |
404 | The requested model or upload was not found in this workspace. |
409 | The upload is in a state that cannot be completed, or the object is missing. |
410 | The upload URL expired before the bundle was uploaded. |
500 | The server could not complete the operation. |
Errors by endpoint
| Endpoint | Codes | Notes |
|---|---|---|
POST /v1/models/uploads | 400, 401, 409, 500 | 400 for invalid filename, unsupported modality/task, or size_bytes above the limit. 409 if a version reservation cannot be created after conflicts. 500 for storage or database failures. |
PUT presigned upload_url | Storage-dependent | Object storage returns its own XML or HTTP error if the URL is expired, malformed, or the uploaded object is rejected. |
POST /v1/models/uploads/{upload_id}/complete | 400, 401, 404, 409, 410, 500 | 400 for validation and size failures. 404 if the upload ID is unknown. 409 if the upload is already validating, failed, expired, or the object is missing before URL expiry. 410 if the URL expired before the object was found. |
GET /v1/models/uploads/{upload_id} | 401, 404, 500 | 404 means the upload does not exist in the authenticated workspace. |
GET /v1/models | 401, 500 | Returns an empty models array when the workspace has no models. |
GET /v1/models/{model_id} | 401, 404, 500 | 404 means the model does not exist in the authenticated workspace. |
POST /v1/models/{model_id}/infer | 400, 401, 404, 500 | 400 for unsupported task records, missing matching input, invalid JSON, preprocessing failures, or runtime validation failures. 404 means the model ID is unknown in the workspace. |
Validation failures
HTTP/1.1 400 Bad Request
{
"detail": "Missing preprocess.json after flattening"
}{
"upload": {
"id": "upl_ZdvJxLqgP6QeVnkn8SLcWg",
"status": "failed",
"error": "Missing preprocess.json after flattening",
"completed_at": "2026-05-21T16:48:03.120000+00:00"
}
}Retry behavior
Retry network failures and transient 500 responses with backoff. For 400, 401, 404, 409, and 410 responses, fix the request or restart the upload workflow.
async function fetchWithBackoff(url: string, init: RequestInit, attempts = 4) {
for (let attempt = 1; attempt <= attempts; attempt += 1) {
const response = await fetch(url, init);
if (response.ok) return response;
if (![500, 502, 503, 504].includes(response.status) || attempt === attempts) {
throw new Error(await response.text());
}
const delayMs = 250 * 2 ** (attempt - 1);
await new Promise((resolve) => setTimeout(resolve, delayMs));
}
throw new Error("Request failed");
}Do not blindly retry validation errors. A 400 from completion usually means the bundle contents must change; a 409 or 410 usually means the upload workflow needs to be completed in the right order or restarted with a fresh reservation.