본문으로 건너뛰기

에러 코드

봇 API 는 실패를 HTTP 상태 코드와 detailCode 로 알려줘요. 같은 상태 코드라도 대처가 다른 경우가 있으니 detailCode 까지 보고 분기해요.

detailCode 가 없는 응답도 있어요. 토큰 · 권한 · 호출 한도는 앞단 게이트웨이가 먼저 검사해서, 여기서 막힌 401 · 403 · 429 에는 detailCode 가 없어요. 먼저 상태 코드로 가르고, detailCode 는 있을 때만 보세요.

응답 형식​

봇 런타임 API 는 RFC 7807 형식으로 응답해요.

{
"instance": "/v1/live",
"status": 404,
"title": "Not Found",
"detailCode": "OAPI_MNGR_0301",
"message": "The DJ is not broadcasting right now.",
"userId": null,
"extra": null,
"timestamp": 1788407119681
}
필드설명
detailCode대처를 정하는 값이에요. 이 값이 계약이에요.
message사람이 읽는 설명이에요. 문구는 바뀔 수 있으니 이 값으로 분기하지 마세요. 서비스 언어와 일치한다는 보장도 없으니 청취자에게 그대로 보여주지 말고, 노출 문구는 봇에서 만들어요.
statusHTTP 상태 코드예요.
titleHTTP 상태의 표준 문구예요 (Not Found · Forbidden …). 분기에 쓰지 마세요.
instance요청한 경로예요.
userId · extra사내 프레임워크가 채우는 자리예요. 봇 런타임 API 에서는 항상 null 로 실려 나가요.
timestamp응답을 만든 시각이에요. epoch milliseconds 예요.

userId · extra 는 봇이 쓸 값이 아니에요. 다만 null 로라도 응답에 들어 있으니, 스키마를 additionalProperties: false 로 잠그면 여기서 깨져요. 모르는 필드는 무시하도록 두세요.

이벤트 스트림의 오류는 SSE 프레임으로 와요. GET /v1/live/events 는 text/event-stream 으로 응답하기 때문에, 연결에 실패해도 본문이 data: 로 시작해요. 본문을 그대로 JSON 파싱하면 터져요. HTTP 상태 코드로 판별하고, 본문이 필요하면 data: 를 떼고 파싱해요.

HTTP/2 404
content-type: text/event-stream;charset=UTF-8

data:{"status":404,"detailCode":"OAPI_MNGR_0301","message":"The DJ is not broadcasting right now."}

봇이 마주치는 코드​

/v1/oauth 로 시작하는 둘을 뺀 모든 엔드포인트에서 나오는 코드예요. 어떤 엔드포인트가 있는지는 엔드포인트 목록 에 있어요.

400 — 요청을 고쳐야 해요​

detailCode무슨 일인가요어떻게 하나요
OAPI_MNGR_0103요청이 잘못됐어요. 본문이 깨졌거나, 필수 필드·Content-Type 이 빠졌거나, 메서드가 잘못됐어요.요청 형식을 고쳐요. 같은 요청을 다시 보내도 결과가 같아요.
OAPI_MNGR_0108메시지가 비어 있어요. 공백만 있는 경우도 포함해요.보낼 내용을 확인해요. 같은 요청을 다시 보내도 결과가 같아요.
OAPI_MNGR_0109메시지가 200자를 넘었어요. 이모지는 2자로 세어질 수 있어요.길이를 줄여요.

401 — 사람이 다시 연동해야 해요​

detailCode무슨 일인가요어떻게 하나요
없음토큰이 없거나 무효해요. 만료 · 폐기 · DJ 의 연동 해제 · 앱 정지가 모두 여기예요.refresh 를 한 번 시도하고, 그래도 401 이면 멈추고 DJ 에게 재연동을 안내해요.
OAPI_MNGR_0203위와 같아요. 토큰이 폐기된 직후 1분 안에는 이 코드로 올 수 있어요.위와 같아요.

401 에 무한 재시도하지 마세요. 연동이 끊긴 상태에서는 몇 번을 다시 보내도 계속 실패하면서 호출 한도만 소진해요.

이유를 나눠서 알려주지 않는 이유는, 나누면 토큰이 존재하는지 여부가 밖으로 새기 때문이에요. 봇의 대처는 어느 경우든 재연동으로 같아요.

403 — 권한이나 상태 때문에 막혔어요​

detailCode무슨 일인가요어떻게 하나요
없음이 엔드포인트에 필요한 권한이 없어요.재동의만 받으면 돼요. 연동 자체는 살아 있어요.
OAPI_MNGR_0208지금은 이 방송에 채팅을 보낼 수 없어요. 채팅이 동결됐거나 봇이 채팅 금지 상태예요.두 경우가 구분되지 않아요. 잠시 뒤 다시 시도하고, 계속 막히면 DJ 에게 안내해요.
OAPI_MNGR_0209방송에 입장할 수 없어요. DJ 가 봇을 차단했을 수 있어요.재동의로도 재연동으로도 풀리지 않아요. DJ 가 직접 풀어줘야 해요.

403 은 detailCode 유무로 갈라요. 없으면 권한 부족, 있으면 방송 쪽 상태(0208 · 0209)예요.

401 과 403 을 뭉뚱그리지 마세요. 401 은 DJ 가 처음부터 다시 연동해야 하고, 권한 부족 403 은 권한만 추가로 받으면 돼요. 같이 처리하면 멀쩡한 연동을 끊게 돼요.

404 — 방송 중이 아니에요​

detailCode무슨 일인가요어떻게 하나요
OAPI_MNGR_0301DJ 가 지금 방송 중이 아니에요.오류가 아니라 상태예요. 이벤트 스트림이면 백오프 후 다시 연결하고, 조회면 잠시 뒤 다시 불러요.

429 — 너무 자주 불렀어요​

detailCode무슨 일인가요어떻게 하나요
OAPI_MNGR_0302채팅 전송이 너무 잦아요.잠시 기다렸다 다시 보내요.

OAPI_MNGR_0302 는 봇이 과하게 보냈을 때뿐 아니라 그 방송의 채팅이 전체적으로 몰릴 때도 와요. 한도를 방송 전체가 나눠 쓰기 때문에, 봇 자신의 속도를 줄여도 바로 풀리지 않을 수 있어요.

detailCode 없이 429 만 오는 경우는 API 호출 한도예요. 이때는 본문이 비어 있어요. 본문을 파싱하면 터지니 상태 코드로만 판별하세요. 한도는 두 가지예요.

한도넘으면다시 부를 때
초당429, 본문·Retry-After 없음지수 백오프로 다시 시도해요.
하루429, 본문 없음 · Retry-After 있음Retry-After 초만큼 기다려요. 다음 리셋(자정)까지예요.

하루 한도는 앱 총량과 권한별로 따로 세고, 둘 중 하나라도 넘으면 막혀요. 어느 쪽에 걸렸는지는 x-ratelimit-daily-scope 헤더로 와요 — 있으면 그 권한만, 없으면 앱 전체가 막힌 거예요.

응답 헤더로 미리 속도를 줄여요​

한도 헤더는 정상 응답에도 붙어요. 429 를 맞기 전에 이 값을 보고 속도를 줄이세요.

헤더뜻
x-ratelimit-remaining지금 남은 초당 토큰이에요. 0 이면 다음 요청이 429 예요.
x-ratelimit-replenish-rate초당 채워지는 토큰 수예요.
x-ratelimit-burst-capacity순간에 몰아 쓸 수 있는 상한이에요.
x-ratelimit-daily-limit하루 호출 상한이에요.
x-ratelimit-daily-remaining오늘 남은 호출 수예요.
x-ratelimit-daily-reset다음 리셋 시각이에요. epoch seconds 예요.
x-ratelimit-daily-scope하루 한도 429 에만 와요. 걸린 권한이에요.

이벤트 스트림(GET /v1/live/events)에는 한도 헤더가 없어요 — 이 경로는 호출 한도를 세지 않아요. 초당 한도는 DJ 연동마다 따로이고, 하루 한도는 앱 합산이에요. 연동을 늘려도 하루 총량은 커지지 않아요. 오늘 사용량은 개발자 센터 콘솔의 앱 상세에서도 볼 수 있어요.

500 — 서버 오류예요​

detailCode무슨 일인가요어떻게 하나요
OAPI_MNGR_1002서버 오류예요.지수 백오프로 재시도해요. 요청을 고쳐도 달라지지 않아요.

어느 엔드포인트에서든 날 수 있어요. 502(OAPI_MNGR_2302 · OAPI_MNGR_2303)와 달리 어디서 났는지 알려주지 않으니, 봇이 할 일은 지수 백오프 재시도 하나예요.

502 — 잠시 후 다시 시도해요​

detailCode무슨 일인가요어떻게 하나요
OAPI_MNGR_2302방송 서버 오류예요.지수 백오프로 재시도해요.
OAPI_MNGR_2303채팅 서버 오류예요.지수 백오프로 재시도해요.

토큰 엔드포인트의 에러는 형식이 달라요​

POST /v1/oauth/token 과 POST /v1/oauth/revoke 는 OAuth 표준(RFC 6749) 형식을 그대로 써요. detailCode 가 아니라 error 예요. 전체 명세는 토큰 에 있어요.

{
"error": "invalid_grant",
"error_description": "code is expired"
}
errorHTTP무슨 일인가요어떻게 하나요
invalid_request400필수 파라미터가 빠졌어요.요청 형식을 확인해요.
invalid_client401Client ID 나 Client Secret 이 맞지 않아요.자격 증명을 확인해요.
invalid_grant400code 나 refresh_token 이 만료됐거나 이미 썼어요.code 는 60초 안에 써야 해요. refresh_token 이 만료됐으면 DJ 에게 재연동을 안내해요.
unsupported_grant_type400지원하지 않는 grant_type 이에요.authorization_code 또는 refresh_token 을 써요.

관련 문서​