API는 현재 베타 버전이에요. 일부 기능이 변경될 수 있어요.
기본 정보
Base URL
https://chzzk-bot.ddutto.com/api/v1
요청 형식
- 모든 요청은 HTTPS를 사용해요.
- 인증이 필요한 요청은
Authorization헤더에 API 키를 포함해야 해요.
Authorization: DDUBOT_API <URL 인코딩한 api_key>
API 키는 한글이라 인코딩이 필요해요
키가 한글 256자라서 HTTP 헤더에 그대로 실을 수 없어요. 퍼센트 인코딩 해서 보내세요.
- JavaScript:
'DDUBOT_API ' + encodeURIComponent(apiKey) - Python:
'DDUBOT_API ' + urllib.parse.quote(api_key) - cURL: 미리 인코딩한 문자열을 붙여넣기
응답 형식
모든 응답은 JSON 형식으로 반환돼요.
성공 응답 예시:
{
"success": true,
"data": { }
}
성공 응답의 본문 키는 엔드포인트마다 다릅니다. 대부분 data 지만 /roulette 만 roulettes 예요.
| 엔드포인트 | 본문 키 | 최상위에 함께 오는 것 |
|---|---|---|
/roulette | roulettes | — |
/roulette/logs | data | pagination |
/karaoke · /song-requests | data | eventTimestamp |
/attendances · /user_info | data | — |
오류 응답 예시:
{
"success": false,
"data": {
"error": "오류 메시지"
}
}
오류 메시지는 data 안에 있어요
오류는 항상 data.error 입니다. response.error 가 아니라 response.data.error 를 읽으셔야 해요.
(성공 응답의 본문 키는 위 표처럼 엔드포인트마다 다르지만, 오류만은 어디서나 data.error 로 통일돼 있어요.)
const res = await fetch(url, { headers });
const json = await res.json();
if (!json.success) console.error(json.data.error); // ← 여기
오류 코드
| 상태 | 의미 | data.error 메시지 |
|---|---|---|
400 | 인증 실패 또는 요청 파라미터 오류 | 인증 실패는 잘못된 접근입니다. · 파라미터 오류는 항목별 안내 |
403 | 해당 scope 권한이 없음 | 권한이 없습니다. 'read.roulette' scope가 필요합니다. |
429 | 호출 제한 초과 | 요청 횟수 제한을 초과했습니다. N초 후에 다시 시도해주세요. |
500 | 서버 오류 | 서버 오류가 발생했습니다. |
400이 나올 때 — 메시지부터 보세요
메시지가 잘못된 접근입니다. 인지 아닌지로 원인이 갈립니다.
잘못된 접근입니다. 라면 인증 문제예요. 보안상 "헤더가 없음"과 "키가 틀림"을 구분해서 알려주지 않아요.
- 키를 URL 인코딩했는지 — 한글 키를 그대로 넣으면 반드시 실패해요
Authorization헤더가DDUBOT_API로 시작하는지- 키를 복사할 때 앞뒤 공백이 섞이지 않았는지
다른 메시지라면 키는 정상이고 요청 파라미터가 잘못된 거예요. 인증을 통과한 뒤의 검증 실패도 같은 400 을 씁니다.
| 메시지 | 원인 |
|---|---|
잘못된 룰렛 UUID 형식입니다. | uuid 가 UUID 형식이 아님 |
page는 1 이상의 정수여야 합니다. | page 값 오류 |
limit는 최대 50까지 가능합니다. | limit 이 50 초과 |
page가 범위를 초과했습니다. | 마지막 페이지를 넘김 |
viewer_uid와 viewer_nickname은 함께 사용할 수 없습니다. | /user_info 에 두 조건을 동시 지정 |
사용 가능한 API
| 엔드포인트 | 메서드 | 설명 | 필요 권한 |
|---|---|---|---|
/roulette | GET | 룰렛 목록 조회 | read.roulette |
/roulette/logs | GET | 룰렛 로그 조회 | read.roulette |
/song-requests | GET | 신청곡 대기열 조회 | read.song-request |
/karaoke | GET | 노래방 대기열/완료 목록 조회 | read.karaoke |
/attendances | GET | 시청자 출석 집계 조회 | read.attendance |
/user_info | GET | 시청자 정보 조회 | read.viewer_info |
Rate Limiting
제한은 두 겹으로 걸려 있어요. 둘 중 하나라도 걸리면 429 가 반환돼요.
| 기준 | 제한 | 설명 |
|---|---|---|
| 계정(채널) | 분당 15회 | 실질적인 제한. 보통 이쪽에 먼저 걸려요. 같은 계정에서 키를 여러 개 발급해도 15회를 함께 나눠 씁니다 |
| IP 주소 | 분당 60회 | 같은 IP에서 여러 계정의 키를 돌려 써도 이 상한을 넘을 수 없어요 |
응답 헤더에서 Rate Limit 정보를 확인할 수 있어요. 단 200 · 403 · 429 에만 붙어요. 400(인증 실패·파라미터 오류)과 500 에는 이 헤더가 없어요.
| 헤더 | 설명 |
|---|---|
X-RateLimit-Limit | 분당 최대 요청 수. 보통 15 이지만, IP 제한에 걸린 429 에서는 60 이 와요 |
X-RateLimit-Remaining | 남은 요청 수 |
X-RateLimit-Reset | 제한 초기화 시각 (밀리초 단위 Unix 타임스탬프) |
Retry-After | 429일 때만. 몇 초 뒤 재시도하면 되는지 |
X-RateLimit-Reset 은 밀리초예요
초 단위가 아니라 밀리초예요. JavaScript라면 new Date(Number(reset)) 로 바로 쓸 수 있지만,
Python 등에서는 1000 으로 나눠야 해요.
폴링 주기는 5초 이상으로
분당 15회면 평균 4초에 한 번입니다. 여유를 두고 5~10초 간격으로 부르시는 걸 권해요.
429를 받으면 Retry-After 초만큼 기다렸다 다시 시도하도록 만들어두면 안전해요.
다음 단계
API를 사용하려면 먼저 인증 설정이 필요해요.