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

# Códigos de Erro — Judit API

> Lista consolidada dos códigos HTTP, application_error, exceções internas e troubleshooting da Judit API. Erros de autenticação, validação, sigilo, falhas de tribunal, rate limit e como resolver cada um.

> 🤖 Esta página é a referência única de erros da Judit API: HTTP 2xx/4xx/5xx, exceções internas (`name`), `application_error` retornados no payload (mesmo quando o HTTP é 200), e troubleshooting prático.

## Anatomia de um erro

A Judit API distingue dois tipos de erro:

<CardGroup cols={2}>
  <Card title="Erros de transporte (HTTP 4xx/5xx)" icon="plug-circle-xmark">
    A requisição falhou em validação básica, autenticação, autorização ou no servidor. O payload tem o formato `{ error: { name, message, data } }`.
  </Card>

  <Card title="Erros de aplicação (response_type: application_error)" icon="circle-exclamation">
    O HTTP é `200`, mas a consulta não trouxe o objeto esperado. Pode ser "processo não encontrado", "homônimo", sigilo, etc. Vem dentro de `responses[].response_type = application_error`.
  </Card>
</CardGroup>

## Códigos HTTP de Status

A API utiliza as convenções padrão do protocolo HTTP.

### Sucesso (2xx)

| HTTP | Significado | Quando ocorre |
| :- | :- | :- |
| `200` | **OK** | Requisição processada e dados retornados com sucesso. |
| `201` | **Created** | Recurso (ex.: novo monitoramento, nova request) criado com sucesso. |
| `202` | **Accepted** | Requisição aceita e enviada para a fila de processamento assíncrono. |

### Erros do Cliente (4xx)

| HTTP | `error.message` típico | Quando ocorre | Como resolver |
| :- | :- | :- | :- |
| `400` | `BAD_REQUEST` | Payload mal formado, campos obrigatórios ausentes, enum inválido. | Veja `error.data` — traz a lista de validações falhas. Confira o [Schema do Lawsuit](/schemas/lawsuit-object). |
| `401` | `UNAUTHORIZED` | `api-key` ausente ou inválida. | Confira o header `api-key` (sem espaço, sem `Bearer`). Ver [Autenticação](/introduction/authentication). |
| `403` | `FORBIDDEN` | A `api-key` é válida, mas não tem permissão para o recurso (ex.: feature não contratada, sigilo sem credencial). | Verifique se a feature está habilitada no seu plano e se há credencial do tribunal no [Cofre](/essentials/cofre-de-credenciais). |
| `404` | `NOT_FOUND` | Recurso inexistente — `request_id`/`tracking_id` inválido, CNJ não está no datalake. | Confirme o ID. Para CNJs novos, dispare antes uma consulta assíncrona via [`POST /requests`](/requests/requests). |
| `422` | `UNPROCESSABLE_ENTITY` | Estrutura válida mas semanticamente inválida (ex.: `search_type` incompatível com `response_type`). | Veja a tabela em [Tipos de Busca](/requests/requests#tipos-de-busca-suportados). |
| `429` | `TOO_MANY_REQUESTS` | Rate limit do plano excedido. | Implemente backoff exponencial. Cheque os headers `X-RateLimit-*` no response. |

### Erros do Servidor (5xx)

| HTTP | `error.message` típico | Quando ocorre | Como resolver |
| :- | :- | :- | :- |
| `500` | `INTERNAL_SERVER_ERROR` | Falha inesperada do lado da Judit. | Tente novamente com backoff. Se persistir, abra um chamado em `atendimento@judit.io` referenciando o `request_id`. |
| `502` / `504` | `BAD_GATEWAY` / `GATEWAY_TIMEOUT` | Tribunal de origem fora do ar ou timeout. Comum em consultas síncronas. | Tente novamente — se a falha persistir, fluxo assíncrono via [`POST /requests`](/requests/requests) é mais resiliente. |
| `503` | `SERVICE_UNAVAILABLE` | Manutenção. | Aguarde alguns minutos. Acompanhe em status.judit.io (se habilitado). |

## Estrutura do payload de erro HTTP

Independentemente do status (400 ou 500), o corpo da resposta sempre seguirá este contrato:

```json theme={null}
{
    "error": {
        "name": "HttpBadRequestError",
        "message": "BAD_REQUEST",
        "data": [
            {
                "field": "search.search_key",
                "rule": "required",
                "message": "search_key is required"
            }
        ]
    }
}
```

| Campo | Descrição |
| :- | :- |
| `error.name` | Código interno da exceção (ex.: `HttpBadRequestError`, `HttpNotFoundError`, `HttpUnauthorizedError`, `USER_NOT_FOUND`). Use no seu `switch`/`case` para automação. |
| `error.message` | Categoria amigável (`BAD_REQUEST`, `UNAUTHORIZED`, etc.). |
| `error.data` | Detalhes — array de validações ou string com mensagem específica. Útil para exibir validações de formulário ao usuário final. |

## Códigos internos (`error.name`)

Use estes valores para automação programática:

### Autenticação e permissões

| Código (`name`) | HTTP | Causa comum |
| :- | :- | :- |
| `USER_NOT_FOUND` | 401 | API key não enviada no header ou chave revogada. |
| `INSUFFICIENT_PERMISSIONS` | 403 | Tentativa de uso de módulo bloqueado no plano. |
| `HttpUnauthorizedError` | 401 | Genérico — chave inválida. |

### Validação e processamento

| Código (`name`) | HTTP | Causa comum |
| :- | :- | :- |
| `HttpBadRequestError` | 400 | JSON malformado ou campos faltando. |
| `RESOURCE_NOT_FOUND` | 404 | CNJ ainda não capturado. |
| `REQUEST_NOT_FOUND` | 404 | `request_id` consultado não existe. |
| `PROCESSING_ERROR` | 422 | Robô falhou ao ler dados no tribunal. |

## Erros de aplicação (`application_error`)

Quando você recebe `response_type: application_error` em vez do payload esperado, a consulta foi processada com sucesso mas o resultado é uma exceção lógica.

| `response_data.code` | Significado | Quando ocorre | Como resolver |
| :- | :- | :- | :- |
| `LAWSUIT_NOT_FOUND` | Processo não encontrado. | CNJ inexistente ou não acessível. | Verifique o número e tribunal. Pode ser sigiloso — adicione `customer_key` (Cofre). |
| `ENTITY_NOT_FOUND` | Pessoa/empresa não localizada. | CPF/CNPJ não consta no datalake nem no tribunal. | Tente `on_demand: true` para forçar coleta no tribunal. |
| `WARRANT_NOT_FOUND` | Mandado não encontrado no BNMP. | Sem mandados para o documento informado. | Tente busca por `name` ou `rji` se aplicável. |
| `EXECUTION_NOT_FOUND` | Execução penal não encontrada. | Sem registros para o documento. | Confira o tribunal de origem (Justiça da Execução Penal). |
| `INVALID_CREDENTIAL` | Credencial do Cofre inválida ou expirada. | Token/login do tribunal expirou. | Atualize a credencial no [Cofre](/essentials/cofre-de-credenciais). |
| `CRAWLER_ERROR` | Falha na coleta do tribunal. | Tribunal fora do ar, captcha mal resolvido, mudança de layout. | Tente novamente. Se persistir, fluxo de fallback automático é acionado. |
| `RATE_LIMIT_TRIBUNAL` | Tribunal limitou a coleta. | Limite imposto pelo próprio tribunal. | A Judit retoma automaticamente no próximo ciclo. Use `cache_ttl_in_days` maior. |
| `SECRECY_RESTRICTED` | Processo em sigilo sem credencial associada. | `secrecy_level > 0` e a `api-key` não tem credencial do tribunal. | Cadastre uma credencial no [Cofre](/essentials/cofre-de-credenciais) e referencie via `customer_key`. |
| `HOMONYM_AMBIGUOUS` | Busca por nome resultou em homônimos. | Nome muito comum, sem critério adicional. | Refine via CPF/CNPJ ou aplique filtros (`tribunals`, `state`). |

### Exemplo de application\_error

```json theme={null}
{
    "request_id": "87d9f7bf-0071-41ee-a721-e6e1b4082bc9",
    "responses": [
        {
            "response_id": "b6c1a4f0-1234-5678-9abc-def012345678",
            "response_type": "application_error",
            "response_data": {
                "code": "LAWSUIT_NOT_FOUND",
                "message": "Lawsuit 0000000-00.0000.0.00.0000 not found in datalake or court."
            }
        }
    ]
}
```

## Handler centralizado (código pronto)

Crie um interceptador único para logar e tratar os erros da Judit API.

<CodeGroup>
  ```python Python theme={null}
  import requests, os

  def handle_judit_error(response: requests.Response) -> None:
      """Decodifica e trata erros da Judit API."""
      if response.status_code < 400:
          return
      try:
          payload = response.json()
          error_block = payload.get('error', {})
          error_name = error_block.get('name', 'UNKNOWN_ERROR')
          error_details = error_block.get('data', [])
          print(f"❌ HTTP {response.status_code}: {error_name}")
          if error_details:
              print("Detalhes:")
              for detail in error_details:
                  print(f"  - {detail}")
          if error_name == 'USER_NOT_FOUND':
              raise PermissionError("API key inválida. Verifique JUDIT_API_KEY.")
          if response.status_code == 429:
              print("⚠️ Rate limit excedido. Acione backoff.")
      except ValueError:
          print(f"Erro crítico {response.status_code}: resposta não é JSON válido.")
          print(response.text)
  ```

  ```javascript Node.js theme={null}
  async function handleJuditError(response) {
    if (response.ok) return;
    try {
      const payload = await response.json();
      const errorBlock = payload.error || {};
      const errorName = errorBlock.name || 'UNKNOWN_ERROR';
      const errorDetails = errorBlock.data || [];
      console.error(`❌ HTTP ${response.status}: ${errorName}`);
      if (errorDetails.length > 0) {
        console.error("Detalhes:");
        errorDetails.forEach(detail => console.error(`  - ${JSON.stringify(detail)}`));
      }
      if (errorName === 'USER_NOT_FOUND') {
        throw new Error("API key inválida. Verifique JUDIT_API_KEY.");
      }
      if (response.status === 429) {
        console.warn("⚠️ Rate limit excedido. Acione backoff.");
      }
    } catch (e) {
      if (e.name !== 'SyntaxError') throw e;
      console.error(`Erro crítico ${response.status}: resposta não é JSON válido.`);
    }
  }
  ```
</CodeGroup>

## Padrões de tratamento

<AccordionGroup>
  <Accordion title="Backoff exponencial em 429 e 5xx">
    Implemente retry com jitter:

    ```python theme={null}
    import time, random
    for attempt in range(5):
        resp = requests.post(url, headers=h, json=body)
        if resp.status_code < 500 and resp.status_code != 429:
            break
        sleep = (2 ** attempt) + random.random()
        time.sleep(sleep)
    ```

    O header `Retry-After` (quando presente) deve ser respeitado.
  </Accordion>

  <Accordion title="Idempotência via `callback_id`">
    O webhook reentrega em caso de falha. Sempre cheque `callback_id` antes de processar — guarde em uma tabela (id, recebido\_em). Se já existe, ignore.
  </Accordion>

  <Accordion title="Distinção `application_error` vs HTTP 4xx">
    Trate `application_error` como **resultado válido** da consulta (a integração está OK), enquanto HTTP 4xx indica que **a chamada** está errada. Logue separadamente no monitoramento.
  </Accordion>

  <Accordion title="Sigilo (`secrecy_level`)">
    Quando o processo é sigiloso e a `api-key` não tem credencial registrada para o tribunal, a Judit retorna `application_error: SECRECY_RESTRICTED`. Para acessar, cadastre a credencial do advogado no [Cofre](/essentials/cofre-de-credenciais) e referencie via `customer_key` na própria consulta.
  </Accordion>

  <Accordion title="Quotas e limites">
    Ao receber 429, leia `X-RateLimit-Limit`, `X-RateLimit-Remaining` e `X-RateLimit-Reset` para ajustar o disparo. Para fluxos em massa, adote janela deslizante.
  </Accordion>
</AccordionGroup>

## Tabela de troubleshooting rápida

| Sintoma | Hipótese mais provável | Próximo passo |
| :- | :- | :- |
| HTTP 401 sempre | Header `api-key` ausente / valor errado / espaço/quebra de linha. | `echo $JUDIT_API_KEY \| wc -c` — confira o tamanho. |
| HTTP 403 em rota específica | Feature não habilitada no plano. | Falar com a Judit no `atendimento@judit.io`. |
| `LAWSUIT_NOT_FOUND` em CNJ existente | CNJ está em sigilo. | Ver [Cofre de Credenciais](/essentials/cofre-de-credenciais). |
| Webhook não chega | URL não pública/HTTPS, ou retornando ≠ 2xx. | Confira em [Webhook](/webhook/callbacks#requisitos-do-endpoint). |
| 2 webhooks com mesmo `request_id` | Comportamento esperado — primeiro vem do cache (`cached_response: true`), segundo do tribunal. | Veja [cached\_response](/webhook/callbacks#duas-respostas). |
| Tracking sem novos eventos | `recurrence` muito alta ou `notification_filters.step_terms` muito restrito. | Reduza recurrence; relaxe filtros. |
| Resposta vazia em `name` | Homônimo ou nome com acentos. | Buscar por CPF/CNPJ; remover acentos para teste. |

## Próximos passos

* 👉 **[Rate Limits](/essentialConcepts/rate-limits)** — função de Retry com Exponential Backoff para tratar `429`.
* 👉 **[Autenticação](/introduction/authentication)** — como enviar credenciais corretamente para evitar `401`.
* 👉 **[Webhook & Callbacks](/webhook/callbacks)** — comportamento de reentregas e idempotência.
* 👉 **[Glossário](/resource/glossary)** — termos técnicos referenciados


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.