Errors

Status codes and the consistent error response shape.

Vocenza uses conventional HTTP status codes and returns a consistent JSON error body. On the Realtime API, the same shape arrives as an error event.

{
  "error": {
    "type": "invalid_request",
    "message": "Field 'input' is required.",
    "param": "input"
  }
}

Status codes

StatustypeMeaning
400invalid_requestA parameter is missing or malformed.
401authentication_errorMissing or invalid API key.
403permission_errorKey revoked, or model not enabled for the project.
404not_foundResource (voice, file, session) does not exist.
413payload_too_largeAudio or text exceeds the size limit.
429rate_limitToo many requests — back off and retry.
500server_errorSomething failed on our side. Safe to retry.
503overloadedTemporary capacity issue. Retry with backoff.

Retries

Retries are safe on 429, 500, 502, 503, and 504. Use exponential backoff with jitter and cap attempts.

retry.ts
async function withRetry<T>(fn: () => Promise<T>, attempts = 4): Promise<T> {
  for (let i = 0; i < attempts; i++) {
    try {
      return await fn();
    } catch (err) {
      const status = (err as { status?: number }).status;
      const retryable = status && [429, 500, 502, 503, 504].includes(status);
      if (!retryable || i === attempts - 1) throw err;
      await new Promise((r) => setTimeout(r, 2 ** i * 250 + Math.random() * 100));
    }
  }
  throw new Error("unreachable");
}

Respect Retry-After

On 429, honor the Retry-After response header when present — it tells you exactly how long to wait before the next attempt.