Contratos de API — Dashboard de Maturidade (FinOps)
Sumário
- 1. Backend FinOps — Otimizações (
/optimization) - 1.1 GET /optimization/aws-optimizations-hub
- 1.2 GET /optimization/aws-reserved-instances
- 1.3 GET /optimization/aws-optimization/:id
- 1.4 GET /optimization/detached-disks
- 1.5 GET /optimization/underutilized-vms
- 2. Engine de Anomalias de Custo AWS
- 2.1 GET /cards
- 2.2 GET /labels/anomaly-by-feedback
- 2.3 GET /graph
- 2.4 GET /table/detected-anomalies
- 2.5 GET /table/anomalies-root-causes
- 3. Modelos de Dados Compartilhados
1. Backend FinOps — Otimizações (/optimization)
Serviço: plat-eng-finopping-backend-finopping
Arquivo de rotas: src/route/optimization/optimization.ts
Prefixo registrado em: src/privateApp.ts → /optimization
Autenticação: Requer autenticação (módulo authModule aplicado globalmente no privateApp)
Tecnologia: Node.js + Fastify
1.1 GET /optimization/aws-optimizations-hub
Descrição: Retorna o consolidado de recomendações do AWS Optimization Hub, com métricas de economia estimada, quantidade de recomendações ativas e dados tabulares para exibição comparativa.
Parâmetros de entrada:
| Local | Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|---|
| query | start_date |
string (YYYY-MM-DD) |
Sim | Data de início do período analisado |
| query | end_date |
string (YYYY-MM-DD) |
Sim | Data de fim do período analisado |
| query | time_grouper |
'dia' \| 'semana' \| 'mês' \| 'ano' |
Sim | Granularidade temporal dos dados comparativos |
| query | x_axis |
string |
Sim | Dimensão do eixo X da tabela principal. Valores válidos: status, value stream, squad, produto, conta, tipo de recurso |
| query | chart_dimension |
string |
Sim | Dimensão de agrupamento dos dados. Mesmos valores de x_axis, mais nenhuma (sem agrupamento) |
| query | filter_<campo> |
string |
Não | Filtro dinâmico WHERE por campo da tabela (ex: filter_status=WAITING_REVIEW, filter_tag_vs=vsFinops). Aceita múltiplos |
Resposta 200:
{
sucess: boolean; // Indica sucesso da operação
message: string; // Mensagem descritiva
data: {
totalsDimensions: Record<string, unknown>; // Totais agrupados por dimensão (ex: serviço, conta)
estimatedMonthlySavings: number; // Economia mensal estimada (USD)
currentRecommendations: number; // Quantidade de recomendações ativas
tableRows: unknown[]; // Linhas da tabela principal (recomendações ativas)
tableRowsPending: unknown[]; // Linhas com recomendações pendentes de ação
tableRowsComparative: unknown[]; // Linhas comparativas (evolução temporal)
optimizations: unknown[]; // Lista completa de otimizações processadas
}
}
1.2 GET /optimization/aws-reserved-instances
Descrição: Retorna recomendações de compra de instâncias reservadas na AWS, incluindo custo atual, potencial de economia e lista de recomendações detalhadas.
Parâmetros de entrada:
| Local | Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|---|
| query | start_date |
string (YYYY-MM-DD) |
Sim | Data de início do período analisado |
| query | end_date |
string (YYYY-MM-DD) |
Sim | Data de fim do período analisado |
| query | filter_<campo> |
string |
Não | Filtro dinâmico WHERE por campo da tabela (ex: filter_status=WAITING_REVIEW). Aceita múltiplos |
Resposta 200:
{
sucess: boolean;
message: string;
data: {
totalCost: number; // Custo total atual das instâncias (USD)
estimatedMonthlySavings: number; // Economia mensal estimada com Reserved Instances (USD)
currentRecommendations: number; // Quantidade de recomendações de RI
tableRows: unknown[]; // Detalhamento por instância/serviço recomendado
}
}
1.3 GET /optimization/aws-optimization/:id
Descrição: Retorna os detalhes completos de uma recomendação AWS específica pelo seu identificador.
Parâmetros de entrada:
| Local | Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|---|
| path | id |
string |
Sim | ID único da otimização AWS |
Resposta 200:
{
sucess: boolean;
message: string;
data: Record<string, unknown>; // Objeto livre com todos os campos da recomendação
}
1.4 GET /optimization/detached-disks
Descrição: Lista discos Azure desacoplados (sem VM associada), com custo mensal, status e metadados de tagging para triagem de otimização.
Parâmetros de entrada:
| Local | Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|---|
| query | start_date |
string (YYYY-MM-DD) |
Sim | Data de início do período analisado |
| query | end_date |
string (YYYY-MM-DD) |
Sim | Data de fim do período analisado |
| query | filter_<campo> |
string |
Não | Filtro dinâmico WHERE por campo da tabela (ex: filter_status=WAITING_REVIEW). Aceita múltiplos |
Headers de tabela internos (ordem das colunas de tableRows):
Primeira inatividade; Última inatividade; Resolvido em; Status; ID do recurso; Tag vs; Tag squad; Tag produto; Estrutura provisionamento; Custo mensal (US$)
Resposta 200:
{
sucess: boolean;
message: string;
data: {
totalCost: number; // Custo mensal total dos recursos identificados (USD)
currentResourcesToOptimize: number; // Quantidade de discos passíveis de otimização
tableRows: unknown[]; // Registros com os campos descritos nos headers acima
}
}
Campo de custo utilizado internamente:
monthly_amortized_cost_usd
1.5 GET /optimization/underutilized-vms
Descrição: Lista VMs Azure subutilizadas, com custo mensal, status e metadados de tagging, permitindo priorizar desligamentos ou redimensionamentos.
Parâmetros de entrada: Idênticos ao endpoint detached-disks (start_date, end_date, filter_*).
Headers de tabela internos (ordem das colunas de tableRows):
Primeira inatividade; Última inatividade; Resolvido em; Status; ID do recurso; Tag vs; Tag squad; Tag produto; Estrutura provisionamento; Custo mensal (US$)
Resposta 200:
{
sucess: boolean;
message: string;
data: {
totalCost: number;
currentResourcesToOptimize: number;
tableRows: unknown[];
}
}
Campo de custo utilizado internamente:
monthly_amortized_cost_usd
2. Engine de Anomalias de Custo AWS
Serviço: plat-eng-finop-cloud-cost-anomalies-engine
Arquivo de configuração: serverless.yml
Autenticação: API Key via header (x-api-key) — private: true no API Gateway
Tecnologia: Python 3.11 + AWS Lambda + API Gateway (Serverless Framework)
Base de dados: PostgreSQL (tabelas tb_cost_anomalies e tb_root_causes)
2.1 GET /cards
Descrição: Retorna os KPIs resumidos do mês corrente para exibição em cards do dashboard: total de anomalias detectadas, impacto financeiro total e data da última anomalia.
Autenticação: private: true (API Key obrigatória)
CORS: habilitado (*)
Parâmetros de entrada: Nenhum.
Resposta 200:
{
"detected_anomalies": int, # Quantidade de anomalias detectadas no mês corrente (a partir do dia 1)
"total_impact": float, # Soma do impacto financeiro total no mês corrente (USD)
"last_anomaly": str | None # Data da anomalia mais recente no formato "DD/MM/YYYY", ou null
}
2.2 GET /labels/anomaly-by-feedback
Descrição: Retorna a contagem de anomalias agrupada por tipo de avaliação (feedback), permitindo visualizar a distribuição entre anomalias precisas, falsos positivos, atividades planejadas e não avaliadas.
Autenticação: private: true (API Key obrigatória)
CORS: habilitado
Parâmetros de entrada: Nenhum.
Resposta 200:
{
"accurate_anomaly": int, # Anomalias confirmadas como precisas (feedback = "YES")
"false_positive": int, # Falsos positivos (feedback = "NO")
"not_an_issue": int, # Atividade planejada / não é um problema (feedback = "PLANNED_ACTIVITY")
"without_feedback": int # Sem avaliação (feedback = NULL)
}
Mapeamento de valores de feedback:
| Valor no banco | Valor na API |
|---|---|
YES |
accurate_anomaly |
NO |
false_positive |
PLANNED_ACTIVITY |
not_an_issue |
NULL |
without_feedback |
2.3 GET /graph
Descrição: Endpoint unificado para geração de dados de gráficos. Retorna pares (x_axis, dimension) para diferentes agrupamentos. O tipo de gráfico é controlado pelo parâmetro x_axis.
Autenticação: private: true (API Key obrigatória)
CORS: habilitado
Parâmetros de entrada:
| Local | Parâmetro | Tipo | Obrigatório | Valores aceitos | Descrição |
|---|---|---|---|---|---|
| query | x_axis |
string |
Sim | month, feedback, service, account, cost_type |
Define o eixo X do gráfico |
| query | dimension |
string |
Não | impact (padrão) |
Métrica do eixo Y |
| query | limit |
string |
Não | Número inteiro | Limite de itens retornados (aplicado apenas em x_axis=service; padrão: 10) |
Resposta 200:
[
{
"x_axis": str, # Rótulo do eixo X (mês, tipo de feedback, serviço, conta ou tipo de custo)
"dimension": float # Valor da dimensão (ex: impacto financeiro em USD)
},
# ... demais itens
]
Comportamento por x_axis:
x_axis |
Fonte de dados | Agrupamento | Ordenação |
|---|---|---|---|
month |
tb_cost_anomalies |
TO_CHAR(anomaly_start_date, 'MM/YYYY') |
Crescente por mês |
feedback |
tb_cost_anomalies |
Tipo de feedback mapeado | Decrescente por impacto |
service |
tb_root_causes |
service |
Decrescente por contribution_impact (TOP 10) |
account |
tb_root_causes |
linked_account_name |
Decrescente por contribution_impact |
cost_type |
tb_cost_anomalies |
actual_spend vs expected_spend |
Alfabético |
Mapeamento de feedback para rótulo no eixo X (x_axis=feedback):
| Valor no banco | Rótulo no eixo X |
|---|---|
YES |
accurate_anomaly |
NO |
false_positive |
PLANNED_ACTIVITY |
not_an_issue |
NULL |
without_feedback |
Resposta 400 (x_axis ausente ou inválido):
{
"error": str, # Mensagem de erro
"valid_x_axis": list # ["month", "feedback", "service", "account", "cost_type"]
}
2.4 GET /table/detected-anomalies
Descrição: Retorna lista paginada de anomalias de custo detectadas, com suporte a múltiplos filtros. É o endpoint principal para exibição tabular de anomalias.
Autenticação: private: true (API Key obrigatória)
CORS: habilitado
Parâmetros de entrada:
| Local | Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|---|
| query | limit |
string (int) |
Não | Quantidade de itens por página (padrão: 100) |
| query | offset |
string (int) |
Não | Deslocamento para paginação (padrão: 0) |
| query | feedback |
string |
Não | Filtro: accurate_anomaly, false_positive, not_an_issue, without_feedback, all |
| query | start_date |
string (date) |
Não | Filtro: data de início da anomalia >= este valor |
| query | end_date |
string (date) |
Não | Filtro: data de fim da anomalia <= este valor |
| query | creation_date |
string (date) |
Não | Filtro: DATE(anomaly_start_date) = este valor |
| query | monitor_name |
string |
Não | Filtro por nome do monitor AWS |
| query | anomaly_id |
string |
Não | Filtro por ID da anomalia |
| query | service |
string |
Não | Filtro por serviço AWS (faz JOIN com tb_root_causes) |
Resposta 200:
{
"total": int, # Total de registros que atendem aos filtros
"limit": int, # Limite utilizado na consulta
"offset": int, # Offset utilizado na consulta
"items": [
{
"anomaly_id": str, # ID único da anomalia (AWS)
"monitor_arn": str, # ARN do monitor AWS que gerou a anomalia
"monitor_name": str, # Nome do monitor
"anomaly_start_date": str, # Data de início no formato "DD/MM/YYYY"
"anomaly_end_date": str, # Data de fim no formato "DD/MM/YYYY"
"total_impact_amount": float, # Impacto financeiro total (USD)
"impact_percentage_above_expected": float, # Percentual acima do gasto esperado
"score_current": float, # Score de severidade da anomalia
"anomaly_summary": str, # Resumo descritivo da anomalia
"actual_spend": float, # Gasto real no período (USD)
"expected_spend": float, # Gasto esperado no período (USD)
"last_synced_at": str, # Última sincronização no formato "DD/MM/YYYY"
"feedback": str, # Avaliação: "Anomalia precisa" | "Falso positivo" | "Não é um problema" | "Sem Avaliação"
"justification": str | None # Justificativa textual (se preenchida)
}
]
}
Mapeamento de feedback para exibição:
| Valor no banco | Valor retornado na API |
|---|---|
YES |
"Anomalia precisa" |
NO |
"Falso positivo" |
PLANNED_ACTIVITY |
"Não é um problema" |
NULL |
"Sem Avaliação" |
2.5 GET /table/anomalies-root-causes
Descrição: Retorna lista paginada das causas raiz das anomalias, identificando serviços, contas e regiões com maior contribuição de impacto financeiro.
Autenticação: private: true (API Key obrigatória)
CORS: habilitado
Parâmetros de entrada:
| Local | Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|---|
| query | limit |
string (int) |
Não | Itens por página (padrão: 100) |
| query | offset |
string (int) |
Não | Deslocamento para paginação (padrão: 0) |
| query | anomaly_id |
string |
Não | Filtra causas raiz de uma anomalia específica |
| query | service |
string |
Não | Filtra pelo serviço AWS |
Resposta 200:
{
"anomaly_id": str | None, # ID da anomalia filtrada (quando fornecido via query `anomalyId`)
"total": int, # Total de registros que atendem aos filtros
"limit": int,
"offset": int,
"items": [
{
"root_cause_id": str, # UUID único da causa raiz
"anomaly_id": str, # ID da anomalia relacionada (FK)
"service": str, # Serviço AWS (ex: "Amazon EC2", "Amazon S3")
"region": str, # Região AWS (ex: "us-east-1")
"linked_account_id": str, # ID da conta AWS vinculada
"linked_account_name": str, # Nome da conta AWS vinculada
"usage_type": str, # Tipo de uso AWS (ex: "USE1-BoxUsage:t3.medium")
"contribution_impact": float # Contribuição financeira desta causa raiz (USD)
}
]
}
Os itens são ordenados por
contribution_impact DESC.
3. Modelos de Dados Compartilhados
CostAnomaly (tb_cost_anomalies)
Modelo principal de anomalia, persistido e consumido pelos endpoints de consulta.
| Campo | Tipo Python | Tipo DB | Descrição |
|---|---|---|---|
anomaly_id |
str |
TEXT PK |
ID único da anomalia (AWS) |
monitor_arn |
str |
TEXT |
ARN do monitor AWS |
monitor_name |
str |
TEXT |
Nome do monitor AWS |
anomaly_start_date |
datetime |
TIMESTAMP |
Início da anomalia |
anomaly_end_date |
datetime |
TIMESTAMP |
Fim da anomalia |
total_impact_amount |
float |
NUMERIC |
Impacto financeiro total (USD) |
impact_percentage_above_expected |
float |
NUMERIC |
% acima do esperado |
score_current |
float |
NUMERIC |
Score de severidade atual |
anomaly_summary |
str |
TEXT |
Descrição resumida da anomalia |
actual_spend |
float |
NUMERIC |
Gasto real (USD) |
expected_spend |
float |
NUMERIC |
Gasto esperado (USD) |
last_synced_at |
datetime |
TIMESTAMP |
Última sincronização |
feedback |
str \| None |
TEXT |
YES | NO | PLANNED_ACTIVITY | NULL |
justification |
str \| None |
TEXT |
Justificativa textual |
RootCause (tb_root_causes)
Causas raiz associadas a uma anomalia.
| Campo | Tipo Python | Tipo DB | Descrição |
|---|---|---|---|
root_cause_id |
str (UUID) |
TEXT PK |
ID único da causa raiz |
anomaly_id |
str |
TEXT FK |
ID da anomalia relacionada |
service |
str |
TEXT |
Serviço AWS (ex: "Amazon EC2") |
region |
str |
TEXT |
Região AWS (ex: "us-east-1") |
linked_account_id |
str |
TEXT |
ID da conta AWS |
linked_account_name |
str |
TEXT |
Nome da conta AWS |
usage_type |
str |
TEXT |
Tipo de uso AWS |
contribution_impact |
float |
NUMERIC |
Contribuição no impacto financeiro (USD) |
Documento gerado em 2026-03-23.