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 partes menores por meio de um mecanismo chamado paginação (pagination). 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 por cursor (cursor pagination) e paginação por offset (offset pagination). 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 por cursor, aplicando limites estritos ao método de offset.
Neste guia, vamos percorrer ambas as abordagens de paginação com exemplos de código funcional. 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 automatizar os fluxos de trabalho do Zendesk sem escrever a lógica de paginação, também abordaremos isso.
Entendendo a paginação da API do 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 do 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 falha na 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é recuperar 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 da pesquisa: 100 itens por página no máximo
Geralmente, você 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 em relação ao seu limite de taxa (rate limit). 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 por cursor é mais eficiente do que a paginação por offset, então mudar de método pode realmente reduzir o uso da sua API.
Uma mudança crítica a saber: a partir de 15 de agosto de 2023, as solicitações de paginação baseadas em 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 por cursor agora é sua única opção. Saiba mais sobre essa mudança no anúncio de paginação por offset do Zendesk.
Paginação por cursor: o método recomendado
A paginação por cursor é a abordagem preferida do Zendesk para a maioria dos endpoints de lista. Ela 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 a torna significativamente mais rápida para grandes conjuntos de dados, porque a API não precisa contar e pular registros para encontrar sua página.
Como funciona a paginação por cursor
Para habilitar a paginação por cursor, adicione um parâmetro page[size] à sua solicitação. Isso diz ao Zendesk que você quer usar o modo de cursor e especifica quantos itens retornar por página (até 100 para a maioria dos endpoints).
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.
Exemplo em Python com paginação por cursor
Aqui está um exemplo funcional completo 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 por cursor - Verificamos o limite de taxa (HTTP 429) e respeitamos o cabeçalho Retry-After
- Após a primeira solicitação, usamos a URL
links.nextdiretamente para as páginas subsequentes - O loop continua até que
has_moreseja falso
Exemplo em Node.js com paginação por cursor
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();
Paginação por offset: o método legado
A paginação por offset é a abordagem mais antiga que o Zendesk ainda suporta, mas não recomenda mais. Ela funciona especificando um número de página e a API calcula quais registros retornar com base nesse offset desde o início do conjunto de dados.
Como funciona a paginação por offset
Com a paginação por offset, você usa o parâmetro page para solicitar um número de página específico e, opcionalmente, per_page para definir o número de itens por página (até 100).
A resposta inclui:
- next_page: URL para a próxima página ou nulo se você estiver na última página
- previous_page: URL para a página anterior ou nulo se você estiver na primeira página
- count: Número total de registros no conjunto de dados
Aqui está uma resposta típica:
{
"tickets": [
{ "id": 1, "subject": "Sample ticket" },
{ "id": 2, "subject": "Another ticket" }
],
"count": 15420,
"next_page": "https://example.zendesk.com/api/v2/tickets.json?page=2",
"previous_page": null
}
Exemplo em Python com paginação por offset
Veja como paginar usando o método de offset:
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_tickets_offset():
tickets = []
url = BASE_URL
while url:
response = requests.get(url, auth=auth)
if response.status_code == 429:
retry_after = int(response.headers.get('Retry-After', 60))
time.sleep(retry_after)
continue
if response.status_code == 400:
# You've hit the 10,000 record limit
print('Error: Cannot paginate beyond 10,000 records with offset pagination')
break
response.raise_for_status()
data = response.json()
for ticket in data['tickets']:
tickets.append(ticket)
# Move to next page
url = data['next_page']
return tickets
Limitações a serem observadas
A paginação por offset tem várias desvantagens que explicam por que o Zendesk está eliminando-a gradualmente:
-
O limite rígido de 10.000 registros: Você não pode recuperar mais de 10.000 registros usando a paginação por offset. Tentar solicitar a página 101 ou posterior retorna um erro 400.
-
Degradação do desempenho: À medida que você solicita páginas mais profundas (página 50, página 90), a API leva mais tempo para responder porque deve contar e pular todos os registros precedentes.
-
Inconsistência de dados: Se os registros forem adicionados ou removidos enquanto você estiver paginando, você poderá ver duplicatas ou perder registros. Isso acontece porque o offset é calculado novamente para cada solicitação com base no estado atual do conjunto de dados.
-
Nenhuma contagem total com paginação por cursor: Uma vantagem da paginação por offset é que ela retorna uma
countde registros totais. A paginação por cursor não fornece isso, então você precisará de uma chamada de API separada se precisar do total.
Cursor vs offset: qual você deve usar?
A escolha é direta para a maioria dos casos de uso:
| Recurso | Paginação por Cursor | Paginação por Offset |
|---|---|---|
| Limite de registros | Ilimitado | 10.000 no máximo |
| Desempenho | Consistente (rápido mesmo em páginas profundas) | Degrada-se conforme 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 por 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 offset quando:
- Você precisa da contagem total de registros
- Você está construindo uma interface do usuário que permite que os usuários pulem 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 offset e atingindo o limite de 10.000 registros, migrar para a paginação por 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 a URL da próxima página em vez denext_page
Armadilhas comuns de paginação e soluções
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 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 oferece suporte à paginação por cursor e retorna até 1.000 registros por página. Consulte a documentação da API de pesquisa do Zendesk para obter mais detalhes.
Automatizando fluxos de trabalho do Zendesk sem a API
Construir 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. eesel AI se conecta diretamente à sua conta do 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 o eesel AI à sua conta do Zendesk em minutos
- A IA aprende com seus tickets anteriores, artigos da central de ajuda e macros
- Você define regras de automação em português claro (sem necessidade de código)
- O eesel AI lida com todas as chamadas de API, paginação e processamento de dados
Você pode automatizar o roteamento de tickets, rascunhar 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 do Zendesk continua sendo a escolha certa. Mas se seu objetivo é automatizar fluxos de trabalho e melhorar a eficiência, ferramentas como o eesel AI podem levá-lo lá mais rapidamente.
Comece a automatizar seus fluxos de trabalho do Zendesk hoje mesmo
A paginação é um conceito fundamental ao trabalhar com a API do Zendesk. A paginação por cursor oferece melhor desempenho e sem limites de registro, tornando-a a escolha clara para a maioria das integrações modernas. A paginação por offset ainda tem seu lugar para conjuntos de dados menores e quando você precisa de contagens totais de registros, mas o limite de 10.000 registros significa que ela não é adequada para recuperação de dados em grande escala.
Os exemplos de código neste guia devem fornecer uma base sólida para implementar a paginação em seus próprios projetos. Lembre-se de lidar com os limites de taxa com elegância, fique atento a casos extremos, como páginas vazias, e escolha o método de paginação que se adapta ao seu caso de uso específico.
Se você preferir pular o desenvolvimento da API completamente e começar a automatizar seus fluxos de trabalho do Zendesk hoje mesmo, experimente o eesel AI. Ele lida com a complexidade técnica para que você possa se concentrar em fornecer um melhor suporte ao cliente.
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.



