# Buscar mensagens em um chat

POST /message/find

Busca mensagens com múltiplos filtros disponíveis. Este endpoint permite:

1. **Busca por ID específico**: Use `id` para encontrar uma mensagem exata
2. **Filtrar por chat**: Use `chatid` para mensagens de uma conversa específica
3. **Filtrar por rastreamento**: Use `track_source` e `track_id` para mensagens com dados de tracking
4. **Histórico de ligações**: Use apenas `messageType: call`, `limit` e `offset`
   para listar as chamadas mais recentes. A resposta pode trazer
   `callPeer` (identidade conhecida do contato) e `content.isVideo`.
5. **Status dos contatos**: Use `chatid: status@broadcast` para os Status
   recebidos, mesmo sem webhook `status_posts`. Sem esse `chatid`, a busca não
   traz Status. Eles ficam guardados por 24 horas, como no WhatsApp (a limpeza
   roda uma vez por dia, então filtre `messageTimestamp` se precisar do corte
   exato), e o Status que o autor apaga sai da lista. Cada um vem com o autor
   em `sender_pn`, `sender_lid` e `sender_image_preview_url` (foto, quando
   conhecida) e, nos de imagem, vídeo ou link, com a miniatura em
   `content.JPEGThumbnail`. Baixe a mídia pelo `/message/download`. Um Status
   que não abriu vem com `messageType: error` e só o ID, o autor e o horário.
   **Status de grupo** (enviados e recebidos) ficam na conversa de cada grupo
   com `messageType: GroupStatusMessage` e o texto em `text`: liste todos com
   `messageType: GroupStatusMessage`, sem `chatid`. Saem em 24 horas, como os
   outros Status (os de campanha do `/sender` ficam com a campanha).
6. **Limitar resultados**: Use `limit` para controlar quantas mensagens retornar
7. **Ordenação**: Resultados ordenados por data (mais recentes primeiro)

Fora dos Status, as mensagens guardadas só trazem no `content` as
miniaturas em base64 que não têm cópia no servidor (prévia de link sem
cópia, localização, anúncio, convites); as de mídia que pode ser baixada de
novo (`JPEGThumbnail` e afins) chegam só no webhook, na hora da mensagem.
Nas mensagens enviadas pela API nos últimos 7 dias, `sendPayload` traz o
pedido de envio, sem os arquivos em base64 (links vêm). Depois do envio (em
conversa individual, 1 hora depois), o arquivo em base64 guardado vira o
texto `[arquivo removido após o envio: tipo, N bytes]`.


## Autenticação

```json
[
  {
    "token": []
  }
]
```

```json
{
  "token": {
    "name": "token",
    "type": "apiKey",
    "in": "header"
  }
}
```

## Corpo da requisição

```json
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "ID específico da mensagem para busca exata",
            "example": "user123:r3EB0538"
          },
          "chatid": {
            "type": "string",
            "description": "ID do chat no formato internacional",
            "example": "5511999999999@s.whatsapp.net"
          },
          "messageType": {
            "type": "string",
            "description": "Tipo da mensagem. Use `call` com `limit` e `offset` para o histórico de ligações.",
            "example": "call"
          },
          "track_source": {
            "type": "string",
            "description": "Origem do rastreamento para filtrar mensagens",
            "example": "chatwoot"
          },
          "track_id": {
            "type": "string",
            "description": "ID de rastreamento para filtrar mensagens",
            "example": "msg_123456789"
          },
          "limit": {
            "type": "integer",
            "description": "Número máximo de mensagens a retornar (padrão 100, sem máximo). Para muitas mensagens, prefira páginas de até 1000 e avance com `pagination.nextOffset`.",
            "minimum": 1,
            "default": 100,
            "example": 20
          },
          "offset": {
            "type": "integer",
            "description": "Deslocamento para paginacao (0 retorna as mensagens mais recentes)",
            "default": 0
          }
        }
      },
      "examples": {
        "chatSearch": {
          "summary": "Buscar por chat especifico",
          "description": "Busca mensagens de uma conversa especifica",
          "value": {
            "chatid": "5511999999999@s.whatsapp.net",
            "limit": 20,
            "offset": 0
          }
        },
        "idSearch": {
          "summary": "Buscar por ID especifico",
          "description": "Busca uma mensagem especifica pelo seu ID",
          "value": {
            "id": "user123:r3EB0538"
          }
        },
        "trackingSearch": {
          "summary": "Buscar por rastreamento",
          "description": "Busca mensagens usando dados de tracking com paginacao",
          "value": {
            "track_source": "chatwoot",
            "track_id": "conv_123456",
            "limit": 50,
            "offset": 100
          }
        },
        "callHistory": {
          "summary": "Histórico de ligações",
          "value": {
            "messageType": "call",
            "limit": 40,
            "offset": 0
          }
        }
      }
    }
  }
}
```

## Respostas

```json
{
  "200": {
    "description": "Lista de mensagens encontradas com metadados de paginacao",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "messages": {
              "type": "array",
              "items": {
                "$ref": "#/components/schemas/Message"
              }
            },
            "pagination": {
              "type": "object",
              "description": "Dados da página, como nas outras listas, sem `totalRecords` (contar as mensagens pesaria a cada página).",
              "properties": {
                "limit": {
                  "type": "integer"
                },
                "offset": {
                  "type": "integer"
                },
                "hasMore": {
                  "type": "boolean",
                  "description": "Há mais mensagens depois desta página."
                },
                "nextOffset": {
                  "type": "integer",
                  "description": "Offset da próxima página."
                }
              }
            }
          }
        }
      }
    }
  },
  "400": {
    "description": "Parametros invalidos"
  },
  "401": {
    "description": "Token invalido ou expirado"
  },
  "404": {
    "description": "Chat nao encontrado"
  },
  "500": {
    "description": "Erro interno do servidor"
  }
}
```

## #/components/schemas/Message

```json
{
  "type": "object",
  "description": "Representa uma mensagem trocada no sistema",
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid",
      "description": "ID único interno da mensagem (formato r + 7 caracteres hex aleatórios)"
    },
    "messageid": {
      "type": "string",
      "description": "ID original da mensagem no provedor"
    },
    "chatid": {
      "type": "string",
      "description": "ID da conversa relacionada"
    },
    "sender": {
      "type": "string",
      "description": "ID do remetente da mensagem"
    },
    "senderName": {
      "type": "string",
      "description": "Nome exibido do remetente"
    },
    "isGroup": {
      "type": "boolean",
      "description": "Indica se é uma mensagem de grupo",
      "default": false
    },
    "fromMe": {
      "type": "boolean",
      "description": "Indica se a mensagem foi enviada pelo usuário",
      "default": false
    },
    "messageType": {
      "type": "string",
      "description": "Tipo de conteúdo da mensagem"
    },
    "source": {
      "type": "string",
      "description": "Plataforma de origem da mensagem"
    },
    "messageTimestamp": {
      "type": "integer",
      "description": "Timestamp original da mensagem em milissegundos",
      "default": 0
    },
    "status": {
      "type": "string",
      "description": "Status do ciclo de vida da mensagem.\nExemplos comuns: `Queued`, `Canceled`, `Failed`, `Sent`, `Delivered`, `Read`.\nEm mensagem de grupo, segue o participante mais adiantado: `Delivered` quando pelo menos um recebeu, `Read` quando pelo menos um leu e `Played` quando pelo menos um ouviu.\n"
    },
    "text": {
      "type": "string",
      "description": "Texto original da mensagem",
      "default": ""
    },
    "quoted": {
      "type": "string",
      "description": "ID da mensagem citada/respondida",
      "default": ""
    },
    "edited": {
      "type": "string",
      "description": "Histórico de edições da mensagem",
      "default": ""
    },
    "reaction": {
      "type": "string",
      "description": "ID da mensagem reagida",
      "default": ""
    },
    "vote": {
      "type": "string",
      "description": "Dados de votação de enquete e listas",
      "default": ""
    },
    "convertOptions": {
      "type": "string",
      "description": "Conversão de opções da mensagem, lista, enquete e botões",
      "default": ""
    },
    "buttonOrListid": {
      "type": "string",
      "description": "ID do botão ou item de lista selecionado",
      "default": ""
    },
    "owner": {
      "type": "string",
      "description": "Dono da mensagem",
      "default": ""
    },
    "error": {
      "type": "string",
      "description": "Mensagem de erro caso o envio tenha falhado",
      "default": ""
    },
    "content": {
      "description": "Conteúdo bruto da mensagem (JSON serializado ou texto)",
      "oneOf": [
        {
          "type": "object",
          "additionalProperties": true
        },
        {
          "type": "string",
          "description": "Texto bruto quando não for JSON"
        }
      ]
    },
    "wasSentByApi": {
      "type": "boolean",
      "description": "Indica se a mensagem foi enviada via API"
    },
    "pinned": {
      "type": "boolean",
      "description": "Mensagem fixada na conversa (fixar e desafixar chegam também em `messages_update`, tipos `Pinned` e `Unpinned`)"
    },
    "sendFunction": {
      "type": "string",
      "description": "Função usada para enviar a mensagem (quando enviada via API)"
    },
    "sendPayload": {
      "description": "Payload usado no envio quando disponível. Dados de mídia em base64 são omitidos.",
      "oneOf": [
        {
          "type": "object",
          "additionalProperties": true
        },
        {
          "type": "string",
          "description": "Texto bruto quando não for JSON"
        }
      ]
    },
    "fileURL": {
      "type": "string",
      "description": "URL ou referência de arquivo da mensagem"
    },
    "callPeer": {
      "type": "object",
      "description": "Contato conhecido associado a uma ligação, quando disponível em `messageType: call`.",
      "properties": {
        "jid": {
          "type": "string"
        },
        "name": {
          "type": "string"
        },
        "imagePreviewUrl": {
          "type": "string"
        }
      }
    },
    "send_folder_id": {
      "type": "string",
      "description": "Pasta associada ao envio (quando aplicável)"
    },
    "track_source": {
      "type": "string",
      "description": "Origem de rastreamento"
    },
    "track_id": {
      "type": "string",
      "description": "ID de rastreamento (pode repetir)"
    },
    "ai_metadata": {
      "type": "object",
      "description": "Registro de uma rodada da IA. O completo (pedido ao modelo, resposta e `outcome`) fica uma vez, na última mensagem do contato que a rodada respondeu, também quando nada saiu (erro, resposta descartada). Cada mensagem enviada pela IA leva só `agent_id` e `turn` (o `id` dessa mensagem do contato).",
      "properties": {
        "agent_id": {
          "type": "string",
          "description": "ID do agente de IA responsável"
        },
        "turn": {
          "type": "string",
          "description": "Na mensagem enviada pela IA: o `id` da mensagem do contato onde está o registro completo da rodada."
        },
        "flow_id": {
          "type": "string",
          "description": "Mensagem enviada por um fluxo: o `id` do fluxo. A mensagem enviada pela IA traz o `agent_id`."
        },
        "request": {
          "type": "object",
          "description": "Dados da requisição à API de IA",
          "properties": {
            "messages": {
              "type": "array",
              "description": "Histórico de mensagens enviadas para a API"
            },
            "tools": {
              "type": "array",
              "description": "Ferramentas disponíveis para o agente"
            },
            "options": {
              "type": "object",
              "description": "Opções de configuração da API",
              "properties": {
                "model": {
                  "type": "string"
                },
                "temperature": {
                  "type": "number"
                },
                "maxTokens": {
                  "type": "integer"
                },
                "topP": {
                  "type": "number"
                },
                "frequencyPenalty": {
                  "type": "number"
                },
                "presencePenalty": {
                  "type": "number"
                }
              }
            }
          }
        },
        "response": {
          "type": "object",
          "description": "Resposta da API de IA",
          "properties": {
            "choices": {
              "type": "array",
              "description": "Resultados retornados pela API"
            },
            "toolResults": {
              "type": "array",
              "description": "Resultados da execução de ferramentas"
            },
            "error": {
              "type": "string",
              "description": "Mensagem de erro, se houver"
            }
          }
        },
        "outcome": {
          "type": "object",
          "description": "O que a rodada fez de fato (só no registro completo).",
          "properties": {
            "status": {
              "type": "string",
              "enum": [
                "sent",
                "cancelled",
                "error",
                "empty"
              ],
              "description": "`sent`: enviou algo; `cancelled`: descartada (a conversa pausou, um fluxo começou ou bateu o limite de respostas por hora); `error`: o provedor falhou; `empty`: nada a enviar."
            },
            "texts": {
              "type": "integer",
              "description": "Mensagens de texto enviadas."
            },
            "audio": {
              "type": "boolean",
              "description": "Respondeu em áudio."
            },
            "menus": {
              "type": "integer",
              "description": "Menus enviados."
            },
            "files": {
              "type": "integer",
              "description": "Arquivos (mensagens cadastradas) enviados."
            },
            "handoff": {
              "type": "string",
              "description": "`chamar_humano`: o resumo para quem atender."
            },
            "lead": {
              "type": "array",
              "items": {
                "type": "string"
              },
              "description": "`atualizar_lead`: o que foi gravado no CRM (`lead_email = ana@exemplo.com; column = Agendado`)."
            },
            "detail": {
              "type": "string",
              "description": "Por que foi descartada, ou o erro."
            }
          }
        }
      }
    },
    "sender_pn": {
      "description": "JID PN resolvido do remetente (quando disponível)",
      "oneOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ]
    },
    "sender_lid": {
      "description": "LID original do remetente (quando disponível)",
      "oneOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ]
    },
    "sender_image_preview_url": {
      "type": "string",
      "format": "uri",
      "description": "URL temporária de preview do remetente, quando conhecida. A hidratação desta versão preenche mensagens recebidas em grupos; o campo pode ser omitido. Não provoca consulta de foto ao WhatsApp na listagem."
    }
  }
}
```

## Guias relacionados

[Autenticação](/docs/authentication) · [Erros e retries](/docs/errors-and-retries) · [Server URL](/docs/server-url)
