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

# Paginação

> Como paginar listas na API do Connecta DESK com page e perPage, e como usar hasMore para saber se há mais páginas.

Todo `GET` de lista é paginado. Você escolhe a página com dois parâmetros de query, e o `meta` da
resposta informa se existem mais páginas.

<ParamField query="page" type="integer" default="1">
  Número da página, começando em 1. Um valor inválido ou menor que 1 volta para o padrão.
</ParamField>

<ParamField query="perPage" type="integer" default="20">
  Quantidade de itens por página. O limite padrão é 100. Se você pedir mais, recebe 100, sem erro.
</ParamField>

```bash theme={null}
curl --request GET \
  --url "$CONNECTA_URL/contacts?page=2&perPage=50" \
  --header "Authorization: Bearer $CONNECTA_TOKEN"
```

## O meta

```json theme={null}
{
  "data": [ "…50 contatos…" ],
  "meta": { "page": 2, "perPage": 50, "hasMore": true }
}
```

<ResponseField name="page" type="integer">
  A página que você recebeu.
</ResponseField>

<ResponseField name="perPage" type="integer">
  Quantidade de itens por página aplicada de fato, já considerando o limite.
</ResponseField>

<ResponseField name="hasMore" type="boolean">
  `true` quando existem registros depois desta página.
</ResponseField>

## Total de registros

O `meta` não informa o total de registros nem o total de páginas. Para saber se existe outra
página, use `hasMore`.

Se você precisa exibir uma contagem na tela, some os itens recebidos enquanto percorre as páginas.

## Percorrendo tudo

Para ler todos os registros, avance `page` enquanto `hasMore` for `true`.

<CodeGroup>
  ```javascript Node.js theme={null}
  async function* paginar(caminho, params = {}) {
    let page = 1;

    for (;;) {
      const query = new URLSearchParams({ ...params, page, perPage: 100 });
      const res = await fetch(`${process.env.CONNECTA_URL}${caminho}?${query}`, {
        headers: { Authorization: `Bearer ${process.env.CONNECTA_TOKEN}` }
      });

      if (!res.ok) throw new Error(`${res.status} em ${caminho}`);

      const { data, meta } = await res.json();
      yield* data;

      if (!meta.hasMore) return;
      page += 1;
    }
  }

  for await (const contato of paginar('/contacts', { search: 'silva' })) {
    console.log(contato.id, contato.name);
  }
  ```

  ```python Python theme={null}
  import os, requests

  def paginar(caminho, **params):
      page = 1

      while True:
          res = requests.get(
              f"{os.environ['CONNECTA_URL']}{caminho}",
              params={**params, "page": page, "perPage": 100},
              headers={"Authorization": f"Bearer {os.environ['CONNECTA_TOKEN']}"},
          )
          res.raise_for_status()

          corpo = res.json()
          yield from corpo["data"]

          if not corpo["meta"]["hasMore"]:
              return
          page += 1

  for contato in paginar("/contacts", search="silva"):
      print(contato["id"], contato["name"])
  ```

  ```php PHP theme={null}
  function paginar(string $caminho, array $params = []): iterable
  {
      $page = 1;

      while (true) {
          $query = http_build_query($params + ['page' => $page, 'perPage' => 100]);
          $ch = curl_init(getenv('CONNECTA_URL') . $caminho . '?' . $query);
          curl_setopt_array($ch, [
              CURLOPT_RETURNTRANSFER => true,
              CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('CONNECTA_TOKEN')],
          ]);

          $corpo = json_decode(curl_exec($ch), true);
          yield from $corpo['data'];

          if (!$corpo['meta']['hasMore']) {
              return;
          }
          $page++;
      }
  }
  ```
</CodeGroup>

<Warning>
  Uma varredura completa consome uma requisição por página, e cada uma conta no
  [limite por minuto](/essentials/limites-de-uso). Com `perPage=100`, você gasta 1 requisição a
  cada 100 registros. Antes de aumentar a frequência do laço, suba o `perPage`.
</Warning>

## Cuidado com dados que mudam

Cada página é calculada no momento da requisição, a partir da posição dos registros
(`page` × `perPage`). Se registros forem criados ou removidos entre uma página e outra, um item
pode aparecer duas vezes ou ficar de fora da varredura.

Para exportações que precisam ser exatas:

* Use um período fixo de datas quando o endpoint aceitar filtro por período.
* Remova duplicados pelo `id` ao juntar os resultados.
* Rode a varredura em um horário de menor movimento.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.