status: "failed". Jobs que falham ou são cancelados não são cobrados. Você paga apenas pelos jobs concluídos. Em um node app, o job do próprio app nunca é cobrado. Cada nó de geração ou de LLM é cobrado quando o seu próprio job é concluído. Uma falha não cancela nós paralelos nem outras ramificações, então um nó concluído depois que o app já falhou também é cobrado, e essas cobranças não são reembolsadas. Um nó que falha, é cancelado ou nunca começa não é cobrado. Veja API Keys & Billing.
Erros no momento da requisição e jobs com falha
Erros no momento da requisição retornam um status4xx ou 5xx. Nenhum job é criado. Leia o corpo conforme descrito abaixo.
Jobs com falha retornam um status de sucesso no envio. Faça polling em GET /jobs/{id} ou aguarde um webhook. Quando o job termina, status é "failed" e a falha fica no objeto error de nível superior. Não leia result em um job com falha: ele é omitido (ou null). Ele só contém a saída quando status é "completed". Um job cancelled não tem nem result nem error.
Use error.code para decidir o que fazer. message pode ser omitido e, para provider_error e internal, é um texto livre do provedor. Não faça parsing de message.
Corpos de resposta
Em generate, jobs, assets, styles e node apps, leiamessage ?? error quando o corpo for JSON. Um desses dois campos traz o resumo. Alguns corpos 5xx não são JSON, incluindo um 502 cujo corpo é o texto simples error code: 502. Faça o parsing de forma defensiva: se o corpo não for JSON, decida com base no status HTTP.
A maioria das falhas usa { "message": "..." }, às vezes com campos extras (limit, jobType, modelAccessDenial). JSON inválido e alguns handlers abaixo usam { "error": "..." } em vez disso.
Endpoints MCP como /mcp retornam erros JSON-RPC, { "jsonrpc", "id", "error": { "code", "message" } }, e não os corpos HTTP desta página.
Envie Accept: application/json
Erros { "message" }, incluindo 401 e 404, são JSON quando Accept é application/json ou */*. Quando Accept está ausente, ou é text/html, esses status retornam uma página HTML (Content-Type: text/html) e um parser de JSON vai falhar.
Isso importa para clientes que não enviam o cabeçalho Accept. O urllib do Python é um deles. O curl envia Accept: */* por padrão, e o fetch do Node também, então ambos recebem JSON, a menos que você sobrescreva Accept.
POST /generate/..., GET /jobs/{id}, GET /styles e GET /assets sem autenticação retornam 401 {"message":"Unauthorized"} para */* e application/json, e uma página HTML quando Accept está ausente ou é text/html. Um GET /jobs/{id} autenticado para um id desconhecido faz o mesmo com o status: 404 JSON {"message":"Job not found or unauthorized"} quando Accept pede JSON, e 404 text/html quando Accept está ausente.
JSON inválido (400) e validação (422) usam { "error" } e continuam em JSON mesmo quando Accept está ausente. O mesmo vale para o 422 de campo removido, o 410 de modelo descontinuado, o 402 de Zero Data Retention, as respostas { "error" } de node apps e os erros mapeados da API de operações do Agent. Os 402 e 429 na admissão de um job POST /generate/... também são JSON, inclusive para um Accept de navegador.
413 e 500 usam { "message" } e seguem o Accept, assim como 401 e 404.
Validação (422)
details lista todos os problemas. field é o caminho unido por . ("image_style_references.0.url"). Erros no nível do objeto usam uma string vazia, como na chave desconhecida acima. Várias chaves desconhecidas produzem Unrecognized keys: ... e o mesmo field vazio. expected só é adicionado quando code é "invalid_type".
Um cabeçalho X-Webhook-URL inválido usa esse mesmo 422.
GET /jobs com parâmetros de consulta inválidos também retorna esse 422. Não é um 400.
Uma verificação de entrada de Zero Data Retention que falha dentro da ferramenta retorna 422 com a explicação em message (o formato { "message" }, então o Accept importa). Veja Zero Data Retention.
Campos removidos e obsoletos (422)
O campo removido batchSize / batch_size usa um 422 diferente. Não há array details:
batch_size é removido da mesma forma. field é o nome que você enviou.
Um alias de campo obsoleto usa reason "deprecated_field" ou "conflicting_fields", além de replacement, sunset_date e migration_url quando se aplicam. Decida com base em error e reason. A frase a ser mostrada para uma pessoa é message.
Modelos descontinuados (410)
Um modelo que passou da data de descontinuação retorna 410 com Deprecation: true e um cabeçalho Sunset (uma data RFC 1123):
error é o valor estável "model_unavailable". replacement e migration_url são omitidos quando não há substituto recomendado. Repetir com o mesmo modelo continuará retornando 410. Mude para replacement quando ele estiver definido e veja Descontinuações.
Um modelo obsoleto, mas ainda ativo, envia Deprecation e Sunset em todas as respostas, incluindo erros. Usar um alias de campo obsoleto faz o mesmo, inclusive no seu próprio 422. Quando existe um guia de migração, um cabeçalho Link: <migration_url>; rel="deprecation" também é enviado.
Códigos de status
400
JSON inválido em generate é sempre JSON, sem precisar do cabeçalho Accept:
{ "error" } para uma URL de entrada que não consegue usar: Invalid URL for input "<key>" ou Failed to download URL for <key>: …. A mensagem de download também cobre falhas temporárias, então, ao contrário de generate (veja Downloads de entrada), uma falha de download em node app é sempre 400. Tente novamente uma vez se a URL for válida.
JSON inválido em POST /node-apps/{id}/execute não é o 400 de generate acima. Ele vira um 500 { "message": "Internal Error" }, sem texto de exceção, e segue o Accept.
Outras respostas 400 em assets e node apps são { "message": "..." } com uma explicação curta, por exemplo No file provided em um upload pré-assinado ou Invalid pagination parameters nas versões de node app. Um upload de asset com falha repassa o status do serviço de upload (400, 401, 404 ou 500) e pode colocar o texto da resposta em message. Esse texto às vezes é uma string JSON. Parâmetros de consulta inválidos em GET /jobs são 422, não 400.
401
Generate, jobs, assets, styles e node apps:
{ "message": "Presigned upload URL expired" } ou { "message": "Invalid presigned upload URL" }.
Pagamento necessário (402)
Para um cliente cobrado via API (uma chave de API, ou MCP usando uma chave de API) cujo saldo de API não cobre o job:
message para 402 na API pública:
Uma chamada de generate com Zero Data Retention em um workspace que não tem o recurso ativado retorna este corpo, sempre em JSON:
402. Eles consomem o saldo de computação do workspace, não o saldo de API.
403
404
Todo 404 é { "message" }, por exemplo um id de job desconhecido:
Accept faz com que esses erros sejam HTML, exceto o Endpoint not found para um modelo que sua chave ou seu plano não pode usar, que é sempre JSON. Um GET /jobs/{id} autenticado para um id desconhecido sem Accept é 404 text/html.
Uma operação do Agent desconhecida também é
404 { "message": "Endpoint not found" }, não o formato { "error", "code" } do Agent.
405
O corpo é texto simples sem cabeçalho Content-Type, não JSON, inclusive quando Accept é application/json. O texto é o método seguido de method not allowed, por exemplo GET method not allowed. Um cabeçalho Allow lista os métodos que o caminho aceita.
Payload grande demais (413)
Um corpo de requisição grande demais é rejeitado com 413. Vindo da própria API, o corpo segue o Accept:
413 em HTML. Não envie arquivos inline. Faça o upload do arquivo com POST /assets e passe a URL retornada na requisição de generate.
Downloads de entrada
Um host que retorna404 ou 410 gera um 422 permanente. O corpo é JSON, e o Accept importa:
410 do host usa a mesma frase com 410. Outras rejeições permanentes usam Input file rejected: ….
Uma falha de download que pode ser repetida é 502 ou 504. Decida com base no código de status, não no corpo, e tente novamente.
Um
502 que se repete para a mesma URL provavelmente significa que a URL está bloqueada ou quebrada. Troque a URL.
Falhas de conversão na exportação 3D também são 502. Esse caminho não foi testado em produção, então o corpo também pode chegar como texto simples do Cloudflare error code: 502. Decida com base no código de status e tente novamente. Um 502 que se repete para a mesma URL de modelo provavelmente significa que a URL está bloqueada ou quebrada.
429 de concorrência
Quando o job não pode entrar em backlog, uma requisição acima do limite de concorrência pode ser rejeitada com 429 e Content-Type: application/json:
limit é o seu limite de concorrência para esse tipo de job. Ele é contado por usuário, não por workspace. É aproximado: uma rajada curta pode ser aceita acima dele, então não conte que a requisição limit + 1 será a que falha. jobType é uma categoria interna de job, não o caminho público do modelo. Não tome decisões com base nele.
O Krea 2 também pode retornar apenas { "message": "CONCURRENCY_LIMIT_REACHED" }, sem limit nem jobType, quando sua fila compartilhada está cheia. Esse não é o seu limite. Aguarde e tente novamente.
O backlog só fica ativo quando o plano o inclui (Pro e superiores), o modelo oferece suporte e a requisição não é de Zero Data Retention. No momento, requisições do Krea 2 não entram em backlog em nenhum plano, então retornam 429 acima do limite. Quando ele está ativo, o job extra é aceito com status: "backlogged" e começa assim que houver uma vaga livre. Não há um limite separado para o backlog. Veja Limites de Taxa.
A API não envia Retry-After nem X-RateLimit-*. A resposta inclui cf-ray. Ao receber 429, tente novamente com backoff exponencial depois que os jobs em andamento terminarem (faça polling em GET /jobs/{id} ou use um webhook).
Se uma conclusão posterior esgotar o saldo, os jobs que ainda estão no backlog falham com error.code "insufficient_balance". Isso é um job com falha, não um HTTP 402. Esses jobs não enviam webhook, então faça polling em GET /jobs/{id} para jobs em backlog.
API de operações do Agent
POST /agent/{operation} e GET /agent/session/{sessionId} retornam { "error", "code"?, "allowedModels"? }. Apenas error é obrigatório. allowedModels está em camelCase. Um turno que falha depois de ter sido aceito aparece como status: "failed" na sessão, não como um desses erros HTTP. Veja Agent API.
Um código de erro do Agent não reconhecido continua sendo
422 com { "error", "code" }. O 404 de operação desconhecida e um 500 não tratado usam { "message" } e seguem o Accept.
error.code de jobs com falha
GET /jobs e GET /jobs/{id} definem error apenas quando status é "failed". Não há result utilizável:
As entregas de webhook de um job com falha usam o mesmo objeto de job, incluindo
error. Uma entrega de cancelamento não tem error. Um payload maior que 256 KiB não é enviado, e nenhuma outra entrega é feita para esse job, então faça polling em GET /jobs/{id}. Verifique a assinatura antes de confiar no corpo. Veja Webhooks.
Depuração
Não existe um cabeçalho de id de requisição da Krea. Toda resposta inclui o cabeçalhocf-ray do Cloudflare. Nenhum cabeçalho Retry-After ou X-RateLimit-* é enviado.
Ao escrever para support@krea.ai, inclua:
- O
job_id, quando a chamada criou ou referenciou um job - O horário e o endpoint
- Para um erro no momento da requisição, o valor de
cf-ray
Access-Control-Allow-Origin é *. Em generate, jobs, assets, styles e node apps, Access-Control-Expose-Headers não é definido, então o fetch do navegador não consegue ler cf-ray, Deprecation nem Sunset. Copie o cf-ray do log de rede ou de um cliente no servidor.
Em qualquer resposta, verifique Deprecation e Sunset antes que o modelo pare de aceitar chamadas. Veja Descontinuações.
Próximos passos
Ciclo de vida do job
Faça polling do status até o job ser concluído, falhar ou ser cancelado
Webhooks
Verifique a assinatura em uma entrega de job com falha
Limites de taxa
Quando jobs extras entram em backlog e quando retornam 429
API Keys & Billing
Adicione saldo de API depois de um 402