Playbook
Daily accounting sync with polling
An external accounting system syncs with QUiCK daily, when webhooks are unavailable or unusable.
This playbook shows a simple, robust polling-based sync pattern for when webhooks are not available. The method stores the date of the last successful run and uses from_date to request only the changes.
Prerequisites
- A Public API token
- Persistent storage for the last sync date (DB, kv, file)
1. Load the last sync date
Read the timestamp of the last successful run from local storage (ISO 8601). If there is none, start from 2024-01-01.
2. Fetch expenses page by page
curl -H "Authorization: Token $QUICK_TOKEN" \
"https://api.quick.riport.co.hu/1/expenses/?date_field=created&from_date=2026-07-13&ordering=-created&page_size=100"The response contains the results, next, previous and count fields.
3. Page through the next URL
Follow the next URL until it becomes null — that pulls in every page:
let url = `${BASE}/1/expenses/?date_field=created&from_date=${from}&ordering=-created&page_size=100`;
while (url) {
const res = await fetch(url, { headers: { Authorization: `Token ${TOKEN}` }});
const page = await res.json();
for (const row of page.results) upsertLocal(row);
url = page.next;
}4. De-duplicate by id
During incremental sync the same id may come back across several runs (after an edit, for example). Use an INSERT ... ON CONFLICT (id) DO UPDATE pattern.
5. Sync incomes
The same pattern applies to incomes:
curl -H "Authorization: Token $QUICK_TOKEN" \
"https://api.quick.riport.co.hu/1/incomes/?from_date=2026-07-13"6. Pulse balance
Finish by reading the daily balance:
curl -H "Authorization: Token $QUICK_TOKEN" https://api.quick.riport.co.hu/1/pulse/7. Update the sync date
If every request succeeded, store the new sync date — the start of the run, not its end, so no items slip through.
Related endpoints
- GET/1/expenses/
- GET/1/incomes/
- GET/1/pulse/
Common pitfalls
A time window without overlap
If you set the sync date to the **end** of the run, items created during the run are missed. Always store the start of the run, or roll back by a one-minute buffer.
Polling too frequently
Polling every minute returns `429 Too Many Requests`. A daily (or hourly) run is enough for most cases; handle `429` with exponential backoff.