status: "failed". Неудавшиеся и отменённые задания не тарифицируются. Вы платите только за завершённые задания. В node app собственное задание приложения никогда не тарифицируется. Каждый узел генерации или LLM тарифицируется, когда завершается его собственное задание. Сбой не отменяет параллельные узлы и другие ветви, поэтому узел, завершившийся уже после сбоя приложения, тоже тарифицируется, и эти списания не возвращаются. Узел, который завершился ошибкой, был отменён или так и не запустился, не тарифицируется. См. API-ключи и биллинг.
Ошибки при запросе и неудавшиеся задания
Ошибки при запросе возвращают статус4xx или 5xx. Задание не создаётся. Читайте тело ответа, как описано ниже.
Неудавшиеся задания при отправке возвращают успешный статус. Опрашивайте GET /jobs/{id} или дождитесь webhook. Когда задание заканчивается, status равен "failed", а сведения о сбое находятся в объекте error верхнего уровня. Не читайте result у неудавшегося задания: это поле отсутствует (или равно null). Результат в нём есть, только когда status равен "completed". У задания со статусом cancelled нет ни result, ни error.
Ветвите логику по error.code. Поле message может отсутствовать, а для provider_error и internal оно содержит произвольный текст провайдера. Не разбирайте message.
Тела ответов
Для generate, jobs, assets, styles и node apps читайтеmessage ?? error, если тело ответа — JSON. Одно из этих двух полей содержит краткое описание. Некоторые тела ответов 5xx не являются JSON, в том числе 502, тело которого — простой текст error code: 502. Разбирайте ответ с осторожностью: если тело не JSON, ветвите логику по HTTP-статусу.
В большинстве ошибок используется формат { "message": "..." }, иногда с дополнительными полями (limit, jobType, modelAccessDenial). Некорректный JSON и некоторые обработчики, описанные ниже, вместо этого используют { "error": "..." }.
MCP-эндпоинты, такие как /mcp, возвращают ошибки JSON-RPC в формате { "jsonrpc", "id", "error": { "code", "message" } }, а не HTTP-тела, описанные на этой странице.
Отправляйте Accept: application/json
Ошибки формата { "message" }, включая 401 и 404, возвращаются в JSON, когда Accept равен application/json или */*. Когда Accept отсутствует или равен text/html, эти статусы возвращают HTML-страницу (Content-Type: text/html), и JSON-парсер выдаст ошибку.
Это важно для клиентов, которые не отправляют заголовок Accept. Один из них — urllib в Python. curl по умолчанию отправляет Accept: */*, как и fetch в Node, поэтому оба получают JSON, если вы не переопределите Accept.
Неаутентифицированные POST /generate/..., GET /jobs/{id}, GET /styles и GET /assets возвращают 401 {"message":"Unauthorized"} для */* и application/json и HTML-страницу при отсутствующем Accept или text/html. Аутентифицированный GET /jobs/{id} с неизвестным id ведёт себя так же со своим статусом: 404 в JSON {"message":"Job not found or unauthorized"}, когда Accept запрашивает JSON, и 404 text/html, когда Accept отсутствует.
Некорректный JSON (400) и ошибки валидации (422) используют { "error" } и остаются в JSON даже без Accept. То же касается 422 для удалённых полей, 410 для выведенных из эксплуатации моделей, 402 для Zero Data Retention, ответов node apps в формате { "error" } и сопоставленных ошибок Agent operation API. Ответы 402 и 429 при приёме задания POST /generate/... тоже возвращаются в JSON, в том числе для браузерного Accept.
413 и 500 используют { "message" } и зависят от Accept, как 401 и 404.
Валидация (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, не пройденная внутри инструмента, возвращает 422 с объяснением в message (формат { "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)
Модель, у которой прошла дата вывода из эксплуатации, возвращает 410 с заголовками Deprecation: true и Sunset (дата в формате RFC 1123):
error — стабильное значение "model_unavailable". replacement и migration_url отсутствуют, если рекомендуемой замены нет. Повторные запросы к той же модели будут и дальше возвращать 410. Переключитесь на replacement, если оно указано, и см. Устаревшие модели.
Модель, которая устарела, но ещё работает, отправляет Deprecation и Sunset в каждом ответе, включая ошибки. То же происходит при использовании устаревшего псевдонима поля, в том числе в его собственном 422. Если существует руководство по миграции, также отправляется заголовок Link: <migration_url>; rel="deprecation".
Коды статуса
400
Некорректный JSON в generate всегда возвращается в JSON, заголовок Accept не требуется:
{ "error" } для входного URL, который не удаётся использовать: Invalid URL for input "<key>" или Failed to download URL for <key>: …. Сообщение о загрузке охватывает и временные сбои, поэтому, в отличие от generate (см. Загрузка входных файлов), сбой загрузки в node app всегда возвращает 400. Если URL корректен, повторите запрос один раз.
Некорректный JSON в POST /node-apps/{id}/execute — это не тот 400 для generate, что описан выше. Он превращается в 500 { "message": "Internal Error" } без текста исключения и зависит от Accept.
Другие ответы 400 для assets и node apps имеют формат { "message": "..." } с кратким пояснением, например No file provided при presigned-загрузке или Invalid pagination parameters для версий node app. Неудачная загрузка asset передаёт статус сервиса загрузки как есть (400, 401, 404 или 500) и может поместить текст его ответа в message. Иногда этот текст является JSON-строкой. Некорректные параметры запроса в GET /jobs возвращают 422, а не 400.
401
Generate, jobs, assets, styles и node apps:
{ "message": "Presigned upload URL expired" } или { "message": "Invalid presigned upload URL" }.
402 Требуется оплата
Для клиента с биллингом через API (API-ключ или MCP с API-ключом), у которого API-баланса не хватает на задание:
message для 402 в публичном API:
Вызов generate с Zero Data Retention в рабочем пространстве, где эта функция не включена, возвращает такое тело, всегда в JSON:
402. Они относятся к балансу compute-юнитов рабочего пространства, а не к API-балансу.
403
404
Каждый 404 имеет формат { "message" }, например для неизвестного id задания:
Accept эти ответы возвращаются в HTML, кроме Endpoint not found для модели, которую ваш ключ или тариф не может использовать, — этот ответ всегда в JSON. Аутентифицированный GET /jobs/{id} с неизвестным id без Accept возвращает 404 text/html.
Неизвестная операция Agent тоже возвращает
404 { "message": "Endpoint not found" }, а не формат Agent { "error", "code" }.
405
Тело ответа — простой текст без заголовка Content-Type, а не JSON, даже когда 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. Ветвите логику по коду статуса, а не по телу ответа, и повторяйте запрос.
Если
502 повторяется для одного и того же URL, скорее всего, URL заблокирован или не работает. Измените URL.
Сбои конвертации при экспорте 3D тоже возвращают 502. Этот путь не проверялся вживую, поэтому тело также может прийти как простой текст Cloudflare error code: 502. Ветвите логику по коду статуса и повторяйте запрос. Если 502 повторяется для одного и того же URL модели, скорее всего, URL заблокирован или не работает.
429 из-за параллелизма
Если задание нельзя поставить в бэклог, запрос сверх лимита параллелизма может быть отклонён с 429 и Content-Type: application/json:
limit — ваш лимит параллелизма для этого вида заданий. Он считается на пользователя, а не на рабочее пространство. Лимит приблизительный: короткий всплеск может быть принят сверх него, поэтому не рассчитывайте, что ошибкой завершится именно запрос номер limit + 1. jobType — внутренняя категория задания, а не публичный путь модели. Не ветвите логику по этому полю.
Krea 2 также может вернуть только { "message": "CONCURRENCY_LIMIT_REACHED" }, без limit и jobType, когда её общая очередь заполнена. Это не ваш лимит. Сделайте паузу и повторите запрос.
Бэклог включён, только если он входит в тариф (Pro и выше), модель его поддерживает и запрос не использует Zero Data Retention. Запросы к Krea 2 сейчас не попадают в бэклог ни на одном тарифе, поэтому сверх лимита они возвращают 429. Когда бэклог включён, дополнительное задание принимается со статусом status: "backlogged" и запускается, как только освобождается слот. Отдельного лимита на размер бэклога нет. См. Лимиты запросов.
API не отправляет Retry-After или X-RateLimit-*. Ответ содержит cf-ray. При 429 повторяйте запрос с экспоненциальным backoff после завершения уже запущенных заданий (опрашивайте GET /jobs/{id} или используйте webhook).
Если более позднее завершённое задание исчерпает баланс, задания, которые всё ещё находятся в бэклоге, завершатся ошибкой с error.code "insufficient_balance". Это неудавшееся задание, а не HTTP 402. Для таких заданий webhook не отправляется, поэтому опрашивайте GET /jobs/{id} для заданий в бэклоге.
Agent operation API
POST /agent/{operation} и GET /agent/session/{sessionId} возвращают { "error", "code"?, "allowedModels"? }. Обязательно только поле error. allowedModels записывается в camelCase. Ход, который завершился неудачей после того, как был принят, отображается как status: "failed" в сессии, а не как одна из этих HTTP-ошибок. См. Agent API.
Нераспознанный код ошибки Agent всё равно возвращает
422 с { "error", "code" }. 404 для неизвестной операции и необработанный 500 используют { "message" } и зависят от Accept.
error.code неудавшегося задания
GET /jobs и GET /jobs/{id} заполняют error, только когда status равен "failed". Пригодного для использования result нет:
Доставки webhook для неудавшегося задания используют тот же объект задания, включая
error. Доставка об отмене не содержит error. Полезная нагрузка больше 256 KiB не отправляется, и дальнейшие доставки для этого задания не выполняются, поэтому в таком случае опрашивайте GET /jobs/{id}. Проверяйте подпись, прежде чем доверять телу запроса. См. Webhooks.
Отладка
Заголовка с id запроса Krea нет. Каждый ответ содержит заголовок Cloudflarecf-ray. Заголовки Retry-After и X-RateLimit-* не отправляются.
Когда пишете на support@krea.ai, укажите:
job_id, если вызов создал задание или обращался к нему- Время и эндпоинт
- Для ошибки при запросе — значение
cf-ray
Access-Control-Allow-Origin равен *. Для generate, jobs, assets, styles и node apps заголовок Access-Control-Expose-Headers не задан, поэтому браузерный fetch не может прочитать cf-ray, Deprecation или Sunset. Скопируйте cf-ray из сетевого журнала или из серверного клиента.
В любом ответе проверяйте Deprecation и Sunset, прежде чем модель перестанет принимать вызовы. См. Устаревшие модели.
Следующие шаги
Жизненный цикл задания
Опрашивайте статус, пока задание не завершится, не завершится ошибкой или не будет отменено
Webhooks
Проверьте подпись доставки для неудавшегося задания
Лимиты запросов
Когда дополнительные задания попадают в бэклог, а когда возвращают 429
API-ключи и биллинг
Пополните API-баланс после ошибки 402