> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pilotstatus.com.br/llms.txt
> Use this file to discover all available pages before exploring further.

# GET /v1/messages/history — Histórico de Mensagens

> Recupere todo o histórico de mensagens armazenado (conversas diretas e em grupo) do número conectado.

Recupere **todo o histórico de mensagens armazenado** (conversas diretas e em grupo) do número conectado.

## Endpoint

`GET https://pilotstatus.com.br/v1/messages/history`

<Note>
  Requer uma chave de API **com escopo de número** (`ps_*`) no cabeçalho `x-api-key`. Chaves com escopo de tenant retornam `403`. Você também pode identificar a chave com `x-api-key-id: <api_key_id>`.

  **Todos os provedores suportados:** este endpoint funciona tanto para números **não oficiais (Pilot Status web)** quanto para números oficiais da **Meta Cloud API**.
</Note>

## Parâmetros de query

<ParamField query="startDate" type="string">
  Data/hora ISO 8601. Filtra mensagens com `providerTimestamp` **em ou após** esta data.
</ParamField>

<ParamField query="endDate" type="string">
  Data/hora ISO 8601. Filtra mensagens com `providerTimestamp` **em ou antes** desta data.
</ParamField>

<ParamField query="page" default="1" type="integer">
  Número da página (≥ 1).
</ParamField>

<ParamField query="pageSize" default="30" type="integer">
  Resultados por página (1–100).
</ParamField>

Tanto `startDate` quanto `endDate` são opcionais individualmente. Quando fornecidos, cada um deve ser uma string ISO 8601 válida e `startDate` não pode ser posterior a `endDate`; caso contrário, `400 INVALID_DATE_RANGE` é retornado.

Os resultados são ordenados por `providerTimestamp` de forma decrescente (mais recentes primeiro). O endpoint retorna até aproximadamente **um mês** de histórico armazenado, contado a partir da data de conexão do número.

## Efeito do modo PII

A resposta depende do **modo PII** configurado para o número (definido no painel, no painel Privacidade & retenção da página API Keys ou nas configurações do número). Os limites da query vêm exclusivamente dos seus `startDate`/`endDate` — a janela PII **não** é aplicada à query. Em vez disso, as linhas que ficam fora da janela de retenção ainda são retornadas, porém **redigidas**: a linha está presente (indexada pelo seu `providerTimestamp`) com `redacted: true` e com `text`, `media`, `participantName` e `participantPhone` nulos.

| Modo PII                    | Efeito                                                                                                                                                                                                                                                    |
| --------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `STORE_INDEFINITE` (padrão) | Todas as mensagens são retornadas na íntegra (sujeitas aos filtros de data).                                                                                                                                                                              |
| `STORE_X_DAYS`              | Mensagens dos últimos N dias são retornadas na íntegra. Mensagens mais antigas que `piiRetentionDays` são retornadas **redigidas** (`redacted: true`, com `text`/`media`/`participantName`/`participantPhone` nulos), indexadas pelo `providerTimestamp`. |
| `RELAY_ONLY`                | Toda mensagem é retornada **redigida** (`redacted: true`, com conteúdo/mídia/contraparte nulos) e a resposta inclui um campo `notice: "PII_RELAY_ONLY"`.                                                                                                  |

## Exemplo

<CodeGroup>
  ```bash cURL theme={null}
  curl "https://pilotstatus.com.br/v1/messages/history?startDate=2026-06-01T00:00:00Z&endDate=2026-06-30T23:59:59Z&page=1&pageSize=30" \
    -H "x-api-key: ps_your_key_here"
  ```

  ```json Response (200) theme={null}
  {
    "messages": [
      {
        "id": "cm_01HZX...",
        "conversationId": "conv_01HZX...",
        "direction": "INBOUND",
        "providerKind": "PILOT_STATUS",
        "externalMessageId": "wamid.HBg...",
        "status": "DELIVERED",
        "messageType": "text",
        "origin": null,
        "text": "Olá, ainda está disponível?",
        "participantName": "Ana",
        "participantPhone": "+5511988887777",
        "repliedToExternalId": null,
        "media": null,
        "sentAt": null,
        "deliveredAt": "2026-06-27T10:00:01.000Z",
        "readAt": null,
        "providerTimestamp": "2026-06-27T10:00:00.000Z",
        "createdAt": "2026-06-27T10:00:00.500Z"
      }
    ],
    "total": 1,
    "page": 1,
    "pageSize": 30,
    "totalPages": 1
  }
  ```

  ```json RELAY_ONLY (200) theme={null}
  {
    "messages": [
      {
        "id": "cm_01HZX...",
        "conversationId": "conv_01HZX...",
        "direction": "INBOUND",
        "providerKind": "PILOT_STATUS",
        "externalMessageId": "wamid.HBg...",
        "status": "DELIVERED",
        "messageType": "text",
        "origin": null,
        "text": null,
        "participantName": null,
        "participantPhone": null,
        "repliedToExternalId": null,
        "media": null,
        "redacted": true,
        "sentAt": null,
        "deliveredAt": "2026-06-27T10:00:01.000Z",
        "readAt": null,
        "providerTimestamp": "2026-06-27T10:00:00.000Z",
        "createdAt": "2026-06-27T10:00:00.500Z"
      }
    ],
    "total": 1,
    "page": 1,
    "pageSize": 30,
    "totalPages": 1,
    "notice": "PII_RELAY_ONLY"
  }
  ```
</CodeGroup>

## Campos do objeto de mensagem

<ResponseField name="id" type="string" required>
  ID interno da mensagem no Pilot Status.
</ResponseField>

<ResponseField name="conversationId" type="string" required>
  ID da conversa pai (direta ou em grupo).
</ResponseField>

<ResponseField name="direction" type="string" required>
  `"INBOUND"` (recebida) ou `"OUTBOUND"` (enviada).
</ResponseField>

<ResponseField name="providerKind" type="string" required>
  Provedor que processou a mensagem (`PILOT_STATUS`, `META`, …).
</ResponseField>

<ResponseField name="externalMessageId" type="string | null">
  ID da mensagem no provedor (ex.: `wamid` da Meta) quando disponível.
</ResponseField>

<ResponseField name="status" type="string" required>
  Status da mensagem (`QUEUED`, `SENT`, `DELIVERED`, `READ`, `FAILED`, …).
</ResponseField>

<ResponseField name="messageType" type="string" required>
  `text`, `image`, `audio`, `video`, `document`, `location`, `contacts`, `sticker` ou `reaction`.
</ResponseField>

<ResponseField name="origin" type="string | null">
  Origem de uma mensagem enviada (ex.: `APP`, `API`) quando disponível.
</ResponseField>

<ResponseField name="text" type="string | null">
  Texto ou legenda da mensagem quando disponível.
</ResponseField>

<ResponseField name="participantName" type="string | null">
  Nome de exibição do WhatsApp da contraparte/remetente quando disponível.
</ResponseField>

<ResponseField name="participantPhone" type="string | null">
  Contraparte/remetente no formato E.164 quando disponível.
</ResponseField>

<ResponseField name="repliedToExternalId" type="string | null">
  `externalMessageId` da mensagem à qual esta responde, quando disponível.
</ResponseField>

<ResponseField name="media" type="object | null">
  Descritor de mídia `{ provider, id, url, mimeType, fileName }` quando a mensagem carrega mídia; `null` caso contrário.

  * `media.provider` — o provedor que entregou a mídia — `"META"` para números da Meta Cloud API, ou uma tag interna de provedor para números não oficiais.
  * `media.id` — ID de mídia da **Meta**. Definido em números `META` — passe-o para `GET /v1/media/{mediaId}` para baixar os bytes; `null` para números não oficiais.
  * `media.url` — URL de download direto quando disponível. Mídia recebida da **META** é espelhada no S3 (portanto mensagens META geralmente carregam tanto `id` **quanto** `url`); o provedor não oficial fornece seu próprio link. Melhor esforço — pode ser `null`.
  * `media.mimeType` — Tipo MIME da mídia quando conhecido (pode ser `null`).
  * `media.fileName` — Nome do arquivo de mídia quando conhecido (pode ser `null`).
</ResponseField>

<ResponseField name="redacted" type="boolean">
  `true` quando a linha fica fora da janela de retenção de PII do número (ou o número está em `RELAY_ONLY`). Linhas redigidas mantêm seu `id`, `providerTimestamp` e os metadados de entrega, mas `text`, `media`, `participantName` e `participantPhone` são `null`.
</ResponseField>

<ResponseField name="sentAt" type="string | null">
  ISO 8601 — quando a mensagem foi enviada.
</ResponseField>

<ResponseField name="deliveredAt" type="string | null">
  ISO 8601 — quando a mensagem foi entregue.
</ResponseField>

<ResponseField name="readAt" type="string | null">
  ISO 8601 — quando a mensagem foi lida (apenas quando as confirmações de leitura estão habilitadas).
</ResponseField>

<ResponseField name="providerTimestamp" type="string" required>
  ISO 8601 — timestamp do provedor para a mensagem (chave de ordenação).
</ResponseField>

<ResponseField name="createdAt" type="string" required>
  ISO 8601 — quando o registro foi criado no Pilot Status.
</ResponseField>

## Erros comuns

* `400 INVALID_DATE_RANGE` — `startDate` ou `endDate` não é uma string ISO 8601 válida, ou `startDate > endDate`.
* `400 NUMBER_NOT_FOUND` — a chave de API não está vinculada a um número de WhatsApp.
* `401` — cabeçalho `x-api-key` ausente ou inválido.
* `403` — chave com escopo de tenant utilizada (é necessária uma chave com escopo de número).
