# Limites e tempos

> Limites por endpoint e por adquirente, tempo de resposta, Retry-After e o que fazer em cada caso.

Fonte: https://app.thronecorporate.com/docs/limites

## Resumo

| O quê | Limite | Passou do limite |
|---|---|---|
| Chamadas com chave válida | Sem limite geral | Não se aplica |
| `POST /transactions` (Pix) | 10 por segundo por conta | `429 rate_limit_exceeded`, com `Retry-After` |
| `POST /elements/checkout` (cartão) | Sem limite por conta. Cada adquirente tem uma capacidade de criação, dividida entre todas as contas | `503 temporarily_unavailable`, com `Retry-After` |
| `POST /withdrawals` | 1 por minuto por conta, mais o limite diário da conta | `429 rate_limited` ou `429 daily_limit_exceeded` |
| Chamadas sem credencial válida | 10 por segundo por IP | `429`, com `Retry-After` |
| Valor de uma venda no cartão | Mínimo e máximo por adquirente, que variam com a moeda e com a cotação do dia | `422 invalid_amount`, com o limite na moeda que você mandou |
| Validade do checkout de cartão | 24 horas | A venda vira `expired` |
| Validade da `Idempotency-Key` | 24 horas, na conta inteira | Não se aplica |

## Tempo de resposta

| Chamada | Timeout recomendado no seu cliente HTTP |
|---|---|
| `POST /elements/checkout` e `POST /elements/checkout/br` | 60 segundos |
| Todas as outras | 20 segundos |

A criação do checkout de cartão fala com a adquirente. Na maior parte das vezes a resposta sai em poucos segundos, mas em pico pode passar de 40 segundos. Não corte antes de 60 segundos: se você desistir de uma chamada que deu certo, perde um checkout criado.

Se o timeout estourar mesmo assim, repita com a **mesma** `Idempotency-Key` e o mesmo corpo. A regra completa está em [como repetir com segurança](/docs/comecar#como-repetir-uma-chamada-com-seguranca).

## Quando a resposta é 429 ou 503

`429` e `503` dizem que nada foi criado e que vale tentar de novo daqui a pouco.

1. Leia o header `Retry-After` (em segundos) e espere pelo menos esse tempo.
2. Repita com uma `Idempotency-Key` nova.
3. Se vier de novo, aumente a espera a cada tentativa (recuo exponencial) e some uma variação aleatória. Assim várias repetições não chegam todas no mesmo segundo.
4. Pare depois de poucas tentativas. Mostre ao comprador um "tente em instantes" ou ofereça outro meio de pagamento.

No cartão, o `503` traz também `"retryable": true`. Ele aparece quando a adquirente está sem capacidade, instável ou em pausa. Com mais de uma adquirente habilitada, você pode criar o checkout na outra, com o campo `acquirer` ([como escolher](/docs/cartao/escolher)).

Exemplo em Node.js, com timeout, repetição segura e recuo:

```js Node.js
import { randomUUID } from 'node:crypto';

const esperar = (s) => new Promise((r) => setTimeout(r, s * 1000));

async function criarCheckout(corpo, tentativas = 4) {
  let chave = randomUUID(); // guarde junto do pedido
  for (let i = 0; i < tentativas; i++) {
    let res;
    try {
      res = await fetch('https://app.thronecorporate.com/api/v1/elements/checkout', {
        method: 'POST',
        headers: {
          Authorization: `Bearer ${process.env.THRONE_PK}:${process.env.THRONE_SK}`,
          'Content-Type': 'application/json',
          Accept: 'application/json',
          'Idempotency-Key': chave,
        },
        body: JSON.stringify(corpo),
        signal: AbortSignal.timeout(60000),
      });
    } catch {
      continue; // sem resposta (conexão caiu ou timeout): repete com a MESMA chave
    }

    if (res.status === 409) {
      const erro = await res.json().catch(() => ({}));
      if (erro.error === 'idempotency_key_processing') {
        await esperar(3); // a primeira chamada ainda está em andamento
        continue;
      }
      return res;
    }

    if (res.status !== 429 && res.status !== 503) {
      return res; // 201 ou um erro que não se resolve repetindo
    }

    // 429 ou 503: nada foi criado. Espera e repete com chave nova.
    const retryAfter = Number(res.headers.get('Retry-After')) || 1;
    await esperar(Math.max(retryAfter, Math.min(60, 2 ** i)) * (1 + Math.random() / 2));
    chave = randomUUID();
  }
  return null; // mostre "tente em instantes" ou outro meio de pagamento
}
```

## Mínimo e máximo por venda no cartão

O mínimo e o máximo de uma venda dependem da adquirente e variam com a moeda e com a cotação do dia. Um preço perto do máximo pode passar num dia e não passar no outro.

- **Consultar antes**: `GET /elements/acquirers?currency=chf` mostra o mínimo e o máximo atuais de cada adquirente, já na moeda pedida. Os valores são indicativos e acompanham a cotação.
- **Acima do máximo**: a resposta é `422 invalid_amount`, com `max_amount_cents` na moeda que você mandou e `alternatives` com as outras adquirentes habilitadas que aceitam esse valor. Nada foi criado. Não repita o mesmo valor na mesma adquirente: divida o pedido ou crie com `acquirer` de uma das `alternatives`.
- **Abaixo do mínimo**: a resposta é `422 invalid_amount`, com o mínimo na sua moeda no `message` e no campo `min_amount_cents`.

Exemplo de resposta acima do máximo:

```json
{
  "error": "invalid_amount",
  "message": "Valor acima do máximo aceito nesta adquirente: CHF 318,90.",
  "max_amount_cents": 31890,
  "currency": "CHF",
  "alternatives": ["sterling"]
}
```

As moedas aceitas e o efeito da cotação no máximo estão em [Moedas e limites](/docs/cartao/moeda).

## Capacidade de criação no cartão

O Throne não limita quantos checkouts a sua conta cria. Cada adquirente, porém, tem uma capacidade de criação dividida entre todas as contas que usam ela. Num pico grande, ou quando a adquirente fica instável, a criação responde `503 temporarily_unavailable` com `Retry-After`, sem criar nada.

Para gastar menos capacidade e vender mais:

- Crie o checkout quando o comprador clicar em comprar, não quando a página carrega.
- Guarde o `transaction_id` na sessão do comprador e reaproveite o mesmo checkout por até 24 horas, se ele voltar à página.
- Não crie um checkout novo a cada recarga da página nem a cada tentativa de cartão: o mesmo checkout aceita várias tentativas.

## Limites por comprador na página de pagamento

A página de pagamento tem limites de uso por comprador, contra abuso e teste de cartão. Uma compra normal não chega perto deles. O que costuma esbarrar nos limites:

- recarregar o elemento em laço;
- abrir o mesmo checkout em muitas abas ao mesmo tempo;
- tentar dezenas de cartões no mesmo checkout em poucos minutos.

## Webhooks

- Responda `2xx` em até 3 segundos.
- Sem `2xx`, o Throne tenta de novo, até 10 tentativas no total, com intervalos crescentes.

Detalhes em [Webhooks](/docs/webhooks).
