status: "failed"로 끝날 수 있습니다. 실패하거나 취소된 작업은 청구되지 않습니다. 완료된 작업에 대해서만 요금이 부과됩니다. 노드 앱에서는 앱 자체의 작업은 청구되지 않습니다. 각 생성 노드 또는 LLM 노드는 해당 노드의 작업이 완료될 때 청구됩니다. 실패가 발생해도 병렬 노드나 다른 분기는 취소되지 않으므로, 앱이 이미 실패한 뒤에 완료된 노드도 청구되며 이 요금은 환불되지 않습니다. 실패했거나, 취소되었거나, 시작되지 않은 노드는 청구되지 않습니다. API 키 및 청구를 참고하세요.
요청 시점 오류와 실패한 작업
요청 시점 오류는4xx 또는 5xx 상태를 반환합니다. 작업은 생성되지 않습니다. 아래 설명에 따라 본문을 읽으세요.
실패한 작업은 제출 시점에 성공 상태를 반환합니다. GET /jobs/{id}를 폴링하거나 웹훅을 기다리세요. 작업이 끝나면 status가 "failed"이고, 실패 정보는 최상위 error 객체에 담깁니다. 실패한 작업에서는 result를 읽지 마세요. 이 필드는 생략되거나 null입니다. result에는 status가 "completed"일 때만 출력이 담깁니다. cancelled 작업에는 result도 error도 없습니다.
error.code를 기준으로 분기하세요. message는 생략될 수 있으며, provider_error와 internal의 경우 공급자가 보낸 자유 형식 텍스트입니다. message를 파싱하지 마세요.
응답 본문
generate, jobs, assets, styles, 노드 앱에서는 본문이 JSON일 때message ?? error를 읽으세요. 두 필드 중 하나에 요약이 담깁니다. 일부 5xx 본문은 JSON이 아닙니다. 예를 들어 502의 본문은 일반 텍스트 error code: 502일 수 있습니다. 방어적으로 파싱하세요. 본문이 JSON이 아니면 HTTP 상태를 기준으로 분기하세요.
대부분의 실패는 { "message": "..." }를 사용하며, 추가 필드(limit, jobType, modelAccessDenial)가 붙기도 합니다. 잘못된 JSON과 아래의 일부 핸들러는 대신 { "error": "..." }를 사용합니다.
/mcp 같은 MCP 엔드포인트는 이 페이지의 HTTP 본문이 아니라 JSON-RPC 오류 { "jsonrpc", "id", "error": { "code", "message" } }를 반환합니다.
Accept: application/json 보내기
401과 404를 포함한 { "message" } 오류는 Accept가 application/json 또는 */*일 때 JSON입니다. Accept가 없거나 text/html이면 이 상태들은 HTML 페이지(Content-Type: text/html)로 반환되어 JSON 파서가 실패합니다.
이는 Accept 헤더를 보내지 않는 클라이언트에 중요합니다. Python의 urllib가 그 예입니다. curl과 Node의 fetch는 기본적으로 Accept: */*를 보내므로, Accept를 재정의하지 않는 한 둘 다 JSON을 받습니다.
인증되지 않은 POST /generate/..., GET /jobs/{id}, GET /styles, GET /assets는 */*와 application/json에 대해 401 {"message":"Unauthorized"}를 반환하고, Accept가 없거나 text/html이면 HTML 페이지를 반환합니다. 알 수 없는 id로 인증된 GET /jobs/{id}를 호출해도 상태만 다를 뿐 동일하게 동작합니다. Accept가 JSON을 요청하면 404 JSON {"message":"Job not found or unauthorized"}를, Accept가 없으면 404 text/html을 반환합니다.
잘못된 JSON(400)과 유효성 검사(422)는 { "error" }를 사용하며 Accept가 없어도 JSON으로 유지됩니다. 제거된 필드의 422, 종료(sunset) 410, Zero Data Retention 402, 노드 앱의 { "error" } 응답, 매핑된 Agent operation API 오류도 마찬가지입니다. POST /generate/... 작업 접수 시의 402와 429도 브라우저의 Accept인 경우를 포함해 JSON입니다.
413과 500은 { "message" }를 사용하며 401, 404와 마찬가지로 Accept를 따릅니다.
유효성 검사 (422)
details에는 모든 문제가 나열됩니다. field는 .으로 연결한 경로입니다("image_style_references.0.url"). 객체 수준 오류는 위의 알 수 없는 키처럼 빈 문자열을 사용합니다. 알 수 없는 키가 여러 개이면 Unrecognized keys: ...와 동일한 빈 field가 생성됩니다. expected는 code가 "invalid_type"일 때만 추가됩니다.
잘못된 X-Webhook-URL 헤더도 이와 같은 422를 사용합니다.
잘못된 쿼리 파라미터로 GET /jobs를 호출해도 이 422를 반환합니다. 400이 아닙니다.
도구 내부에서 Zero Data Retention 입력 검사가 실패하면 message에 설명을 담아 422를 반환합니다({ "message" } 형식이므로 Accept가 중요합니다). Zero Data Retention을 참고하세요.
제거 및 지원 중단된 필드 (422)
제거된 batchSize / batch_size 필드는 다른 형태의 422를 사용합니다. details 배열은 없습니다:
batch_size도 같은 방식으로 제거되었습니다. field는 보낸 이름 그대로입니다.
지원 중단된 필드 별칭은 reason "deprecated_field" 또는 "conflicting_fields"를 사용하며, 해당하는 경우 replacement, sunset_date, migration_url이 함께 포함됩니다. error와 reason을 기준으로 분기하세요. 사람에게 보여 줄 문장은 message입니다.
종료된 모델 (410)
종료일이 지난 모델은 Deprecation: true와 Sunset 헤더(RFC 1123 날짜)와 함께 410을 반환합니다:
error는 고정 값 "model_unavailable"입니다. 권장 대체 모델이 없으면 replacement와 migration_url은 생략됩니다. 같은 모델로 재시도하면 계속 410이 반환됩니다. replacement가 설정되어 있으면 해당 모델로 전환하고, Deprecations를 참고하세요.
지원 중단되었지만 아직 사용 가능한 모델은 오류를 포함한 모든 응답에 Deprecation과 Sunset을 보냅니다. 지원 중단된 필드 별칭을 사용할 때도 해당 422를 포함해 동일합니다. 마이그레이션 가이드가 있으면 Link: <migration_url>; rel="deprecation" 헤더도 함께 전송됩니다.
상태 코드
400
generate에서 잘못된 JSON은 Accept 헤더 없이도 항상 JSON입니다:
{ "error" }를 사용합니다: Invalid URL for input "<key>" 또는 Failed to download URL for <key>: …. 다운로드 메시지는 일시적인 실패도 포함하므로, generate와 달리(입력 다운로드 참고) 노드 앱의 다운로드 실패는 항상 400입니다. URL이 유효하다면 한 번 재시도하세요.
POST /node-apps/{id}/execute에서 잘못된 JSON은 위의 generate 400이 아닙니다. 예외 텍스트 없이 500 { "message": "Internal Error" }가 되며 Accept를 따릅니다.
assets와 노드 앱의 다른 400 응답은 짧은 설명이 담긴 { "message": "..." }입니다. 예를 들어 presigned 업로드의 No file provided나 노드 앱 버전의 Invalid pagination parameters가 있습니다. asset 업로드가 실패하면 업로드 서비스의 상태(400, 401, 404 또는 500)가 그대로 전달되며, 응답 텍스트가 message에 담길 수 있습니다. 이 텍스트는 JSON 문자열인 경우도 있습니다. GET /jobs의 잘못된 쿼리 파라미터는 400이 아니라 422입니다.
401
generate, jobs, assets, styles, 노드 앱:
{ "message": "Presigned upload URL expired" } 또는 { "message": "Invalid presigned upload URL" }를 반환합니다.
402 결제 필요
API 잔액이 작업 비용을 충당하지 못하는 API 청구 클라이언트(API 키, 또는 API 키를 사용하는 MCP)의 경우:
402 message 값:
Zero Data Retention이 활성화되지 않은 워크스페이스에서 Zero Data Retention으로 generate를 호출하면 다음 본문을 반환하며, 항상 JSON입니다:
402 본문을 사용합니다. 이 경우 API 잔액이 아니라 워크스페이스 컴퓨트 잔액이 사용됩니다.
403
404
모든 404는 { "message" }입니다. 예를 들어 알 수 없는 작업 id의 경우:
Accept 헤더가 없으면 이 응답들은 HTML이 됩니다. 단, 키나 플랜으로 사용할 수 없는 모델에 대한 Endpoint not found는 예외로 항상 JSON입니다. Accept 없이 알 수 없는 id로 인증된 GET /jobs/{id}를 호출하면 404 text/html입니다.
알 수 없는 Agent operation도 Agent의
{ "error", "code" } 형식이 아니라 404 { "message": "Endpoint not found" }입니다.
405
본문은 JSON이 아니라 Content-Type 헤더가 없는 일반 텍스트이며, Accept가 application/json이어도 마찬가지입니다. 텍스트는 메서드 뒤에 method not allowed가 붙은 형태입니다(예: GET method not allowed). Allow 헤더에 해당 경로가 허용하는 메서드가 나열됩니다.
413 페이로드 초과
너무 큰 요청 본문은 413으로 거부됩니다. API 자체에서 반환하는 본문은 Accept를 따릅니다:
413 페이지로 거부될 수 있습니다. 파일을 인라인으로 보내지 마세요. POST /assets로 파일을 업로드하고 반환된 URL을 generate 요청에 전달하세요.
입력 다운로드
호스트가404 또는 410을 반환하면 영구적인 422입니다. 본문은 JSON이며 Accept가 중요합니다:
410을 반환하면 같은 문장에 410이 들어갑니다. 그 밖의 영구적인 거부는 Input file rejected: …를 사용합니다.
재시도할 수 있는 다운로드 실패는 502 또는 504입니다. 본문이 아니라 상태 코드를 기준으로 분기하고 재시도하세요.
같은 URL에서
502가 계속 반복된다면 URL이 차단되었거나 손상되었을 가능성이 높습니다. URL을 바꾸세요.
3D 내보내기 변환 실패도 502입니다. 이 경로는 실제 환경에서 테스트되지 않았으므로 본문이 Cloudflare 일반 텍스트 error code: 502로 도착할 수도 있습니다. 상태 코드를 기준으로 분기하고 재시도하세요. 같은 모델 URL에서 502가 계속 반복된다면 URL이 차단되었거나 손상되었을 가능성이 높습니다.
429 동시성
작업을 백로그할 수 없으면, 동시성 상한을 넘은 요청은 Content-Type: application/json과 함께 429로 거부될 수 있습니다:
limit은 이 종류의 작업에 대한 동시성 상한입니다. 워크스페이스 단위가 아니라 사용자 단위로 계산됩니다. 근사값이므로 짧은 순간에 몰린 요청은 상한을 넘어서도 접수될 수 있습니다. 따라서 limit + 1번째 요청이 실패할 것이라고 가정하지 마세요. jobType은 공개 모델 경로가 아니라 내부 작업 분류입니다. 이 값을 기준으로 분기하지 마세요.
Krea 2는 공유 큐가 가득 찼을 때 limit이나 jobType 없이 { "message": "CONCURRENCY_LIMIT_REACHED" }만 반환할 수도 있습니다. 이는 사용자의 상한 때문이 아닙니다. 백오프 후 재시도하세요.
백로그는 플랜에 포함되어 있고(Pro 이상), 모델이 지원하며, 요청이 Zero Data Retention이 아닐 때만 적용됩니다. Krea 2 요청은 현재 어떤 플랜에서도 백로그되지 않으므로 상한을 넘으면 429를 반환합니다. 백로그가 적용되면 추가 작업은 status: "backlogged"로 접수되고 슬롯이 비면 시작됩니다. 별도의 백로그 상한은 없습니다. Rate Limits를 참고하세요.
API는 Retry-After나 X-RateLimit-*를 보내지 않습니다. 응답에는 cf-ray가 포함됩니다. 429를 받으면 진행 중인 작업이 끝난 뒤(GET /jobs/{id}를 폴링하거나 웹훅 사용) 지수 백오프로 재시도하세요.
나중에 완료된 작업으로 잔액이 소진되면, 백로그에 남아 있던 작업은 error.code "insufficient_balance"로 실패합니다. 이는 HTTP 402가 아니라 실패한 작업입니다. 이러한 작업은 웹훅을 보내지 않으므로, 백로그된 작업은 GET /jobs/{id}로 폴링하세요.
Agent operation API
POST /agent/{operation}과 GET /agent/session/{sessionId}는 { "error", "code"?, "allowedModels"? }를 반환합니다. error만 필수입니다. allowedModels는 camelCase입니다. 접수된 뒤 실패한 턴은 이러한 HTTP 오류가 아니라 세션의 status: "failed"로 표시됩니다. Agent를 참고하세요.
인식되지 않는 Agent 오류 코드도
{ "error", "code" }와 함께 422입니다. 알 수 없는 operation의 404와 처리되지 않은 500은 { "message" }를 사용하며 Accept를 따릅니다.
실패한 작업의 error.code
GET /jobs와 GET /jobs/{id}는 status가 "failed"일 때만 error를 설정합니다. 사용할 수 있는 result는 없습니다:
실패한 작업의 웹훅 전송은
error를 포함해 동일한 작업 객체를 사용합니다. 취소된 작업의 전송에는 error가 없습니다. 256 KiB보다 큰 페이로드는 전송되지 않으며 해당 작업에 대한 이후 전송도 이루어지지 않으므로, 대신 GET /jobs/{id}를 폴링하세요. 본문을 신뢰하기 전에 서명을 검증하세요. 웹훅을 참고하세요.
디버깅
Krea 요청 ID 헤더는 없습니다. 대신 모든 응답에 Cloudflare의cf-ray 헤더가 포함됩니다. Retry-After나 X-RateLimit-* 헤더는 전송되지 않습니다.
support@krea.ai로 문의할 때는 다음을 포함하세요:
- 호출이 작업을 생성했거나 작업을 대상으로 한 경우
job_id - 시각과 엔드포인트
- 요청 시점 오류의 경우
cf-ray값
Access-Control-Allow-Origin은 *입니다. generate, jobs, assets, styles, 노드 앱에서는 Access-Control-Expose-Headers가 설정되어 있지 않으므로, 브라우저의 fetch로는 cf-ray, Deprecation, Sunset을 읽을 수 없습니다. 네트워크 로그나 서버 측 클라이언트에서 cf-ray를 복사하세요.
모델이 호출을 더 이상 받지 않게 되기 전에, 모든 응답에서 Deprecation과 Sunset을 확인하세요. Deprecations를 참고하세요.
다음 단계
작업 수명 주기
작업이 완료, 실패 또는 취소될 때까지 상태 폴링하기
웹훅
실패한 작업 전송의 서명 검증하기
요청 한도
추가 작업이 백로그되는 경우와 429를 반환하는 경우
API 키 및 청구
402 이후 API 잔액 충전하기