최종 업데이트
오류
2xx가 아닌 모든 응답은 같은 네 필드를 가진 JSON 오류 형식입니다. code로 분기하고, message는 사람에게 보여 주고, requestId는 로그에 남기고, retryable이 true일 때만 재시도하세요.
오류 형식
429 Too Many Requests
{ "code": "rate_limit_exceeded", "message": "API key rate limit exceeded.", "requestId": "3f2b6c1e-8a4d-4f0e-9b7a-2d5c1e6f8a90", "retryable": true}| 필드 | 유형 | 의미 |
|---|---|---|
code | string | snake_case로 된 안정적이고 기계가 읽을 수 있는 식별자입니다. message가 아니라 반드시 이 값으로 분기하세요. |
message | string | 사람이 읽을 수 있는 영어 설명입니다. 운영자에게 보여 줘도 안전하지만 문구는 바뀔 수 있습니다. |
requestId | string | 서버가 생성한 요청의 UUID입니다. 지원팀에 문의할 때 함께 알려 주세요. 저희 로그에서 요청을 찾을 수 있는 유일한 방법입니다. |
retryable | boolean | 같은 요청을 변경 없이 나중에 다시 보내면 성공할 수 있을 때(속도 제한, 일시적 장애) true입니다. 그 밖의 경우에는 요청을 바꿔야 합니다. |
상태 코드도 여전히 중요합니다
HTTP 상태는 대략적인 분류(4xx는 클라이언트 쪽, 5xx는 저희 쪽)이고,
code는 세부 원인입니다. 상태만 확인하는 클라이언트는 스코프가 없는 경우와 요금제에 모듈이 없는 경우(둘 다 403)를 구분할 수 없습니다.오류 처리
아래 패턴은 RoomScope 대시보드가 직접 사용하는 방식입니다. 오류 형식을 파싱하고, 본문이 JSON이 아니면 http_error로 대체하며, 서버가 재시도 가능하다고 표시한 오류만 지수 백오프로 재시도합니다.
class ApiError extends Error { constructor(status, { code, message, requestId, retryable }) { super(message); Object.assign(this, { status, code, requestId, retryable: Boolean(retryable) }); }} async function call(path, init) { const res = await fetch(`https://api.toktokdata.live${path}`, init); if (res.ok) return res.status === 204 ? undefined : res.json(); let envelope = {}; try { envelope = await res.json(); } catch {} throw new ApiError(res.status, { code: "http_error", message: `Request failed (${res.status})`, ...envelope });} // Retry only when the server says so.async function withRetry(fn, attempts = 3) { for (let i = 0; ; i++) { try { return await fn(); } catch (e) { if (!(e instanceof ApiError) || !e.retryable || i === attempts - 1) throw e; await new Promise((r) => setTimeout(r, 500 * 2 ** i)); } }}상태별 코드
코드는 안정적이지만 새 코드가 추가될 수 있으므로, 알 수 없는 코드는 상태에 따라 처리하세요. 레퍼런스의 각 엔드포인트에 반환될 수 있는 코드가 나와 있습니다.
| 상태 | 코드 | 발생 조건 | 재시도 가능 |
|---|---|---|---|
| 400 | validation_error | 본문 또는 파라미터 형식이 잘못되었습니다. message에 해당 필드 이름이 표시됩니다. | 아니요 |
| 400 | invalid_rankings_input | 랭킹: board가 없거나, 값이 128자를 넘거나, limit, leagueTier, period 또는 liveOnly 값이 잘못되었습니다. | 아니요 |
| 400 | invalid_cursor · invalid_region · invalid_trend_type | 엔드포인트가 받지 않는 cursor, region(insights에서는 두 글자) 또는 트렌드 유형입니다. | 아니요 |
| 400 | invalid_live_history_input · invalid_alert_input · invalid_dataset · invalid_format | 엔드포인트별 입력 오류입니다. 무엇을 고쳐야 하는지 message에 나와 있습니다. | 아니요 |
| 401 | unauthorized | key가 없거나, 형식이 잘못되었거나, 알 수 없거나, 폐기 또는 만료되었거나, 워크스페이스가 비활성 상태입니다. WWW-Authenticate: Bearer와 함께 전송됩니다. | 아니요 |
| 402 | credit_cap_exceeded | 이 요청을 처리하면 해당 기간의 사용량이 크레딧 한도를 넘게 됩니다. | 아니요 |
| 403 | insufficient_scope | key에 필요한 스코프가 없거나, 대시보드 전용 경로입니다. | 아니요 |
| 403 | module_not_entitled | 워크스페이스 요금제에 LIVE 또는 조회 모듈이 포함되어 있지 않습니다. | 아니요 |
| 403 | export_format_not_entitled | 요금제에 해당 내보내기 형식이 포함되어 있지 않습니다. | 아니요 |
| 404 | not_found | 메서드와 경로에 일치하는 경로가 없습니다. | 아니요 |
| 404 | creator_not_found · video_not_found · live_session_not_found · alert_not_found · export_not_found | 리소스가 존재하지 않거나 다른 워크스페이스에 속해 있습니다. | 아니요 |
| 409 | export_not_ready · api_key_limit_reached | 내보내기를 아직 생성하는 중이거나, 요금제의 key 개수 한도에 도달했습니다. | 아니요 |
| 429 | rate_limit_exceeded | key가 초당 요청 수를 초과했습니다. Retry-After를 따르세요. | 예 |
| 429 | daily_quota_exceeded | key가 일일 할당량을 모두 사용했습니다. Retry-After는 UTC 자정까지 남은 시간입니다. | 예 |
| 503 | rate_limit_unavailable · metering_unavailable · webhook_unavailable | 의존하는 서비스가 중단되었습니다. 백오프를 적용해 재시도하세요. | 예 |
| 500 | internal_error | 저희 쪽에서 문제가 발생했습니다. 백오프를 적용해 재시도하고, 문의할 때는 requestId를 함께 알려 주세요. | 예 |
오류가 아닌 경우
- 랭킹에서 알 수 없거나 지원되지 않는
region은 오류가 아닙니다. 응답은200이며publishable: false, 빈entries목록, 그리고 이유를 설명하는provenance가 함께 반환됩니다. - 수집 중인 팔로잉, 팔로워, 댓글은
202와 함께status: "collecting",jobId,Retry-After헤더를 반환합니다. 그 초만큼 기다린 뒤 다시 호출하세요.
속도 제한은 별도 페이지에서 다룹니다: 속도 제한.
이 페이지가 도움이 되었나요?