Enviar e receber
Mídia
Imagem, áudio, vídeo e documento passam pelo mesmo
POST /v1/messages. O binário nunca trafega no recurso da
mensagem: o que você recebe são metadados e uma URL assinada e temporária.
Enviar mídia
Troque type e use o bloco media no lugar de
text.
{
"numberId": "num_4711",
"to": { "phone": "+5511999990000" },
"type": "document",
"media": {
"url": "https://cdn.seuproduto.com.br/contratos/2026-08/exemplo.pdf",
"filename": "contrato.pdf",
"caption": "Segue o contrato para assinatura."
}
}
{
"numberId": "num_4711",
"conversationId": "conv_991",
"type": "audio",
"media": {
"base64": "SUQzBAAAAAAA...",
"mimetype": "audio/ogg",
"ptt": true
}
}
| Campo | Descrição |
|---|---|
url |
URL http(s) pública do arquivo. Mutuamente exclusiva com base64. |
base64 |
O arquivo embutido. Exige mimetype. Mutuamente exclusiva com url. |
mimetype |
No formato tipo/subtipo. Obrigatório quando você usa base64. |
filename |
Nome apresentado ao destinatário. Até 255 caracteres. |
caption |
Legenda exibida junto da mídia. Até 1024 caracteres. |
ptt |
Envia o áudio como nota de voz. Só se aplica a type: audio, e só em canal que declare audioPtt: true. |
Arquivo maior que isso precisa ir por url. Base64 ainda infla o
tamanho em cerca de um terço — para qualquer coisa que não seja um áudio
curto, url é o caminho melhor.
Confira a capacidade antes
Cada canal declara quais tipos de mídia aceita e se suporta nota de voz.
Consulte GET /v1/channels e leia midia e
audioPtt. Enviar algo que o canal não declara devolve
422 CHANNEL_CAPABILITY_UNSUPPORTED.
Receber mídia
Numa mensagem recebida, o bloco media traz os metadados e — se o
arquivo já estiver disponível — uma URL assinada:
{
"id": "msg_18291",
"conversationId": "conv_991",
"numberId": "num_4711",
"direction": "inbound",
"type": "image",
"status": "received",
"media": {
"mimetype": "image/jpeg",
"filename": "foto.jpg",
"size": 184320,
"caption": "É esse o comprovante?",
"url": "https://…<assinada e temporária>",
"urlExpiresAt": "2026-08-13T19:12:03.000Z",
"pending": false
}
}
url
Ela é assinada e temporária, gerada sob demanda a cada
leitura. Um link guardado no seu banco vira um 403 silencioso
no dia seguinte — a imagem simplesmente para de carregar na sua interface,
sem erro nenhum no seu log.
Baixe o arquivo para o seu próprio armazenamento assim que
receber, ou peça a URL de novo com
GET /v1/messages/{id} na hora de exibir. O campo
urlExpiresAt diz quando ela deixa de valer.
Quando o arquivo ainda não chegou
Falha de mídia nunca derruba a mensagem. Se os metadados
chegaram mas o binário não, a mensagem é persistida normalmente — texto,
legenda e remetente completos — com media.pending: true e sem
url.
"media": {
"mimetype": "application/pdf",
"filename": "comprovante.pdf",
"pending": true
}
Isso é deliberado: descartar a mensagem inteira porque um anexo falhou faria você perder o que o cliente escreveu. O anexo é recuperável; a mensagem perdida não.
Rebaixar o arquivo
POST /v1/messages/{id}/media/redownload
curl -X POST \
-H "x-api-key: $NUNTIS_API_KEY" \
https://api.nuntis.com.br/v1/messages/msg_18291/media/redownload
A resposta é o recurso completo da mensagem, com media.url
preenchida quando a recuperação deu certo.
| Situação | Resposta |
|---|---|
| Mídia recuperada | 200 com media.url e pending: false. |
| Mídia já estava disponível | 200 com o recurso como está. É idempotente — pedir de novo não é erro. |
| Mensagem sem mídia | 400 VALIDATION_FAILED. |
| Canal ou armazenamento indisponível agora | 503 CHANNEL_UNREACHABLE, com retryable: true. Tente de novo com backoff. |
A rota devolve o recurso da mensagem, com uma URL nova — não os bytes do arquivo. Baixe pela URL devolvida.
Fluxo recomendado
- Chega
message.receivedno seu webhook. - Se
media.pendingforfalse, baixe pelaurle guarde no seu armazenamento. - Se for
true, agende umredownloadcom backoff em vez de tentar em laço. - Na sua interface, sirva sempre do seu armazenamento — nunca da URL do Nuntis.