Pagination
The three list shapes returned by the NovaFisko API, the page and per_page parameters, and the right way to go through all pages.
Not all lists are paginated. The API returns three shapes depending on the nature of the resource. The reference specifies the shape of each route.
| Shape | When | Examples |
|---|---|---|
| Plain array | Reference data of limited size | companies, accounts, journals, third-parties, vat-codes, fiscal-years |
| Page-based pagination | Lists that keep growing | entries, documents, document-imports, bank-transactions, coda-files, history, sync/conflicts |
| Cursor stream | Change tracking | sync/pull |
Plain arrays
Reference data is returned in full, as a JSON array at the root. Filter it with the search parameters of the route.
curl "https://api.novafisko.com/v1/companies/k3Jd9fPq2LmX/third-parties?type=supplier&q=brasserie" \
-H "Authorization: Bearer $NOVAFISKO_TOKEN"
[
{
"id": 41,
"type": "supplier",
"code": "BRASSCOL",
"name": "Brasserie des Collines SA",
"vat_number": "BE0999900134",
"version": 3
}
]
Page-based pagination
Parameters
| Parameter | Default | Maximum | Description |
|---|---|---|---|
page |
1 |
Page number, starting at 1 | |
per_page |
50 |
200 |
Number of items per page |
Bank transactions (bank-transactions) are an exception: 100 items by default, 500 at most.
Response shape
curl "https://api.novafisko.com/v1/companies/k3Jd9fPq2LmX/entries?from=2026-07-01&to=2026-09-30&per_page=2&page=1" \
-H "Authorization: Bearer $NOVAFISKO_TOKEN"
{
"current_page": 1,
"data": [
{
"id": 1842,
"journal_id": 3,
"number": 212,
"entry_date": "2026-09-30T00:00:00.000000Z",
"label": "Brasserie des Collines SA",
"reference": "F-2026-0918",
"status": "posted",
"journal": {"id": 3, "code": "ACH", "type": "purchase"},
"third_party": {"id": 41, "name": "Brasserie des Collines SA"},
"lines": [
{"id": 5521, "account_id": 118, "debit": "1250.00", "credit": "0.00", "account": {"id": 118, "number": "604000", "label": "Achats de marchandises"}},
{"id": 5522, "account_id": 77, "debit": "262.50", "credit": "0.00", "account": {"id": 77, "number": "411000", "label": "TVA à récupérer"}},
{"id": 5523, "account_id": 90, "debit": "0.00", "credit": "1512.50", "account": {"id": 90, "number": "440000", "label": "Fournisseurs"}}
]
}
],
"first_page_url": "https://api.novafisko.com/v1/companies/k3Jd9fPq2LmX/entries?page=1",
"from": 1,
"last_page": 87,
"last_page_url": "https://api.novafisko.com/v1/companies/k3Jd9fPq2LmX/entries?page=87",
"links": [
{"url": null, "label": "« Précédent", "active": false},
{"url": "https://api.novafisko.com/v1/companies/k3Jd9fPq2LmX/entries?page=1", "label": "1", "active": true}
],
"next_page_url": "https://api.novafisko.com/v1/companies/k3Jd9fPq2LmX/entries?page=2",
"path": "https://api.novafisko.com/v1/companies/k3Jd9fPq2LmX/entries",
"per_page": 2,
"prev_page_url": null,
"to": 2,
"total": 173
}
| Field | Description |
|---|---|
data |
The items of the page |
current_page, last_page |
Current page and last page |
per_page |
Page size applied, after capping |
total |
Total number of items matching the filters |
from, to |
Rank of the first and last item of the page |
next_page_url, prev_page_url |
URL of the next or previous page, null if there is none |
The URLs contained in next_page_url and links do not include your filters (from, to, per_page...). Build the URL of the next page yourself by incrementing page and keeping your parameters.
Variants
A few routes add fields to the standard pagination or simplify its shape.
| Route | Specific feature |
|---|---|
sync/conflicts |
Standard pagination, plus open: the number of conflicts still open |
trash |
data, current_page, per_page, last_page, total, plus counts, types, retention_days, can_purge |
activity, firms/{firm}/activity |
data, current_page, per_page and has_more instead of total |
firms/{firm}/webhooks/{webhook}/deliveries |
data and meta: {current_page, last_page, per_page, total} |
For the activity log, keep going as long as has_more is true.
Going through all pages
use GuzzleHttp\Client;
$client = new Client([
'base_uri' => 'https://api.novafisko.com/v1/',
'headers' => ['Authorization' => 'Bearer '.getenv('NOVAFISKO_TOKEN'), 'Accept' => 'application/json'],
]);
$page = 1;
do {
$response = json_decode((string) $client->get("companies/{$company}/entries", [
'query' => ['fiscal_year_id' => 7, 'per_page' => 200, 'page' => $page],
])->getBody(), true);
foreach ($response['data'] as $entry) {
// Handle one entry
}
$page++;
} while ($page <= $response['last_page']);
import os
import requests
session = requests.Session()
session.headers.update({"Authorization": f"Bearer {os.environ['NOVAFISKO_TOKEN']}", "Accept": "application/json"})
def all_entries(company, **filters):
page = 1
while True:
payload = session.get(
f"https://api.novafisko.com/v1/companies/{company}/entries",
params={**filters, "per_page": 200, "page": page},
timeout=60,
).json()
yield from payload["data"]
if page >= payload["last_page"]:
break
page += 1
Order and stability
Paginated lists are sorted from newest to oldest (entries by entry date then by id, history by id). If items are created while you are going through the list, an item may slip from one page to the next and appear twice. Two safeguards:
- bound the period with
fromandtoover a closed interval; - deduplicate on
idon your side.
For a complete copy kept up to date, do not poll the lists in a loop. Load them once, then follow the changes with sync/pull.
Cursor stream
GET sync/pull has no pages. You give it the last cursor received and it returns the changes that have occurred since.
curl "https://api.novafisko.com/v1/companies/k3Jd9fPq2LmX/sync/pull?since=48211&limit=500" \
-H "Authorization: Bearer $NOVAFISKO_TOKEN"
{
"cursor": 48236,
"has_more": false,
"full_resync": false,
"changes": [
{"resource": "third_parties", "op": "upsert", "id": 41, "version": 4, "data": {"id": 41, "name": "Brasserie des Collines SA"}, "changed_at": "2026-10-05T08:41:02+00:00", "seq": 48236}
],
"server_time": "2026-10-05T08:41:09+00:00"
}
As long as has_more is true, call the route again immediately with the new cursor. The full walkthrough is in Continuous sync.