# Erros

> Um documento de problema legível por máquina para cada falha, e o que cada tipo significa para a sua lógica de repetição.

Source: https://developers.backresto.com/pt/docs/errors

Todas as falhas (incluindo uma rota que não existe) respondem com
`application/problem+json`, o formato definido pela RFC 9457. Não há caminho
nesta API que devolva uma página de erro em HTML, por isso um parser que assuma
JSON numa resposta não-2xx está seguro.

```json
{
  "type": "https://api.backresto.com/problems/forbidden",
  "title": "Forbidden",
  "status": 403,
  "detail": "The authenticated client lacks the required scope.",
  "instance": "/v1/restaurants/restaurant-1/collections/delivery-pictures/records/8f2c/assets",
  "requestId": "b1c8b0a4-6c1e-4f6b-9e1c-3b2a5d7f0e91"
}
```

`type` é o identificador estável: ramifique com base nele, não em `detail`, que
é prosa e pode ser reescrito. `requestId` é o valor a citar numa mensagem para
o suporte. É também devolvido no cabeçalho de resposta `X-Request-ID`, e pode
definir esse cabeçalho você mesmo para correlacionar com os seus próprios
rastreios.

## O catálogo

| Sufixo de `type` | Estado | O que aconteceu | Repetir? |
| --- | --- | --- | --- |
| `invalid-request` | 400 | Falta um parâmetro ou está malformado: um `limit` fora dos limites, uma coleção desconhecida, ou um cursor que não corresponde ao restaurante, à coleção e ao `limit` com que está a paginar. | Não. Corrija o pedido. |
| `unauthorized` | 401 | Sem cabeçalho `Authorization`, ou uma chave malformada, desconhecida, revogada, expirada, ou que ficou sem concessão nenhuma. | Não. A chave precisa de atenção. |
| `forbidden` | 403 | A chave tem uma concessão para este restaurante, mas não o scope de que este endpoint precisa. | Não. O cliente tem de mandar emitir uma chave com esse scope. |
| `not-found` | 404 | Sem concessão para este restaurante, ou esse registo não existe. As situações são deliberadamente indistinguíveis. | Não. |
| `conflict` | 409 | O pedido entra em conflito com um recurso existente. | Não. |
| `payload-too-large` | 413 | O corpo do pedido excede o limite. | Não. |
| `rate-limit-exceeded` | 429 | O seu cliente ultrapassou o orçamento de pedidos. | Sim, depois de `Retry-After`. |
| `dependency-unavailable` | 503 | Um componente de que a API precisa está brevemente indisponível. | Sim, com recuo progressivo. |
| `internal-error` | 500 | Uma falha inesperada, já registada do nosso lado. | Uma vez, com recuo progressivo; depois diga-nos o `requestId`. |

## O que um cliente deve fazer

Três grupos, e mais nada justifica escrever código:

**Não repetir**: 400, 401, 403, 404, 409, 413. O pedido vai falhar outra vez
exatamente da mesma maneira. Registe o `type` e o `requestId`, e mostre-os: um
`401`, em particular, significa que uma pessoa do lado do seu cliente revogou
alguma coisa, e um ciclo de tentativas só vai esconder isso durante uma semana.

**Repetir com recuo progressivo**: 429, 503. Respeite o `Retry-After` num 429;
é o número de segundos até o seu orçamento voltar a encher, e não é uma
sugestão. Para o 503, recuo exponencial com variação aleatória, e desista em
vez de martelar.

**Repetir uma vez e depois escalar**: 500. Se voltar a acontecer no mesmo
pedido, não é transitório.

Todos os endpoints desta API são `GET`, por isso repetir é sempre seguro do
ponto de vista da API; a razão para não repetir um 4xx é que desperdiça o seu
orçamento, não que arrisque uma escrita duplicada.

## Correlacionar com os seus próprios registos

Envie o seu próprio identificador e ele volta:

```bash
curl "https://api.backresto.com/v1/restaurants/$RESTAURANT_ID/collections/deliveries/records?limit=100" \
  -H "Authorization: Bearer $BACKRESTO_PARTNER_API_KEY" \
  -H "X-Request-ID: 3f7a1c9e-2b4d-4a86-9f0c-5e1d8b6a2c40" \
  --include
```

O valor é repetido no cabeçalho da resposta e no `requestId` de um documento de
problema, o que faz com que um único grep responda a «o que é que o BackResto
viu quando o meu processo falhou às 04:12?».
