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.courttakes 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 answer409 register_identity_ambiguouswith every candidate, and you retry with thesubject_idof the one you mean. - Leave
event_typesout and you get["*"]— every type, including ones added later. metadatais 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:
| Category | Event types | Works today |
|---|---|---|
representation | company.role.added, company.role.removed — managing directors, board members and Prokuristen — and company.representation_rule.changed | yes |
capital | company.capital.changed | yes |
registered_office | company.registered_office.changed (registered office moved), company.address.changed, company.register_court.changed | yes |
identity | company.name.changed, company.legal_form.changed, company.purpose.changed, company.articles.changed | yes |
conversion | company.merger.recorded, company.transformation.recorded | yes |
insolvency | company.insolvency.recorded — opened, rejected for lack of assets, ended, provisional measures | yes |
dissolution | company.liquidation.recorded (dissolved), company.deregistered (deleted) | yes |
other_entries | company.legal_relationship.recorded, company.note.recorded | yes |
shareholders | company.shareholder.added, company.shareholding.changed, company.shareholder.removed | not yet |
financial_statement | company.financial_statement.published | not 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
| Operation | Endpoint | Cost |
|---|---|---|
| List | GET /monitors | free |
| Read one | GET /monitors/{id} | free |
| Change types or metadata, or pause | PATCH /monitors/{id} | free |
| Delete | DELETE /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
2xxquickly and do the work afterwards. Slow handlers are retried. - Be idempotent. Assume every delivery may arrive more than once, and deduplicate on the
svix-idheader (the delivery's id) and on each event'sid. - 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:
role | What it is | What it receives |
|---|---|---|
own | A destination you set up, here or in the app | Every event of every monitor, on its cadence |
account_inbox | Your sign-in address, added by Registercheck when you created your first monitor in the dashboard or through the MCP server | The events of monitors created with an API key, as before; a dashboard monitor's only when that monitor delivers to it |
route | An e-mail address, Slack channel or webhook a dashboard monitor delivers to | Only 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.