Símbolo da AmivuSímbolo da AmivuDevelopers

Mensagens

O ciclo de vida de uma mensagem, do envio ao recibo — e o que é `null`.

Uma mensagem pertence a uma conversa e tem uma direção: inbound quando veio do contato, outbound quando saiu de você.

Enviar

Uma rota, todos os canais. A conversa determina por onde a mensagem sai — e as capacidades do canal são conferidas antes de qualquer coisa ser gravada.

Terminal
curl https://api.amivu.com.br/v1/messages \
  -H "Authorization: Bearer $AMIVU_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: pedido-8291-entrega" \
  -d '{
    "conversation_id": "conv_01K7ZFA5X8Q2M4N6P8R0T2V4W6",
    "type": "text",
    "text": "Seu pedido saiu para entrega."
  }'

Imagem, vídeo, áudio e documento

Mídia são duas chamadas: suba o arquivo em POST /v1/uploads e envie o attachment_id que voltou, com o type do arquivo e, se quiser, uma legenda em text. O envio é o mesmo que o atendente faz pelo painel — mesma fila, mesmos recibos. Tipos aceitos, limite de tamanho e validade do anexo estão em Anexos e mídia.

Terminal
curl https://api.amivu.com.br/v1/messages \
  -H "Authorization: Bearer $AMIVU_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: pedido-8291-catalogo" \
  -d '{
    "conversation_id": "conv_01K7ZFA5X8Q2M4N6P8R0T2V4W6",
    "type": "document",
    "attachment_id": "att_01K7ZFA5X8Q2M4N6P8R0T2V4W6",
    "text": "Segue o catálogo."
  }'
Modelo aprovado ainda não
type: "template" faz parte do schema, mas é recusado com 422 unsupported_message_type em qualquer canal. Não é falha passageira: retentar não adianta. Quando isso mudar, entra no changelog.
Nada é gravado quando o canal não aceita
Um canal sem suporte ao tipo — mídia no chat do site, por exemplo — recusa com 422 unsupported_message_type e a conversa fica intacta. Gravar primeiro e descobrir depois deixaria um balão na tela do atendente que o cliente nunca recebeu.

O ciclo de vida

queued ──▶ sent ──▶ delivered ──▶ read
   │         │
   └─────────┴──▶ failed
  • queued — aceita por nós. Ainda não entregue ao canal.
  • sent — o canal aceitou a mensagem.
  • delivered — o canal confirmou que chegou ao aparelho.
  • read — o contato leu.
  • failed — o canal recusou. O motivo vem em error.

A resposta de POST /v1/messages devolve queued, e isso é deliberado: o retorno síncrono do provedor confirma apenas o enfileiramento na ponta dele. A falha real chega depois, por webhook de status. Tratar o 201 como “entregue” é o erro de integração mais comum com qualquer API de mensageria.

Quando status é null

Duas situações, e as duas são informação:

  • Mensagem recebida — quem entregou foi o outro lado; não há estado nosso a reportar.
  • Canal sem recibo — a conversa não passa por um transporte que confirme entrega. É o caso do registro manual.

A Amivu não fabrica estado. Preencher delivered porque “provavelmente chegou” seria mentir num campo em que integrações tomam decisões — inclusive a de cobrar alguém.

Para saber o que um canal específico reporta, leia capabilities.delivery_receipts e capabilities.read_receipts em GET /v1/channels/{id}.

Quando falha

{
  "object": "message",
  "id": "msg_01K7ZFA5X8Q2M4N6P8R0T2V4W6",
  "status": "failed",
  "error": {
    "code": "130497",
    "message": "Conta sem verificação de negócio para enviar a este destino."
  }
}

O code é o do provedor, repassado sem tradução. Ele pede ação humana com muito mais frequência do que uma retentativa resolveria — e é por isso que a Amivu não reenvia sozinha: um número bloqueado continua bloqueado na décima tentativa.

Receber

Não pergunte de tempos em tempos. Assine message.received e a Amivu faz um POST assinado no seu endpoint com a mensagem e a conversa dentro.

Mensagem com mídia traz o arquivo em attachment.url, baixável com a mesma chave — ver Anexos e mídia.

Se precisar mesmo ler o histórico — para montar uma tela, por exemplo — GET /v1/conversations/{id}/messages devolve da mais nova para a mais velha, com cursor.

Escrevemos sobre operação de atendimento, canais e IA no blog da Amivu.