> ## Documentation Index
> Fetch the complete documentation index at: https://docs.niadra.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Erros

> Respostas application/problem+json, o catálogo de códigos e o que fazer com cada um.

Todo erro da API da Niadra tem o mesmo formato e um código estável. O seu código decide pelo `code`, nunca pelo texto de `detail`, que pode mudar. Os códigos são versionados junto do OpenAPI da `/v1`: dentro de uma versão, um código nunca muda de sentido.

## O documento de problema

Os erros respondem com `Content-Type: application/problem+json`, o formato da RFC 9457.

```json theme={null}
{
  "type": "https://docs.niadra.com/errors/scope_missing",
  "title": "scope missing",
  "status": 403,
  "detail": "this key lacks the `act` scope",
  "code": "scope_missing",
  "request_id": "req_01J8ZK4Q6T"
}
```

| Campo        | Descrição                                                                                                                          |
| ------------ | ---------------------------------------------------------------------------------------------------------------------------------- |
| `type`       | Uma URI do tipo de problema: `https://docs.niadra.com/errors/<code>`.                                                              |
| `title`      | O código por extenso, como `scope missing`.                                                                                        |
| `status`     | O status HTTP, repetido no corpo.                                                                                                  |
| `detail`     | O que aconteceu nesta requisição. Nunca traz dado pessoal: handle, texto de mensagem e documento ficam fora das mensagens de erro. |
| `code`       | O código estável do catálogo abaixo.                                                                                               |
| `request_id` | O id da requisição. Informe quando falar com o suporte. Toda resposta traz esse id, com sucesso ou não.                            |

## O catálogo

| Código                     | Status | SDK de Python              | SDK de TypeScript           | O que fazer                                                                                                                                                                                                                                                                                                                                  |
| -------------------------- | ------ | -------------------------- | --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `invalid_input`            | 422    | `UnprocessableEntityError` | `NiadraAPIError`            | O corpo não bate com o contrato: campo desconhecido, campo obrigatório faltando, valor fora do limite, uma correção sem os campos que a ação dela pede, um lote acima de 2,5 MB ou de 500 itens. `detail` lista o caminho do campo e o tipo do erro, nunca o valor enviado. Corrija a requisição; repetir o mesmo corpo dá a mesma resposta. |
| `verification_not_allowed` | 422    | `UnprocessableEntityError` | `NiadraAPIError`            | Um `verify` declarou nível acima do teto da sua fonte. Agente automatizado para em V2; V3 exige fonte que executa OTP; V4 é para mesa humana e sistema de registro. Mude a fonte no Console, não a requisição.                                                                                                                               |
| `about_without_link`       | 422    | `UnprocessableEntityError` | `NiadraAPIError`            | `about` citou uma conta ou parceiro sem vínculo ativo com a pessoa. A resposta nunca diz se a organização existe. Crie o vínculo com [`POST /v1/identity/links`](/api/identity-links), ou leia sem `about`.                                                                                                                                  |
| `unauthenticated`          | 401    | `AuthenticationError`      | `NiadraAuthenticationError` | Chave ausente, mal formada, girada ou revogada. Não tente de novo. Os SDKs descartam o contexto guardado daquela chave num 401.                                                                                                                                                                                                              |
| `forbidden`                | 403    | `PermissionDeniedError`    | `NiadraPermissionError`     | A chave é válida mas não pode fazer isso, ou o acesso da fonte dela foi cortado; ou a pessoa do Console não tem um papel da rota; ou uma pessoa `vendor` perguntou por uma fonte fora do vínculo dela.                                                                                                                                       |
| `scope_missing`            | 403    | `PermissionDeniedError`    | `NiadraPermissionError`     | A chave não tem o escopo da rota: `track`, `act`, `context`, `search`, `identify`, `admin` ou `analytics`. Crie uma chave com o escopo.                                                                                                                                                                                                      |
| `operation_not_allowed`    | 403    | `PermissionDeniedError`    | `NiadraPermissionError`     | Uma ação usou operação ou tipo de objeto que o escopo `act` desta fonte não permite.                                                                                                                                                                                                                                                         |
| `not_found`                | 404    | `NotFoundError`            | `NiadraAPIError`            | O item, objeto ou recurso não existe neste espaço, ou a política da sua fonte não deixa ver.                                                                                                                                                                                                                                                 |
| `conflict`                 | 409    | `ConflictError`            | `NiadraAPIError`            | A mesma `Idempotency-Key` foi enviada com outro corpo nas últimas 24 horas. Use uma chave nova para uma requisição nova.                                                                                                                                                                                                                     |
| `wrong_cell`               | 421    | `WrongCellError`           | `NiadraAPIError`            | O espaço está mudando de célula. Tente de novo na hora, numa conexão nova; os dois SDKs fazem isso por você.                                                                                                                                                                                                                                 |
| `rate_limited`             | 429    | `RateLimitError`           | `NiadraRateLimitError`      | Passou do limite do espaço ou da chave. Espere os segundos de `Retry-After`. A leitura é a última coisa a ser limitada.                                                                                                                                                                                                                      |
| `internal_error`           | 500    | `ServerError`              | `NiadraAPIError`            | Algo falhou do nosso lado. Tente de novo com recuo e mande o `request_id` se continuar.                                                                                                                                                                                                                                                      |
| `unavailable`              | 503    | `ServerError`              | `NiadraAPIError`            | Uma dependência está fora por um momento. Tente de novo depois do `Retry-After`; as escritas esperam na fila do SDK até lá.                                                                                                                                                                                                                  |

Uma rota que pede pessoa, como os vereditos de revisão, responde 403 `forbidden` a uma chave de fonte. Os tamanhos estão em [Limites e convenções](/conventions).

No SDK de Python, `code` e `request_id` são propriedades de `APIError`, e `problem` traz o corpo já lido. No SDK de TypeScript, `NiadraAPIError` tem `status`, `code`, `requestId` e `problem`.

## Erros dentro de um lote

[`POST /v1/batch`](/api/batch) responde 200 quando todos os itens entraram e 207 quando algum foi recusado; [`POST /v1/feedback`](/api/feedback) e o [webhook de sistema](/api/ingest-webhook) respondem do mesmo jeito. Os códigos de item são os do catálogo, mais `too_large`, para um item acima de 1 MB. Um item ruim nunca derruba o lote: os itens válidos são gravados e cada item recusado volta com a posição dele.

```json theme={null}
{
  "accepted": 41,
  "duplicates": 2,
  "errors": [
    { "index": 7, "code": "invalid_input", "detail": "a system event needs `canonical_type`" },
    { "index": 19, "code": "verification_not_allowed", "detail": "level V4 is above the ceiling of this source" }
  ]
}
```

| Campo        | Descrição                                                                              |
| ------------ | -------------------------------------------------------------------------------------- |
| `accepted`   | Itens gravados.                                                                        |
| `duplicates` | Itens cuja `idempotency_key` já estava gravada. Contados, nunca gravados duas vezes.   |
| `errors`     | Uma entrada por item recusado: `index` (a posição dele em `items`), `code` e `detail`. |

Duplicata não é erro: reenviar um lote depois de um tempo esgotado é seguro. Os SDKs registram no log os itens recusados, com o código, e os descartam, porque o mesmo item seria recusado de novo.

## Novas tentativas

| Resposta                         | Leituras (`context`, navegação)                                               | Escritas (lote, identify, verify)                                 |
| -------------------------------- | ----------------------------------------------------------------------------- | ----------------------------------------------------------------- |
| 421                              | Repetida na hora, dentro do tempo máximo                                      | Repetida na hora                                                  |
| 429                              | Python: repetida quando o `Retry-After` cabe no tempo. TypeScript: não repete | Repetida depois do `Retry-After`                                  |
| 500, 502, 503, 504, erro de rede | Python: repetida com recuo, dentro do tempo. TypeScript: não repete           | Repetida com recuo exponencial e variação aleatória, 3 tentativas |
| 408                              | Não repete                                                                    | TypeScript: repetida como um 5xx. Python: final                   |
| Qualquer outro 4xx               | Final                                                                         | Final                                                             |

Os dois SDKs dão às leituras um tempo total curto e próprio, então uma nova tentativa nunca faz o agente esperar além dele. No modo padrão, uma leitura que falha resolve com um valor vazio ou com o último valor bom, e o agente segue sem a memória naquele turno.

## Rastrear uma requisição

Mande um cabeçalho `traceparent` do W3C, e a Niadra continua o seu rastro; toda resposta traz `request_id`. Informe o `request_id` quando falar com a gente. Os erros dos SDKs expõem esse id como `request_id` em Python e `requestId` em TypeScript.

## Próximos passos

<CardGroup cols={2}>
  <Card title="Limites e convenções" href="/conventions">
    idempotência, paginação, limites de taxa e tamanhos.
  </Card>

  <Card title="SDK de Python" href="/sdk/python">
    as classes de exceção e o modo estrito.
  </Card>

  <Card title="SDK de TypeScript" href="/sdk/typescript">
    as classes de erro e o `Result`.
  </Card>

  <Card title="Enviar um lote" href="/api/batch">
    as respostas 200 e 207 na referência da API.
  </Card>
</CardGroup>
