# Custos e consumo

> Preço por mensagem entregue, franquia de serviço, consumo do mês e como aplicar o preço.

Fonte: https://metahub.matratecnologia.com/docs/custos

A Meta cobra por mensagem **entregue** do negócio para o contato; mensagem que não chega a `delivered` não é cobrada. O hub não calcula valor: repassa o que a Meta informa e conta o nível gratuito.

**Campos de preço.** O `pricing` do `whatsapp.message.status` (`source: "meta"`) vem no `sent` e em um de `delivered`/`read`:

| Campo | Valores |
|---|---|
| `category` | `service`, `group_service`, `utility`, `marketing`, `marketing_lite`, `authentication`, `authentication-international`, `referral_conversion`, `group_marketing`, `group_utility` (como a Meta manda; trate valor novo como desconhecido) |
| `type` | `regular` (cobrada), `free_customer_service` (serviço 1:1 dentro do nível gratuito), `free_group_customer_service` (serviço de grupo dentro do nível gratuito) ou `free_entry_point` (grátis por estar numa janela de ponto de entrada gratuito); trate outro valor como desconhecido |
| `subtype` | `paid_exempt` para conta de governo ou sem fins lucrativos isenta |
| `billable` | Obsoleto na Meta; decida por `type` |
| `model` | Modelo de preço, como a Meta manda |

Observado em testes com o app real: reação enviada pelo hub recebeu só o status `sent`, sem `pricing`; texto, interativo e imagem vieram com `category: "service"` e `type: "free_customer_service"`.

**Nível gratuito de serviço.** Desde 01/10/2026 a mensagem de serviço (resposta livre, sem template) volta a ser cobrada, com 1.000 mensagens de serviço **entregues** grátis por número por mês. Não acumula e vira à meia-noite no fuso da conta de mensagens na Meta. Template de utilidade dentro da janela de atendimento também passou a ser cobrado (`type: "regular"`).

`GET /v1/connections/:connectionId/usage` → `{ "usage": { ... } }`:

```json
{
  "month": "2026-10",
  "timezone": "America/Sao_Paulo",
  "limit": 1000,
  "delivered": 812,
  "free": 812,
  "charged": 0,
  "remaining": 188,
  "exhausted": false
}
```

- `delivered`: mensagens de serviço entregues no mês, cada uma contada uma vez (pelo primeiro `delivered` ou `read` com `category: "service"`). `free` são as de `type: "free_customer_service"`, `charged` as de `type: "regular"`; uma de serviço com outro `type` (como `free_entry_point`) conta em `delivered` e em nenhum dos dois, então `delivered` pode passar de `free + charged`. `exhausted` fica `true` com a primeira cobrada ou com `free` em 1.000; `remaining` é `0` quando `exhausted`, senão `limit - free`.
- **Mês.** Vira à meia-noite no fuso da conta de mensagens, lido da Meta (`timezone`, nome IANA); conta cujo fuso a Meta não informou usa o padrão do hub (`America/Sao_Paulo`).
- **Aproximação.** Os status ficam 30 dias no hub: no dia 31 o primeiro dia do mês já pode ter saído e a conta fica menor que a real. A conta é por conexão, e a Meta conta por número: se o número veio de outro workspace no meio do mês, a contagem recomeça do zero aqui e o aviso de 800 pode não sair. Mensagem de serviço de grupo (`group_service`) desconta da mesma franquia na Meta, mas não entra nesta conta. A fonte da verdade é a fatura da Meta.

O evento `whatsapp.usage.free_tier` avisa sem consulta:

```json
{
  "phoneNumberId": "109876543210987",
  "month": "2026-10",
  "timezone": "America/Sao_Paulo",
  "level": "warning",
  "limit": 1000,
  "free": 800,
  "charged": 0
}
```

`level` é `warning` ao chegar a 800 gratuitas e `exhausted` na primeira mensagem de serviço cobrada. Cada nível sai uma vez por número e mês.

**Método de pagamento.** Passadas as 1.000 gratuitas, sem método de pagamento válido a Meta não entrega mensagens de serviço. O envio recusado na hora sai `failed` com `errorCode: "payment_method_required"` (Meta `131042`); recusado depois do aceite, o `whatsapp.message.status` `failed` traz `131042` em `errors`.

**Janela de ponto de entrada gratuito (FEP).** Quando o contato escreve por um anúncio Click-to-WhatsApp (Android/iOS) e o negócio responde dentro da janela de atendimento, a resposta é grátis e abre uma janela de até 7 dias em que marketing, utilidade, autenticação e serviço saem grátis (mensagem do Meta Business Agent continua cobrada). O hub lê o fim dela de `conversation.expiration_timestamp` (só vem no `sent`) e devolve em `freeEntryPoint.expiresAt` no `GET …/windows`. Ela só muda o preço: mensagem livre continua exigindo a janela de 24 h, e fora dela só template.

**Consumo do mês.** `GET /v1/connections/:connectionId/consumption?month=YYYY-MM` (sem `month`, o mês corrente; aceita o corrente e os 12 anteriores, no fuso da conta; fora disso, 400 `CONSUMPTION_MONTH_OUT_OF_RANGE`) → `{ "consumption": { ... } }`:

```json
{
  "month": "2026-10",
  "timezone": "America/Sao_Paulo",
  "currency": "BRL",
  "hub": [
    { "category": "marketing", "type": "regular", "delivered": 1 },
    { "category": "service", "type": "free_customer_service", "delivered": 1 },
    { "category": "utility", "type": "regular", "delivered": 1 }
  ],
  "meta": {
    "fetchedAt": "2026-10-23T18:06:32.265Z",
    "items": [
      { "category": "MARKETING", "type": "REGULAR", "country": "BR", "tier": "0:MAX", "volume": 1 },
      { "category": "SERVICE", "type": "FREE_CUSTOMER_SERVICE", "country": "BR", "tier": null, "volume": 1 },
      { "category": "UTILITY", "type": "REGULAR", "country": "BR", "tier": "0:250000", "volume": 1 }
    ]
  }
}
```

- `hub`: contado dos status de entrega desta conexão, cada mensagem uma vez (pelo primeiro `delivered` ou `read` com `pricing`), por `category` e `type` como o webhook manda (minúsculas). Só o que passou pela conexão, e só 30 dias (retenção dos status).
- `meta`: o `pricing_analytics` da Meta para o número da conexão, lido todo dia às 6:00 (mês corrente e anterior), por categoria, tipo, país e faixa de volume, como a Meta manda (maiúsculas; `AUTHENTICATION_INTERNATIONAL` corresponde a `authentication-international` do webhook). Inclui o que o hub não vê (mensagens mandadas pelo app no Coexistence). A Meta avisa que o dado é aproximado e pode diferir da fatura. Número que veio de outro workspace do hub mostra só a partir do dia seguinte ao da troca. `null` antes da primeira leitura.
- `tier` (`<inferior>:<superior>`, ou `null` em mensagem grátis) é a faixa de volume do par país e categoria: existe só para utilidade e autenticação; marketing vem `0:MAX`. A faixa não chega pelo webhook.
- `currency` é a moeda de cobrança da conta na Meta (`null` enquanto a Meta não informa).
- **O preço é do app.** O hub não lê o custo em dinheiro: o token da conexão lê o volume, mas a Meta recusa o custo (permissão). Para estimar, multiplique cada linha de `meta.items` com `type: "REGULAR"` pelo preço da tabela da Meta para o país, a categoria e a faixa, na moeda da conta; os tipos grátis valem zero. A tabela muda só no início de cada trimestre (1º de janeiro, abril, julho e outubro), com aviso de 1 mês.

**Como gastar menos.**

- Uma mensagem em vez de várias: cada balão entregue conta. Junte o texto que sairia em sequência.
- Mídia com `caption` em vez de mídia seguida de texto.
- Resposta de agente de IA num balão só, sem quebrar em frases.
