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
Every list response uses one envelope:
Page through results
Pagination is cursor-based, not offset-based — passlimit and starting_after/ending_before with the id of the last record you saw, and keep going while has_more is true:
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 oncompleted_at[gte] from where the last run left off:
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 windowX-RateLimit-Remaining— requests left in the window
429 response includes Retry-After (seconds) — back off and retry rather than hammering the endpoint.
Putting it together
Everything above in one script. PointVORI_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.
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.