Webhooks
Keep your own lists of companies to monitor (for example your customers) and receive their changes as they are found: board members and owners, status, tax debt, court cases and enforcement, official notices, annual reports and credit rating. Changes are pushed to your server as signed HTTPS requests, or can be polled from GET /monitoring/events.
Set up
# 1. A list
curl -X POST https://api.regia.ee/monitoring/lists \
-H 'X-API-Key: YOUR_API_KEY' -H 'Content-Type: application/json' \
-d '{"name":"Accounting clients"}'
# 2. Its companies (up to 2,000 per request; replace: true syncs the whole list)
curl -X POST https://api.regia.ee/monitoring/lists/lst_…/companies \
-H 'X-API-Key: YOUR_API_KEY' -H 'Content-Type: application/json' \
-d '{"add":[{"registry_code":"10421629","external_ref":"client-42"}]}'
# 3. Where to send changes (the response has signing_secret once: store it)
curl -X PUT https://api.regia.ee/webhook \
-H 'X-API-Key: YOUR_API_KEY' -H 'Content-Type: application/json' \
-d '{"url":"https://your-app.com/webhooks/regia","enabled":true}'Each company can carry your own external_ref, which comes back in every event. A list, or a single company, can follow only some categories: registry, people, tax, court, announcements, reports, rating and assets. Monitoring starts when a company is added; earlier history is not sent.
What arrives
One POST per change. A company on several of your lists gives one event that names all of them. Changes are detected twice a day, in the morning and in the evening, and sent within minutes.
POST /webhooks/regia HTTP/1.1
Content-Type: application/json
User-Agent: Regia-Webhooks/1.0
X-Regia-Event-Id: evt_48213
X-Regia-Timestamp: 1790661912
X-Regia-Signature: v1=5f1c…{
"id": "evt_48213",
"type": "monitoring.change",
"created_at": "2026-09-29T06:05:12.000Z",
"data": {
"company": {
"registry_code": "10421629",
"name": "Näide OÜ"
},
"lists": [
{
"id": "lst_Q2x9aVb3KpT1mZr0",
"name": "Accounting clients",
"external_ref": "client-42"
}
],
"category": "tax",
"kind": "tax_debt",
"tone": "bad",
"details": {
"old": 0,
"new": 1250.4
},
"detected_at": "2026-09-29T06:05:12.000Z"
}
}tone says whether the change is bad, good or neutral for the company; details depends on the kind and often has old and new. The same objects come from GET /monitoring/events.
Saved searches
Save company filters and the same webhook receives, every morning after the data is refreshed, the companies that started to match: new companies in your field, companies that got tax debt, fell to a lower rating or grew past a size. What matches when you create a search is the starting point and is not sent. Up to 500 companies go in one search.matches event; a bigger day comes in parts. Without a webhook, poll GET /searches/{search}/matches.
curl -X POST https://api.regia.ee/searches \
-H 'X-API-Key: YOUR_API_KEY' -H 'Content-Type: application/json' \
-d '{"name":"New builders in Harju","filters":{"activity":["41","43"],"county":["Harju"],"registered_within_days":30}}'{
"id": "evt_srch_Hq3Lk8PzXw1Ab7Tc_20260930_1",
"type": "search.matches",
"created_at": "2026-09-30T06:10:00.000Z",
"data": {
"search": {
"id": "srch_Hq3Lk8PzXw1Ab7Tc",
"name": "New builders in Harju"
},
"date": "2026-09-30",
"part": 1,
"parts": 1,
"total": 1,
"companies": [
{
"registry_code": "17012345",
"name": "Näide Ehitus OÜ",
"legal_form": "Osaühing",
"status": "R",
"registered_on": "2026-09-29",
"address": "Harju maakond, Tallinn, Näite tn 1",
"activity_code": "41201",
"employees": null,
"revenue": null,
"tax_debt": null,
"rating": null
}
]
}
}Verify the signature
X-Regia-Signature is v1= followed by the hex HMAC-SHA256 of timestamp + "." + body, keyed with your signing secret. Reject requests older than five minutes.
import { createHmac, timingSafeEqual } from "node:crypto";
// rawBody: the request body exactly as received, before JSON parsing.
function verifyRegia(rawBody, headers, secret) {
const timestamp = headers.get("x-regia-timestamp") ?? "";
const signature = headers.get("x-regia-signature") ?? "";
if (!/^\d+$/.test(timestamp) || !/^v1=[a-f0-9]{64}$/.test(signature)) return false;
if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false; // replayed
const expected = createHmac("sha256", secret).update(timestamp + "." + rawBody).digest();
return timingSafeEqual(expected, Buffer.from(signature.slice(3), "hex"));
}
// Verify, store the event and skip ids you already have, then answer 2xx.
// Do slow work in your own background job.Delivery and retries
Answer with any 2xx status within 10 seconds. Anything else, a timeout or a redirect counts as a failure and is retried after 1 minute, 5 minutes, 15 minutes, 1, 3, 6 and 12 hours: 8 attempts in all. The same event can arrive twice, so use id to skip duplicates. After the last attempt the delivery is marked failed; retry it from the dashboard (API page) or with POST /webhook/deliveries/{id}/retry, or catch up with GET /monitoring/events.
Test your endpoint with POST /webhook/test or the Send test button on the API page: it sends a webhook.test event signed the same way.