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

# Erros

> Um formato só, sete códigos, e quais deles vale reenviar.

Todo erro da API vem como JSON com um campo:

```json theme={null}
{ "error": "Descrição do que deu errado" }
```

<Warning>
  Trate erro pelo **código HTTP**, nunca pelo texto. A mensagem existe para você ler no
  log e pode mudar sem aviso. O código não muda.
</Warning>

## Códigos

| Código | Significa                                                                            | Reenviar?                                     |
| ------ | ------------------------------------------------------------------------------------ | --------------------------------------------- |
| `400`  | Parâmetro ausente, inválido ou fora do limite                                        | Só depois de corrigir                         |
| `401`  | Chave ausente, inválida, revogada ou com prefixo errado                              | Não. Veja [Autenticação](/guias/autenticacao) |
| `403`  | Chave válida, operação não permitida (sandbox com chave live, conta sem verificação) | Não. Resolva no painel                        |
| `404`  | Recurso não existe ou não é da sua conta                                             | Não                                           |
| `409`  | Conflito de estado (saque turbo já em andamento)                                     | Sim, depois de esperar                        |
| `429`  | Passou do [limite de requisições](/guias/limites)                                    | Sim, com backoff                              |
| `500`  | Erro inesperado no servidor                                                          | Sim, com backoff                              |
| `502`  | Falha temporária junto ao provedor                                                   | Sim, com backoff                              |
| `503`  | Recurso indisponível no momento (carteira LTC ausente, cripto fora do ar)            | Sim, mais tarde                               |

<Note>
  `404` em vez de `403` para recurso de outra conta é proposital. A API não confirma que um
  id existe se ele não é seu.
</Note>

## Mensagens que você vai encontrar

<AccordionGroup>
  <Accordion title="400 — validação" icon="circle-exclamation">
    | Mensagem                                                   | Causa                                                                             |
    | ---------------------------------------------------------- | --------------------------------------------------------------------------------- |
    | `valueCents must be >= 80 (R$ 0.80), or provide productId` | Valor abaixo do mínimo da loja. O número na mensagem é o mínimo real da sua conta |
    | `priceCents must be >= 100 (R$ 1.00)`                      | Produto abaixo de R\$ 1,00                                                        |
    | `callbackUrl must be a valid, public HTTPS URL`            | URL sem HTTPS, com IP, `localhost` ou rede privada                                |
    | `paymentMethod must be 'pix' or 'ltc'`                     | Método desconhecido                                                               |
    | `Invalid product ID format`                                | O id não é um ObjectId válido                                                     |
    | `Turbo payouts are PIX-only.`                              | `turbo: true` com `method` diferente de `pix`                                     |
  </Accordion>

  <Accordion title="401 — autenticação" icon="key">
    | Mensagem                                                   | Causa                                    |
    | ---------------------------------------------------------- | ---------------------------------------- |
    | `API key required. Use: Authorization: Bearer ps_live_...` | Header ausente ou malformado             |
    | `Invalid API key prefix. Use ps_live_ or ps_test_`         | Prefixo desconhecido                     |
    | `Invalid or revoked API key`                               | Chave inexistente ou revogada            |
    | `API key environment mismatch. Please generate a new key.` | Prefixo não bate com o ambiente da chave |
  </Accordion>

  <Accordion title="403 — permissão" icon="lock">
    | Mensagem                                                          | Causa                                         |
    | ----------------------------------------------------------------- | --------------------------------------------- |
    | `Sandbox endpoint requires ps_test_ key`                          | Rota de sandbox chamada com chave de produção |
    | `PIX not verified. Complete verification in the dashboard first.` | Saque antes de verificar a chave PIX          |
  </Accordion>

  <Accordion title="404 e 502" icon="magnifying-glass">
    | Mensagem                | Causa                                          |
    | ----------------------- | ---------------------------------------------- |
    | `Product not found`     | Produto inexistente, inativo ou de outra conta |
    | `Charge not found`      | Cobrança inexistente ou de outra conta         |
    | `Payment not found`     | Pagamento inexistente ou de outra conta        |
    | `LTC price unavailable` | Cotação de Litecoin fora do ar no momento      |
  </Accordion>
</AccordionGroup>

## Como tratar

```js theme={null}
async function chamar(url, opcoes, tentativas = 4) {
  for (let i = 0; i < tentativas; i++) {
    const res = await fetch(url, opcoes);
    if (res.ok) return res.json();

    const { error } = await res.json().catch(() => ({ error: res.statusText }));

    // Erro do cliente: reenviar não resolve, só queima requisição.
    if (res.status < 500 && res.status !== 429) {
      throw new Error(`${res.status}: ${error}`);
    }

    // 429, 5xx: vale esperar. Backoff com jitter pra não sincronizar rajada.
    const espera = 2 ** i * 1000 + Math.random() * 1000;
    await new Promise((r) => setTimeout(r, espera));
  }
  throw new Error("limite de tentativas excedido");
}
```

<Tip>
  Registre o corpo `{ "error": ... }` junto do código HTTP e do `paymentId` nos seus logs.
  Quando você chamar a gente [no Discord](https://discord.gg/8eyQQFZZxY), é essa tripla que
  resolve em uma resposta em vez de cinco.
</Tip>
