Relatórios

Consulte o relatório de campanhas e fluxos de template com custo por categoria da Meta — mensagens enviadas, entregues, lidas e respondidas, com o mesmo recorte da aba Campanhas de /relatorios. Exige plano Enterprise.

escopo: reports:readEnterprise

Relatório de campanhas e fluxos de template, com custo por categoria da Meta (marketing, utility, authentication, authentication-international, service). Filtros: ?start_date=&end_date=&connection_id=&campaign_id=&template_name=&source=&campaign_status=&category=&currency=. O período também aceita `preset=today|last7|last30` ou `preset=custom&from=&to=` como alternativa a start_date/end_date; qualquer um dos dois formatos resolve para o mesmo `period` na resposta. `currency` aceita brl (padrão) ou usd e define a moeda de todos os custos. Use &include=filters para receber também as opções válidas de cada filtro — qualquer outro valor de `include` é 422, nunca ignorado em silêncio. `totals.campaigns` conta só campanhas com envio no período; os fluxos de template com envio ficam em `totals.template_sources`. O período segue o mesmo teto das demais abas de relatório: no máximo 1830 dias; com `g=hour|day|week` vale o máximo da visão pedida (2, 92 e 366 dias). `daily` traz um item por dia do período até hoje (no fuso da empresa), com zeros nos dias sem envio, e fica vazio quando não houve nenhum envio.

  • Custo só nasce quando a Meta confirma ENTREGA (`delivered` ou `read`) — uma mensagem `sent` sem confirmação fica `pending`, nunca zero.
  • `amount` só tem valor com `pending: 0` no mesmo bloco; havendo pendência, some `null` e `known_amount` traz o parcial já resolvido. Nunca some `known_amount` como se fosse o total.
  • Conexões `uazapi` não são Meta Cloud API: o custo dessas linhas é `not_applicable`, e a categoria dessas linhas não é cobrada.
  • `currency` escolhe a moeda de TODOS os blocos `costs` da resposta: `brl` (padrão) ou `usd`. A resposta ecoa a escolha em `currency` (`BRL` ou `USD`) e em `applied_filters.currency`. Para ver a outra moeda, faça uma nova chamada com `currency` diferente — contagens (`sent`, `resolved`, `pending`…) são as mesmas nas duas.
  • O custo canônico é o US$ da tarifa da Meta. O R$ é ESTIMADO: tarifa em US$ × PTAX de venda do Banco Central do dia local da mensagem (`basis` inclui `usd_rate_x_ptax_venda`). Enquanto a PTAX do dia não é publicada, a linha fica `pending` em R$.
  • `basis` lista, sem repetição e em ordem alfabética, as bases de preço dos envios do bloco (`rate_card_base_tier` para tarifa oficial, `usd_rate_x_ptax_venda` para R$ estimado pela PTAX, `historical_reference` para preço histórico informado pelo cliente); vem `[]` quando o bloco não tem custo. As linhas históricas do DFImóveis usam a referência validada pelo cliente (`historical_reference`) também em R$, não a PTAX.
  • `by_category` separa cada categoria por `pricing_window` e `template_category`. `category: service` com `pricing_window: customer_service_24h` é template enviado grátis dentro da janela de atendimento de 24 h, e `template_category` guarda a categoria original do template. `pricing_window: free_entry_point_72h` é a janela gratuita de 72 h aberta por anúncio (ponto de entrada) — NÃO é a janela de 24 h e mantém a categoria do template. `pricing_window: null` é envio sem janela gratuita. O filtro `category=service` inclui os templates da janela de 24 h.
  • Respostas livres de atendente e da IA não entram neste relatório: ele conta só envios de campanha e de template.
  • `by_source` é limitado a 500 origens; a partir daí a resposta vem com `truncated: true` e o excedente não aparece — refine o período ou os filtros.
  • Taxas (`delivery_rate`, `read_rate`, `reply_rate`) vêm em percentual de 0 a 100, com 1 casa decimal — não são fração de 0 a 1.
  • `by_source[].source_key` identifica a origem: `campaign:<campaign_id>` para campanha e `template:<connection_id>:<template_name>` para fluxo de template (`none` no lugar do connection_id quando a mensagem não tem conexão).
  • `campaigns` é alias de `by_source` (mesmo array) — mantido para compatibilidade com integrações existentes; prefira `by_source` em código novo.
  • `available_filters` só aparece com `&include=filters` — traz as conexões, campanhas e templates com envio no período, mais o catálogo fixo de categorias e o `period` (start_date/end_date) a que as opções se referem, para popular seletores sem uma segunda chamada. Se essa segunda leitura falhar, a resposta ainda vem 200 sem `available_filters`, com `degraded: ['available_filters']` no corpo.
  • `available_filters.templates[].category` é a categoria do TEMPLATE cadastrado na Meta; já `by_category[].category` pode ser `service` para envios dentro da janela de atendimento de 24h — são duas superfícies diferentes, não o mesmo dado em dois formatos.
  • Todo erro 4xx deste endpoint responde `{ success: false, error, code }` — inclusive o 422 de parâmetro inválido.
  • Uma única chamada gera um único `data_as_of` para todos os níveis (totals, by_source, by_category, daily) — os números nunca vêm de instantes diferentes.
  • `preset` (today, last7, last30 ou custom com from/to) é equivalente a start_date/end_date; qualquer uma das duas formas resolve para o mesmo intervalo e aparece em `period` na resposta, com o `preset` efetivamente usado.

Resposta (200)

Corpo da resposta
{
  "timezone": "America/Sao_Paulo",
  "data_as_of": "2026-09-16T12:00:00.000Z",
  "currency": "BRL",
  "period": {
    "preset": "custom",
    "start": "2026-07-24",
    "end": "2026-07-30",
    "timezone": "America/Sao_Paulo"
  },
  "applied_filters": {
    "start_date": "2026-07-24",
    "end_date": "2026-07-30",
    "connection_id": null,
    "campaign_id": null,
    "template_name": null,
    "source": "all",
    "campaign_status": null,
    "category": null,
    "currency": "brl"
  },
  "totals": {
    "campaigns": 0,
    "template_sources": 1,
    "recipients": 4936,
    "sent": 4936,
    "delivered": 4555,
    "not_delivered": 381,
    "read": 256,
    "replied": 426,
    "failed": 0,
    "delivery_rate": 92.3,
    "read_rate": 5.2,
    "reply_rate": 8.6,
    "costs": {
      "amount": 1457.6,
      "known_amount": 1457.6,
      "coverage": 1,
      "sent": 4936,
      "resolved": 0,
      "free": 0,
      "not_billed": 381,
      "void": 0,
      "not_applicable": 0,
      "historical": 4555,
      "pending": 0,
      "status": "complete",
      "basis": [
        "historical_reference"
      ]
    }
  },
  "byStatus": [],
  "by_source": [
    {
      "recipients": 4936,
      "sent": 4936,
      "delivered": 4555,
      "not_delivered": 381,
      "read": 256,
      "replied": 426,
      "failed": 0,
      "delivery_rate": 92.3,
      "read_rate": 5.2,
      "reply_rate": 8.6,
      "costs": {
        "amount": 1457.6,
        "known_amount": 1457.6,
        "coverage": 1,
        "sent": 4936,
        "resolved": 0,
        "free": 0,
        "not_billed": 381,
        "void": 0,
        "not_applicable": 0,
        "historical": 4555,
        "pending": 0,
        "status": "complete",
        "basis": [
          "historical_reference"
        ]
      },
      "source_type": "template",
      "source_key": "template:<connection_id>:boas_vindas",
      "campaign_id": null,
      "campaign_name": null,
      "campaign_status": null,
      "template_name": "boas_vindas",
      "connection_id": "<uuid>"
    }
  ],
  "campaigns": [
    {
      "recipients": 4936,
      "sent": 4936,
      "delivered": 4555,
      "not_delivered": 381,
      "read": 256,
      "replied": 426,
      "failed": 0,
      "delivery_rate": 92.3,
      "read_rate": 5.2,
      "reply_rate": 8.6,
      "costs": {
        "amount": 1457.6,
        "known_amount": 1457.6,
        "coverage": 1,
        "sent": 4936,
        "resolved": 0,
        "free": 0,
        "not_billed": 381,
        "void": 0,
        "not_applicable": 0,
        "historical": 4555,
        "pending": 0,
        "status": "complete",
        "basis": [
          "historical_reference"
        ]
      },
      "source_type": "template",
      "source_key": "template:<connection_id>:boas_vindas",
      "campaign_id": null,
      "campaign_name": null,
      "campaign_status": null,
      "template_name": "boas_vindas",
      "connection_id": "<uuid>"
    }
  ],
  "by_category": [
    {
      "recipients": 12,
      "sent": 12,
      "delivered": 12,
      "not_delivered": 0,
      "read": 9,
      "replied": 4,
      "failed": 0,
      "delivery_rate": 100,
      "read_rate": 75,
      "reply_rate": 33.3,
      "costs": {
        "amount": 0,
        "known_amount": 0,
        "coverage": 1,
        "sent": 12,
        "resolved": 0,
        "free": 12,
        "not_billed": 0,
        "void": 0,
        "not_applicable": 0,
        "historical": 0,
        "pending": 0,
        "status": "complete",
        "basis": []
      },
      "category": "service",
      "pricing_window": "customer_service_24h",
      "template_category": "utility"
    },
    {
      "recipients": 12,
      "sent": 12,
      "delivered": 12,
      "not_delivered": 0,
      "read": 9,
      "replied": 4,
      "failed": 0,
      "delivery_rate": 100,
      "read_rate": 75,
      "reply_rate": 33.3,
      "costs": {
        "amount": 0,
        "known_amount": 0,
        "coverage": 1,
        "sent": 12,
        "resolved": 0,
        "free": 12,
        "not_billed": 0,
        "void": 0,
        "not_applicable": 0,
        "historical": 0,
        "pending": 0,
        "status": "complete",
        "basis": []
      },
      "category": "marketing",
      "pricing_window": "free_entry_point_72h",
      "template_category": "marketing"
    }
  ],
  "daily": [
    {
      "recipients": 4936,
      "sent": 4936,
      "delivered": 4555,
      "not_delivered": 381,
      "read": 256,
      "replied": 426,
      "failed": 0,
      "delivery_rate": 92.3,
      "read_rate": 5.2,
      "reply_rate": 8.6,
      "costs": {
        "amount": 1457.6,
        "known_amount": 1457.6,
        "coverage": 1,
        "sent": 4936,
        "resolved": 0,
        "free": 0,
        "not_billed": 381,
        "void": 0,
        "not_applicable": 0,
        "historical": 4555,
        "pending": 0,
        "status": "complete",
        "basis": [
          "historical_reference"
        ]
      },
      "date": "2026-07-24"
    }
  ],
  "truncated": false,
  "available_filters": {
    "connections": [
      {
        "id": "<uuid>",
        "name": "WhatsApp Principal",
        "provider": "meta_cloud"
      }
    ],
    "campaigns": [
      {
        "id": "<uuid>",
        "name": "Promoção de Julho",
        "status": "sent",
        "connection_id": "<uuid>"
      }
    ],
    "templates": [
      {
        "template_name": "boas_vindas",
        "connection_id": "<uuid>",
        "category": "utility"
      }
    ],
    "categories": [
      "marketing",
      "utility",
      "authentication",
      "authentication-international",
      "service",
      "unknown"
    ],
    "period": {
      "start_date": "2026-07-24",
      "end_date": "2026-07-30"
    }
  }
}

Erros

StatusCódigoQuando ocorre
422INVALID_PARAMETERstart_date/end_date (ou preset/from/to) ausentes, fora do formato YYYY-MM-DD, com data inicial posterior à final ou período acima de 366 dias; connection_id/campaign_id que não é UUID; source fora de all, campaign ou template; campaign_status fora do enum; template_name acima de 512 caracteres; category fora do catálogo; currency fora de brl ou usd; include fora de filters; ou campaign_id/campaign_status combinados com source=template (template_name é aceito com qualquer source)
403INSUFFICIENT_SCOPEA chave não tem o escopo reports:read
403PLAN_REQUIREDA conta não está no plano Enterprise

Exemplo

curl
curl -s -H "Authorization: Bearer <sua-key>" https://www.prosalab.com/api/v1/reports/campaigns
Relatórios — Prosalab Developers