Scope contract notice: API key scopes are enforced for public routes; see Scope reference for required grants.

Error Handling

API errors use a stable JSON envelope so integrations can branch on status and code.

Error Envelope

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Request validation failed",
    "details": {},
    "requestId": "req_123"
  }
}

code and message are required. details and requestId are optional. Use code for programmatic handling; treat message as human-readable text that may change.

Every response includes an X-Request-Id header. Error envelopes include the same value in error.requestId. Include this value when contacting support so VoiceAgent can correlate the failed request with logs and Sentry events. You may send your own X-Request-Id header; VoiceAgent will return the same value.

Status Codes

VoiceAgent follows the ADR-011 status-code catalog. Common partner-facing statuses are:

Status Meaning
400 The request is malformed, unparsable, or missing required transport material.
401 Authentication is missing, invalid, expired, or rejected.
403 The caller is authenticated but is not allowed to perform the operation.
404 The addressed resource does not exist in the caller's workspace scope.
422 The request parsed, but a domain rule or semantic precondition failed.
429 A rate limit or quota rejected the request.
500 An unexpected server failure occurred.
503 A dependency, configured capability, or transient service capacity is unavailable.

Handling Pattern

async function voiceagent(path, options = {}) {
  const response = await fetch(`https://api.voiceagent.example/api/v1${path}`, {
    ...options,
    headers: {
      Authorization: `Bearer ${process.env.VOICEAGENT_API_KEY}`,
      "Content-Type": "application/json",
      ...options.headers,
    },
  });

  const body = await response.json().catch(() => ({}));

  if (!response.ok) {
    const error = body.error ?? {
      code: "UNKNOWN_ERROR",
      message: "VoiceAgent request failed",
    };

    if (response.status === 401) {
      throw new Error("Check VOICEAGENT_API_KEY");
    }

    if (response.status === 429) {
      const retryAfter = response.headers.get("Retry-After");
      throw new Error(`Rate limited. Retry after ${retryAfter ?? "a short delay"}`);
    }

    throw new Error(`${response.status} ${error.code}: ${error.message}`);
  }

  return body;
}

Validation Details

Validation failures may include structured details. Do not depend on every endpoint returning the same details shape; use it for logs and developer diagnostics.