{"openapi":"3.1.0","info":{"title":"whatsapi.sh — a API do WhatsApp sem dor de cabeça","version":"1.0.0","description":"Endpoints REST diretos sobre os seus próprios números do WhatsApp pareados. Toda operação daqui também é uma tool MCP (veja x-mcp-tools), autenticada pela mesma chave `wa_`. Escreve TypeScript ou JavaScript? `npm i @whatsapi.sh/sdk` dá um método tipado para cada endpoint daqui."},"servers":[{"url":"http://127.0.0.1:3334"}],"tags":[{"name":"Numbers","description":"Adicione um número à sua conta, pareie por QR code ou código de pareamento e acompanhe o estado da conexão."},{"name":"Messages","description":"Texto, mídia, localização, cartões de contato — para um chat ou em lote, com indicador de digitação e recibos de leitura."},{"name":"Queue","description":"Mensagens seguradas para que as conversas que um número inicia saiam com minutos de intervalo, e não todas de uma vez — veja o que está na fila ou desista de alguma."},{"name":"OTP","description":"Entregue um código de uso único e confira o que o usuário digitou — o código volta na resposta."},{"name":"Webhooks","description":"Um endpoint de eventos assinados por conta: configure, envie um teste, faça a rotação do segredo, consulte o log de entregas."},{"name":"Usage","description":"Envios medidos no mês da cobrança, divididos por chave de API."}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"Uma chave de API `wa_` do painel."}}},"paths":{"/messages":{"post":{"operationId":"send_message_post","summary":"Envie uma mensagem pelo WhatsApp","tags":["Messages"],"description":"Envie uma mensagem de texto para um número pelo WhatsApp. Consome uma mensagem da cota mensal da conta.\n\n**Uma mensagem para alguém que este número nunca procurou não sai na hora.** Ela é aceita, cobrada e vai PARA A FILA: a resposta traz `status: \"queued\"` e `scheduledAt`, e ela sai 15–25 minutos depois, uma de cada vez. É de propósito. Uma rajada de primeiras abordagens é o jeito mais rápido de ter um número banido, e espaçar elas é o que separa um número que dura de um que não dura. O `message.sent` chega no webhook da conta quando ela sai, com o id do WhatsApp. Use `skipQueue: true` para uma mensagem que a pessoa está esperando agora, ou desligue a fila do número com update_number.\n\nRespostas para quem falou primeiro nunca entram na fila e nunca gastam limite. Uma primeira abordagem também gasta uma das CONVERSAS NOVAS do dia — o teto anti-ban informado em `newConversationsRemaining`. Uma resposta `sent` traz o id de mensagem do WhatsApp; os recibos de entrega e de leitura chegam depois, no webhook da conta, não aqui.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"to":{"type":"string","minLength":1,"description":"Destinatário — um telefone em formato internacional (+5511988887777) ou um endereço de WhatsApp (5511988887777@s.whatsapp.net, um contato @lid ou um grupo @g.us)."},"from":{"description":"Qual dos seus números de WhatsApp faz o envio — o id dele ou o telefone. Opcional: com um único número conectado, resolvemos para você.","type":"string","minLength":1},"text":{"type":"string","minLength":1,"maxLength":4096,"description":"O corpo da mensagem."},"linkPreview":{"description":"Renderiza um card de prévia para o primeiro link do texto. Padrão: ligado.","type":"boolean"},"skipQueue":{"description":"Envia na hora, em vez de pegar um lugar na fila do número. Só para uma mensagem que a pessoa está esperando neste momento — uma resposta, um código, a confirmação de algo que ela acabou de fazer. Prospecção enviada assim é exatamente o que faz o WhatsApp banir números, que é o motivo de a fila existir. Padrão: desligado.","type":"boolean"},"humanize":{"description":"Se envia como uma pessoa: ficar online, abrir o que ela escreveu por último e mostrar “digitando…” pelo tempo que a mensagem levaria para ser digitada. Ligado por padrão, o que soma alguns segundos à chamada — `false` envia direto e na hora. Configure cada parte por número com update_number.","type":"boolean"}},"required":["to","text"],"additionalProperties":false}}}},"responses":{"201":{"description":"A requisição funcionou.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}},"required":["data"]},"example":{"data":{"id":"9c1f0b7e-8b1a-4a2e-9b0a-1f2e3d4c5b6a","to":"+5511988887777","from":"a1b2c3d4-0000-0000-0000-000000000000","status":"queued","scheduledAt":"2026-08-24T19:18:00.000Z","timestamp":"2026-08-24T19:00:00.000Z","quotaRemaining":4999,"newConversationsRemaining":19,"creditRemaining":0}}}}},"400":{"description":"VALIDATION_ERROR — os erros, nunca os valores."},"401":{"description":"UNAUTHORIZED / INVALID_TOKEN — a chave está ausente ou errada."},"429":{"description":"RATE_LIMIT_EXCEEDED / QUOTA_EXCEEDED — o Retry-After diz quando libera."}}}},"/messages/media":{"post":{"operationId":"send_media_post","summary":"Envie foto, vídeo, áudio ou arquivo","tags":["Messages"],"description":"Envie mídia pelo WhatsApp a partir de uma URL pública ou dados em base64. O `type` escolhe a bolha que o destinatário vê: `image` e `video` aceitam legenda, `document` é um anexo nomeado por `fileName`, e `audio` vira um áudio de voz quando o arquivo é ogg/opus — qualquer outro formato de áudio vai como anexo tocável, porque o WhatsApp não renderiza áudio de voz que não é opus. Arquivos têm teto de 16MB, e `url` ganha de `base64` para arquivos grandes. Consome uma mensagem.\n\nComo todo envio: mídia para alguém que este número nunca procurou vai PARA A FILA em vez de sair, e volta com `status: \"queued\"` e `scheduledAt`. O arquivo é baixado quando chega a vez dele, então a `url` precisa continuar acessível até lá.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"to":{"type":"string","minLength":1,"description":"Destinatário — um telefone em formato internacional (+5511988887777) ou um endereço de WhatsApp (5511988887777@s.whatsapp.net, um contato @lid ou um grupo @g.us)."},"from":{"description":"Qual dos seus números de WhatsApp faz o envio — o id dele ou o telefone. Opcional: com um único número conectado, resolvemos para você.","type":"string","minLength":1},"type":{"type":"string","enum":["image","video","audio","document"],"description":"Que tipo de bolha de mídia enviar."},"url":{"description":"URL https pública do arquivo — a melhor opção. Baixamos em streaming e encaminhamos os bytes, então o tamanho do arquivo nunca passa pela sua requisição.","type":"string","format":"uri"},"base64":{"description":"O arquivo em base64, puro ou como URI `data:<mime>;base64,…`. Base64 infla a requisição em um terço, então prefira `url` para qualquer coisa além de arquivos pequenos.","type":"string","minLength":1},"mimeType":{"description":"Sobrescreve o content type detectado, ex.: `image/webp`.","type":"string","minLength":3},"caption":{"description":"Texto mostrado sob a mídia. Só imagens e vídeos — o WhatsApp não tem campo de legenda para documento nem áudio.","type":"string","maxLength":1024},"fileName":{"description":"Documentos: o nome de arquivo que o WhatsApp mostra na bolha.","type":"string","minLength":1,"maxLength":255},"seconds":{"description":"Áudios de voz: a duração, para a bolha mostrar o tamanho certo.","type":"integer","exclusiveMinimum":0,"maximum":600},"skipQueue":{"description":"Envia na hora, em vez de pegar um lugar na fila do número. Só para uma mensagem que a pessoa está esperando neste momento — uma resposta, um código, a confirmação de algo que ela acabou de fazer. Prospecção enviada assim é exatamente o que faz o WhatsApp banir números, que é o motivo de a fila existir. Padrão: desligado.","type":"boolean"},"humanize":{"description":"Se envia como uma pessoa: ficar online, abrir o que ela escreveu por último e mostrar “digitando…” pelo tempo que a mensagem levaria para ser digitada. Ligado por padrão, o que soma alguns segundos à chamada — `false` envia direto e na hora. Configure cada parte por número com update_number.","type":"boolean"}},"required":["to","type"],"additionalProperties":false}}}},"responses":{"201":{"description":"A requisição funcionou.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}},"required":["data"]}}}},"400":{"description":"VALIDATION_ERROR — os erros, nunca os valores."},"401":{"description":"UNAUTHORIZED / INVALID_TOKEN — a chave está ausente ou errada."},"429":{"description":"RATE_LIMIT_EXCEEDED / QUOTA_EXCEEDED — o Retry-After diz quando libera."}}}},"/messages/image":{"post":{"operationId":"send_media_post","summary":"Envie foto, vídeo, áudio ou arquivo","tags":["Messages"],"description":"Envie mídia pelo WhatsApp a partir de uma URL pública ou dados em base64. O `type` escolhe a bolha que o destinatário vê: `image` e `video` aceitam legenda, `document` é um anexo nomeado por `fileName`, e `audio` vira um áudio de voz quando o arquivo é ogg/opus — qualquer outro formato de áudio vai como anexo tocável, porque o WhatsApp não renderiza áudio de voz que não é opus. Arquivos têm teto de 16MB, e `url` ganha de `base64` para arquivos grandes. Consome uma mensagem.\n\nComo todo envio: mídia para alguém que este número nunca procurou vai PARA A FILA em vez de sair, e volta com `status: \"queued\"` e `scheduledAt`. O arquivo é baixado quando chega a vez dele, então a `url` precisa continuar acessível até lá.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"to":{"type":"string","minLength":1,"description":"Destinatário — um telefone em formato internacional (+5511988887777) ou um endereço de WhatsApp (5511988887777@s.whatsapp.net, um contato @lid ou um grupo @g.us)."},"from":{"description":"Qual dos seus números de WhatsApp faz o envio — o id dele ou o telefone. Opcional: com um único número conectado, resolvemos para você.","type":"string","minLength":1},"url":{"description":"URL https pública do arquivo — a melhor opção. Baixamos em streaming e encaminhamos os bytes, então o tamanho do arquivo nunca passa pela sua requisição.","type":"string","format":"uri"},"base64":{"description":"O arquivo em base64, puro ou como URI `data:<mime>;base64,…`. Base64 infla a requisição em um terço, então prefira `url` para qualquer coisa além de arquivos pequenos.","type":"string","minLength":1},"mimeType":{"description":"Sobrescreve o content type detectado, ex.: `image/webp`.","type":"string","minLength":3},"caption":{"description":"Texto mostrado sob a mídia. Só imagens e vídeos — o WhatsApp não tem campo de legenda para documento nem áudio.","type":"string","maxLength":1024},"fileName":{"description":"Documentos: o nome de arquivo que o WhatsApp mostra na bolha.","type":"string","minLength":1,"maxLength":255},"seconds":{"description":"Áudios de voz: a duração, para a bolha mostrar o tamanho certo.","type":"integer","exclusiveMinimum":0,"maximum":600},"skipQueue":{"description":"Envia na hora, em vez de pegar um lugar na fila do número. Só para uma mensagem que a pessoa está esperando neste momento — uma resposta, um código, a confirmação de algo que ela acabou de fazer. Prospecção enviada assim é exatamente o que faz o WhatsApp banir números, que é o motivo de a fila existir. Padrão: desligado.","type":"boolean"},"humanize":{"description":"Se envia como uma pessoa: ficar online, abrir o que ela escreveu por último e mostrar “digitando…” pelo tempo que a mensagem levaria para ser digitada. Ligado por padrão, o que soma alguns segundos à chamada — `false` envia direto e na hora. Configure cada parte por número com update_number.","type":"boolean"}},"required":["to"],"additionalProperties":false}}}},"responses":{"201":{"description":"A requisição funcionou.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}},"required":["data"]}}}},"400":{"description":"VALIDATION_ERROR — os erros, nunca os valores."},"401":{"description":"UNAUTHORIZED / INVALID_TOKEN — a chave está ausente ou errada."},"429":{"description":"RATE_LIMIT_EXCEEDED / QUOTA_EXCEEDED — o Retry-After diz quando libera."}}}},"/messages/video":{"post":{"operationId":"send_media_post","summary":"Envie foto, vídeo, áudio ou arquivo","tags":["Messages"],"description":"Envie mídia pelo WhatsApp a partir de uma URL pública ou dados em base64. O `type` escolhe a bolha que o destinatário vê: `image` e `video` aceitam legenda, `document` é um anexo nomeado por `fileName`, e `audio` vira um áudio de voz quando o arquivo é ogg/opus — qualquer outro formato de áudio vai como anexo tocável, porque o WhatsApp não renderiza áudio de voz que não é opus. Arquivos têm teto de 16MB, e `url` ganha de `base64` para arquivos grandes. Consome uma mensagem.\n\nComo todo envio: mídia para alguém que este número nunca procurou vai PARA A FILA em vez de sair, e volta com `status: \"queued\"` e `scheduledAt`. O arquivo é baixado quando chega a vez dele, então a `url` precisa continuar acessível até lá.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"to":{"type":"string","minLength":1,"description":"Destinatário — um telefone em formato internacional (+5511988887777) ou um endereço de WhatsApp (5511988887777@s.whatsapp.net, um contato @lid ou um grupo @g.us)."},"from":{"description":"Qual dos seus números de WhatsApp faz o envio — o id dele ou o telefone. Opcional: com um único número conectado, resolvemos para você.","type":"string","minLength":1},"url":{"description":"URL https pública do arquivo — a melhor opção. Baixamos em streaming e encaminhamos os bytes, então o tamanho do arquivo nunca passa pela sua requisição.","type":"string","format":"uri"},"base64":{"description":"O arquivo em base64, puro ou como URI `data:<mime>;base64,…`. Base64 infla a requisição em um terço, então prefira `url` para qualquer coisa além de arquivos pequenos.","type":"string","minLength":1},"mimeType":{"description":"Sobrescreve o content type detectado, ex.: `image/webp`.","type":"string","minLength":3},"caption":{"description":"Texto mostrado sob a mídia. Só imagens e vídeos — o WhatsApp não tem campo de legenda para documento nem áudio.","type":"string","maxLength":1024},"fileName":{"description":"Documentos: o nome de arquivo que o WhatsApp mostra na bolha.","type":"string","minLength":1,"maxLength":255},"seconds":{"description":"Áudios de voz: a duração, para a bolha mostrar o tamanho certo.","type":"integer","exclusiveMinimum":0,"maximum":600},"skipQueue":{"description":"Envia na hora, em vez de pegar um lugar na fila do número. Só para uma mensagem que a pessoa está esperando neste momento — uma resposta, um código, a confirmação de algo que ela acabou de fazer. Prospecção enviada assim é exatamente o que faz o WhatsApp banir números, que é o motivo de a fila existir. Padrão: desligado.","type":"boolean"},"humanize":{"description":"Se envia como uma pessoa: ficar online, abrir o que ela escreveu por último e mostrar “digitando…” pelo tempo que a mensagem levaria para ser digitada. Ligado por padrão, o que soma alguns segundos à chamada — `false` envia direto e na hora. Configure cada parte por número com update_number.","type":"boolean"}},"required":["to"],"additionalProperties":false}}}},"responses":{"201":{"description":"A requisição funcionou.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}},"required":["data"]}}}},"400":{"description":"VALIDATION_ERROR — os erros, nunca os valores."},"401":{"description":"UNAUTHORIZED / INVALID_TOKEN — a chave está ausente ou errada."},"429":{"description":"RATE_LIMIT_EXCEEDED / QUOTA_EXCEEDED — o Retry-After diz quando libera."}}}},"/messages/audio":{"post":{"operationId":"send_media_post","summary":"Envie foto, vídeo, áudio ou arquivo","tags":["Messages"],"description":"Envie mídia pelo WhatsApp a partir de uma URL pública ou dados em base64. O `type` escolhe a bolha que o destinatário vê: `image` e `video` aceitam legenda, `document` é um anexo nomeado por `fileName`, e `audio` vira um áudio de voz quando o arquivo é ogg/opus — qualquer outro formato de áudio vai como anexo tocável, porque o WhatsApp não renderiza áudio de voz que não é opus. Arquivos têm teto de 16MB, e `url` ganha de `base64` para arquivos grandes. Consome uma mensagem.\n\nComo todo envio: mídia para alguém que este número nunca procurou vai PARA A FILA em vez de sair, e volta com `status: \"queued\"` e `scheduledAt`. O arquivo é baixado quando chega a vez dele, então a `url` precisa continuar acessível até lá.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"to":{"type":"string","minLength":1,"description":"Destinatário — um telefone em formato internacional (+5511988887777) ou um endereço de WhatsApp (5511988887777@s.whatsapp.net, um contato @lid ou um grupo @g.us)."},"from":{"description":"Qual dos seus números de WhatsApp faz o envio — o id dele ou o telefone. Opcional: com um único número conectado, resolvemos para você.","type":"string","minLength":1},"url":{"description":"URL https pública do arquivo — a melhor opção. Baixamos em streaming e encaminhamos os bytes, então o tamanho do arquivo nunca passa pela sua requisição.","type":"string","format":"uri"},"base64":{"description":"O arquivo em base64, puro ou como URI `data:<mime>;base64,…`. Base64 infla a requisição em um terço, então prefira `url` para qualquer coisa além de arquivos pequenos.","type":"string","minLength":1},"mimeType":{"description":"Sobrescreve o content type detectado, ex.: `image/webp`.","type":"string","minLength":3},"caption":{"description":"Texto mostrado sob a mídia. Só imagens e vídeos — o WhatsApp não tem campo de legenda para documento nem áudio.","type":"string","maxLength":1024},"fileName":{"description":"Documentos: o nome de arquivo que o WhatsApp mostra na bolha.","type":"string","minLength":1,"maxLength":255},"seconds":{"description":"Áudios de voz: a duração, para a bolha mostrar o tamanho certo.","type":"integer","exclusiveMinimum":0,"maximum":600},"skipQueue":{"description":"Envia na hora, em vez de pegar um lugar na fila do número. Só para uma mensagem que a pessoa está esperando neste momento — uma resposta, um código, a confirmação de algo que ela acabou de fazer. Prospecção enviada assim é exatamente o que faz o WhatsApp banir números, que é o motivo de a fila existir. Padrão: desligado.","type":"boolean"},"humanize":{"description":"Se envia como uma pessoa: ficar online, abrir o que ela escreveu por último e mostrar “digitando…” pelo tempo que a mensagem levaria para ser digitada. Ligado por padrão, o que soma alguns segundos à chamada — `false` envia direto e na hora. Configure cada parte por número com update_number.","type":"boolean"}},"required":["to"],"additionalProperties":false}}}},"responses":{"201":{"description":"A requisição funcionou.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}},"required":["data"]}}}},"400":{"description":"VALIDATION_ERROR — os erros, nunca os valores."},"401":{"description":"UNAUTHORIZED / INVALID_TOKEN — a chave está ausente ou errada."},"429":{"description":"RATE_LIMIT_EXCEEDED / QUOTA_EXCEEDED — o Retry-After diz quando libera."}}}},"/messages/document":{"post":{"operationId":"send_media_post","summary":"Envie foto, vídeo, áudio ou arquivo","tags":["Messages"],"description":"Envie mídia pelo WhatsApp a partir de uma URL pública ou dados em base64. O `type` escolhe a bolha que o destinatário vê: `image` e `video` aceitam legenda, `document` é um anexo nomeado por `fileName`, e `audio` vira um áudio de voz quando o arquivo é ogg/opus — qualquer outro formato de áudio vai como anexo tocável, porque o WhatsApp não renderiza áudio de voz que não é opus. Arquivos têm teto de 16MB, e `url` ganha de `base64` para arquivos grandes. Consome uma mensagem.\n\nComo todo envio: mídia para alguém que este número nunca procurou vai PARA A FILA em vez de sair, e volta com `status: \"queued\"` e `scheduledAt`. O arquivo é baixado quando chega a vez dele, então a `url` precisa continuar acessível até lá.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"to":{"type":"string","minLength":1,"description":"Destinatário — um telefone em formato internacional (+5511988887777) ou um endereço de WhatsApp (5511988887777@s.whatsapp.net, um contato @lid ou um grupo @g.us)."},"from":{"description":"Qual dos seus números de WhatsApp faz o envio — o id dele ou o telefone. Opcional: com um único número conectado, resolvemos para você.","type":"string","minLength":1},"url":{"description":"URL https pública do arquivo — a melhor opção. Baixamos em streaming e encaminhamos os bytes, então o tamanho do arquivo nunca passa pela sua requisição.","type":"string","format":"uri"},"base64":{"description":"O arquivo em base64, puro ou como URI `data:<mime>;base64,…`. Base64 infla a requisição em um terço, então prefira `url` para qualquer coisa além de arquivos pequenos.","type":"string","minLength":1},"mimeType":{"description":"Sobrescreve o content type detectado, ex.: `image/webp`.","type":"string","minLength":3},"caption":{"description":"Texto mostrado sob a mídia. Só imagens e vídeos — o WhatsApp não tem campo de legenda para documento nem áudio.","type":"string","maxLength":1024},"fileName":{"description":"Documentos: o nome de arquivo que o WhatsApp mostra na bolha.","type":"string","minLength":1,"maxLength":255},"seconds":{"description":"Áudios de voz: a duração, para a bolha mostrar o tamanho certo.","type":"integer","exclusiveMinimum":0,"maximum":600},"skipQueue":{"description":"Envia na hora, em vez de pegar um lugar na fila do número. Só para uma mensagem que a pessoa está esperando neste momento — uma resposta, um código, a confirmação de algo que ela acabou de fazer. Prospecção enviada assim é exatamente o que faz o WhatsApp banir números, que é o motivo de a fila existir. Padrão: desligado.","type":"boolean"},"humanize":{"description":"Se envia como uma pessoa: ficar online, abrir o que ela escreveu por último e mostrar “digitando…” pelo tempo que a mensagem levaria para ser digitada. Ligado por padrão, o que soma alguns segundos à chamada — `false` envia direto e na hora. Configure cada parte por número com update_number.","type":"boolean"}},"required":["to"],"additionalProperties":false}}}},"responses":{"201":{"description":"A requisição funcionou.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}},"required":["data"]}}}},"400":{"description":"VALIDATION_ERROR — os erros, nunca os valores."},"401":{"description":"UNAUTHORIZED / INVALID_TOKEN — a chave está ausente ou errada."},"429":{"description":"RATE_LIMIT_EXCEEDED / QUOTA_EXCEEDED — o Retry-After diz quando libera."}}}},"/messages/batch":{"post":{"operationId":"send_batch_post","summary":"Envie um texto para vários destinatários","tags":["Messages"],"description":"Envie o mesmo texto para até 25 destinatários numa chamada — uma mensagem, e uma mensagem de cota, por destinatário. A resposta reporta cada destinatário separadamente: um lote em que uns chegam e outros não é o caso normal, não é erro. Se algo sistêmico interrompe a rodada (o número perde a sessão, a cota ou o limite de taxa recusa), os destinatários restantes voltam como `skipped` em vez de ser tentados. Envie eles de novo assim que isso se resolver.\n\n**Enquanto o número espaça os envios, que é o padrão, um lote não envia: ele enfileira.** Cada destinatário volta como `queued` com o seu próprio `scheduledAt`. As mensagens saem uma de cada vez: com minutos de intervalo para quem o número nunca procurou, com segundos para quem ele já conversa. Vinte e cinco mensagens chegando no mesmo segundo é exatamente o padrão pelo qual o WhatsApp restringe números, então o endpoint não faz mais isso. Acompanhe `message.sent` no webhook da conta para pegar os ids, `GET /v1/queue` para ver o que ainda está na fila, e desligue o espaçamento do número se você realmente quiser todas de uma vez. Só em planos pagos.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"to":{"minItems":1,"maxItems":25,"type":"array","items":{"type":"string","minLength":1,"description":"Destinatário — um telefone em formato internacional (+5511988887777) ou um endereço de WhatsApp (5511988887777@s.whatsapp.net, um contato @lid ou um grupo @g.us)."},"description":"Destinatários, até 25. Cada um recebe a própria mensagem; sem duplicatas."},"from":{"description":"Qual dos seus números de WhatsApp faz o envio — o id dele ou o telefone. Opcional: com um único número conectado, resolvemos para você.","type":"string","minLength":1},"text":{"type":"string","minLength":1,"maxLength":4096,"description":"O corpo da mensagem — o mesmo para todos."},"skipQueue":{"description":"Envia na hora, em vez de pegar um lugar na fila do número. Só para uma mensagem que a pessoa está esperando neste momento — uma resposta, um código, a confirmação de algo que ela acabou de fazer. Prospecção enviada assim é exatamente o que faz o WhatsApp banir números, que é o motivo de a fila existir. Padrão: desligado.","type":"boolean"},"humanize":{"description":"Se envia como uma pessoa: ficar online, abrir o que ela escreveu por último e mostrar “digitando…” pelo tempo que a mensagem levaria para ser digitada. Ligado por padrão, o que soma alguns segundos à chamada — `false` envia direto e na hora. Configure cada parte por número com update_number.","type":"boolean"}},"required":["to","text"],"additionalProperties":false}}}},"responses":{"200":{"description":"A requisição funcionou.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}},"required":["data"]}}}},"400":{"description":"VALIDATION_ERROR — os erros, nunca os valores."},"401":{"description":"UNAUTHORIZED / INVALID_TOKEN — a chave está ausente ou errada."},"429":{"description":"RATE_LIMIT_EXCEEDED / QUOTA_EXCEEDED — o Retry-After diz quando libera."}}}},"/messages/location":{"post":{"operationId":"send_location_post","summary":"Envie uma localização","tags":["Messages"],"description":"Envie um pin de mapa pelo WhatsApp. Consome uma mensagem e — como todo envio — entra na fila em vez de sair quando abre uma conversa que este número nunca teve.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"to":{"type":"string","minLength":1,"description":"Destinatário — um telefone em formato internacional (+5511988887777) ou um endereço de WhatsApp (5511988887777@s.whatsapp.net, um contato @lid ou um grupo @g.us)."},"from":{"description":"Qual dos seus números de WhatsApp faz o envio — o id dele ou o telefone. Opcional: com um único número conectado, resolvemos para você.","type":"string","minLength":1},"latitude":{"type":"number","minimum":-90,"maximum":90},"longitude":{"type":"number","minimum":-180,"maximum":180},"name":{"description":"Rótulo mostrado no pin.","type":"string","maxLength":200},"skipQueue":{"description":"Envia na hora, em vez de pegar um lugar na fila do número. Só para uma mensagem que a pessoa está esperando neste momento — uma resposta, um código, a confirmação de algo que ela acabou de fazer. Prospecção enviada assim é exatamente o que faz o WhatsApp banir números, que é o motivo de a fila existir. Padrão: desligado.","type":"boolean"},"humanize":{"description":"Se envia como uma pessoa: ficar online, abrir o que ela escreveu por último e mostrar “digitando…” pelo tempo que a mensagem levaria para ser digitada. Ligado por padrão, o que soma alguns segundos à chamada — `false` envia direto e na hora. Configure cada parte por número com update_number.","type":"boolean"}},"required":["to","latitude","longitude"],"additionalProperties":false}}}},"responses":{"201":{"description":"A requisição funcionou.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}},"required":["data"]}}}},"400":{"description":"VALIDATION_ERROR — os erros, nunca os valores."},"401":{"description":"UNAUTHORIZED / INVALID_TOKEN — a chave está ausente ou errada."},"429":{"description":"RATE_LIMIT_EXCEEDED / QUOTA_EXCEEDED — o Retry-After diz quando libera."}}}},"/messages/contact":{"post":{"operationId":"send_contact_post","summary":"Envie um cartão de contato","tags":["Messages"],"description":"Envie um cartão de contato (vCard) pelo WhatsApp, para o destinatário salvar o número com um toque. Consome uma mensagem e — como todo envio — entra na fila em vez de sair quando abre uma conversa que este número nunca teve.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"to":{"type":"string","minLength":1,"description":"Destinatário — um telefone em formato internacional (+5511988887777) ou um endereço de WhatsApp (5511988887777@s.whatsapp.net, um contato @lid ou um grupo @g.us)."},"from":{"description":"Qual dos seus números de WhatsApp faz o envio — o id dele ou o telefone. Opcional: com um único número conectado, resolvemos para você.","type":"string","minLength":1},"name":{"type":"string","minLength":1,"maxLength":200,"description":"Nome de exibição no cartão."},"vcard":{"type":"string","minLength":1,"description":"O payload vCard, ex.: `BEGIN:VCARD\\nVERSION:3.0\\n…\\nEND:VCARD`."},"skipQueue":{"description":"Envia na hora, em vez de pegar um lugar na fila do número. Só para uma mensagem que a pessoa está esperando neste momento — uma resposta, um código, a confirmação de algo que ela acabou de fazer. Prospecção enviada assim é exatamente o que faz o WhatsApp banir números, que é o motivo de a fila existir. Padrão: desligado.","type":"boolean"},"humanize":{"description":"Se envia como uma pessoa: ficar online, abrir o que ela escreveu por último e mostrar “digitando…” pelo tempo que a mensagem levaria para ser digitada. Ligado por padrão, o que soma alguns segundos à chamada — `false` envia direto e na hora. Configure cada parte por número com update_number.","type":"boolean"}},"required":["to","name","vcard"],"additionalProperties":false}}}},"responses":{"201":{"description":"A requisição funcionou.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}},"required":["data"]}}}},"400":{"description":"VALIDATION_ERROR — os erros, nunca os valores."},"401":{"description":"UNAUTHORIZED / INVALID_TOKEN — a chave está ausente ou errada."},"429":{"description":"RATE_LIMIT_EXCEEDED / QUOTA_EXCEEDED — o Retry-After diz quando libera."}}}},"/otp":{"post":{"operationId":"send_otp_post","summary":"Envie um código de verificação","tags":["OTP"],"description":"Gera um código de 6 dígitos, envia pelo WhatsApp e o devolve. Devolver o código é de propósito: verifique por sua conta, ou entregue ao check_otp e não guarde nada. Os códigos expiram em 5 minutos por padrão, e um número só pode receber um código novo uma vez por minuto. Consome uma mensagem.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"to":{"type":"string","minLength":1,"description":"Destinatário — um telefone em formato internacional (+5511988887777) ou um endereço de WhatsApp (5511988887777@s.whatsapp.net, um contato @lid ou um grupo @g.us)."},"from":{"description":"Qual dos seus números de WhatsApp faz o envio — o id dele ou o telefone. Opcional: com um único número conectado, resolvemos para você.","type":"string","minLength":1},"template":{"description":"Corpo da mensagem. Precisa conter `{code}`; `{minutes}` expande para o prazo de validade. Padrão: “{code} is your verification code. It expires in {minutes} minutes.”","type":"string","minLength":1,"maxLength":1000},"expiresInSeconds":{"description":"Por quanto tempo o código vale. Padrão 300 (5 minutos).","type":"integer","minimum":60,"maximum":3600}},"required":["to"],"additionalProperties":false}}}},"responses":{"201":{"description":"A requisição funcionou.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}},"required":["data"]}}}},"400":{"description":"VALIDATION_ERROR — os erros, nunca os valores."},"401":{"description":"UNAUTHORIZED / INVALID_TOKEN — a chave está ausente ou errada."},"429":{"description":"RATE_LIMIT_EXCEEDED / QUOTA_EXCEEDED — o Retry-After diz quando libera."}}}},"/otp/check":{"post":{"operationId":"check_otp_post","summary":"Confira um código de verificação","tags":["OTP"],"description":"Verifica um código enviado com send_otp e o consome, para ele nunca servir duas vezes. Código errado ou expirado responde 400 OTP_INVALID — erro de propósito, não um `verified: false`, para que uma checagem faltando no chamador nunca pareça sucesso. Cinco chutes errados matam o código. Grátis.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"to":{"type":"string","minLength":1,"description":"Destinatário — um telefone em formato internacional (+5511988887777) ou um endereço de WhatsApp (5511988887777@s.whatsapp.net, um contato @lid ou um grupo @g.us)."},"code":{"type":"string","minLength":4,"maxLength":10,"description":"O código que o usuário digitou."}},"required":["to","code"],"additionalProperties":false}}}},"responses":{"200":{"description":"A requisição funcionou.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}},"required":["data"]}}}},"400":{"description":"VALIDATION_ERROR — os erros, nunca os valores."},"401":{"description":"UNAUTHORIZED / INVALID_TOKEN — a chave está ausente ou errada."},"429":{"description":"RATE_LIMIT_EXCEEDED / QUOTA_EXCEEDED — o Retry-After diz quando libera."}}}},"/numbers":{"get":{"operationId":"list_numbers_get","summary":"Liste os seus números do WhatsApp","tags":["Numbers"],"description":"Todos os números do WhatsApp na conta com o status de conexão. Comece daqui quando não souber de qual número enviar, ou para ver se algum precisa parear de novo. Grátis.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"A requisição funcionou.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}},"required":["data"]}}}},"400":{"description":"VALIDATION_ERROR — os erros, nunca os valores."},"401":{"description":"UNAUTHORIZED / INVALID_TOKEN — a chave está ausente ou errada."},"429":{"description":"RATE_LIMIT_EXCEEDED / QUOTA_EXCEEDED — o Retry-After diz quando libera."}}},"post":{"operationId":"create_number_post","summary":"Adicione um número do WhatsApp","tags":["Numbers"],"description":"Cria um novo slot de número do WhatsApp na conta e o retorna. É o passo um de dois: o slot começa `disconnected` e não envia nada até o pair_number vincular uma conta real do WhatsApp a ele. Quantos podem existir ao mesmo tempo é o que o plano vende. Grátis.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":80,"description":"Um rótulo que você escolhe, ex.: “Suporte” — visível só para você."},"historySync":{"description":"Puxa o histórico de conversas existente no telefone no momento do pareamento. Desligado por padrão: copia conversas que de outro modo nunca veríamos.","type":"boolean"},"age":{"description":"Há quanto tempo esta linha de WhatsApp é usada de verdade — a gente não consegue ver, então pergunta. É o que define quantas conversas NOVAS o número pode começar por dia: `new` (criada há poucos dias) começa em 5/dia e vai subindo, `established` (em uso há mais de um mês) já começa no teto de 20/dia. O padrão é `new`, a resposta segura. Exagerar aqui só custa o seu próprio número.","type":"string","enum":["new","weeks","established"]}},"required":["name"],"additionalProperties":false}}}},"responses":{"201":{"description":"A requisição funcionou.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}},"required":["data"]}}}},"400":{"description":"VALIDATION_ERROR — os erros, nunca os valores."},"401":{"description":"UNAUTHORIZED / INVALID_TOKEN — a chave está ausente ou errada."},"429":{"description":"RATE_LIMIT_EXCEEDED / QUOTA_EXCEEDED — o Retry-After diz quando libera."}}}},"/numbers/check/{phone}":{"get":{"operationId":"check_number_get","summary":"Verifique se um telefone está no WhatsApp","tags":["Numbers"],"description":"Pergunta ao WhatsApp se um telefone tem conta e, tendo, traz a foto de perfil. Celulares brasileiros são checados com e sem o nono dígito, e a resposta informa a forma que realmente bateu. Se não der para falar com o WhatsApp, a resposta assume que sim e define `verified: false` — uma indisponibilidade não pode travar envios para pessoas reais. Grátis.","security":[{"bearerAuth":[]}],"parameters":[{"name":"phone","in":"path","required":true,"description":"O telefone a consultar, ex.: +5511988887777.","schema":{"type":"string","minLength":6,"description":"O telefone a consultar, ex.: +5511988887777."}},{"name":"from","in":"query","required":false,"description":"Qual dos seus números de WhatsApp faz o envio — o id dele ou o telefone. Opcional: com um único número conectado, resolvemos para você.","schema":{"description":"Qual dos seus números de WhatsApp faz o envio — o id dele ou o telefone. Opcional: com um único número conectado, resolvemos para você.","type":"string","minLength":1}}],"responses":{"200":{"description":"A requisição funcionou.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}},"required":["data"]}}}},"400":{"description":"VALIDATION_ERROR — os erros, nunca os valores."},"401":{"description":"UNAUTHORIZED / INVALID_TOKEN — a chave está ausente ou errada."},"429":{"description":"RATE_LIMIT_EXCEEDED / QUOTA_EXCEEDED — o Retry-After diz quando libera."}}}},"/numbers/{id}":{"get":{"operationId":"number_status_get","summary":"Veja o status de um número","tags":["Numbers"],"description":"O estado atual de um número: `connected` (pronto para enviar), `pairing` (esperando a leitura do QR), `disconnected` (perdeu a sessão — pareie de novo) ou `banned` (o WhatsApp restringiu; espere a janela de 24h passar antes de reconectar). Grátis.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Id do número, vem do list_numbers.","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"Id do número, vem do list_numbers."}}],"responses":{"200":{"description":"A requisição funcionou.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}},"required":["data"]}}}},"400":{"description":"VALIDATION_ERROR — os erros, nunca os valores."},"401":{"description":"UNAUTHORIZED / INVALID_TOKEN — a chave está ausente ou errada."},"429":{"description":"RATE_LIMIT_EXCEEDED / QUOTA_EXCEEDED — o Retry-After diz quando libera."}}},"patch":{"operationId":"update_number_patch","summary":"Mude os ajustes de um número","tags":["Numbers"],"description":"Renomeie um número, corrija a idade que o dono declarou ou mude o jeito como ele envia. As duas políticas de envio são a parte interessante:\n\n`pacing` é a fila. Enquanto está ligada — o padrão — uma mensagem para alguém que este número nunca procurou é aceita e segurada, e sai 15–25 minutos depois, uma de cada vez. É a coisa mais eficaz para manter vivo um número não oficial, então só desligue se você mesmo for espaçar os envios.\n\n`humanize` é a cara de um envio: online, lê o que a pessoa escreveu, digita pelo tempo que a resposta é longa. Custa alguns segundos por chamada e compra um número que não parece um script.\n\nTudo é opcional e se junta ao que já está lá. Gratuito.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Id do número, vem do list_numbers.","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"Id do número, vem do list_numbers."}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"description":"O rótulo que você escolheu.","type":"string","minLength":1,"maxLength":80},"age":{"description":"Corrija há quanto tempo esta linha de WhatsApp está em uso real — isso define quantas conversas NOVAS o número pode iniciar por dia. Exagerar aqui só custa o seu próprio número.","type":"string","enum":["new","weeks","established"]},"pacing":{"description":"Como este número espaça as conversas que ele INICIA. Respostas para quem falou primeiro nunca ficam seguradas.","type":"object","properties":{"enabled":{"description":"Coloca as primeiras abordagens na fila em vez de enviar na hora. Ligado por padrão. Desligar torna todo envio imediato — e o ritmo vira problema seu, o que é sério de assumir: rajadas de primeiras abordagens são o que faz o WhatsApp banir números.","type":"boolean"},"minMinutes":{"description":"Menor intervalo entre duas conversas que este número inicia, em minutos. Padrão 15.","type":"integer","minimum":1,"maximum":720},"maxMinutes":{"description":"Maior intervalo, em minutos. Padrão 25. O intervalo real é sorteado entre os dois, porque uma fila que solta uma mensagem exatamente a cada vinte minutos é um metrônomo, e metrônomo é assinatura.","type":"integer","minimum":1,"maximum":720}},"additionalProperties":false},"humanize":{"description":"Quais partes do comportamento humano este número faz em todo envio. Cada uma é um padrão que o WhatsApp consegue ler: uma sessão que nunca fica online, nunca lê nada e responde uma mensagem longa no mesmo instante está se declarando software.","type":"object","properties":{"enabled":{"description":"Se este número envia como uma pessoa. Ligado por padrão.","type":"boolean"},"typing":{"description":"Mostra “digitando…” pelo tempo que a mensagem levaria para ser digitada, antes de enviá-la.","type":"boolean"},"presence":{"description":"Fica online antes de enviar e sai depois.","type":"boolean"},"markRead":{"description":"Põe os tiques azuis no que o destinatário escreveu por último antes de responder. Desligue se não quiser mandar recibo de leitura nas suas conversas.","type":"boolean"}},"additionalProperties":false}},"additionalProperties":false}}}},"responses":{"200":{"description":"A requisição funcionou.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}},"required":["data"]}}}},"400":{"description":"VALIDATION_ERROR — os erros, nunca os valores."},"401":{"description":"UNAUTHORIZED / INVALID_TOKEN — a chave está ausente ou errada."},"429":{"description":"RATE_LIMIT_EXCEEDED / QUOTA_EXCEEDED — o Retry-After diz quando libera."}}},"delete":{"operationId":"delete_number_delete","summary":"Exclua um número","tags":["Numbers"],"description":"Remove um número da conta para sempre, deslogando a sessão do WhatsApp no caminho. Isso libera um slot do limite do plano. Mensagens já enviadas ficam como estão, e o uso que elas custaram continua na conta. Grátis, e sem volta.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Id do número a excluir, vem do list_numbers.","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"Id do número a excluir, vem do list_numbers."}}],"responses":{"200":{"description":"A requisição funcionou.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}},"required":["data"]}}}},"400":{"description":"VALIDATION_ERROR — os erros, nunca os valores."},"401":{"description":"UNAUTHORIZED / INVALID_TOKEN — a chave está ausente ou errada."},"429":{"description":"RATE_LIMIT_EXCEEDED / QUOTA_EXCEEDED — o Retry-After diz quando libera."}}}},"/numbers/{id}/pair":{"post":{"operationId":"pair_number_post","summary":"Pareie um número com o WhatsApp","tags":["Numbers"],"description":"Inicia (ou retoma) a vinculação de uma conta do WhatsApp a um dos seus números. `qr` devolve um QR code para ler em WhatsApp → Aparelhos conectados; `code` devolve um código de vinculação de 8 caracteres para digitar lá no lugar, e precisa do telefone sendo vinculado. Um QR vive ~90 segundos e um novo só pode ser gerado a cada poucos minutos, então chame de novo para consultar: `state: \"pairing\"` sem código ainda quer dizer apenas que está sendo gerado. Grátis.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Id do número a parear, vem do list_numbers.","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"Id do número a parear, vem do list_numbers."}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"mode":{"description":"`qr` (padrão) ou `code` para o código de vinculação digitado.","type":"string","enum":["qr","code"]},"phone":{"description":"Obrigatório com `mode: \"code\"` — o telefone sendo vinculado.","type":"string","minLength":8}},"additionalProperties":false}}}},"responses":{"200":{"description":"A requisição funcionou.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}},"required":["data"]}}}},"400":{"description":"VALIDATION_ERROR — os erros, nunca os valores."},"401":{"description":"UNAUTHORIZED / INVALID_TOKEN — a chave está ausente ou errada."},"429":{"description":"RATE_LIMIT_EXCEEDED / QUOTA_EXCEEDED — o Retry-After diz quando libera."}}}},"/numbers/{id}/unpair":{"post":{"operationId":"unpair_number_post","summary":"Desconecte um número do WhatsApp","tags":["Numbers"],"description":"Desloga a conta do WhatsApp vinculada neste número, mantendo o número em si. Use para vincular outro telefone: um número conectado não pode ser pareado de novo enquanto não for desconectado. Grátis.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Id do número, vem do list_numbers.","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"Id do número, vem do list_numbers."}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":false}}}},"responses":{"200":{"description":"A requisição funcionou.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}},"required":["data"]}}}},"400":{"description":"VALIDATION_ERROR — os erros, nunca os valores."},"401":{"description":"UNAUTHORIZED / INVALID_TOKEN — a chave está ausente ou errada."},"429":{"description":"RATE_LIMIT_EXCEEDED / QUOTA_EXCEEDED — o Retry-After diz quando libera."}}}},"/chats/{phone}/typing":{"post":{"operationId":"typing_post","summary":"Mostre o indicador de digitação","tags":["Messages"],"description":"Mostra (ou limpa) o indicador de “digitando…” num chat. Grátis — não é mensagem. O WhatsApp limpa sozinho depois de alguns segundos, então chame de novo durante uma resposta longa.","security":[{"bearerAuth":[]}],"parameters":[{"name":"phone","in":"path","required":true,"description":"Destinatário — um telefone em formato internacional (+5511988887777) ou um endereço de WhatsApp (5511988887777@s.whatsapp.net, um contato @lid ou um grupo @g.us).","schema":{"type":"string","minLength":1,"description":"Destinatário — um telefone em formato internacional (+5511988887777) ou um endereço de WhatsApp (5511988887777@s.whatsapp.net, um contato @lid ou um grupo @g.us)."}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"from":{"description":"Qual dos seus números de WhatsApp faz o envio — o id dele ou o telefone. Opcional: com um único número conectado, resolvemos para você.","type":"string","minLength":1},"state":{"description":"`composing` mostra o indicador, `paused` limpa. Padrão: composing.","type":"string","enum":["composing","paused"]},"recording":{"description":"Mostra “gravando áudio…” no lugar de “digitando…”.","type":"boolean"}},"additionalProperties":false}}}},"responses":{"200":{"description":"A requisição funcionou.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}},"required":["data"]}}}},"400":{"description":"VALIDATION_ERROR — os erros, nunca os valores."},"401":{"description":"UNAUTHORIZED / INVALID_TOKEN — a chave está ausente ou errada."},"429":{"description":"RATE_LIMIT_EXCEEDED / QUOTA_EXCEEDED — o Retry-After diz quando libera."}}}},"/chats/{phone}/read":{"post":{"operationId":"mark_read_post","summary":"Marque mensagens como lidas","tags":["Messages"],"description":"Coloque os ticks azuis nas mensagens que o seu número recebeu num chat. Grátis. Os ids das mensagens vêm do webhook de entrada.","security":[{"bearerAuth":[]}],"parameters":[{"name":"phone","in":"path","required":true,"description":"Destinatário — um telefone em formato internacional (+5511988887777) ou um endereço de WhatsApp (5511988887777@s.whatsapp.net, um contato @lid ou um grupo @g.us).","schema":{"type":"string","minLength":1,"description":"Destinatário — um telefone em formato internacional (+5511988887777) ou um endereço de WhatsApp (5511988887777@s.whatsapp.net, um contato @lid ou um grupo @g.us)."}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"from":{"description":"Qual dos seus números de WhatsApp faz o envio — o id dele ou o telefone. Opcional: com um único número conectado, resolvemos para você.","type":"string","minLength":1},"messageIds":{"minItems":1,"maxItems":100,"type":"array","items":{"type":"string","minLength":1},"description":"Ids das mensagens recebidas a confirmar."}},"required":["messageIds"],"additionalProperties":false}}}},"responses":{"200":{"description":"A requisição funcionou.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}},"required":["data"]}}}},"400":{"description":"VALIDATION_ERROR — os erros, nunca os valores."},"401":{"description":"UNAUTHORIZED / INVALID_TOKEN — a chave está ausente ou errada."},"429":{"description":"RATE_LIMIT_EXCEEDED / QUOTA_EXCEEDED — o Retry-After diz quando libera."}}}},"/webhooks":{"get":{"operationId":"get_webhook_get","summary":"Veja o seu endpoint de webhook","tags":["Webhooks"],"description":"O endpoint para onde os eventos vão via POST, quais ele assina e se ele segue saudável. `null` quando nenhum está registrado. `disabledReason: \"failures\"` significa que paramos de entregar após uma longa sequência de tentativas mortas — conserte o endpoint e salve de novo (ou envie um teste) para religar. Grátis.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"A requisição funcionou.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}},"required":["data"]}}}},"400":{"description":"VALIDATION_ERROR — os erros, nunca os valores."},"401":{"description":"UNAUTHORIZED / INVALID_TOKEN — a chave está ausente ou errada."},"429":{"description":"RATE_LIMIT_EXCEEDED / QUOTA_EXCEEDED — o Retry-After diz quando libera."}}},"put":{"operationId":"set_webhook_put","summary":"Registre o seu endpoint de webhook","tags":["Webhooks"],"description":"Aponte o whatsapi.sh para uma URL https e comece a receber eventos lá. A resposta traz o segredo de assinatura UMA VEZ, no primeiro registro: guarde — toda entrega é assinada com ele no header `x-whatsapi-signature` (`t=<unix>,v1=<hmac-sha256 of \"<t>.<body>\">`), e é por essa assinatura que você sabe que a requisição é realmente nossa. Chamar de novo atualiza a URL ou os eventos assinados e mantém o mesmo segredo, a menos que você peça a rotação. Salvar também religa um endpoint que tínhamos desligado. Grátis.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri","description":"Para onde os eventos vão via POST, ex.: https://api.yourapp.com/webhooks/whatsapp."},"events":{"minItems":1,"type":"array","items":{"type":"string","enum":["message.created","message.sent","message.failed","message.status","number.connected","number.disconnected","number.logged_out"]},"description":"Quais eventos receber: message.created, message.sent, message.failed, message.status, number.connected, number.disconnected, number.logged_out. Por padrão, todos."},"rotateSecret":{"description":"Gera um novo segredo de assinatura e o retorna — o antigo para de funcionar.","type":"boolean"}},"required":["url"],"additionalProperties":false}}}},"responses":{"200":{"description":"A requisição funcionou.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}},"required":["data"]}}}},"400":{"description":"VALIDATION_ERROR — os erros, nunca os valores."},"401":{"description":"UNAUTHORIZED / INVALID_TOKEN — a chave está ausente ou errada."},"429":{"description":"RATE_LIMIT_EXCEEDED / QUOTA_EXCEEDED — o Retry-After diz quando libera."}}},"post":{"operationId":"set_webhook_post","summary":"Registre o seu endpoint de webhook","tags":["Webhooks"],"description":"Aponte o whatsapi.sh para uma URL https e comece a receber eventos lá. A resposta traz o segredo de assinatura UMA VEZ, no primeiro registro: guarde — toda entrega é assinada com ele no header `x-whatsapi-signature` (`t=<unix>,v1=<hmac-sha256 of \"<t>.<body>\">`), e é por essa assinatura que você sabe que a requisição é realmente nossa. Chamar de novo atualiza a URL ou os eventos assinados e mantém o mesmo segredo, a menos que você peça a rotação. Salvar também religa um endpoint que tínhamos desligado. Grátis.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri","description":"Para onde os eventos vão via POST, ex.: https://api.yourapp.com/webhooks/whatsapp."},"events":{"minItems":1,"type":"array","items":{"type":"string","enum":["message.created","message.sent","message.failed","message.status","number.connected","number.disconnected","number.logged_out"]},"description":"Quais eventos receber: message.created, message.sent, message.failed, message.status, number.connected, number.disconnected, number.logged_out. Por padrão, todos."},"rotateSecret":{"description":"Gera um novo segredo de assinatura e o retorna — o antigo para de funcionar.","type":"boolean"}},"required":["url"],"additionalProperties":false}}}},"responses":{"200":{"description":"A requisição funcionou.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}},"required":["data"]}}}},"400":{"description":"VALIDATION_ERROR — os erros, nunca os valores."},"401":{"description":"UNAUTHORIZED / INVALID_TOKEN — a chave está ausente ou errada."},"429":{"description":"RATE_LIMIT_EXCEEDED / QUOTA_EXCEEDED — o Retry-After diz quando libera."}}},"delete":{"operationId":"delete_webhook_delete","summary":"Remova o seu endpoint de webhook","tags":["Webhooks"],"description":"Para de enviar eventos e esquece o endpoint, o segredo dele e o histórico de entregas. Registrar de novo gera um segredo novo. Grátis.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"A requisição funcionou.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}},"required":["data"]}}}},"400":{"description":"VALIDATION_ERROR — os erros, nunca os valores."},"401":{"description":"UNAUTHORIZED / INVALID_TOKEN — a chave está ausente ou errada."},"429":{"description":"RATE_LIMIT_EXCEEDED / QUOTA_EXCEEDED — o Retry-After diz quando libera."}}}},"/webhooks/test":{"post":{"operationId":"test_webhook_post","summary":"Envie um evento de teste no seu endpoint","tags":["Webhooks"],"description":"Envia um evento `ping` ao seu endpoint registrado agora e espera a resposta, para você conferir a URL e a sua checagem de assinatura sem esperar uma mensagem real. O resultado é o desfecho real: `ok: false` traz o status HTTP que o seu servidor respondeu, ou o motivo de não termos alcançado ele. Um ping bem-sucedido também revive um endpoint que desligamos automaticamente. Grátis.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":false}}}},"responses":{"200":{"description":"A requisição funcionou.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}},"required":["data"]}}}},"400":{"description":"VALIDATION_ERROR — os erros, nunca os valores."},"401":{"description":"UNAUTHORIZED / INVALID_TOKEN — a chave está ausente ou errada."},"429":{"description":"RATE_LIMIT_EXCEEDED / QUOTA_EXCEEDED — o Retry-After diz quando libera."}}}},"/webhooks/deliveries":{"get":{"operationId":"list_webhook_deliveries_get","summary":"Entregas de webhook recentes","tags":["Webhooks"],"description":"As últimas entregas que tentamos, mais novas primeiro — o que enviamos, o que o seu endpoint respondeu e quantas tentativas levou. É a resposta para “o evento nunca chegou”. As entregas ficam guardadas por uma semana. Grátis.","security":[{"bearerAuth":[]}],"parameters":[{"name":"limit","in":"query","required":false,"description":"Quantos retornar, mais novos primeiro. Até 50 (o padrão).","schema":{"description":"Quantos retornar, mais novos primeiro. Até 50 (o padrão).","type":"integer","minimum":1,"maximum":50}}],"responses":{"200":{"description":"A requisição funcionou.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}},"required":["data"]}}}},"400":{"description":"VALIDATION_ERROR — os erros, nunca os valores."},"401":{"description":"UNAUTHORIZED / INVALID_TOKEN — a chave está ausente ou errada."},"429":{"description":"RATE_LIMIT_EXCEEDED / QUOTA_EXCEEDED — o Retry-After diz quando libera."}}}},"/queue":{"get":{"operationId":"list_queued_messages_get","summary":"Veja o que está esperando para sair","tags":["Queue"],"description":"Toda mensagem que está ocupando um lugar na fila de envio de um número, da mais próxima para a mais distante. Uma mensagem cai aqui quando abre uma conversa que o número nunca teve. Ela é aceita e cobrada na hora, e depois é solta com 15–25 minutos de intervalo, para que uma sequência de primeiras abordagens não pareça um disparo. O `scheduledAt` diz quando cada uma sai, e o `message.sent` chega no webhook da conta quando isso acontece. Gratuito.","security":[{"bearerAuth":[]}],"parameters":[{"name":"numberId","in":"query","required":false,"description":"Só a fila deste número. Omita para ver todos os números da conta.","schema":{"description":"Só a fila deste número. Omita para ver todos os números da conta.","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"name":"limit","in":"query","required":false,"description":"Quantas retornar, das mais próximas primeiro. Padrão 200.","schema":{"description":"Quantas retornar, das mais próximas primeiro. Padrão 200.","type":"integer","minimum":1,"maximum":200}}],"responses":{"200":{"description":"A requisição funcionou.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}},"required":["data"]},"example":{"data":[{"id":"9c1f0b7e-8b1a-4a2e-9b0a-1f2e3d4c5b6a","numberId":"a1b2c3d4-0000-0000-0000-000000000000","to":"+5511988887777","kind":"text","preview":"Hi Marina — following up on the quote…","scheduledAt":"2026-08-24T19:18:00.000Z","queuedAt":"2026-08-24T19:00:00.000Z"}]}}}},"400":{"description":"VALIDATION_ERROR — os erros, nunca os valores."},"401":{"description":"UNAUTHORIZED / INVALID_TOKEN — a chave está ausente ou errada."},"429":{"description":"RATE_LIMIT_EXCEEDED / QUOTA_EXCEEDED — o Retry-After diz quando libera."}}}},"/queue/{id}":{"delete":{"operationId":"cancel_queued_message_delete","summary":"Cancele uma mensagem que ainda não saiu","tags":["Queue"],"description":"Tire da fila uma mensagem que ainda está esperando. A cota da mensagem e o limite de conversas novas do dia voltam os dois, então é como se ela nunca tivesse sido pedida. Uma mensagem que já saiu não dá para cancelar — o WhatsApp está com ela — e a resposta diz isso em vez de fingir. O id é o mesmo que a chamada de envio devolveu. Gratuito.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"Id da mensagem na fila — o que a chamada de envio devolveu.","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"Id da mensagem na fila — o que a chamada de envio devolveu."}}],"responses":{"200":{"description":"A requisição funcionou.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}},"required":["data"]}}}},"400":{"description":"VALIDATION_ERROR — os erros, nunca os valores."},"401":{"description":"UNAUTHORIZED / INVALID_TOKEN — a chave está ausente ou errada."},"429":{"description":"RATE_LIMIT_EXCEEDED / QUOTA_EXCEEDED — o Retry-After diz quando libera."}}}},"/usage":{"get":{"operationId":"get_usage_get","summary":"Consulte cota e uso","tags":["Usage"],"description":"Mensagens enviadas no mês contra a cota do plano, hoje contra o limite diário de uso justo, o saldo de créditos restante e a divisão por chave. Leia antes de um envio em lote. Grátis.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"A requisição funcionou.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}},"required":["data"]}}}},"400":{"description":"VALIDATION_ERROR — os erros, nunca os valores."},"401":{"description":"UNAUTHORIZED / INVALID_TOKEN — a chave está ausente ou errada."},"429":{"description":"RATE_LIMIT_EXCEEDED / QUOTA_EXCEEDED — o Retry-After diz quando libera."}}}}},"x-mcp-tools":[{"name":"send_message","title":"Send a WhatsApp message","description":"Send a text message to a phone number over WhatsApp. Counts as one message against the account's monthly quota.\n\n**A message to someone this number has never written to is not sent immediately.** It is accepted, charged and QUEUED: the answer carries `status: \"queued\"` and `scheduledAt`. It leaves 15–25 minutes later, one at a time. That is deliberate. A burst of first approaches is the fastest way to get a WhatsApp number banned, and spacing them out is what separates a number that lasts from one that does not. `message.sent` fires on the account's webhook when it goes out, carrying WhatsApp's id. Use `skipQueue: true` for a message the recipient is waiting for right now, or turn the queue off for the number with update_number.\n\nReplies to people who wrote first are never queued and never spend budget. A first approach also spends one of the number's NEW CONVERSATIONS for the day — the anti-ban ceiling reported as `newConversationsRemaining`. A `sent` answer carries WhatsApp's message id; delivery and read receipts arrive later on the account's webhook, not here.","inputSchema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"to":{"type":"string","minLength":1,"description":"Recipient — a phone number in international format (+5511988887777) or a WhatsApp address (5511988887777@s.whatsapp.net, an @lid contact, or a @g.us group)."},"from":{"description":"Which of your WhatsApp numbers sends this — its id or its phone number. Optional: with a single connected number it is resolved for you.","type":"string","minLength":1},"text":{"type":"string","minLength":1,"maxLength":4096,"description":"The message body."},"linkPreview":{"description":"Render a preview card for the first link in the text. Default: on.","type":"boolean"},"skipQueue":{"description":"Send immediately instead of taking a slot in this number's queue. Only for a message the recipient is expecting right now — a reply, a code, a confirmation of something they just did. Outreach sent this way is exactly what gets WhatsApp numbers banned, which is why the queue exists. Default: off.","type":"boolean"},"humanize":{"description":"Whether to send like a person: come online, open what they last wrote, show “typing…” for as long as the message would take to type. On by default, which adds a few seconds to the call — `false` sends it bare and instantly. Configure the parts per number with update_number.","type":"boolean"}},"required":["to","text"],"additionalProperties":false}},{"name":"send_media","title":"Send a photo, video, voice note or file","description":"Send media over WhatsApp from a public URL or base64 data. `type` picks the bubble the recipient sees: `image` and `video` support a caption, `document` is a file attachment named by `fileName`, and `audio` becomes a voice note when the file is ogg/opus — any other audio format is sent as a playable attachment instead, because WhatsApp will not render a voice note that is not opus. Files are capped at 16MB, and `url` beats `base64` for anything sizeable. Counts as one message.\n\nLike every send: media to someone this number has never written to is QUEUED rather than sent, and comes back with `status: \"queued\"` and `scheduledAt`. The file is fetched when the slot comes up, so a `url` has to still be reachable then.","inputSchema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"to":{"type":"string","minLength":1,"description":"Recipient — a phone number in international format (+5511988887777) or a WhatsApp address (5511988887777@s.whatsapp.net, an @lid contact, or a @g.us group)."},"from":{"description":"Which of your WhatsApp numbers sends this — its id or its phone number. Optional: with a single connected number it is resolved for you.","type":"string","minLength":1},"type":{"type":"string","enum":["image","video","audio","document"],"description":"Which kind of media bubble to send."},"url":{"description":"Public https URL of the file — the better option. We stream the download and forward the bytes, so the size of the file never rides in your request.","type":"string","format":"uri"},"base64":{"description":"The file as base64, bare or as a `data:<mime>;base64,…` URI. Base64 inflates a request by a third, so prefer `url` for anything but small files.","type":"string","minLength":1},"mimeType":{"description":"Overrides the detected content type, e.g. `image/webp`.","type":"string","minLength":3},"caption":{"description":"Text shown under the media. Images and videos only — WhatsApp has no caption field for documents or audio.","type":"string","maxLength":1024},"fileName":{"description":"Documents: the filename WhatsApp shows on the bubble.","type":"string","minLength":1,"maxLength":255},"seconds":{"description":"Voice notes: duration, so the bubble shows the right length.","type":"integer","exclusiveMinimum":0,"maximum":600},"skipQueue":{"description":"Send immediately instead of taking a slot in this number's queue. Only for a message the recipient is expecting right now — a reply, a code, a confirmation of something they just did. Outreach sent this way is exactly what gets WhatsApp numbers banned, which is why the queue exists. Default: off.","type":"boolean"},"humanize":{"description":"Whether to send like a person: come online, open what they last wrote, show “typing…” for as long as the message would take to type. On by default, which adds a few seconds to the call — `false` sends it bare and instantly. Configure the parts per number with update_number.","type":"boolean"}},"required":["to","type"],"additionalProperties":false}},{"name":"send_batch","title":"Send one text to many recipients","description":"Send the same text to up to 25 recipients in one call — one message, and one message's worth of quota, per recipient. The answer reports each recipient separately: a batch where some land and some do not is the normal case, not an error. If something systemic stops the run (the number drops its session, the quota or rate limit refuses) the remaining recipients come back as `skipped` instead of being attempted. Send them again once that is cleared.\n\n**While the number paces its sends, which is the default, a batch does not send: it queues.** Every recipient comes back as `queued` with its own `scheduledAt`. The messages leave one at a time: minutes apart for anyone this number has never written to, seconds apart for people it already talks to. Twenty-five messages arriving in one second is precisely the pattern WhatsApp restricts numbers for, so the endpoint no longer does that. Watch `message.sent` on the account's webhook for the ids, `GET /v1/queue` for what is still waiting, and turn pacing off for the number if you truly want them at once. Paid plans only.","inputSchema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"to":{"minItems":1,"maxItems":25,"type":"array","items":{"type":"string","minLength":1,"description":"Recipient — a phone number in international format (+5511988887777) or a WhatsApp address (5511988887777@s.whatsapp.net, an @lid contact, or a @g.us group)."},"description":"Recipients, up to 25. Each gets its own message; no duplicates."},"from":{"description":"Which of your WhatsApp numbers sends this — its id or its phone number. Optional: with a single connected number it is resolved for you.","type":"string","minLength":1},"text":{"type":"string","minLength":1,"maxLength":4096,"description":"The message body — the same for everyone."},"skipQueue":{"description":"Send immediately instead of taking a slot in this number's queue. Only for a message the recipient is expecting right now — a reply, a code, a confirmation of something they just did. Outreach sent this way is exactly what gets WhatsApp numbers banned, which is why the queue exists. Default: off.","type":"boolean"},"humanize":{"description":"Whether to send like a person: come online, open what they last wrote, show “typing…” for as long as the message would take to type. On by default, which adds a few seconds to the call — `false` sends it bare and instantly. Configure the parts per number with update_number.","type":"boolean"}},"required":["to","text"],"additionalProperties":false}},{"name":"send_location","title":"Send a location pin","description":"Send a map pin over WhatsApp. Counts as one message, and — like every send — is queued rather than sent when it opens a conversation this number has never had.","inputSchema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"to":{"type":"string","minLength":1,"description":"Recipient — a phone number in international format (+5511988887777) or a WhatsApp address (5511988887777@s.whatsapp.net, an @lid contact, or a @g.us group)."},"from":{"description":"Which of your WhatsApp numbers sends this — its id or its phone number. Optional: with a single connected number it is resolved for you.","type":"string","minLength":1},"latitude":{"type":"number","minimum":-90,"maximum":90},"longitude":{"type":"number","minimum":-180,"maximum":180},"name":{"description":"Label shown on the pin.","type":"string","maxLength":200},"skipQueue":{"description":"Send immediately instead of taking a slot in this number's queue. Only for a message the recipient is expecting right now — a reply, a code, a confirmation of something they just did. Outreach sent this way is exactly what gets WhatsApp numbers banned, which is why the queue exists. Default: off.","type":"boolean"},"humanize":{"description":"Whether to send like a person: come online, open what they last wrote, show “typing…” for as long as the message would take to type. On by default, which adds a few seconds to the call — `false` sends it bare and instantly. Configure the parts per number with update_number.","type":"boolean"}},"required":["to","latitude","longitude"],"additionalProperties":false}},{"name":"send_contact","title":"Send a contact card","description":"Send a contact card (vCard) over WhatsApp, so the recipient can save the number with one tap. Counts as one message, and — like every send — is queued rather than sent when it opens a conversation this number has never had.","inputSchema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"to":{"type":"string","minLength":1,"description":"Recipient — a phone number in international format (+5511988887777) or a WhatsApp address (5511988887777@s.whatsapp.net, an @lid contact, or a @g.us group)."},"from":{"description":"Which of your WhatsApp numbers sends this — its id or its phone number. Optional: with a single connected number it is resolved for you.","type":"string","minLength":1},"name":{"type":"string","minLength":1,"maxLength":200,"description":"Display name on the card."},"vcard":{"type":"string","minLength":1,"description":"The vCard payload, e.g. `BEGIN:VCARD\\nVERSION:3.0\\n…\\nEND:VCARD`."},"skipQueue":{"description":"Send immediately instead of taking a slot in this number's queue. Only for a message the recipient is expecting right now — a reply, a code, a confirmation of something they just did. Outreach sent this way is exactly what gets WhatsApp numbers banned, which is why the queue exists. Default: off.","type":"boolean"},"humanize":{"description":"Whether to send like a person: come online, open what they last wrote, show “typing…” for as long as the message would take to type. On by default, which adds a few seconds to the call — `false` sends it bare and instantly. Configure the parts per number with update_number.","type":"boolean"}},"required":["to","name","vcard"],"additionalProperties":false}},{"name":"send_otp","title":"Send a verification code","description":"Generate a 6-digit code, send it over WhatsApp and return it. Returning the code is deliberate: verify it yourself, or hand it back to check_otp and keep nothing. Codes expire in 5 minutes by default and one number can only be sent a new code once a minute. Counts as one message.","inputSchema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"to":{"type":"string","minLength":1,"description":"Recipient — a phone number in international format (+5511988887777) or a WhatsApp address (5511988887777@s.whatsapp.net, an @lid contact, or a @g.us group)."},"from":{"description":"Which of your WhatsApp numbers sends this — its id or its phone number. Optional: with a single connected number it is resolved for you.","type":"string","minLength":1},"template":{"description":"Message body. Must contain `{code}`; `{minutes}` expands to the expiry. Default: “{code} is your verification code. It expires in {minutes} minutes.”","type":"string","minLength":1,"maxLength":1000},"expiresInSeconds":{"description":"How long the code stays valid. Default 300 (5 minutes).","type":"integer","minimum":60,"maximum":3600}},"required":["to"],"additionalProperties":false}},{"name":"check_otp","title":"Check a verification code","description":"Verify a code sent with send_otp and consume it, so it can never be used twice. A wrong or expired code answers 400 OTP_INVALID — deliberately an error, not a `verified: false`, so a missing check at the caller can never read as success. Five wrong guesses kill the code. Free.","inputSchema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"to":{"type":"string","minLength":1,"description":"Recipient — a phone number in international format (+5511988887777) or a WhatsApp address (5511988887777@s.whatsapp.net, an @lid contact, or a @g.us group)."},"code":{"type":"string","minLength":4,"maxLength":10,"description":"The code the user typed."}},"required":["to","code"],"additionalProperties":false}},{"name":"list_numbers","title":"List your WhatsApp numbers","description":"Every WhatsApp number on the account with its connection status. Start here when you do not know which number to send from, or to check whether one needs re-pairing. Free.","inputSchema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{},"additionalProperties":false}},{"name":"create_number","title":"Add a WhatsApp number","description":"Create a new WhatsApp number slot on the account and return it. This is step one of two: the slot starts `disconnected` and cannot send until pair_number links a real WhatsApp account to it. How many can exist at once is what the plan sells. Free.","inputSchema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":80,"description":"A label you choose, e.g. “Support” — only you ever see it."},"historySync":{"description":"Pull the phone's existing chat history on pairing. Off by default: it copies conversations we otherwise never see.","type":"boolean"},"age":{"description":"How long this WhatsApp line has been in real use — we cannot see it, so we ask. It sets how many NEW conversations the number may start per day: `new` (registered days ago) starts at 5/day and climbs, `established` (in use over a month) starts at the 20/day ceiling. Defaults to `new`, the safe answer. Overstating it only costs you the number.","type":"string","enum":["new","weeks","established"]}},"required":["name"],"additionalProperties":false}},{"name":"check_number","title":"Check whether a phone is on WhatsApp","description":"Ask WhatsApp whether a phone number has an account, and get its profile picture when it does. Brazilian mobiles are checked with and without the extra 9 and the answer reports the form that actually matched. If WhatsApp cannot be reached the answer assumes yes and sets `verified: false` — an outage must not block sends to real people. Free.","inputSchema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"phone":{"type":"string","minLength":6,"description":"The phone number to look up, e.g. +5511988887777."},"from":{"description":"Which of your WhatsApp numbers sends this — its id or its phone number. Optional: with a single connected number it is resolved for you.","type":"string","minLength":1}},"required":["phone"],"additionalProperties":false}},{"name":"number_status","title":"Get one number's status","description":"One number's current state: `connected` (ready to send), `pairing` (waiting for a scan), `disconnected` (session dropped — pair it again) or `banned` (WhatsApp restricted it; wait out the 24h window before reconnecting). Free.","inputSchema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"numberId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"Id of the number, from list_numbers."}},"required":["numberId"],"additionalProperties":false}},{"name":"update_number","title":"Change a number's settings","description":"Rename a number, correct the age its owner declared, or change how it sends. The two sending policies are the interesting part:\n\n`pacing` is the queue. While it is on — the default — a message to someone this number has never written to is accepted and held, then sent 15–25 minutes later, one at a time. It is the single most effective thing keeping an unofficial number alive, so turn it off only if you are pacing the sends yourself.\n\n`humanize` is what one send looks like: online, reads what they wrote, types for as long as the reply is long. It costs a few seconds per call and buys a number that does not read as a script.\n\nEverything is optional and merges into what is already there. Free.","inputSchema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"numberId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"Id of the number, from list_numbers."},"name":{"description":"The label you chose.","type":"string","minLength":1,"maxLength":80},"age":{"description":"Correct how long this WhatsApp line has been in real use — it sets how many NEW conversations the number may start per day. Overstating it only costs you the number.","type":"string","enum":["new","weeks","established"]},"pacing":{"description":"How this number spaces the conversations it STARTS. Replies to people who wrote first are never held.","type":"object","properties":{"enabled":{"description":"Queue first approaches instead of sending them straight away. On by default. Turning it off makes every send immediate — and makes the pacing your problem, which is a real thing to take on: bursts of first approaches are what WhatsApp bans numbers for.","type":"boolean"},"minMinutes":{"description":"Shortest gap between two conversations this number starts, in minutes. Default 15.","type":"integer","minimum":1,"maximum":720},"maxMinutes":{"description":"Longest gap, in minutes. Default 25. The real gap is picked at random between the two, because a queue that fires exactly every twenty minutes is a metronome, and a metronome is a signature.","type":"integer","minimum":1,"maximum":720}},"additionalProperties":false},"humanize":{"description":"Which parts of the human act this number performs on every send. Each one is a pattern WhatsApp can read: a session that is never online, never reads and answers a long message instantly is describing itself as software.","type":"object","properties":{"enabled":{"description":"Send like a person at all. On by default.","type":"boolean"},"typing":{"description":"Show “typing…” for as long as the message would take to type, before sending it.","type":"boolean"},"presence":{"description":"Come online before sending, go offline after.","type":"boolean"},"markRead":{"description":"Put blue ticks on what the recipient last wrote before answering it. Turn this off if read receipts on your own chats are not wanted.","type":"boolean"}},"additionalProperties":false}},"required":["numberId"],"additionalProperties":false}},{"name":"pair_number","title":"Pair a number with WhatsApp","description":"Start (or resume) linking a WhatsApp account to one of your numbers. `qr` returns a QR code to scan from WhatsApp → Linked devices; `code` returns an 8-character linking code to type there instead, and needs the phone number being linked. A QR lives ~90 seconds and a new one can only be minted every few minutes, so call again to poll: `state: \"pairing\"` with no code yet simply means it is still being minted. Free.","inputSchema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"numberId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"Id of the number to pair, from list_numbers."},"mode":{"description":"`qr` (default) or `code` for the type-in linking code.","type":"string","enum":["qr","code"]},"phone":{"description":"Required with `mode: \"code\"` — the phone number being linked.","type":"string","minLength":8}},"required":["numberId"],"additionalProperties":false}},{"name":"typing","title":"Show the typing indicator","description":"Show (or clear) the “typing…” indicator in a chat. Free — it is not a message. WhatsApp clears it on its own after a few seconds, so call it again for a long reply.","inputSchema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"to":{"type":"string","minLength":1,"description":"Recipient — a phone number in international format (+5511988887777) or a WhatsApp address (5511988887777@s.whatsapp.net, an @lid contact, or a @g.us group)."},"from":{"description":"Which of your WhatsApp numbers sends this — its id or its phone number. Optional: with a single connected number it is resolved for you.","type":"string","minLength":1},"state":{"description":"`composing` shows the indicator, `paused` clears it. Default: composing.","type":"string","enum":["composing","paused"]},"recording":{"description":"Show “recording audio…” instead of “typing…”.","type":"boolean"}},"required":["to"],"additionalProperties":false}},{"name":"mark_read","title":"Mark messages as read","description":"Put blue ticks on messages your number received in a chat. Free. Message ids come from the inbound webhook.","inputSchema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"to":{"type":"string","minLength":1,"description":"Recipient — a phone number in international format (+5511988887777) or a WhatsApp address (5511988887777@s.whatsapp.net, an @lid contact, or a @g.us group)."},"from":{"description":"Which of your WhatsApp numbers sends this — its id or its phone number. Optional: with a single connected number it is resolved for you.","type":"string","minLength":1},"messageIds":{"minItems":1,"maxItems":100,"type":"array","items":{"type":"string","minLength":1},"description":"Ids of the received messages to acknowledge."}},"required":["to","messageIds"],"additionalProperties":false}},{"name":"get_webhook","title":"Get your webhook endpoint","description":"The endpoint events are being POSTed to, which ones it is subscribed to, and whether it is still healthy. `null` when none is registered. `disabledReason: \"failures\"` means we stopped delivering after a long run of dead attempts — fix the endpoint and set it again (or fire a test) to switch it back on. Free.","inputSchema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{},"additionalProperties":false}},{"name":"set_webhook","title":"Register your webhook endpoint","description":"Point whatsapi.sh at an https URL and start receiving events there. The answer carries the signing secret ONCE, on first registration: keep it — every delivery is signed with it in the `x-whatsapi-signature` header (`t=<unix>,v1=<hmac-sha256 of \"<t>.<body>\">`), and that signature is how you know a request is really from us. Calling this again updates the URL or the subscription and keeps the same secret unless you ask to rotate it. Saving also re-enables an endpoint we had disabled. Free.","inputSchema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"url":{"type":"string","format":"uri","description":"Where to POST events, e.g. https://api.yourapp.com/webhooks/whatsapp."},"events":{"minItems":1,"type":"array","items":{"type":"string","enum":["message.created","message.sent","message.failed","message.status","number.connected","number.disconnected","number.logged_out"]},"description":"Which events to receive: message.created, message.sent, message.failed, message.status, number.connected, number.disconnected, number.logged_out. Defaults to all of them."},"rotateSecret":{"description":"Mint a new signing secret and return it — the old one stops working.","type":"boolean"}},"required":["url"],"additionalProperties":false}},{"name":"test_webhook","title":"Fire a test event at your endpoint","description":"Send a `ping` event to your registered endpoint right now and wait for the answer, so you can verify the URL and your signature check without waiting for a real message. The result is the actual outcome: `ok: false` carries the HTTP status your server answered, or why we could not reach it. A successful ping also revives an endpoint we had auto-disabled. Free.","inputSchema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{},"additionalProperties":false}},{"name":"list_queued_messages","title":"See what is waiting to be sent","description":"Every message currently holding a slot in a number's send queue, soonest first. Messages land here when they open a conversation the number has never had. They are accepted and charged straight away, then released 15–25 minutes apart, so a run of first approaches does not read as a broadcast. `scheduledAt` says when each one leaves, and `message.sent` fires on the account's webhook when it does. Free.","inputSchema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"numberId":{"description":"Only this number's queue. Omit for every number on the account.","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"limit":{"description":"How many to return, soonest first. Default 200.","type":"integer","minimum":1,"maximum":200}},"additionalProperties":false}},{"name":"cancel_queued_message","title":"Cancel a message that hasn't been sent yet","description":"Take a waiting message back out of the queue. Its message quota and the day's new-conversation budget are both handed back, so it is as if it had never been asked for. A message that has already left cannot be cancelled — WhatsApp has it — and the answer says so rather than pretending. The id is the one the send call returned. Free.","inputSchema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"Id of the queued message — what the send call answered with."}},"required":["id"],"additionalProperties":false}},{"name":"get_usage","title":"Check quota and usage","description":"Messages sent this month against the plan quota, today against the daily fair-use cap, the leftover credit balance, and the per-key breakdown. Read this before a bulk send. Free.","inputSchema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{},"additionalProperties":false}}]}