문서로 건너뛰기
Python

페이지네이션

한 페이지는 `list`, 모든 페이지는 `list_all`, 한 번에 한 항목씩은 `iterate`.

한 페이지: list

list_page.py
cursor: str | None = None while True:    page = client.emails.list(status='failed', limit=50, cursor=cursor)     for email in page['items']:        print(email['id'], email['lastError'])     if not page['hasMore'] or page['nextCursor'] is None:        break     cursor = page['nextCursor']

페이지는 {'items': [...], 'hasMore': ..., 'nextCursor': ...}입니다. 그다음 페이지를 받으려면 같은 필터와 함께 nextCursor를 cursor=로 돌려보내세요.

마지막 페이지에서 nextCursor는 None이며, hasMore는 이 페이지 너머에도 일치하는 행이 더 있는지 알려 줍니다. openemail.types에서 페이지는 Page[T]이므로, emails.list는 Page[EmailResource]를 반환하고 타입 검사기는 각 항목에 무엇이 담기는지 압니다.

API는 스레드와 초안을 pageToken으로 페이지 처리합니다. 클라이언트는 다른 모든 목록과 마찬가지로 이를 nextCursor로 건네주고 cursor=로 돌려받으며, list_all과 iterate가 대신 따라갑니다. 이 값은 불투명하므로, 받은 것을 그대로 돌려주고 직접 만들지 마십시오.

모든 페이지: list_all

list_all.py
complaints = client.suppressions.list_all(reason='complaint')print(len(complaints), [row['email'] for row in complaints]) book = client.addresses.list_all()print(book['unrestricted'], len(book['addresses']), len(book['domains']))

list_all은 nextCursor를 마지막 페이지까지 따라가 하나의 list를 반환합니다. 반환하기 전에 모든 페이지를 가져오므로, 끝이 있는 필터를 주십시오.

다른 것을 반환하는 것은 addresses.list_all 하나뿐입니다. 주소록 전체, 즉 {'unrestricted': ..., 'addresses': [...], 'domains': [...]}를 반환하며, 모든 페이지의 주소가 그 안에 들어 있습니다.

한 번에 하나씩: iterate

iterate.py
from itertools import islice for email in client.emails.iterate(status='bounced'):    if email['createdAt'] < '2026-09-01':        break     print(email['id'], email['lastError']) first_ten = list(islice(client.threads.iterate(folder='inbox'), 10))print([thread['id'] for thread in first_ten])

iterate는 제너레이터를 반환합니다. 호출만으로는 아무것도 보내지 않습니다. 첫 페이지는 루프가 첫 항목을 요청할 때 가져오고, 그 뒤의 각 페이지는 루프가 앞 페이지의 끝에 도달했을 때만 가져옵니다. 루프를 벗어나거나 itertools.islice로 일부만 취하면 요청이 멈춥니다.

list_all과 iterate의 limit=은 가져오는 각 페이지의 크기이지, 받게 될 항목 수의 상한이 아닙니다. 따라서 limit이 클수록 요청 수가 줄어듭니다. cursor=는 이미 가지고 있는 페이지에서부터 훑기 시작합니다. 둘 다 hasMore가 false이거나 nextCursor가 None이면 멈추고, 페이지가 자신을 가져온 커서를 가리킬 때도 멈추므로, 잘못 동작하는 페이지가 영원히 반복될 수 없습니다.

네임스페이스 안의 목록

list_all과 iterate는 옆에 있는 list와 같은 엔드포인트를 페이지별로 훑으며, 훑는 목록의 이름을 딴 다른 쌍들도 마찬가지입니다. 각 쌍은 해당 목록과 같은 필터를 받습니다.

네임스페이스한 페이지모든 페이지한 번에 하나씩
emailslist_eventslist_all_eventsiterate_events
calendarlist_eventslist_all_eventsiterate_events
templateslist_versionslist_all_versionsiterate_versions
templateslist_imageslist_all_imagesiterate_images
trackinglist_openslist_all_opensiterate_opens
trackinglist_clickslist_all_clicksiterate_clicks
ruleslist_runslist_all_runsiterate_runs
audienceslist_contactslist_all_contactsiterate_contacts
broadcastslist_recipientslist_all_recipientsiterate_recipients
contactslist_peoplelist_all_peopleiterate_people
contactslist_threadslist_all_threadsiterate_threads
domainslist_addresseslist_all_addressesiterate_addresses
formslist_submissionslist_all_submissionsiterate_submissions
memberslist_invitationslist_all_invitationsiterate_invitations
fileslist_linkslist_all_linksiterate_links
temp_maillist_messageslist_all_messagesiterate_messages
webhookslist_deliverieslist_all_deliveriesiterate_deliveries
webhookslist_workspace_deliverieslist_all_workspace_deliveriesiterate_workspace_deliveries
webhookslist_activitylist_all_activityiterate_activity
webhookslist_workspace_activitylist_all_workspace_activityiterate_workspace_activity
keyslist_requestslist_all_requestsiterate_requests
keyslist_activitylist_all_activityiterate_activity
keyslist_workspace_requestslist_all_workspace_requestsiterate_workspace_requests
keyslist_workspace_activitylist_all_workspace_activityiterate_workspace_activity

더 많은 것을 담은 페이지

other_pages.py
people = client.contacts.list_people(sort='recent', limit=50)print(len(people['items']), people['seen'], people['nextCursor']) sends = client.templates.list_sends('order-shipped', page=2, page_size=50)print(sends['total'], sends['page'], sends['pageSize'], len(sends['items']))

몇몇 목록은 페이지 이상의 것을 담습니다. contacts.list_people은 items, hasMore, nextCursor 옆에 seen을 더하고, temp_mail.list_messages는 expiresAt을 더하며, addresses.list는 items 대신 addresses를 unrestricted, domains, hasMore, nextCursor와 함께 반환합니다. 모두 여전히 cursor=로 이어 가고 각자의 list_all과 iterate로 훑습니다.

두 목록은 다른 방식으로 페이지를 나눕니다. templates.list_sends는 페이지 번호를 셉니다. page=와 page_size=를 넘기고, items 옆의 total, page, pageSize를 읽습니다. imports.list_failures는 API가 보낸 그대로인 {'object': 'list', 'data': [...], 'nextCursor': ...}로 남겨 두며, nextCursor에 담긴 숫자를 after=로 넘겨 이어 갑니다. 둘 다 list_all이나 iterate가 없습니다.

페이지 크기

대부분의 목록은 1에서 100까지의 limit=을 받고 기본값은 25이며, 이 두 숫자는 PAGE_LIMITS(PAGE_LIMITS.MAX_LIMIT와 PAGE_LIMITS.DEFAULT_LIMIT)에 있습니다. contacts.list, audiences.list_contacts, broadcasts.list_recipients, tracking 목록은 최대 200까지 받고 기본값은 50이며, temp_mail.list_messages는 최대 50까지 받습니다. 범위를 벗어난 값은 범위 안으로 잘라 맞추지 않고 422로 거부됩니다.

AsyncOpenEmail에서

비동기 클라이언트도 같은 방식으로 페이지를 넘깁니다. list와 list_all은 await로 호출하고, iterate는 비동기 이터레이터를 반환하므로 호출 앞에 await를 붙이지 않고 async for로 순회합니다.

async_pages.py
import asyncio from openemail import AsyncOpenEmail  async def main() -> None:    async with AsyncOpenEmail() as client:        page = await client.emails.list(status='failed', limit=50)        print(len(page['items']), page['nextCursor'])         everyone = await client.members.list_all()        print(len(everyone))         async for delivery in client.webhooks.iterate_deliveries('whe_…', status='failed'):            print(delivery['eventType'], delivery['responseCode'])  asyncio.run(main())