Documentation / Concepts / Pagination
Pagination
The API uses offset-based pagination. Every page costs credits — plan your iteration accordingly.
Paginated endpoints
Pagination is available on the endpoints that return lists:
GET /v1/transactions— DVF transactions (max limit 200)GET /v1/portfolio— portfolio properties (max limit 100)GET /v1/alerts— webhook alerts (max limit 50)
Parameters
| Parameter | Default | Description |
|---|---|---|
limit | 50 | Results per page. Range: 1–200 for /v1/transactions. |
offset | 0 | Start index (0-based). Pass the previous page's next_cursor value. |
The next_cursor field
Every paginated response includes a next_cursor field:
- A non-null value (
number): there are more results. Use this value as theoffsetof the next request.
next_cursor = offset + number of results returned - A
nullvalue: you are on the last page.
{
"transactions": [ /* 50 objects */ ],
"total_found": 312,
"next_cursor": 50,
"_credits": { "used": 5, "remaining": 95 },
"query_time_ms": 143
}
// Last page:
{
"transactions": [ /* 12 objects */ ],
"total_found": 312,
"next_cursor": null,
"_credits": { "used": 5, "remaining": 90 },
"query_time_ms": 121
}Example — walking through every page
curl "https://mcp.normi.fr/v1/transactions?code_postal=75011&type_local=Appartement&limit=50&offset=0" \ -H "X-API-Key: normi_your_token"
# Use next_cursor as the offset for the next page curl "https://mcp.normi.fr/v1/transactions?code_postal=75011&type_local=Appartement&limit=50&offset=50" \ -H "X-API-Key: normi_your_token"
import requests
def fetch_all(code_postal, type_local, api_key, limit=50):
url = "https://mcp.normi.fr/v1/transactions"
headers = {"X-API-Key": api_key}
offset = 0
all_results = []
while True:
r = requests.get(url, headers=headers, params={
"code_postal": code_postal,
"type_local": type_local,
"limit": limit,
"offset": offset,
})
data = r.json()
all_results.extend(data["transactions"])
if data.get("next_cursor") is None:
break
offset = data["next_cursor"]
return all_resultsEvery page costs credits
Every paginated call to
GET /v1/transactions costs 5 credits, whatever the page size. Narrow your filters (type_local, price, surface, date) to cut the number of pages and avoid spending your quota for nothing.total_found vs returned results
The total_found field gives the total number of results matching your filters (before pagination). That lets you work out the number of pages:
total_pages = ceil(total_found / limit) // e.g. 312 results / 50 per page = 7 pages (the last one with 12 results)
Result stability
DVF transactions rarely change (an annual release, no edits). Result order is stable across pages, but not guaranteed if new data is loaded while you iterate.