1. The missing rows can be inside one invoice
An invoice export can contain every parent invoice yet omit invoice lines. Stripe explicitly says a retrieved invoice’s lines property contains only the first handful of items and provides a separate URL for the full paginated list.[8] This is a resource-boundary problem, not Search freshness or business transfer matching. The export’s unit of completeness must therefore include each invoice’s line collection, not merely the invoice IDs returned by an outer iterator.
2. Public reports show why this matters
An Airbyte pull request describes missing invoice-line records because its incremental path expanded embedded lines.data while its paginator checked only the outer events list. Its proposed repair retrieves the full invoice-lines collection when the embedded list indicates more items.[11] This is a third-party report, not a test performed for this article. A separate Stripe Java issue asks about paginating an upcoming invoice with more than ten items while preserving preview parameters.[9] That historical preview issue demonstrates developer demand; it is not evidence that the same SDK bug remains today.
3. Start a child-resource traversal explicitly
For an existing invoice, use GET /v1/invoices/{id}/lines. Stripe documents this as the endpoint returning the full paginated collection of line-item objects, with limit from 1 to 100 and a default of 10.[8] A straightforward export design always reads this endpoint for each selected invoice, rather than treating embedded rows as a complete dataset. Alternatively, explicitly inspect the embedded collection’s completion state. Never infer completeness merely from a plausible invoice total or a successfully retrieved parent object.
4. Advance using line IDs, not invoice IDs
After writing a page of lines, inspect that child response’s has_more. If true, supply the last returned line object’s ID as starting_after on the same invoice-lines endpoint; continue until false.[8][2] The invoice ID stays in the path and is not the continuation cursor. For reverse navigation, ending_before uses the first returned object ID; do not combine it with starting_after.[8][1] Follow the endpoint’s returned sequence rather than sorting IDs yourself. Finish processing the last page before marking the invoice complete.
5. Auto-pagination does not erase the parent boundary
Stripe’s auto-pagination helpers make successive requests until the traversed list ends.[2] Applying a helper to the parent invoice list is not equivalent to iterating each invoice’s separate lines URL.[8] Recommended structure: enumerate selected invoice IDs, enqueue a line-export task for each, then complete each child iterator independently. Store parent invoice identity on every exported row. An event-based importer should likewise distinguish an event-list continuation from a nested invoice-lines continuation; the Airbyte report illustrates the consequence of checking only the former.[11]
6. Checkpoint each invoice after durable writes
Recommended child-task state includes account context, test/live context, API version, invoice ID, endpoint, last committed line ID and a completion flag. Keep parent enumeration progress separately. Write rows before advancing the line cursor, and use account, invoice and line identity to make replay idempotent. If a worker stops after rows commit but before the checkpoint advances, replay should not create duplicate export rows. If a page is empty while claiming more results, or the cursor fails to advance, retain an error state. These are application safeguards, not Stripe snapshot or exactly-once guarantees.
7. Audit child completion before closing the export
Record invoices selected, child tasks completed, committed line counts and unresolved failures. Revisit previously exported invoices if an older importer assumed embedded lines were complete; fixing future traversal alone does not establish historical completeness. Keep the initial article’s scope narrow: existing invoice-line exports for supported Stripe accounts with authorized access, not upcoming-invoice simulation, Search, or PayIn functionality. Before production use, exercise multiple child pages and interruption after a committed write. No live-account export or implementation test is claimed here; complete traversal remains an input to accounting checks, not proof that the accounts reconcile.
Sources and dates
Official documentation supports technical behavior; community questions demonstrate qualitative demand only. Retrieved and checked on 2026-09-22. Retrieval is not publication. Unstated dates remain unknown. This is documentation research, not a live-account test, PayIn feature claim, or legal, tax or financial advice. Account eligibility and regional availability require separate confirmation.
- [1] Pagination · Publication date not stated; update date not stated · Checked 2026-09-22.
- [2] How pagination works · Publication date not stated; update date not stated · Checked 2026-09-22.
- [8] Retrieve an invoice's line items · Publication date not stated; update date not stated · Checked 2026-09-22.
- [9] Fetching upcoming invoice’s line items loses the request’s original parameters · Published: 2018-02-19; Updated: 2022-11-23 · Checked 2026-09-22.
- [11] Fetch complete invoice line item lists when event payloads are truncated · Published: 2026-08-26; Updated: 2026-09-21 · Checked 2026-09-22.