Para integradores de PDV

Leve o WhatsApp oficial para as lojas que usam o seu PDV.

Confirmação de pedido com comprovante em PDF e aviso de pedido pronto, no WhatsApp do cliente final e com o nome da loja. Um diferencial que o lojista percebe no primeiro dia — e que você entrega com duas chamadas HTTP.

POST https://api.biwapp.com/notifications/send
Quero integrar meu sistema

Como funciona

  1. 1Pedido registrado no caixa
    POSTtype: "confirmacao"

    O cliente recebe a confirmação do pedido com o comprovante em PDF anexado.

  2. 2Pedido pronto para retirada
    POSTtype: "pronto"

    O cliente recebe o aviso de que pode buscar as peças.

Antes de começar

O que você precisa ter em mãos

As duas notificações usam o mesmo endereço. O campo type do corpo decide qual mensagem sai.

Endereço
POST https://api.biwapp.com/notifications/send — somente HTTPS.
Token da loja
Um por unidade, começa com bwp_ e tem 52 caracteres. É gerado pela equipe BIWAPP na implantação da loja e entregue a você — ele é exibido uma única vez.
Preço
R$ 0,06 por mensagem de notificação, pago pela loja. Só conta o que a API do WhatsApp aceita — envios recusados não são cobrados.
Formato
JSON em UTF-8, com Content-Type: application/json. Acentos e cedilha funcionam normalmente.
Pré-requisito
A notificação precisa estar ligada e com template aprovado na unidade. Isso é configurado pela BIWAPP; se não estiver, a API responde 409 dizendo qual das duas coisas falta.

Autenticação

Um cabeçalho, em toda chamada

O token identifica a loja e autoriza o envio. Mande-o no cabeçalho X-Biwapp-Token. Não há login, sessão nem renovação: o mesmo token vale até ser trocado.

Trocar o token no painel BIWAPP invalida o anterior na hora. Por isso ele deve ficar na configuração da loja no seu sistema — nunca fixo no código-fonte, onde uma troca exigiria uma nova versão do PDV.

Cabeçalhostoken ilustrativo
POST /notifications/send HTTP/1.1
Host: api.biwapp.com
Content-Type: application/json
X-Biwapp-Token: bwp_3f9a1c07b2e44d8a91c6f02e57b83d1a4c9e60f2b7d5a8e1
POST/notifications/sendtype: "confirmacao"

Confirmação do pedido

Chame logo depois que o pedido for gravado no PDV. Você manda o nome do cliente, o número do pedido e o comprovante em texto — o mesmo que sairia na impressora. A BIWAPP audita esse texto, transforma em PDF e anexa à mensagem. Você não precisa gerar arquivo nem hospedar link.

Corpo da requisição

CampoDescrição
typestringobrigatório

"confirmacao"

phonestringobrigatório

Celular do cliente, com ou sem DDI e máscara.

(11) 99000-0000, 11990000000 e +55 11 99000-0000 viram 5511990000000.

parameters.1stringobrigatório

Nome do cliente, como deve aparecer na mensagem.

parameters.2stringobrigatório

Número do pedido. Também dá nome ao anexo: Pedido-12345.pdf.

parameters.receipt_textstringobrigatório

O comprovante em texto puro, com quebras de linha (\n ou \r\n). Até 8.000 caracteres.

Não é variável da mensagem: a BIWAPP retira este campo dos parâmetros antes do envio. Regras do comprovante

external_refstringopcional

A sua referência do pedido. Aparece no registro de envios e ajuda o suporte a localizar uma mensagem.

Resposta de sucesso

CampoDescrição
toO telefone como foi usado no envio, só dígitos e com DDI.
provider_idIdentificador da mensagem no provedor do WhatsApp. Guarde-o para rastrear uma entrega com o suporte.
type · campO tipo recebido e o código interno dele (camp7 = confirmação).
Requisição
curl -X POST https://api.biwapp.com/notifications/send \
  -H "Content-Type: application/json" \
  -H "X-Biwapp-Token: bwp_SEU_TOKEN_AQUI" \
  --max-time 30 \
  -d '{
    "type": "confirmacao",
    "phone": "(11) 99000-0000",
    "parameters": {
      "1": "Cliente X",
      "2": "12345",
      "receipt_text": "Loja X — Pedido 12345\nRua Gaivota, xxx — São Paulo/SP\nContato: (11) 5000-5000\n\n21/09/2026 14:32\nCliente: Cliente X\n\n2x Camisa social .......... R$ 39,80\n1x Calça alfaiataria ...... R$ 32,90\n\nTotal ..................... R$ 72,70\nPrevisão de entrega: 24/09/2026"
    },
    "external_ref": "PED-12345"
  }'
// Node.js 18+ — fetch nativo, sem dependências
const BIWAPP_URL = 'https://api.biwapp.com/notifications/send'

export async function enviarConfirmacao(pedido) {
  const resposta = await fetch(BIWAPP_URL, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-Biwapp-Token': process.env.BIWAPP_TOKEN
    },
    body: JSON.stringify({
      type: 'confirmacao',
      phone: pedido.telefone,
      parameters: {
        1: pedido.cliente,
        2: pedido.numero,
        receipt_text: pedido.comprovante   // texto puro, com \n
      },
      external_ref: 'PED-' + pedido.numero
    }),
    signal: AbortSignal.timeout(30_000)
  })

  const dados = await resposta.json()
  if (!resposta.ok) {
    // 4xx: a requisição precisa de ajuste — dados.message explica o quê
    throw new Error(`BIWAPP ${resposta.status}: ${dados.message}`)
  }
  return dados   // { message, type, camp, to, provider_id }
}

// uso
const enviado = await enviarConfirmacao({
  telefone: '(11) 99000-0000',
  cliente: 'Cliente X',
  numero: '12345',
  comprovante: [
    'Loja X — Pedido 12345',
    'Contato: (11) 5000-5000',
    '',
    '2x Camisa social .......... R$ 39,80',
    '1x Calça alfaiataria ...... R$ 32,90',
    '',
    'Total ..................... R$ 72,70',
    'Previsão de entrega: 24/09/2026'
  ].join('\n')
})
console.log('Enviado para', enviado.to, '· id', enviado.provider_id)
# Python 3 — pip install requests
import os
import requests

comprovante = "\n".join([
    "Loja X — Pedido 12345",
    "Contato: (11) 5000-5000",
    "",
    "2x Camisa social .......... R$ 39,80",
    "1x Calça alfaiataria ...... R$ 32,90",
    "",
    "Total ..................... R$ 72,70",
    "Previsão de entrega: 24/09/2026",
])

resposta = requests.post(
    "https://api.biwapp.com/notifications/send",
    headers={"X-Biwapp-Token": os.environ["BIWAPP_TOKEN"]},
    json={
        "type": "confirmacao",
        "phone": "(11) 99000-0000",
        "parameters": {
            "1": "Cliente X",
            "2": "12345",
            "receipt_text": comprovante,
        },
        "external_ref": "PED-12345",
    },
    timeout=30,
)

dados = resposta.json()
if resposta.status_code != 200:
    # 4xx: a requisição precisa de ajuste — dados["message"] explica o quê
    raise RuntimeError(f"BIWAPP {resposta.status_code}: {dados['message']}")
print("Enviado para", dados["to"], "· id", dados["provider_id"])
// .NET 6+ — System.Net.Http.Json, sem pacotes extras
using System.Net.Http.Json;
using System.Text.Json;

var http = new HttpClient { Timeout = TimeSpan.FromSeconds(30) };
http.DefaultRequestHeaders.Add("X-Biwapp-Token",
    Environment.GetEnvironmentVariable("BIWAPP_TOKEN"));

var comprovante = string.Join("\n",
    "Loja X — Pedido 12345",
    "Contato: (11) 5000-5000",
    "",
    "2x Camisa social .......... R$ 39,80",
    "1x Calça alfaiataria ...... R$ 32,90",
    "",
    "Total ..................... R$ 72,70",
    "Previsão de entrega: 24/09/2026");

var resposta = await http.PostAsJsonAsync(
    "https://api.biwapp.com/notifications/send",
    new
    {
        type = "confirmacao",
        phone = "(11) 99000-0000",
        parameters = new Dictionary<string, string>
        {
            ["1"] = "Cliente X",
            ["2"] = "12345",
            ["receipt_text"] = comprovante
        },
        external_ref = "PED-12345"
    });

var dados = await resposta.Content.ReadFromJsonAsync<JsonElement>();
if (!resposta.IsSuccessStatusCode)
    throw new InvalidOperationException(
        $"BIWAPP {(int)resposta.StatusCode}: {dados.GetProperty("message").GetString()}");

Console.WriteLine($"Enviado para {dados.GetProperty("to").GetString()}");
// Delphi 10.2 Tokyo ou superior — só RTL, sem componentes de terceiros
uses
  System.SysUtils, System.Classes, System.JSON,
  System.Net.HttpClient, System.Net.URLClient;

function EnviarConfirmacao(const Telefone, Cliente, Pedido,
  Comprovante: string): string;
var
  Http: THTTPClient;
  Corpo, Parametros: TJSONObject;
  Envio: TStringStream;
  Resposta: IHTTPResponse;
begin
  Http := THTTPClient.Create;
  Corpo := TJSONObject.Create;
  try
    Parametros := TJSONObject.Create;
    Parametros.AddPair('1', Cliente);
    Parametros.AddPair('2', Pedido);
    // o cupom como está: quebras de linha #13#10 ou #10
    Parametros.AddPair('receipt_text', Comprovante);

    Corpo.AddPair('type', 'confirmacao');
    Corpo.AddPair('phone', Telefone);
    Corpo.AddPair('parameters', Parametros); // Corpo passa a ser o dono
    Corpo.AddPair('external_ref', 'PED-' + Pedido);

    Http.ConnectionTimeout := 10000;
    Http.ResponseTimeout := 30000;
    Http.ContentType := 'application/json';
    Http.CustomHeaders['X-Biwapp-Token'] := 'bwp_SEU_TOKEN_AQUI';

    Envio := TStringStream.Create(Corpo.ToJSON, TEncoding.UTF8);
    try
      Resposta := Http.Post(
        'https://api.biwapp.com/notifications/send', Envio);
      Result := Resposta.ContentAsString(TEncoding.UTF8);
      if Resposta.StatusCode <> 200 then
        raise Exception.CreateFmt('BIWAPP %d: %s',
          [Resposta.StatusCode, Result]);
    finally
      Envio.Free;
    end;
  finally
    Corpo.Free;
    Http.Free;
  end;
end;
Resposta200 OK
{
  "message": "Notificação enviada.",
  "type": "confirmacao",
  "camp": "camp7",
  "to": "5511990000000",
  "provider_id": "6700f2c9a8b41e0d93c25f71"
}

Do cupom ao WhatsApp

O que acontece com a requisição acima, do seu lado até a tela do cliente.

O PDV mandaparameters.receipt_text
A BIWAPP geraPDF A4 · Courier
Pedido-12345.pdf
O cliente recebe(11) 99000-0000
Texto ilustrativo: a mensagem é o template aprovado da sua unidade, com o nome e o número do pedido no lugar.
POST/notifications/sendtype: "pronto"

Pedido pronto

Chame quando o pedido mudar para pronto para retirada no PDV. É um aviso curto, sem anexo: só o nome do cliente e o número do pedido.

Corpo da requisição

CampoDescrição
typestringobrigatório

"pronto"

phonestringobrigatório

Celular do cliente, com ou sem DDI e máscara — mesma regra da confirmação.

parameters.1stringobrigatório

Nome do cliente.

parameters.2stringobrigatório

Número do pedido.

external_refstringopcional

A sua referência do pedido, para o registro de envios.

A resposta tem o mesmo formato da confirmação, com "type": "pronto" e "camp": "camp8".

Requisição
curl -X POST https://api.biwapp.com/notifications/send \
  -H "Content-Type: application/json" \
  -H "X-Biwapp-Token: bwp_SEU_TOKEN_AQUI" \
  --max-time 30 \
  -d '{
    "type": "pronto",
    "phone": "(11) 99000-0000",
    "parameters": {
      "1": "Cliente X",
      "2": "12345"
    },
    "external_ref": "PED-12345"
  }'
// Node.js 18+ — fetch nativo, sem dependências
const resposta = await fetch('https://api.biwapp.com/notifications/send', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-Biwapp-Token': process.env.BIWAPP_TOKEN
  },
  body: JSON.stringify({
    type: 'pronto',
    phone: '(11) 99000-0000',
    parameters: { 1: 'Cliente X', 2: '12345' },
    external_ref: 'PED-12345'
  }),
  signal: AbortSignal.timeout(30_000)
})

const dados = await resposta.json()
if (!resposta.ok) throw new Error(`BIWAPP ${resposta.status}: ${dados.message}`)
console.log('Enviado para', dados.to, '· id', dados.provider_id)
# Python 3 — pip install requests
import os
import requests

resposta = requests.post(
    "https://api.biwapp.com/notifications/send",
    headers={"X-Biwapp-Token": os.environ["BIWAPP_TOKEN"]},
    json={
        "type": "pronto",
        "phone": "(11) 99000-0000",
        "parameters": {"1": "Cliente X", "2": "12345"},
        "external_ref": "PED-12345",
    },
    timeout=30,
)

dados = resposta.json()
if resposta.status_code != 200:
    raise RuntimeError(f"BIWAPP {resposta.status_code}: {dados['message']}")
print("Enviado para", dados["to"], "· id", dados["provider_id"])
// .NET 6+ — System.Net.Http.Json, sem pacotes extras
using System.Net.Http.Json;
using System.Text.Json;

var http = new HttpClient { Timeout = TimeSpan.FromSeconds(30) };
http.DefaultRequestHeaders.Add("X-Biwapp-Token",
    Environment.GetEnvironmentVariable("BIWAPP_TOKEN"));

var resposta = await http.PostAsJsonAsync(
    "https://api.biwapp.com/notifications/send",
    new
    {
        type = "pronto",
        phone = "(11) 99000-0000",
        parameters = new Dictionary<string, string>
        {
            ["1"] = "Cliente X",
            ["2"] = "12345"
        },
        external_ref = "PED-12345"
    });

var dados = await resposta.Content.ReadFromJsonAsync<JsonElement>();
if (!resposta.IsSuccessStatusCode)
    throw new InvalidOperationException(
        $"BIWAPP {(int)resposta.StatusCode}: {dados.GetProperty("message").GetString()}");

Console.WriteLine($"Enviado para {dados.GetProperty("to").GetString()}");
// Delphi 10.2 Tokyo ou superior — só RTL, sem componentes de terceiros
uses
  System.SysUtils, System.Classes, System.JSON,
  System.Net.HttpClient, System.Net.URLClient;

function EnviarPedidoPronto(const Telefone, Cliente, Pedido: string): string;
var
  Http: THTTPClient;
  Corpo, Parametros: TJSONObject;
  Envio: TStringStream;
  Resposta: IHTTPResponse;
begin
  Http := THTTPClient.Create;
  Corpo := TJSONObject.Create;
  try
    Parametros := TJSONObject.Create;
    Parametros.AddPair('1', Cliente);
    Parametros.AddPair('2', Pedido);

    Corpo.AddPair('type', 'pronto');
    Corpo.AddPair('phone', Telefone);
    Corpo.AddPair('parameters', Parametros); // Corpo passa a ser o dono
    Corpo.AddPair('external_ref', 'PED-' + Pedido);

    Http.ConnectionTimeout := 10000;
    Http.ResponseTimeout := 30000;
    Http.ContentType := 'application/json';
    Http.CustomHeaders['X-Biwapp-Token'] := 'bwp_SEU_TOKEN_AQUI';

    Envio := TStringStream.Create(Corpo.ToJSON, TEncoding.UTF8);
    try
      Resposta := Http.Post(
        'https://api.biwapp.com/notifications/send', Envio);
      Result := Resposta.ContentAsString(TEncoding.UTF8);
      if Resposta.StatusCode <> 200 then
        raise Exception.CreateFmt('BIWAPP %d: %s',
          [Resposta.StatusCode, Result]);
    finally
      Envio.Free;
    end;
  finally
    Corpo.Free;
    Http.Free;
  end;
end;
Resposta200 OK
{
  "message": "Notificação enviada.",
  "type": "pronto",
  "camp": "camp8",
  "to": "5511990000000",
  "provider_id": "6700f3e1c7d52a0b84e19c33"
}

Do caixa ao WhatsApp

O que acontece com a requisição acima, do seu lado até a tela do cliente.

O PDV mandanome e número do pedido
A BIWAPP montatemplate aprovado da loja
O cliente recebe(11) 99000-0000
Texto ilustrativo: a mensagem é o template aprovado da sua unidade.

O comprovante

Mande o cupom como ele é

O receipt_text vira um PDF em fonte monoespaçada, então o alinhamento feito com espaços e pontilhados se mantém exatamente como no cupom impresso. Não precisa reformatar nada.

  • 8.000caracteres no máximo. Acima disso a API responde 422.
  • 85 colunaspor linha no PDF (A4, Courier 10). O cupom térmico de 40 a 48 colunas cabe folgado; linhas mais longas quebram entre palavras.
  • 58 linhaspor página. Comprovantes maiores viram várias páginas, numeradas no rodapé.
  • \n · \r\nas duas quebras de linha funcionam. TAB vira 4 espaços, porque no PDF ele não avança.
  • Latin-1acentos, cedilha, travessão e aspas curvas saem corretos. Emojis e símbolos fora desse conjunto aparecem como ?.

Auditoria de conteúdo

A confirmação sai por um template de utilidade do WhatsApp — a categoria das mensagens que o cliente espera receber por ter feito um pedido. Se o anexo trouxer campanha, a Meta pode reclassificar o template como marketing, e a loja perde o envio transacional. Por isso cada comprovante é lido antes de virar PDF.

O comprovante deve conter só dados do pedido, da loja e de contato. A diferença entre o que passa e o que é barrado raramente é a palavra, e sim o convite:

Passa

  • Desconto fidelidade ... -R$ 8,14desconto como linha de valor do pedido
  • Pago no cartão VISA ****5678forma de pagamento
  • www.lojax.com.br · (11) 5000-5000site e telefone da loja
  • Garantia de 30 dias para reclamaçõescondição do serviço contratado

É barrado

  • Ganhe 10% de desconto na próxima!oferta para a próxima compra
  • Use o cupom VOLTA10cupom
  • Siga-nos no Instagram @lojaxpedido de divulgação
  • Só hoje: coleta grátisurgência e oferta

Comprovante barrado não é enviado. A resposta é 422, com a lista do que foi encontrado e a linha inteira onde está — para quem opera o PDV achar a origem:

Resposta422 Unprocessable Entity
{
  "message": "O comprovante tem conteúdo de marketing e não pode ir num template de UTILIDADE. Ele deve conter só dados do pedido, da loja e de contato.\n• \"Aproveite\" (chamada para ação) em: Aproveite: 20% de desconto na próxima lavagem!\n• \"de desconto na próxima\" (oferta para a próxima compra) em: Aproveite: 20% de desconto na próxima lavagem!",
  "audit": [
    {
      "motivo": "chamada para ação",
      "termo": "Aproveite",
      "linha": "Aproveite: 20% de desconto na próxima lavagem!"
    },
    {
      "motivo": "oferta para a próxima compra",
      "termo": "de desconto na próxima",
      "linha": "Aproveite: 20% de desconto na próxima lavagem!"
    }
  ]
}

Respostas e erros

Todo erro diz o que corrigir

Toda resposta é JSON e traz o campo message, escrito para ser mostrado ou registrado como está. Os 4xx pedem ajuste na requisição ou na configuração da loja — repetir não resolve. Só os 5xx merecem nova tentativa.

StatusQuando aconteceO que fazerRepetir?
200A API do WhatsApp aceitou a mensagem.Registre o provider_id junto do pedido.—
401Cabeçalho X-Biwapp-Token ausente, ou token que não existe mais.Confira o cabeçalho. Se o token foi trocado no painel, atualize-o na configuração da loja.Não
403A unidade está inativa na BIWAPP.Fale com a BIWAPP.Não
404A unidade ainda não tem notificações configuradas.Fale com a BIWAPP.Não
409Esta notificação está desligada na unidade, ou sem template selecionado.A message diz qual dos dois. A BIWAPP liga ou configura no painel.Não
422type inválido, phone ausente, comprovante ausente, acima de 8.000 caracteres ou barrado na auditoria.Corrija conforme a message. Na auditoria, o campo audit aponta a linha.Não
502O PDF não pôde ser publicado, ou a API do WhatsApp recusou o envio. O motivo do provedor vem em error.Nada foi enviado ao cliente. Tente de novo em alguns segundos.Sim, com espera
500Erro inesperado na BIWAPP.Repita uma vez. Persistindo, contate o suporte com o external_ref.Uma vez

Boas práticas

O que evita dor de cabeça no balcão

Não trave o caixa esperando

A resposta costuma levar poucos segundos, mas depende do WhatsApp. Faça a chamada em segundo plano, com tempo limite de 30 segundos, e deixe o operador seguir com o próximo cliente.

Não repita depois de um tempo esgotado

Cada 200 é uma mensagem entregue ao WhatsApp e não há deduplicação: duas chamadas iguais geram duas mensagens. Se a sua chamada estourou o tempo, o envio pode ter saído. Registre o external_ref e confira antes de reenviar.

200 é aceito, não entregue

O sucesso confirma que o WhatsApp aceitou a mensagem. A entrega ao aparelho acontece em seguida e pode não ocorrer — por exemplo, se o número não tiver WhatsApp. O provider_id permite rastrear cada caso com o suporte.

Chame depois de gravar o pedido

Dispare a confirmação só quando o pedido já estiver salvo no PDV, com o número definitivo. Um pedido cancelado logo em seguida já terá sido confirmado ao cliente.

Um token por loja

Cada unidade tem o seu token, e ele define de qual WhatsApp a mensagem sai. Em rede com várias lojas, guarde o token na configuração de cada uma — nunca um token só para todas.

Telefone de cadastro é suficiente

Não precisa limpar máscara nem adicionar DDI: números brasileiros de 10 ou 11 dígitos recebem o 55 automaticamente. Números de outros países devem vir com o DDI.

Homologação

Antes de liberar nas lojas

Use um celular da sua equipe como cliente de teste. As mensagens de teste são mensagens reais e entram na contagem do mês da unidade.

Quer integrar o seu PDV com a BIWAPP?

Fale com a gente para liberar a integração nas lojas que usam o seu sistema. São duas chamadas HTTP — e o cliente passa a receber a confirmação e o aviso de pronto no WhatsApp.