Enviar mídia (imagem, vídeo, áudio ou documento)
POST /send/media
Envia diferentes tipos de mídia para um contato, grupo ou canal/newsletter. Suporta URLs ou arquivos base64.
Tipos de Mídia Suportados
image: Imagens (JPG preferencialmente)video: Vídeos (apenas MP4)videoplay: Vídeo com comportamento visual de autoplay/loop no WhatsAppdocument: Documentos (PDF, DOCX, XLSX, etc)audio: Áudio comum (MP3 ou OGG)myaudio: Mensagem de voz (alternativa ao PTT)ptt: Mensagem de voz (Push-to-Talk)ptv: Mensagem de vídeo (Push-to-Video)sticker: Figurinha/Sticker
Recursos Específicos
- Upload por URL ou base64
- Caption/legenda opcional com suporte a placeholders
- Nome personalizado para documentos (
docName) - Geração automática de thumbnails para imagens e vídeos quando
thumbnailnão é informado - Compressão otimizada conforme o tipo
viewOncerecomendado para mídia compatível
Envio para Newsletter
Para enviar mídia para um canal, use o mesmo campo number, mas informe o JID completo do canal:
- Exemplo:
120363123456789012@newsletter
{
"number": "120363123456789012@newsletter",
"type": "image",
"file": "https://exemplo.com/foto.jpg",
"text": "Imagem publicada no canal"
}
Campos Comuns
Este endpoint suporta todos os campos opcionais comuns documentados na tag "Enviar Mensagem", incluindo:
delay, readchat, readmessages, replyid, mentions, forward, track_source, track_id, placeholders e envio para grupos.
Exemplos Básicos
Visualização Única (viewOnce)
O campo viewOnce é recomendado quando quiser mídia de visualização única e hoje produz efeito para os tipos:
image, video, videoplay, ptv, audio, myaudio e ptt.
Para document, sticker e demais endpoints de envio, o campo é ignorado silenciosamente.
Thumbnail personalizado
Use thumbnail em image, video, videoplay, ptv ou
document. Aceita URL HTTP/HTTPS, Data URL ou base64 de imagem com até
1 MiB e 4096 px por dimensão. A API converte para JPEG e prioriza essa
imagem em relação à miniatura automática. Para documentos, envie uma
imagem de pelo menos 480 px para uma prévia mais nítida no WhatsApp Web.
Documentos sem thumbnail não recebem miniatura automática.
Ao reenviar o mesmo documento, reutilize a mesma miniatura: o WhatsApp pode associar a prévia ao conteúdo do arquivo também em mensagens antigas.
Imagem Simples
{
"number": "5511999999999",
"type": "image",
"file": "https://exemplo.com/foto.jpg"
}
Documento com Nome
{
"number": "5511999999999",
"type": "document",
"file": "https://exemplo.com/contrato.pdf",
"docName": "Contrato.pdf",
"text": "Segue o documento solicitado"
}
Autenticação
[
{
"token": []
}
]
{
"token": {
"name": "token",
"type": "apiKey",
"in": "header"
}
}
Corpo da requisição
{
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"number": {
"type": "string",
"description": "ID do chat para o qual a mensagem será enviada. Pode ser um número de telefone em formato internacional, um ID de grupo (`@g.us`), um ID de usuário (com `@s.whatsapp.net` ou `@lid`) ou um ID de canal/newsletter (`@newsletter`).",
"example": "5511999999999"
},
"type": {
"type": "string",
"description": "Tipo de mídia (image, video, videoplay, document, audio, myaudio, ptt, ptv, sticker)",
"enum": [
"image",
"video",
"videoplay",
"document",
"audio",
"myaudio",
"ptt",
"ptv",
"sticker"
],
"example": "image"
},
"file": {
"type": "string",
"description": "URL ou base64 do arquivo",
"example": "https://exemplo.com/imagem.jpg"
},
"text": {
"type": "string",
"description": "Texto descritivo (caption) - aceita placeholders",
"example": "Veja esta foto!"
},
"docName": {
"type": "string",
"description": "Nome do arquivo (apenas para documents)",
"example": "relatorio.pdf"
},
"thumbnail": {
"type": "string",
"description": "URL HTTP/HTTPS, Data URL ou base64 de imagem para image, video, videoplay, ptv e document. Até 1 MiB e 4096 px por dimensão. Tem prioridade sobre a miniatura automática; documentos sem este campo não recebem miniatura automática.",
"example": "https://exemplo.com/thumb.jpg"
},
"mimetype": {
"type": "string",
"description": "MIME type do arquivo (opcional, detectado automaticamente)",
"example": "application/pdf"
},
"replyid": {
"type": "string",
"description": "ID da mensagem para responder",
"example": "3EB0538DA65A59F6D8A251"
},
"mentions": {
"type": "string",
"description": "Números para mencionar, separados por vírgula (só em grupos). Para mencionar todos, use all ou inclua @all ou @todos no texto da mensagem",
"example": "5511999999999,5511888888888"
},
"readchat": {
"type": "boolean",
"description": "Marca conversa como lida após envio",
"example": true
},
"readmessages": {
"type": "boolean",
"description": "Marca últimas mensagens recebidas como lidas",
"example": true
},
"delay": {
"type": "integer",
"description": "Atraso em milissegundos antes do envio, durante o atraso aparecerá 'Digitando...' ou 'Gravando áudio...'",
"example": 1000
},
"forward": {
"type": "boolean",
"description": "Marca a mensagem como encaminhada no WhatsApp",
"example": true
},
"track_source": {
"type": "string",
"description": "Origem do rastreamento da mensagem",
"example": "chatwoot"
},
"track_id": {
"type": "string",
"description": "ID para rastreamento da mensagem (aceita valores duplicados)",
"example": "msg_123456789"
},
"async": {
"type": "boolean",
"description": "Se true, envia a mensagem de forma assíncrona via fila interna",
"example": false
},
"viewOnce": {
"type": "boolean",
"description": "Recomendado para mídia com visualização única em tipos compatíveis (`image`, `video`, `videoplay`, `ptv`, `audio`, `myaudio`, `ptt`). Em tipos não compatíveis, o campo é ignorado silenciosamente.",
"example": false
}
},
"required": [
"number",
"type",
"file"
]
},
"examples": {
"image": {
"summary": "Imagem",
"description": "Envio de imagem simples",
"value": {
"number": "5511999999999",
"type": "image",
"file": "https://exemplo.com/foto.jpg"
}
},
"imageWithCaption": {
"summary": "Imagem com legenda",
"description": "Imagem com texto descritivo",
"value": {
"number": "5511999999999",
"type": "image",
"file": "https://exemplo.com/foto.jpg",
"text": "Veja esta foto!"
}
},
"imageViewOnce": {
"summary": "Imagem view once",
"description": "Imagem enviada como visualização única",
"value": {
"number": "5511999999999",
"type": "image",
"file": "https://exemplo.com/foto.jpg",
"text": "Abra uma vez",
"viewOnce": true
}
},
"document": {
"summary": "Documento",
"description": "Documento PDF com nome personalizado",
"value": {
"number": "5511999999999",
"type": "document",
"file": "https://exemplo.com/contrato.pdf",
"docName": "Contrato.pdf",
"text": "Segue o documento solicitado"
}
},
"audio": {
"summary": "Mensagem de voz",
"description": "Arquivo de áudio como mensagem de voz",
"value": {
"number": "5511999999999",
"type": "ptt",
"file": "https://exemplo.com/audio.ogg"
}
},
"video": {
"summary": "Vídeo",
"description": "Arquivo de vídeo com legenda",
"value": {
"number": "5511999999999",
"type": "video",
"file": "https://exemplo.com/video.mp4",
"text": "Confira este vídeo!"
}
},
"videoplay": {
"summary": "Vídeo com autoplay",
"description": "Vídeo MP4 enviado com comportamento visual de autoplay/loop no WhatsApp",
"value": {
"number": "5511999999999",
"type": "videoplay",
"file": "https://exemplo.com/video.mp4",
"text": "Confira este vídeo"
}
},
"ptv": {
"summary": "Mensagem de vídeo",
"description": "Arquivo de vídeo como mensagem de vídeo",
"value": {
"number": "5511999999999",
"type": "ptv",
"file": "https://exemplo.com/video.mp4"
}
},
"sticker": {
"summary": "Figurinha",
"description": "Envio de figurinha/sticker",
"value": {
"number": "5511999999999",
"type": "sticker",
"file": "https://exemplo.com/sticker.webp"
}
},
"newsletterImage": {
"summary": "Imagem para newsletter",
"description": "Publica uma imagem em um canal usando o JID completo `@newsletter`.",
"value": {
"number": "120363123456789012@newsletter",
"type": "image",
"file": "https://exemplo.com/foto.jpg",
"text": "Imagem publicada no canal"
}
},
"newsletterDocument": {
"summary": "Documento para newsletter",
"description": "Publica um documento em um canal usando o JID completo `@newsletter`.",
"value": {
"number": "120363123456789012@newsletter",
"type": "document",
"file": "https://exemplo.com/contrato.pdf",
"docName": "Contrato.pdf",
"text": "Documento publicado no canal"
}
}
}
}
}
}
Respostas
{
"200": {
"description": "Mídia enviada com sucesso",
"content": {
"application/json": {
"schema": {
"allOf": [
{
"$ref": "#/components/schemas/Message"
},
{
"type": "object",
"properties": {
"response": {
"type": "object",
"properties": {
"status": {
"type": "string",
"example": "success"
},
"message": {
"type": "string",
"example": "Media sent successfully"
},
"fileUrl": {
"type": "string",
"example": "https://mmg.whatsapp.net/..."
}
}
}
}
}
]
}
}
}
},
"400": {
"description": "Requisição inválida",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string",
"example": "Invalid media type or file format"
}
}
}
}
}
},
"401": {
"description": "Não autorizado",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string",
"example": "Invalid token"
}
}
}
}
}
},
"413": {
"description": "Arquivo muito grande",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string",
"example": "File size exceeds limit"
}
}
}
}
}
},
"415": {
"description": "Formato de mídia não suportado",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string",
"example": "Unsupported media format"
}
}
}
}
}
},
"500": {
"description": "Erro interno do servidor",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string",
"example": "Failed to upload media"
}
}
}
}
}
}
}
#/components/schemas/Message
{
"type": "object",
"description": "Representa uma mensagem trocada no sistema",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"description": "ID único interno da mensagem (formato r + 7 caracteres hex aleatórios)"
},
"messageid": {
"type": "string",
"description": "ID original da mensagem no provedor"
},
"chatid": {
"type": "string",
"description": "ID da conversa relacionada"
},
"sender": {
"type": "string",
"description": "ID do remetente da mensagem"
},
"senderName": {
"type": "string",
"description": "Nome exibido do remetente"
},
"isGroup": {
"type": "boolean",
"description": "Indica se é uma mensagem de grupo",
"default": false
},
"fromMe": {
"type": "boolean",
"description": "Indica se a mensagem foi enviada pelo usuário",
"default": false
},
"messageType": {
"type": "string",
"description": "Tipo de conteúdo da mensagem"
},
"source": {
"type": "string",
"description": "Plataforma de origem da mensagem"
},
"messageTimestamp": {
"type": "integer",
"description": "Timestamp original da mensagem em milissegundos",
"default": 0
},
"status": {
"type": "string",
"description": "Status do ciclo de vida da mensagem.\nExemplos comuns: `Queued`, `Canceled`, `Failed`, `Sent`, `Delivered`, `Read`.\nEm mensagem de grupo, segue o participante mais adiantado: `Delivered` quando pelo menos um recebeu, `Read` quando pelo menos um leu e `Played` quando pelo menos um ouviu.\n"
},
"text": {
"type": "string",
"description": "Texto original da mensagem",
"default": ""
},
"quoted": {
"type": "string",
"description": "ID da mensagem citada/respondida",
"default": ""
},
"edited": {
"type": "string",
"description": "Histórico de edições da mensagem",
"default": ""
},
"reaction": {
"type": "string",
"description": "ID da mensagem reagida",
"default": ""
},
"vote": {
"type": "string",
"description": "Dados de votação de enquete e listas",
"default": ""
},
"convertOptions": {
"type": "string",
"description": "Conversão de opções da mensagem, lista, enquete e botões",
"default": ""
},
"buttonOrListid": {
"type": "string",
"description": "ID do botão ou item de lista selecionado",
"default": ""
},
"owner": {
"type": "string",
"description": "Dono da mensagem",
"default": ""
},
"error": {
"type": "string",
"description": "Mensagem de erro caso o envio tenha falhado",
"default": ""
},
"content": {
"description": "Conteúdo bruto da mensagem (JSON serializado ou texto)",
"oneOf": [
{
"type": "object",
"additionalProperties": true
},
{
"type": "string",
"description": "Texto bruto quando não for JSON"
}
]
},
"wasSentByApi": {
"type": "boolean",
"description": "Indica se a mensagem foi enviada via API"
},
"pinned": {
"type": "boolean",
"description": "Mensagem fixada na conversa (fixar e desafixar chegam também em `messages_update`, tipos `Pinned` e `Unpinned`)"
},
"sendFunction": {
"type": "string",
"description": "Função usada para enviar a mensagem (quando enviada via API)"
},
"sendPayload": {
"description": "Payload usado no envio quando disponível. Dados de mídia em base64 são omitidos.",
"oneOf": [
{
"type": "object",
"additionalProperties": true
},
{
"type": "string",
"description": "Texto bruto quando não for JSON"
}
]
},
"fileURL": {
"type": "string",
"description": "URL ou referência de arquivo da mensagem"
},
"callPeer": {
"type": "object",
"description": "Contato conhecido associado a uma ligação, quando disponível em `messageType: call`.",
"properties": {
"jid": {
"type": "string"
},
"name": {
"type": "string"
},
"imagePreviewUrl": {
"type": "string"
}
}
},
"send_folder_id": {
"type": "string",
"description": "Pasta associada ao envio (quando aplicável)"
},
"track_source": {
"type": "string",
"description": "Origem de rastreamento"
},
"track_id": {
"type": "string",
"description": "ID de rastreamento (pode repetir)"
},
"ai_metadata": {
"type": "object",
"description": "Registro de uma rodada da IA. O completo (pedido ao modelo, resposta e `outcome`) fica uma vez, na última mensagem do contato que a rodada respondeu, também quando nada saiu (erro, resposta descartada). Cada mensagem enviada pela IA leva só `agent_id` e `turn` (o `id` dessa mensagem do contato).",
"properties": {
"agent_id": {
"type": "string",
"description": "ID do agente de IA responsável"
},
"turn": {
"type": "string",
"description": "Na mensagem enviada pela IA: o `id` da mensagem do contato onde está o registro completo da rodada."
},
"flow_id": {
"type": "string",
"description": "Mensagem enviada por um fluxo: o `id` do fluxo. A mensagem enviada pela IA traz o `agent_id`."
},
"request": {
"type": "object",
"description": "Dados da requisição à API de IA",
"properties": {
"messages": {
"type": "array",
"description": "Histórico de mensagens enviadas para a API"
},
"tools": {
"type": "array",
"description": "Ferramentas disponíveis para o agente"
},
"options": {
"type": "object",
"description": "Opções de configuração da API",
"properties": {
"model": {
"type": "string"
},
"temperature": {
"type": "number"
},
"maxTokens": {
"type": "integer"
},
"topP": {
"type": "number"
},
"frequencyPenalty": {
"type": "number"
},
"presencePenalty": {
"type": "number"
}
}
}
}
},
"response": {
"type": "object",
"description": "Resposta da API de IA",
"properties": {
"choices": {
"type": "array",
"description": "Resultados retornados pela API"
},
"toolResults": {
"type": "array",
"description": "Resultados da execução de ferramentas"
},
"error": {
"type": "string",
"description": "Mensagem de erro, se houver"
}
}
},
"outcome": {
"type": "object",
"description": "O que a rodada fez de fato (só no registro completo).",
"properties": {
"status": {
"type": "string",
"enum": [
"sent",
"cancelled",
"error",
"empty"
],
"description": "`sent`: enviou algo; `cancelled`: descartada (a conversa pausou, um fluxo começou ou bateu o limite de respostas por hora); `error`: o provedor falhou; `empty`: nada a enviar."
},
"texts": {
"type": "integer",
"description": "Mensagens de texto enviadas."
},
"audio": {
"type": "boolean",
"description": "Respondeu em áudio."
},
"menus": {
"type": "integer",
"description": "Menus enviados."
},
"files": {
"type": "integer",
"description": "Arquivos (mensagens cadastradas) enviados."
},
"handoff": {
"type": "string",
"description": "`chamar_humano`: o resumo para quem atender."
},
"lead": {
"type": "array",
"items": {
"type": "string"
},
"description": "`atualizar_lead`: o que foi gravado no CRM (`lead_email = ana@exemplo.com; column = Agendado`)."
},
"detail": {
"type": "string",
"description": "Por que foi descartada, ou o erro."
}
}
}
}
},
"sender_pn": {
"description": "JID PN resolvido do remetente (quando disponível)",
"oneOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"sender_lid": {
"description": "LID original do remetente (quando disponível)",
"oneOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"sender_image_preview_url": {
"type": "string",
"format": "uri",
"description": "URL temporária de preview do remetente, quando conhecida. A hidratação desta versão preenche mensagens recebidas em grupos; o campo pode ser omitido. Não provoca consulta de foto ao WhatsApp na listagem."
}
}
}