Introdução à API
O que dá para fazer com a API do Vamo, a URL base e a sua primeira requisição em menos de 2 minutos.
A API do Vamo liga o seu sistema ao WhatsApp da sua loja. Com ela você envia mensagens e modelos, mantém contatos em dia, acompanha conversas, registra pedidos que baixam o estoque e recebe avisos (webhooks) quando algo muda.
| Você quer… | Use |
|---|---|
| Responder um cliente que escreveu nas últimas 24 horas | POST /messages/send |
| Falar com quem não escreveu (confirmação de pedido, aviso de entrega) | POST /templates/send |
| Sincronizar clientes com o seu CRM | Contatos e importação em massa |
| Lançar uma venda feita no balcão ou no site e baixar o estoque | POST /orders |
| Saber quando uma mensagem foi entregue ou um pedido mudou | Webhooks |
URL base
Todas as rotas ficam em:
https://vamo.ai/api/v1A versão faz parte do caminho (/v1). Os exemplos desta seção mostram só o caminho depois da base, por exemplo GET /contacts é https://vamo.ai/api/v1/contacts.
Sua primeira requisição
Crie uma chave
No Vamo, abra Desenvolvedores → Chaves API e clique em Criar chave API. Dê um nome (por exemplo "Teste local"), escolha o tipo Secreta e o acesso Somente leitura. Copie a chave na hora: ela aparece uma única vez.
Só o proprietário, os administradores e os desenvolvedores da organização veem essa página.
Liste dois contatos
curl "https://vamo.ai/api/v1/contacts?pageSize=2" \
-H "Authorization: Bearer sk_live_SUA_CHAVE"Leia a resposta
{
"data": [
{
"id": "2c9d8e7f-6a5b-4c3d-9e2f-1a0b9c8d7e6f",
"storeId": "7b1e2c3d-4a5f-4b6c-8d7e-9f0a1b2c3d4e",
"name": "Mariana Costa",
"phone": "+5511987654321",
"waId": "5511987654321",
"status": "active",
"tags": ["vip"],
"lastInboundAt": "2026-10-30T14:02:11.000Z",
"createdAt": "2026-09-12T10:00:00.000Z",
"spent": [{ "currency": "BRL", "total": 468890 }]
}
],
"pagination": { "page": 1, "pageSize": 2, "total": 148 }
}Os dados vêm sempre em data. Listas trazem também pagination. Valores em dinheiro vêm em centavos: 468890 é R$ 4.688,90.
Recebeu 401? Confira se o cabeçalho é exatamente Authorization: Bearer <chave>. Os detalhes estão em Autenticação.
Convenções
| O quê | Como é |
|---|---|
| Formato | JSON na ida e na volta. Envie Content-Type: application/json nos POST e PATCH |
| IDs | UUID (2c9d8e7f-6a5b-…) |
| Datas | ISO 8601 em UTC (2026-10-30T14:02:11.000Z) |
| Dinheiro | Inteiro em centavos (×100), também para guaranis: Gs. 150.000 vai como 15000000 |
| Telefones | Formato internacional com + e código do país: +5511987654321 |
| Sucesso | 200 (leitura e alteração), 201 (criação ou envio), 202 (envio em massa aceito) |
| Erros | Sempre { "error": { "code": "…", "message": "…" } } (veja Erros) |
Campos desconhecidos no corpo são ignorados. Novos campos podem aparecer nas respostas: não quebre se encontrar um que você não conhece.
Paginação
As listas de contatos, conversas, mensagens de uma conversa, pedidos e modelos são paginadas pela query string:
| Parâmetro | Padrão | Regra |
|---|---|---|
page | 1 | Começa em 1 |
pageSize | 50 | Máximo 100: um valor maior vira 100 |
page ou pageSize que não são números inteiros positivos respondem 400 validation_error.
A resposta traz pagination.total, o total de itens com os filtros aplicados. Para percorrer tudo, avance page até page * pageSize >= total. As listas vêm do mais recente para o mais antigo (mensagens de uma conversa são a exceção: veja Conversas), e itens criados no mesmo instante saem sempre na mesma ordem, então uma página nunca repete nem pula um item da anterior. Um item criado enquanto você percorre as páginas empurra os outros uma posição: para uma cópia completa, percorra de novo ou use os webhooks.
Lojas, webhooks e o histórico de entregas de um webhook não são paginados.
Limites de requisição
Cada chave pode fazer um número de requisições por minuto, numa janela deslizante (os últimos 60 segundos), conforme o plano da organização:
| Plano | Requisições por minuto, por chave |
|---|---|
| Starter | 100 |
| Professional | 1.000 |
| Enterprise | 1.000 (ou o que estiver no contrato) |
Toda rota conta, inclusive as que falham. Um envio em massa conta como uma requisição. Cada chave tem a sua conta: duas chaves da mesma organização não dividem o limite.
Toda resposta traz:
| Cabeçalho | O que é |
|---|---|
X-RateLimit-Limit | O limite por minuto da chave |
X-RateLimit-Remaining | Quantas requisições ainda cabem agora |
X-RateLimit-Reset | Quando a janela tem espaço de novo, em segundos Unix |
Passou do limite: 429 com o código rate_limited, o cabeçalho Retry-After (em segundos) e retryAfterSec no corpo. Espere esse tempo e tente de novo.
{ "error": { "code": "rate_limited", "message": "Too many requests. Try again in 12 seconds.", "retryAfterSec": 12 } }O WhatsApp também tem limites próprios nos envios: quando a Meta segura os envios do seu número, o envio responde 429 com o código whatsapp_rate_limited e Retry-After. Veja Erros.
Idempotência
Uma falha de rede no meio de um envio deixa a dúvida: a mensagem saiu? Para repetir sem medo, mande o cabeçalho Idempotency-Key com um valor único por operação (até 200 caracteres; um UUID serve) nestas rotas:
POST /messages/sendePOST /templates/sendPOST /bulk/messagesePOST /bulk/contactsPOST /contactsePOST /webhooks
curl -X POST https://vamo.ai/api/v1/messages/send \
-H "Authorization: Bearer sk_live_SUA_CHAVE" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: pedido-1042-aviso-envio" \
-d '{ "contactId": "2c9d8e7f-6a5b-4c3d-9e2f-1a0b9c8d7e6f", "content": "Seu pedido saiu para entrega!" }'| Situação | O que acontece |
|---|---|
| Primeira requisição com a chave | Roda normalmente. Uma resposta de sucesso (2xx) fica guardada por 24 horas |
| Repetição com a mesma chave e o mesmo corpo | Nada é enviado nem criado de novo: volta a mesma resposta, com o cabeçalho Idempotent-Replayed: true |
| A mesma chave com outro corpo (ou outra rota) | 422 idempotency_key_reused |
| Repetição enquanto a primeira ainda roda | 409 idempotency_key_in_progress com Retry-After: 1 |
A primeira terminou em erro (4xx ou 5xx) | A chave é liberada: a repetição roda de novo |
A chave vale só dentro da sua organização e por 24 horas. POST /orders também aceita Idempotency-Key, com regras próprias.
Chamadas pelo navegador (CORS)
As rotas /v1 aceitam chamadas de qualquer origem (com a pré-verificação OPTIONS do navegador), então dá para chamá-las direto de uma página web. Os cabeçalhos X-RateLimit-* e Retry-After ficam visíveis para o seu JavaScript. As respostas vêm com Cache-Control: no-store: nenhum navegador ou cache guarda os dados. Faça isso só com uma chave publicável (pk_live_…), que lê apenas a loja e os modelos. Uma chave secreta no navegador fica visível para qualquer visitante.