Vox Gateway

에러 코드

에러 응답 형태 · HTTP 상태 코드 요약 · 전체 에러 코드 표.

요청의 성패는 HTTP 상태 코드로 알립니다. 2xx는 성공, 4xx는 보낸 정보로는 처리할 수 없었다는 뜻이고(대부분 error 코드가 함께 옵니다), 5xx는 우리 쪽 문제이거나 통신사·LiveKit 같은 외부 의존의 문제입니다.

에러 응답 형태

오류 본문은 평평한 봉투입니다. 코드는 항상 error 키에 있고, 진단에 필요한 값이 있으면 중첩 없이 같은 층에 함께 옵니다.

429 Too Many Requests
{ "error": "number_busy", "current": 1, "limit": 1 }

같은 층에 올 수 있는 키는 다음이 전부입니다. 어떤 코드에 무엇이 붙는지는 아래 에러 코드 표의 설명에 적혀 있습니다.

타입언제
errorstring항상. 무엇이 잘못됐는지. 값은 상태 코드별 응답 설명에 있습니다.
candidatesobject[]발신 번호를 골라야 할 때의 후보 (number_id · phone · workspace_name).
currentinteger동시통화 한도에 걸렸을 때 지금 진행 중인 통화 수.
end_reasonstring실제로 다이얼을 시도한 뒤 실패했을 때.
fieldstring필수 값이 빠졌을 때 그 필드 이름.
languagestring언어 전환을 거절했을 때 요청받은 언어.
limitinteger그때 걸린 한도 값.
maximuminteger아래 표의 코드 중 하나입니다.
messagestring본문 검증에 걸린 첫 항목을 한 줄로 옮긴 것.
providerstring언어 전환을 거절했을 때 그 통화가 쓰는 TTS 프로바이더.
reasonstring아래 표의 코드 중 하나입니다.
statusstring종료·옵션 변경을 거절했을 때 그 통화의 현재 상태.
supportedstring[]값이 허용 목록 밖일 때 그 목록.

/api/my/*조회 실패 404만 FastAPI 기본 봉투({"detail": "call not found"})를 씁니다. 같은 라우터라도 녹음 링크 거절은 error 봉투이고, /api/v1/*는 전부 error입니다. 중첩된 error.code 구조는 어디에도 없습니다.

HTTP 상태 코드

코드
200요청이 처리됐습니다.
201발신을 접수했습니다 — 통화는 비동기로 진행됩니다.
202종료·옵션 변경을 접수했습니다. 실제 반영은 그다음입니다.
400본문이나 값이 잘못됐습니다. 그대로 재시도하면 같은 결과입니다.
401자격증명이 없거나 무효합니다.
403자격증명은 유효하지만 그 자원에 권한이 없습니다.
404없거나, 내 것이 아닙니다 — 둘을 구분해 알려주지 않습니다.
409지금 상태에서는 할 수 없는 요청입니다. 재시도해도 대개 같습니다.
422값은 형식에 맞지만 설정·문맥과 맞지 않습니다.
429한도를 넘었습니다. 잠시 뒤 재시도하세요.
502외부 의존(LiveKit 등)이 일시적으로 실패했습니다 — 재시도할 만합니다.
503그 기능이 이 배포에 설정돼 있지 않거나 회선을 잡지 못했습니다.

발신 거절은 대부분 전화를 걸기 전에 납니다 — 그 경우 통화 기록도 요금도 생기지 않습니다. 실제로 다이얼한 뒤의 실패에는 end_reason이 함께 옵니다.

에러 코드

/api/v1/*가 낼 수 있는 코드 전부입니다. 알파벳순이고, 각 오퍼레이션 지면의 응답 스키마 (V1Error)에도 같은 목록이 실립니다.

errorHTTP
call_not_active409끊거나 옵션을 바꾸려는 통화가 진행 중이 아닙니다. 이미 끝났거나 아직 연결 전입니다 — 현재 status가 함께 옵니다.
call_not_found404그 통화가 없거나 내 번호의 통화가 아닙니다. 둘을 구분해 알려주지 않습니다.
concurrency_limit_platform_exceeded429플랫폼 전체 동시통화 한도를 넘었습니다. 잠시 뒤 재시도하세요. current·limit이 함께 옵니다.
concurrency_limit_workspace_exceeded429워크스페이스 동시통화 한도를 넘었습니다. current·limit이 함께 옵니다.
dispatch_failed503다이얼했지만 회선을 잡지 못했습니다. 실제로 시도한 결과라 end_reason이 함께 옵니다.
from_number_required422발신 번호를 지정하지 않았는데 접근 가능한 번호가 둘 이상입니다. candidates에서 하나를 골라 X-Number-Id로 다시 부르세요. OAuth 연결에서만 납니다.
hangup_failed502종료 신호 전송이 일시적으로 실패했습니다 — 재시도할 만합니다. 통화는 살아 있습니다.
hangup_unavailable503이 배포에 종료 기능이 설정돼 있지 않습니다.
invalid_api_key401Authorization 헤더가 없거나 Bearer가 아니거나 모르는 키입니다. 키를 재발급하면 이전 키는 즉시 무효가 됩니다.
invalid_language400지원하지 않는 통화 언어입니다. 지원 목록이 supported로 함께 옵니다.
invalid_max_duration_sec400최대 연결 시간은 60~1800초여야 합니다.
invalid_phone_format400착신번호가 국내형 010/070(11자리)도, 짧은 내선도 아닙니다. 국제번호는 지원하지 않습니다.
invalid_request_body400본문이 JSON이 아니거나 형식이 맞지 않습니다. 아는 옵션이 하나도 없거나, 값의 타입이 다르거나, 허용 밖 값일 때도 이 코드입니다. 이 엔드포인트가 아는 필드가 supported로, 검증에 걸린 첫 항목이 message로 함께 옵니다. 쿼리 파라미터가 범위를 벗어난 경우도 같습니다.
language_unavailable422통화 중 언어 전환 요청인데, 이 통화가 쓰는 TTS 프로바이더가 그 언어를 말할 수 없습니다. 통화 중에는 프로바이더를 바꿀 수 없어 전환만 거절되고 통화는 그대로 진행됩니다. 현재 프로바이더가 provider로 함께 옵니다.
max_duration_exceeds_policy400번호의 통화 정책 상한을 넘었습니다. maximum 이하로 요청하세요.
missing_required_field400필수 값이 비어 있습니다. 어느 필드인지가 field로 함께 옵니다.
no_agent_endpoint422자체 Agent를 바인딩했는데 chat URL이 비어 있습니다. 전화를 걸지 않고 거절합니다.
no_number_available422발신 가능한(배정된) 번호가 하나도 없습니다. OAuth 연결에서만 납니다.
number_busy429이 번호의 동시통화 한도를 넘었거나(current·limit 동반), 다이얼했더니 상대가 통화 중이었습니다(end_reason 동반). 함께 오는 키로 두 경우를 가릅니다.
number_not_allowed403지정한 번호에 접근 권한이 없습니다. OAuth 연결에서만 납니다.
number_not_found404다이얼했더니 없는 번호였습니다. end_reason이 함께 옵니다.
options_failed502통화 옵션 변경 신호를 보내지 못했습니다 — 일시적이라 재시도할 수 있습니다. 통화는 살아 있습니다.
options_unavailable503통화 옵션 기능이 이 배포에 설정돼 있지 않습니다.
range_not_satisfiable416요청한 녹음 바이트 범위를 제공할 수 없습니다.
recording_not_available409녹음 파일을 받을 수 없습니다. reason은 pending(준비 중), none(없음), failed(실패)입니다.
recording_storage_error502녹음 저장소에서 파일을 가져오지 못했습니다.
recording_unavailable503이 배포에 녹음 저장소가 설정되지 않았습니다.
room_unknown409종료·옵션 변경 신호를 보낼 통화 세션을 찾지 못했습니다. 수신 통화에서 gateway가 재시작된 뒤 납니다. 통화는 살아 있습니다.
workspace_inactive403번호가 워크스페이스에 배정돼 있지 않거나 워크스페이스가 비활성 상태입니다.
  • 종료·옵션 변경 거절은 통화를 죽이지 않습니다. call_not_active · room_unknown · hangup_failed · options_failed 어느 쪽이든 통화는 살아 있으니, 사유를 받고 대화를 이어가세요.
  • 202접수이지 적용이 아닙니다 — 통화 옵션은 Get Calloptions_pending으로 반영을 확인하세요.
  • 통화가 어떻게 끝났는지는 오류가 아니라 통화 객체의 값입니다 — Get Callend_reason을 보세요.

엔드포인트별로 어떤 코드가 나는지는 적지 않습니다 — 코드가 늘 때마다 두 곳을 고쳐야 하고, 실제로 한쪽이 부분집합인 채로 남은 적이 있습니다.

On this page