# Rate limit e retry

- **Repita** apenas `429` e `5xx` (`503 unavailable`, `503 authz_unavailable`, `503 unavailable`). Todo outro `4xx` exige corrigir a requisição.
- Em `429`, espere o número de segundos do cabeçalho `Retry-After`. Sem o cabeçalho, espere 30 s e dobre a cada tentativa seguida, até 5 vezes. Reduza a concorrência.
- Em `503`, espere `Retry-After`; sem ele, use backoff de 5, 10, 20, 40 s. `unavailable` (banco) segue a mesma regra. Se persistir, pare e avise uma pessoa.
- Use **`Idempotency-Key`** em todo `POST` que cria: repetir a mesma chave com o mesmo corpo devolve a mesma resposta e não duplica. Mesma chave com outro pedido: `422 idempotency_conflict` (no upload de galeria, `409`).
- Um laço de lote completo, com 429, `Retry-After` e idempotência, está em [Galerias e arquivos](/cdn/galerias/#b-subir-em-lote-com-laço-shell-429-retry-after-e-idempotência).

## Polling de deploy com backoff

Não há webhooks neste ciclo: consulte `GET /v1/projects/{p}/services/{s}/deployments/{d}` até o estado ser final (`ready`, `failed`, `blocked`, `canceled`, `superseded`). Comece em 2 s, dobre até 30 s, desista após 20 minutos e peça uma pessoa. Estados não finais: `queued`, `building`, `deploying`. Para um deploy de **grupo**, consulte `GET /v1/projects/{p}/group-deployments/{g}`: `running` é o único não final; `ready`, `failed`, `canceled` e `superseded` são finais. Um `429` ou `503` durante o polling segue as regras acima e não interrompe o deploy, que continua no servidor.

```bash
SUF=$(date +%s)-$RANDOM
H="Authorization: Bearer $NEBULAR_TOKEN"
P=$(curl -sS -X POST "$NEBULAR_API/v1/projects" -H "$H" -H "Content-Type: application/json" \
  -d "{\"name\": \"rl1-$SUF\"}" | jq -r .id)
S=$(curl -sS -X PATCH "$NEBULAR_API/v1/projects/$P/services/web" -H "$H" -H "Content-Type: application/json" \
  -d '{"source": {"type": "image", "ref": "ghcr.io/org/app:1.0"}}' | jq -r .id)
D=$(curl -sS -X POST "$NEBULAR_API/v1/projects/$P/services/$S/deployments" -H "$H" \
  -H "Content-Type: application/json" -d '{}' | jq -r .id)

delay=2; deadline=$(( $(date +%s) + 1200 ))
while :; do
  state=$(curl -sS "$NEBULAR_API/v1/projects/$P/services/$S/deployments/$D" \
    -H "$H" | jq -r '.status')
  case "$state" in
    ready) echo "no ar"; break ;;
    failed|blocked|canceled|superseded) echo "terminou em $state"; exit 1 ;;
  esac
  [ "$(date +%s)" -lt "$deadline" ] || { echo "tempo esgotado"; exit 1; }
  sleep "$delay"; delay=$(( delay * 2 > 30 ? 30 : delay * 2 ))
done
```
