पेजिनेशन
एक पेज के लिए `list`, हर पेज के लिए `list_all`, और एक बार में एक आइटम के लिए `iterate`।
एक पेज: list
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] लौटाता है और type checker जानता है कि हर आइटम में क्या है।
API थ्रेड और ड्राफ़्ट को pageToken के साथ पेज करता है। क्लाइंट इसे बाकी हर सूची की तरह आपको nextCursor के रूप में देता है और cursor= के रूप में वापस लेता है, और list_all तथा iterate आपके लिए उसका अनुसरण करते हैं। यह अपारदर्शी है: जो मिला वही वापस भेजें और ख़ुद कभी न बनाएँ।
हर पेज: list_all
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 लौटाता है। लौटने से पहले हर पेज fetch किया जाता है, इसलिए इसे ऐसा फ़िल्टर दें जो ख़त्म हो।
addresses.list_all ही अकेला है जो कुछ और लौटाता है: पूरी address book, {'unrestricted': ..., 'addresses': [...], 'domains': [...]}, जिसमें हर पेज के पते होते हैं।
एक बार में एक: iterate
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 एक generator लौटाता है। इसे कॉल करने से कुछ नहीं भेजा जाता: पहला पेज तब fetch होता है जब loop अपना पहला आइटम माँगता है, और उसके बाद का हर पेज तभी जब loop पिछले पेज के अंत तक पहुँचता है। loop से बाहर निकलना, या itertools.islice से एक slice लेना, अनुरोध रोक देता है।
list_all और iterate पर limit= उनके द्वारा fetch किए गए हर पेज का आकार है, न कि आपको मिलने वाले आइटम की कुल सीमा, इसलिए बड़ा limit मतलब कम अनुरोध। cursor= चलना उस पेज से शुरू करता है जो आपके पास पहले से है। दोनों तब रुकते हैं जब hasMore false हो या nextCursor None हो, और तब भी जब कोई पेज वही cursor बताए जिससे वह fetch हुआ था, ताकि ग़लत व्यवहार करने वाला पेज हमेशा के लिए loop में न घूमे।
किसी namespace के अंदर की सूचियाँ
list_all और iterate उसी endpoint से पेज-दर-पेज गुज़रते हैं जिससे उनके साथ वाला list, और यही बात उन दूसरी जोड़ियों पर भी लागू होती है जिनका नाम उस सूची पर रखा गया है जिसे वे पार करती हैं। हर जोड़ी वही फ़िल्टर लेती है जो उसकी सूची।
| नेमस्पेस | एक पेज | हर पेज | एक बार में एक |
|---|---|---|---|
| emails | list_events | list_all_events | iterate_events |
| calendar | list_events | list_all_events | iterate_events |
| templates | list_versions | list_all_versions | iterate_versions |
| templates | list_images | list_all_images | iterate_images |
| tracking | list_opens | list_all_opens | iterate_opens |
| tracking | list_clicks | list_all_clicks | iterate_clicks |
| rules | list_runs | list_all_runs | iterate_runs |
| audiences | list_contacts | list_all_contacts | iterate_contacts |
| broadcasts | list_recipients | list_all_recipients | iterate_recipients |
| contacts | list_people | list_all_people | iterate_people |
| contacts | list_threads | list_all_threads | iterate_threads |
| domains | list_addresses | list_all_addresses | iterate_addresses |
| forms | list_submissions | list_all_submissions | iterate_submissions |
| members | list_invitations | list_all_invitations | iterate_invitations |
| files | list_links | list_all_links | iterate_links |
| temp_mail | list_messages | list_all_messages | iterate_messages |
| webhooks | list_deliveries | list_all_deliveries | iterate_deliveries |
| webhooks | list_workspace_deliveries | list_all_workspace_deliveries | iterate_workspace_deliveries |
| webhooks | list_activity | list_all_activity | iterate_activity |
| webhooks | list_workspace_activity | list_all_workspace_activity | iterate_workspace_activity |
| keys | list_requests | list_all_requests | iterate_requests |
| keys | list_activity | list_all_activity | iterate_activity |
| keys | list_workspace_requests | list_all_workspace_requests | iterate_workspace_requests |
| keys | list_workspace_activity | list_all_workspace_activity | iterate_workspace_activity |
ज़्यादा जानकारी वाले पेज
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': ...}, और यह after= से आगे बढ़ता है, जो nextCursor में दी गई संख्या है। दोनों में से किसी के पास 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 एक async iterator लौटाता है जिस पर आप async for से loop चलाते हैं, कॉल के आगे कोई await लगाए बिना।
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())