Whapier

Programadores

Documentação da API

Uma API REST autenticada por token para mensagens, modelos, contactos, campanhas, fluxos e o estado de entrega e o custo de cada mensagem. Crie uma chave de API em Ferramentas de programador na sua conta e autentique todas as chamadas com Authorization: Bearer <token>.

Há exemplos completos em PHP, Node.js, Python, Java e Ruby na documentação dentro da aplicação depois de criar uma conta.

Referência legível por máquinas: OpenAPI 3.1 (JSON) · Coleção Postman

Antes de começar

Autenticação

Todos os pedidos levam uma chave de API no cabeçalho Authorization como token Bearer. As chaves são criadas em Ferramentas de programador > Chaves de API e mostradas uma única vez.

Uma chave tem âmbitos: read (todos os GET), send (os endpoints de envio, as campanhas e o início de fluxos) e manage (criar, alterar e eliminar contactos, grupos, respostas automáticas, webhooks e modelos, mais as ações da caixa de entrada). Uma chave sem o âmbito recebe 403 com a indicação do âmbito em falta.

Uma chave pode expirar: uma chave expirada recebe 401 com "This API key has expired". Um token em falta ou desconhecido também é 401.

Uma chave sandbox valida todos os pedidos, regista a mensagem com o estado "sandbox" e não envia nada para o WhatsApp - desenvolva contra a API real sem uma linha de WhatsApp nem custos.

Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>
Limite de pedidos

60 pedidos por minuto por chave de API; os pedidos sem chave são contados por endereço IP.

Todas as respostas levam X-RateLimit-Limit e X-RateLimit-Remaining. Acima do limite, a resposta é 429 com statusCode 429, uma message e um cabeçalho Retry-After em segundos.

GET /api/usage indica o limite em rate_limit.per_minute. /api e /api/v2 partilham um único contador por chave.

HTTP/1.1 429 Too Many Requests
Retry-After: 42
{"statusCode": 429, "message": "Too many requests. Try again in 42 seconds."}
Idempotência

Envie um cabeçalho Idempotency-Key (1 a 128 caracteres, único por operação) nos endpoints POST que criam algo: os envios, as campanhas, os contactos, os grupos e as respostas automáticas.

A mesma chave com o mesmo pedido dentro de 24 horas devolve a resposta guardada com o cabeçalho Idempotent-Replayed: true, e nada volta a ser executado. Um cliente que repete o pedido depois de um timeout deixa de enviar duas vezes.

A mesma chave com um pedido diferente é 422; a mesma chave enquanto o primeiro pedido ainda está a correr é 409. Só as respostas 2xx e 4xx são guardadas, por isso um 5xx pode ser repetido com a mesma chave.

Idempotency-Key: 7c9e6679-7425-40de-944b-e07fc1f90ae7
Datas e fusos horários

Todas as datas que a API devolve estão em UTC, em ISO-8601 com o respetivo desvio, seja qual for o fuso horário que a organização usa no painel.

As datas que envia (scheduled_at, since) são lidas como UTC, salvo se incluírem um desvio.

"created_at": "2026-10-05T09:30:00+00:00"
Erros

Todas as respostas são JSON com statusCode e message; um payload recusado acrescenta errors, um mapa de nome de campo para a lista de problemas.

400 entrada inválida; 401 chave em falta, inválida ou expirada; 403 âmbito, subscrição, limite do plano ou conta em análise; 404 uuid desconhecido, ou que pertence a outro espaço de trabalho; 409 conflito (uma transição de campanha impossível, uma Idempotency-Key ainda em curso); 422 recusado por uma regra (a janela de 24 horas, STOP, variáveis do modelo); 429 limite de pedidos; 500 culpa nossa.

As ações da caixa de entrada (assign, close e reopen em /api/conversations/{contact_uuid}) respondem 409 enquanto o ticketing está desligado em Definições > Tickets; ler a conversa e adicionar uma nota funcionam em qualquer caso.

Em /api (v1), uma recusa do próprio WhatsApp é um 200 com data.success false e o motivo em data.data.error (code, message, type). Em /api/v2 a mesma recusa é um HTTP 422 - consulte Versões.

{"statusCode": 400, "message": "The given data was invalid.", "errors": {"phone": ["The phone number is not valid."]}}
Paginação

Os endpoints de listagem aceitam page (a partir de 1) e per_page (predefinição 10, máx. 100; /api/messages usa 25 por predefinição) e estão ordenados do mais recente para o mais antigo.

Contactos, grupos, respostas automáticas, modelos, campanhas e registos de campanha respondem com data, links e meta (current_page, last_page, per_page, total). /api/messages responde com statusCode, data e meta (page, per_page, total, last_page).

Uma conversa é, em vez disso, paginada por cursor: GET /api/contacts/{uuid}/messages e GET /api/conversations/{contact_uuid} respondem do mais recente para o mais antigo com next_before; passe-o como before para obter as mensagens mais antigas.

Enviar um modelo

Um envio de modelo tem de levar exatamente tantos parâmetros quantos os marcadores do modelo aprovado; a Meta recusa uma discrepância com o erro 132000.

GET /api/templates/{uuid} devolve example_payload: um corpo completo para POST /api/send/template com o número certo de parâmetros para o cabeçalho, o corpo e os botões URL - substitua os valores e envie-o.

POST /api/templates submete um modelo à Meta a partir de uma forma JSON plana e responde com o motivo da Meta quando é recusado; POST /api/templates/sync obtém os modelos da Meta após uma alteração no Meta Business Manager.

GET https://whapier.com/api/templates/{{uuid}}
{"data": {"name": "order_update", "variables": {"header": 0, "body": 1, "buttons": 0}, "example_payload": {"phone": "+40721000001", "template": {"name": "order_update", "language": {"code": "en"}, "components": [{"type": "body", "parameters": [{"type": "text", "text": "Ana"}]}]}}}}
Webhooks

Os webhooks de saída configuram-se em Ferramentas de programador > Webhooks ou pela API (POST /api/webhooks): um URL https e os eventos a receber. O segredo de assinatura é gerado por nós e mostrado uma só vez. Cada entrega é um POST com um corpo JSON que leva event e data.

O cabeçalho X-Whapier-Signature é "sha256=" seguido do HMAC-SHA256 do corpo bruto do pedido com esse segredo, em hexadecimal. Volte a calculá-lo sobre os bytes que recebeu e compare antes de confiar no payload.

Responda 2xx em 15 segundos. Uma entrega que falha é repetida mais duas vezes, após 60 segundos e após 5 minutos; à terceira falha o evento é descartado.

Os eventos: message.received e message.sent; message.status quando a Meta reporta uma mensagem como delivered, read ou failed (com a falha e a campanha de onde veio); campaign.finished com as contagens finais; ticket.created e ticket.closed; contact.opted_out e contact.opted_in; contact, group e autoreply created, updated e deleted; template.status.update, template.quality.update e account.update tal como a Meta os envia. GET /api/webhooks/events lista-os com uma descrição e POST /api/webhooks/{uuid}/test entrega um exemplo.

X-Whapier-Signature: sha256=5d41402abc4b2a76b9719d911017c592...
{"event": "message.status", "data": {"uuid": "64968a32-fdd9-4c1d-8941-b8e538036616", "wam_id": "wamid.HBgM...", "status": "delivered", "timestamp": "2026-10-05T09:30:00+00:00", "failure": null, "contact": {"uuid": "81a2d165-41e2-43f2-847e-d69e08cba0e0", "phone": "+40721000001"}, "campaign": null}}
{"event": "campaign.finished", "data": {"uuid": "3f1c2d0e-5b7a-4c8d-9e0f-1a2b3c4d5e6f", "name": "October offers", "status": "completed", "counts": {"contacts": 120, "sent": 118, "delivered": 110, "read": 64, "failed": 2}, "finished_at": "2026-10-05T09:30:00+00:00"}}
message.received
message.sent
message.status
message.status.update
contact.created
contact.updated
contact.deleted
contact.opted_out
contact.opted_in
group.created
group.updated
group.deleted
autoreply.created
autoreply.updated
autoreply.deleted
campaign.finished
ticket.created
ticket.closed
template.status.update
template.quality.update
account.update
Versões: v1 e v2

/api (versão 1) continua suportado tal como está. /api/v2 serve os mesmos endpoints, payloads e campos com uma diferença: o estado HTTP transporta o resultado.

Na v2, uma recusa do WhatsApp num envio é um HTTP 422 cujo corpo tem statusCode 422, a message, error (code, message e type do WhatsApp) e data (a resposta da v1), em vez de um 200 com data.success false. Sempre que o statusCode num corpo difere do estado HTTP, o estado HTTP segue o statusCode.

Tudo o resto - autenticação, âmbitos, limite de pedidos, idempotência, datas, paginação - é idêntico, e a mesma chave funciona em ambas.

POST https://whapier.com/api/v2/send
{"statusCode": 422, "message": "Template name does not exist", "error": {"code": 132001, "message": "Template name does not exist", "type": "OAuthException"}, "data": {"success": false, "message": "Template name does not exist", "data": {"error": {"code": 132001}}}}

Verificação

GET /api/verify Verificar a chave de API
# Confirma que o token Bearer é válido e que a subscrição da organização está ativa, antes de chamar outros endpoints.
# HTTP 200: token válido. 401: token em falta/inválido. 403: subscrição inativa.

curl -X GET \
https://whapier.com/api/verify \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Accept: application/json'

Contactos

GET /api/contacts Obter a lista de contactos
# Parâmetros opcionais: ?page=1&per_page=10 (per_page no máximo 100).
# Do mais recente para o mais antigo. Resposta: data (objetos de contacto), links e meta (current_page, last_page, per_page, total).
# Um contacto: id, uuid, phone, first_name, last_name, email, address, metadata, groups (uuid, name), source, opted_in_at, opted_out_at, created_at, updated_at.
# Filtros de pesquisa, combinados com AND: phone (qualquer formato que o país da organização consiga ler; 400 quando não é um número), email (exato, sem distinguir maiúsculas), q (2 a 128 caracteres, procurado no nome, email e número), group (o uuid de um grupo de contactos; 400 quando é desconhecido), opted_out (true | false), updated_since (uma data, UTC), source (api, manual, import, entry point...).

curl -X GET \
"https://whapier.com/api/contacts?page=1&per_page=10" \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Accept: application/json'
GET /api/contacts/{uuid} Obter um contacto
# O objeto contacto de Obter a lista de contactos mais unread_messages, last_message_at e ticket (status, assigned_to: name, email).
# ticket é null enquanto o ticketing está desligado em Definições > Tickets, ou quando a conversa ainda não tem ticket. 404 quando o uuid é desconhecido, foi eliminado ou pertence a outro espaço de trabalho.

curl -X GET \
https://whapier.com/api/contacts/{{uuid}} \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Accept: application/json'
POST /api/contacts Adicionar contacto
# Campos do corpo JSON:
#   phone (obrigatório) — número internacional; validado e guardado em E.164. Tem de ser único por organização (400 se estiver duplicado).
#   first_name, last_name, email (opcionais) — omita-os, ou envie null ou "", para contactos sem nome.
#   street, city, state, zip, country (opcionais) — guardados no JSON de address.
#   metadata (opcional) — qualquer valor serializável em JSON.
#   group (opcional) — array de strings com UUIDs de grupos de contactos.
#   marketing_opt_in (opcional, booleano) — true regista o consentimento de marketing no contacto (histórico de consentimento RGPD, source: api); false regista um opt-out. Omita-o para deixar o consentimento inalterado.
# Respostas: 200 sucesso { statusCode, id, message }; 400 erro de validação; 403 subscrição inativa ou limite de contactos atingido.
# Aceita um cabeçalho Idempotency-Key (consulte Antes de começar).

curl -X POST \
https://whapier.com/api/contacts \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
    "phone": "+40721000001",
    "first_name": "Ana",
    "last_name": "Pop",
    "email": "ana@example.com",
    "group": [
        "d746e4c5-db24-4fb2-be03-590421344d69"
    ],
    "marketing_opt_in": true
}'
POST /api/contacts/bulk Criar ou atualizar contactos em massa
# contacts (obrigatório, 1 a 500 objetos) com os campos de Adicionar contacto por linha. Uma linha cujo phone já existe no espaço de trabalho é atualizada com os campos presentes (como faz Editar contacto); um número novo é criado.
# Cada linha é independente: uma linha errada falha sozinha e as outras passam. Resposta: { statusCode, created, updated, failed: [ { index, phone, errors } ], limit_reached, message }.
# A criação para no limite de contactos do plano: limit_reached fica true e as linhas que não couberam são listadas em failed. As atualizações nunca contam para o limite. Aceita um cabeçalho Idempotency-Key.

curl -X POST \
https://whapier.com/api/contacts/bulk \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
    "contacts": [
        {
            "phone": "+40721000001",
            "first_name": "Ana",
            "last_name": "Pop",
            "email": "ana@example.com"
        },
        {
            "phone": "0721 000 002",
            "first_name": "Ion",
            "group": [
                "d746e4c5-db24-4fb2-be03-590421344d69"
            ]
        },
        {
            "phone": "not-a-phone",
            "first_name": "Nobody"
        }
    ]
}'
PUT /api/contacts/{uuid} Editar contacto
# Os mesmos campos JSON de Adicionar contacto. O {uuid} do caminho é o id do contacto devolvido na criação.
# phone é opcional numa atualização; se o alterar, o novo número não pode pertencer a outro contacto (400 duplicado).
# É permitido atualizar com o mesmo phone deste contacto.
# Os campos que omitir mantêm o valor; envie um campo como null ou "" para o limpar. As chaves de metadata que enviar são fundidas com as já guardadas; as restantes mantêm-se.
# marketing_opt_in (opcional, booleano) — true regista o consentimento de marketing (source: api), false regista um opt-out; se for omitido, o consentimento fica inalterado.
# 404 quando o uuid é desconhecido, foi eliminado ou pertence a outro espaço de trabalho.

curl -X PUT \
https://whapier.com/api/contacts/{{uuid}} \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
    "first_name": "Ana",
    "last_name": "Popescu",
    "metadata": {
        "plan": "platinum"
    }
}'
DELETE /api/contacts/{uuid} Eliminar contacto
# Faz um soft delete do contacto; sai de imediato de todas as listas. 404 quando o uuid é desconhecido ou já foi eliminado.
# Resposta: { statusCode, id, message }.

curl -X DELETE \
https://whapier.com/api/contacts/{{uuid}} \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Accept: application/json'

Grupos de contactos

GET /api/contact-groups Obter a lista de grupos de contactos
# Parâmetros opcionais: ?page=1&per_page=10 (per_page no máximo 100).
# Cada grupo: uuid, name, contacts_count (membros ativos), created_at, updated_at.

curl -X GET \
"https://whapier.com/api/contact-groups?page=1&per_page=10" \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Accept: application/json'
POST /api/contact-groups Adicionar grupo de contactos
# name (obrigatório) tem de ser único entre os grupos da organização (400 se já existir).
# Resposta: { statusCode, id, message }. Aceita um cabeçalho Idempotency-Key.

curl -X POST \
https://whapier.com/api/contact-groups \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
    "name": "Lead 5"
}'
PUT /api/contact-groups/{uuid} Editar grupo de contactos
# O mesmo corpo de Adicionar grupo de contactos. 404 para um uuid desconhecido.

curl -X PUT \
https://whapier.com/api/contact-groups/{{uuid}} \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
    "name": "Lead 5"
}'
DELETE /api/contact-groups/{uuid} Eliminar grupo de contactos
# Remove o grupo e as suas associações; os contactos em si são mantidos. 404 para um uuid desconhecido.

curl -X DELETE \
https://whapier.com/api/contact-groups/{{uuid}} \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Accept: application/json'

Respostas automáticas

GET /api/canned-replies Obter a lista de respostas automáticas
# Parâmetros opcionais: ?page=1&per_page=10 (per_page no máximo 100).
# Cada resposta: uuid, name, trigger, match_criteria, response_type, response (o texto, ou null para multimédia), file (name, url) ou null, created_at, updated_at.

curl -X GET \
"https://whapier.com/api/canned-replies?page=1&per_page=10" \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Accept: application/json'
POST /api/canned-replies Adicionar resposta automática
# Corpo: name e trigger (máx. 255), match_criteria (exact match | contains), response_type (text | image | audio), response.
# Para text, response é a resposta (máx. 4096). Para image ou audio envie multipart/form-data com o ficheiro como response (png/jpg até 5 MB; mp3/aac/ogg/amr/opus/m4a até 16 MB); sem ficheiro, o pedido é um 400.
# Resposta: { statusCode, id, message }. 403 quando o limite de respostas automáticas do plano é atingido. Aceita um cabeçalho Idempotency-Key.

curl -X POST \
https://whapier.com/api/canned-replies \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
    "name": "About Us",
    "trigger": "what do you do?",
    "match_criteria": "contains",
    "response_type": "text",
    "response": "We sell shoes"
}'
PUT /api/canned-replies/{uuid} Editar resposta automática
# Os mesmos campos de Adicionar resposta automática. Uma atualização sem ficheiro mantém o conteúdo multimédia já existente. 404 para um uuid desconhecido.

curl -X PUT \
https://whapier.com/api/canned-replies/{{uuid}} \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
    "name": "About Us",
    "trigger": "what do you do?",
    "match_criteria": "contains",
    "response_type": "text",
    "response": "We sell shoes and clothes"
}'
DELETE /api/canned-replies/{uuid} Eliminar resposta automática
# 404 para um uuid desconhecido. Resposta: { statusCode, id, message }.

curl -X DELETE \
https://whapier.com/api/canned-replies/{{uuid}} \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Accept: application/json'

Linhas de WhatsApp

GET /api/whatsapp-connections Listar ligações
# Devolve o uuid de cada linha (use-o como whatsapp_connection em /api/send). Sem ids internos da base de dados.
# Cada linha: uuid, type, name, phone, display_phone_number e, para uma linha WhatsApp Business, verified_name e number_status. 403 quando não há nenhuma linha ligada.

curl -X GET \
https://whapier.com/api/whatsapp-connections \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Accept: application/json'

Mensagens

POST /api/send Enviar mensagem
# Opcional: whatsapp_connection (UUID obtido em GET /api/whatsapp-connections). Omita-o para usar a linha predefinida da organização.
# phone (obrigatório) — em qualquer formato; normalizado para E.164 com o país da organização. Um número novo passa a ser um contacto (first_name, last_name, email opcionais).
# message (obrigatório, máx. 4096); header e footer (opcionais, máx. 60); buttons (opcional, até 3 de { id, title }).
# As mensagens de texto livre precisam de uma janela de 24 horas aberta: 422 quando a última mensagem do cliente tem mais de um dia. 403: subscrição, limite do plano, quota diária do período de teste ou conta em análise.
# Resposta: 200 { statusCode, data: { success, data: { chat: { uuid, wam_id, status, type, created_at, contact } } } }. Uma recusa do WhatsApp é um 200 com data.success false e data.data.error em /api; um HTTP 422 em /api/v2.
# Aceita um cabeçalho Idempotency-Key.

curl -X POST \
https://whapier.com/api/send \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
    "phone": "+40721000001",
    "message": "Hello Ana, how are you?",
    "whatsapp_connection": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
    "header": "Example Shoes",
    "footer": "Reply STOP to opt out",
    "buttons": [
        {
            "id": "yes",
            "title": "Fine"
        },
        {
            "id": "no",
            "title": "Not well"
        }
    ]
}'
POST /api/send/media Enviar multimédia
# Opcional: whatsapp_connection (UUID obtido em GET /api/whatsapp-connections). Omita-o para usar a linha predefinida da organização.
# media_type (image | video | audio | document | sticker); media_url (https, num anfitrião público; verificado com um pedido HEAD contra os limites de tamanho e de tipo do WhatsApp - caso contrário, 400 com o motivo); caption (opcional, não para audio); file_name (obrigatório para document).
# As mesmas proteções e a mesma resposta de Enviar mensagem.

curl -X POST \
https://whapier.com/api/send/media \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
    "phone": "+40721000001",
    "media_type": "image",
    "media_url": "https://cdn.example.com/offers/october.jpg",
    "caption": "Our October offers"
}'
POST /api/send/template Enviar mensagem de modelo
# Opcional: "whatsapp_connection": "<uuid>" para uma linha WABA específica (UUID obtido em GET /api/whatsapp-connections).
# template.name e template.language ("en" ou { "code": "en" }) são obrigatórios; components seguem a estrutura do próprio WhatsApp (header, body, parâmetros dos botões).
# Funciona fora da janela de 24 horas. A um contacto que fez opt-out (STOP) não é enviado um modelo MARKETING: 422. Os modelos de utilidade e de autenticação continuam a ser enviados.
# As mesmas proteções e a mesma resposta de Enviar mensagem.

curl -X POST \
https://whapier.com/api/send/template \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
    "phone": "+40721000001",
    "template": {
        "name": "order_update",
        "language": {
            "code": "en"
        },
        "components": [
            {
                "type": "header",
                "parameters": [
                    {
                        "type": "text",
                        "text": "48213"
                    }
                ]
            },
            {
                "type": "body",
                "parameters": [
                    {
                        "type": "text",
                        "text": "Ana"
                    },
                    {
                        "type": "text",
                        "text": "48213"
                    },
                    {
                        "type": "date_time",
                        "date_time": {
                            "fallback_value": "October 7, 2026"
                        }
                    }
                ]
            },
            {
                "type": "button",
                "sub_type": "url",
                "index": "0",
                "parameters": [
                    {
                        "type": "text",
                        "text": "48213"
                    }
                ]
            }
        ]
    }
}'
POST /api/send/location Enviar localização
# latitude (-90 a 90) e longitude (-180 a 180) obrigatórios; name e address opcionais.
# As mesmas proteções e a mesma resposta de Enviar mensagem.

curl -X POST \
https://whapier.com/api/send/location \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
    "phone": "+40721000001",
    "latitude": 46.77120000000000032969182939268648624420166015625,
    "longitude": 23.623599999999999710098563809879124164581298828125,
    "name": "Example Shoes",
    "address": "Str. Memorandumului 12, Cluj-Napoca"
}'
POST /api/send/contacts Enviar cartões de contacto
# contacts (1 a 10 cartões) no formato contacts[] do WhatsApp: name.formatted_name obrigatório; phones[], emails[], addresses[], org opcionais.
# As mesmas proteções e a mesma resposta de Enviar mensagem.

curl -X POST \
https://whapier.com/api/send/contacts \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
    "phone": "+40721000001",
    "contacts": [
        {
            "name": {
                "formatted_name": "Example Shoes Support",
                "first_name": "Support"
            },
            "phones": [
                {
                    "phone": "+40700000000",
                    "type": "WORK"
                }
            ],
            "emails": [
                {
                    "email": "support@example.com",
                    "type": "WORK"
                }
            ]
        }
    ]
}'
POST /api/send/reaction Enviar reação
# message_id (o wam_id da mensagem a que se reage) e emoji (obrigatório; "" remove a reação).
# As mesmas proteções e a mesma resposta de Enviar mensagem.

curl -X POST \
https://whapier.com/api/send/reaction \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
    "phone": "+40721000001",
    "message_id": "wamid.HBgMNDA3MjEwMDAwMDEVAgARGBI5QkY2RkE3RDlCMjc2RjI2QkEA",
    "emoji": "👍"
}'
POST /api/send/location-request Pedir localização
# message (obrigatório, máx. 1024): o texto mostrado por cima do botão "Enviar localização".
# As mesmas proteções e a mesma resposta de Enviar mensagem.

curl -X POST \
https://whapier.com/api/send/location-request \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
    "phone": "+40721000001",
    "message": "Where should we deliver?"
}'
POST /api/send/request-contact-info Pedir dados de contacto
# message (obrigatório, máx. 1024): pede a um utilizador do WhatsApp identificado apenas por nome de utilizador que partilhe o seu número de telefone.
# As mesmas proteções e a mesma resposta de Enviar mensagem.

curl -X POST \
https://whapier.com/api/send/request-contact-info \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
    "phone": "+40721000001",
    "message": "Could you share your number so we can call you back?"
}'
POST /api/send/carousel Enviar carrossel
# message (obrigatório, máx. 1024) e cards (2 a 10): header { type: image | video, link } obrigatório; body (máx. 160), url_button { text, url } e quick_replies (até 3 de { id, title }) opcionais.
# As mesmas proteções e a mesma resposta de Enviar mensagem.

curl -X POST \
https://whapier.com/api/send/carousel \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
    "phone": "+40721000001",
    "message": "Our new arrivals",
    "cards": [
        {
            "header": {
                "type": "image",
                "link": "https://cdn.example.com/shoes/1.jpg"
            },
            "body": "Runner, 89 EUR",
            "url_button": {
                "text": "See it",
                "url": "https://example.com/shoes/1"
            }
        },
        {
            "header": {
                "type": "image",
                "link": "https://cdn.example.com/shoes/2.jpg"
            },
            "body": "Trail, 119 EUR",
            "quick_replies": [
                {
                    "id": "trail",
                    "title": "Tell me more"
                }
            ]
        }
    ]
}'

Fluxos

POST /api/flows/{uuid}/start Iniciar um fluxo
# contact (obrigatório): o uuid ou o phone do contacto (normalizado com o país da organização).
# 200 { statusCode, success: true, message }; 404 fluxo ou contacto desconhecido; 422 fluxo não publicado; 409 o contacto já está numa sessão de fluxo.
# Tudo o que o fluxo envia está sujeito à janela de 24 horas, salvo se usar nós de modelo.

curl -X POST \
https://whapier.com/api/flows/{{uuid}}/start \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
    "contact": "+40721000001"
}'

Campanhas

GET /api/campaigns Listar campanhas
# Opcional: ?page=1&per_page=10&search=
# Cada campanha: uuid, name, status, scheduled_at, created_at, template (uuid, name, language, category, status), whatsapp_connection (uuid, name, type), audience (type: all | group | segment, uuid, name), counts (contacts, sent, delivered, read, failed).

curl -X GET \
"https://whapier.com/api/campaigns?page=1&per_page=10" \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Accept: application/json'
POST /api/campaigns Criar campanha (modelo WABA com variáveis)
# Use quando whatsapp_connection for uma linha WhatsApp Cloud (WABA) obtida em GET /api/whatsapp-connections.
#
# PRÉ-REQUISITOS
# - template: UUID de um registo de GET /api/templates (no âmbito da organização), NÃO a string com o nome público do modelo.
# - Faça corresponder o número de variáveis ao seu modelo aprovado: abra os metadados do modelo na interface ou na Meta — o BODY usa {{1}}, {{2}}, … por ordem.
# - Tem de fornecer um parâmetro de body para cada marcador do BODY, pela mesma ordem. Um número que não corresponda ao modelo aprovado é recusado à partida (422), e não pelo WhatsApp a seguir.
#
# NOTAS SOBRE OS CAMPOS
# - contacts: "all" ou o uuid de um grupo de contactos; ou segment: o uuid de um segmento guardado (um dos dois, não ambos). send_immediately: true, ou scheduled_at (uma data, lida como UTC).
# - header: objeto opcional; se for omitido equivale a { "format": "TEXT", "parameters": [] }.
# - body: use body.parameters[] para as variáveis. Formato API (recomendado): { "type": "text", "value": "literal for {{1}}" } por posição.
#   Alternativa (estilo painel): { "selection": "static", "value": "..." } ou { "selection": "dynamic", "value": "first name" } (associa campos do contacto).
# - footer / buttons: opcionais; use [] ou {} se não forem usados. Os modelos com variáveis de URL/resposta rápida precisam de buttons[] com a mesma forma do formulário de campanha da aplicação web.
# - Cabeçalho multimédia (IMAGE|VIDEO|DOCUMENT): header.parameters[] com type (IMAGE|VIDEO|DOCUMENT), "selection": "link", "value": "https://..." (URL público; a API não consegue carregar ficheiros).
#
# RESPOSTA: 200 { "statusCode": 200, "uuid": "...", "message": "..." }. Consulte GET /api/campaigns/{uuid} para o relatório e GET /api/campaigns/{uuid}/logs para o estado por destinatário, ou subscreva o webhook campaign.finished.
# 403 quando o limite de campanhas do plano é atingido. Aceita um cabeçalho Idempotency-Key.

curl -X POST \
https://whapier.com/api/campaigns \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
    "name": "Billing reminder blast",
    "whatsapp_connection": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
    "contacts": "all",
    "send_immediately": true,
    "template": "281a3383-985c-4084-bcb0-9ec523c952de",
    "header": {
        "format": "TEXT",
        "parameters": []
    },
    "body": {
        "parameters": [
            {
                "type": "text",
                "value": "Ana"
            },
            {
                "type": "text",
                "value": "48213"
            },
            {
                "type": "text",
                "value": "7 October 2026"
            }
        ]
    },
    "footer": {},
    "buttons": []
}'
GET /api/campaigns/{uuid} Obter uma campanha com o seu relatório
# O objeto campanha de Listar campanhas mais report: counts (contacts, sent, delivered, read, failed, pending), failure_reasons (code, title, count - os dez mais frequentes), started_at, finished_at (null até a campanha terminar), paused_reason, paused_detail e paused_at (null a menos que o estado seja paused).
# paused_reason é user (pausada a partir do painel ou da API), admin, failing, failure_rate ou quality (pausada pela plataforma; paused_detail diz porquê). 404 para uma campanha desconhecida.

curl -X GET \
https://whapier.com/api/campaigns/{{uuid}} \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Accept: application/json'
POST /api/campaigns/{uuid}/pause Pausar uma campanha
# Sem corpo. Só uma campanha scheduled ou ongoing pode ser pausada: 409 caso contrário, com o estado em que a campanha está. Os registos ficam como estão e retomar volta a pegar neles.
# Resposta: { statusCode, status, message } - status é o novo estado da campanha. 404 para uma campanha desconhecida.

curl -X POST \
https://whapier.com/api/campaigns/{{uuid}}/pause \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{}'
POST /api/campaigns/{uuid}/resume Retomar uma campanha
# Sem corpo. Só uma campanha paused pode ser retomada: 409 caso contrário. Uma campanha pausada antes da sua hora volta a scheduled; uma pausada durante o envio volta a ongoing.
# Resposta: { statusCode, status, message }. 404 para uma campanha desconhecida.

curl -X POST \
https://whapier.com/api/campaigns/{{uuid}}/resume \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{}'
POST /api/campaigns/{uuid}/cancel Cancelar uma campanha
# Sem corpo. Uma campanha scheduled, ongoing ou paused pode ser cancelada: 409 caso contrário. O que não foi enviado fica por enviar; o relatório continua a mostrar quem foi alcançado.
# Resposta: { statusCode, status, message }. 404 para uma campanha desconhecida.

curl -X POST \
https://whapier.com/api/campaigns/{{uuid}}/cancel \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{}'
GET /api/campaigns/{uuid}/logs Registos da campanha
# Opcional: ?page=1&per_page=10&search= (pesquisa por nome/telefone do contacto).
# Cada linha: contact (uuid, phone, first_name, last_name), status, message (uuid, wam_id, status) ou null, error (code, title, reason) ou null, retry_count, created_at, updated_at. 404 para uma campanha desconhecida.

curl -X GET \
"https://whapier.com/api/campaigns/{{uuid}}/logs?page=1&per_page=10" \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Accept: application/json'

Modelos

GET /api/templates Listar modelos
# Parâmetros opcionais: ?page=1&per_page=10 (per_page no máximo 100).
# Cada modelo: uuid, name, language, category, status, components (tal como o WhatsApp os aprovou), variables (header, body, buttons: quantos marcadores cada parte recebe), rejection (o motivo da rejeição, ou null), quality_score, updated_at.

curl -X GET \
"https://whapier.com/api/templates?page=1&per_page=10" \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Accept: application/json'
GET /api/templates/{uuid} Obter um modelo com um exemplo pronto a enviar
# O objeto modelo de Listar modelos mais example_payload: um corpo completo para POST /api/send/template com um parâmetro por marcador (os exemplos com que o modelo foi submetido, ou um valor que nomeia a posição), uma ligação para um cabeçalho multimédia e um sufixo para cada botão URL com variável.
# Parâmetro opcional: whatsapp_connection (o uuid de uma linha) quando o mesmo modelo existe em várias linhas. 404 para um uuid desconhecido.

curl -X GET \
https://whapier.com/api/templates/{{uuid}} \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Accept: application/json'
POST /api/templates Criar modelo
# name (letras minúsculas, dígitos e underscores), category (MARKETING | UTILITY) e language (um código de idioma da Meta como en ou pt_BR) são obrigatórios; whatsapp_connection (o uuid de uma linha WhatsApp Business) é opcional - caso contrário, a linha predefinida.
# header (opcional): { format: TEXT, text (máx. 60, um único {{1}} permitido), examples } ou { format: IMAGE | VIDEO | DOCUMENT, media_url: uma ligação https pública para um ficheiro de exemplo }.
# body.text (obrigatório, máx. 1024, marcadores {{1}}, {{2}}, ...) com body.examples, um por marcador; footer (opcional, máx. 60); buttons (opcional, até 10): { type: QUICK_REPLY | URL | PHONE_NUMBER | COPY_CODE, text, url, phone_number, example }.
# Resposta: 200 { statusCode, uuid, status, message } - status é PENDING até a Meta o rever (o webhook template.status.update avisa). 400 com o motivo da Meta quando a Meta o recusa; os modelos AUTHENTICATION ainda não podem ser submetidos pela API. Uma chave sandbox não pode submeter (403). Aceita um cabeçalho Idempotency-Key.

curl -X POST \
https://whapier.com/api/templates \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
    "name": "order_update",
    "category": "UTILITY",
    "language": "en",
    "header": {
        "format": "TEXT",
        "text": "Order {{1}}",
        "examples": [
            "48213"
        ]
    },
    "body": {
        "text": "Hi {{1}}, your order {{2}} ships on {{3}}.",
        "examples": [
            "Ana",
            "48213",
            "October 7"
        ]
    },
    "footer": "Example Shoes",
    "buttons": [
        {
            "type": "URL",
            "text": "Track",
            "url": "https://example.com/track/{{1}}",
            "example": "48213"
        },
        {
            "type": "QUICK_REPLY",
            "text": "Stop updates"
        }
    ]
}'
POST /api/templates/sync Sincronizar modelos a partir da Meta
# Sem corpo. Obtém da Meta os modelos de cada linha WhatsApp Business, como faz a atualização do painel, para que um modelo alterado no Meta Business Manager apareça também aqui.
# Resposta: { statusCode, synced, message } - synced é o número de modelos adicionados ou alterados. Uma chave sandbox não pode sincronizar (403); 400 quando a Meta recusou o pedido.

curl -X POST \
https://whapier.com/api/templates/sync \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{}'

Webhooks

GET /api/webhooks Listar webhooks
# Cada linha: uuid, url, events, secret_preview (os últimos seis caracteres do segredo de assinatura), created_at, updated_at. O segredo completo é mostrado uma só vez, na resposta de Adicionar webhook.
# 403 quando o módulo Webhooks não está incluído no plano.

curl -X GET \
https://whapier.com/api/webhooks \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Accept: application/json'
GET /api/webhooks/events Listar eventos
# Cada evento que um webhook pode receber: data (name, description). A página Webhooks do painel lê o mesmo catálogo.
# Uma entrega é { event, data }; a forma de data por evento está em Antes de começar > Webhooks, e POST /api/webhooks/{uuid}/test entrega um exemplo de qualquer um deles.

curl -X GET \
https://whapier.com/api/webhooks/events \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Accept: application/json'
POST /api/webhooks Adicionar webhook
# url (obrigatório, https, único por organização) e events (obrigatório, um ou mais nomes de GET /api/webhooks/events).
# Resposta: { statusCode, uuid, secret, message } - a única vez em que o segredo completo é devolvido; guarde-o para verificar X-Whapier-Signature. Aceita um cabeçalho Idempotency-Key.

curl -X POST \
https://whapier.com/api/webhooks \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
    "url": "https://example.com/hooks/whapier",
    "events": [
        "message.received",
        "message.status",
        "campaign.finished"
    ]
}'
PUT /api/webhooks/{uuid} Editar webhook
# Mesmo corpo que Adicionar webhook. A lista events substitui a guardada; o segredo mantém-se. 404 para um uuid desconhecido.

curl -X PUT \
https://whapier.com/api/webhooks/{{uuid}} \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
    "url": "https://example.com/hooks/whapier",
    "events": [
        "message.received",
        "message.status"
    ]
}'
DELETE /api/webhooks/{uuid} Eliminar webhook
# Remove o endpoint e as suas subscrições; nada mais lhe é entregue. Resposta: { statusCode, uuid, message }. 404 para um uuid desconhecido.

curl -X DELETE \
https://whapier.com/api/webhooks/{{uuid}} \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Accept: application/json'
POST /api/webhooks/{uuid}/test Enviar um evento de teste
# event (obrigatório): um nome de GET /api/webhooks/events. O payload de exemplo é enviado por POST para o url como { event, data, test: true }, assinado com o segredo em X-Whapier-Signature.
# Resposta: { statusCode, event, delivered, http_status, message } - delivered é false com o estado com que o seu endpoint respondeu, ou http_status null quando não foi possível contactá-lo. 404 para um uuid desconhecido.

curl -X POST \
https://whapier.com/api/webhooks/{{uuid}}/test \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
    "event": "message.status"
}'

Estado das mensagens

GET /api/messages Listar mensagens
# Parâmetros opcionais: status (sent | delivered | read | failed | accepted | played), direction (inbound | outbound), since e until (datas, UTC), contact (o uuid de um contacto), campaign (o uuid de uma campanha: as mensagens que produziu), wam_id (uma mensagem pelo id WhatsApp), api_key (o uuid de uma chave, ou current: as mensagens enviadas com a chave que faz o pedido), page, per_page (predefinição 25, máx. 100).
# Resposta: { statusCode, data: [ message ], meta: { page, per_page, total, last_page } }. 404 quando contact, campaign ou api_key é desconhecido.
# Uma mensagem: uuid, wam_id, direction, status, type, content, created_at, delivered_at, read_at, failed_at, failure (code, title, reason, retryable) ou null, pricing (category, model, billable, amount, currency, country), api_key (uuid, name) ou null quando não foi enviada pela API, contact (uuid, phone, first_name, last_name).
# content por type - text: body, header, footer, buttons (type, text); template: name, language, body; image, video, audio, document, sticker: caption, media (type, url, filename); interactive e button: text, payload (o que o cliente carregou); location: latitude, longitude, name, address; contacts: contacts (name, phones); reaction: emoji, wam_id.

curl -X GET \
"https://whapier.com/api/messages?status=failed&per_page=25" \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Accept: application/json'
GET /api/contacts/{uuid}/messages Conversa com um contacto
# Os mesmos objetos mensagem de Listar mensagens, para um só contacto, do mais recente para o mais antigo. Parâmetros opcionais: per_page (predefinição 25, máx. 100), before (o uuid da mensagem mais antiga que já tem).
# Resposta: { statusCode, data: [ message ], meta: { per_page, has_more, next_before } } - passe next_before como before para obter as mensagens mais antigas. 404 para um contacto ou um cursor desconhecido.

curl -X GET \
"https://whapier.com/api/contacts/{{uuid}}/messages?per_page=25" \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Accept: application/json'
GET /api/messages/{uuid} Obter uma mensagem
# O mesmo objeto de mensagem mais history: uma lista de { status, timestamp, recorded_at }, com cada mudança de estado comunicada pelo WhatsApp. 404 para um uuid desconhecido.

curl -X GET \
https://whapier.com/api/messages/{{uuid}} \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Accept: application/json'

Utilização

GET /api/usage Plano e utilização
# Dados da resposta: plan (name, status, valid_until), limits (contacts, messages, campaigns: used, limit; limit null = ilimitado), trial_daily_messages (apenas contas em período de teste), messages_sent (today, last_7_days, last_30_days), estimated_cost (last_30_days: amount, currency), rate_limit (per_minute).

curl -X GET \
https://whapier.com/api/usage \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Accept: application/json'

Caixa de entrada

GET /api/conversations/{contact_uuid} Obter uma conversa
# Resposta data: contact (uuid, phone, first_name, last_name), ticketing (se Definições > Tickets está ligado), ticket (status, assigned_to: name, email; opened_at, waiting_since, resolved_at) ou null, messages (uuid, wam_id, direction, type, text, status, created_at - as 50 mais recentes, primeiro a mais nova), next_before.
# Parâmetro opcional: before (o uuid da mensagem mais antiga que tem) para as mensagens anteriores; 400 quando o cursor não é uma mensagem deste contacto. 404 para um contacto desconhecido.

curl -X GET \
https://whapier.com/api/conversations/{{uuid}} \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Accept: application/json'
POST /api/conversations/{contact_uuid}/assign Atribuir uma conversa
# user_email (obrigatório, pode ser null): o email de um membro ativo da organização; null retira a atribuição do ticket. Uma conversa sem ticket recebe um.
# Resposta: { statusCode, data: ticket, message } com o ticket tal como Obter uma conversa o mostra. 409 enquanto o ticketing está desligado; 422 quando nenhum membro ativo da organização tem esse email; 404 para um contacto desconhecido.

curl -X POST \
https://whapier.com/api/conversations/{{uuid}}/assign \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
    "user_email": "maria@example.com"
}'
POST /api/conversations/{contact_uuid}/close Fechar uma conversa
# Sem corpo. Resolve o ticket (status closed, resolved_at definido), como o botão da caixa de entrada. Resposta: { statusCode, data: ticket, message }.
# 409 enquanto o ticketing está desligado; 404 para um contacto desconhecido.

curl -X POST \
https://whapier.com/api/conversations/{{uuid}}/close \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{}'
POST /api/conversations/{contact_uuid}/reopen Reabrir uma conversa
# Sem corpo. Reabre um ticket fechado (status open, resolved_at limpo); um ticket aberto é devolvido tal como está. Resposta: { statusCode, data: ticket, message }.
# 409 enquanto o ticketing está desligado; 404 para um contacto desconhecido.

curl -X POST \
https://whapier.com/api/conversations/{{uuid}}/reopen \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{}'
POST /api/conversations/{contact_uuid}/notes Adicionar uma nota interna
# note (obrigatório, máx. 5000): visível para os agentes na conversa, nunca enviada ao contacto. Funciona com o ticketing ligado ou desligado.
# Resposta: { statusCode, uuid, created_at, message }. 404 para um contacto desconhecido. Aceita um cabeçalho Idempotency-Key.

curl -X POST \
https://whapier.com/api/conversations/{{uuid}}/notes \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{
    "note": "Customer called; wants the order delivered on Friday."
}'

Obtenha uma chave de API em dois minutos

Teste gratuito, sem cartão de crédito — o painel de programador está incluído em todos os planos.

Testar gratuitamente