Enviar uma mensagem pelo smartphone manualmente é simples. Já integrar esse envio a um sistema exige alguns cuidados: autenticação, formato do payload, endpoint correto, identificação do destinatário, hospedagem de arquivos, acompanhamento de status e tratamento de falhas.

Com a API do Z-API, sua aplicação pode enviar textos, áudios e documentos para contatos ou grupos por meio de requisições HTTP. 

A documentação apresenta endpoints RESTful específicos para cada tipo de conteúdo, com autenticação por Client-Token e parâmetros de instância e token na URL.

Neste tutorial, você verá como realizar os primeiros envios usando cURL e JavaScript com fetch, seguindo a estrutura apresentada na documentação utilizada como base para este conteúdo. Como APIs podem receber atualizações, confirme os campos e parâmetros no endpoint correspondente antes de colocar a integração em produção.

  1. A seguir, você vai ver como:
  2. Preparar uma instância do Z-API;
  3. Montar a URL base da requisição;
  4. Autenticar chamadas com Client-Token;
  5. Enviar texto simples;
  6. Enviar áudio por link ou Base64;
  7. Enviar PDF por link ou Base64;
  8. Interpretar respostas com zaapId, messageId e id;
  9. Acompanhar processamento, entrega e leitura;
  10. Diagnosticar erros comuns;
  11. Estruturar o envio com mais segurança para produção.

Importante: os exemplos usam placeholders como {instanceId}, {token}, <api-key> e 5511999999999. Substitua esses valores pelas credenciais e pelo telefone de teste da sua própria instância.

Como enviar textos, áudios e PDFs pela API?

O envio de uma mensagem passa por algumas etapas:

Sua aplicação

     ↓ POST autenticado

API do Z-API

     ↓ retorna IDs

Fila da instância

     ↓

App de mensagens

     ↓ webhooks

Processamento, entrega e leitura

Na documentação de quickstart, o Z-API descreve um fluxo em que a aplicação envia a mensagem, a API adiciona o pedido a uma fila e retorna um identificador. A instância então processa a fila, enquanto os webhooks informam a evolução do envio.

Isso cria uma distinção importante:

  • A resposta HTTP confirma que a API recebeu a requisição;
  • O webhook de delivery informa o processamento ou uma eventual falha;
  • O webhook de status informa mudanças posteriores, como recebimento e leitura.

Portanto, não considere uma resposta HTTP 200 como prova de que o destinatário já recebeu ou leu a mensagem.

Preparando sua instância

Antes de fazer a primeira chamada, você precisa ter uma instância configurada no Z-API.

1. Crie ou selecione uma instância

No painel do Z-API, localize o identificador da instância. A documentação informa que o instanceId está disponível na área de instâncias.

2. Conecte o app de mensagens

Siga o procedimento indicado no painel para conectar a sessão. A instância precisa estar disponível para processar as mensagens.

Se a instância estiver desconectada, a requisição poderá falhar ou a mensagem não avançará para o processamento. A documentação de webhooks também descreve um evento de desconexão quando há indisponibilidade na comunicação entre telefone, aplicativo e Z-API.

3. Obtenha o token da instância

O token é utilizado na URL dos endpoints de envio.

Trate esse valor como segredo. Não publique o token no frontend, em repositórios, exemplos reais de código ou mensagens de suporte.

4. Tenha um Client-Token

Os exemplos atuais dos endpoints utilizam o cabeçalho:

Client-Token: <api-key>

Mantenha esse valor em uma variável de ambiente ou em um gerenciador de segredos.

5. Separe um número de teste

Faça os primeiros envios para um contato sob seu controle. Teste o conteúdo, os status, os webhooks e o comportamento de erro antes de incluir clientes na operação.

Estrutura da URL e dos cabeçalhos

Os endpoints seguem a estrutura:

https://api.z-api.io/instances/{instanceId}/token/{token}/{endpoint}

Nos exemplos deste artigo:

instanceId = ID da instância
token     = token da instância
api-key    = Client-Token da conta

Os cabeçalhos básicos são:

Content-Type: application/json
Client-Token: <api-key>

O corpo da requisição deve ser enviado em JSON. Em uma aplicação real, valide o destinatário e trate corretamente caracteres especiais antes de enviar a requisição.

Aproveite e conheça a nova funcionalidade do Z-API: proteção antifraude em grupos de avisos.

Envio de texto pela API

O endpoint documentado para texto simples é:

POST /instances/{instanceId}/token/{token}/send-text

Os principais campos são:

  • phone: número do destinatário ou identificador do grupo, em formato numérico;
  • message: conteúdo do texto.

A documentação orienta enviar o telefone somente com números, sem máscara ou formatação, como:

5511999999999

Envio de texto com cURL

curl –request POST \
  –url https://api.z-api.io/instances/{instanceId}/token/{token}/send-text \
  –header ‘Client-Token: <api-key>’ \
  –header ‘Content-Type: application/json’ \
  –data ‘{
    “phone”: “5511999999999”,
    “message”: “Olá! Seu pedido foi confirmado.”
  }’

Substitua:

  • {instanceId} pelo ID da instância;
  • {token} pelo token da instância;
  • <api-key> pelo Client-Token;
  • 5511999999999 pelo número utilizado no teste.

Envio de texto com JavaScript

const instanceId = process.env.ZAPI_INSTANCE_ID;
const token = process.env.ZAPI_TOKEN;
const clientToken = process.env.ZAPI_CLIENT_TOKEN;

const url = `https://api.z-api.io/instances/instanceId/token/{token}/send-text`;

const response = await fetch(url, {
  method: “POST”,
  headers: {
    “Client-Token”: clientToken,
    “Content-Type”: “application/json”
  },
  body: JSON.stringify({
    phone: “5511999999999”,
    message: “Olá! Seu pedido foi confirmado.”
  })
});

const body = await response.json();

if (!response.ok) {
  throw new Error(
    `Falha ao enviar texto: ${response.status} ${JSON.stringify(body)}`
  );
}

console.log(“Mensagem aceita pela API:”, body);

Resposta esperada

A documentação apresenta uma resposta 200 com identificadores como:

{
  “zaapId”: “3999984263738042930CD6ECDE9VDWSA”,
  “messageId”: “D241XXXX732339502B68”,
  “id”: “D241XXXX732339502B68”
}

Salve o messageId no seu banco de dados. Ele permite relacionar o envio inicial aos eventos posteriores de delivery e status.

Recursos opcionais no texto

A documentação também apresenta opções para adicionar atraso antes do envio e atraso relacionado ao estado de digitação.

Esses recursos podem ser úteis em fluxos conversacionais, mas devem ser utilizados com critério. O objetivo não deve ser esconder a latência de uma integração lenta.

Você também pode utilizar formatação de texto, emojis e quebras de linha. Mensagens longas devem ser revisadas para leitura em telas pequenas e para não esconder a ação principal.

Envio de áudio pela API

O endpoint documentado para áudio é:

POST /instances/{instanceId}/token/{token}/send-audio

Os principais campos são:

  • phone: destinatário;
  • audio: URL pública do áudio ou conteúdo em Base64.

A documentação apresenta duas formas de enviar o arquivo:

  • por link, quando o áudio está hospedado em uma URL acessível;
  • por Base64, quando a aplicação envia o conteúdo codificado.

Envio de áudio por link com cURL

curl –request POST \
  –url https://api.z-api.io/instances/{instanceId}/token/{token}/send-audio \
  –header ‘Client-Token: <api-key>’ \
  –header ‘Content-Type: application/json’ \
  –data ‘{
    “phone”: “5511999999999”,
    “audio”: “https://example.com/audio.mp3”,
    “viewOnce”: false,
    “waveform”: true

A URL precisa estar acessível pela infraestrutura responsável pelo processamento.

Evite links que dependam de login, cookies ou autenticação exclusiva do navegador.

Envio de áudio por link com JavaScript

const instanceId = process.env.ZAPI_INSTANCE_ID;
const token = process.env.ZAPI_TOKEN;
const clientToken = process.env.ZAPI_CLIENT_TOKEN;

const url = `https://api.z-api.io/instances/instanceId/token/{token}/send-audio`;

const payload = {
  phone: “5511999999999”,
  audio: “https://example.com/audio.mp3”,
  viewOnce: false,
  waveform: true
};

const response = await fetch(url, {
  method: “POST”,
  headers: {
    “Client-Token”: clientToken,
    “Content-Type”: “application/json”
  },
  body: JSON.stringify(payload)
});

const body = await response.json();

if (!response.ok) {
  throw new Error(
    `Falha ao enviar áudio: ${response.status} ${JSON.stringify(body)}`
  );
}

console.log(“Áudio aceito pela API:”, body);

Envio de áudio em Base64

Quando a aplicação já possui o arquivo localmente, você pode codificá-lo e montar um Data URL. Exemplo em Node.js:

import { readFile } from “node:fs/promises”;

const audioBuffer = await readFile(“./audio.mp3”);
const base64 = audioBuffer.toString(“base64”);
const audioDataUrl = `data:audio/mpeg;base64,base64`;consturl=`https://api.z-api.io/instances/{process.env.ZAPI_INSTANCE_ID}` +
  `/token/${process.env.ZAPI_TOKEN}/send-audio`;

const response = await fetch(url, {
  method: “POST”,
  headers: {
    “Client-Token”: process.env.ZAPI_CLIENT_TOKEN,
    “Content-Type”: “application/json”
  },
  body: JSON.stringify({
    phone: “5511999999999”,
    audio: audioDataUrl,
    waveform: true
  })
});

const result = await response.json();

if (!response.ok) {
  throw new Error(JSON.stringify(result));
}

console.log(result);

O Base64 aumenta o tamanho da requisição. Para arquivos maiores ou fluxos frequentes, um link estável pode ser mais eficiente, desde que o arquivo permaneça disponível durante o processamento.

Opções de áudio

A documentação apresenta campos opcionais para:

  • viewOnce: enviar como visualização única;
  • waveform: exibir ondas de áudio;
  • delayMessage: aguardar antes de enviar;
  • delayTyping: simular o estado de gravação;
  • processamento em segundo plano, quando suportado pelo endpoint.

Use essas opções apenas quando fizerem sentido para a experiência. O estado de gravação, por exemplo, não deve ser utilizado para mascarar a latência de um sistema lento.

Resposta do envio de áudio

O retorno de sucesso segue a mesma estrutura de identificadores:

{  
“zaapId”: “3999984263738042930CD6ECDE9VDWSA”,  
“messageId”: “D241XXXX732339502B68”,  
“id”: “D241XXXX732339502B68”
}

Salve o messageId e acompanhe os webhooks.

O fato de o arquivo ter sido aceito pela API não significa que o áudio já foi entregue ao destinatário.

Aproveite e confira também: como enviar carrosséis de produtos por mensagem com o Z-API.

Envio de PDF pela API

O endpoint documentado para documentos é:

POST /instances/{instanceId}/token/{token}/send-document/{extension}

Para um PDF, substitua {extension} por pdf:

POST /instances/{instanceId}/token/{token}/send-document/pdf

Os principais campos são:

  • phone: destinatário;
  • document: URL pública ou conteúdo em Base64;
  • fileName: nome apresentado ao destinatário, quando utilizado.

A extensão do arquivo faz parte do caminho do endpoint. Portanto, quando o endpoint exigir /send-document/pdf, não utilize apenas /send-document.

Envio de PDF por link com cURL

curl –request POST \
  –url https://api.z-api.io/instances/{instanceId}/token/{token}/send-document/pdf \
  –header ‘Client-Token: <api-key>’ \
  –header ‘Content-Type: application/json’ \
  –data ‘{
    “phone”: “5511999999999”,
    “document”: “https://example.com/arquivos/contrato.pdf”,
    “fileName”: “Contrato.pdf”
  }’

Use uma URL que entregue o arquivo correto e permaneça disponível pelo tempo necessário para o processamento.

Envio de PDF por link com JavaScript

const instanceId = process.env.ZAPI_INSTANCE_ID;
const token = process.env.ZAPI_TOKEN;
const clientToken = process.env.ZAPI_CLIENT_TOKEN;

const url =
  `https://api.z-api.io/instances/instanceId`+`/token/{token}/send-document/pdf`;

const payload = {
  phone: “5511999999999”,
  document: “https://example.com/arquivos/contrato.pdf”,
  fileName: “Contrato.pdf”,
  caption: “Segue o documento solicitado.”
};
const response = await fetch(url, {
  method: “POST”,
  headers: {
    “Client-Token”: clientToken,
    “Content-Type”: “application/json”
  },
  body: JSON.stringify(payload)
});

const body = await response.json();

if (!response.ok) {
  throw new Error(
    `Falha ao enviar PDF: ${response.status} ${JSON.stringify(body)}`
  );
}

console.log(“PDF aceito pela API:”, body);

A documentação apresenta fileName e descrição do documento como atributos opcionais. Consulte o endpoint utilizado para confirmar o nome exato do campo de legenda ou descrição disponível na sua versão.

Envio de PDF em Base64

Você também pode converter um arquivo local para Base64:

import { readFile } from “node:fs/promises”;

const pdfBuffer = await readFile(“./contrato.pdf”);
const pdfBase64 = pdfBuffer.toString(“base64”);
const documentDataUrl = `data:application/pdf;base64,pdfBase64`;consturl=`https://api.z-api.io/instances/{process.env.ZAPI_INSTANCE_ID}` +
  `/token/${process.env.ZAPI_TOKEN}/send-document/pdf`;

const response = await fetch(url, {
  method: “POST”,
  headers: {
    “Client-Token”: process.env.ZAPI_CLIENT_TOKEN,
    “Content-Type”: “application/json”
  },
  body: JSON.stringify({
    phone: “5511999999999”,
    document: documentDataUrl,
    fileName: “Contrato.pdf”
  })
});

const result = await response.json();

if (!response.ok) {
  throw new Error(JSON.stringify(result));
}

console.log(result);

Use Base64 com cuidado. Arquivos grandes aumentam o tamanho do payload e o consumo de memória no processo que prepara a requisição. Para uma operação de maior escala, considere uma hospedagem controlada e URLs com validade adequada.

Resposta do envio de PDF

Em uma resposta bem-sucedida, a documentação apresenta os IDs da mensagem:

{  
“zaapId”: “3999984263738042930CD6ECDE9VDWSA”,  
“messageId”: “D241XXXX732339502B68”,  
“id”: “D241XXXX732339502B68”
}

Não descarte esses valores depois do console.log. Em produção, grave o messageId junto ao pedido, cliente ou atendimento que originou o envio.

Como validar o status da mensagem?

A documentação de webhooks do Z-API apresenta quatro grupos de eventos:

  • Delivery: informa quando a mensagem foi processada ou quando ocorreu uma falha no processamento;
  • Receive: ocorre quando alguém interage com seu número;
  • Status: informa mudanças como received, read, replied e deleted;
  • Disconnected: indica indisponibilidade na comunicação entre telefone, aplicativo e Z-API.

Esses eventos permitem acompanhar a mensagem depois da requisição inicial.

Configure uma URL HTTPS

A aplicação deve disponibilizar endpoints HTTPS para receber os POSTs do Z-API.

Uma estrutura possível é:

POST https://app.exemplo.com/webhooks/zapi/delivery

POST https://app.exemplo.com/webhooks/zapi/status

POST https://app.exemplo.com/webhooks/zapi/receive

POST https://app.exemplo.com/webhooks/zapi/disconnected

Consulte a documentação do painel e do endpoint de configuração para definir as rotas corretas na sua instância.

Registre o ID da mensagem

O fluxo de validação deve relacionar o evento recebido ao messageId salvo na resposta inicial.

app.post(“/webhooks/zapi/status”, async (req, res) => {
  const event = req.body;

  // Responda rapidamente ao provedor.
  res.sendStatus(200);

  if (!event.messageId) {
    console.warn(“Status sem messageId”, event);
    return;
  }

  await messages.updateByMessageId(event.messageId, {
    status: event.status,
    receivedAt: new Date()
  });
});

Em produção, valide a autenticidade do webhook, trate duplicidades e mova o processamento pesado para uma fila.

Estados não são equivalentes

Evite tratar todos os retornos como se representassem o mesmo estado.

Uma estrutura possível é:

REQUEST_ACCEPTED

PROCESSING

SENT_TO_WHATSAPP

RECEIVED

READ

FAILED

A resposta 200 da requisição inicial pode representar REQUEST_ACCEPTED.

O webhook de delivery pode atualizar o registro para SENT_TO_WHATSAPP.

O webhook de status pode atualizar o estado para RECEIVED ou READ.

Essa separação permite identificar em qual etapa ocorreu uma falha e evita que o sistema apresente uma mensagem como entregue antes de existir confirmação correspondente.

Quanto custa a automação de mensagens para pequenas empresas em 2026? Acesse e confira tudo sobre o investimento em API de mensagens.

10 erros comuns e como corrigir

1. URL com instanceId ou token incorreto

Sintoma: erro de autenticação ou instância não encontrada.

Verifique se os valores foram copiados do painel correto e se não há espaços, aspas ou caracteres extras.

2. Client-Token ausente

Sintoma: a chamada chega ao endpoint, mas é rejeitada.

Inclua o cabeçalho exatamente como documentado:

Client-Token: <api-key>

Não confunda o Client-Token com o token da instância. Eles aparecem em lugares diferentes da requisição.

3. Telefone com máscara

Sintoma: destinatário inválido ou envio não processado.

Utilize somente números no formato indicado pela documentação, sem +, espaços, parênteses ou hífens:

5511999999999

Para grupos, use o identificador de grupo quando o endpoint permitir.

4. Endpoint de PDF sem extensão

Sintoma: rota não encontrada ou requisição inválida.

Use:

/send-document/pdf

e não apenas:

/send-document

quando o endpoint exigir a extensão.

5. URL do arquivo inacessível

Sintoma: texto funciona, mas áudio ou PDF falha.

Teste a URL fora da sua rede. Verifique se:

  • ela responde sem login;
  • entrega o arquivo correto;
  • o certificado é válido;
  • não expira antes do processamento.

6. Base64 malformado

Sintoma: arquivo corrompido ou erro no processamento.

Confirme o MIME type e a estrutura do Data URL:

data:audio/mpeg;base64,…

data:application/pdf;base64,…

Evite quebras de linha acidentais ou a duplicação do prefixo.

7. JSON inválido

Sintoma: erro 400 ou corpo não interpretado.

No JavaScript, utilize JSON.stringify. No cURL, confira aspas e caracteres especiais.

Ao inserir variáveis dinamicamente, valide quebras de linha e caracteres especiais.

8. Confundir resposta com entrega

Sintoma: o sistema marca a mensagem como entregue assim que recebe a resposta da API.

A resposta inicial deve ser tratada como aceite ou processamento inicial. Atualize o estado com os webhooks de delivery e status.

9. Instância desconectada

Sintoma: mensagens não avançam ou os webhooks informam indisponibilidade.

Verifique o painel da instância, a conexão do aplicativo de mensagens e o evento de desconexão.

Evite criar novas tentativas em loop sem entender a causa da falha.

10. Credenciais expostas

Sintoma: chamadas inesperadas ou risco de uso indevido.

Revogue e substitua as chaves comprometidas. Mantenha as credenciais no backend e nunca no código JavaScript executado no navegador.

Envio seguro em produção

Depois que o primeiro envio funcionar, a prioridade deve ser transformar o exemplo em uma integração controlada.

Use variáveis de ambiente

ZAPI_INSTANCE_ID=seu_instance_id

ZAPI_TOKEN=seu_token

ZAPI_CLIENT_TOKEN=sua_client_token

No código, leia essas variáveis pelo ambiente de execução.

Não envie os valores para o frontend.

Crie uma camada de serviço

Em vez de espalhar URLs e credenciais pela aplicação, centralize o envio em uma camada de serviço:

async function sendText({ phone, message }) {
  const url =
    `https://api.z-api.io/instances/process.env.ZAPIINSTANCEID`+`/token/{process.env.ZAPI_TOKEN}/send-text`;

  const response = await fetch(url, {
    method: “POST”,
    headers: {
      “Client-Token”: process.env.ZAPI_CLIENT_TOKEN,
      “Content-Type”: “application/json”
    },
    body: JSON.stringify({ phone, message })
  });

  const result = await response.json();

  if (!response.ok) {
    throw new Error(
      `Z-API ${response.status}: ${JSON.stringify(result)}`
    );
  }

  return result;
}

A mesma camada pode ter métodos para sendAudio e sendDocument. Isso facilita:

  • testes;
  • logs;
  • tratamento de erros;
  • padronização;
  • manutenção;
  • eventual alteração do fornecedor.

Use filas e idempotência

Se um evento do seu sistema gerar uma mensagem, registre uma chave de operação antes de enviar. Assim, uma retentativa de webhook ou de workflow não cria duas mensagens para o mesmo pedido ou evento.

Monitore tudo

Registre, no mínimo:

  • tipo de mensagem;
  • destinatário;
  • origem do evento;
  • horário da chamada;
  • status HTTP;
  • messageId;
  • status posterior;
  • erro retornado;
  • número de tentativas.

Não armazene conteúdo sensível sem necessidade. Proteja os logs e limite o acesso às informações.

Checklist para o primeiro envio

Antes de colocar a integração para funcionar, confirme:

  • Criar ou selecionar uma instância;
  • conectar a instância;
  • obter instanceId e token;
  • obter o Client-Token;
  • definir um número de teste;
  • montar a URL correta;
  • usar Content-Type: application/json;
  • enviar o telefone sem máscara;
  • testar primeiro o envio de texto;
  • salvar zaapId e messageId;
  • testar áudio por link;
  • testar áudio em Base64, se necessário;
  • testar PDF com /send-document/pdf;
  • configurar webhooks HTTPS;
  • diferenciar aceite, processamento, entrega e leitura;
  • simular erros de URL e credenciais;
  • implementar logs e idempotência;
  • validar políticas e consentimento antes de escalar.

Envie textos, áudios e PDFs integrando seu sistema com o Z-API

Enviar textos, áudios e PDFs pela API de mensagens envolve mais do que copiar um endpoint. É preciso preparar a instância, autenticar a chamada, montar o payload correto, hospedar arquivos quando optar por link, interpretar a resposta e acompanhar os eventos posteriores.

Para texto, o endpoint utilizado é /send-text. Para áudio, /send-audio, com possibilidade de utilizar link ou Base64. Para PDF, /send-document/pdf, com a extensão no caminho e o documento enviado por link ou Base64.

Em todos os casos, salve o messageId. A resposta inicial indica que a requisição foi aceita, mas os webhooks permitem acompanhar o processamento, o recebimento e a leitura.

Comece com um contato de teste, valide os três tipos de conteúdo e só depois conecte os endpoints a pedidos, leads, notificações ou atendimentos reais.

Faça seu primeiro envio pela API: configure uma instância, execute um dos exemplos deste tutorial e acompanhe o resultado pelos webhooks do Z-API.

Avalie este post
bg section

Especialista nas áreas de SEO e Copywriting há mais de oito anos, focado em estratégias de posicionamento orgânico (SEO, GEO e AEO) e entrega de conteúdo relevante para os leitores. No Z-API, atuo na criação de conteúdo estratégico para impulsionar a performance digital da marca e ofertar artigos com conhecimentos úteis para os usuários.