--- name: business-register-open-data description: Look up an Estonian company's registry code, status, and address by name, or download bulk Business Register snapshots (entities, shareholders, beneficial owners). module: ariregister.mjs execution: get --- # Business Register Open Data ## Vetted module (use this first) `ariregister.mjs` ships in https://kodanikukratt.ee/kratt-agent.tar.gz (plain ESM, Node 22+) and is re-verified against the live source. For tax arrears, chain into `emta.mjs` (see the `tax-public-inquiries` guide): ```js import { show } from "./kratt.mjs"; import { findCompany } from "./ariregister.mjs"; import { taxDebt } from "./emta.mjs"; const c = await findCompany("Bolt Technology"); if (!c) { show("registry code could not be retrieved"); // say exactly this — never guess a code } else { show({ regCode: c.regCode, name: c.name, status: c.status, address: c.address, url: c.url }); // cite c.url const debt = await taxDebt(c.regCode); show(debt.text); // report the arrears status only from this line, with its timestamp } ``` - `findCompany(name)` matches historical names too (Taxify OÜ → Bolt Technology OÜ) and returns `null` when nothing matches. - Also exported: `searchCompanies(name)` for all autocomplete rows. **Anti-fabrication rule (issue #16):** a registry code is an identifier, not something to recall. State a code ONLY if it appears in output your script printed. If the lookup returns nothing, say the code could not be retrieved — never supply an 8-digit number from memory (observed failure: fabricated 14036220 / 14532842 for Bolt Technology OÜ; the real code is 12417834). The sections below are the fallback if a module call throws, plus the bulk snapshots the module does not cover. ## Single-company lookup by name (preferred for one registry code) For a single company's registry code (`registrikood`), status, or address — do NOT download a bulk snapshot. Use the public autocomplete JSON the search UI calls. No authentication, returns JSON directly, works with any user agent. ```text GET https://ariregister.rik.ee/est/api/autocomplete?q=Bolt+Technology&company=true ``` - `q` is a name substring (URL-encoded). `company=true` restricts to legal entities. - Response: `{ "status": "OK", "data": [ { "reg_code", "name", "historical_names", "status", "legal_address", "zip_code", "legal_form", "url", "company_id" }, ... ] }`. - `status` is a registry status code (`R` = registered/active). - `historical_names` lets you match a company that was renamed (e.g. "Taxify OÜ" → "Bolt Technology OÜ"). - Match the exact name against `name` (or `historical_names`); if several rows come back, do not blindly take the first — pick the one whose name matches. The `/est/api/autocomplete` path works and returns JSON. Do NOT use the bare `/api/autocomplete` path — it answers HTTP 500 `Internal Server Error` (checked 2026-08-02). ```probe-limit claim `/api/autocomplete` path — it answers HTTP 500 `Internal Server Error` GET https://ariregister.rik.ee/api/autocomplete?q=Bolt+Technology&company=true expect-status 500 expect /Internal Server Error/ # The control is the path this guide tells the agent to use, same host, same # query. Without it, a day when the whole register 500s would "confirm" this # limitation while the one route we depend on was down. control GET https://ariregister.rik.ee/est/api/autocomplete?q=Bolt+Technology&company=true ``` ### Anti-fabrication grounding rule (issue #16) A registry code is an identifier, not something to recall. State a registry code ONLY if it appears verbatim in output your script actually printed from this endpoint. If the lookup returns an empty `data` array, an error, or you cannot match the requested company, say the code could not be retrieved — NEVER supply a registry code from memory or guess an 8-digit number. (Observed failure: the agent confidently answered fabricated codes like 14036220 / 14532842 for Bolt Technology OÜ; the real code is 12417834, which this endpoint returns.) ## Bulk snapshots (many companies / fields not in autocomplete) Public ZIP snapshots from `https://avaandmed.ariregister.rik.ee/en/downloading-open-data`. No login. Send a normal user agent if Cloudflare returns 403. Use these only when you need bulk data or fields the autocomplete does not carry (shareholders, beneficial owners, registry-card detail) — not for a single company's registry code. 1. Fetch the download page and select the dataset family and format. 2. Resolve relative links against `https://avaandmed.ariregister.rik.ee`. 3. Download the archive, record its filename and retrieval time, and verify the ZIP before parsing. Known direct snapshot: ```text https://avaandmed.ariregister.rik.ee/sites/default/files/avaandmed/ettevotja_rekvisiidid__lihtandmed.csv.zip ``` Other published families include `yldandmed`, `registrikaardid`, `kaardile_kantud_isikud`, `osanikud`, `kasusaajad`, `kommertspandid`, and `maarused`, commonly as JSON or XML ZIPs. ## Return Preserve registry code (`reg_code`/`ariregistri_kood`), legal form and status, name and historical names, address, source, and retrieval time. For bulk snapshots also keep the source filename and snapshot date. Keep beneficial-owner and person records separate from core entity records. ## Limits - Archives are large; inspect headers and stream/process them instead of loading several complete snapshots into memory. - Static snapshots are open; WSDL/API services linked from the site can have different terms or fees. - Schemas differ across dataset families and formats. ## Verify - Autocomplete: require HTTP 200 JSON with `status: "OK"` and a `data` array; a usable result has a numeric `reg_code` and a `name` matching the requested company. - Bulk: require HTTP 200, `application/zip`, ZIP magic bytes `PK`, and a valid archive member; for the simple CSV snapshot require a header containing the registry identifier before analysis. ## Module API findCompany(name) -> {regCode, name, status, address, historicalNames, url}