API: Dashboard¶
Visão Geral¶
Endpoints para relatórios e métricas do dashboard. Fornecem KPIs, gráficos de atendimentos ao longo do tempo, funil de steps, horários de pico e efetividade de follow-ups.
Todos os endpoints respeitam multi-tenancy via query filters globais no AppDbContext.
Endpoints¶
GET /api/dashboard/kpi-overview¶
Retorna uma visão geral dos KPIs de atendimento no período.
Autorização: Requer autenticação
Query Parameters:
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| startDate | DateTime | Sim | Data inicial do período (UTC) |
| endDate | DateTime | Sim | Data final do período (UTC) |
| agentId | Guid | Não | Filtrar por agente específico |
Response (200 OK):
{
"totalConversations": 1250,
"activeConversations": 42,
"resolvedByAi": 890,
"escalatedConversations": 120,
"avgResolutionTimeHours": 2.5,
"aiResolutionRate": 71.2
}
Campos:
| Campo | Descrição |
|---|---|
| totalConversations | Total de conversas no período |
| activeConversations | Conversas atualmente ativas (Status = Active) |
| resolvedByAi | Conversas resolvidas automaticamente pela IA |
| escalatedConversations | Conversas escaladas para humano |
| avgResolutionTimeHours | Tempo médio de resolução em horas |
| aiResolutionRate | Percentual de resolução pela IA (0-100) |
GET /api/dashboard/conversations-over-time¶
Retorna série temporal de atendimentos agrupados por granularidade.
Autorização: Requer autenticação
Query Parameters:
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| startDate | DateTime | Sim | Data inicial do período (UTC) |
| endDate | DateTime | Sim | Data final do período (UTC) |
| granularity | string | Não | Granularidade: hour, day (default), month |
| agentId | Guid | Não | Filtrar por agente específico |
Response (200 OK):
{
"dataPoints": [
{
"timestamp": "2024-01-15T00:00:00Z",
"total": 45,
"resolvedByAi": 32,
"escalated": 8
},
{
"timestamp": "2024-01-16T00:00:00Z",
"total": 52,
"resolvedByAi": 38,
"escalated": 6
}
]
}
Granularidades:
| Valor | Agrupamento |
|---|---|
| hour | Por hora (Timestamp = data + hora) |
| day | Por dia (default, Timestamp = data) |
| month | Por mês (Timestamp = primeiro dia do mês) |
GET /api/dashboard/step-funnel¶
Retorna o funil de steps de um agente, mostrando quantas conversas passaram por cada step.
Autorização: Requer autenticação
Query Parameters:
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| startDate | DateTime | Sim | Data inicial do período (UTC) |
| endDate | DateTime | Sim | Data final do período (UTC) |
| agentId | Guid | Não | Filtrar por agente específico |
Response (200 OK):
{
"items": [
{
"stepId": "550e8400-e29b-41d4-a716-446655440001",
"stepName": "Boas-vindas",
"order": 1,
"conversationCount": 500
},
{
"stepId": "550e8400-e29b-41d4-a716-446655440002",
"stepName": "Coleta de Pedido",
"order": 2,
"conversationCount": 380
},
{
"stepId": "550e8400-e29b-41d4-a716-446655440003",
"stepName": "Confirmação",
"order": 3,
"conversationCount": 290
}
]
}
Lógica:
- Usa a entidade StepTransition para contar conversas distintas que transitaram para cada step (ToStepId)
- Join com AgentSteps para obter nome e ordem
- Ordenado por Order ascendente
GET /api/dashboard/peak-hours¶
Retorna um heatmap de horários de pico (dia da semana × hora do dia).
Autorização: Requer autenticação
Query Parameters:
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| startDate | DateTime | Sim | Data inicial do período (UTC) |
| endDate | DateTime | Sim | Data final do período (UTC) |
| agentId | Guid | Não | Filtrar por agente específico |
Response (200 OK):
{
"dataPoints": [
{ "dayOfWeek": 0, "hour": 8, "count": 15 },
{ "dayOfWeek": 0, "hour": 9, "count": 42 },
{ "dayOfWeek": 1, "hour": 10, "count": 38 }
]
}
Campos:
| Campo | Descrição |
|---|---|
| dayOfWeek | Dia da semana (0=Domingo, 6=Sábado) |
| hour | Hora do dia (0-23) |
| count | Quantidade de conversas iniciadas |
Observação: Retorna todas as 168 combinações (7 dias × 24 horas), preenchendo com count: 0 onde não houver dados.
GET /api/dashboard/follow-up-effectiveness¶
Retorna métricas de efetividade dos follow-ups automáticos.
Autorização: Requer autenticação
Query Parameters:
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| startDate | DateTime | Sim | Data inicial do período (UTC) |
| endDate | DateTime | Sim | Data final do período (UTC) |
| agentId | Guid | Não | Filtrar por agente específico |
Response (200 OK):
{
"totalFollowUpsSent": 200,
"reengagedConversations": 68,
"reengagementRate": 34.0,
"avgResponseTimeMinutes": 45.5
}
Campos:
| Campo | Descrição |
|---|---|
| totalFollowUpsSent | Total de follow-ups enviados no período |
| reengagedConversations | Conversas que receberam resposta do usuário após o follow-up |
| reengagementRate | Percentual de reengajamento (0-100) |
| avgResponseTimeMinutes | Tempo médio de resposta do usuário após o follow-up (minutos) |
Lógica:
- Consulta ConversationFollowUps com LastSentAt no período
- Verifica reengajamento: existe Message com Role=User e CreatedAt > LastSentAt
- Calcula tempo médio: diferença entre LastSentAt e o primeiro Message (Role=User) posterior
Entidade StepTransition¶
Criada para suportar o funil de steps. A IA pode pular steps (não segue ordem linear), então CurrentStepId na conversa não é suficiente para reconstruir o funil.
Tabela: step_transitions
| Coluna | Tipo | Descrição |
|---|---|---|
| id | uuid | PK |
| conversation_id | uuid | FK para conversations |
| agent_id | uuid | FK para agents |
| from_step_id | uuid? | FK para agent_steps (null no primeiro step) |
| to_step_id | uuid | FK para agent_steps |
| transitioned_at | timestamp | Data/hora da transição |
Índices:
- (agent_id, transitioned_at) — filtro por agente + período
- conversation_id — consultas por conversa
- to_step_id — agrupamento no funil
Tracking automático:
- InitializeStepTrackingStep — cria transição para o primeiro step (from=null)
- ApplyAiDecisionsStep — cria transição quando a IA muda de step
- PersistMessagesStep — persiste no banco
Multi-tenancy¶
Todos os endpoints respeitam o filtro de tenant via query filters globais:
- StepTransition filtra via st.Conversation.Instance.TenantId
- Conversation, ConversationFollowUp têm filtros próprios
- Não é necessário passar tenantId — é inferido automaticamente do token JWT