2. Autenticação e Segurança
2.1 Tipo de Autenticação
A API Portal Retail ERP utiliza autenticação por API Key (chave de acesso). Este é o método mais seguro e prático para integrações entre sistemas ERP e APIs.
Como Funciona
Você recebe uma chave de acesso única:
X-API-Key: ERP-RETAILPORTAL-2024-SECURE-KEY-ABC123DEF456GHI789JKL012MNO345PQR678STU
Esta chave deve ser enviada em cada requisição no cabeçalho HTTP.
Características da Chave
| Propriedade | Valor |
|---|---|
| Comprimento | 16 a 256 caracteres |
| Caracteres permitidos | A-Z, a-z, 0-9, hífen (-), ponto (.), til (~) |
| Sensibilidade | Diferencia maiúsculas de minúsculas |
| Validade | Indefinida (até revogação) |
| Resets | Solicitar ao suporte se expirada |
Exemplo de Chave Válida
ERP-RETAILPORTAL-2024-SECURE-KEY-ABC123DEF456GHI789JKL012MNO345PQR678STU
Exemplo de Chave Inválida
❌ ERP@RETAILPORTAL — Contém @
❌ erp-retailportal — Muito curta (< 16 caracteres)
❌ ERP_RETAILPORTAL_2024 — Contém underscore (_)
2.2 Exemplos Práticos de Requisição
Exemplo 1: Criar um Produto (Requisição Individual)
curl --request POST \
--url https://api.retailportal.com/erp-data/product \
--header 'Content-Type: application/json' \
--header 'X-API-Key: ERP-RETAILPORTAL-2024-SECURE-KEY-ABC123DEF456GHI789JKL012MNO345PQR678STU' \
--data '{
"erpId": 12345,
"ncmCode": "84733090",
"status": "Active",
"ean": "7896045000001",
"description": "Dipirona 500mg Cápsulas",
"brand": "Genérico",
"sku": "SKU-DIPO-500-001"
}'
Resposta (201 Created):
{
"success": true,
"id": 98765,
"message": "Produto criado com sucesso",
"description": "Dipirona 500mg Cápsulas"
}
Exemplo 2: Criar Produtos em Lote
curl --request POST \
--url https://api.retailportal.com/erp-data/product/batch \
--header 'Content-Type: application/json' \
--header 'X-API-Key: ERP-RETAILPORTAL-2024-SECURE-KEY-ABC123DEF456GHI789JKL012MNO345PQR678STU' \
--data '{
"products": [
{
"erpId": 12345,
"ncmCode": "84733090",
"status": "Active",
"ean": "7896045000001",
"description": "Dipirona 500mg"
},
{
"erpId": 12346,
"ncmCode": "84733091",
"status": "Active",
"ean": "7896045000002",
"description": "Ibuprofeno 600mg"
}
]
}'
Resposta (202 Accepted):
{
"message": "Batch received and will be processed asynchronously",
"jobId": "hangfire-job-1234567890",
"totalItems": 2
}
Exemplo 3: Consultar Status de Processamento
curl --request GET \
--url https://api.retailportal.com/erp-data/batch-job-report/hangfire-job-1234567890 \
--header 'X-API-Key: ERP-RETAILPORTAL-2024-SECURE-KEY-ABC123DEF456GHI789JKL012MNO345PQR678STU'
Resposta (200 OK):
{
"jobId": "hangfire-job-1234567890",
"entityType": "ErpProduct",
"state": "Finished",
"isComplete": true,
"createdAt": "2024-12-06T10:30:00Z",
"completedAt": "2024-12-06T10:35:15Z",
"duration": "00:05:15",
"totalItems": 2,
"successCount": 2,
"failureCount": 0,
"hasPartialData": false
}
Exemplo 4: Sem Autenticação (Erro 401)
curl --request POST \
--url https://api.retailportal.com/erp-data/product \
--header 'Content-Type: application/json' \
--data '{ "erpId": 123 }'
Resposta (401 Unauthorized):
HTTP/1.1 401 Unauthorized
Content-Type: application/json
"Unauthorized"
Exemplo 5: API Key Inválida (Erro 401)
curl --request POST \
--url https://api.retailportal.com/erp-data/product \
--header 'Content-Type: application/json' \
--header 'X-API-Key: CHAVE-ERRADA-12345' \
--data '{ "erpId": 123 }'
Resposta (401 Unauthorized):
HTTP/1.1 401 Unauthorized
Content-Type: application/json
"Unauthorized: Invalid API Key"
2.3 Cabeçalhos Obrigatórios
Cabeçalho: X-API-Key
| Campo | Valor |
|---|---|
| Nome | X-API-Key |
| Tipo | String |
| Obrigatório | Sim |
| Exemplo | ERP-RETAILPORTAL-2024-SECURE-KEY-ABC123DEF456 |
Cabeçalho: Content-Type (Obrigatório para POST/PUT)
| Campo | Valor |
|---|---|
| Nome | Content-Type |
| Tipo | String |
| Valor esperado | application/json |
| Obrigatório | Sim (para POST/PUT/PATCH) |
| Exemplo | Content-Type: application/json |
Cabeçalho: Accept (Recomendado)
| Campo | Valor |
|---|---|
| Nome | Accept |
| Tipo | String |
| Recomendado | Sim |
| Valor esperado | application/json |
| Exemplo | Accept: application/json |
Cabeçalho: User-Agent (Recomendado)
Para melhor rastreamento, inclua informação sobre seu sistema:
User-Agent: MyERP/1.0 (Company: ACME; Environment: Production)
2.4 Regras de Rate-Limit e Restrições
Rate Limiting: Proteção Contra Abuso
A API implementa rate limiting para proteger a plataforma de abuso. Se você ultrapassar o limite, a API responderá com HTTP 429.
Limites Padrão
| Métrica | Limite | Janela |
|---|---|---|
| Tentativas de autenticação | 100 | 5 minutos |
| Requisições gerais | 1.000 | 5 minutos |
| Requisições de batch | 100 | 5 minutos |
Quando Ativa: Rate Limit
Você excedeu o limite quando: - Faz mais de 100 tentativas falhadas com API Key em 5 minutos - Sua chave é bloqueada por 15 minutos automaticamente
Exemplo de Resposta 429 Too Many Requests
HTTP/1.1 429 Too Many Requests
Retry-After: 45
Content-Type: application/json
{
"message": "Too many authentication attempts. Please try again later",
"retryAfter": 45,
"resetTime": "2024-12-06T10:45:30Z"
}
O que significa:
- Retry-After: 45 — Aguarde 45 segundos antes de reenviar
- resetTime — Horário em que o bloqueio será removido (UTC)
Como Evitar Rate Limit
✅ Use a mesma chave para todas as requisições ✅ Implemente backoff exponencial (espere progressivamente mais) ✅ Reutilize conexões HTTP (connection pooling) ✅ Processe em lotes em vez de requisições individuais ✅ Aguarde antes de reenviar após falha
❌ Não teste múltiplas chaves simultaneamente ❌ Não faça requisições em loops rápidos ❌ Não reenvie imediatamente após falha
Limites de Tamanho
| Limite | Valor | Impacto |
|---|---|---|
| Tamanho máximo de requisição | 10 MB | JSON muito grande será rejeitado |
| Itens por batch | 1.000 | Enviar 1.001 itens resultará em erro |
| Campos por item | Sem limite | Pode incluir dados customizados em JSON |
Timeouts
| Operação | Timeout | Comportamento |
|---|---|---|
| Operações síncronas (GET, POST individual) | 30 segundos | Requisição cancelada, erro 500 |
| Operações assíncronas (batch) | 5 minutos | Processamento continua em background, consulte status |
2.5 Boas Práticas de Segurança
Proteção da Chave de Acesso
✅ O que FAZER
# ✅ Armazenar em variável de ambiente
export ERP_API_KEY="ERP-RETAILPORTAL-2024-SECURE-KEY-ABC123"
# ✅ Usar em script protegido
curl --header "X-API-Key: $ERP_API_KEY" ...
# ✅ Rotacionar chaves regularmente (a cada 90 dias)
# Abra ticket no suporte para requisitar nova chave
# ✅ Usar HTTPS (nunca HTTP)
https://api.retailportal.com/erp-data/product
# ✅ Auditar logs de autenticação
# Verificar tentativas falhadas no painel de controle
❌ O que NÃO FAZER
# ❌ Nunca inserir a chave direto no código
export API_KEY="ERP-RETAILPORTAL-2024-SECURE-KEY-ABC123" # ❌ NÃO FAÇA ISTO
# ❌ Nunca incluir em URLs
GET https://api.retailportal.com/erp-data/product?apikey=ABC123 # ❌ Logs expõem chave
# ❌ Nunca enviar por email ou chat
# Sempre use canais seguros (VPN, tickets encriptados)
# ❌ Nunca usar HTTP (sem SSL)
http://api.retailportal.com/erp-data/product # ❌ Conexão insegura
# ❌ Nunca compartilhar entre empresas
# Cada empresa deve ter sua própria chave
Validação de Resposta
Sempre valide as respostas:
import json
import hashlib
response = requests.get(
'https://api.retailportal.com/erp-data/product/1',
headers={'X-API-Key': api_key}
)
# ✅ Validar status HTTP
if response.status_code == 200:
data = response.json()
# ✅ Validar estrutura
if 'success' not in data:
raise ValueError("Response missing 'success' field")
# ✅ Validar conteúdo
if not isinstance(data['success'], bool):
raise ValueError("'success' must be boolean")
else:
print(f"Erro: {response.status_code}")
print(f"Detalhes: {response.text}")
2.6 Certificado SSL/TLS
A API usa certificado SSL/TLS válido. Você deve:
✅ Validar o certificado em produção ✅ Usar bibliotecas padrão (curl, requests, etc.) que validam automaticamente ✅ Usar HTTPS, nunca HTTP
Validação Manual (Python)
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.ssl_ import create_urllib3_context
# ✅ Validação automática (padrão)
response = requests.get('https://api.retailportal.com/erp-data/product/1')
# ❌ Desabilitar validação (NUNCA em produção!)
response = requests.get(
'https://api.retailportal.com/erp-data/product/1',
verify=False # ❌ NUNCA USE ISTO EM PRODUÇÃO
)
Checklist de Segurança
Antes de colocar em produção, valide:
- [ ] Chave de API armazenada em variável de ambiente
- [ ] Certificado SSL validado
- [ ] Todas as requisições usam HTTPS
- [ ] Logs nunca expõem a chave completa
- [ ] Monitoramento de tentativas falhadas ativado
- [ ] Timeout configurado apropriadamente (30 segundos para síncrono)
- [ ] Autenticação testada com chave válida e inválida
- [ ] Rate limit testado (enviar múltiplas requisições)
- [ ] Chave será rotacionada a cada 90 dias
- [ ] Plano de ação em caso de exposição da chave