Guia de Uso - APIs /4c/decision (4C Decision API)
Base URL: https://csuite.internut.com.br/4c/decision
Documentação Swagger: https://csuite.internut.com.br/4c/decision/docs
OpenAPI Spec: https://csuite.internut.com.br/4c/decision/openapi.json
📋 Índice
- Visão Geral
- Decisão Completa
- Decisão Automática
- Decisão em Lote
- Candidatos Automáticos
- Executar Ação
- Versionamento
- Health & Metrics
- Exemplos Práticos
- Troubleshooting
1. Visão Geral
O 4C Decision API é o orquestrador de decisões do sistema 4 Certos Dinâmico, responsável por:
- Tomar decisões completas: Cliente certo, Oferta certa, Canal certo, Timing certo
- Integrar modelos ML: Intent, Offer (Learning-to-Rank), Channel, Timing
- Aplicar políticas: Constraints, guardrails, opt-outs
- Gerar explicações: SHAP values, justificativas naturais (LLM)
- Executar ações: Envio de mensagens via WhatsApp, Email, CRM
Características:
- ✅ API REST assíncrona (FastAPI)
- ✅ Versionamento (/v1/...)
- ✅ Integração com Feature Service, Scoring Service, Executor
- ✅ Rate limiting configurável (120 req/min para /decide, 240 req/min para /send)
- ✅ Telemetria em ClickHouse
- ✅ Métricas Prometheus
2. Decisão Completa
Endpoint: POST /decide ou POST /v1/decide
Descrição: Solicita uma decisão completa para um cliente, incluindo oferta, canal e timing.
Request:
{
"customer_id": 123,
"org_id": 1,
"candidates": [
{
"sku": "BK4-2516",
"price": 1500.00
},
{
"sku": "BK4-2517",
"price": 2000.00
}
],
"constraints": {
"min_intent": 0.45,
"max_contacts_per_day": 2,
"respect_opt_out": true
},
"include_explanations": true,
"include_natural_justification": false
}
Parâmetros:
- customer_id (int, obrigatório) - ID do cliente
- org_id (int, opcional) - ID da organização (para carregar políticas do CSuite)
- candidates (array, opcional) - Lista de ofertas candidatas. Se vazio, usa decisão automática
- constraints (object, opcional) - Constraints manuais (sobrescrevem políticas do CSuite)
- min_intent (float) - Score mínimo de intenção (0.0-1.0)
- max_contacts_per_day (int) - Máximo de contatos por dia
- respect_opt_out (bool) - Respeitar opt-out do cliente
- include_explanations (bool, padrão: false) - Incluir explicações SHAP
- include_natural_justification (bool, padrão: false) - Gerar justificativa natural via LLM (requer include_explanations=true)
Response (Aprovada):
{
"decision_id": "uuid-123",
"approved": true,
"customer_id": 123,
"offer": {
"sku": "BK4-2516",
"price": 1500.00,
"margin_pct": 25.5
},
"channel": "whatsapp",
"timing": {
"send_at": "2025-01-27T14:30:00Z",
"score": 0.85
},
"scores": {
"intent": 0.72,
"offer": 0.88,
"channel": 0.91,
"timing": 0.85
},
"explanations": {
"intent": {
"factors": [
{
"feature": "recency_days",
"value": 15,
"shap": 0.12
},
{
"feature": "freq_12m",
"value": 5,
"shap": 0.08
}
]
}
},
"natural_justification": "Recomendamos este produto porque o cliente tem histórico de compras recentes e demonstrou interesse em produtos similares."
}
Response (Pulada):
{
"decision_id": "uuid-123",
"approved": false,
"skip_reason": "low_intent",
"customer_id": 123,
"scores": {
"intent": 0.35
}
Exemplo:
curl -X POST "https://csuite.internut.com.br/4c/decision/decide" \
-H "Content-Type: application/json" \
-d '{
"customer_id": 123,
"org_id": 1,
"candidates": [
{"sku": "BK4-2516", "price": 1500.00}
],
"include_explanations": true
}'
Casos de uso:
- Decisão 1:1 com cliente específico
- Campanhas segmentadas
- Cross-sell e up-sell
- Recuperação de carrinho abandonado
3. Decisão Automática
Endpoint: POST /decide/auto ou POST /v1/decide/auto
Descrição: Decisão automática sem candidatos (sistema escolhe automaticamente a melhor oferta).
Request:
{
"customer_id": 123,
"org_id": 1,
"include_explanations": true,
"include_natural_justification": true
}
Parâmetros:
- customer_id (int, obrigatório) - ID do cliente
- org_id (int, opcional) - ID da organização
- include_explanations (bool, padrão: false) - Incluir explicações SHAP
- include_natural_justification (bool, padrão: false) - Gerar justificativa natural via LLM
Response:
{
"decision_id": "uuid-123",
"approved": true,
"customer_id": 123,
"offer": {
"sku": "BK4-2516",
"price": 1500.00
},
"channel": "whatsapp",
"timing": {
"send_at": "2025-01-27T14:30:00Z"
},
"scores": {
"intent": 0.72,
"offer": 0.88,
"channel": 0.91,
"timing": 0.85
}
}
Exemplo:
curl -X POST "https://csuite.internut.com.br/4c/decision/decide/auto" \
-H "Content-Type: application/json" \
-d '{
"customer_id": 123,
"org_id": 1
}'
Casos de uso:
- Decisões em massa (batch)
- Automação completa
- Quando não há candidatos pré-definidos
4. Decisão em Lote
Endpoint: POST /decide/batch/auto ou POST /v1/decide/batch/auto
Descrição: Decisões automáticas para múltiplos clientes.
Request:
{
"customer_ids": [123, 456, 789],
"org_id": 1,
"include_explanations": false
}
Parâmetros:
- customer_ids (array[int], obrigatório) - Lista de IDs de clientes
- org_id (int, opcional) - ID da organização
- include_explanations (bool, padrão: false) - Incluir explicações
Response:
{
"decisions": [
{
"decision_id": "uuid-123",
"customer_id": 123,
"approved": true,
"offer": {"sku": "BK4-2516", "price": 1500.00},
"channel": "whatsapp"
},
{
"decision_id": "uuid-456",
"customer_id": 456,
"approved": false,
"skip_reason": "low_intent"
}
],
"total": 3,
"approved": 1,
"skipped": 2
}
Exemplo:
curl -X POST "https://csuite.internut.com.br/4c/decision/decide/batch/auto" \
-H "Content-Type: application/json" \
-d '{
"customer_ids": [123, 456, 789],
"org_id": 1
}'
Casos de uso:
- Campanhas em massa
- Processamento batch
- Automação de marketing
5. Candidatos Automáticos
Endpoint: GET /candidates/auto ou GET /v1/candidates/auto
Descrição: Obtém lista de candidatos automáticos para um cliente.
Parâmetros de Query:
- customer_id (int, obrigatório) - ID do cliente
- org_id (int, opcional) - ID da organização
- limit (int, padrão: 10) - Número máximo de candidatos
Response:
{
"customer_id": 123,
"candidates": [
{
"sku": "BK4-2516",
"price": 1500.00,
"score": 0.88
},
{
"sku": "BK4-2517",
"price": 2000.00,
"score": 0.75
}
]
}
Exemplo:
curl "https://csuite.internut.com.br/4c/decision/candidates/auto?customer_id=123&org_id=1&limit=10"
Casos de uso:
- Pré-visualização de ofertas
- Seleção manual de candidatos
- Análise de recomendações
6. Executar Ação
Endpoint: POST /send ou POST /v1/send
Descrição: Executa uma ação (envio de mensagem) baseada em uma decisão.
Request:
{
"decision_id": "uuid-123",
"action": {
"type": "whatsapp",
"customer_id": 123,
"message": "Olá! Temos uma oferta especial para você...",
"offer": {
"sku": "BK4-2516",
"price": 1500.00
}
}
}
Parâmetros:
- decision_id (string, obrigatório) - ID da decisão (retornado por /decide)
- action (object, obrigatório) - Ação a ser executada
- type (string) - Tipo de ação: whatsapp, email, crm, etc.
- customer_id (int) - ID do cliente
- message (string) - Mensagem a ser enviada
- offer (object, opcional) - Oferta associada
Response:
{
"decision_id": "uuid-123",
"status": "queued",
"action_id": "action-uuid",
"queued_at": "2025-01-27T14:30:00Z"
}
Exemplo:
curl -X POST "https://csuite.internut.com.br/4c/decision/send" \
-H "Content-Type: application/json" \
-d '{
"decision_id": "uuid-123",
"action": {
"type": "whatsapp",
"customer_id": 123,
"message": "Oferta especial para você!"
}
}'
Casos de uso:
- Executar decisão aprovada
- Envio de mensagens
- Integração com sistemas externos
7. Versionamento
Todos os endpoints possuem versão /v1/...:
POST /decide→POST /v1/decidePOST /decide/auto→POST /v1/decide/autoPOST /decide/batch/auto→POST /v1/decide/batch/autoGET /candidates/auto→GET /v1/candidates/autoPOST /send→POST /v1/send
Recomendação: Use preferencialmente as versões /v1/... para garantir compatibilidade futura.
8. Health & Metrics
Health Check
Endpoint: GET /health
Descrição: Verifica saúde da API.
Response:
{
"status": "ok"
}
Exemplo:
curl "https://csuite.internut.com.br/4c/decision/health"
Métricas Prometheus
Endpoint: GET /metrics
Descrição: Retorna métricas Prometheus da Decision API.
Exemplo:
curl "https://csuite.internut.com.br/4c/decision/metrics"
Telemetria
Endpoint: GET /telemetry/events/count
Descrição: Retorna contagem de eventos em ClickHouse.
Parâmetros de Query:
- since_minutes (int, padrão: 60) - Janela de tempo em minutos
Exemplo:
curl "https://csuite.internut.com.br/4c/decision/telemetry/events/count?since_minutes=60"
Métricas do Executor
Endpoint: GET /metrics/executor
Descrição: Proxy para expor métricas do executor via Decision API.
Exemplo:
curl "https://csuite.internut.com.br/4c/decision/metrics/executor"
9. Exemplos Práticos
Fluxo Completo: Decisão → Execução
import requests
BASE_URL = "https://csuite.internut.com.br/4c/decision"
# 1. Solicitar decisão
decision_resp = requests.post(
f"{BASE_URL}/v1/decide",
json={
"customer_id": 123,
"org_id": 1,
"candidates": [
{"sku": "BK4-2516", "price": 1500.00}
],
"include_explanations": True
}
)
decision = decision_resp.json()
# 2. Se aprovada, executar ação
if decision.get("approved"):
send_resp = requests.post(
f"{BASE_URL}/v1/send",
json={
"decision_id": decision["decision_id"],
"action": {
"type": decision["channel"],
"customer_id": 123,
"message": f"Oferta especial: {decision['offer']['sku']} por R$ {decision['offer']['price']:.2f}",
"offer": decision["offer"]
}
}
)
print(f"Ação enviada: {send_resp.json()}")
else:
print(f"Decisão pulada: {decision.get('skip_reason')}")
Decisão Automática em Lote
import requests
BASE_URL = "https://csuite.internut.com.br/4c/decision"
# Obter lista de clientes
customer_ids = [123, 456, 789, 101, 102]
# Decisões em lote
batch_resp = requests.post(
f"{BASE_URL}/v1/decide/batch/auto",
json={
"customer_ids": customer_ids,
"org_id": 1
}
)
batch_result = batch_resp.json()
print(f"Total: {batch_result['total']}")
print(f"Aprovadas: {batch_result['approved']}")
print(f"Puladas: {batch_result['skipped']}")
# Executar ações para decisões aprovadas
for decision in batch_result["decisions"]:
if decision.get("approved"):
requests.post(
f"{BASE_URL}/v1/send",
json={
"decision_id": decision["decision_id"],
"action": {
"type": decision["channel"],
"customer_id": decision["customer_id"],
"message": f"Oferta: {decision['offer']['sku']}",
"offer": decision["offer"]
}
}
)
Obter Candidatos e Decidir
import requests
BASE_URL = "https://csuite.internut.com.br/4c/decision"
# 1. Obter candidatos automáticos
candidates_resp = requests.get(
f"{BASE_URL}/v1/candidates/auto",
params={"customer_id": 123, "org_id": 1, "limit": 5}
)
candidates = candidates_resp.json()["candidates"]
# 2. Usar candidatos na decisão
decision_resp = requests.post(
f"{BASE_URL}/v1/decide",
json={
"customer_id": 123,
"org_id": 1,
"candidates": [
{"sku": c["sku"], "price": c["price"]}
for c in candidates
],
"include_explanations": True
}
)
decision = decision_resp.json()
10. Troubleshooting
Erro 500 (Internal Server Error)
Possíveis causas:
- Serviço Feature Service indisponível
- Serviço Scoring Service indisponível
- Erro de conexão com MySQL/ClickHouse
- Erro no Policy Engine
Solução:
1. Verificar logs em Grafana/Kibana
2. Verificar saúde dos serviços (/health)
3. Verificar conexão com banco de dados
4. Verificar configuração de variáveis de ambiente
Erro 404 (Not Found)
Possíveis causas:
- Endpoint incorreto
- Roteamento Traefik incorreto
- Serviço não está rodando
Solução:
1. Verificar URL base: https://csuite.internut.com.br/4c/decision
2. Verificar roteamento no Traefik
3. Verificar se o serviço está rodando: docker service ls
Erro 429 (Too Many Requests)
Possíveis causas:
- Rate limiting ativado
- Muitas requisições por minuto
Solução:
1. Verificar limites configurados:
- RATE_LIMIT_DECIDE_RPM (padrão: 120)
- RATE_LIMIT_SEND_RPM (padrão: 240)
2. Reduzir frequência de requisições
3. Usar batch endpoints para múltiplos clientes
Timeout
Possíveis causas:
- Latência alta nos serviços
- Timeout de conexão com banco de dados
- Cache Redis indisponível
Solução:
1. Verificar latência dos serviços
2. Verificar conexão com MySQL/Redis
3. Verificar cache do Redis
4. Aumentar timeout se necessário
Decisão Sempre Pulada
Possíveis causas:
- Score de intenção muito baixo
- Constraints muito restritivos
- Cliente em opt-out
- Políticas do CSuite bloqueando
Solução:
1. Verificar skip_reason na resposta
2. Verificar scores retornados
3. Ajustar constraints ou políticas
4. Verificar opt-out do cliente
📚 Documentação Adicional
- Swagger UI: https://csuite.internut.com.br/4c/decision/docs
- OpenAPI Spec: https://csuite.internut.com.br/4c/decision/openapi.json
- Manual Completo 4C:
4c/docs/MANUAL_APIS_4C.md
🔐 Autenticação
Por padrão, a API não requer autenticação. Para produção, configure:
- API Keys via middleware
- OAuth2 via FastAPI Security
- JWT Tokens via dependências
📊 Rate Limiting
A Decision API implementa rate limiting leve em memória, por IP + endpoint, configurável por variáveis de ambiente:
RATE_LIMIT_ENABLED=true|false– habilita/desabilita o limitador internoRATE_LIMIT_DECIDE_RPM– requisições/minuto para/decide*(padrão:120)RATE_LIMIT_SEND_RPM– requisições/minuto para/send(padrão:240)
Nota: Este mecanismo é uma proteção básica (anti-abuso acidental). Para ambientes de alta escala, recomenda-se combiná-lo com rate limiting em camada de borda (Traefik, Nginx, API Gateway).
Última atualização: 2025-01-27