PopNowDocs da API
Referência
Conteúdo principal

Erros

Cada código de negócio, o que ele significa e quais erros vale a pena tentar de novo.

Quando uma chamada dá errado, a resposta traz um número (code) que diz o tipo de problema e uma frase (msg) para uma pessoa ler. Decida pelo número; mostre ou registre a frase.

O envelope

{ "code": 40201, "msg": "Insufficient balance", "request_id": "req_…" }
  • code é um código de negócio. 200 significa sucesso; todo o resto está abaixo.
  • Em caso de falha não há campo data, exceto em alguns erros da biblioteca de assets, que acrescentam data.reason.
  • O status HTTP também vem certo (40201 chega com HTTP 402). Decida por um dos dois, sem misturar — recomendamos o code, que é mais específico.
  • request_id também vai no cabeçalho X-Request-Id. Informe-o ao falar com o suporte.

Se a resposta nem for JSON — uma página HTML ou de texto da rede no meio do caminho —, trate pelo status HTTP e registre o começo do corpo.

Idioma das mensagens de erro

msg e o errorMessage de uma tarefa com falha vêm em inglês por padrão. Envie Accept-Language com en, ja, ko, de, fr, es, pt-BR, ru, it ou pl, ou defina o idioma de erros da API no console, para recebê-los nesse idioma; os demais voltam ao inglês. Respostas de erro trazem Content-Language. Os códigos nunca mudam com o idioma — mais um motivo para nunca interpretar o msg.

Quando um modelo informa um motivo específico de falha (por exemplo, uma imagem de referência ilegível), o errorMessage repassa esse motivo em inglês, sem detalhes internos.

Códigos gerais

codeHTTPSignificadoTentar de novo?
200200 / 202Sucesso—
400400A requisição ou o input é inválido; o msg aponta o problemaNão — corrija
40003400Um upload não confere com o ticket (tamanho, tipo ou conteúdo)Não — novo ticket, novo upload
40004400Requisição válida, mas o modelo não atende essa combinação de configurações agoraNão — mude a configuração citada no msg
401401Chave ausente, desconhecida ou revogada (detalhes)Não
403403Não permitido (veja Permissões)Não
404404Não existe ou pertence a outra chaveNão
409409Conflito com o estado atual (quando tentar de novo)Às vezes
40901409Uma cotação expirou ou o preço mudouCote de novo
413413Corpo da requisição grande demaisNão — envie a mídia por upload em vez de embutir
429429Requisições demaisSim — depois de Retry-After
500500Algo quebrou do nosso ladoSim — com espera crescente
503503Um serviço de apoio ficou indisponível por um instanteSim — depois de Retry-After

Saldo e limites

codeHTTPSignificadoO que fazer
40201402Créditos insuficientes para a reserva desta tarefaCompre créditos e envie de novo
40202402Um limite de gasto da chave foi atingidoAumente no console da API ou espere ele zerar

Permissões

codeHTTPSignificadoO que fazer
40301403Esta chave não pode chamar este modeloAdicione o modelo à lista permitida da chave
40302403A requisição veio de um endereço fora da lista de IPsAdicione o endereço ou tire a restrição
40303403O serviço não é oferecido nesta regiãoNão há como contornar
40310403O e-mail da conta ainda não foi verificadoAbra o link do e-mail de cadastro; a chave funciona assim que for verificado

Um 403 simples com chave válida significa que a conta não pode usar a API no momento; fale com o suporte informando o request_id.

Disponibilidade de modelos

codeHTTPSignificadoTentar de novo?
50301503O modelo não está aceitando tarefas agoraSim, mais tarde — ou escolha outro modelo
40004400O modelo funciona, mas não com essas configuraçõesNão — mude a configuração

Nenhum dos dois cria tarefa nem reserva créditos.

Códigos de falha de tarefas

Uma tarefa aceita que depois falha tem state: "failed" e um destes valores em errorCode. A lista é fechada: trate qualquer outro valor como upstream_failed.

errorCodeSignificadoTentar de novo?
invalid_requestO modelo não aceitou os parâmetrosNão — corrija
unsupported_combinationEssa combinação de configurações não é suportada agoraNão — mude uma configuração
content_rejectedO modelo recusou esse conteúdoNão — mude o prompt ou a referência
invalid_assetUm arquivo de referência não pôde ser lido ou não está mais disponívelEnvie de novo e crie outra tarefa
rate_limitedO serviço de geração estava ocupadoSim, com espera crescente
upstream_unavailableA geração está indisponível por um tempoSim, daqui a pouco
generation_failedA geração rodou, mas não produziu nadaTalvez — a mesma entrada costuma falhar igual
timeoutA tarefa ficou sem tempoTalvez — tente uma saída mais curta ou com menos resolução
upstream_failedTodo o restoSim, com espera crescente

Uma tarefa com falha libera a reserva e não custa nada (alguns poucos modelos cobram recusas de conteúdo e avisam na própria página). O errorMessage explica o motivo em palavras; decida só pelo errorCode.

Quando vale repetir um 409

CasoTentar de novo?
Duas requisições com o mesmo Idempotency-Key chegaram juntasSim, com a mesma chave, após uma pausa curta
O Idempotency-Key já foi usado em outra requisição ou por outra chaveNão
Um upload ou um resultado ainda está em processamentoSim, depois de alguns segundos
jobs/retry numa tarefa que ainda não terminouSim, quando ela estiver final
jobs/retry numa tarefa que deu certoNão — crie uma nova tarefa
Um ticket de upload ou arquivo enviado expirouNão — envie de novo

Escrevendo a nova tentativa

Repita só o que pode dar certo na segunda vez, espere Retry-After quando ele vier e, se não vier, aumente a espera exponencialmente:

JavaScript
const RETRYABLE = new Set([429, 500, 503, 50301]);

async function call(path, init, attempts = 4) {
  for (let i = 0; i < attempts; i++) {
    const res = await fetch(`https://api.popnow.ai/api/v1${path}`, init);
    if (!res.headers.get('content-type')?.includes('json')) {
      throw new Error(`HTTP ${res.status}: ${(await res.text()).slice(0, 200)}`);
    }
    const body = await res.json();
    if (body.code === 200) return body.data;
    if (!RETRYABLE.has(body.code)) throw new Error(`${body.code} ${body.msg} (${body.request_id})`);
    const wait = Number(res.headers.get('retry-after')) * 1000 || 2 ** i * 1000 + Math.random() * 500;
    await new Promise((r) => setTimeout(r, wait));
  }
  throw new Error('out of retries');
}
Python
import random, time, requests

RETRYABLE = {429, 500, 503, 50301}

def call(method, path, attempts=4, **kwargs):
    for i in range(attempts):
        res = requests.request(method, f"https://api.popnow.ai/api/v1{path}", timeout=60, **kwargs)
        try:
            body = res.json()
        except ValueError:
            raise RuntimeError(f"HTTP {res.status_code}: {res.text[:200]}")
        if body["code"] == 200:
            return body["data"]
        if body["code"] not in RETRYABLE:
            raise RuntimeError(f'{body["code"]} {body["msg"]} ({body.get("request_id")})')
        retry_after = res.headers.get("retry-after")
        time.sleep(float(retry_after) if retry_after else 2**i + random.random() / 2)
    raise RuntimeError("out of retries")

Ao repetir createTask, envie sempre o mesmo Idempotency-Key, para que uma requisição que na verdade deu certo não seja executada nem cobrada duas vezes.

Depuração

  1. Anote o request_id e o code.
  2. Procure a tarefa nos logs do console da API, pelo ID da tarefa ou pelo request_id.
  3. Ainda travado? Fale com o suporte com o request_id, o horário (UTC) e o code. Nunca envie sua chave de API.

Nesta página