registercheckby openlaw group
Understand the data

Monitoring

Monitor a company and be told when its register entry changes.

A monitor ties your account to one company. When its register entry changes, the monitor matches an event, listed free by GET /events?monitor_id=, and sends it to your destinations as a delivery, which GET /deliveries lists. The chain is monitor → event → delivery → destination.

This is the supported alternative to polling. Re-reading a company record on a schedule costs 10 credits a time and will usually tell you nothing changed.

Creating a monitor

Name the company the way you already know it — court, register and number — and skip the search:

curl -X POST "https://api.registercheck.de/v1/monitors" \
  -H "Authorization: Bearer $REGISTERCHECK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "register": {"court": "München", "type": "HRB", "number": "999999"},
    "event_types": ["representation", "capital"],
    "metadata": {"crm_id": "0015g00000XyZ"}
  }'

Or by its id, if you have one: {"subject_id": "cmp_01hxn3rys1fh58w4d1pb1x9s81"}. Give one, not both. register has the shape of a company's own register; the monitor names its company in subject.

  • register.court takes the court's code (D2601), its name (Amtsgericht München) or its town (München). A name that fits two courts ("Frankfurt") is refused with both named.
  • An identity that matches no company answers 404. About 1% of register identities are shared by more than one entry; those answer 409 register_identity_ambiguous with every candidate, and you retry with the subject_id of the one you mean.
  • Leave event_types out and you get ["*"] — every type, including ones added later.
  • metadata is yours: a CRM id, a team, anything to find the monitor again.

The monitor always belongs to the account that owns the API key. Creating a second monitor on the same company answers 409 with the existing one's id in existing_id.

Event types

Name event types, or a category that stands for several — the same groups the app shows:

CategoryEvent typesWorks today
representationcompany.role.added, company.role.removed — managing directors, board members and Prokuristen — and company.representation_rule.changedyes
capitalcompany.capital.changedyes
registered_officecompany.registered_office.changed (registered office moved), company.address.changed, company.register_court.changedyes
identitycompany.name.changed, company.legal_form.changed, company.purpose.changed, company.articles.changedyes
conversioncompany.merger.recorded, company.transformation.recordedyes
insolvencycompany.insolvency.recorded — opened, rejected for lack of assets, ended, provisional measuresyes
dissolutioncompany.liquidation.recorded (dissolved), company.deregistered (deleted)yes
other_entriescompany.legal_relationship.recorded, company.note.recordedyes
shareholderscompany.shareholder.added, company.shareholding.changed, company.shareholder.removednot yet
financial_statementcompany.financial_statement.publishednot yet
*every event type, including ones added later—

A register entry has the same type here as in the register history: both read what the entry says, not only the column it was filed under. A deletion is company.deregistered — the register files most of them as a "liquidation" — and an articles change is company.articles.changed, not a change of legal form.

A category becomes the event types it covers, and the monitor shows those. Types that do not work yet are accepted — the monitor starts delivering them when their source is switched on — and every monitor lists them in unavailable_event_types, so you are never left waiting for an event that cannot come. GET /event-types lists every type with its labels: monitorable says whether a monitor can ask for it, and available and unavailable_reason say whether it is delivered yet. GET /event-groups lists the categories.

Beneficial ownership (beneficial_owners) is not offered: nothing detects it, the group is listed with available: false, and asking for it answers 400 with the reason.

A monitor reports what the register enters after it was created. An entry dated more than 14 days before you created the monitor is not sent — it is history you could read when you started monitoring — even when we only find it now, as happens when a company's register sheet is read again.

An authorised signatory holds a role here, as everywhere else in the API: company.role.added covers both a board appointment and a grant of Prokura, and the event's data.role_type says which.

Creating a monitor costs 10 credits; every other monitor operation is free. Send an Idempotency-Key so a retry after a timeout cannot create or charge twice.

Managing monitors

OperationEndpointCost
ListGET /monitorsfree
Read oneGET /monitors/{id}free
Change types or metadata, or pausePATCH /monitors/{id}free
DeleteDELETE /monitors/{id}free

Only creating a monitor costs anything. Managing your own is free, so there is no reason to cache the list rather than reading it.

PATCH changes only what you send: {"status": "paused"} stops delivery without touching the event types, and {"status": "active"} resumes it. A paused monitor keeps its configuration and delivers nothing.

A monitor counts against the number of companies your plan monitors at once while it is active; a paused one does not. Resuming a monitor created in the dashboard when that number is reached answers 403 monitor_limit_reached, the refusal a create gets at the same limit, and the monitor stays paused. Monitors created with an API key or through the MCP server never count.

A monitor belonging to another account answers 404, not 403 — a 403 would confirm it exists.

Receiving events

Events are sent to the active destinations on your account — e-mail addresses, webhook URLs and Slack channels (by the incoming-webhook URL Slack issues), set up in the app under Benachrichtigungen or with POST /destinations. A destination you set up yourself receives every event of every monitor; Destination roles names the two kinds that receive less. A destination's cadence is instant (every change on its own), or a daily, weekly or monthly digest sent at 07:00 Europe/Berlin; a period with no changes sends nothing. Each send is a delivery: GET /deliveries lists what was sent where, and GET /events?monitor_id= lists what a monitor matched, whether or not it was sent.

An event a monitor reports carries the moment the monitor reported it as its created_at: on GET /events?monitor_id=, in each delivery and in the webhook body, the same instant in all three. A monitor created in the dashboard reports a change at its next check (see Detection latency), so its created_at can be later than the moment the change reached Registercheck. Polling a monitor's events on created_at[gte] still finds every one, whenever it is reported; the list stays ordered by the register day first.

Each destination has a cadence: instant sends every change on its own as it is detected; daily, weekly and monthly send one digest of the period's changes at 07:00 Europe/Berlin — every day, every Monday, on the 1st. A new e-mail address or Slack channel is daily and a webhook instant unless you say otherwise; a destination you set up before cadences existed stays instant. Change it with PATCH /destinations/{id}. A period without changes sends nothing. Switching to a digest starts its first period then — it never collects what you were already told — and switching back to instant sends the open period at once. A webhook is told at once for now.

For Slack, create an incoming webhook for the channel in Slack and send its URL as address with "channel": "slack". Each change arrives as a short German message: what changed, the register date and a link to the company. The URL is Slack's key to that channel, so it is shown in full only when you create the destination; afterwards it reads https://hooks.slack.com/services/T…/B…/…wxyz. If Slack keeps refusing the webhook (it was removed, or the channel archived), the destination is switched off after ten failed deliveries in a row, as a webhook is; disabled_reason says so.

A webhook destination should:

  • Respond 2xx quickly and do the work afterwards. Slow handlers are retried.
  • Be idempotent. Assume every delivery may arrive more than once, and deduplicate on the svix-id header (the delivery's id) and on each event's id.
  • Treat the payload as a signal, not as truth. Re-read the company to get the new state.

Webhooks has the exact payload, the signature headers and a verified handler.

Destination roles

Every destination carries a role, which says what it receives:

roleWhat it isWhat it receives
ownA destination you set up, here or in the appEvery event of every monitor, on its cadence
account_inboxYour sign-in address, added by Registercheck when you created your first monitor in the dashboard or through the MCP serverThe events of monitors created with an API key, as before; a dashboard monitor's only when that monitor delivers to it
routeAn e-mail address, Slack channel or webhook a dashboard monitor delivers toOnly the events of the dashboard monitors that deliver to it, at their check times

A route destination is always instant: a request to change its cadence answers 409 with code route_endpoint. Creating a destination with the address of a route makes that destination own instead of answering 409, and from then on it receives every event. A dashboard monitor that delivers to one of your own destinations sends its events there at its check time, and that destination's digest leaves them out, so nothing arrives twice.

Detection latency

Changes are detected by re-reading register entries every 15 minutes, not by a push from the courts. A change is typically visible within a day or two of appearing in the register, which is itself days or weeks after the underlying event. Monitoring is for keeping a portfolio current, not for real-time decisions.

A monitor created with an API key reports a change as soon as it is detected. A monitor created in the dashboard reports at its check (Prüfung). The plan sets how often a monitor may check at most: every 15 minutes on the Scale plan, hourly on Business and the earlier paid plans, otherwise daily at 06:00 Europe/Berlin. Each monitor checks at the speed chosen for it — weekly on Monday at 06:00 is always possible — or, without a choice, at the speed of your account inbox's cadence: instant the plan's fastest, daily daily, weekly and monthly weekly. Changing the inbox's cadence with PATCH /destinations/{id} therefore changes how often those monitors check.

On this page