OPWS Developers

에러 (Errors)

모든 SDK 에러는 추상 클래스 OpenEchoError를 상속하며, 서버 wire 코드(err.code)와 err.httpStatus·err.message를 항상 보존합니다.

ts
import {
  OpenEchoError, CapabilityDenied, UsageCapExceeded, OriginForbidden,
} from "@openecho/partner-sdk";

try {
  await oe.broadcast.tts.send({ /* ... */ });
} catch (err) {
  if (err instanceof CapabilityDenied) {
    // TTS capability 미허가
  } else if (err instanceof UsageCapExceeded) {
    // 일일 quota 초과
  } else if (err instanceof OpenEchoError) {
    console.error(err.code, err.httpStatus, err.message);
  }
}

서버 wire 에러 (14)

서버 wire 코드와 SDK 에러 클래스의 완전한 대응입니다. HTTP 상태는 대표값이며, 실제 값은 서버 응답을 그대로 보존합니다.

코드HTTP클래스설명
PARTNER_UNAUTHORIZED401UnauthorizedpublicKey 무효 또는 거부
PARTNER_TICKET_UNAUTHORIZED401TicketUnauthorizedSSE 스트림 티켓 인증 실패
PARTNER_ORIGIN_FORBIDDEN403OriginForbidden허용되지 않은 origin — 도메인 잠금
CAPABILITY_DENIED403CapabilityDenied해당 기능 capability 미허가
TARGET_UNRESOLVED404TargetUnresolvedtargetHandle을 해석할 수 없음
BROADCAST_CONTENT_NOT_READY400ContentNotReady오디오 준비가 완료되지 않은 항목
BROADCAST_INELIGIBLE409BroadcastIneligible현재 방송 불가 상태(동시 방송 등)
IDEMPOTENCY_KEY_REUSED409IdempotencyKeyReused동일 키가 다른 페이로드로 재사용됨
TARGET_REVISION_STALE409TargetRevisionStale대상 revision 변경 — expectedRevision 갱신 필요
STREAM_GONE410SessionExpiredSSE 세션 만료(이벤트 보존 기간 초과)
USAGE_CAP_EXCEEDED429UsageCapExceeded일일 TTS quota 초과
RATE_LIMITED429RateLimited요청 속도 제한 초과
STREAM_LIMIT_EXCEEDED429StreamLimitExceededSSE 동시 스트림 수 한도 초과
RATE_LIMIT_BACKEND_UNAVAILABLE503RateLimitBackendUnavailable속도 제한 백엔드 일시 불가

auth 에러는 정확한 타입으로 노출됩니다

잘못된 키(401)·미등록 origin(403)·티켓 인증 실패(401)는 각각 Unauthorized·OriginForbidden·TicketUnauthorized로 매핑되며 서버 메시지를 보존합니다. UnknownOpenEchoError로 퇴화하지 않습니다.

클라이언트 측 에러 (3)

다음 세 에러는 서버 wire 코드가 아니라 클라이언트/transport 계층에서 발생하므로 wire 표에 없습니다.

클래스발생 시점의미
MicChunkLoadFailedmic.start()MIC 청크 다운로드 실패 — 네트워크 오류 또는 CSP 차단(script-src 확인)
GatewayMasked모든 호출게이트웨이가 2xx + HTML로 4xx를 마스킹(GATEWAY_MASKED)
InvalidApiResponse모든 호출2xx 응답이 JSON이 아님(INVALID_API_RESPONSE)

멱등성 키

idempotencyKey는 중복 방송을 막는 클라이언트 생성 키입니다.

  • 새 방송마다 crypto.randomUUID()로 고유 키를 생성합니다.
  • 네트워크 오류로 재시도할 때는 동일한 키를 재사용합니다(서버가 멱등 처리).
  • 다른 페이로드에 같은 키를 재사용하면 IdempotencyKeyReused(409)가 발생합니다.

Quota · Rate Limit

파트너 앱별 일일 TTS 한도 초과 시 UsageCapExceeded(429)가 발생하며 다음 날 자정(UTC)에 초기화됩니다. 단시간 과도 요청은 RateLimited(429) — 지수 백오프로 재시도합니다. RateLimitBackendUnavailable(503)은 잠시 후 재시도합니다.

Origin 잠금 진단

도메인 잠금(OriginForbidden)은 두 단계로 확인합니다.

  1. 브라우저 CORS 차단 — 미등록 origin은 preflight에서 차단됩니다. DevTools → Network에서 CORS error 확인. 해결: 관리 콘솔에서 origin 추가.
  2. curl로 wire error 확인 — CORS를 우회해 실제 error.code를 확인합니다.
bash
curl -s -X POST "https://your-openecho-api.example.com/api/partner/v1/broadcasts/tts" \
  -H "X-OpenEcho-Key: pk_test_..." \
  -H "Content-Type: application/json" \
  -H "Origin: https://not-registered.example.com" \
  -d '{"targetHandle":"grp_main","text":"test","language":"ko","idempotencyKey":"k","partial":false}'

Unauthorized(키 오류)와 OriginForbidden(도메인 잠금)은 별개입니다. 응답 error.code로 정확히 구분하세요.

CloudFront /api 마스킹 주의

dev 환경에서 CloudFront는 /api/* 4xx를 SPA index.html(HTTP 200)로 치환할 수 있습니다. 이때 SDK는 null 대신 명시적으로 throw합니다.

  • 2xx + HTMLGatewayMasked
  • 2xx + 비-JSONInvalidApiResponse

운영 환경에서는 CloudFront SPA 오류 응답을 /api/*에서 제외해 이 문제가 발생하지 않아야 합니다.