registercheckby openlaw group
Guides

Follow new formations

Poll the formations feed on created_at and never miss a new company.

The shape of it

every few minutes  →  GET /formations?created_at[gte]=<T − 10 min>  →  page to the end  →  dedupe by id  →  T = newest created_at

A formation is a company whose first register entry is a new registration, not a move of the registered office, a conversion or a merger. The list is ordered by the Registertag (registration_date), newest first. That is the order you want to read, and the wrong one to poll on.

Why not poll on the Registertag

  • Late finds. About a quarter of formations are found days after their Registertag. They sort into the middle of the list, below rows you already read, so paging from the top stops before it reaches them.
  • Visible after discovery. A formation is usually published a few minutes after we find the company: its first register entry is written about two minutes later, and the list refreshes within a minute of that write. When the write takes longer, the formation appears later.

created_at is the moment a formation became available through the API. Every formation you have not seen yet has a created_at later than your last poll, whatever its Registertag.

Poll

from datetime import datetime, timedelta, timezone

OVERLAP = timedelta(minutes=10)

def poll(since: datetime, seen: set[str]) -> datetime:
    newest = since
    params = {"created_at[gte]": (since - OVERLAP).strftime("%Y-%m-%dT%H:%M:%SZ"), "limit": 100}
    while True:
        r = session.get(f"{BASE}/formations", params=params)
        r.raise_for_status()
        page = r.json()
        for formation in page["data"]:
            if formation["id"] in seen:            # the overlap re-reads a few; that is its job
                continue
            seen.add(formation["id"])
            handle(formation)
            created = datetime.fromisoformat(formation["created_at"].replace("Z", "+00:00"))
            newest = max(newest, created)
        if not page["has_more"]:
            return newest                          # store it; it is the next `since`
        params["starting_after"] = page["data"][-1]["id"]

Three rules:

  1. Overlap by ten minutes and deduplicate by id. Delivery is at-least-once and eventually consistent: a formation usually appears about three minutes after we find the company, sometimes later, and its created_at is the moment it appeared, so the overlap catches it. Keep the ids of the last hour or so; that is enough.
  2. Page forward with starting_after until has_more is false. The order is stable (registration_date, then the order we found them in, then id, all descending), so a row that arrives while you page is never served twice in one walk and is caught by the next poll.
  3. Every page costs 10 credits. Poll every few minutes, not every few seconds, and keep limit=100: a quiet interval is one page.

Filters combine with the poll. legal_form=gmbh&legal_form=ug&state=DE-BY follows new GmbHs and UGs in Bavaria; capital[gte]=25000 only the ones with at least 25,000 EUR of capital. GET /legal-forms lists every legal_form.

curl -G -g https://api.registercheck.de/v1/formations \
  -H "Authorization: Bearer $REGISTERCHECK_API_KEY" \
  -d "created_at[gte]=2026-09-30T14:00:00Z" \
  -d "legal_form=gmbh" \
  -d "legal_form=ug" \
  -d "state=DE-BY" \
  -d "capital[gte]=25000" \
  -d "limit=100"

-g stops curl from reading the square brackets as a glob pattern. To look back over a range of Registertage instead, bound registration_date[gte] and registration_date[lte].

Keep your own notes on a formation

session.patch(f"{BASE}/formations/{formation_id}",
              json={"metadata": {"crm_id": "0015g00000XyZ", "stage": "contacted"}})

Metadata merges: a key you set is added or replaced, a key set to null is removed, and a key you do not name is left alone. It belongs to your workspace; nobody else sees it. A formation stays retrievable with its metadata after it leaves the list's 180-day window. Each update costs 1 credit and returns the formation.

What to know

  • The window. The list covers the last 180 days of Registertage. Without a registration_date or created_at bound it shows the last 30.
  • Completeness. Registertage before 2026-09-09 are incomplete until they are back-filled.
  • Right after a restart the list can answer 503 with Retry-After. Wait that many seconds and poll again with the same since; nothing was charged.

On this page