Track changes
Replace a polling loop with a monitor and a webhook.
The shape of it
monitor once → we re-read the register → event fires → your webhook → you re-read the companyYou monitor a company. We detect that its register entry moved. Your endpoint gets told. You fetch the new state.
Monitor a company
def watch(company_id: str, events=("*",)):
existing = session.get(f"{BASE}/monitors", params={"limit": 100}).json()
if any(m["company"]["id"] == company_id for m in existing["data"]):
return # already watching it
r = session.post(f"{BASE}/monitors", json={
"company_id": company_id,
"event_types": list(events),
})
r.raise_for_status()
return r.json()["id"]Only company_id is required; the monitor belongs to the account that owns the key.
Reading GET /monitors first is free, so the pre-check costs nothing — and creating a
monitor costs 10 credits, so it is worth doing.
Narrow the events
* is the default and it is noisy. Monitor what you will act on:
| You care about | Monitor |
|---|---|
| A counterparty's solvency | company.capital.changed, company.legal_form.changed |
| Who can sign | company.officer.appointed, company.officer.removed |
| Change of control | company.shareholder.added, company.shareholder.removed, company.shareholder.changed |
| Keeping records tidy | company.name.changed, company.address.changed |
"Who can sign" is two types rather than four: an authorised signatory is an officer here,
so a grant of Prokura and a board appointment both raise
company.officer.appointed.
Change the selection later with
PATCH /monitors/{id}, which touches only
what you send — so {"status": "paused"} stops delivery without losing your event types.
Handle the webhook
app.post('/hooks/registercheck', async (req, res) => {
res.status(200).end(); // acknowledge first, work after
const eventId = req.headers['svix-id'] as string; // NOT req.body: there is none there
const { company_id, event_type } = req.body;
if (await alreadyProcessed(eventId)) return; // events can repeat
const fresh = await fetchCompany(company_id); // the payload is a signal, not state
await applyChange(company_id, event_type, fresh);
await markProcessed(eventId);
});Three rules, in order of how much trouble they save you:
- Acknowledge immediately. A slow handler is a retried handler.
- Deduplicate on the
svix-idheader. Assume at-least-once delivery. The body carries no event id — see Webhooks. - Re-read the company. Treat the event as "something changed", not as the new value.
What this is not
Detection runs on a cycle against the register, and the register itself lags the real world by days or weeks. Expect to hear about a change a day or two after it is published, and do not build anything that needs to know within the hour.
Housekeeping
Only creating a monitor costs anything; listing, reading, updating and deleting are free.
So read GET /monitors whenever you want the truth rather than trusting a local index, and
delete what you no longer watch — the cost of a monitor is the 10 credits you already paid,
not an ongoing charge.