registercheckby openlaw group
Get started

Pagination

Cursors for lists, page tokens for search, and the ceilings that apply.

There are two shapes, and which one you get depends on what you are reading.

Lists of a thing you already found

Officers, events, documents, statements, shareholders, monitors, lists — anything hanging off a record you already have — page with a cursor.

ParameterDefaultMaximum
limit20100
starting_afterthe id of an object in the list
ending_beforethe id of an object in the list

starting_after and ending_before take the id of an object you have already seen, not a number. They cannot be combined.

curl "https://api.registercheck.de/v1/companies/{company_id}/officers?limit=50" \
  -H "Authorization: Bearer $REGISTERCHECK_API_KEY"
{
  "object": "list",
  "data": [{ "id": "8f14e45f-ceea-467a-9c3a-4d5b8e5a1c22", "object": "officer" }],
  "has_more": true,
  "url": "/v1/companies/{company_id}/officers"
}

Walk it by passing the last id you saw:

def all_officers(session, company_id):
    cursor = None
    while True:
        params = {"limit": 100}
        if cursor:
            params["starting_after"] = cursor
        page = session.get(f"{BASE}/companies/{company_id}/officers", params=params).json()
        yield from page["data"]
        if not page["has_more"]:
            return
        cursor = page["data"][-1]["id"]

An unknown cursor is an error, not an empty page

Passing an id that is not in this list returns 400, not an empty result. That is deliberate: a caller paging with an id from a different list has a bug, and answering with nothing would hide it.

Search results

Search and filter endpoints page with an opaque token instead, because the result set is not a list of objects you can point into.

ParameterDefaultMaximum
limit20100
pagethe next_page of the previous result
{
  "object": "search_result",
  "data": [],
  "has_more": true,
  "next_page": "2",
  "total_count": 4213
}
  • total_count — matches across the whole result set, or null when it cannot be counted cheaply. Check for null before showing it.
  • next_page — pass it back as page. null on the last page.
def all_matches(session, **params):
    page = None
    while True:
        result = session.get(f"{BASE}/search/companies",
                             params={**params, "limit": 100, **({"page": page} if page else {})}).json()
        yield from result["data"]
        if not result["has_more"]:
            return
        page = result["next_page"]

Treat next_page as opaque. It happens to be a number today; that is not a promise.

Both shapes agree on two things

data always holds the items, and has_more always tells you whether to keep going. If you only ever read those two fields, the same loop works against either.

Asking for limit=101 returns 400; it is not silently clamped.

Each page is a separate billable call. Walking 4,000 search results at 100 per page is 40 calls — 40 credits for search, but 40,000 if you then read every company at 10 credits each. Consider POST /search/companies/filter, which answers a structured query for 25 credits a page.

Unknown parameters are ignored

Query parameters the endpoint does not recognise are dropped rather than rejected. ?name=Siemens on an endpoint whose parameter is q returns an unfiltered page, not an error. Check your parameter names against the reference when a result set looks larger or more random than it should.

On this page