# Enviar mensagens

Envie texto livre na janela de atendimento ou use um template aprovado, com os anexos e botões previstos no modelo.

### POST /public/v1/messages

> Escolha `text` ou `template`, nunca os dois. Os modelos dos exemplos são ilustrativos: consulte [os templates do seu número](https://patrociniotech.com/documentacao-api/templates.md) e use os nomes e campos retornados.

## Enviar um template

Este exemplo usa um modelo com duas variáveis numeradas: nome da pessoa e número do pedido. Pode ser enviado dentro ou fora da janela de atendimento.

cURL · enviar template

```bash
curl -X POST https://api.patrociniotech.com/public/v1/messages \
  -H "Authorization: Bearer SUA_CHAVE" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: aviso-pedido-8421-v1" \
  -d '{
  "to": "5521999999999",
  "phone_number_id": "SEU_NUMERO_ID",
  "template": "aviso_entrega",
  "language": "pt_BR",
  "variables": [
    "Maria",
    "8421"
  ],
  "client_ref": "pedido-8421"
}'
```

## Escolher a API de entrega

O endereço da Patrocinio continua `POST /public/v1/messages`. O campo opcional `delivery_api` escolhe a API da Meta para esta mensagem; não muda o número remetente, a chave de acesso nem a URL base da integração.

| delivery\_api | Quando usar |
| --- | --- |
| cloud | Padrão quando o campo é omitido. WhatsApp Cloud API: texto livre permitido pela janela e templates das categorias suportadas, incluindo MARKETING. |
| marketing | Marketing Messages API: somente templates aprovados da categoria MARKETING. Exige que a conta conclua a ativação correspondente na Meta. |

cURL · template de marketing pela Marketing Messages API

```bash
curl -X POST https://api.patrociniotech.com/public/v1/messages \
  -H "Authorization: Bearer SUA_CHAVE" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: oferta-novembro-contato-8421-marketing-v1" \
  -d '{
  "to": "5521999999999",
  "phone_number_id": "SEU_NUMERO_ID",
  "template": "oferta_agencias",
  "language": "pt_BR",
  "delivery_api": "marketing",
  "variables": [
    "Maria"
  ],
  "client_ref": "oferta-novembro-contato-8421"
}'
```

Confirme as variáveis e os anexos no catálogo do seu número antes de usar o exemplo. Texto livre, avisos de utilidade e códigos de autenticação continuam em `cloud`; escolher `marketing` para esses conteúdos retorna `422 delivery_api_template_mismatch`, sem converter a categoria. Valores diferentes de `cloud` e `marketing` retornam `422 invalid_request`.

Ao escolher `marketing`, a Patrocinio encaminha o envio ao endpoint Meta `/PHONE_NUMBER_ID/marketing_messages` com `product_policy: STRICT`. Não existe troca automática para Cloud API quando essa rota está indisponível ou recusa o envio. O integrador não deve implementar essa troca como retry.

> A seleção não aceita termos nem ativa a conta na Meta, e não altera `message_activity_sharing`. Aprovação do template, qualidade, limites, bloqueios e saída de promoções continuam válidos. A opção não garante mais entregas nem preço menor.

Na Marketing Messages API, um template novo pode levar até dez minutos para sincronizar. Um modelo sem uso por mais de sete dias também precisa de sincronização após o primeiro uso; a Meta orienta aguardar dez minutos antes de iniciar o tráfego de marketing. Isso não é prazo de aprovação nem garantia de entrega. Não envie mensagens de aquecimento automaticamente.

Se a Meta recusar marketing pela Cloud API com o código `131063`, a integração retorna `422 cloud_marketing_disabled`. Falta de ativação ou permissão da Marketing Messages API retorna `422 marketing_api_not_ready`. Confira a configuração e a [orientação do erro](https://patrociniotech.com/documentacao-api/erros.md); nenhuma dessas respostas troca a rota por conta própria.

Referências Meta: [ativação da Marketing Messages API](https://developers.facebook.com/documentation/business-messaging/whatsapp/marketing-messages/get-started/) e [envio de marketing](https://developers.facebook.com/documentation/business-messaging/whatsapp/marketing-messages/send-marketing-messages/).

## Resposta de envio aceito

JSON · HTTP 200

```json
{
  "success": true,
  "data": {
    "message_id": "wamid.EXEMPLO",
    "status": "sent",
    "delivery_api": "cloud",
    "to": "5521999999999",
    "client_ref": "pedido-8421"
  }
}
```

`sent` confirma que a Meta aceitou o envio. Guarde `message_id` e acompanhe `message.status` no [webhook](https://patrociniotech.com/documentacao-api/webhook.md) para confirmar entrega, leitura ou falha.

`delivery_api` registra a API selecionada para a operação. Esse campo não é confirmação de entrega; mantenha-o junto à referência e ao payload para consultar e comparar os resultados.

Guarde também o `to` da resposta: ele identifica o destinatário reconhecido pela Meta. Mantenha o status no seu sistema a partir dos eventos; para conferir uma mensagem já identificada, use a consulta abaixo.

## Consultar um envio sem reenviar

### GET /public/v1/messages/{message_id}/status

Informe o `message_id` devolvido no envio. A consulta lê o estado registrado na Patrocinio Tech, não envia uma mensagem nem consulta o telefone na Meta. Somente mensagens de saída da empresa autenticada são acessíveis.

cURL · consultar status

```bash
curl "https://api.patrociniotech.com/public/v1/messages/wamid.EXEMPLO/status" \
  -H "Authorization: Bearer SUA_CHAVE"
```

JSON · estado registrado

```json
{
  "success": true,
  "data": {
    "message_id": "wamid.EXEMPLO",
    "status": "delivered",
    "delivery_api": "cloud",
    "delivery_api_confirmed": null,
    "client_ref": "pedido-8421",
    "phone_number_id": "SEU_NUMERO_ID",
    "to": "5521999999999",
    "created_at": "2026-11-06T12:00:00Z",
    "message_at": "2026-11-06T12:00:00Z",
    "checked_at": "2026-11-06T12:01:00Z",
    "error": null
  }
}
```

| Campo | Interpretação |
| --- | --- |
| status | sent, delivered, read, played, failed ou unknown. unknown indica ausência de um estado reconhecido; não é confirmação de falha. |
| delivery\_api | API selecionada para o envio: cloud ou marketing. Pode ser null em históricos sem esse registro. Não representa entrega nem uma mudança de categoria do template. |
| delivery\_api\_confirmed | API comprovada pela classificação do webhook Meta: marketing\_lite confirma marketing; marketing confirma cloud. null significa que essa evidência ainda não foi registrada, não uma falha de envio. |
| error | Somente em failed: code numérico da Meta, quando preservado, reason estável da integração e message em português. O texto bruto não é exposto; code pode ser nulo. |
| created\_at / message\_at | Horários UTC do registro e da mensagem/última tentativa. Não são o horário de entrega ou leitura; esses horários não são disponibilizados nesta consulta. |
| checked\_at | Horário desta consulta. Não comprova que chegou um novo evento da Meta nesse instante. |

> O webhook continua sendo o caminho principal. Use esta consulta para conciliar estados pendentes, com intervalo e tentativas limitados; ela também consome a cota de 600 requisições por minuto por chave. Codifique o identificador no caminho da URL com `encodeURIComponent(message_id)`.

`404 message_not_found` pode significar identificador incorreto, registro ainda não persistido, removido pela retenção ou pertencente a outra conta. Não comprova que a mensagem deixou de ser enviada nem autoriza reenvio automático. Sem `message_id`, preserve a operação e a chave de idempotência para recuperar o aceite original.

## Consultar quando o envio ficou sem resposta

### GET /public/v1/messages/status

Se o POST terminou em timeout ou 5xx antes de devolver o `message_id`, consulte com a **Idempotency-Key original**. A leitura encontra inclusive a reserva da tentativa, sem enviar outra mensagem nem liberar a chave.

cURL · consultar pela chave original

```bash
curl "https://api.patrociniotech.com/public/v1/messages/status" \
  -H "Authorization: Bearer SUA_CHAVE" \
  -H "Idempotency-Key: aviso-pedido-8421-v1"
```

Para uma mensagem já registrada, também é possível consultar por `client_ref`, de até 64 caracteres. Informe apenas uma das opções por chamada. Use uma referência por operação; se houver duas tentativas com a mesma referência, a API retorna `409 ambiguous_client_ref` e não escolhe uma delas.

cURL · consultar pela referência

```bash
curl --get "https://api.patrociniotech.com/public/v1/messages/status" \
  -H "Authorization: Bearer SUA_CHAVE" \
  --data-urlencode "client_ref=pedido-8421"
```

| data.resolution | O que significa |
| --- | --- |
| matched | A mensagem foi localizada no banco. data.message traz message\_id, status, destinatário, horários e error, no mesmo formato da consulta por ID. message\_id pode ser null em uma recusa anterior ao aceite. |
| accepted | Existe um aceite durável da Meta, mas o registro local não foi concluído. message traz o ID original e status sent; isso ainda não confirma entrega. Preserve a operação para reconciliação. |
| unconfirmed | Existe uma reserva sem confirmação do envio. message é null. Não significa failed e não permite criar uma nova chave para enviar de novo. |

JSON · tentativa ainda sem confirmação

```json
{
  "success": true,
  "data": {
    "lookup": "idempotency_key",
    "resolution": "unconfirmed",
    "message": null,
    "checked_at": "2026-11-06T12:01:00Z",
    "retention": {
      "idempotency_days": 2,
      "messages_days": 365,
      "measured_from": "created_at"
    }
  }
}
```

> Atenção: Uma consulta por `client_ref` só encontra tentativas já persistidas. Para timeout antes desse registro, use a chave de idempotência. Em qualquer consulta, `404 message_not_found` não comprova que o envio falhou: pode haver processamento em andamento ou remoção pela retenção.

`retention` informa os prazos configurados no momento da consulta, contados da criação. São dois dias para a reserva e 365 dias para mensagens por padrão; a manutenção é periódica. Mantenha seu histórico de operações e não use o fim desse prazo como autorização para repetir um envio incerto.

## Repetir a operação com segurança

O cabeçalho `Idempotency-Key` é opcional no contrato HTTP e recomendado em todo envio automatizado. Sem ele, repetir o POST pode enviar outra mensagem. A chave identifica uma operação dentro da empresa, inclusive quando existem várias chaves de API.

Gere uma `Idempotency-Key` por mensagem e salve-a antes de enviar. Em falha de conexão ou 5xx, repita com **a mesma chave e o mesmo corpo**.

A escolha de `delivery_api` faz parte dessa operação. Omitir o campo e enviar `cloud` explicitamente são equivalentes, inclusive para a chave de idempotência. Repetir a mesma chave com a mesma API de entrega conserva o envio original; trocar `cloud` por `marketing`, ou o contrário, usando a mesma chave retorna `409 idempotency_conflict`. Não altere a rota nem gere outra chave para contornar um resultado incerto.

| Resultado | Como agir |
| --- | --- |
| 200 · idempotent\_replay: true | A resposta é de uma operação já aceita. Use o message\_id retornado; a repetição não dispara outro envio. |
| 409 · idempotency\_in\_flight | A operação está em andamento ou sem confirmação. Aguarde e repita com a mesma chave. Se persistir, confira os eventos antes de iniciar outro envio. |
| 409 · idempotency\_conflict | A chave pertence a outro conteúdo. Confira a operação original; use outra chave somente para uma nova mensagem intencional. |
| 409 · idempotency\_legacy\_unverified | O registro antigo não permite comparar o conteúdo. Verifique o envio original e os eventos antes de outra tentativa. |

> Atenção: Não gere outra chave para contornar uma tentativa sem confirmação. A reserva não é liberada automaticamente após cinco minutos. A proteção dura pelo período de retenção; mantenha o histórico da operação também no seu sistema.

Dados recusados antes do envio podem ser corrigidos. Para tratar limites e indisponibilidade, use a política de [novas tentativas](https://patrociniotech.com/documentacao-api/erros.md).

## Enviar texto livre

O contato precisa ter escrito para o mesmo número da empresa nas últimas 24 horas. Confirme a [janela de atendimento](https://patrociniotech.com/documentacao-api/janela.md) quando necessário; ela não determina a gratuidade.

cURL · enviar texto livre

```bash
curl -X POST https://api.patrociniotech.com/public/v1/messages \
  -H "Authorization: Bearer SUA_CHAVE" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: texto-pedido-8421-v1" \
  -d '{
  "to": "5521999999999",
  "phone_number_id": "SEU_NUMERO_ID",
  "text": "Seu pedido saiu para entrega.",
  "client_ref": "pedido-8421"
}'
```

## Enviar um template com PDF

O cabeçalho `DOCUMENT` exige o arquivo em cada envio. Este exemplo combina um PDF, variáveis nomeadas e um botão de link dinâmico.

cURL · enviar template com PDF

```bash
curl -X POST https://api.patrociniotech.com/public/v1/messages \
  -H "Authorization: Bearer SUA_CHAVE" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: bilhete-pedido-8421-v1" \
  -d '{
  "to": "5521999999999",
  "phone_number_id": "SEU_NUMERO_ID",
  "template": "entrega_pedido_documento",
  "language": "pt_BR",
  "variable_names": [
    "pedido",
    "valor"
  ],
  "variables": [
    "8421",
    "R$ 495,75"
  ],
  "header_media": {
    "type": "document",
    "link": "https://arquivos.suaempresa.com/bilhetes/8421.pdf",
    "filename": "Bilhete 8421.pdf"
  },
  "button_url_param": "8421",
  "button_url_index": 0,
  "client_ref": "pedido-8421"
}'
```

> A Meta precisa acessar o link sem uma sessão de navegador. Use HTTPS e mantenha o arquivo disponível durante o envio. A amostra da aprovação não substitui o documento do pedido; para enviar sem PDF, selecione um template sem esse cabeçalho.

## Enviar um código de autenticação

Use um modelo `AUTHENTICATION` com botão OTP. A API preenche o corpo e o botão nativo com o mesmo `otp_code`. O índice suportado é `0`.

cURL · autenticação

```bash
curl -X POST https://api.patrociniotech.com/public/v1/messages \
  -H "Authorization: Bearer SUA_CHAVE" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: verificacao-operacao-1234-v1" \
  -d '{
  "to": "5521999999999",
  "phone_number_id": "SEU_NUMERO_ID",
  "template": "codigo_verificacao",
  "language": "pt_BR",
  "otp_code": "123456",
  "otp_index": 0,
  "client_ref": "operacao-1234"
}'
```

> Atenção: Gere o código no seu servidor e valide prazo, destinatário, operação, uso único e tentativas. O texto de expiração do template não invalida o código nem apaga a mensagem. Veja [validade do código e prazo de entrega](https://patrociniotech.com/documentacao-api/templates.md).

## Referência dos campos

Envie somente os campos documentados. Nomes desconhecidos, inclusive dentro de `header_media` e `pix_order`, retornam `422 invalid_request`. Os detalhes indicam o campo a corrigir; ele não é ignorado para prosseguir com valores padrão.

### Destinatário e conteúdo

| Campo | Regra |
| --- | --- |
| to | Obrigatório. Telefone internacional, com DDI e DDD, somente dígitos. Ex.: 5521999999999 (Brasil) ou 351912345678 (Portugal). O envio não acrescenta o país automaticamente. |
| phone\_number\_id | ID do seu número conectado. Sem ele, a API usa o número padrão da conta. |
| delivery\_api | Opcional: cloud (padrão) ou marketing. marketing exige template da categoria MARKETING e ativação na Meta; não aceita texto livre, UTILITY ou AUTHENTICATION. |
| text | Texto livre de até 4.096 caracteres. Exige janela aberta e não pode ser combinado com campos de template. |
| template | Nome do modelo aprovado. Use em vez de text. |
| language | Idioma do modelo. Padrão: pt\_BR. |
| reply\_to\_message\_id | Opcional. ID da mensagem recebida que será citada na resposta. |

### Variáveis e cabeçalho

| Campo | Regra |
| --- | --- |
| variables | Um valor por variável do corpo. Até 20 valores de 1.024 caracteres; a quantidade exigida vem do modelo. |
| variable\_names | Nomes associados aos valores em variables, para modelos NAMED. Use a ordem da listagem ou mantenha cada par nome/valor correspondente. |
| header\_media | Obrigatório se o modelo exigir mídia. Objeto com type (document, image ou video), link HTTP(S) válido, sem usuário/senha ou espaços, e filename opcional para documento. |
| header\_text | Até 200 caracteres. Obrigatório se o cabeçalho de texto tiver uma variável; omita para cabeçalho fixo ou de mídia. |

### Botões e autenticação

| Campo | Regra |
| --- | --- |
| button\_url\_param | Valor da parte variável de um botão de link. Até 200 caracteres; a API aceita um link dinâmico por template. |
| button\_url\_index | Posição do botão de link na lista, começando em zero. Padrão: 0. |
| coupon\_code / coupon\_index | Código de até 15 caracteres e posição do botão de cupom COPY\_CODE. Não use para autenticação. |
| otp\_code | Código de autenticação de até 15 caracteres, sem espaços ou caracteres de controle. variables pode ser omitido. |
| otp\_index | Para autenticação, use 0 ou omita. Não combine OTP com anexo, cupom, link dinâmico ou PIX. |
| pix\_order | Pedido para um template de cobrança, com botão ORDER\_DETAILS. Veja o exemplo abaixo. |

Valores de variáveis não aceitam quebras de linha, tabulações ou mais de quatro espaços consecutivos. Nenhum valor é cortado para caber: a API informa o erro para você corrigir.

## Marketing, consentimento e saída da lista

A API permite enviar um template `MARKETING` a um contato com aceite `pending` ou sem cadastro local. Isso não registra consentimento como `accepted`. Conserve no seu sistema a origem da lista e a evidência de que a pessoa espera essa comunicação.

Uma recusa de promoções em qualquer número da mesma empresa, ou um bloqueio no número de envio, impede novos envios de marketing com `422 marketing_not_allowed`. Não há parâmetro para ignorar essa exclusão. A consulta de [janela e preferência](https://patrociniotech.com/documentacao-api/janela.md) permite conferir o bloqueio antes; a API verifica novamente ao enviar.

> Nas campanhas do painel, incluir contatos com aceite pendente exige confirmação de risco. Essa opção não transforma pendência em aceite e não inclui quem pediu para sair. A API de envio individual não recebe essa opção de campanha.

Uma saída de promoções não impede um aviso legítimo de pedido com template `UTILITY` ou um código solicitado com `AUTHENTICATION`. Use a categoria correspondente ao conteúdo; mudar a categoria não é uma forma de reenviar a promoção recusada.

## Relacionar o envio ao seu pedido

`client_ref` é opcional, tem até 64 caracteres e volta nos eventos de status. Use um identificador único da operação, como `pedido-8421-entrega-v1`, para consultá-la depois. Ele ajuda na conciliação, mas não substitui a `Idempotency-Key` nem impede envios duplicados.

O envio não impõe unicidade de `client_ref`. Garanta essa regra no seu outbox por empresa: bilhete, reembolso e aviso do mesmo pedido são operações diferentes. Uma referência reutilizada pode retornar `409 ambiguous_client_ref` na consulta. Veja [o que persistir e como validar a integração](https://patrociniotech.com/documentacao-api/validacao.md).

Guarde também `message_id` e `phone_number_id`: um pedido pode ter várias mensagens e mais de um número de envio.

## Cobrança PIX

Disponível para template de detalhes do pedido e conta com pagamentos habilitados na Meta. Os valores são inteiros JSON em centavos; strings, decimais e booleanos são recusados. A API confere a soma dos itens e da taxa, sem arredondar valores.

### Ver exemplo de cobrança e campos de pagamento

cURL · cobrança PIX

```bash
curl -X POST https://api.patrociniotech.com/public/v1/messages \
  -H "Authorization: Bearer SUA_CHAVE" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: cobranca-pedido-8421-v1" \
  -d '{
  "to": "5521999999999",
  "phone_number_id": "SEU_NUMERO_ID",
  "template": "cobranca_emissao",
  "language": "pt_BR",
  "pix_order": {
    "reference_id": "PED-8421",
    "pix_code": "CODIGO_PIX_COMPLETO_GERADO_PELO_SEU_PSP",
    "merchant_name": "Sua Empresa",
    "key": "CHAVE_PIX_DA_EMPRESA",
    "key_type": "EVP",
    "items": [
      {
        "name": "Emissão de passagem",
        "amount": 49575,
        "quantity": 1
      }
    ],
    "tax": 0
  },
  "client_ref": "pedido-8421"
}'
```

| Em pix\_order | Uso |
| --- | --- |
| reference\_id | Referência da cobrança no seu sistema. Até 64 caracteres. |
| pix\_code | Copia e cola completo gerado pelo seu PSP para esta cobrança. Não use o texto ilustrativo acima. |
| merchant\_name / key / key\_type | Nome do recebedor, chave PIX e tipo: CNPJ, CPF, EMAIL, PHONE ou EVP. |
| items | Até 30 itens com name, amount unitário em centavos e quantity. |
| tax / total\_amount | tax é opcional, com padrão 0. Se total\_amount for informado, deve ser igual a Σ(amount × quantity) + tax. |
| Limite numérico | Cada valor e o total calculado devem caber em 9.007.199.254.740.991 centavos, limite de inteiro seguro da integração. Isso não substitui os limites da Meta ou do seu PSP. |
| goods\_type / retailer\_id | goods\_type: digital-goods (padrão) ou physical-goods. retailer\_id é opcional em cada item; sem ele, a posição identifica o item. |

## Validar um telefone

Se o cadastro contém apenas DDD e telefone, informe o país em `country` (ISO de duas letras) nesta consulta antes de enviar. Para um telefone já internacional, use `+` e DDI, ou envie somente os dígitos e omita `country`. Não presuma que todos os clientes usam o DDI 55.

### POST /public/v1/validate

cURL · validar formato

```bash
curl -X POST https://api.patrociniotech.com/public/v1/validate \
  -H "Authorization: Bearer SUA_CHAVE" \
  -H "Content-Type: application/json" \
  -d '{"to": "(21) 99999-9999", "country": "BR"}'
```

Use o `to` normalizado quando `data.valid` for `true`. Essa consulta valida o formato; não confirma existência no WhatsApp nem autorização para envio.

> Atenção: `valid=true` não significa que a mensagem será entregue. Um telefone digitado errado pode ter formato válido. A Cloud API não oferece uma consulta prévia para confirmar se o destinatário tem WhatsApp.

Após enviar, guarde `message_id` e `client_ref`. Considere a entrega confirmada apenas ao receber `message.status` com `delivered` ou `read`. O aceite inicial `sent` ainda pode terminar em `failed`.

Se chegar `error.reason=recipient_unreachable` com `error.code=131026`, registre a falha e confira o telefone com o cliente por outro canal. Esse código não comprova ausência de WhatsApp. Evite repetições automáticas e variações do número sem confirmação.

---

Fonte: https://patrociniotech.com/documentacao-api/mensagens
Índice para IA: https://patrociniotech.com/documentacao-api/llms.txt
