Autenticação¶
A API usa API Key estática via header X-API-Key. Não há OAuth ou JWT.
Tipos de chave¶
| Tipo | Header | Quem usa |
|---|---|---|
| Owner key | X-API-Key: <env API_KEY> |
Você (dev/admin) |
| Subscriber key | X-API-Key: <uuid> |
Assinante (EA e frontend) |
| Admin secret | X-Admin-Secret: <env ADMIN_SECRET> |
Admin endpoints (/admin/*) |
Como assinantes obtêm a chave¶
- Cliente compra plano EA Basic ou Pro em Eduzz
- Webhook
/webhooks/eduzzdispara automático - Sistema gera UUID v4 via
gen_random_uuid()no Postgres - Email HTML é enviado com a chave e instruções MT5
Ver Webhooks e Multi-Tenancy para o fluxo completo.
Como o cliente usa¶
No MT5, configurar nos parâmetros do EA:
Internamente o EA faz:
string headers = "X-API-Key: " + InpApiKey + "\r\n";
WebRequest("GET", InpApiUrl + "/api/scan", headers, ...);
Rate limits¶
flowchart LR
R[Request] --> A{IP cap<br/>200/min?}
A -->|excedeu| 429a[429]
A -->|ok| B{Auth válida?}
B -->|não| 401[401]
B -->|sim| C{Plan limit<br/>excedido?}
C -->|sim| 429b[429]
C -->|não| OK[200]
| Plano | Limite | Quando excede |
|---|---|---|
owner |
600 req/min | scripts admin, indexação |
pro |
300 req/min | EA + frontend simultâneos |
basic |
60 req/min | suficiente para 1 EA + checagens ocasionais |
Headers de resposta quando limita:
Anti-key-sharing¶
Detector roda por chave (não por IP):
- Mais de 3 IPs distintos usando a mesma chave em 1h → alerta Telegram
- Cooldown de 6h entre alertas para mesma chave (evita spam)
- Não bloqueia o tráfego (uso legítimo: VPS + PC + celular)
Erros comuns¶
401 Unauthorized¶
Causas:
- Chave digitada errado (espaço, char a mais)
- Chave foi revogada (refund/cancel via Eduzz)
- Plano expirou (
expires_at < NOW()) - Chave foi regenerada pelo cliente
429 Too Many Requests¶
Solução:
- Aumentar plano
- Reduzir frequência de polling do EA (não recomendado <1min)
- Verificar se outro script não está consumindo a mesma chave
403 Forbidden em /admin/*¶
X-Admin-Secret ausente ou errado. Conferir .env da VPS.
Owner key vs Subscriber key¶
| Aspecto | Owner | Subscriber |
|---|---|---|
| Origem | env var API_KEY |
DB api_keys.api_key |
| Lookup | nenhum (fast path) | SELECT no DB |
| Symbols | todos | conforme symbols_allowed |
| TFs | todos | conforme tfs_allowed |
| Expira? | nunca | sim, via expires_at |
| key_id | None |
int |
Aparece em /admin/keys? |
não | sim |
Aparece em last_seen_at? |
não | sim |
Boa prática para integradores¶
- Não logar a key. Em logs use hash:
key[:8] + "..."ouhash(key) % 10000. - Não compartilhar: a key é pessoal.
- Reagir a 401: implementar refresh manual (mostrar dialog "sua chave expirou, gere nova em /minha-conta").
- Respeitar Retry-After: backoff exponencial em 429.
- Timeout razoável: 30s para
/scan, mais para/history(pode varrer muitas linhas).