Errors
The VDF AI API uses conventional HTTP status codes to indicate the outcome of a request. Codes in the 2xx range indicate success. Codes in the 4xx range indicate a problem with the request — a missing field, a failed authentication, a resource you cannot see. Codes in the 5xx range indicate an error in your deployment or in a system it depends on.
Branch on the status code. Error messages are written for developers and may change between releases.
{
"success": false,
"error": "Workspace not found"
} HTTP status codes
| Status | Meaning |
|---|---|
200 OK |
The request succeeded. |
201 Created |
The resource was created. |
400 Bad Request |
The request was malformed or failed validation — for example, a required field is missing. |
401 Unauthorized |
No access token was sent, or the token is invalid or has expired. |
402 Payment Required |
Your deployment's licence does not currently permit the request. Contact your administrator. |
403 Forbidden |
The token is valid, but the user lacks the permission or capability the operation requires. |
404 Not Found |
The resource does not exist, or it exists but is not visible to you. |
409 Conflict |
The request conflicts with the current state, such as a duplicate name or a resource that is still in use. |
429 Too Many Requests |
Your deployment's licensed throughput is momentarily exhausted. Retry after the Retry-After interval. |
500 Internal Server Error |
An unexpected error occurred in your deployment. |
502 Bad Gateway |
A system the request depends on — a model provider, an MCP server, a connected database — returned an error. |
503 Service Unavailable |
A dependency of the service is temporarily unavailable. |
504 Gateway Timeout |
A system the request depends on did not respond in time. |
Error responses
Error responses have a JSON body. Most endpoints return a success flag set to false and a human-readable error message. A few return a detail field instead, which holds either a message or a list of validation problems.
Treat the body as diagnostic information for logs and developers. The status code is the stable part of the contract.
{
"detail": "Not found"
} Licence and throughput limits
Capacity is governed by your deployment's licence rather than by per-client rate limits. When the licensed throughput is momentarily exhausted, metered requests — the ones that do billable work, such as running agents — return 429 with a Retry-After header, and the error THROUGHPUT_LIMIT.
A rejected request does not consume capacity, so the limit clears as soon as traffic subsides. If your deployment's licence is not active, requests return 402; that condition needs your administrator, not a retry.
HTTP/1.1 429 Too Many Requests
Retry-After: 2
Content-Type: application/json
{"success": false, "error": "THROUGHPUT_LIMIT"} Retrying safely
Retry 429 responses after the Retry-After interval, and retry 502, 503, and 504 responses with exponential backoff and a cap on attempts.
Be careful with requests that create resources or start work — agent runs, network executions, synchronisations. After a timeout, the first attempt may still be running. Check the state of the resource first (for example, by listing recent runs) instead of sending the request again blindly.
import os
import time
import requests
def get_with_retry(path, attempts=5):
url = f"{os.environ['VDF_BASE_URL']}{path}"
headers = {"Authorization": f"Bearer {os.environ['VDF_ACCESS_TOKEN']}"}
for attempt in range(attempts):
response = requests.get(url, headers=headers, timeout=30)
if response.status_code == 429:
time.sleep(float(response.headers.get("Retry-After", 1)))
continue
if response.status_code in (502, 503, 504):
time.sleep(min(2 ** attempt, 30))
continue
response.raise_for_status()
return response.json()
raise RuntimeError(f"Gave up after {attempts} attempts")