Content-Type: application/problem+json. Sem wrapper error: {} nem details
genérico.
Cada
type resolve para esta página: o slug final é a âncora da sua
seção, como #not-found-404.A forma comum
Seis campos, sempre presentes:string
obrigatório
URI canônica e estável do tipo. É o único campo que convém comparar em código.
string
obrigatório
Texto estável por tipo. Não descreve a ocorrência.
integer
obrigatório
O mesmo código HTTP da resposta.
string
obrigatório
Descreve esta ocorrência. Não faça parse dele: não é uma interface e pode
mudar sem aviso.
string
obrigatório
Alias curto em
snake_case. É uma string aberta: podem aparecer códigos
novos sem quebrar um cliente antigo. O slug de type
é o mesmo código em kebab-case.string
obrigatório
Identifica a ocorrência e coincide com o header
X-Request-ID. É o que vai em
um relatório de bug.string
Opcional na RFC 9457, e a API não o emite.
X-Request-ID. O 401 soma
WWW-Authenticate: Bearer, e o 429, Retry-After.
O catálogo completo
As extensões vão no nível raiz do Problem, não aninhadas.
invalid_request — 400
O corpo ou os parâmetros não cumprem o contrato: falta um campo obrigatório,
sobra um não declarado, ou um valor não valida.
array
obrigatório
Pelo menos um elemento, com
code e detail obrigatórios e um pointer
opcional: um JSON Pointer RFC 6901 para o campo culpado, que começa com /.
Com ele você marca o input errado em vez de mostrar um texto genérico.unauthorized — 401
Você não mandou Authorization, ou a chave que mandou não vale. É o mesmo
erro para as duas causas: distingui-las diria a um atacante se uma chave
existe.
forbidden_connection — 403
A chave autenticou bem, mas o connection_id pedido não pertence a essa
loja.
403 e não 404 porque a conexão viaja no path: o cliente já sabe que a
pediu. Para recursos de catálogo é o contrário: ver not_found.
forbidden_scope — 403
A chave autenticou bem, mas não tem o scope da operação:
recommendations:read, catalog:read ou signals:write. Uma chave não muda de
scopes: é preciso outra que o tenha.
forbidden_origin — 403
A chave autenticou bem e tem o scope, mas a página que a está usando não
é uma das origens com as quais foi emitida. Cada chave pública (spk_) nomeia
os domínios https:// de onde vale; escolhem-se ao emiti-la em API &
Agentes. Um pedido sem cabeçalho Origin (um servidor, curl, Postman) e um
desde http://localhost passam só com a chave: a regra é apenas para páginas
https.
Resolve-se emitindo uma chave que liste o domínio da loja, não mexendo no
código. Uma chave sem domínios é de servidor: não serve desde nenhum
storefront.
not_found — 404
O recurso não existe, ou existe e é de outra loja. Nenhum detail diz qual dos dois é.
conflict — 409
A requisição colide com o estado atual: uma regressão de source_version
na ingestão de catálogo. Um sinal mais velho que o aplicado não sobrescreve o
catálogo.
cart_items_limit_exceeded — 422
O carrinho de uma requisição de recomendações supera o limite configurado.
integer
obrigatório
O limite vigente,
200 por padrão. Vem na resposta para que você não o fixe
no código.integer
obrigatório
Quantos itens você mandou.
signal_batch_limit_exceeded — 422
Um lote de sinais do storefront traz mais do que o permitido.
integer
obrigatório
O limite vigente,
50 por padrão. O SDK já divide os lotes com este número.integer
obrigatório
Quantos sinais você mandou.
rate_limited — 429
A chave gastou suas 60 requisições por minuto; Retry-After diz quantos
segundos esperar. Ver Cota e cache.
internal_error — 500
Algo quebrou do lado do servidor. O detail nunca traz o stack, a
mensagem interna nem o nome de um componente.
request_id é imprescindível: conecta o que você viu com o log do
servidor.
signals_unavailable — 503
O armazenamento de sinais do storefront não está disponível. É transitório:
tente de novo com espera. O SDK faz isso sozinho, com o mesmo signal_id, e
uma nova tentativa nunca conta duas vezes.
Como tratá-los a partir do SDK
O SDK traduz qualquer um destes Problems para umCrossUpApiError tipado e
preserva as extensões que não conhece, para não quebrar quando a API somar
campos.
Use
isCrossUpApiError(err) e não err instanceof CrossUpApiError:
instanceof falha se há duas cópias do pacote na árvore de módulos.- Não se olha o
Content-Type, olha-se a forma do corpo. Um proxy pode reescrever o header, e o erro é tipado mesmo assim. - O status do transporte manda. Se o corpo declara outro, a diferença
fica em
extensions.status: é a prova de que algo no meio reescreve respostas. errorFromResponsenunca lança. Diante de HTML, corpo vazio ou JSON que não é um Problem, devolve um erro sintético comcode: "unexpected_response", o status real e o corpo cru.