Mídia (Upload/Download)

9. Mídia (Upload/Download)#

POST/v1/instances/{instanceId}/média#

Faz upload de arquivo para o S3. Retorna um media_id (UUID) que pode ser usado nos endpoints de mensagem via o campo media_id. Este endpoint e opcional para fluxos que querem preparar/reutilizar mídias; para envio simples, os endpoints messages/image, messages/video, messages/audio, messages/document e messages/sticker também aceitam media_url ou multipart/form-data direto.

Auth: Todos autenticados

Limites:

Limite Valor
Tamanho máximo por arquivo 64 MB
Content-Type aceito multipart/form-data OU application/json
MIME types aceitos image/*, video/*, audio/*, application/pdf (qualquer outro retorna 400 unsupported media MIME type)

Opcao 1: Multipart upload (recomendado para upload direto)#

text
Content-Type: multipart/form-data

Form field: file (arquivo binario, max 64 MB)

Exemplo:

bash
curl -X POST https://api.catcher.one/v1/instances/$INSTANCE/media \
  -H "X-API-Key: $TOKEN" \
  -F "file=@/caminho/para/documento.pdf"
text
Content-Type: application/json
json
{
  "media_url": "https://exemplo.com/imagem.png",
  "file_name": "imagem.png"
}

Util quando o arquivo já está em um bucket público (R2, S3 com signed URL, etc). O servidor baixa respeitando o timeout HTTP global (HTTP_TIMEOUT, padrão 30s), aplica o mesmo limite de 64 MB, e rejeita MIME type fora da allowlist. URLs em redes privadas / IPs internos / Meta CDN são rejeitadas (SSRF guard + proxy discipline).

Resposta 201:

json
{
  "media_id": "68854a58-c8c9-4021-9c6f-765dc5cdff34",
  "mime_type": "image/png",
  "file_name": "imagem.png",
  "file_size": 45678
}

media_id e um UUID v4 — use como media_id no body de qualquer endpoint POST /v1/instances/{instanceId}/messages/{image|video|audio|document|sticker} dentro dos 7 dias de retencao padrão, ou envie a mídia direto nesses endpoints via media_url/file.

Erros:

Status error_code Descricao
400 BAD_REQUEST file required (multipart sem o campo file), failed to read file, file too large (max 64MB), unsupported media MIME type, invalid JSON, media_url or file upload required, failed to parse multipart form
401 UNAUTHORIZED Sem Authorization: Bearer nem X-API-Key, ou credencial inválida
404 NOT_FOUND instance not found (instância não pertence a sua empresa)
500 INTERNAL_SERVER_ERROR upload failed (S3 indisponível), failed to save media record (DB indisponível)
503 SERVICE_UNAVAILABLE media storage not configured (S3 não wired no backend — não deve ocorrer em staging/prod)

GET/v1/instances/{instanceId}/média/{mediaId}#

Faz download de um arquivo de mídia. Funciona tanto para mídia enviada (upload via POST) quanto para mídia recebida (baixada automaticamente de mensagens inbound do WhatsApp).

Auth: Todos autenticados

Parametros de URL:

Parametro Descricao
instanceId ID da instância
mediaId UUID da mídia (retornado no upload, no campo media_id do evento message.received, ou no campo media_id do objeto de mensagem)

Resposta 200: Arquivo binario com headers:

  • Content-Type: MIME type do arquivo (ex: image/png, audio/ogg; codecs=opus)
  • Content-Disposition: inline; filename="imagem.png"
  • Content-Length: Tamanho em bytes

Erros:

Status Descricao
404 Mídia não encontrada
503 Armazenamento S3 não configurado

Exemplo de uso (download de audio recebido):

bash
# 1. Receba um evento message.received via webhook/SSE com media_id
# 2. Baixe o arquivo:
curl -o audio.ogg \
  -H "X-API-Key: $TOKEN" \
  "https://api.catcher.one/v1/instances/$INSTANCE/media/b2c3d4e5-f6a7-8901-bcde-f12345678901"

Nota: Toda mídia recebida no WhatsApp (imagens, videos, audios, documentos, stickers) e baixada automaticamente do WhatsApp e armazenada no S3. O media_id e incluído no evento message.received e no objeto de mensagem retornado pelos endpoints de chat/mensagens.


GET/v1/instances/{instanceId}/média/{mediaId}/info#

Retorna apenas metadata da mídia (MIME, tamanho, filename, timestamps) como JSON, sem baixar o binario. Use este endpoint para espelhar informações da mídia no seu banco ou decidir se vale a pena baixar o arquivo antes de puxar os bytes.

Auth: Todos autenticados

Parametros de URL: mesmos do endpoint de download (instanceId, mediaId).

Resposta 200:

json
{
  "id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
  "mime_type": "image/jpeg",
  "file_name": "foto.jpg",
  "file_size": 102400,
  "download_url": "/v1/instances/84c2e480-.../media/b2c3d4e5-...",
  "info_url": "/v1/instances/84c2e480-.../media/b2c3d4e5-.../info",
  "created_at": "2026-03-28T14:30:00Z"
}

Quando a mídia e temporaria (upload com TTL), o campo expires_at acompanha. O mesmo shape aparece inline no campo media da resposta de GET /v1/instances/{instanceId}/message/{messageId} — consumidores podem usar as mesmas chaves em ambos os contextos.

Erros:

Status Descricao
404 Mídia não encontrada para está instância

GET/v1/instances/{instanceId}/média#

Lista paginada de mídias da instância. Cada item inclui remote_jid da conversa associada (quando a mídia está vinculada a uma mensagem).

Auth: Todos autenticados

Query params:

Parametro Tipo Descricao
page int Página (default: 1)
limit int Itens por página (default: 50, max: 100)
mime_type string Filtro por prefixo MIME (ex: image/, video/)
remote_jid string Filtra mídias de uma conversa especifica (ex: 5511999887766@s.whatsapp.net)

Resposta 200:

json
{
  "data": [
    {
      "id": "uuid-media",
      "external_id": "uuid-media",
      "instance_id": "uuid-instance",
      "s3_key": "company/instance/file.png",
      "mime_type": "image/png",
      "file_name": "foto.png",
      "file_size": 45678,
      "remote_jid": "5511999887766@s.whatsapp.net",
      "created_at": "2026-03-28T14:30:00Z"
    }
  ],
  "total": 120,
  "page": 1,
  "limit": 50
}

Nota: remote_jid pode estar ausente para mídias que não estão associadas a nenhuma mensagem (ex: uploads manuais ainda não enviados).

Erros:

Status Descricao
401 Sem autenticação válida
404 Instância não pertence a sua empresa
500 Erro de acesso ao banco do tenant

GET/v1/instances/{instanceId}/média/conversations#

Lista conversas que possuem mídias, com contadores e metadados agregados. Util para agrupar a galeria de mídia por conversa.

Auth: Todos autenticados

Query params:

Parametro Tipo Descricao
mime_type string Filtro por prefixo MIME (ex: image/)

Resposta 200:

json
{
  "data": [
    {
      "remote_jid": "5511999887766@s.whatsapp.net",
      "media_count": 42,
      "total_size": 156789012,
      "last_media_at": "2026-03-28T14:30:00Z",
      "thumbnail_id": "uuid-da-midia-mais-recente"
    }
  ]
}
Campo Descricao
remote_jid JID da conversa
media_count Quantidade de mídias na conversa
total_size Tamanho total em bytes
last_media_at Data da mídia mais recente
thumbnail_id UUID da mídia mais recente (pode ser usado para thumbnail via GET .../media/{thumbnail_id})

Erros:

Status Descricao
401 Sem autenticação válida
404 Instância não pertence a sua empresa
500 Erro de acesso ao banco do tenant