Errors & FAQ
에러 처리 방법과 자주 묻는 질문입니다.
HTTP 상태 코드
| 코드 | 설명 | 해결 방법 |
|---|---|---|
| 400 | 잘못된 요청 | 요청 형식 확인. Database API "Access denied"는 API 키 팀과 DB 소유 팀 불일치 |
| 401 | 인증 실패 | API 키 확인 |
| 402 | 크레딧 부족 | 크레딧 충전 |
| 403 | 접근 거부 | API 키 활성화 상태 확인 |
| 422 | 입력 검증 실패 | 파라미터 타입/값 확인 (예: output_format은 jpeg/png/webp만 허용) |
| 429 | 요청 한도 초과 | Retry-After 헤더 확인. 어떤 한도인지는 error.code로 구분 |
| 500 | 서버 오류 | 잠시 후 재시도 |
403 storage_quota_exceeded
팀이 스토리지 쿼터를 초과한 상태에서 POST /files/upload-url을 호출하면 이 코드와 함께 403이 반환됩니다. 파일당 50MB 제한과는 별개이며, 파일 총량이 한도를 넘으면 새 업로드가 거부됩니다. AI 예측 결과물은 이 쿼터로 차단되지 않습니다. 응답 형태: { "detail": { "code": "storage_quota_exceeded", "message": "..." } }. message는 바이트/파일 개수 한도 중 어느 쪽을 넘었는지에 따라 문구가 달라지는 설명 문자열입니다(변동될 수 있음) — 분기 처리는 항상 code 값으로 하세요. 해결: 오래된 파일 삭제(사용량은 GET /files/storage로 확인) 또는 상위 플랜 업그레이드. 리셀러 워크스페이스에서 end-customer별 한도(default_customer_storage_* 또는 지갑 storage_quota)를 걸어 두면 그 고객만 초과했을 때는 팀 쿼터가 남아 있어도 customer_storage_quota_exceeded로 거부됩니다 — 이 경우 고객 쪽 문구에는 팀 수치가 노출되지 않습니다.
코드는 표면마다 다릅니다
Core.Today는 두 개의 독립된 표면을 제공하고, 둘은 서로 다른 코드 집합을 씁니다. 아래 표의 “표면” 열이 어느 쪽이 그 코드를 내는지 알려줍니다.
- • AI API —
/v1/predictions,/v1/files,/v1/databases등. - • LLM gateway — OpenAI·Anthropic·Gemini 호환 LLM 경로.
가장 흔한 함정: missing_api_key, invalid_api_key, api_key_disabled는 LLM 게이트웨이에만 존재합니다. AI API는 같은 상황에서 상태별 기본값인 unauthorized(401) / forbidden(403)을 반환합니다. POST /predictions 클라이언트가 invalid_api_key로 분기하면 그 가지는 영원히 실행되지 않습니다.
에러 응답 형태
에러 응답은 아래 봉투를 따릅니다. detail은 문자열일 수도, { code, message, … } 객체일 수도 있습니다 (422는 검증 항목 배열). 레이트리밋·용량 거절·쿼터 초과처럼 트래픽이 많은 경로는 대부분 객체 형태라 String(detail)을 하면 [object Object]가 찍힙니다. 표시는 error.message를, 분기는 error.code를 쓰세요 — message 문구는 예고 없이 다듬어집니다.
{
"detail": {
"code": "customer_wallet_insufficient",
"message": "End-customer 'acme-01' budget exhausted. Required: 120. Top up ..."
},
"error": {
"type": "api_error",
"code": "customer_wallet_insufficient",
"message": "End-customer 'acme-01' budget exhausted. ...",
"request_id": "3f2a9c1e-...",
"wallet_remaining": 30.0,
"topup_required": 90.0
},
"request_id": "3f2a9c1e-..."
}- •
request_id는 모든 응답의X-Request-Id헤더에도 실립니다. 문의 시 이 값을 함께 보내주시면 해당 요청의 서버 로그를 바로 찾을 수 있습니다. - • 코드별로
error에 추가 필드가 붙습니다 (예: 402의topup_required, 동시성 429의group/limit, 사용량 429의reset_at,model_retired의replacement). - • 재시도 가능한 응답에는
Retry-After헤더가 붙습니다. 공식 SDK는 이 값을 자동으로 존중합니다.
예외: 본문 크기 초과(413)는 이 봉투를 따르지 않습니다
AI API의 본문 상한(10MB)은 예외 핸들러보다 앞단의 미들웨어에서 검사되므로, 초과 시 응답은 { "detail": "Request body too large. Maximum size: 10MB" } 뿐입니다 — error 객체도, code도, request_id도 없습니다. 이 한 가지 응답만은 상태 코드 413으로 판별하세요. LLM 게이트웨이는 별개로 50 MiB 한도를 가지며, 그쪽은 정상적으로 request_too_large 코드를 냅니다.
에러 코드 레퍼런스 (동기 응답)
요청이 즉시 거절될 때 error.code로 전달되는 값입니다. “표면” 열이 어느 제품이 그 코드를 내는지, “원인 주체” 열이 누가 고쳐야 하는 문제인지 알려줍니다 — Core.Today로 표시된 항목은 요청 측 잘못이 아니며 키·잔액을 건드릴 필요가 없습니다.
| code | Surface | Status | At fault | Retry | Meaning | What to do |
|---|---|---|---|---|---|---|
unauthorized | AI API | 401 | Caller | No | The AI API's default authentication-failure code — both a missing key and an invalid key arrive as this value. | The AI API does not distinguish missing from invalid keys by code. Read message for the specific reason. |
forbidden | AI API | 403 | Caller | No | The AI API's default permission-denied code — disabled key, owner/admin-only operation, and so on. | A 403 with no more specific code. Check message for the reason. |
missing_api_key | LLM gateway | 401 | Caller | No | No Authorization or x-api-key header was sent. | Retry with the API key in the header. The same situation on the AI API surface is unauthorized. |
invalid_api_key | LLM gateway | 401 | Caller | No | The key does not exist or has been revoked. | Check the key in the console. This code is an authoritative 'the key really is gone' answer. |
api_key_disabled | LLM gateway | 403 | Caller | No | The key has been deactivated. | Re-enable the key in the console, or issue a new one. |
api_key_expired | LLM gateway | 403 | Caller | No | The key is past its expiry time. | Issue a new key. Expiry cannot be undone. |
ip_not_allowed | LLM gateway | 403 | Caller | No | The calling IP is not in this key's allow-list. | Edit the key's allowed IPs in the console, or call from a listed address. |
auth_service_unavailable | LLM gateway | 503 | Core.Today | After Retry-After | The auth service was temporarily unreachable, so the key could not be verified. | Do NOT rotate your key — nothing is wrong with it. Retry after the Retry-After delay (10s). |
insufficient_scope | AI API | 403 | Caller | No | The key lacks permission for this endpoint. | Call with a key that carries the required scope. |
ambiguous_auth | AI API | 400 | Caller | No | Two different credentials were sent at once (Clerk session + X-API-Key, or X-API-Key + X-Phantom-Token). | Rejected because the intended identity is ambiguous. Send exactly one. |
phantom_token_missing | AI API | 401 | Caller | No | Reseller browser path: the X-Phantom-Token header is absent. | Mint a phantom token on your server and pass it to the client. |
phantom_token_invalid | AI API | 401 | Caller | No | The phantom token's signature is wrong, or it has expired or been revoked. | Mint a fresh token. There is no need to rotate the underlying API key. |
reseller_mode_required | AI API | 403 | Caller | No | A reseller-only feature was called on a workspace that is not in reseller mode. | Request reseller mode in the console. It takes effect as soon as it is approved. |
customer_id_required | LLM gateway | 400 | Caller | No | A billable request from a reseller workspace arrived without X-Customer-Id. | Rejected fail-closed when the end customer cannot be identified. Add the header. |
ambiguous_customer_id | LLM gateway | 400 | Caller | No | The X-Customer-Id header was sent more than once. | Check whether a proxy or SDK is appending the header twice. Exactly one is allowed. |
invalid_customer_id | Both | 400 | Caller | No | X-Customer-Id is malformed — allowed characters are A-Z a-z 0-9 _ . - up to 128 chars. | Normalize your customer identifier and call again. |
customer_mismatch | AI API | 403 | Caller | No | The requested resource does not belong to the end customer named in X-Customer-Id. | You cannot reach another customer's data. Call with the correct customer_id. |
bad_request | AI API | 400 | Caller | No | The AI API's default 400 code — a rejected request with no more specific code. | The reason is in message. |
validation_error | AI API | 422 | Caller | No | The request body does not match the schema. | The error.errors array names which field was rejected and why. |
not_found | Both | 404 | Caller | No | AI API: the model or resource does not exist. Gateway: the endpoint does not exist (often a base_url typo). | For models, list what is available with GET /providers/models/catalog. |
method_not_allowed | LLM gateway | 405 | Caller | No | Wrong method — /models and /pricing are GET-only. | Call them with GET. |
unknown_api_type | LLM gateway | 400 | Caller | No | The URI matches none of the provider routes. | Check the path prefix (/openai/v1/..., /anthropic/v1/..., /gemini/v1beta/...). |
unsupported_model | LLM gateway | 400 | Caller | No | The model name is not one the LLM gateway supports. | List the supported models with GET /llm/v1/pricing. |
model_retired | LLM gateway | 400 | Caller | No | The model has been retired. | The replacement field in the response names the successor model. |
model_not_determinable | LLM gateway | 400 | Caller | No | A billable request whose model cannot be determined from either the URL or the body (usually the Gemini path). | Without a model there is no price to reserve, so the call is refused. Name the model explicitly. |
request_too_large | LLM gateway | 413 | Caller | No | The request body exceeded the gateway's 50 MiB limit. | Send images by reference through an upload URL. The AI API's 413 is a separate, smaller limit (10MB) — see the warning below. |
(no code) | AI API | 413 | Caller | No | The AI API body exceeded 10MB. The middleware bypasses the exception handlers, so there is no error object, no code and no request_id. | This one response cannot be branched on by code — detect it by status 413. Send large inputs via an upload URL. |
request_body_read_failed | LLM gateway | 400 | Caller | Yes | The request body could not be read to completion (e.g. the connection dropped mid-upload). Not a size problem. | Retry as-is. If it repeats, check the client's network and timeouts. |
input_nesting_too_deep | AI API | 400 | Caller | No | The input object is nested deeper than the allowed limit. | Flatten the input. Deep nesting is refused as a parsing-cost defense. |
too_many_file_references | AI API | 400 | Caller | No | The request carries more file references than the limit allows. | Split the references across multiple requests. |
insufficient_credits | Both | 402 | Caller | No | The team is out of credits. | Top up. error.required / error.available carry the needed and held amounts. |
payment_required | LLM gateway | 402 | Caller | No | The 402 fallback used when a balance-related refusal arrives without a specific code. | Treat it exactly like insufficient_credits — check the balance and top up. |
customer_not_found | Both | 402 · 404 | Caller | No | Reseller: the X-Customer-Id is not registered in this workspace. 402 on the charging path, 404 on the phantom-token auth path. | Do not treat the 404 as 'resource missing' — branch on code, not status. Create the customer first with POST /reseller/customers. |
team_blocked | AI API | 403 | Caller | No | An administrator has blocked this workspace's usage (abnormal usage, policy violation). All API key / LLM / MCP calls and credit-charging paths are refused; console reads still work. | Check the reason in the console banner and contact support@core.today. Retrying returns the same response until the block is lifted. |
customer_suspended | Both | 402 · 403 | Caller | No | Reseller: the end customer is suspended. 402 on the charging path, 403 on the phantom-token auth path. | Reactivate with POST /reseller/customers/{id}/reactivate. |
customer_wallet_insufficient | Both | 402 | Caller | No | Reseller: the end customer's budget is exhausted. | Top up by error.topup_required (wallet_cap / wallet_spent / wallet_remaining are included). |
reseller_account_insufficient | Both | 402 | Caller | No | Reseller: the end customer still has budget, but the reseller's own workspace is out of credits. | Top up the workspace, not the customer wallet — do not confuse this with customer_wallet_insufficient. |
addon_past_due | AI API | 409 | Caller | No | The storage add-on's renewal payment is past due. | Clear the outstanding balance first — retrying alone will not resolve it. |
conflict | AI API | 409 | Caller | No | The AI API's default 409 code — the request conflicts with the resource's current state. | Re-read the resource state and adjust the request. |
document_not_found | AI API | 404 | Caller | No | Data API: the document targeted by PUT/PATCH/GET/DELETE does not exist. (Before 2026-09-12 this surfaced as a 400 carrying an internal error string.) | To create-if-missing, add ?upsert=true to PUT/PATCH — the response's result says created|updated. |
document_already_exists | AI API | 409 | Caller | No | Data API: POST /documents is create-only and a document with that id already exists. Nothing was overwritten. | Use PUT (replace) or PATCH (merge) to change the existing document, or ?upsert=true when you don't care which. |
document_conflict | AI API | 409 | Caller | Yes | Data API: the same document was modified concurrently and this write lost the race, even after 3 server-side retries. | Resend the request as-is (a PATCH merge is idempotent). |
db_rate_limited | AI API | 429 | Caller | After Retry-After | Data API: the workspace's per-minute budget (read / search / write class, plan-dependent) is exhausted. Refused requests are not charged. | Retry after Retry-After. error.op_class / error.limit say which budget; upgrade the plan if it is consistently short. |
invalid_where | AI API | 400 | Caller | No | Data API: the where filter is not a JSON object, or uses an unknown operator, an invalid field name or a malformed value. Rejected before any charge. | Fix the operator/field the message names. Supported: $eq $ne $in $nin $gt $gte $lt $lte $exists $prefix $contains $match $and $or $not. |
embedding_failed | AI API | 502 | Model provider | Yes | Data API: the auto-embedding call (LLM gateway) for an embed-configured knn_vector field failed, so the write was aborted. Nothing was stored. Causes: no active API key in the workspace (console writes), or the gateway returned an error / insufficient credits. | Retry the same request. If it persists, check credits and API key status — or compute the vector yourself and send it in the field, which skips the embedding call. |
precondition_failed | AI API | 412 | Caller | No | Data API: the document changed after the _meta.version you sent in If-Match. Nothing was written. | Re-read the document (GET → new _meta.version), re-apply your change and retry with the new If-Match. |
invalid_if_match | AI API | 400 | Caller | No | Data API: the If-Match value is not a <seq_no>.<primary_term> token. Rejected before any charge. | Send back _meta.version from a response (or the ETag from GET) verbatim. |
database_reindexing | AI API | 409 | Caller | After Retry-After | Data API: the database is being reindexed (schema change), so writes are refused. Reads and searches still work. | Poll GET /databases/{uid}/reindex and retry once reindex.status is done (see Retry-After). |
job_already_running | AI API | 409 | Caller | After Retry-After | Data API: a job of the same kind (export/import) is already running for this database. | Check GET /databases/{uid}/export or /import and start again once it has finished. |
import_fetch_failed | AI API | 400 | Caller | No | Data API: the import URL could not be fetched — private address, over 50 MB, timeout or a non-2xx response. | Use a public http(s) URL (or a Core.Today file URL) under 50 MB. |
database_unavailable | AI API | 503 | Core.Today | After Retry-After | Data API: the document store (OpenSearch/S3) could not be written right now. Deducted credits are refunded. | Retry after Retry-After (2s). If it persists, check status.core.today. |
credit_service_unavailable | LLM gateway | 503 | Core.Today | After Retry-After | The credit service was down, so the request could not be authorized. | Nothing is wrong with your balance and nothing was charged. Retry after the Retry-After delay. |
reserve_in_flight | LLM gateway | 409 | Core.Today | After Retry-After | A reservation for the same request_id is still in flight. | Retry after 1 second. This state is transient. |
rate_limited | Both | 429 | Caller | After Retry-After | Gateway: the key's per-minute LLM token budget is exhausted. AI API: the default for a 429 with no more specific code. | Wait out the Retry-After delay, then retry. X-RateLimit-Reset gives the reset time. |
api_key_rate_limited | AI API | 429 | Caller | After Retry-After | The API key's per-minute/hour/day request limit was exceeded. | Wait out the Retry-After delay, then retry. No credits were charged. |
customer_rate_limited | AI API | 429 | Caller | After Retry-After | Reseller: the end customer's own request rate limit was exceeded. | Retry after the delay, or raise rate_limit on the wallet. |
customer_concurrency_exceeded | Both | 429 | Caller | After Retry-After | Reseller: the end customer hit its per-category concurrency ceiling (see error.group / error.limit). | Retry once an in-flight job finishes. No credits were charged. |
admission_queue_full | AI API | 429 | Model provider | After Retry-After | The provider's concurrency pool (admission queue) for this model was already at capacity, so the request was rejected immediately — it never started waiting. Unlike admission_timeout, which fails after waiting, this is a synchronous error returned at request-creation time. | No credits are charged; resubmit after `retry_after` seconds. |
customer_token_rate_limited | LLM gateway | 429 | Caller | After Retry-After | Reseller: the end customer's per-minute LLM token budget is exhausted. | Wait for the next minute, or raise llm_tokens_per_minute on the wallet. |
model_rate_limited | LLM gateway | 429 | Caller | After Retry-After | The per-minute request cap configured for that model was exceeded. | Retry after the delay. The token budget reserved for the call is rolled back. |
usage_limit_exceeded | AI API | 429 | Caller | No | The daily/monthly credit budget is spent. This is not a rate limit. | Retrying will not help — wait until error.reset_at or raise the budget. |
storage_quota_exceeded | AI API | 403 | Caller | No | The team's storage quota is full. | Delete old files or move to a larger plan. |
customer_scope_required | AI API | 400 | Caller | No | In a reseller workspace, a call that needs an end-customer scope (customer DB document API, file delete) carried neither X-Customer-Id nor X-Customer-Scope: all. A missing header is never treated as 'all' — this is fail-closed so a proxy that drops the header cannot silently disable customer isolation. | Send X-Customer-Id when acting for a customer, or X-Customer-Scope: all for the reseller's own administrative access. |
customer_storage_quota_exceeded | AI API | 403 | Caller | No | Reseller: the storage quota assigned to this end customer (X-Customer-Id) — bytes or file count — is full. Independent of the team-wide quota; checked only when issuing an upload URL. | Have the customer delete files, or raise the limit with storage_quota on PATCH /reseller/customers/{id} (takes effect immediately). Defaults come from default_customer_storage_* on PATCH /reseller/settings. |
capacity_exceeded | AI API | 503 | Core.Today | After Retry-After | Too many predictions are already in flight on our side. | No credits were charged. Retry after the Retry-After delay. |
heavy_capacity_exceeded | AI API | 503 | Core.Today | After Retry-After | The ceiling for long-running work (video, music) has been reached. | No credits were charged. Retry after the Retry-After delay. |
job_store_unavailable | AI API | 503 | Core.Today | After Retry-After | The job-status store was unreachable while creating the job. Nothing was started and credits are refunded. | Safe to resubmit — no job was started, so there is no duplicate-run risk. |
job_status_unavailable | AI API | 503 | Core.Today | After Retry-After | Could not read the status of an already-running job. The job itself is unaffected. | Do NOT resubmit — the job is still running and resubmitting double-charges. Re-poll the same job_id after the delay. |
job_not_found_or_expired | AI API | 404 | Caller | No | The job_id is wrong, or the job record aged past its 24-hour retention. | Past 24 hours a completed job may still return 200 with its result through a fallback lookup (when queried with the same user's credentials). If the 404 stands, find the output via GET /files or your usage history. |
internal_error | Both | 500 | Core.Today | Yes | An unexpected server error. | Safe to retry. If it repeats, contact us with the response's request_id. |
service_unavailable | AI API | 503 | Core.Today | After Retry-After | The AI API's default 503 code — a temporary outage with no more specific code. | Retry after the Retry-After delay. |
upstream_error | AI API | 502 | Core.Today | Yes | The AI API's default 502 code — a dependency upstream of us did not answer. | Nothing is wrong with your request. Retry shortly. |
proxy_error | LLM gateway | 502 | Core.Today | Yes | The gateway could not reach the provider. | Unrelated to your payload. Retry shortly; if it persists, contact us with the request_id. |
upstream_auth_failure | LLM gateway | 503 | Core.Today | After Retry-After | The gateway's provider credentials failed (the whole key pool was exhausted). | Nothing to do with your key. Retry after the Retry-After delay; contact us if it persists. |
provider_not_configured | LLM gateway | 503 | Core.Today | No | The requested provider is not configured on this gateway. The status is 503, but the condition is not transient. | Retrying will never help — do not back off and retry just because it is a 503. Contact support. |
stream_interrupted | LLM gateway | 200 · SSE | Model provider | Yes | The streaming response was cut mid-flight. The 200 headers were already sent, so the failure is injected into the body as an event: error frame instead. | A client that only reads content deltas discards this frame and mistakes the following [DONE] for a clean finish. Always check for an error field in your stream loop. Credits settle only against usage the upstream actually reported. |
에러 코드 레퍼런스 (예측 실패)
POST /predictions는 즉시 job_id를 반환하므로, 실제 실패 사유는 GET /predictions/{job_id} 응답의 error_code로 전달됩니다 (status는 failed). 이 표는 AI API 전용입니다.
실패한 예측의 크레딧은 자동 환불됩니다. 다만 credits_used가 0인지로 환불 여부를 판정하지는 마세요 — 오래된 레코드와 만료 후 폴백 조회는 이 값이 null(“알 수 없음”)입니다. 실제 청구 내역은 사용량·청구 API를 기준으로 확인하세요.
| code | Status | At fault | Retry | Meaning | What to do |
|---|---|---|---|---|---|
invalid_input | failed | Caller | No | The provider rejected the input (400/422). | Compare against the input schema on the model's detail page. |
payload_too_large | failed | Caller | No | The input file or body exceeded the provider's limit (413/415). | Lower the image resolution or shrink the file. |
provider_rejected | failed | Model provider | No | The provider reported the job as failed (moderation, safety filters, and so on). | The error text is the provider's own reason. Credits are refunded. |
provider_rate_limited | failed | Model provider | Yes | The provider rate-limited our request. | Retry shortly. Credits are refunded. |
provider_unavailable | failed | Model provider | Yes | The provider returned a 5xx. | Retry shortly. Credits are refunded. |
provider_timeout | failed | Model provider | Yes | The provider did not answer within the time limit. | Retry. Credits are refunded. |
queue_timeout | failed | Model provider | Yes | The job never started moving in the provider's queue. | Retry. Credits are refunded. |
admission_timeout | failed | Model provider | Yes | The job waited longer than the admission-queue's wait limit (default 600s) for the provider's concurrency slot to free up. Unlike queue_timeout — which fires after the provider's own queue has already accepted the job — this happens before any request reaches the provider, in our gateway's admission-queue stage. If the model has a fallback, this code is also used when we routed to that fallback instead of waiting and the fallback failed too; the message then names the fallback failure. | Credits are refunded; resubmit after `retry_after` seconds |
admission_drained | failed | Core.Today | Yes | The job was waiting in the admission queue for provider capacity when the gateway restarted (e.g. a deploy), and its pending reservation was cancelled. Unlike queue_timeout/admission_timeout, this is unrelated to provider limits — it is caused by our own restart. | Credits are refunded; resubmit after `retry_after` seconds |
provider_error | failed | Model provider | Yes | An unclassified provider error — the default when none of the codes above fit. | Read the error text. Safe to retry, and credits are refunded. |
provider_model_not_found | failed | Core.Today | No | The provider rejected our model mapping (typically an upstream rename). | Not an input problem — a registry problem on our side. Contact us with the job_id. Credits are refunded. |
provider_auth_error | failed | Core.Today | No | The gateway failed to authenticate against the provider. | An alert has already been raised automatically. Credits are refunded. |
gateway_execution_timeout | failed | Core.Today | Yes | The job was aborted after exceeding the gateway's maximum execution time. | Our problem. Credits are refunded and retrying is safe. |
gateway_internal_error | failed | Core.Today | Yes | An internal gateway error. | Our problem. Credits are refunded. If it repeats, contact us with the job_id. |
Rate Limits
API 키별 기본 한도 — 초과 시 api_key_rate_limited(AI API) 또는 rate_limited (LLM 게이트웨이)
분당
20/min
시간당
200/hour
일간
1,000/day
팀 단위로 상향 조정할 수 있습니다. 리셀러 워크스페이스의 키는 여러 end-customer 트래픽이 합산 통과하므로 훨씬 높은 상한이 적용되고, 실질 게이트는 아래 end-customer별 한도가 맡습니다.
리셀러 end-customer별 한도 (X-Customer-Id 단위)
요청 속도(customer_rate_limited), 카테고리별 동시 실행 수(customer_concurrency_exceeded, 기본 이미지 10·비디오 5), 분당 LLM 토큰(customer_token_rate_limited)을 지갑별로 설정할 수 있습니다. 현재 사용 현황은 GET /reseller/customers/{id}/concurrency로 확인하세요. 스토리지 용량도 같은 단위로 제한할 수 있습니다 — 초과 시 403 customer_storage_quota_exceeded(지갑 storage_quota > 워크스페이스 default_customer_storage_* 순으로 적용).
IP 기반 제한은 2026-05-05에 폐지됐습니다 — 인증된 요청에는 중복이었고, 사무실·모바일 NAT처럼 IP를 공유하는 정상 사용자를 오탐했기 때문입니다. 429를 받았다면 IP가 아니라 위 한도 중 하나이며, error.code가 어느 쪽인지 알려줍니다.
자주 묻는 질문
Q: API 키를 분실했어요
A: 대시보드에서 기존 키를 삭제하고 새 키를 발급받으세요.
Q: 크레딧이 부족해요
A: 다음날 UTC 자정에 무료 크레딧이 충전됩니다. 또는 충전 코드를 사용하세요.
Q: 예측이 실패했는데 크레딧이 차감됐어요
A: 실패한 예측의 크레딧은 자동으로 환불됩니다.
Q: 스트리밍 응답이 중간에 끊겼는데 에러가 없어요
A: 헤더가 이미 200으로 나간 뒤에는 상태 코드로 실패를 알릴 수 없어, 게이트웨이가 SSE 본문에 data: {"error": {"code": "stream_interrupted", ...}} 프레임을 주입한 뒤 스트림을 닫습니다. content delta만 읽는 클라이언트는 이 프레임을 버리고 뒤따르는 [DONE]을 정상 종료로 착각합니다 — 스트림 루프에서 반드시 error 필드를 확인하세요.
Q: 결과 파일은 얼마나 보관되나요?
A: 팀 플랜에 따라 보관 기간이 다릅니다 (Free 30일, Pro 365일, Team·Enterprise 무기한). 결과 파일의 다운로드 URL은 기본 7일간 유효하며, 만료돼도 파일 자체는 삭제되지 않습니다 — POST /files/sign으로 언제든 새 URL을 재발급받을 수 있습니다.
Q: 이미지 업로드 용량 제한이 있나요?
A: /files/upload-url을 거치는 파일은 파일당 최대 50MB입니다. 반면 요청 본문에 직접 담는 데이터는 AI API 10MB, LLM 게이트웨이 50 MiB 한도를 따릅니다 — 큰 이미지는 업로드 URL을 거쳐 참조로 넘기세요.