API: Conversations¶
Visão Geral¶
Gerenciamento de conversas entre contatos WhatsApp e a plataforma. Suporta modo IA (automático) e modo Manual (operador humano).
Autorização e Rate Limiting¶
O grupo de endpoints de conversas requer autenticação e usa a política de rate limiting Realtime: 120 requisições por 60 segundos por usuário.
O endpoint de envio de mensagens (POST /api/conversations/{id}/messages) usa uma política separada SendMessage: 30 requisições por 60 segundos por usuário.
| Endpoint | Política | Limite | Janela |
|---|---|---|---|
| Todos (exceto SendMessage) | Realtime | 120 req | 60s |
| POST /conversations/{id}/messages | SendMessage | 30 req | 60s |
Endpoints¶
GET /api/instances/{instanceId}/conversations¶
Lista conversas de uma instância.
Query Parameters:
- status (opcional): Active, Resolved
- page (opcional): Página (default: 1)
- pageSize (opcional): Itens por página (default: 20)
Response (200 OK):
{
"items": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"contactPhone": "+5511999998888",
"contactName": "João Silva",
"contactProfilePictureUrl": "https://cdn.exemplo.com/profile.jpg",
"status": "Active",
"mode": "AI",
"startedAt": "2024-01-20T10:00:00Z",
"lastMessageAt": "2024-01-20T10:30:00Z",
"lastMessage": "Qual o horário de funcionamento?",
"unreadCount": 2
}
],
"totalCount": 50,
"page": 1,
"pageSize": 20
}
GET /api/conversations/{id}¶
Retorna detalhes de uma conversa.
Response (200 OK):
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"instanceId": "660e8400-e29b-41d4-a716-446655440001",
"instanceName": "Suporte Principal",
"agentId": "770e8400-e29b-41d4-a716-446655440002",
"agentName": "Suporte TI",
"contactPhone": "+5511999998888",
"contactName": "João Silva",
"contactProfilePictureUrl": "https://cdn.exemplo.com/profile.jpg",
"status": "Active",
"mode": "AI",
"modeChangedAt": null,
"startedAt": "2024-01-20T10:00:00Z",
"lastMessageAt": "2024-01-20T10:30:00Z",
"resolvedAt": null,
"summary": null,
"totalInputTokens": 1500,
"totalOutputTokens": 800
}
GET /api/conversations/{id}/messages¶
Lista mensagens de uma conversa com paginação.
Query Parameters:
- before (opcional): Cursor para paginação (ID da mensagem)
- limit (opcional): Quantidade (default: 50)
Response (200 OK):
{
"items": [
{
"id": "880e8400-e29b-41d4-a716-446655440000",
"role": "User",
"type": "Text",
"content": "Qual o horário de funcionamento?",
"mediaUrl": null,
"mediaMimeType": null,
"mediaFileName": null,
"status": "Read",
"createdAt": "2024-01-20T10:30:00Z",
"inputTokens": null,
"outputTokens": null,
"reactions": [
{
"emoji": "👍",
"senderPhone": "+5511999998888",
"fromMe": false
}
],
"systemEventType": null,
"actorName": null
},
{
"id": "990e8400-e29b-41d4-a716-446655440001",
"role": "Assistant",
"type": "Text",
"content": "Nosso horário é das 8h às 18h.",
"mediaUrl": null,
"mediaMimeType": null,
"mediaFileName": null,
"status": "Delivered",
"createdAt": "2024-01-20T10:30:05Z",
"inputTokens": 50,
"outputTokens": 20,
"reactions": [],
"systemEventType": null,
"actorName": null
},
{
"id": "aa0e8400-e29b-41d4-a716-446655440002",
"role": "System",
"type": "Text",
"content": "Conversa transferida para atendimento humano.",
"mediaUrl": null,
"mediaMimeType": null,
"mediaFileName": null,
"status": "Read",
"createdAt": "2024-01-20T10:30:06Z",
"inputTokens": null,
"outputTokens": null,
"reactions": null,
"systemEventType": "EscalatedByAi",
"actorName": "Suporte TI"
}
],
"hasMore": true,
"oldestMessageId": "770e8400-e29b-41d4-a716-446655440000"
}
POST /api/conversations/start¶
Inicia uma nova conversa a partir do portal.
Request:
{
"instanceId": "660e8400-e29b-41d4-a716-446655440001",
"contactPhone": "+5511999998888",
"message": "Olá, como posso ajudar?"
}
Response (201 Created):
{
"conversationId": "550e8400-e29b-41d4-a716-446655440000",
"messageId": "880e8400-e29b-41d4-a716-446655440000"
}
POST /api/conversations/{id}/messages¶
Envia uma mensagem na conversa.
Rate Limiting: SendMessage (30 req/60s)
Request:
{
"content": "Segue o documento solicitado.",
"attachments": [
{
"fileName": "manual.pdf",
"mimeType": "application/pdf",
"base64": "JVBERi0xLjQK..."
}
],
"isVoiceMessage": false
}
Response (200 OK):
{
"messageId": "880e8400-e29b-41d4-a716-446655440000",
"whatsappMessageId": "wamid.xxx",
"status": "Sent"
}
POST /api/conversations/{id}/transfer¶
Transfere o modo da conversa (AI ↔ Manual).
Request:
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
targetMode |
string | Sim | "AI" ou "Manual" |
triggerImmediateResponse |
bool | Não (default: false) | Quando true e targetMode = "AI", agenda resposta imediata da IA via pipeline DeferredAiResponse (sem aguardar nova mensagem do contato) |
Validação: Ao transferir para modo IA, o sistema verifica se o agente está ativo e se o tenant possui créditos de IA disponíveis. Caso o agente esteja desativado ou não haja créditos, retorna erro 409.
Response (200 OK):
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"mode": "AI",
"modeChangedAt": "2024-01-20T11:00:00Z"
}
POST /api/conversations/{id}/resolve¶
Resolve uma conversa.
Request:
Response (200 OK):
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"status": "Resolved",
"resolvedAt": "2024-01-20T11:30:00Z"
}
PUT /api/conversations/{id}/read¶
Marca a conversa como lida pelo operador.
Response: 204 No Content
POST /api/conversations/{conversationId}/messages/{messageId}/react¶
Adiciona ou remove uma reação a uma mensagem.
Request:
Response (200 OK):
Tipos de Mensagem¶
| Type | Descrição |
|---|---|
| Text | Mensagem de texto |
| Image | Imagem (jpg, png, gif, webp) |
| Audio | Áudio/Voice message |
| Video | Vídeo |
| Document | Documento (pdf, doc, etc) |
| Sticker | Sticker do WhatsApp |
Status de Mensagem¶
| Status | Descrição |
|---|---|
| Pending | Aguardando envio |
| Sent | Enviada (✓) |
| Delivered | Entregue (✓✓) |
| Read | Lida (✓✓ azul) |
| Failed | Falhou |
Modos de Conversa¶
| Mode | Descrição |
|---|---|
| AI | IA processa as mensagens automaticamente |
| Manual | Operador humano responde via portal |
SignalR - Eventos Real-time¶
O hub ConversationHub emite eventos para atualizações em tempo real:
| Evento | Descrição |
|---|---|
| NewMessage | Nova mensagem na conversa (inclui mensagens de sistema com SystemEventType e ActorName) |
| MessageStatusUpdated | Status de entrega atualizado |
| ConversationUpdated | Conversa atualizada (status, modo) |
| ConversationEscalated | Conversa escalada para modo manual |
| NewConversation | Nova conversa iniciada |
| CreditBalanceUpdated | Saldo de créditos atualizado |
Mensagens de Sistema¶
Mensagens com role: "System" representam eventos internos do sistema. Nunca são enviadas ao WhatsApp e nunca incluídas no histórico da IA. Campos adicionais:
| Campo | Tipo | Descrição |
|---|---|---|
systemEventType |
string? | Tipo do evento (AiCapReached, AiFailure, CreditsExhausted, EscalatedByAi, ResolvedByAi, ResolvedByOperator, ModeChangedToManual, ModeChangedToAi) |
actorName |
string? | Quem causou o evento (nome do operador/agente IA, null para automático) |
Exemplo de Uso (Blazor)¶
_hubConnection.On<MessageNotification>("NewMessage", message =>
{
// Mensagens de sistema têm role = "System" e systemEventType preenchido
_messages.Add(MapToMessageItemResponse(message));
StateHasChanged();
});
Erros Comuns¶
| Status | Código | Descrição |
|---|---|---|
| 404 | CONVERSATION_NOT_FOUND | Conversa não encontrada |
| 400 | INSTANCE_DISCONNECTED | Instância WhatsApp desconectada |
| 400 | CONVERSATION_RESOLVED | Conversa já resolvida |