Migrando a paginação antiga

Migrando sua integração de paginação por página usando parâmetro page para o cursor

Para garantir a melhor experiência e performance, estamos migrando nossa paginação de page para cursor. Essa mudança traz um ganho significativo, especialmente para grandes volumes de dados.

A paginação por cursor oferece mais estabilidade e eficiência, pois aponta para uma posição fixa na lista de resultados. Isso minimiza problemas caso os dados sejam alterados durante a sua iteração.

Incentivamos você a migrar para o novo método para aproveitar todos os benefícios de uma integração mais robusta e performática.

❗️

Esta migração não é só uma recomendação de uso

A migração para a paginação por cursor é crucial para a excelência das operações que a PipeRun oferece. Por isso, a adoção deste novo método não é apenas uma recomendação, mas sim um passo que se tornará obrigatório em breve.

Migre sua integração com ajuda de IA: paginação pagecursorSe você usa uma ferramenta de IA (Claude, ChatGPT, Copilot, Gemini, Cursor etc.), copie o bloco abaixo, cole junto com o código da sua integração e peça a refatoração. Revise o resultado antes de aplicar em produção.
Refatore minha integração com a API do CRM PipeRun (`api.pipe.run`) para migrar da paginação antiga por número de página (parâmetro `page`) para a nova paginação por cursor (parâmetro `cursor`). Analise o código que vou fornecer, identifique **todos** os pontos que listam dados paginados da PipeRun e reescreva-os no formato novo, mantendo a linguagem e o estilo do código original. Se o meu código for **Python**, antes de refatorar, avalie a biblioteca oficial `piperun-extractor` (https://github.com/crmpiperun/piperun-extractor). Ela já implementa a paginação por cursor, faz carga incremental por data (`after`) e exporta para JSONL/Parquet. Se ela cobrir o meu caso de uso, recomende substituí-la ao código customizado em vez de refatorar; mantenha código próprio apenas se houver requisito que a biblioteca não atende, e justifique. ## Formato antigo (a remover) Requisição: ```http GET /v1/deals?show=10&page=1 ``` Resposta (campos de paginação): ```json { "success": true, "data": [{}, {}], "meta": { "total": 50, "count": 10, "per_page": 10, "current_page": 1, "total_pages": 5, "links": { "next": "https://api.pipe.run/v1/deals?show=10&page=2" } } } ``` A iteração incrementava `page` até atingir `total_pages` ou `data` vir vazio. ## Formato novo (a adotar) Primeira requisição — o `cursor` vazio é proposital: ```http GET /v1/deals?show=10&cursor= ``` Resposta (campos de paginação): ```json { "success": true, "data": [{}, {}], "meta": { "cursor": { "current": null, "prev": null, "next": "eyJpZCI7NDA2NTA3UTYsIl9wb2ludHNUb05leHRJdGVtRyI6dHJ1ZX0", "count": null } } } ``` Cada requisição seguinte repete a chamada passando em `cursor` o valor exato de `meta.cursor.next` da resposta anterior. A iteração termina quando `meta.cursor.next` vier `null`/vazio ou `data` vier vazio. Pseudocódigo de referência (adapte à linguagem do meu código): ```python cursor = "" # primeira chamada com cursor vazio while True: resp = api.get(f"/v1/deals?show=10&cursor={cursor}") processar(resp["data"]) cursor = resp["meta"]["cursor"]["next"] if not cursor or not resp["data"]: break ``` ## Regras obrigatórias 1. **As requisições de paginação DEVEM ser sequenciais.** Se o código atual busca páginas em paralelo — threads, workers, pool de conexões, `Promise.all`, `asyncio.gather`, goroutines, jobs em fila disparados por número de página, ou qualquer padrão do tipo "descobre `total_pages` e dispara N requisições" — remova esse paralelismo do loop de paginação. No formato novo, cada requisição depende do cursor retornado pela anterior; não existe como calcular cursors antecipadamente. Isso é uma decisão de arquitetura da PipeRun, não uma limitação a ser contornada. Paralelismo em outras partes do código (ex.: processamento dos dados após a busca) pode ser mantido. 2. Trate o cursor como uma string opaca: não decodifique, não modifique e não construa cursors manualmente. Apenas repasse o valor recebido em `meta.cursor.next`. 3. Remova toda dependência de `meta.total`, `meta.total_pages`, `meta.current_page`, `meta.per_page` e `meta.links` — esses campos não existem na resposta nova. Se houver barra de progresso ou log do tipo "página X de Y", substitua por contagem acumulada de registros processados. 4. Não altere o processamento dos dados (`data`), filtros de negócio, autenticação, retries ou tratamento de erros existentes. A mudança é apenas no mecanismo de paginação. 5. Mantenha o parâmetro `show` (tamanho da página). Para compensar a perda do paralelismo, considere aumentá-lo até o máximo permitido pela documentação da PipeRun, reduzindo o número total de requisições. 6. Evite ordenações avançadas/customizadas nas consultas paginadas por cursor. Se o código usa parâmetros de ordenação, sinalize isso na entrega. ## Casos que você deve sinalizar, não resolver silenciosamente - Código que pula direto para uma página específica (`page=N`): não existe equivalente no cursor, que só avança sequencialmente. - Checkpoints que persistem o número da página para retomar uma extração interrompida: o número de página não tem significado no formato novo. - Lógica que precisa saber o total de registros ou de páginas antes de iterar. Para cada caso encontrado, mostre o trecho de código, explique por que ele quebra e proponha uma alternativa (ex.: reiniciar a extração com filtros incrementais por data em vez de retomar por página). ## Entrega esperada 1. O código refatorado completo de todos os trechos alterados. 2. Um resumo das mudanças: arquivo/função e o que mudou em cada um. 3. A lista de pontos de atenção sinalizados acima, se existirem.

1. Paginação Antiga (page)

Neste modelo, a navegação entre as páginas era feita de forma sequencial, utilizando o parâmetro page. Você informava o número da página que desejava acessar (page=1, page=2, etc.) para buscar o próximo conjunto de dados. Então você tinha uma requisição assim:

GET /v1/deals?show=10&page=1

E recebia esta resposta:

{
  "success": true,
  "message": "OK",
  "data": [{...},{...}],
  "meta": {
    "total": 50,
    "count": 10,
    "per_page": 10,
    "current_page": 1,
    "total_pages": 5,
    "links": {
      "next": "https://api.pipe.run/v1/deals?show=1&page=2"
    }
  }
}

Para navegar em todas as paginas você iria iterar pagina a pagina, incrementando o número da pagina até atingir o limite de paginas ou não ter mais dados para serem recuperados. Exemplo de pseudo código em Python:

pagina = 1
while True:
    response = api.get(f"/deals?show=10&page={pagina}")
    // processamento dos dados
    if pagina >= response["meta"]["total_pages"] or not response["data"]:
        break
    pagina += 1

2. Paginação Nova (cursor)

A paginação por cursor oferece um método mais robusto e eficiente, ideal para lidar com grandes conjuntos de dados. Em vez de usar um número de página, você usa o valor de cursor.next retornado na resposta da API para buscar a próxima página. Esse cursor atua como um "marcador" que aponta para o último item do conjunto de dados anterior, garantindo uma busca contínua e precisa, mesmo que os dados sejam alterados durante a sua navegação. Então, para este novo formato você terá uma requisição assim:

GET /v1/deals?show=10&cursor=

Note que o conteúdo da primeira requisição é uma string vazia, e isto é proposital.

Obtendo uma resposta como a descrita abaixo:

{
  "success": true,
  "message": "OK",
  "data": [{...},{...}],
  "meta": {
    "cursor": {
      "current": null,
      "prev": null,
      "next": "eyJpZCI7NDA2NTA3UTYsIl9wb2ludHNUb05leHRJdGVtRyI6dHJ1ZX0",
      "count": null
    }
  }
}

Para navegar em todas as paginas você irá iterar pagina a pagina, usando a hash cursor.next da requisição anterior, até ela ser null ou não ter mais dados para serem recuperados. Neste exemplo, a segunda requisição seria assim:

GET /v1/deals?show=10&cursor=eyJpZCI7NDA2NTA3UTYsIl9wb2ludHNUb05leHRJdGVtRyI6dHJ1ZX0

Exemplo de pseudo código em Python:

cursor = ""  # começa como string vazia
while True:
    response = api.get(f"/deals?show=10&cursor={cursor}")
    // processamento dos dados
    cursor = response["meta"]["cursor"]["next"]
    if not cursor or not response["data"]:
        break

3. O que muda em relação ao sistema antigo?

Diferenças Práticas

AntigoNovo
Parâmetro page=NParâmetro cursor=valor
Pode ir direto à página NSó avança para próxima "página" conhecida
Possível saber total de páginas/itensNão é possivel saber o total de páginas de imediato
Gera problemas se os dados mudam no meio do processoCursor aponta diretamente para o ponto certo, reduz esses problemas
Muito lentoMuito rápido
Ordenações avançadas são possíveis mas não recomendadasOrdenações avançadas podem deduplicar dados com itens semelhantes

Por quê mudar?

  • Melhor para grandes volumese menos erros se os dados mudam enquanto você percorre
  • Mais escalável O cursor aponta para um ponto fixo do resultado, e não depende de contagens que podem variar enquanto a lista muda.

Did this page help you?