Introdução
A API REST do WhatSMS permite enviar mensagens, gerir contactos, tickets e campanhas, e ouvir eventos em tempo real via webhooks. Todos os pedidos são autenticados por API Key e isolados por tenant.
Base URL
https://api.whatsms.pt/api/v2
CRUD completo, paginação estruturada, suporte a media e rate limiting por API Key.
API Key por tenant
Cada conta tem a sua API Key. Cria e revoga em Configurações → Integrações → API Keys.
HTTPS obrigatório
Todos os pedidos devem usar HTTPS. Pedidos HTTP são recusados automaticamente.
RGPD nativo
Os dados ficam em servidores europeus. Conformidade RGPD nativa, sem enviar dados para fora da UE.
Autenticação
Todos os pedidos requerem o header Authorization com a API Key no formato Bearer. Obtém a tua API Key em Configurações → Integrações → API Keys.
Header obrigatório
Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Exemplo cURL
curl -X GET https://api.whatsms.pt/api/v2/contacts \ -H "Authorization: Bearer sk_live_xxxxxxxxxxxx" \ -H "Content-Type: application/json"
⚠️ Segurança
Nunca exponhas a API Key em código client-side ou repositórios públicos. Usa variáveis de ambiente no servidor. Se uma key for comprometida, revoga-a imediatamente em Configurações → Integrações → API Keys.
Erros
A API usa códigos HTTP standard. O corpo de erro segue sempre esta estrutura:
Formato de erro
{ "error": "Mensagem descritiva do erro" }| Código | Significado |
|---|---|
| 200 | Sucesso |
| 201 | Criado com sucesso |
| 400 | Pedido inválido — parâmetros em falta ou incorrectos |
| 401 | Não autenticado — API Key inválida ou em falta |
| 403 | Sem permissão para este recurso |
| 404 | Recurso não encontrado |
| 429 | Rate limit atingido — aguarda antes de repetir |
| 500 | Erro interno do servidor |
Tickets
Um ticket representa uma conversa com um contacto. Agrupa mensagens, canal, estado e agente responsável.
/api/v2/ticketsListar ticketsParâmetros
Filtrar por estado: open, pending, closed
Filtrar por contacto
Página (default: 1)
Resultados por página (default: 20, max: 100)
Resposta
{
"tickets": [
{
"id": "uuid",
"status": "open",
"channel": "whatsapp",
"contact": { "id": "uuid", "name": "João Silva", "number": "351910000000" },
"lastMessage": "Olá, preciso de ajuda",
"createdAt": "2026-01-15T10:30:00Z"
}
],
"count": 42,
"hasMore": true
}/api/v2/tickets/:ticketIdObter ticket por IDParâmetros
ID do ticket
Resposta
{
"ticket": {
"id": "uuid",
"status": "open",
"channel": "whatsapp",
"contact": { "id": "uuid", "name": "João Silva", "number": "351910000000" },
"user": { "id": "uuid", "name": "Agente" },
"queue": { "id": "uuid", "name": "Suporte" },
"createdAt": "2026-01-15T10:30:00Z",
"updatedAt": "2026-01-15T11:00:00Z"
}
}/api/v2/ticketsCriar ticketCorpo do pedido
{
"contactId": "uuid", // obrigatório
"status": "open", // open | pending | closed
"channel": "whatsapp", // whatsapp | sms | telegram
"whatsappId": "uuid", // canal WhatsApp a usar
"queueId": "uuid", // fila/departamento
"userId": "uuid" // agente responsável
}Resposta
{
"ticket": {
"id": "uuid",
"status": "open",
"channel": "whatsapp",
"createdAt": "2026-01-15T10:30:00Z"
}
}/api/v2/tickets/:ticketIdActualizar ticketParâmetros
ID do ticket
Corpo do pedido
{
"status": "closed", // open | pending | closed
"userId": "uuid", // reatribuir agente
"queueId": "uuid" // mover para fila
}Resposta
{
"ticket": { "id": "uuid", "status": "closed", "updatedAt": "2026-01-15T12:00:00Z" }
}Mensagens de um ticket
As mensagens estão aninhadas sob o ticket. Para enviar uma mensagem, usa POST /tickets/:id/messages.
/api/v2/tickets/:ticketId/messagesListar mensagens do ticketParâmetros
ID do ticket
Página (default: 1)
Resultados por página (default: 20)
Resposta
{
"messages": [
{
"id": "uuid",
"body": "Olá, preciso de ajuda",
"fromMe": false,
"mediaType": null,
"mediaUrl": null,
"ack": 3,
"createdAt": "2026-01-15T10:30:00Z"
}
],
"count": 15,
"hasMore": false
}/api/v2/tickets/:ticketId/messages60 req/min por API KeyEnviar mensagemParâmetros
ID do ticket
Corpo do pedido
{
"body": "Olá! Como posso ajudar?", // obrigatório (texto ou caption)
"mediaUrl": "https://...", // URL de imagem/documento/áudio
"mediaType": "image", // image | document | audio | video
"quotedMsgId": "uuid" // responder a mensagem específica
}Resposta
{
"message": {
"id": "uuid",
"body": "Olá! Como posso ajudar?",
"fromMe": true,
"ack": 1,
"createdAt": "2026-01-15T10:31:00Z"
}
}Contactos
Gestão completa de contactos. Um contacto pode ter vários tickets em vários canais.
/api/v2/contactsListar contactosParâmetros
Pesquisar por nome, número ou email
Página (default: 1)
Resultados por página (default: 20)
Resposta
{
"contacts": [
{
"id": "uuid",
"name": "João Silva",
"number": "351910000000",
"email": "joao@exemplo.pt",
"profilePicUrl": "https://...",
"isGroup": false,
"createdAt": "2026-01-10T09:00:00Z"
}
],
"count": 150,
"hasMore": true
}/api/v2/contacts/:contactIdObter contacto por IDParâmetros
ID do contacto
Resposta
{
"contact": {
"id": "uuid",
"name": "João Silva",
"number": "351910000000",
"email": "joao@exemplo.pt",
"extraInfo": [{ "name": "NIF", "value": "123456789" }],
"createdAt": "2026-01-10T09:00:00Z"
}
}/api/v2/contactsCriar contactoCorpo do pedido
{
"name": "João Silva", // obrigatório
"number": "351910000000", // obrigatório
"email": "joao@exemplo.pt",
"profilePicUrl": "https://...",
"extraInfo": [
{ "name": "NIF", "value": "123456789" }
]
}Resposta
{
"contact": {
"id": "uuid",
"name": "João Silva",
"number": "351910000000",
"createdAt": "2026-01-15T10:00:00Z"
}
}/api/v2/contacts/:contactIdActualizar contactoParâmetros
ID do contacto
Corpo do pedido
{
"name": "João M. Silva",
"email": "joao.novo@exemplo.pt",
"extraInfo": [{ "name": "Empresa", "value": "Acme Lda" }]
}Resposta
{
"contact": { "id": "uuid", "name": "João M. Silva", "updatedAt": "2026-01-15T11:00:00Z" }
}Campanhas
Envio em massa para grupos de contactos via WhatsApp ou SMS, com agendamento e controlo de estado.
/api/v2/campaignsListar campanhasParâmetros
pending | running | finished | cancelled
Página (default: 1)
Resposta
{
"campaigns": [
{
"id": "uuid",
"name": "Promoção Verão 2026",
"status": "finished",
"scheduledAt": "2026-06-01T09:00:00Z",
"sentCount": 342,
"failedCount": 3,
"createdAt": "2026-05-20T10:00:00Z"
}
],
"count": 8,
"hasMore": false
}/api/v2/campaignsCriar campanhaCorpo do pedido
{
"name": "Promoção Verão 2026", // obrigatório
"message": "Olá {{name}}! ...", // obrigatório (suporta {{name}}, {{number}})
"whatsappId": "uuid", // canal a usar
"contactGroupId": "uuid", // grupo de contactos alvo
"scheduledAt": "2026-06-01T09:00:00Z" // null = envio imediato
}Resposta
{
"campaign": {
"id": "uuid",
"name": "Promoção Verão 2026",
"status": "pending",
"createdAt": "2026-05-20T10:00:00Z"
}
}Agentes IA
Os agentes IA respondem automaticamente a tickets usando LLMs (Cortecs Sovereign Cloud — conformidade EU AI Act). Podem usar ferramentas como KiviCare, calendário, CRM e base de conhecimento.
/api/v2/ai-agentsListar agentes IASem parâmetros obrigatórios.
Resposta
{
"agents": [
{
"id": "uuid",
"name": "Maria — Assistente FamilyClinic",
"model": "cortecs:llama-4-maverick",
"isActive": true,
"enabledIntegrations": ["kivicare"],
"handoffEnabled": true,
"createdAt": "2026-03-01T10:00:00Z"
}
]
}/api/v2/ai-agents/assignAtribuir agente IA a um ticketCorpo do pedido
{
"ticketId": "uuid", // obrigatório
"agentId": "uuid" // obrigatório — null para remover agente
}Resposta
{
"ticket": { "id": "uuid", "aiAgentId": "uuid", "updatedAt": "2026-01-15T10:00:00Z" }
}Webhooks
Configura um endpoint HTTPS para receber eventos em tempo real. O WhatSMS faz um POST com payload JSON assinado com HMAC-SHA256.
Header de assinatura
X-WhatSMS-Signature: sha256=<hmac_hex>
Verifica a assinatura com o teu webhook secret para garantir que o pedido vem do WhatSMS.
Eventos disponíveis
| Evento | Descrição |
|---|---|
| message.received | Nova mensagem recebida de um contacto |
| message.sent | Mensagem enviada com sucesso |
| message.ack | Confirmação de entrega/leitura (ack 1–5) |
| ticket.created | Novo ticket criado |
| ticket.updated | Ticket actualizado (status, agente, fila) |
| ticket.closed | Ticket fechado |
| contact.created | Novo contacto criado |
| contact.updated | Contacto actualizado |
| campaign.finished | Campanha concluída |
Payload de exemplo — message.received
{
"event": "message.received",
"tenantId": "uuid",
"timestamp": "2026-01-15T10:30:00Z",
"data": {
"message": {
"id": "uuid",
"body": "Olá, preciso de ajuda",
"fromMe": false,
"mediaType": null,
"createdAt": "2026-01-15T10:30:00Z"
},
"ticket": { "id": "uuid", "status": "open" },
"contact": { "id": "uuid", "name": "João Silva", "number": "351910000000" }
}
}Rate Limits
Os limites são por API Key e por janela de 1 minuto. Quando atingires o limite recebes um 429 com o header Retry-After em segundos.
| Endpoint | Limite |
|---|---|
| Todos os endpoints v2 | 300 req/min por API Key |
| POST /tickets/:id/messages | 60 req/min por API Key |
| POST /campaigns | 10 req/min por API Key |
SDKs & Integrações
Integra o WhatSMS no teu stack com o node n8n oficial ou directamente via HTTP em qualquer linguagem.
Node n8n
Node nativo para n8n com trigger de webhooks e acções de envio de mensagens. Disponível no marketplace do n8n.
Em breveHTTP / REST
API REST padrão compatível com qualquer linguagem — JavaScript, Python, PHP, Go, etc. Usa o Swagger interactivo para explorar e testar todos os endpoints.
Abrir Swagger →Exemplo — enviar mensagem com fetch
const res = await fetch("https://api.whatsms.pt/api/v2/tickets/{ticketId}/messages", {
method: "POST",
headers: {
"Authorization": "Bearer sk_live_xxxxxxxxxxxx",
"Content-Type": "application/json"
},
body: JSON.stringify({ body: "Olá! Como posso ajudar?" })
});
const { message } = await res.json();
console.log(message.id);Documentação completa e testa todos os endpoints no Swagger interactivo.
⚡ Abrir Swagger