Se você estiver criando integrações com o Zendesk, descobrirá rapidamente que a API não entrega todo o seu banco de dados de tickets de uma só vez. Em vez disso, ela serve os dados em pedaços pequenos por meio de um mecanismo chamado paginação. Isso é por design. A paginação mantém a API responsiva e evita timeouts quando você está lidando com milhares (ou milhões) de tickets de suporte.
Mas é aqui que fica interessante. O Zendesk oferece duas maneiras diferentes de paginar seus dados: paginação com cursor e paginação por deslocamento (offset). Uma é rápida, moderna e virtualmente ilimitada. A outra é limitada a 10.000 registros e carrega alguma bagagem de designs de API mais antigos. Desde agosto de 2023, o Zendesk tem incentivado os desenvolvedores a usar a paginação com cursor, aplicando limites estritos ao método de deslocamento (offset).
Neste guia, vamos percorrer ambas as abordagens de paginação com exemplos de código funcionais. Você aprenderá quando usar cada método, como lidar com casos extremos e quais armadilhas evitar. E se você está pensando que deve haver uma maneira mais fácil de trabalhar com os dados do Zendesk sem escrever a lógica de paginação você mesmo, vamos abordar isso também.
Para mais contexto sobre as abordagens de paginação do Zendesk, você também pode achar útil nosso guia completo para paginar tickets do Zendesk.
Entendendo a paginação na API Zendesk
Antes de mergulharmos no código, vamos esclarecer por que a paginação existe e como ela funciona em alto nível.
A API Zendesk divide grandes conjuntos de resultados em páginas menores por motivos de desempenho. Solicitar 100.000 tickets em uma única chamada de API causaria timeout ou travaria a maioria dos sistemas. Em vez disso, você solicita a página 1, processa esses resultados, depois solicita a página 2 e assim por diante até ter recuperado tudo.
Diferentes endpoints têm diferentes tamanhos de página padrão:
- Tickets e usuários: 100 itens por página
- Artigos da Central de Ajuda: 30 itens por página
- Resultados de pesquisa: 100 itens por página no máximo
Você geralmente pode ajustar o tamanho da página dentro dos limites, mas não pode exceder o máximo para nenhum endpoint específico.
Todas as solicitações de API contam para o seu limite de taxa. O Zendesk permite um certo número de solicitações por minuto, dependendo do seu plano, e a paginação pode consumir essa cota rapidamente se você estiver recuperando grandes conjuntos de dados. A boa notícia é que a paginação com cursor é mais eficiente do que a paginação por deslocamento (offset), então mudar de método pode realmente reduzir o uso da sua API.
Uma mudança crítica para saber: a partir de 15 de agosto de 2023, as solicitações de paginação baseadas em deslocamento (offset) além dos primeiros 10.000 registros (100 páginas) retornam um erro 400 Bad Request. Se você precisar de mais de 10.000 registros, a paginação com cursor agora é sua única opção. Saiba mais sobre esta mudança no anúncio de paginação por deslocamento (offset) do Zendesk.
Paginação com cursor vs paginação por deslocamento (offset)
Vamos detalhar as diferenças entre essas duas abordagens para que você possa escolher a certa para o seu caso de uso.
| Característica | Paginação com Cursor | Paginação por Deslocamento (Offset) |
|---|---|---|
| Limite de registro | Ilimitado | 10.000 no máximo |
| Desempenho | Consistente (rápido mesmo em páginas profundas) | Degrada à medida que o número da página aumenta |
| Contagem total disponível | Não | Sim (propriedade count) |
| Ir para página arbitrária | Não é possível | Possível |
| Consistência de dados durante a paginação | Melhor | Propenso a duplicatas/registros perdidos |
| Recomendação do Zendesk | Recomendado | Suporte legado apenas |
Use a paginação com cursor quando:
- Você precisa de mais de 10.000 registros
- O desempenho é importante (especialmente para grandes conjuntos de dados)
- Você está processando dados sequencialmente sem precisar pular
Use a paginação por deslocamento (offset) quando:
- Você precisa da contagem total de registros
- Você está construindo uma interface do usuário que permite aos usuários pular para páginas específicas
- Você está trabalhando com um pequeno conjunto de dados (menos de 10.000 registros) e a simplicidade é importante
Se você estiver usando atualmente a paginação por deslocamento (offset) e atingindo o limite de 10.000 registros, migrar para a paginação com cursor é simples. As principais mudanças são:
- Substitua o parâmetro
pageporpage[size] - Verifique
meta.has_moreem vez de verificar senext_pageé nulo - Use
links.nextpara o URL da próxima página em vez denext_page
Na eesel AI, nós nos integramos diretamente com o Zendesk e lidamos com toda a complexidade da paginação automaticamente. Mas se você estiver criando integrações personalizadas, entender essas diferenças é essencial.
Como funciona a paginação com cursor
A paginação com cursor usa um ponteiro (o cursor) que rastreia sua posição no conjunto de dados em vez de contar os registros desde o início a cada vez. Isso o torna significativamente mais rápido para grandes conjuntos de dados porque a API não precisa contar e pular registros para encontrar sua página.
Para habilitar a paginação com cursor, adicione um parâmetro page[size] à sua solicitação. Isso diz ao Zendesk que você deseja usar o modo de cursor e especifica quantos itens retornar por página (até 100 para a maioria dos endpoints). Consulte a documentação de paginação com cursor do Zendesk para obter detalhes completos.
A resposta inclui dois objetos-chave:
- meta: Contém
has_more(booleano),after_cursorebefore_cursor - links: Contém URLs
nexteprevpara as páginas adjacentes
Veja como é uma resposta típica:
{
"tickets": [
{ "id": 1, "subject": "Sample ticket" },
{ "id": 2, "subject": "Another ticket" }
],
"meta": {
"has_more": true,
"after_cursor": "eyJvIjoibmljZV9pZCIsInYiOiJhV2tCQUFBQUFBQUEifQ==",
"before_cursor": "eyJvIjoibmljZV9pZCIsInYiOiJhUzRCQUFBQUFBQUEifQ=="
},
"links": {
"next": "https://example.zendesk.com/api/v2/tickets.json?page[size]=100&page[after]=eyJvIjoibmljZV9pZCIsInYiOiJhV2tCQUFBQUFBQUEifQ==",
"prev": "https://example.zendesk.com/api/v2/tickets.json?page[size]=100&page[before]=eyJvIjoibmljZV9pZCIsInYiOiJhUzRCQUFBQUFBQUEifQ=="
}
}
Você continua paginando até que meta.has_more seja falso. Nesse ponto, você recuperou todos os registros.
Implementando a paginação com cursor em Python
Aqui está um exemplo completo e funcional usando Python e a biblioteca requests:
import requests
import time
ZENDESK_SUBDOMAIN = 'your-subdomain'
ZENDESK_EMAIL = 'your-email@example.com'
ZENDESK_API_TOKEN = 'your-api-token'
BASE_URL = f'https://{ZENDESK_SUBDOMAIN}.zendesk.com/api/v2/tickets.json'
auth = (f'{ZENDESK_EMAIL}/token', ZENDESK_API_TOKEN)
def fetch_all_tickets():
tickets = []
url = BASE_URL
params = {'page[size]': 100} # Use cursor pagination with 100 items per page
while url:
response = requests.get(url, auth=auth, params=params)
# Handle rate limiting
if response.status_code == 429:
retry_after = int(response.headers.get('Retry-After', 60))
print(f'Rate limited. Waiting {retry_after} seconds...')
time.sleep(retry_after)
continue
response.raise_for_status()
data = response.json()
# Process tickets from this page
for ticket in data['tickets']:
tickets.append(ticket)
print(f"Fetched ticket {ticket['id']}: {ticket['subject']}")
# Check if there are more pages
if data['meta']['has_more']:
url = data['links']['next']
params = None # Next URL already includes all parameters
else:
url = None
return tickets
if __name__ == '__main__':
all_tickets = fetch_all_tickets()
print(f'\nTotal tickets fetched: {len(all_tickets)}')
Coisas importantes a serem observadas neste exemplo:
- Começamos com
page[size]=100para habilitar a paginação com cursor - Verificamos o limite de taxa (HTTP 429) e respeitamos o cabeçalho Retry-After
- Após a primeira solicitação, usamos o URL
links.nextdiretamente para as páginas subsequentes - O loop continua até que
has_moreseja falso
Implementando a paginação com cursor em Node.js
Aqui está a mesma lógica em Node.js usando axios:
const axios = require('axios');
const ZENDESK_SUBDOMAIN = 'your-subdomain';
const ZENDESK_EMAIL = 'your-email@example.com';
const ZENDESK_API_TOKEN = 'your-api-token';
const BASE_URL = `https://${ZENDESK_SUBDOMAIN}.zendesk.com/api/v2/tickets.json`;
const auth = Buffer.from(`${ZENDESK_EMAIL}/token:${ZENDESK_API_TOKEN}`).toString('base64');
async function fetchAllTickets() {
const tickets = [];
let url = BASE_URL;
let params = { 'page[size]': 100 };
try {
do {
const response = await axios.get(url, {
headers: { Authorization: `Basic ${auth}` },
params: params
});
const data = response.data;
// Process tickets from this page
for (const ticket of data.tickets) {
tickets.push(ticket);
console.log(`Fetched ticket ${ticket.id}: ${ticket.subject}`);
}
// Prepare for next page
if (data.meta.has_more) {
url = data.links.next;
params = null; // Next URL includes all parameters
} else {
url = null;
}
} while (url);
console.log(`\nTotal tickets fetched: ${tickets.length}`);
return tickets;
} catch (error) {
if (error.response && error.response.status === 429) {
const retryAfter = error.response.headers['retry-after'] || 60;
console.log(`Rate limited. Retry after ${retryAfter} seconds`);
} else {
console.error('Error fetching tickets:', error.message);
}
throw error;
}
}
fetchAllTickets();
Armadilhas comuns e como evitá-las
Mesmo com código funcional, você encontrará casos extremos em produção. Veja como lidar com os problemas mais comuns.
Lidando com limites de taxa
O Zendesk retorna HTTP 429 quando você excede seu limite de taxa. A resposta inclui um cabeçalho Retry-After informando quantos segundos esperar. Sempre implemente o backoff exponencial em vez de bombardear a API:
import time
def make_request_with_backoff(url, auth, max_retries=5):
for attempt in range(max_retries):
response = requests.get(url, auth=auth)
if response.status_code == 429:
retry_after = int(response.headers.get('Retry-After', 60))
# Exponential backoff: wait longer with each retry
wait_time = retry_after * (2 ** attempt)
time.sleep(wait_time)
continue
return response
raise Exception('Max retries exceeded')
Lidando com páginas vazias
Ocasionalmente, você pode encontrar uma página vazia onde has_more era verdadeiro, mas a próxima solicitação não retorna nenhum registro. Isso pode acontecer quando o registro final da página anterior era o último registro em todo o conjunto de dados. Salve o valor after_cursor anterior para uso futuro neste caso.
Expiração do cursor
Para o endpoint Export Search Results, os cursores expiram após uma hora. Se o seu processamento demorar mais do que isso, você precisará reiniciar a exportação ou processar os dados mais rapidamente.
Limitações da API de pesquisa
A API de pesquisa tem suas próprias peculiaridades de paginação:
- Máximo de 1.000 resultados por consulta no total
- Máximo de 100 resultados por página
- Usa apenas paginação por deslocamento (offset)
- Solicitar a página 11 (com 100 resultados por página) retorna um erro 422
Se você precisar de mais de 1.000 resultados de pesquisa, use o endpoint Export Search Results, que suporta paginação com cursor e retorna até 1.000 registros por página. Consulte a documentação da API de pesquisa do Zendesk para obter mais detalhes.
Consistência de dados durante a paginação
Os dados paginados podem ser imprecisos devido à natureza em tempo real dos dados. Um ou mais itens podem ser adicionados ou removidos da sua instância de banco de dados entre as solicitações. Uma maneira de reduzir as imprecisões da paginação (embora não eliminá-las completamente) é classificar os registros por um atributo que não pode ser modificado, como o ID ou a data de criação, se isso for suportado pelo recurso.
Na eesel AI, nosso Agente de IA lida com essas complexidades automaticamente. Gerenciamos o limite de taxa, a expiração do cursor e os problemas de consistência de dados para que você não precise escrever essa lógica você mesmo.
Migrando da paginação por deslocamento (offset) para a paginação com cursor
Se você estiver usando atualmente a paginação por deslocamento (offset), aqui está um guia de migração rápido mostrando as principais mudanças:
Antes (paginação por deslocamento (offset)):
url = f'https://{subdomain}.zendesk.com/api/v2/tickets.json'
while url:
response = requests.get(url, auth=auth)
data = response.json()
# Process tickets...
url = data['next_page'] # null when done
Depois (paginação com cursor):
url = f'https://{subdomain}.zendesk.com/api/v2/tickets.json?page[size]=100'
params = {'page[size]': 100}
while url:
response = requests.get(url, auth=auth, params=params)
data = response.json()
# Process tickets...
if data['meta']['has_more']:
url = data['links']['next']
params = None
else:
url = None
As principais mudanças são:
- Adicione o parâmetro
page[size]para habilitar o modo de cursor - Verifique
meta.has_moreem vez de verificar senext_pageé nulo - Use
links.nextpara o URL da próxima página em vez denext_page - Remova a dependência da propriedade
count(não disponível na paginação com cursor)
Ignore a complexidade da paginação com a eesel AI
Criar integrações de API personalizadas com paginação adequada, tratamento de erros e limite de taxa exige um esforço de desenvolvimento significativo. Você precisa escrever o código, mantê-lo à medida que o Zendesk atualiza sua API e lidar com todos os casos extremos que discutimos.
Para muitas equipes, existe um caminho mais simples. A eesel AI se conecta diretamente à sua conta Zendesk e lida com toda a recuperação de dados automaticamente. Em vez de escrever a lógica de paginação, você configura o que deseja realizar por meio de uma interface visual.
Veja como funciona:
- Conecte a eesel AI à sua conta Zendesk em minutos
- A IA aprende com seus tickets anteriores, artigos da central de ajuda e macros
- Você define regras de automação em linguagem simples (sem necessidade de código)
- A eesel AI lida com todas as chamadas de API, paginação e processamento de dados
Você pode automatizar o roteamento de tickets, redigir respostas para seus agentes, marcar e priorizar tickets recebidos e gerar relatórios. Tudo sem escrever uma única linha de código de paginação.
Para equipes que precisam de integrações personalizadas, a API Zendesk continua sendo a escolha certa. Mas se seu objetivo é automatizar fluxos de trabalho e melhorar a eficiência, ferramentas como a eesel AI podem levá-lo até lá mais rapidamente. Confira nossos preços para ver como nos comparamos à criação e manutenção de soluções personalizadas.

Perguntas Frequentes
Compartilhe esta postagem

Article by
Stevia Putri
Stevia Putri is a marketing generalist at eesel AI, where she helps turn powerful AI tools into stories that resonate. She’s driven by curiosity, clarity, and the human side of technology.



