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

Próxima Seção

3. Lista de Endpoints