Enviar mensagem
POST /messages/send — envia uma mensagem WhatsApp (texto ou mídia) pela fila do CRM, para conversa, contato ou telefone, com operador opcional.
/messages/sendBetaEscopo necessário: messages:write
Envia uma mensagem WhatsApp (texto ou mídia) por uma conexão WhatsApp da organização. A organização é resolvida a partir da própria API key — não envie organization_id.
O envio é assíncrono: a mensagem é gravada no CRM com status pending e entra na fila de envio. O queued: true da resposta confirma o enfileiramento — a entrega ao destinatário aparece depois, na conversa do CRM.
Destino: informe exatamente um entre conversation_id, contact_id ou phone. Com phone, o contato e a conversa são criados automaticamente se não existirem.
Endpoint
POST https://crm.oficinamartech.com/api/v1/messages/sendCorpo da requisição
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
instance_id | string (UUID) | ✅ | Conexão WhatsApp da organização usada no envio. |
conversation_id | string (UUID) | △ | Conversa existente na organização e na conexão instance_id informada. Um dos três destinos possíveis. |
contact_id | string (UUID) | △ | Contato existente; usa/cria a conversa dele na instância (requer telefone no contato). |
phone | string (até 40) | △ | Telefone em qualquer formato; normalizado para dígitos com DDI. Resolve/cria contato e conversa. |
content | string (1–4096) | ✅ | Texto da mensagem. Em envios de mídia, funciona como caption. |
message_type | text | image | video | audio | document | ❌ | Tipo da mensagem. Default: text. Tipos de mídia exigem media_url. |
media_url | string (URL pública, até 2048) | △ | URL pública da mídia. Obrigatória quando message_type não é text. |
media_mime_type | string (até 120) | ❌ | MIME type da mídia. Ex.: image/jpeg. |
media_filename | string (até 200) | ❌ | Nome do arquivo (útil em document). Ex.: contrato.pdf. |
sender_user_id | string (UUID) | ❌ | Operador (membro ativo da organização) que assina a mensagem. Veja Operador. |
assign_conversation | boolean | ❌ | Atribui a conversa ao sender_user_id quando ela está sem operador. Default: true. |
△ = exatamente um entre conversation_id, contact_id e phone deve ser informado.
Operador
Com sender_user_id, a mensagem sai assinada: o nome do operador aparece no balão da conversa (campos sender_id/sender_name). Combinado com assign_conversation (default true), uma conversa sem dono é atribuída a ele — mesmo comportamento do envio manual pela interface.
Opt-out (LGPD)
Se o contato da conversa registrou opt-out, o envio é bloqueado com 403 contact_opted_out. Não insista: o opt-out é um gate de consentimento.
Resposta
201 Created:
{
"data": {
"message_id": "9b2e1c40-58cc-4372-a567-0e02b2c3d479",
"conversation_id": "1f0b7a2e-...",
"contact_id": "2a7c91d4-...",
"queued": true,
"assigned_to": "5e3f0b8a-..."
}
}| Campo | Tipo | Descrição |
|---|---|---|
message_id | string (UUID) | Mensagem gravada no CRM (status pending; o worker atualiza o estado). |
conversation_id | string (UUID) | Conversa usada no envio (existente ou recém-criada). |
contact_id | string | null | Contato da conversa (quando houver). |
queued | true | Sempre true: o envio é assíncrono, via fila do CRM. |
assigned_to | string | null | Operador dono da conversa após o envio (null quando sem atribuição). |
Exemplos
curl -X POST "https://crm.oficinamartech.com/api/v1/messages/send" \
-H "Authorization: Bearer $OFM_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"instance_id": "1f0b...e3",
"phone": "+55 11 98765-4321",
"content": "Olá! Recebemos sua inscrição 🎉",
"sender_user_id": "5e3f...8a"
}'Códigos de erro específicos
| Status | code | Causa |
|---|---|---|
| 400 | — | JSON inválido, corpo fora do schema ou mais de um destino informado |
| 400 | — | message_type de mídia sem media_url |
| 400 | contact_without_phone | contact_id sem telefone válido para iniciar conversa |
| 400 | instance_disconnected | Conexão WhatsApp não está conectada |
| 401 | missing_api_key | Header Authorization ausente |
| 403 | missing_scope | Chave sem o escopo messages:write |
| 403 | contact_opted_out | Contato registrou opt-out (LGPD) |
| 403 | messaging_guard_blocked | Limite de mensagens do plano ou guarda de assinatura do canal |
| 404 | instance_not_found | instance_id não existe nesta organização |
| 404 | conversation_not_found | conversation_id não encontrado na organização ou pertence a outra conexão |
| 404 | contact_not_found | contact_id não encontrado na organização |
| 404 | operator_not_found | sender_user_id não é membro ativo da organização |
| 500 | enqueue_failed | Falha ao enfileirar a mensagem (ela fica marcada como failed) |
| 500 | — | Erro interno |
Veja Códigos de erro para o formato completo.
Notas
- A organização vem da API key — uma chave só envia mensagens pelas conexões da própria organização.
- A conversa criada por
phoneusa o canal WhatsApp da instância informada e fica vinculada ao contato resolvido/criado (origemapi). - O telefone aceita formatos livres (
+55 11 98765-4321,11987654321, etc.) e é normalizado para dígitos com DDI, com variantes do 9º dígito brasileiro. queued: truenão garante entrega: falhas de envio aparecem depois no status da mensagem dentro do CRM.
Relatório de agenda, tarefas, formulários e automações
GET /analytics/reports/operations — agendamentos por situação e profissional, tarefas por responsável, respostas por formulário e execuções por automação.
Agendar mensagens em grupos
Seleção de grupos, agendamento em lote e acompanhamento por API para agentes de IA.