Skip to main content
This guide walks through building a small client that pulls completed checkout transactions from the Vori API on a recurring schedule — the pattern you can use to feed your own reporting, BI, or accounting tools.

Authenticate with an API key

See the authentication docs for how to create an API key. Make sure the role you assign it can read transactions.

List transactions

The list endpoint supports the following filters, declared as typed query parameters rather than one opaque filter blob: Every list response uses one envelope:

Page through results

Pagination is cursor-based, not offset-based — pass limit and starting_after/ending_before with the id of the last record you saw, and keep going while has_more is true:
Results are always ordered by id descending — this order is not client-selectable.

Run it on a schedule for periodic downloads

For a recurring reporting job, don’t re-download the full history each run. Track a watermark and filter on completed_at[gte] from where the last run left off:
One run covers every store your API key can read, so keep a single watermark rather than one per store. Every transaction carries store_id, so you can split the results by store in your own reporting store after the fact. Polling store by store multiplies your request count and leaves you several watermarks to keep in step, for no benefit. Two things make that watermark safe. It advances to the time the sync started rather than the largest completed_at observed, and it rewinds by a short buffer before it is stored. Every transaction reaches Vori some time after it completes — usually seconds, but a lane that has lost its connection sends its batch when it reconnects — so a window beginning exactly where the last one ended would miss whatever landed in between. Fifteen minutes covers the ordinary gap; raise it if your lanes can be offline for longer. Both mean a run re-reads a little of what the previous run already wrote, which is why the write has to key on id and upsert. Re-reading a transaction is harmless. Missing one is not.

Handle rate limits

Requests are rate-limited per API key. Every response carries your current standing:
  • X-RateLimit-Limit — max requests allowed in the current window
  • X-RateLimit-Remaining — requests left in the window
A 429 response includes Retry-After (seconds) — back off and retry rather than hammering the endpoint.

Putting it together

Everything above in one script. Point VORI_API_KEY at your key, replace write_to_your_reporting_store, and run it on whatever schedule suits you — cron, Airflow, a worker loop. It writes each page as it arrives rather than collecting everything first, so memory stays flat however long the window is, and a run that dies partway keeps the pages it already wrote. The checkpoint records how far through the current window it got and where the next window will start.
The checkpoint is saved after every page and carries both values, but only the cursor changes as you go — the watermark keeps the previous run’s value until the whole window has been written.Transactions come back newest first, so a run partway through has written the recent ones and has not yet reached the older ones. Advancing the watermark there and then failing would leave the next run starting after those older transactions, skipping them permanently. The watermark describes the window, not the page, so it can only move once the window is exhausted.
Each row in data is a complete transaction, with its own line items and payments, so this script never needs a second call per transaction. The refunds array is the exception: it holds a reference to each refund — its ID, timestamps and amounts — not the refund’s own line items and payments. You do not need to fetch those separately either, because a refund is itself a transaction and arrives as its own row in the same feed, where you can match it back by ID.