Pular para o conteúdo

Analytics API Routes

Rotas de analytics e métricas. Todas exigem autenticação e são scoped por account_id.


Descrição: Retorna um dashboard completo com métricas agregadas: contatos (total, novos esta semana/mes), mensagens (enviadas, recebidas, taxa de entrega/leitura), conversas (total, ativas), campanhas (total, este mês), automações ativas.

Auth: Required (getAuthContext()) Rate Limit: Nenhum Audit: Nenhum

Request: N/A

Response:

  • 200:
{
"data": {
"contacts": { "total": 500, "new_this_week": 12, "new_this_month": 45 },
"messages": { "total_sent": 1200, "total_received": 800, "delivery_rate": 98.5, "read_rate": 65.2 },
"conversations": { "total": 300, "active": 42 },
"campaigns": { "total": 15, "this_month": 3 },
"automations": { "active": 8 }
}
}

Notas: Usa Promise.all com 8 queries paralelas. Message stats via RPC message_stats. Delivery rate = delivered / sent * 100. Read rate = read / delivered * 100. Conversas ativas = status != “closed”.


Descrição: Retorna estatísticas de mensagens por dia (sent, delivered, read, failed, received) e totais agregados.

Auth: Required (getAuthContext()) Rate Limit: Nenhum Audit: Nenhum

Request:

  • Query params:
    • period (string, default: “7d”) - “7d” | “30d” | “90d”

Response:

  • 200:
{
"data": {
"period": "7d",
"daily": [
{ "date": "2026-02-13", "sent": 50, "delivered": 48, "read": 30, "failed": 2, "received": 25 }
],
"totals": { "sent": 350, "delivered": 336, "read": 210, "failed": 14, "received": 175 }
}
}

Notas: Usa Zod analyticsQuerySchema para validação do period. RPC message_stats_by_day com parametros p_account_id e p_days_back.


Descrição: Retorna analytics de campanhas executadas: nome, template, recipients, delivered, read, failed, e taxas calculadas.

Auth: Required (getAuthContext()) Rate Limit: Nenhum Audit: Nenhum

Request:

  • Query params:
    • period (string, default: “30d”) - “30d” | “90d”

Response:

  • 200:
{
"data": {
"campaigns": [
{
"id": "uuid",
"name": "Black Friday",
"template_name": "promo_bf_2026",
"executed_at": "2026-02-10T...",
"total_recipients": 500,
"delivered": 490,
"read": 300,
"failed": 10,
"delivery_rate": 98.0,
"read_rate": 61.2
}
]
}
}

Notas: Limita a 20 campanhas mais recentes. Usa RPC campaign_stats_agg para cada campanha (N+1 query, max 20).


Descrição: Exporta dados em formato CSV. Suporta exportação de mensagens, contatos e campanhas. Retorna arquivo CSV com BOM UTF-8.

Auth: Required (getAuthContext()) Rate Limit: Nenhum Audit: Nenhum

Request:

  • Query params:
    • type (string, obrigatório) - “messages” | “contacts” | “campaigns”
    • period (string, default: “30d”) - “7d” | “30d” | “90d” (usado apenas para messages)

Response:

  • 200: text/csv file download
    • Messages: colunas Data, Direção, Tipo, Status, Conteúdo
    • Contacts: colunas Nome, Telefone, Email, Criado em
    • Campaigns: colunas Nome, Status, Criado em, Agendado para
  • 422: Tipo inválido

Notas:

  • Limite de 10.000 registros por exportação
  • CSV injection protection: valores que começam com =, +, -, @, tab, newline são prefixados com '
  • NAO usa withErrorHandling wrapper — error handling manual com try/catch
  • Header Content-Disposition com filename {type}_export.csv

Descrição: Retorna dados de heatmap de atividade de mensagens inbound por dia da semana e hora (UTC).

Auth: Required (getAuthContext()) Rate Limit: Nenhum Audit: Nenhum

Request:

  • Query params:
    • period (string, default: “7d”) - “7d” | “30d” | “90d”

Response:

  • 200:
{
"data": [
{ "day": 0, "hour": 14, "count": 25 },
{ "day": 1, "hour": 9, "count": 42 }
]
}
  • day: 0=domingo … 6=sabado (UTC)
  • hour: 0-23 (UTC)

Notas: Busca até 1000 conversas e 10.000 mensagens inbound. Processamento em memória (Map).


Descrição: Retorna a distribuição RFM (Recency, Frequency, Monetary) dos contatos. Só está habilitado se o account tiver pedidos pagos suficientes.

Auth: Required (getAuthContext()) Rate Limit: Nenhum Audit: Nenhum

Request: N/A

Response:

  • 200:
{
"data": {
"enabled": true,
"orderCount": 150,
"distribution": [
{ "segment": "Champions", "count": 30, "last_calculated_at": "2026-02-20T..." }
],
"lastCalculatedAt": "2026-02-20T..."
}
}
  • Se desabilitado: { "enabled": false, "orderCount": 5, "distribution": [], "lastCalculatedAt": null }

Notas: Mínimo de pedidos definido por MIN_ORDERS_FOR_RFM (constante em src/lib/rfm/constants). Usa RPC rfm_distribution.


Descrição: Dispara recalculo assíncrono dos scores RFM do account. Fire-and-forget (retorna imediatamente).

Auth: Required (getAuthContext()) + role “owner” ou “admin” Rate Limit: Nenhum Audit: Nenhum

Request: N/A

Response:

  • 200: { "data": { "message": "Recalculo iniciado" } }
  • 403: { "data": { "error": "Apenas owner ou admin podem recalcular" } } (nota: retorna 200 com erro no body)

Notas: A função recalculateRfmScores() roda em background com .catch(). Erros são logados mas não retornados ao client. Validação de role feita manualmente (não usa requireRole).


Descrição: Retorna dashboard completo de revenue com overview, serie temporal diaria, revenue por automação, por campanha, e por link de tracking.

Auth: Required (getAuthContext()) Rate Limit: Nenhum Audit: Nenhum

Request:

  • Query params:
    • period (string, default: “30d”) - “7d” | “30d” | “90d”

Response:

  • 200:
{
"data": {
"overview": {
"totalRevenue": 50000.00,
"attributedRevenue": 35000.00,
"productCosts": 15000.00,
"gatewayFees": 1500.00,
"adSpend": 3000.00,
"profit": 15500.00,
"roas": 11.67,
"totalOrders": 200,
"attributedOrders": 140,
"avgOrderValue": 250.00
},
"daily": [
{ "date": "2026-02-13", "totalRevenue": 1500.00, "attributedRevenue": 1000.00, "orderCount": 6 }
],
"byAutomation": [
{ "automationId": "uuid", "automationName": "Carrinho", "revenue": 5000.00, "orderCount": 20, "avgOrderValue": 250.00 }
],
"byCampaign": [
{ "campaignId": "uuid", "campaignName": "Promo BF", "revenue": 10000.00, "orderCount": 40 }
],
"byLink": [
{ "linkId": "uuid", "shortCode": "abc123", "originalUrl": "https://...", "clicks": 500, "orders": 25, "revenue": 6250.00, "conversionRate": 5.0 }
]
}
}

Notas: Usa 5 RPCs paralelas: revenue_with_costs, revenue_by_day, revenue_by_automation, revenue_by_campaign, revenue_by_link. byLink limitado a 20 resultados.


Descrição: Retorna dashboard de ecommerce: overview (pedidos, revenue, ticket medio, carrinhos, recovery rate), dados por plataforma, top produtos, e pedidos por dia.

Auth: Required (getAuthContext()) Rate Limit: Nenhum Audit: Nenhum

Request:

  • Query params:
    • period (string, default: “30d”) - “7d” | “30d” | “90d”

Response:

  • 200:
{
"data": {
"overview": {
"total_orders": 200,
"total_revenue": 50000,
"avg_ticket": 250,
"pending_orders": 5,
"cancelled_orders": 3,
"refunded_orders": 1,
"total_carts": 80,
"recovered_carts": 15,
"recovery_rate": 18.75
},
"byPlatform": ["..."],
"topProducts": ["..."],
"daily": ["..."]
}
}

Notas: Usa 4 RPCs paralelas: ecommerce_overview, ecommerce_by_platform, ecommerce_top_products (limit 10), ecommerce_orders_by_day.


Descrição: Retorna métricas de execução de automações: total, completed, failed, latencia media por automação, e summary geral.

Auth: Required (getAuthContext()) Rate Limit: Nenhum Audit: Nenhum

Request:

  • Query params:
    • period (string, default: “7d”) - “7d” | “30d” | “90d”

Response:

  • 200:
{
"data": {
"data": [
{
"automation_id": "uuid",
"automation_name": "Boas-vindas",
"total_executions": 150,
"completed": 145,
"failed": 5,
"avg_latency_seconds": 2.3
}
],
"summary": {
"totalExecutions": 500,
"successRate": 97.0,
"avgLatency": 1.8
}
}
}

Notas: Usa RPC get_automation_execution_stats. Resultado limitado a top 20 automações por total_executions. Nomes das automações buscados separadamente da tabela automations.


Descrição: Lista todas as métricas customizadas (events) do account, agrupadas por nome, com contagem de eventos, valor total, fontes, e última ocorrencia.

Auth: Required (getAuthContext()) Rate Limit: Nenhum Audit: Nenhum

Request:

  • Query params:
    • source (string, opcional) - filtro por source do evento

Response:

  • 200:
{
"data": {
"metrics": [
{
"metric_name": "Order Placed",
"display_name": "Pedido Realizado",
"sources": ["shopify", "yampi"],
"total_events": 500,
"total_value": 125000.00,
"last_event_at": "2026-02-20T...",
"category": "ecommerce"
}
],
"available_sources": ["shopify", "yampi", "manual"]
}
}

Notas: Agrupamento e calculo feitos em memória (Maps). Display names vem da tabela metrics ou do helper getMetricDisplayName(). Sorted por total_events desc.


Descrição: Retorna detalhes de uma métrica específica: resumo (total eventos, valor, media, contatos únicos) e serie temporal diaria.

Auth: Required (getAuthContext()) Rate Limit: Nenhum Audit: Nenhum

Request:

  • Path params: name (string, URL-encoded) - nome da métrica
  • Query params:
    • period (string, default: “30d”) - “7d” | “30d” | “90d”

Response:

  • 200:
{
"data": {
"metric_name": "Order Placed",
"display_name": "Pedido Realizado",
"period": "30d",
"summary": {
"total_events": 150,
"total_value": 37500.00,
"avg_value": 250.00,
"unique_contacts": 120
},
"daily": [
{ "date": "2026-02-13", "count": 5, "value": 1250.00 }
]
}
}

Notas: Serie diaria preenche dias sem eventos com count: 0, value: 0. Path param e decodificado com decodeURIComponent().


Descrição: Retorna os contatos com maior valor total para uma métrica específica.

Auth: Required (getAuthContext()) Rate Limit: Nenhum Audit: Nenhum

Request:

  • Path params: name (string, URL-encoded) - nome da métrica
  • Query params:
    • limit (number, default: 10, min: 1, max: 50) - quantidade de contatos

Response:

  • 200:
{
"data": {
"contacts": [
{
"contact_id": "uuid",
"contact_name": "Joao Silva",
"event_count": 15,
"total_value": 3750.00,
"last_event_at": "2026-02-20T..."
}
]
}
}

Notas: Usa tabela materializada contact_metrics_summary ordenada por total_value desc. Nomes dos contatos buscados em batch.


Descrição: Retorna feed de atividade (eventos individuais) de uma métrica com paginação por cursor.

Auth: Required (getAuthContext()) Rate Limit: Nenhum Audit: Nenhum

Request:

  • Path params: name (string, URL-encoded) - nome da métrica
  • Query params:
    • limit (number, default: 20, min: 1, max: 100) - itens por página
    • cursor (string, uuid, opcional) - ID do último evento da página anterior

Response:

  • 200:
{
"data": {
"items": [
{
"id": "uuid",
"contact_name": "Maria Souza",
"contact_id": "uuid",
"value": 250.00,
"currency": "BRL",
"source": "shopify",
"properties": { "order_id": "12345" },
"occurred_at": "2026-02-20T..."
}
],
"nextCursor": "uuid-do-ultimo-item | null"
}
}

Notas: Páginação cursor-based usando occurred_at + id como composite cursor. Busca limit + 1 para determinar hasMore. Nomes dos contatos buscados em batch por IDs únicos.