Recipe
Syncing processing statuses
Mirror where an expense stands in QUiCK processing — without webhooks, using incremental polling.
Prerequisites
- A working authenticated integration (see: Authenticating API requests)
- A database where you store the expense status
- A scheduler (cron, worker) that runs the sync regularly
1. Which status fields exist
The QUiCK Public API does not send webhooks — you follow changes by polling. These fields describe where an expense stands:
| Field | Type | Meaning |
|---|---|---|
accounting_status | string | Bookkeeping state |
paid_status | integer | 1 — unpaid, 2 — paid, 3 — instalment |
incomplete | bool | Item with incomplete data |
has_artifact | bool | Whether a document image is attached |
filing_date | datetime | Time of filing |
The same properties are available as list filters: is_approved, is_processed, needs_review, is_incomplete, is_exported.
2. Incremental querying
Store the timestamp of the last successful sync and request only the items created or changed since:
curl -sS "https://api.quick.riport.co.hu/1/expenses/?date_field=created&from_date=2026-07-13&ordering=-created&page_size=100" \
-H "Authorization: Token $QUICK_API_TOKEN"Use an overlap
Set from_date one day earlier than the last run so items on the boundary are not missed. De-duplicate by id.
3. Idempotent update in your own table
id is the stable key. Only overwrite when the state actually changed — that way the sync can be re-run without side effects:
INSERT INTO quick_expenses (expense_id, invoice_number, partner_name, accounting_status, paid_status, synced_at)
VALUES ($1, $2, $3, $4, $5, now())
ON CONFLICT (expense_id) DO UPDATE
SET accounting_status = EXCLUDED.accounting_status,
paid_status = EXCLUDED.paid_status,
invoice_number = EXCLUDED.invoice_number,
synced_at = now()
WHERE quick_expenses.accounting_status IS DISTINCT FROM EXCLUDED.accounting_status
OR quick_expenses.paid_status IS DISTINCT FROM EXCLUDED.paid_status;4. Details and state changes
The full record of an item — including its accounting assignments — is available separately:
curl -sS https://api.quick.riport.co.hu/2/expenses/90231/ \
-H "Authorization: Token $QUICK_API_TOKEN"If your own system decides on approval, you can write the state back. These endpoints are bulk and expect a list of identifiers:
| Endpoint | Effect |
|---|---|
POST /1/expenses/approve/ | Approve the selected expenses |
POST /1/expenses/unapprove/ | Revoke approval |
POST /1/expenses/check/ | Mark as checked |
POST /1/expenses/uncheck/ | Revoke the check |
5. Scheduling and fault tolerance
- Scheduling: accounting data is not real-time — a minute-to-hour cadence is plenty. Polling too frequently returns
429 Too Many Requests. - Partial success: only advance the sync timestamp when the full pagination completed without error; otherwise the next run picks up what was missed.
- Observability: log the number of items processed per run and any errors. A run returning zero items while traffic exists points at a configuration problem.
Related endpoints
- POST/v1/webhooks
- GET/v1/invoices
Common pitfalls
Waiting for a webhook
The QUiCK Public API sends no event notifications and has no webhook registration endpoint. Anyone designing for webhooks will never receive data — the correct pattern is incremental polling.
A period window without overlap
If from_date is exactly the timestamp of the last run, items arriving on the boundary can be missed. Use at least a one-day overlap and de-duplicate by id.
Polling too frequently
A full re-sync every minute (or more often) leads to 429. Query less often, with a larger page_size and a from_date filter.
Advancing the sync timestamp after a failure
If pagination breaks halfway but you already saved the new timestamp, the missed items will never arrive. Only store the new timestamp after a fully successful run.