WhatSMS/API Docs
Swagger →Começar grátis
IntroduçãoAutenticaçãoErrosTickets↳ MensagensContactosCampanhasAgentes IAWebhooksRate LimitsSDKs & n8n
⚡ Swagger interactivo

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.

v2

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ódigoSignificado
200Sucesso
201Criado com sucesso
400Pedido inválido — parâmetros em falta ou incorrectos
401Não autenticado — API Key inválida ou em falta
403Sem permissão para este recurso
404Recurso não encontrado
429Rate limit atingido — aguarda antes de repetir
500Erro interno do servidor

Tickets

Um ticket representa uma conversa com um contacto. Agrupa mensagens, canal, estado e agente responsável.

GET/api/v2/ticketsListar tickets

Parâmetros

status·string

Filtrar por estado: open, pending, closed

contactId·uuid

Filtrar por contacto

pageNumber·integer

Página (default: 1)

pageSize·integer

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
}
GET/api/v2/tickets/:ticketIdObter ticket por ID

Parâmetros

ticketId·uuidobrigatório

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"
  }
}
POST/api/v2/ticketsCriar ticket

Corpo 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"
  }
}
PUT/api/v2/tickets/:ticketIdActualizar ticket

Parâmetros

ticketId·uuidobrigatório

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.

GET/api/v2/tickets/:ticketId/messagesListar mensagens do ticket

Parâmetros

ticketId·uuidobrigatório

ID do ticket

pageNumber·integer

Página (default: 1)

pageSize·integer

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
}
POST/api/v2/tickets/:ticketId/messages60 req/min por API KeyEnviar mensagem

Parâmetros

ticketId·uuidobrigatório

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.

GET/api/v2/contactsListar contactos

Parâmetros

searchParam·string

Pesquisar por nome, número ou email

pageNumber·integer

Página (default: 1)

pageSize·integer

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
}
GET/api/v2/contacts/:contactIdObter contacto por ID

Parâmetros

contactId·uuidobrigatório

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"
  }
}
POST/api/v2/contactsCriar contacto

Corpo 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"
  }
}
PUT/api/v2/contacts/:contactIdActualizar contacto

Parâmetros

contactId·uuidobrigatório

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.

⚠️ As campanhas estão sujeitas às políticas de uso aceitável do WhatsApp Business. O envio em massa não autorizado pode resultar no bloqueio do número.
GET/api/v2/campaignsListar campanhas

Parâmetros

status·string

pending | running | finished | cancelled

pageNumber·integer

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
}
POST/api/v2/campaignsCriar campanha

Corpo 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.

GET/api/v2/ai-agentsListar agentes IA

Sem 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"
    }
  ]
}
POST/api/v2/ai-agents/assignAtribuir agente IA a um ticket

Corpo 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

EventoDescrição
message.receivedNova mensagem recebida de um contacto
message.sentMensagem enviada com sucesso
message.ackConfirmação de entrega/leitura (ack 1–5)
ticket.createdNovo ticket criado
ticket.updatedTicket actualizado (status, agente, fila)
ticket.closedTicket fechado
contact.createdNovo contacto criado
contact.updatedContacto actualizado
campaign.finishedCampanha 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.

EndpointLimite
Todos os endpoints v2300 req/min por API Key
POST /tickets/:id/messages60 req/min por API Key
POST /campaigns10 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 breve
🔌

HTTP / 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