Error Handling

Every failure is reported through one predictable envelope and a standard HTTP status code, so your integration can handle errors uniformly.

The Vantax API uses conventional HTTP status codes to indicate the outcome of a request, and wraps every response — success or failure — in the same top-level envelope. Codes in the 2xx range indicate success, 4xxcodes indicate a problem with the request (and won't succeed on retry without changes), and 5xx codes indicate a transient problem on our side.

Error envelope

When a request fails, success is false and a human-readable message explains what went wrong. There is no data field on an error response.

{
  "success": false,
  "message": "Agent not found"
}
Always branch on the success flag rather than parsing the message string — the wording may change, but the envelope shape is stable.

HTTP status codes

These are the status codes you can expect from the API:

  • 200 OK The request succeeded. The response body contains the requested data.
  • 201 Created A new resource was created — returned by POST endpoints such as creating an Agent or contact.
  • 400 Bad Request The request was malformed — for example invalid JSON, a missing required header, or an unparseable body.
  • 401 Unauthorized No API key was provided, or the key is invalid, revoked, or expired.
  • 403 Forbidden The key is valid but lacks access to this endpoint — typically using an agency key on a resource endpoint, or a sub-account key on an agency endpoint.
  • 404 Not Found The endpoint or resource does not exist, or is not visible to the account derived from your key.
  • 409 Conflict The request conflicts with the current state — for example a duplicate that violates a uniqueness constraint.
  • 422 Unprocessable Entity The request was well-formed but failed validation. The response includes a field-level errors array.
  • 429 Too Many Requests You have exceeded the rate limit. Back off and retry after the window resets.
  • 500 Internal Server Error Something went wrong on our side. These are safe to retry with backoff.

403 vs 401

A 401 means we couldn't authenticate the key at all. A 403 means the key authenticated fine but is the wrong scope for the endpoint — the account is derived from the key, so you never pass an agency or sub-account id yourself.

Validation errors

When a request fails validation, the API responds with 422 and adds an errors array. Each entry names the offending field and a specific message, so you can map problems back to your form or payload precisely.

{
  "success": false,
  "message": "Validation failed",
  "errors": [
    { "field": "name", "message": "name is required" },
    { "field": "voice", "message": "voice must be one of: alloy, sage, verse" },
    { "field": "phone_number", "message": "phone_number must be E.164 formatted" }
  ]
}

Handling errors

A robust client checks both the HTTP status (res.ok) and the success flag in the body, then handles the errors array when present:

const res = await fetch("https://api.vantaxai.com/v1/agents", {
  method: "POST",
  headers: {
    Authorization: "Bearer vx_live_3fa9c2...",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ name: "Front Desk", voice: "sage" }),
});

const body = await res.json();

if (!res.ok || !body.success) {
  // Field-level validation problems (HTTP 422)
  if (res.status === 422 && Array.isArray(body.errors)) {
    for (const e of body.errors) {
      console.error(`${e.field}: ${e.message}`);
    }
  } else {
    console.error(`Request failed (${res.status}): ${body.message}`);
  }
  throw new Error(body.message);
}

// Success — body.data holds the created Agent
const agent = body.data;

Idempotency & retries

Treat the two error classes differently. A 4xx response reflects a problem with the request itself — retrying the identical request will fail the same way, so fix the input instead. A 5xx response (and 429) is transient and safe to retry.

  • Retry on 500 and 429 using exponential backoff with jitter — for example 1s, 2s, 4s, 8s — capping the number of attempts.
  • Do not retry 4xx (400, 401, 403, 404, 409, 422). Resolve the underlying issue — credentials, scope, or payload — before sending again.
  • Honor rate-limit headers. When you receive a 429, wait for the window to reset rather than hammering the endpoint.
async function requestWithRetry(url, init, maxAttempts = 4) {
  for (let attempt = 0; attempt < maxAttempts; attempt++) {
    const res = await fetch(url, init);

    // Retry only transient server errors and rate limits.
    if ((res.status >= 500 || res.status === 429) && attempt < maxAttempts - 1) {
      const backoff = 2 ** attempt * 1000 + Math.random() * 250; // jittered
      await new Promise((r) => setTimeout(r, backoff));
      continue;
    }

    return res; // success, or a non-retryable 4xx the caller should handle
  }
}
Because POSTcreates resources, design retried requests to be idempotent on your side (e.g. de-duplicate by an external reference) so a retried create after a network blip doesn't produce duplicates.
See the full Error Codes reference