오류 및 요청 한도
모든 엔드포인트는 기계 판독용 코드와 요청 ID를 포함한 동일한 구조로 실패를 보고합니다.
오류 응답
호출이 실패하면 success: false가 반환됩니다. code는 프로그램에서 쓰도록 고정된 값이고, error는 사람이 읽기 위한 짧은 영문 메시지이며, request_id는 당사 로그에서 해당 호출을 식별합니다. 입력값에 문제가 있을 때는 param에 문제가 된 파라미터 이름이 들어갑니다.
실제 예시
이 페이지를 렌더링할 때 API에서 가져온 실시간 응답입니다.
{
"success": false,
"error": "coin required",
"code": "INVALID_PARAM",
"request_id": "cb-mwefroqs-bac74b6fc2"
}{
"success": false,
"code": "NOT_FOUND",
"error": "unknown endpoint: GET /api/this-endpoint-does-not-exist",
"request_id": "cb-mwefroqt-0f86946c0f"
}오류 코드
| 코드 | HTTP | 의미 | 대응 방법 |
|---|---|---|---|
| INVALID_PARAM | 400 | 필수 파라미터가 누락되었거나 허용되지 않는 값입니다. 문제가 된 파라미터를 알 수 있으면 `param`에 그 이름이 들어갑니다. | 그대로 재시도하지 말고 요청을 수정하십시오. |
| UNAUTHORIZED | 401 | `CB-API-KEY` 헤더를 보냈지만 알 수 없거나 폐기된 키입니다. 공개 데이터에는 키가 필요 없으므로 헤더를 빼거나 유효한 키를 사용하십시오. | 그대로 재시도하지 마십시오. |
| FORBIDDEN | 403 | 해당 경로는 공개 API에 포함되지 않습니다(내부용 또는 계정 전용). | 재시도하지 마십시오. |
| NOT_FOUND | 404 | 알 수 없는 경로이거나, 요청한 코인 / 거래소 / 펀드가 존재하지 않습니다. | 재시도하지 말고 경로와 식별자를 카탈로그와 대조해 확인하십시오. |
| RATE_LIMITED | 429 | 요청 수가 분당 한도를 초과했습니다. `Retry-After`가 대기해야 할 초를 알려 줍니다. | `Retry-After`만큼 기다린 뒤 백오프를 적용해 재시도하십시오. |
| INTERNAL | 500 | 예기치 않은 서버 오류입니다. 메시지는 의도적으로 일반적인 내용만 담습니다. 신고할 때 `request_id`를 인용하십시오. | 몇 초 뒤 한 번 재시도하고, 계속되면 요청 ID와 함께 신고하십시오. |
| UPSTREAM_FAILED | 503 | 이 엔드포인트의 데이터 소스가 제시간에 응답하지 않았습니다. 그 대신 만료된 수치나 대체 수치를 반환하는 일은 없습니다. | 백오프를 적용해 재시도하고 상태 페이지를 확인하십시오. |
| UNAVAILABLE | 501 / 503 | 데이터셋이 일시적으로 준비되지 않았거나(캐시 워밍 중) 엔드포인트에 아직 합법적인 공개 소스가 없습니다. | 나중에 재시도하십시오. 설계상 사용 불가인 엔드포인트는 카탈로그에 표시되어 있습니다. |
| REQUEST_FAILED | 200 | 일부 이전 엔드포인트는 HTTP 200에 `success: false`로 응답합니다. HTTP 상태만 보지 말고 항상 `success`를 확인하십시오. | 메시지에 따라 다릅니다. 실패한 요청으로 처리하십시오. |
요청 ID
모든 응답에는 X-Request-Id 헤더가 포함됩니다. 실패한 응답은 본문의 request_id에도 같은 값을 담습니다. 짧은 엣지 캐시에서 제공된 응답은 그 응답을 생성한 요청의 ID를 그대로 반환하므로, 연속 호출에서 ID가 같다면 캐시된 사본을 받았다는 뜻입니다.
요청 한도
한도는 분 단위로 적용되며, 익명 호출은 IP 주소별로, 유효한 CB-API-KEY 헤더를 보낸 경우에는 키별로 집계됩니다. 한도는 분당 1200회입니다. /api/coin-icon 아래의 아이콘 요청은 집계하지 않습니다.
요청 한도 헤더
| 이름 | 설명 |
|---|---|
| X-Request-Id | 이 요청의 식별자. 버그 신고 시 함께 알려 주십시오. |
| X-RateLimit-Limit | 현재 1분 구간에 허용되는 요청 수. |
| X-RateLimit-Remaining | 현재 구간에 남은 요청 수. |
| X-RateLimit-Reset | 구간이 초기화되는 Unix 시각(초). |
| Retry-After | HTTP 429와 함께 전송: 재시도 전 대기해야 하는 초. |
| X-Cache | 서버 측 응답 캐시의 HIT, STALE 또는 MISS. |
한도를 초과한 경우
API는 HTTP 429와 코드 RATE_LIMITED로 응답합니다. Retry-After에 지정된 초만큼 기다린 뒤 다시 시도하십시오. 엔드포인트의 캐시 TTL보다 빠르게 폴링하면 캐시된 동일 응답이 반환되므로, 폴링 간격을 각 레퍼런스 페이지에 표시된 TTL에 맞추십시오.
백오프를 적용한 재시도
async function getJson(url, tries = 4) {
for (let i = 0; i < tries; i++) {
const res = await fetch(url);
if (res.status === 429 || res.status >= 500) {
const wait = Number(res.headers.get("Retry-After")) || 2 ** i;
await new Promise((r) => setTimeout(r, wait * 1000));
continue;
}
const body = await res.json();
if (body.success === false) {
throw new Error(body.code + ": " + body.error + " (" + body.request_id + ")");
}
return body;
}
throw new Error("gave up after " + tries + " attempts");
}데이터 없음은 오류가 아닙니다
파라미터는 유효하지만 해당 데이터의 합법적인 공개 소스가 없는 경우 호출은 HTTP 200으로 성공합니다. 값 필드는 null, meta.quality는 UNAVAILABLE이며 coverage.unavailable에 사유가 나열됩니다. 대시로 표시하고 0으로 변환하지 마십시오.
만료된 데이터
수집기가 뒤처지면 엔드포인트는 마지막으로 저장된 값을 meta.is_stale: true와 함께 계속 제공합니다. 사용 가능 창을 지나면 이 값들은 집계에서 제외되고 coverage.stale_excluded에 나열됩니다.