# Erros

> **In English.** Errors follow RFC 9457 Problem Details (`application/problem+json`). `400` means a
> business rule was not met, `422` means the payload itself was rejected (malformed JSON or failed
> validation), `401` and `403` are authentication and plan features, `404` appears only where an
> operation declares it, and `500` is an internal failure to report with `requestId` and `traceId`.
> `400` and `422` are final: repeating the same request produces the same error. Text in Brazilian
> Portuguese.

## Formato

Erros vêm com `Content-Type: application/problem+json` e o corpo `ProblemDetailsResult`:

| Campo | O que traz |
|---|---|
| `type` | URI que identifica o tipo do problema (a seção da RFC 9110 do status). |
| `title` | Nome do status, em inglês (`Bad Request`, `Unprocessable Entity`). |
| `status` | O status HTTP, repetido no corpo. |
| `detail` | Explicação em texto, quando existe (por exemplo, nos `401` de trial expirado e de grupo sem plano). |
| `instance` | Método e caminho da requisição. |
| `errors` | Lista de mensagens, em português. É onde estão as mensagens de regra de negócio e de validação. |
| `problems` | Uma entrada por problema, com `message` e `propertyName` (o campo do payload, quando o erro é de um campo). |
| `traceId`, `spanId`, `requestId` | Identificadores de rastreio. Informe-os ao suporte. |

Exemplo ilustrativo de `422`, com um campo inválido:

```json
{
  "type": "https://tools.ietf.org/html/rfc9110#section-15.5.21",
  "title": "Unprocessable Entity",
  "status": 422,
  "instance": "POST /partners/v1/accounts/0199143a-7c2e-7b1a-9f2d-3c4b5a6d7e8f/document-signatures",
  "errors": ["O e-mail do signatário é inválido."],
  "problems": [
    { "message": "O e-mail do signatário é inválido.", "propertyName": "signers[0].email" }
  ],
  "traceId": "00-9d5ae161cadc20cdb55a260d9f4b5453-184806a3008259ec-00",
  "spanId": "184806a3008259ec",
  "requestId": "0HNOA3C9U49GU:00000001"
}
```

Exemplo ilustrativo de `400`, com uma regra de negócio:

```json
{
  "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
  "title": "Bad Request",
  "status": 400,
  "instance": "POST /partners/v1/accounts/0199143a-7c2e-7b1a-9f2d-3c4b5a6d7e8f/document-signatures",
  "errors": ["Um ou mais papéis (Fiador) não existe(m)"],
  "problems": [],
  "traceId": "00-1c4f0b2d9a8e7f6c5b4a39281706f5e4-5b4a39281706f5e4-00",
  "spanId": "5b4a39281706f5e4",
  "requestId": "0HNOA3C9U49GU:00000002"
}
```

As mensagens exatas variam por operação; a referência de cada operação lista as principais.

## O que cada status significa

| Status | Quando acontece | Corpo |
|---|---|---|
| `400` | Regra de negócio não satisfeita: recurso inexistente na conta, documento em estado que não permite a operação, recurso do plano ausente (SMS, WhatsApp, biometria), cota atingida, duplicidade. | Problem Details, mensagens em `errors`. |
| `401` | Chave ausente ou inválida, conta não vinculada, trial expirado, grupo de faturamento sem plano ativo. | Vazio, exceto nos dois últimos casos (motivo em `detail`). |
| `403` | O plano da conta não inclui uma feature exigida pela operação. | Vazio. |
| `404` | Recurso não encontrado, nas consultas por identificador que declaram `404` (por exemplo, a situação das assinaturas de um documento que não é da conta). | Problem Details. |
| `422` | Payload rejeitado: JSON malformado ou campos que não passaram na validação (obrigatórios, tamanhos, formatos, combinações). | Problem Details, `errors` e `problems` com o campo. |
| `500` | Erro interno. | Problem Details com `requestId` e `traceId`. |

A distinção que mais importa: **`422` é sobre a forma** da requisição (o JSON e os campos) e
**`400` é sobre o estado** (o que a conta, o documento ou o plano permitem agora). Os dois são
definitivos para a mesma requisição.

## O que vale repetir

- `400` e `422`: corrija a requisição. Repetir igual produz o mesmo erro.
- `401`: confira chave, ambiente e vínculo da conta. Veja [Autenticação e contas](https://api.letssign.com.br/docs/guides/autenticacao-e-contas).
- `403`: o plano não tem a feature. Confira `partners_v1_features_list`.
- `404`: o identificador está errado ou pertence a outra conta.
- `500`: pode repetir com espera crescente (por exemplo, três tentativas a partir de 2 segundos).
  Persistindo, informe `requestId` e `traceId` ao suporte.
- **Tempo esgotado sem resposta**: a operação pode ter sido executada. As criações não têm chave de
  idempotência: `partners_v1_document_signatures_create_from_file` e `partners_v1_forms_create`
  criam um documento novo a cada chamada e consomem cota. Antes de repetir, confira se o recurso
  existe (`partners_v2_documents_list` filtrando por `Name` e `CreatedFrom`). Já os upserts de
  contato (`partners_v1_contacts_upsert_person`, `partners_v1_contacts_upsert_company`) são
  idempotentes, e criações com chave natural, como webhooks (URL) e usuários (e-mail), respondem
  `400` na repetição em vez de duplicar.

Não há limite de requisições por chave hoje, então não existe `429`; se um dia houver, ele
aparecerá neste guia e no [changelog](https://api.letssign.com.br/docs/guides/changelog).

## Mensagens frequentes

| Mensagem em `errors` | Operação | Causa e saída |
|---|---|---|
| `Um ou mais papéis (...) não existe(m)` | criação e edição de signatários | O `role` não existe na conta. Consulte `partners_v1_document_signature_roles_list`. |
| `Um ou mais grupos (...) não existe(m) ou está(ão) inativo(s)` | criação de documento, criação de formulário e atualização de grupos do documento | `422`: o id não é grupo **ativo** da conta. Consulte `partners_v1_groups_list`; grupo desativado no aplicativo deixa de ser aceito. |
| `Nenhum signatário assinou o documento até o momento.` | download do assinado | Ainda não há assinatura. Aguarde `DocumentSignatureMember` ou consulte a situação. |
| `A URL ... já é usada como webhook na conta` | cadastro de webhook | A URL já está cadastrada; liste com `partners_v1_webhooks_list`. |
| `Conta não existe`, `Parceiro não pode realizar operações na conta solicitada` | troca de logotipo | O `id` não é de uma conta vinculada ao parceiro. |
| Tags faltando no formulário | criação de formulário | Toda tag do modelo precisa estar em `fillers[].fieldsTags` ou em `filledFields`; a mensagem lista quais faltam. |
