Saltar para o conteúdo

Enviar SMS por API em 10 minutos com Node.js

September 2, 2026 · 6 min de leitura · Atualizado em October 9, 2026

Para enviar um SMS a partir de Node.js, basta um único pedido POST para https://volai.cz/v1/messages com o cabeçalho Authorization: Bearer vk_... e um corpo JSON com {to, body}. O Node 20 traz o fetch de origem, por isso não precisa de instalar nenhum pacote. Um exemplo funcional segue logo abaixo, com tratamento de erros e idempotência, para que uma falha de rede não envie a mesma mensagem duas vezes.

O que vai precisar

  • Node.js 18 ou mais recente - o fetch está integrado desde esta versão; recomendamos a linha LTS atualmente suportada (24, à data de 2 de setembro de 2026).
  • Uma conta volai e uma chave de API do portal (Definições -> API e MCP), no formato vk_....
  • Pelo menos um carregamento de saldo. Os SMS só funcionam após o primeiro carregamento; o saldo de boas-vindas não os cobre - pode experimentar chamadas com ele, mensagens de texto não.
  • Um número de destinatário na Chéquia ou na Eslováquia (+420 ou +421) - não enviamos SMS para outros países.
  • NÃO precisa de um número de telefone próprio. As mensagens saem com o nome de remetente partilhado SMSinfo - os operadores só permitem nas redes checas nomes de remetente aprovados, pelo que no remetente partilhado não é possível definir um nome próprio, e o destinatário não pode responder a SMSinfo. Por isso, escreva a sua identidade diretamente no texto da mensagem, como no exemplo abaixo. Se quiser que seja possível responder, envie a partir do seu próprio número de telemóvel (um complemento, ver o aviso mais abaixo).

Envie o primeiro SMS

O pedido só precisa de dois campos: to (número do destinatário) e body (texto da mensagem). A resposta devolve o id da mensagem, o seu status, o preço em haléres (priceHal) e o número de segmentos (segments) - voltamos a ambos daqui a pouco.

javascript
const response = await fetch("https://volai.cz/v1/messages", {
  method: "POST",
  headers: {
    Authorization: "Bearer vk_A_SUA_CHAVE",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    to: "+420777123456",
    body: "Olá da volai! - A Minha App",
  }),
});

if (!response.ok) {
  const { error } = await response.json();
  throw new Error("volai " + error.code + ": " + error.message);
}

const message = await response.json();
console.log(message);
// { id: "msg_7c1f9a2e", status: "sent", priceHal: 136, segments: 1 }

Quanto custa um SMS e o que são segmentos?

Um SMS de um segmento custa 1.36 CZK sem IVA (preço à data de 2 de setembro de 2026). O número de segmentos que uma mensagem ocupa depende de conter caracteres fora do alfabeto GSM-7 - os operadores contam os SMS segundo a norma GSM 03.38:

CodificaçãoCaracteres no 1.º segmentoCaracteres nas partes seguintes
GSM-7 (caracteres padrão, incluindo é ç à)160153
UCS-2 (caracteres fora do GSM-7, como á ã õ ê)7067

Um único caractere fora do alfabeto de base GSM-7 (em português, por exemplo á í ó ú ã õ â ê ô, mas também aspas tipográficas, emojis e a maioria das escritas não latinas) faz passar a mensagem INTEIRA a UCS-2, mesmo que seja o único caractere desse tipo no texto. Já é, è, ù, ì, ò, ç e à pertencem ao GSM-7. Dica: para ficar com segurança num único segmento, use apenas caracteres GSM-7 simples, ou seja, sem acentos como o til ou o agudo.

Exemplo: uma mensagem com acentos com mais de 70 caracteres

Esta mensagem tem 111 caracteres e contém caracteres acentuados, pelo que é contada como UCS-2 (67 caracteres por segmento numa mensagem de várias partes) - resulta em 2 segmentos, ou seja, 2.72 CZK em vez de 1.36 CZK:

javascript
await fetch("https://volai.cz/v1/messages", {
  method: "POST",
  headers: {
    Authorization: "Bearer vk_A_SUA_CHAVE",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    to: "+420777123456",
    body: "Olá, lembramos que a sua consulta é amanhã às 10:00. Se não lhe convier, responda para marcarmos uma nova data.",
  }),
});
// -> { id: "msg_9a3f1c7d", status: "sent", priceHal: 272, segments: 2 }

Idempotência: repetir pedidos em segurança

Acrescente um cabeçalho Idempotency-Key com uma cadeia de caracteres à sua escolha, por exemplo o ID de uma encomenda. Se o pedido falhar por um erro de rede e o seu fluxo o repetir com o MESMO cabeçalho, a volai devolve a resposta guardada da primeira tentativa em vez de enviar a mensagem uma segunda vez - a chave é válida durante 24 horas.

bash
curl -X POST https://volai.cz/v1/messages \
  -H "Authorization: Bearer vk_A_SUA_CHAVE" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: encomenda-4471" \
  -d '{"to": "+420777123456", "body": "A sua encomenda n.º 4471 foi recebida."}'

Guarde a chave de API em segurança

Uma chave de API (vk_...) tem o mesmo peso que uma palavra-passe - quem a conhecer pode enviar mensagens em seu nome e gastar o saldo da sua conta. Por isso, nunca a escreva em código-fonte que vá submeter a um repositório. Pertence a uma variável de ambiente (process.env.VOLAI_API_KEY em Node.js) ou ao gestor de segredos do seu alojamento.

javascript
// .env.local (nunca faça commit para o repositório)
// VOLAI_API_KEY=vk_a_sua_chave

const response = await fetch("https://volai.cz/v1/messages", {
  method: "POST",
  headers: {
    Authorization: "Bearer " + process.env.VOLAI_API_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ to, body }),
});

Chame sempre o endpoint a partir de um servidor, nunca do navegador - qualquer pessoa poderia ler a chave nas ferramentas de programador do navegador e começar a enviar mensagens próprias a partir da sua conta. Se uma chave for divulgada (por exemplo, por um commit acidental), gere uma nova no portal e revogue a antiga - o valor antigo deixa de funcionar de imediato.

Experimente primeiro sem riscos

Antes de ligar o envio de SMS a um processo real (por exemplo, confirmações de encomenda), envie as primeiras mensagens para o seu próprio número de telefone. Verá exatamente o que o cliente vê - o aspeto do remetente SMSinfo, quanto demora a entrega e se a segmentação sai como espera. Só depois mude to para um número de cliente real.

O que fazer quando a API devolve um erro?

Uma resposta falhada tem sempre a forma {error: {code, message}} com um estado HTTP correspondente ao tipo de erro:

EstadoCódigoSignificado
400invalid_numberNão é um número de telefone checo ou eslovaco válido.
400invalid_bodyO texto da mensagem tem de ter entre 1 e 765 caracteres.
400unsupported_countryNúmero fora de CZ/SK, não enviamos SMS para lá.
400recipient_cannot_receive_smsNúmero fixo - o SMS não poderia chegar. Não é cobrado.
402insufficient_creditO saldo não cobre o preço de todos os segmentos da mensagem, ou a conta ainda não foi carregada - os SMS exigem um primeiro carregamento, o saldo de boas-vindas não os cobre.
429rate_limitedMais de 1 SMS por 2 segundos ou mais de 100 SMS por conta e por dia.
502send_failedA rede telefónica rejeitou o pedido. O saldo não foi debitado, tente de novo.
502send_unknownEntregámos a mensagem à rede, mas não recebemos confirmação - é cobrada, por favor não a reenvie às cegas.

Que estados pode ter uma mensagem?

O campo status assume cinco valores, tanto na lista (GET /v1/messages) como no detalhe de uma mensagem: pending (guardada, ainda a ser enviada), sent (o operador confirmou o envio), failed (rejeitada pelo operador - não é cobrada), unknown (a confirmação de entrega não chegou, tipicamente um tempo limite do operador - é ainda assim cobrada na totalidade, porque a mensagem pode ter chegado) e received (apenas nas mensagens recebidas, ou seja, com direction=in; as mensagens enviadas nunca o têm).

Cada mensagem tem ainda os campos direction (out nas enviadas, in nas recebidas), smsNumber (o número a partir do qual a mensagem foi enviada ou no qual foi recebida; nas mensagens enviadas com o nome partilhado SMSinfo é null) e deliveryStatus (delivered ou undelivered, um relatório de entrega do operador; só existe nos SMS enviados a partir de um número de telemóvel, em todas as outras mensagens é null).

Como envio muitos SMS de uma vez?

O limite de ritmo permite, no máximo, um SMS a cada dois segundos por conta e, no máximo, 100 SMS por dia. Ao enviar várias mensagens de uma vez (por exemplo, lembretes de consultas), uma pequena pausa entre os pedidos é mais simples do que tratar rate_limited e tentar de novo:

javascript
const message = "Lembrete: a sua consulta é amanhã - A Minha App";

for (const to of recipients) {
  const response = await fetch("https://volai.cz/v1/messages", {
    method: "POST",
    headers: {
      Authorization: "Bearer vk_A_SUA_CHAVE",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ to, body: message }),
  });

  if (!response.ok) {
    const { error } = await response.json();
    console.error("volai " + to + ": " + error.code);
  }

  // O limite é de, no máximo, 1 SMS por 2 segundos por conta - uma pequena
  // pausa entre pedidos é mais simples do que tratar rate_limited e
  // tentar de novo.
  await new Promise((resolve) => setTimeout(resolve, 2100));
}

Dois tipos de número recebem SMS

Os números de voz da volai não recebem SMS, por isso uma resposta a uma mensagem enviada com o nome partilhado SMSinfo não aparece em lado nenhum. Se quiser receber SMS e enviar a partir do seu próprio número, escolha o complemento número de telemóvel: um número móvel checo só para SMS, sem chamadas, 290 CZK por 30 dias sem IVA. Ou encomende o número para chamadas e SMS: um número fixo de Praga em que recebe chamadas e SMS, 49 CZK por 30 dias sem IVA (a taxa só é debitada após a ativação, que normalmente demora até 1 dia útil). Em ambos, os SMS recebidos estão incluídos no preço. Pode ler as mensagens recebidas através de GET /v1/messages?direction=in, da ferramenta MCP list_messages ou do webhook message.received, e guardamo-las durante 90 dias; o envio a partir de um número de telemóvel custa 1.90 CZK por segmento, a partir de um número para chamadas e SMS 2.50 CZK por segmento, e só é possível para números checos. Para enviar a partir de um número, use o campo fromNumber em POST /v1/messages (o número obtém-se em GET /v1/sms-numbers ou GET /v1/voice-sms-numbers). O limite diário de envio a partir de um número é de 20 SMS por conta nos primeiros 30 dias após a compra do número e de 50 depois disso. Cada conta pode ter, no máximo, dois números SMS, e só os pode comprar após o primeiro carregamento de saldo; o mesmo vale para os números para chamadas e SMS: no máximo dois por conta, que só se podem encomendar após o primeiro carregamento. Não garantimos códigos de verificação de serviços (bancos, Google e semelhantes), os números destinam-se à comunicação com pessoas, e a receção foi testada na rede da O2. Os pormenores estão nas secções Números SMS e Números para chamadas e SMS da documentação da API. Quando a Twilio é a melhor escolha para receber SMS, descreve-o a comparação entre a Twilio e a volai.

Em resumo: um único POST /v1/messages com os campos to e body envia o SMS, o cabeçalho Idempotency-Key protege um fluxo de envios duplicados quando os pedidos se repetem, e o preço é calculado por segmento, consoante o texto contenha ou não caracteres fora do GSM-7. Mantenha a chave fora do repositório e envie a primeira mensagem para si próprio.

Os passos seguintes

A referência completa da API REST (números, chamadas, webhooks, agentes) encontra-se em /docs/api. Quer saber de imediato quando a volai entrega uma mensagem ao operador, sem consultar GET /v1/messages? Subscreva o evento message.sent - confirma apenas a aceitação pelo operador, não a entrega no telefone (nas mensagens enviadas com o nome partilhado a volai não a vê, ver acima; as mensagens enviadas a partir do seu próprio número de telemóvel têm um relatório de entrega) - ver a documentação dos webhooks. E se, além de SMS, precisar de um número de telefone que atenda chamadas por si, veja a rececionista com IA.

Experimente a volai - os primeiros 50 kr são nossos

Registe-se em um minuto e a sua conta já tem saldo inicial para chamadas e um número - os SMS funcionam depois do primeiro carregamento.

Experimentar gratuitamente