Recursive function to get all Zendesk tickets I'm developing a Python library to consume the Zendesk search API.
Problem is, Zendesk limits search results to 1000 items. Thus in order to get all the results if they are greater than 1000 I need to call the endpoint several times with a recursive function storing the latest created datetime for a ticket once the 1000 limit is reached.

My code at the moment works but it feels wrong. Could you help me to improve this recursive function? For instance I'd prefer not to declare an empty list at the constructor but instead inside the function.

Here is the code:

init.py

import requests
import base64
from zdesktools.lib.api import SearchApi, TicketsApi


class ZdeskTools(object):
    def __init__(self, zendeskApiUrl=None,
                 username=None,
                 password=None):
        session = self._begin_session(username, password)
        config = {
            'zendeskApiUrl': zendeskApiUrl,
            'session': session
        }
        self.search = SearchApi(**config)
        self.tickets = TicketsApi(**config)
        # self.metrics = MetricsApi(**config)

    def _begin_session(self, username, password):
        session = requests.Session()
        username_password = f'{username}/token:{password}'
        encoded_bytes = base64.b64encode(username_password.encode('utf-8'))
        encoded_string = str(encoded_bytes, 'utf-8')
        headers = {
            'Authorization': f'Basic {encoded_string}'
        }
        session.headers.update(headers)
        return session


api.py

from urllib.parse import urlencode
import json
import pprint


class SearchApi(object):
    def __init__(self, **config):
        self.session = config.get('session')
        self.url = config.get('zendeskApiUrl')+'/search.json?'
        self.created_at = []
        self.tickets = []

    def get_ticket_numbers(self, search_params):
        response = self.session.get(f'{self.url}{urlencode(search_params)}')
        data = response.json()
        if 'results' in data:
            for result in data['results']:
                self.created_at.append(result['created_at'])
                self.tickets.append(result['id'])
        if 'next_page' in data:
            if data['next_page'] is not None:
                self.url = data['next_page']
                self.get_ticket_numbers(search_params)
        else:
            self.url = self.url[:self.url.index('?')+1]
            search_params['query'] = search_params['query'] + \
                f' created_at&gt;={self.created_at[-1]}'
            self.get_ticket_numbers(search_params)
        return self.tickets
My usual advice for implementors of recursive algorithms Is this: figure out how to do it without recursion (although i dont know how to prove it Is Always better, i can prove it Is never worse. And i can prove it Is Always possible.)

This advice Is yet stronger in your case because there Is nothing recursive about pagination. Its you who made it recursive artificially.

Further, the api has reasons to provide the data with a page limit. They dont want to run to memory issues when serving those data to you.

Nor should you want to run into memory issues when processing the data. If Its not restricting you, you should also process the data page by page discarding the previous page before loading another one.