문서 섹션
오류
모든 거부에는 detail 옆에 errorKind와, 대응에 필요한 필드가 담깁니다. 처리는 상태와 errorKind로 분기하세요. detail의 문구는 사람이 읽기 위한 것이며 바뀔 수 있습니다.
Python 라이브러리는 상태마다 타입이 지정된 예외를 발생시키며, 예외는 메시지가 아니라 상태만으로 정해집니다. 5xx는 백오프를 두고 재시도한 뒤에 예외로 발생시킵니다.
상태 코드
| 상태 | Python 예외 | 발생 조건 |
|---|---|---|
| 200 | 없음 | 성공: 결과가 본문에 있습니다. |
| 202 | 없음 | 접수됨: 시뮬레이션 작업이 대기열에 들어갔습니다. 결과는 폴링으로 받으세요. |
| 400 Bad Request | ValidationError | 보낸 그대로는 요청에 답할 수 없습니다: 유한한 숫자가 아닌 입력, 설정할 수 없는 역산, 계약을 벗어난 작업 본문, 비어 있거나 한도를 넘는 배치. 집계되지 않습니다. |
| 401 Unauthorized | AuthError | 키를 보내지 않았거나(본문에 keyUrl이 담깁니다), 저희가 발급하지 않았거나 폐기된 키입니다. 할당량과는 관계가 없습니다. |
| 402 Payment Required | QuotaError | 집계되는 모든 경로에서 계정의 월간 할당량을 다 썼습니다. 집계되지 않았습니다. Retry-After에 resetAt까지 남은 초가 담깁니다. |
| 403 Forbidden | AuthError | 작업이 다른 사람의 것이거나, 계정의 요금제에 배치 엔드포인트나 요청한 해석 모드가 포함되어 있지 않습니다. |
| 404 Not Found | NotFound | 그런 계산기 슬러그, 작업 유형, 작업이 없습니다. 집계되지 않습니다. |
| 409 Conflict | APIError | 키 한도에 도달한 상태의 디바이스 승인, 또는 이미 결정된 코드에 대한 승인(로그인한 브라우저의 호출). |
| 422 Unprocessable Content | ValidationError | 본문을 해석할 수 없습니다: 필수 필드가 없거나, 값의 타입이 잘못되었습니다(텍스트로 보낸 입력 등). 경로가 실행되기 전에 응답합니다. |
| 429 Too Many Requests | RateLimitError | 그 자격 증명으로 1분 동안 요청이 너무 많거나, 대기 중이거나 실행 중인 작업이 동시에 너무 많습니다. Retry-After에 다시 시도할 시점이 담깁니다. |
| 500 Internal Server Error | APIError | 결과는 계산되었지만 반환하지 못했거나, 역산에 실패했습니다. 과금되지 않았습니다. |
| 503 Service Unavailable | APIError | 키나 할당량 카운터를 확인하지 못했거나, 작업을 대기열에 넣지 못했습니다. 대기열에 들어가지도 과금되지도 않았습니다. 다시 시도하세요. |
상태 없이 발생하는 예외가 두 가지 더 있습니다. 작업이 failed로 끝났을 때의 JobFailed(작업의 errorKind를 .kind로 지닙니다)와, rftools login이 키를 받지 못했을 때의 LoginError입니다.
거부 본문
API가 보내는 본문입니다. 이번 달 수치는 요금제 표에서 읽어 왔습니다.
{
"detail": "An API key is required. Get a free key at https://rftools.io/dashboard/?newKey=1.",
"errorKind": "invalid_request",
"keyUrl": "https://rftools.io/dashboard/?newKey=1"
}{
"detail": "This API key is not valid. It may have been revoked.",
"errorKind": "invalid_request"
}형식이 잘못되었거나, 알 수 없거나, 폐기된 키입니다. 401은 할당량을 다 썼다는 뜻이 아닙니다.
{
"detail": "This account's 100 API calls for September are used. They reset on 2026-10-01. The API plan includes 10,000 a month.",
"errorKind": "rate_limited",
"reason": "allowance",
"limit": 100,
"used": 100,
"upgradeUrl": "https://rftools.io/pricing/",
"overageUrl": null,
"resetAt": "2026-10-01T00:00:00+00:00"
}Retry-After에 resetAt까지 남은 초가 담깁니다. 계산기를 포함해 집계되는 모든 경로에서 같은 본문입니다. 요금제에서 종량제를 켤 수 있으면 overageUrl이 설정되고, 그 상한까지 다 쓰면 reason이 overage_cap이 됩니다. 집계되지 않았습니다.
{
"detail": "More than 30 requests in 60 seconds from this address. An API key allows 120.",
"errorKind": "rate_limited",
"limit": 30,
"windowSeconds": 60,
"upgradeUrl": "https://rftools.io/pricing/"
}Retry-After가 함께 옵니다. 제한은 요청이 지닌 자격 증명에 따라 정해집니다.
{
"detail": "This account already holds 1 API key, the most the Free plan allows. Revoke a key to free its place, or upgrade to Pro for 3 API keys.",
"errorKind": "not_available",
"keyLimit": 1,
"manageUrl": "https://rftools.io/dashboard/#api-usage",
"upgradeUrl": "https://rftools.io/pricing/"
}POST /apikeys는 400으로 응답하고, 디바이스 승인은 reason: key_limit와 함께 409로 응답합니다.
오류 종류
errorKind는 거부된 요청과, 접수된 뒤 실패한 시뮬레이션 작업에 붙는 정해진 값의 집합입니다. 메시지 문구가 아니라 이 값으로 분기하세요.
| errorKind | 의미 |
|---|---|
| invalid_request | 매개변수가 없거나, 타입이 잘못되었거나, 범위를 벗어났거나, 선언된 선택지에 없거나, 이 작업 유형의 매개변수가 아닙니다. 400 본문에 문제가 있는 모든 매개변수가 나열됩니다. |
| too_large | 요청은 계약 범위 안에 있지만, 이 요금제의 실행 환경이 처리할 수 있는 규모를 넘습니다. 문제의 규모를 줄이세요. |
| not_available | 요청이 이 요금제에 포함되지 않은 모드나 기능을 요구합니다. 메시지에 요금제에 포함된 것이 표시됩니다. |
| rate_limited | 동시 작업 한도나 월간 할당량을 다 썼습니다. Retry-After가 함께 오며, 월간 할당량인 경우 resetAt도 함께 옵니다. |
| timeout | 작업이 그 유형의 시간 상한을 넘었습니다. 과금되지 않습니다. |
| interrupted | 실행이 끝나기 전에 멈췄습니다(워커가 교체되었거나 태스크가 중지됨). 과금되지 않습니다. |
| result_expired | 작업은 완료되었지만 결과가 더 이상 저장되어 있지 않습니다. 상태는 계속 completed이고 resultUrl은 없습니다. |
| transient | 서비스가 그 순간 요청을 받거나 확인하지 못했습니다. 대기열에 들어가지도 과금되지도 않았습니다. 다시 시도하세요. |
| fault | 서비스가 계산 중에 실패했습니다. 메시지에 실패한 단계가 표시됩니다. 과금되지 않습니다. |