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

# Tratamento de erros na prática

> Padrões de retry, logging e resposta ao usuário

## Estrutura do erro

```json theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Too many requests per minute.",
    "request_id": "req_abc123"
  }
}
```

Sempre logue `request_id` + endpoint + payload (sem a API key).

## Wrapper genérico (JavaScript)

```javascript theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
const API_KEY = process.env.SHAPPIRE_API_KEY;
const BASE = 'https://api.shappire.tools/v1';

class ShappireError extends Error {
  constructor(code, message, requestId, status) {
    super(message);
    this.code = code;
    this.requestId = requestId;
    this.status = status;
  }
}

async function shappireFetch(path, options = {}) {
  const res = await fetch(`${BASE}${path}`, {
    ...options,
    headers: {
      'X-API-Key': API_KEY,
      'Content-Type': 'application/json',
      ...options.headers,
    },
  });
  const body = await res.json().catch(() => ({}));

  if (!res.ok) {
    throw new ShappireError(
      body.error?.code,
      body.error?.message,
      body.error?.request_id ?? res.headers.get('X-Request-Id'),
      res.status,
    );
  }
  return body.data;
}
```

## Mapeamento para HTTP do seu app

| Erro Shappire                | Retorne ao cliente   |
| ---------------------------- | -------------------- |
| `invalid_api_key`            | 500 (config interna) |
| `unsupported_platform`       | 422                  |
| `media_unavailable`          | 404                  |
| `rate_limit_exceeded`        | 503 + Retry-After    |
| `concurrency_limit_exceeded` | 503                  |

## Python — decorator

```python theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
def handle_shappire_errors(fn):
    def wrapper(*args, **kwargs):
        try:
            return fn(*args, **kwargs)
        except requests.HTTPError as exc:
            payload = exc.response.json()
            code = payload.get("error", {}).get("code")
            if code == "rate_limit_exceeded":
                raise TooManyRequests(payload)
            raise
    return wrapper
```

## Mensagens ao usuário final

Não exponha `message` em inglês diretamente. Mapeie `error.code`:

| Código                       | Mensagem PT                             |
| ---------------------------- | --------------------------------------- |
| `unsupported_platform`       | Plataforma não suportada                |
| `media_unavailable`          | Vídeo indisponível ou removido          |
| `rate_limit_exceeded`        | Muitas requisições — tente em instantes |
| `concurrency_limit_exceeded` | Downloads em andamento — aguarde        |

Veja a referência completa: [Erros e códigos](/api-reference/guides/errors).
