# Authentication Source: https://docs.openregister.de/authentication How to authenticate with the API All API endpoints require authentication using an API key. You must include your API key in the `Authorization` header of each request using the Bearer token format. ## Getting an API Key (takes under a minute) 1. Create an account at [openregister.de](https://openregister.de) 2. Go to the [API Keys](https://openregister.de/keys) page 3. Create a new API key The free plan includes 500 credits per month - perfect for testing and development. For production use, upgrade to the Pro plan. Learn more about [pricing and credit costs](/pricing). ## Using the API Key Include the API key in the `Authorization` header of all API requests: ```bash theme={"dark"} Authorization: Bearer YOUR_API_KEY ``` ## Next Steps Got your API key? Head to the [Quickstart Guide](/quickstart) to start making your first requests with our official SDKs or other integrations. # Simple company search Source: https://docs.openregister.de/endpoint/autocomplete-company GET /v1/autocomplete/company ## Autocomplete company Fast, lightweight search for companies by name. This endpoint is optimized for autocomplete functionality in user interfaces, returning quick results as users type. It searches both current and historical company names, making it perfect for implementing search-as-you-type features. Returns basic company information including ID, name, and register details. **Cost:** 1 credit per request # Company information Source: https://docs.openregister.de/endpoint/company GET /v1/company/{company_id} ## Get company information Returns comprehensive company data including registration details, management, financial indicators, contact information, and complete historical changes. **Cost:** 10 credits (20 credits with `realtime=true`) ### What's Included * **Management and signatories** in `representation`: managing directors (Geschäftsführer), board members (Vorstand), general partners, liquidators and Prokuristen, current and past. See [Roles](/roles). * **Share capital** (Stammkapital, Grundkapital) in `capital` and its history in `capitals`: a decimal amount with its `currency`, not cents. * **Key financial indicators** in `indicators`: revenue, net income, equity, employees and more per fiscal year. Monetary values are integers in euro cents. For full balance sheets and income statements, use [financials](/endpoint/company-financials). * **Estimated financials** in `estimates`: modelled revenue, EBITDA and employees for companies that do not publish them, with an 80% range and a confidence tier. See [estimated financials](/filtering#estimated-financials). * **Register data**: name and legal form, register court and number, address, business purpose, industry codes and status. Names, addresses, purposes and registers also come with their history. ### Realtime Parameter Add `realtime=true` to fetch the latest data directly from the Handelsregister. Costs an additional 10 credits. Use for compliance checks or when you need guaranteed current data. ### Roles Each entry in `representation` carries a `role` and a `role_detail` — see [Roles](/roles). ### Insolvency Data When the company has insolvency proceedings, the response includes an `insolvencies` array with a summary of each proceeding. Use the [insolvency endpoint](/endpoint/insolvency) to retrieve the full event history of a proceeding. # Contact information Source: https://docs.openregister.de/endpoint/company-contact GET /v0/company/{company_id}/contact > [!WARNING] > > **Deprecated:** This endpoint is deprecated. Contact information is now included in the [company details endpoint](/endpoint/company) response. Use that endpoint instead to get company data including contact information in a single request. ## Get company contact information Retrieve contact information for a company including email addresses, phone numbers, and VAT identification numbers. This data is collected from publicly available sources including company websites. The response includes the source URL where each piece of information was found, allowing you to verify the data origin. **Cost:** 10 credits # Financials Source: https://docs.openregister.de/endpoint/company-financials GET /v1/company/{company_id}/financials ## Get company financials Retrieve detailed financial reports including balance sheets (Bilanz) and income statements (Gewinn- und Verlustrechnung) from the Bundesanzeiger. This endpoint provides structured financial data across multiple reporting periods, allowing for trend analysis and financial health assessment. **Cost:** 10 credits ### Financial Data Structure The response includes complete balance sheet data (assets/Aktiva and liabilities/Passiva) and income statement information when available. Financial reports are structured according to German accounting standards (HGB - Handelsgesetzbuch) and include line items such as current assets, fixed assets, equity, liabilities, revenue, expenses, and net income. **Units:** every monetary value (report rows, merged values and indicators) is an integer in euro cents. Divide by 100 for euros: a `revenue` of `1234567890` is €12,345,678.90. Non-monetary values such as `employees` are plain counts. In addition to the raw financial statements, we provide pre-calculated financial indicators for immediate use. These include key metrics such as balance sheet total, revenue, net income, cash, equity and employees, read from the same statements as the report rows. They are returned at the top level of the response under `indicators`, one entry per fiscal year-end, sorted by date (latest first). Where a company does not publish revenue, EBITDA or headcount, `estimates` holds a modelled figure for its latest fiscal year, the same one the company endpoint returns. See [estimated financials](/filtering#estimated-financials). Each report additionally exposes its rendered document under `sources` as a short-lived, presigned `html_url` (valid for 30 minutes), so you can download or display the full original HTML report. You'll receive data for all available reporting periods, typically covering multiple years. Each report includes the reporting period and a detailed breakdown of financial positions. Not all companies are required to publish detailed financial statements - data availability depends on company size and legal requirements. ### Use Cases **Financial Analysis:** Assess a company's financial health by analyzing revenue trends, profitability, liquidity ratios, and capital structure. Compare financial metrics across multiple periods to identify growth patterns or concerns. **Credit Assessment:** Evaluate creditworthiness by examining equity ratios, debt levels, and cash flow indicators. Banks and suppliers use this data for credit decisions and risk management. **Market Research:** Identify financially strong companies in your target market. Filter for companies with specific revenue ranges, employee counts, or financial characteristics for business development or investment opportunities. # Company historical owners Source: https://docs.openregister.de/endpoint/company-historical-owners GET /v1/company/{company_id}/owners/historical ## Retrieve the historical ownership changes of a company Get the full ownership history of a company across all filed documents. Unlike the current owners endpoint, this endpoint returns ownership data from every shareholder list (Gesellschafterliste) ever filed, allowing you to trace how ownership has changed over time. **Cost:** 25 credits ### Async Processing This endpoint may need to process data before it can return a result. Depending on the state of the data, you will receive one of two responses: | Status | Meaning | | - | - | | `200 OK` | Data is ready — the response body contains the full ownership history. | | `202 Accepted` | Processing is still in progress. Re-call the same endpoint until you receive a `200`. | > [!NOTE] > > When you receive a `202`, wait **30 seconds** before retrying. Re-call the same endpoint with the same `company_id`. There is no separate job ID — simply poll until you get a `200`. > > **`202` responses are not billed.** Credits are only deducted when the endpoint returns `200` with data. ### Supported Legal Forms Historical ownership data is available for: * **GmbH** (Gesellschaft mit beschränkter Haftung) - Limited liability company ### Ownership Data Structure The response includes ownership snapshots across all filed documents. Each snapshot contains the document date, the owners at that point in time, their ownership stake (as percentage and/or nominal shares), and share capital. For corporate shareholders, you'll receive the company ID to retrieve further details. ### Use Cases **Ownership Analysis:** Understand who has controlled a company over time and identify indirect ownership through corporate shareholders. Map ownership chains to reveal corporate structures. **Funding Rounds:** Analyze funding rounds and understand who invested when — trace new shareholders entering the cap table and stake changes over time to reconstruct the company's funding history. **Risk Assessment:** Identify concentration of ownership, related party transactions, or complex ownership structures that may require additional scrutiny. **Network Mapping:** Track ownership connections between companies over time to identify business groups, family holdings, or corporate networks. # Company holdings Source: https://docs.openregister.de/endpoint/company-holdings GET /v1/company/{company_id}/holdings ## Retrieve the holdings of a company Get a list of companies that this company owns or has stakes in. This endpoint reveals a company's investment portfolio and subsidiary structure, showing which other companies it controls or has invested in. Use this to map corporate groups and understand investment strategies. **Cost:** 10 credits # Company owners Source: https://docs.openregister.de/endpoint/company-owners GET /v1/company/{company_id}/owners ## Retrieve the owners of a company Get detailed ownership information including shareholders, their ownership percentages, and share capital. This endpoint provides structured ownership data extracted from official register documents including shareholder lists (Gesellschafterlisten) and company registers. **Cost:** 10 credits (20 credits with `realtime=true`) ### Supported Legal Forms Ownership data is available for the following legal forms: * **GmbH** (Gesellschaft mit beschränkter Haftung) - Limited liability company * **KG** (Kommanditgesellschaft) - Limited partnership * **e.K.** (eingetragener Kaufmann) - Registered merchant * **eGbR** (eingetragene Gesellschaft bürgerlichen Rechts) - Registered civil law partnership * **OHG** (Offene Handelsgesellschaft) - General partnership ### Ownership Data Structure The response includes each owner's type (natural person, German company, foreign company, etc.), their ownership stake (as percentage and/or nominal shares), and their share class (e.g., Komplementär, Kommanditist for KG structures). For corporate shareholders, you'll receive the company ID to retrieve further details. ### Use Cases **Ownership Analysis:** Understand who controls a company and identify indirect ownership through corporate shareholders. Map ownership chains to reveal corporate structures. **Risk Assessment:** Identify concentration of ownership, related party transactions, or complex ownership structures that may require additional scrutiny. **Network Mapping:** Track ownership connections between companies to identify business groups, family holdings, or corporate networks. # Company UBOs Source: https://docs.openregister.de/endpoint/company-ubo GET /v1/company/{company_id}/ubo ## Retrieve the UBOs of a company Identify the Ultimate Beneficial Owners (UBOs) - the natural persons who ultimately own or control a company. This endpoint calculates beneficial ownership by traversing the complete ownership chain, including indirect ownership through multiple corporate layers. **Cost:** 25 credits ### What are UBOs? Ultimate Beneficial Owners are the natural persons who ultimately own or control a company through direct or indirect ownership. According to German law (GwG - Geldwäschegesetz), individuals holding more than 25% of shares or voting rights are typically considered beneficial owners. Our API automatically calculates these percentages by analyzing multi-level ownership structures. ### Supported Legal Forms UBO analysis is currently available for: * **GmbH** - Limited liability company * **gGmbH** - Non-profit limited liability company * **UG** - Entrepreneurial company (mini-GmbH) * **KG** - Limited partnership ### Use Cases **AML/KYC Compliance:** Financial institutions, lawyers, and notaries use UBO data to fulfill anti-money laundering and know-your-customer requirements. Identify who ultimately controls a business relationship. **Enhanced Due Diligence:** For high-risk transactions, identify the natural persons who ultimately benefit from and control the company, even when ownership is structured through complex corporate arrangements. **Regulatory Reporting:** Many industries require disclosure of beneficial ownership. Use this endpoint to automatically identify reportable UBOs for regulatory filings and transparency registers. # Credit usage Source: https://docs.openregister.de/endpoint/credits GET /v1/credits ## Retrieve credit usage Get the credits used in the current period, how many are included in your plan, and when usage resets. Paid plans reset with the billing cycle; the free plan uses a rolling 30-day window that starts with your first request. **Cost:** 0 credits # Document Realtime Source: https://docs.openregister.de/endpoint/document-realtime GET /v1/document ## Retrieve realtime documents for a company Request official documents directly from the Handelsregister in real-time. This endpoint fetches documents on-demand from the official register, ensuring you always receive the most current version available. **Cost:** 10 credits ### Available Document Types You can retrieve several types of official documents by specifying the `document_category` parameter: * **current\_printout (AD)** - Current register extract showing the company's current state (PDF) * **chronological\_printout (CD)** - Complete historical extract showing all changes (PDF) * **historical\_printout (HD)** - Historical snapshot from a previous point in time (PDF) * **shareholder\_list (GV)** - Official shareholder list (Gesellschafterliste) (PDF) * **articles\_of\_association (UT)** - Company articles/bylaws (Satzung/Gesellschaftsvertrag) (PDF) * **structured\_information (SI)** - Structured company data (XML format) Most documents are returned as PDF files that can be downloaded and archived, except for structured\_information which is provided in XML format for programmatic processing. These are the same official documents you would receive from the Handelsregister portal, but accessible via API. ### Use Cases **Legal Documentation:** Lawyers and notaries use this endpoint to obtain official, certified register extracts for transactions, litigation, or regulatory filings. The current printout (AD) is commonly required for contracts and due diligence. **Compliance Archiving:** Maintain audit trails by periodically downloading and archiving official documents. Keep historical snapshots for regulatory compliance and documentation requirements. **Automated Verification:** Integrate document retrieval into your workflows to automatically obtain proof of registration, current ownership, or corporate structure whenever needed for client onboarding or transaction processing. # Document Stored Source: https://docs.openregister.de/endpoint/document-stored GET /v1/document/{document_id} ## Retrieve stored documents for a company Access documents that have been previously retrieved and stored in our database. This endpoint is faster and more cost-effective for accessing historical documents or documents that have already been fetched. For the most current documents, use the [realtime document endpoint](/endpoint/document-realtime) instead. **Cost:** 10 credits # Advanced company search Source: https://docs.openregister.de/endpoint/filter-company POST /v1/search/company ## Search companies Perform advanced searches with complex filters to find companies matching specific criteria. Combine multiple filters on company attributes, financial metrics, ownership characteristics, and geographic location to identify your exact target audience. **Cost:** 10 credits per search ### Powerful Filtering Options Use filters to search by company status, legal form, location (city, postal code, or radius), industry codes, financial metrics (revenue, employees, balance sheet), incorporation date, ownership structure (family-owned, sole owner, owner-managed), insolvency status (`had_insolvency`, `has_open_insolvency`, `insolvency_stage`, `insolvency_opened_at`), the insolvency risk class (`insolvency_risk`), identifiers (`lei`, `vat_id`), and best-available revenue, EBITDA and headcount — reported where published, estimated otherwise (`estimated_revenue`, `estimated_ebitda`, `estimated_employees`, each with a confidence tier). Combine multiple filters with AND logic to narrow your results precisely. You can filter by over 70 different fields, including more than 45 financial indicators such as balance sheet totals, employee counts, provisions, and receivables, plus youngest owner age, capital amounts, and specific ownership characteristics. See our [filtering guide](/filtering) for detailed examples and all available filter fields. ### Use Cases **Lead Generation:** Find companies matching your ideal customer profile. For example, search for GmbH companies in a specific industry with 50-200 employees and revenue over €5M in your target region. **Market Analysis:** Identify all companies in a specific industry sector, analyze their distribution across regions, or find newly incorporated businesses in your market. **Succession Planning:** Search for owner-managed companies where the owner is approaching retirement age (`youngest_owner_age > 60`, `has_representative_owner = true`) - perfect for identifying acquisition opportunities or succession planning services. A full list of all German register courts is available [here](https://drive.google.com/file/d/1TkLE8myGlbj65Kub25mTxTbxiKJJ_zzE/view?usp=sharing). # Search person Source: https://docs.openregister.de/endpoint/filter-person POST /v1/search/person ## Search for a person Search for natural persons by name, city, date of birth, or other attributes. Find people based on their business roles and filter by criteria such as the number of companies they're involved with or their management positions. Use this endpoint to identify individuals for due diligence or to research business networks. More information about filtering can be found [here](/filtering). **Cost:** 10 credits # Insolvency proceeding Source: https://docs.openregister.de/endpoint/insolvency GET /v1/insolvency/{insolvency_id} ## Retrieve an insolvency proceeding Get the full record of a single insolvency proceeding, including its complete event history. Each proceeding is assembled from the official insolvency announcements and tracks the case from the first security measures through opening, distributions, and discharge. **Cost:** 10 credits ### Proceeding Data Structure The response covers the whole lifecycle of a case: * **Status:** `current_status` reflects where the proceeding stands (e.g. `preliminary`, `opened`, `rejected_no_assets`, `lifted`, `discharge_granted`) * **Debtor:** name, kind (legal or natural person), legal form, and — where resolvable — the linked `company_id` for direct lookup of the debtor company * **Administration:** administrator name and address, administration kind (external administration, self administration, protective shield) * **Deadlines and distributions:** `claims_filing_deadline`, opening and closing dates, and distribution figures (`distribution_claims_total`, `distribution_available`) * **Events:** every published announcement as a structured event with a summary, decision and publication dates, and typed `details` (administrator appointments, meetings, discharge decisions, distribution records) ### Use Cases **Case Tracking:** Follow a specific proceeding over time — new events appear as the courts publish announcements, from preliminary measures to the final discharge decision. **Due Diligence:** Reconstruct the full insolvency history of a counterparty, including past proceedings, administrators involved, and how the case was resolved. **Legal Research:** Access structured summaries of each announcement together with meeting dates and locations, without parsing the original court publications yourself. # Start Job Source: https://docs.openregister.de/endpoint/job-create POST /v1/jobs Start a realtime request without waiting for it. The request returns at once with a pending job. Use this instead of `realtime=true` when your client cannot keep a request open for the minutes the Handelsregister may take. Job types: - `company`: refreshes the company from the Handelsregister, like `GET /v1/company/{company_id}?realtime=true`. - `owners`: refreshes the company's owners, like `GET /v1/company/{company_id}/owners?realtime=true`. - `document`: fetches one document, like `GET /v1/document`. Requires `document_category`. Follow a job either way, or both: - Poll `GET /v1/jobs/{job_id}` until `status` is `completed` or `failed`. A completed job carries its result in `results`: the document for a `document` job, the company or its owners for a `company` or `owners` job. - Configure a webhook endpoint: when the job finishes, OpenRegister sends a `job.completed` or `job.failed` webhook to it. The job can be polled all the same. Jobs are available on paid plans. A completed job costs what the same request with `realtime=true` costs: 20 credits for `company` and `owners`, 10 for `document`. Failed jobs and polling are free. ## Start a realtime job Fetch fresh data from the Handelsregister without waiting for it. The request returns at once with a pending job, and OpenRegister fetches the data in the background. Use a job instead of `realtime=true` when your client cannot keep a request open while the Handelsregister answers. **Cost:** 20 credits for `company` and `owners` jobs, 10 credits for `document` jobs, charged when the job completes. Failed jobs are free. ### Job types | `type` | Fetches | Same as | | - | - | - | | `company` | The company's register data | [`GET /v1/company/{company_id}?realtime=true`](/endpoint/company) | | `owners` | The company's owners | [`GET /v1/company/{company_id}/owners?realtime=true`](/endpoint/company-owners) | | `document` | One register document, set by `document_category` | [`GET /v1/document`](/endpoint/document-realtime) | ### Following a job Follow a job either way, or both: 1. **Polling:** call [Get Job](/endpoint/job-get) with the returned `id` until `status` is `completed` or `failed`. A completed job carries its result in `results`. 2. **Webhook:** configure a webhook endpoint in your [OpenRegister dashboard](https://openregister.de/keys). When the job finishes, OpenRegister sends a `job.completed` or `job.failed` webhook to it. The webhook carries no result; read `results` with [Get Job](/endpoint/job-get). Webhooks are delivered and signed the same way as monitor webhooks, see [Receiving Webhooks](/guide/monitoring#receiving-webhooks) and [Verifying Webhook Signatures](/guide/monitoring#verifying-webhook-signatures). > [!NOTE] > > If your endpoint subscribes to selected event types only, add `job.completed` and `job.failed` to receive job webhooks. ### Webhook payload `job.completed` and `job.failed` share one payload. **event\_type** `string` *required* Event type identifier: `job.completed` or `job.failed`. **job\_id** `string` *required* Job ID, as returned by `POST /v1/jobs`. **type** `string` *required* Job type: `company`, `owners` or `document`. **company\_id** `string` *required* Company register ID the job refreshed (e.g. `DE-HRB-F1103-267645`). **document\_category** `string | null` *required* Document category of a `document` job; `null` for `company` and `owners` jobs. **status** `string` *required* Final job status: `completed` or `failed`. **reason** `string | null` *required* Why the job failed, see [failure reasons](/endpoint/job-get#failure-reasons); `null` for completed jobs. **timestamp** `string` *required* When the job finished (ISO 8601 / RFC 3339). ```json job.completed theme={"dark"} { "event_type": "job.completed", "job_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "type": "document", "company_id": "DE-HRB-F1103-267645", "document_category": "current_printout", "status": "completed", "reason": null, "timestamp": "2026-11-04T12:00:00Z" } ``` ```json job.failed theme={"dark"} { "event_type": "job.failed", "job_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "type": "company", "company_id": "DE-HRB-F1103-267645", "document_category": null, "status": "failed", "reason": "timeout", "timestamp": "2026-11-04T12:00:00Z" } ``` ### Error cases | Status | Cause | | - | - | | `400` | Invalid parameters, a `company` job for an inactive company, or an `owners` job for a legal form without [owner data](/endpoint/company-owners#supported-legal-forms) | | `401` | Authentication required | | `402` | Jobs are available on paid plans only | | `404` | Company not found | | `429` | 100 jobs are already pending for your account | | `500` | Internal server error | ### Notes * `document_category` is required for `document` jobs and not allowed for other types. * For `company` and `owners` jobs, `company_id` in the response is the company's latest register ID. It differs from the requested one when the company moved to another register. # Get Job Source: https://docs.openregister.de/endpoint/job-get GET /v1/jobs/{job_id} Get a job's status and, once it completed, its result in `results`. Polling is free. - `document` jobs return `results.document` with a download URL, presigned again on every read. - `company` jobs return `results.company`, the same as `GET /v1/company/{company_id}`. - `owners` jobs return `results.owners`, the same as `GET /v1/company/{company_id}/owners`. Results are returned for 12 hours after the job finished (`expires_at`); after that, `results` is null and the regular endpoints serve the data. ## Get a job Returns a job's status and, once it completed, its result. Poll this endpoint after [starting a job](/endpoint/job-create) until `status` is `completed` or `failed`, or wait for the job's webhook and read the result here. **Recommended polling interval:** every 5–10 seconds. **Cost:** 0 credits ### Status values | Status | Meaning | What to do | | - | - | - | | `pending` | Queued or still being fetched from the Handelsregister | Continue polling | | `completed` | The data was fetched | Read `results` | | `failed` | The job could not be completed, see `reason` | Terminal; start a new job | ### Results A completed job returns its result in `results`. Only the field of the job's type is set, the other two are `null`. | Job type | Field | Content | | - | - | - | | `document` | `results.document` | `url`, `file_name` and `file_date` of the fetched document | | `company` | `results.company` | The company, as [`GET /v1/company/{company_id}`](/endpoint/company) returns it | | `owners` | `results.owners` | The owners, as [`GET /v1/company/{company_id}/owners`](/endpoint/company-owners) returns them | The document `url` is short-lived and presigned again on every read; read the job again for a fresh one. Results are returned for 12 hours after the job finished, until `expires_at`. After that `results` is `null`; read the regular endpoints instead. `results` is also `null` while the job is pending and when it failed. ```json Completed owners job theme={"dark"} { "id": "9e8a48af-fc0f-498f-8072-aeb087a8a0f9", "type": "owners", "company_id": "DE-HRB-F1103-267645", "document_category": null, "status": "completed", "reason": null, "results": { "document": null, "company": null, "owners": { "company_id": "DE-HRB-F1103-267645", "owners": [ ... ], ... } }, "expires_at": "2026-11-05T01:48:59.936Z", "created_at": "2026-11-04T13:48:42.601Z", "finished_at": "2026-11-04T13:48:59.936Z" } ``` ### Failure reasons | Reason | Meaning | | - | - | | `not_available` | The register holds no such document for this company (for `owners` jobs: no shareholder list) | | `timeout` | The Handelsregister did not answer in time; try again later | | `internal_error` | Any other failure | ### Error cases | Status | Cause | | - | - | | `401` | Authentication required | | `404` | No job with this ID for your account | | `500` | Internal server error | # Create Monitor Source: https://docs.openregister.de/endpoint/monitor-create POST /v1/monitor ## Create a monitor Create a monitor to receive webhook notifications when a company or person is updated. **Cost:** 25 credits (50 credits for daily monitors) > [!NOTE] > > Before creating monitors, you must configure a webhook URL in your [OpenRegister dashboard](https://openregister.de/keys). See the [Monitoring guide](/guide/monitoring) for a full overview of how monitoring works. ### Entity ID The `entity_id` format depends on the `entity_type`: * **Company** — use the register ID, e.g. `DE-HRB-F1103-267645`. You can find this on the company page or via the search endpoints. * **Person** — use the person UUID returned by the person search or person endpoint. ### Preferences Preferences control which data categories trigger a webhook notification. You must provide at least one preference. All values must correspond to the given `entity_type` — mixing preferences across entity types returns a `400 Bad Request`. **Company** (`entity_type: company`) | Value | What triggers a notification | | - | - | | `basic` | Core firmographic data — name, registered address, legal form, or status | | `representation` | Directors, officers, managing partners, or authorised signatories | | `financials` | Annual accounts or financial statements filed | | `documents` | New documents or publications filed with the register | | `ownership` | Direct owners (shareholders) of the company | | `holdings` | Companies in which this company holds a stake | **Person** (`entity_type: person`) | Value | What triggers a notification | | - | - | | `management_positions` | Board or management roles the person holds across any company | | `holdings` | Companies in which this person holds a stake | ### Update Frequency The optional `update_frequency` field controls how often the monitored company is checked for register updates: | Value | Check cadence | Creation cost | Monthly cost | | - | - | - | - | | `weekly` (default) | At least once per week | 25 credits | 25 credits | | `daily` | Once per day | 50 credits | 50 credits | If you omit the field, the monitor defaults to `weekly`. > [!WARNING] > > `update_frequency` is only supported for company monitors. Including it when `entity_type` is `person` returns a `400 Bad Request` validation error. ### Use Cases **Compliance monitoring** — Subscribe to `basic`, `representation` and `ownership` changes on counterparties or customers. Receive alerts on legal form conversions, address moves, or management changes as soon as they appear in the register. **Ownership change alerts** — Use the `ownership` and `holdings` preferences to detect when a company's shareholder structure changes, keeping your KYC data current without manual re-checks. **Financial filing alerts** — Monitor the `financials` and `documents` preferences to be notified the moment new annual accounts or register publications are available, enabling automated document retrieval and archiving workflows. **Due diligence pipelines** — Add a monitor when onboarding a new counterparty. Receive ongoing notifications for the duration of the relationship and remove the monitor when the relationship ends. # Delete Monitor Source: https://docs.openregister.de/endpoint/monitor-delete DELETE /v1/monitor/{entity_id} ## Delete a monitor Permanently removes a monitor and stops all future webhook notifications for that entity. **Cost:** 0 credits > [!NOTE] > > See the [Monitoring guide](/guide/monitoring) for a full overview of how monitoring works, including how to manage the monitor lifecycle. ### Entity ID Pass the same `entity_id` that was used when creating the monitor — the company register ID (e.g. `DE-HRB-F1103-267645`) or the person UUID. Deletion is immediate and permanent. To resume monitoring the same entity you must create a new monitor. > [!WARNING] > > Deletion cannot be undone. All preferences configured on the monitor are removed and no further notifications will be delivered for that entity. ### Use Cases **Offboarding a client or counterparty** — When a business relationship ends, delete the corresponding monitor to stop receiving notifications for that entity and avoid unnecessary noise. **Pruning stale monitors** — Periodically review your monitor list and remove entities that are no longer relevant to your business to keep your subscription list clean. # List Monitors Source: https://docs.openregister.de/endpoint/monitor-list GET /v1/monitor ## List monitors Returns all monitors created for the current API user. **Cost:** 0 credits > [!NOTE] > > See the [Monitoring guide](/guide/monitoring) for a full overview of how monitoring works, including webhook setup and preference options. ### Response The response contains an `items` array. Each item represents one active or disabled monitor and includes: | Field | Type | Description | | - | - | - | | `entity_id` | string | The company register ID or person UUID being monitored | | `entity_type` | string | `company` or `person` | | `preferences` | array | The data categories this monitor is watching | | `update_frequency` | string | How often the entity is checked for updates: `daily` or `weekly`. Always `weekly` for person monitors | | `disabled` | boolean | Whether the monitor has been disabled by the system | ### The `disabled` flag A monitor is marked `disabled: true` when your account is downgraded to a plan that no longer includes monitoring access. Disabled monitors are preserved so you do not lose your configuration, but they stop delivering notifications. Monitors are **not** automatically re-enabled when you upgrade again — this is intentional to prevent unexpected billing. To re-enable a disabled monitor, contact the team at [founders@openregister.de](mailto:founders@openregister.de). Use the list endpoint to check for disabled monitors after any plan change so you can act before missing notifications. ### Use Cases **Audit active subscriptions** — Retrieve the full list of entities you are currently watching to verify coverage, identify gaps, or reconcile against your internal records. **Detect disabled monitors** — Filter the response for `disabled: true` items to find monitors that have stopped delivering notifications due to a plan downgrade. Contact [founders@openregister.de](mailto:founders@openregister.de) to get them re-enabled. **Reconcile with your database** — Periodically compare the list of monitors against your own data to identify entities that should no longer be monitored and clean them up with the delete endpoint. # Person information Source: https://docs.openregister.de/endpoint/person GET /v1/person/{person_id} ## Get person information Retrieve detailed information about a natural person including their name, date of birth, city of residence, age, and their roles across multiple companies. This endpoint aggregates data about a person's management positions, providing a complete profile of their business activities. **Cost:** 10 credits ### Roles Each entry in `management_positions` carries a `role_detail` — see [Roles](/roles). # Person holdings Source: https://docs.openregister.de/endpoint/person-holdings GET /v1/person/{person_id}/holdings ## Get person holdings Retrieve all companies where a person holds ownership stakes. This endpoint provides a portfolio view showing the person's shareholdings across different companies, including ownership percentages. Use this to understand a person's business network and investment portfolio. **Cost:** 10 credits # Insolvency search Source: https://docs.openregister.de/endpoint/search-insolvency POST /v1/search/insolvency ## Search insolvency proceedings Search all German insolvency proceedings — for companies and natural persons — sourced from the official insolvency announcements (Insolvenzbekanntmachungen). Combine a free-text query with structured filters to find exactly the proceedings you care about. **Cost:** 10 credits per search ### Query and Filters The free-text `query` matches debtor names, case numbers, administrator names, and courts. Filters narrow results by: * **Proceeding attributes:** `current_status`, `proceeding_kind` (regular or consumer insolvency), `administration_kind` (external administration, self administration, protective shield), `insolvency_grounds`, `has_open_insolvency` * **Debtor attributes:** `debtor_kind` (legal or natural person), `debtor_legal_form` * **Location:** `court`, `city` * **Dates (`YYYY-MM-DD`, range via `min`/`max`):** `opened_at`, `closed_at`, `last_event_at`, `claims_filing_deadline` * **Entity links:** `company_id`, `person_id` — resolve a proceeding directly to a company or person in OpenRegister See the [filtering guide](/filtering#insolvency-search-fields) for the full field list and filter types. ### Use Cases **Risk Monitoring:** Screen your customer and supplier base for open insolvency proceedings. Filter by `has_open_insolvency = true` and `company_id` to check specific counterparties before extending credit. **Distressed-Asset Sourcing:** Find newly opened proceedings in your target region or industry by filtering on `opened_at` ranges, `court`, and `proceeding_kind` — a reliable early signal for restructuring and acquisition opportunities. **Claims Management:** Track `claims_filing_deadline` dates across proceedings you are involved in, so filing windows are never missed. # Search by website URL Source: https://docs.openregister.de/endpoint/search-lookup GET /v0/search/lookup ## Find company by website URL Find a company by providing its website URL. Our system analyzes the website and matches it to companies in our database. The response includes the company ID that you can use with other endpoints to retrieve detailed information like financials, shareholders, and ownership structure. This is useful for enriching web data with company information. **Cost:** 10 credits # Store credentials Source: https://docs.openregister.de/endpoint/transparenzregister-credentials POST /v1/transparenzregister/credentials Store username and password credentials for accessing the Transparenzregister API. These credentials will be used for subsequent requests to retrieve company documents. Credential names are user-scoped; the reserved name `sandbox` cannot be used. Credentials are validated against Transparenzregister before they are persisted. ## Store Transparenzregister credentials Stores Transparenzregister login credentials so that subsequent extract requests can authenticate on your behalf. Use the body field `name` to identify this credential set. If omitted, `name` defaults to `default`. You can store multiple named credential sets (e.g. per client). Submitting the same `name` again overwrites the stored credentials for that name without affecting extracts already in flight. The reserved name `sandbox` **cannot** be used — it is reserved for test-mode extracts via `X-Credential-Name: sandbox` on the [order extract](/endpoint/transparenzregister-extract-create) endpoint. Using `sandbox` as a credential name returns `400`. Your credentials are encrypted at rest. The plaintext values never touch our database — only encrypted ciphertext is persisted, and every decryption is logged and auditable. ### Responses | Status | Meaning | | - | - | | `201` | Credentials stored successfully | | `400` | Invalid body (e.g. reserved name `sandbox`, missing username/password) | | `401` | Not authenticated, or Transparenzregister rejected the provided username/password | | `402` | Transparenzregister API access requires a paid API plan — [contact us](mailto:founders@openregister.de) | | `409` | Maximum number of stored credential sets reached for this account | | `500` | Internal server error | **Cost:** 0 credits # Order extract Source: https://docs.openregister.de/endpoint/transparenzregister-extract-create POST /v1/transparenzregister/extracts Submit a Transparenzregister extract request and return an extract resource with processing status. Sandbox integration testing (recommended for all non-production testing): - Send `X-Credential-Name: sandbox`. - Do not send `company_id` (an empty body `{}` is valid). - OpenRegister uses the Transparenzregister test environment and built-in test authentication. - The request is submitted with the fixed test EKRN `DE727032388716`. - The response has `company_id: null`. Production usage: - Always set `X-Credential-Name` to `default` or another stored credential name. - `company_id` is required and must resolve to exactly one Transparenzregister legal entity. ## Order a Transparenzregister extract Places an order for a Transparenzregister extract and returns a `TransparenzregisterExtract` resource with processing status. Use the returned `id` as the polling handle. The typical flow is: 1. Store your credentials with the [credentials endpoint](/api/endpoint/transparenzregister-credentials) 2. Order an extract here with `company_id` (production) or sandbox mode (see below) 3. Poll the [get extract endpoint](/api/endpoint/transparenzregister-extract-get) with the returned `id` until `status` is `completed` or `failed` At the Transparenzregister (EiS), requests are asynchronous: search → submit request → order documents → download. OpenRegister coordinates that workflow internally; you only poll until `status` leaves `processing`. ### Sandbox mode (integration testing) Send header `X-Credential-Name: sandbox` and omit `company_id` (an empty body `{}` is valid). OpenRegister uses the EiS test environment at `https://test2.api.transparenzregister.de` with the built-in test user `testnutzer-eis@transparenzregister.de`. The request uses the fixed test EKRN `DE727032388716`; the response has `company_id: null`. **Cost:** 0 credits. ### Production mode Always set `X-Credential-Name` — use `default` or another stored credential name you use in production. `company_id` is **required** and must resolve to exactly one Transparenzregister legal entity. ### Error cases | Status | Cause | | - | - | | `400` | Invalid parameters (e.g. reserved credential name where not allowed, invalid `company_id`) | | `401` | Authentication required | | `402` | Transparenzregister API access requires a paid API plan | | `403` | Transparenzregister rejected authentication for the selected credential mode (EiS: account not unlocked, identification incomplete, or account locked) | | `404` | Company not found, credentials not found, or no Transparenzregister match for the company | | `409` | Multiple Transparenzregister companies matched — request cannot be disambiguated | | `429` | Production extract quota exceeded for the rolling 30-day window | | `500` | Internal server error | **Cost:** 25 credits (0 credits when `X-Credential-Name: sandbox`) ### Notes * The returned `id` (e.g. `tre_12345678`) is stable — store it to retrieve the extract later. # Get extract Source: https://docs.openregister.de/endpoint/transparenzregister-extract-get GET /v1/transparenzregister/extracts/{extract_id} Get the results of a Transparenzregister extract request. This endpoint handles all internal complexity including polling request status, selecting all available documents, creating Transparenzregister baskets, and returning download URLs when ready. If the request is still processing, it will return a pending status. Polling reuses the credential mode stored on the extract at create time. Sandbox extracts keep using the Transparenzregister test client automatically; no credential header is accepted on this endpoint. ## Get Transparenzregister extract Returns the current state of a previously ordered extract. Poll this endpoint after calling the [order extract endpoint](/api/endpoint/transparenzregister-extract-create) until `status` is `completed` or `failed`. **Recommended polling interval:** every 5–10 seconds. Most extracts complete within 5-60 seconds, but can take longer depending on Transparenzregister availability. * **`200`** — Extract retrieved; may still be `processing` or terminal `completed` / `failed` * **`202`** — Extract is still processing (same response schema as `200`) Do **not** send `X-Credential-Name` on this request. Polling reuses the credential mode stored when the extract was created; sandbox extracts keep using the Transparenzregister test client automatically. Once `status` is `completed`, results are cached — you can fetch the same `extract_id` again without re-processing or incurring additional costs. **Cost:** 0 credits ### Status values | Status | Meaning | What to do | | - | - | - | | `processing` | Queued or still handled by Transparenzregister | Continue polling | | `completed` | Structured report and/or documents are ready | Read `report` and `documents` | | `failed` | Extract could not be completed | Terminal — order a new extract | #### Top-level extract fields | Field | Description | | - | - | | `id` | Stable OpenRegister extract id (e.g. `tre_12345678`) | | `status` | `completed` \| `processing` \| `failed` | | `company_id` | Company identifier; `null` for sandbox extracts | | `ekrn` | 14-character Einheitliche und kontinuierliche Rechtseinheitsnummer (upstream `ekrn`) | | `reference_number` | Upstream `referenznummer` (6 characters); identifies the register extract and chains corrections | | `submitted_at` / `completed_at` | OpenRegister timestamps (not present in upstream JSON) | #### `report` — parsed register entry Derived from the JSON variant of the extract document. | API field | Upstream | Notes | | - | - | - | | `created_at` | `erstellungsdatum` | `dd.mm.jjjj` → ISO `YYYY-MM-DD` | | `notice_type` | `angabenZumAuszug.artDerMitteilung` | e.g. `Mitteilung wirtschaftlich Berechtigter nach §§ 20, 21 GwG`, `Automatische Eintragung nach § 20a GwG` | | `validity.from` / `validity.until` | `gueltigVonDatum` / `gueltigVonSonstiges`, `gueltigBisDatum` / `gueltigBisSonstiges` | Each side has `date` and/or `note` (e.g. `Unbekannt`, `vor dem 01.10.2017`, `bis auf Weiteres`) | | `status_flags.deleted` | `loeschkennzeichen` | | | `status_flags.deletion_date` | `loeschdatum` | Only when entity is deleted | | `status_flags.discrepancy_note` | `vermerkUnstimmigkeitsmeldung` | e.g. ongoing § 23a GwG review, or completed on a date | | `status_flags.corrected_references` | `berichtigt` | List of 6-char reference numbers this extract corrects | | `status_flags.corrected_by_reference` | `wirdBerichtigtDurch` | Reference of a later extract that corrects this one (see EiS § 8) | | `groups[].position` | `gruppen[].position` | | | `groups[].interest_type` | `gruppen[].wirtschaftlichesInteresseGruppe` | Often the § 3 Abs. 3 Nr. 4 GwG group-of-beneficiaries case | | `groups[].description` | `gruppen[].beschreibungGruppe` | Free text (up to 10 000 chars upstream) | | `ubos[].position` | `wirtschaftlichBerechtigte[].position` | | | `ubos[].natural_person.title` | `titel` | e.g. `Dr.` / `Prof.` — not a job title | | `ubos[].natural_person.first_name` / `last_name` | `vorname` / `nachname` | As on ID document | | `ubos[].natural_person.full_name` | — | Derived (space-joined first + last) | | `ubos[].natural_person.date_of_birth` | `geburtsdatum` | ISO date | | `ubos[].natural_person.nationalities` | `staatsangehoerigkeit` | Mapped toward ISO 3166-1 alpha-2 where known (`Deutschland`→`DE`, `Österreich`→`AT`, `Schweiz`→`CH`; 2-letter codes uppercased) | | `ubos[].natural_person.city` | `wohnort` | Primary residence | | `ubos[].natural_person.country` | `wohnSitzLand` | Same country mapping as nationalities | | `ubos[].interest.type` | `wirtschaftlichesInteresseArt` | Legal category (capital, voting rights, control, trust roles, foundation, etc. — see EiS § 7.1 enumeration) | | `ubos[].interest.scope` | `wirtschaftlichesInteresseUmfang` | Free text (up to 10 000 chars) | | `ubos[].interest.percentage` | — | **Derived:** best-effort parse of a percentage from `scope` text (regex); `null` if none found — not authoritative | | `fictional_ubo_reason` | `grundFiktiveWb` | When no natural-person UBO per § 3 GwG could be determined (enumerated upstream strings) | #### `ubos[].interest.type` — enumeration Values are the full German strings returned by the register, including legal references. Examples include: * `Beteiligung an der Vereinigung selbst, insbesondere der Höhe der Kapitalanteile (§ 19 Abs. 3 Nr. 1a GwG)` * `Beteiligung an der Vereinigung selbst, insbesondere der Stimmrechte (§ 19 Abs. 3 Nr. 1a GwG)` * `Ausübung von Kontrolle auf sonstige Weise (§ 19 Abs. 3 Nr. 1b GwG)` * `Treugeber (Settlor), Trustee oder Protektor (§ 3 Abs. 3 Nr. 1 GwG)` * `Mitglied des Vorstands der Stiftung (§ 3 Abs. 3 Nr. 2 GwG)` * `Begünstigter (§ 3 Abs. 3 Nr. 3 GwG)` * `Person mit sonstigem beherrschendem Einfluss auf Vermögensverwaltung / Ertragsverteilung (§ 3 Abs. 3 Nr. 5 GwG)` * `Sonstige Funktion des gesetzlichen Vertreters (§ 19 Abs. 3 Nr. 1c GwG)` * `Funktion des geschäftsführenden Gesellschafters oder Partners (§ 19 Abs. 3 Nr. 1c GwG)` * `Person mit beherrschendem Einfluss nach § 3 Abs. 3 Nr. 6 GwG` * `Funktion des gesetzlichen Vertreters, geschäftsführenden Gesellschafters oder Partners (§ 19 Abs. 3 Nr. 1c GwG)` * `Person mit beherrschendem Einfluss auf eine Vereinigung, die Mitglied des Vorstands der Stiftung ist oder die als Begünstigte der Stiftung bestimmt worden ist (§ 3 Abs. 3 Nr. 6a GwG)` * `Person mit beherrschendem Einfluss auf eine Vereinigung, die als Treugeber (Settlor), Verwalter von Trusts (Trustee) oder Protektor handelt oder die als Begünstigte der Rechtseinheit bestimmt worden ist (§ 3 Abs. 3 Nr. 6b GwG)` #### `fictional_ubo_reason` — upstream `grundFiktiveWb` When set, typical values include: * `Es wurde keine natürliche Person ermittelt, die die Voraussetzungen eines wirtschaftlich Berechtigten nach § 3 Abs. 1 oder Abs. 2 S. 1 - 4 GwG erfüllt.` * `Die Ermittlung eines wirtschaftlich Berechtigten nach § 3 Abs. 1 oder Abs. 2 S. 1 - 4 GwG war nach Durchführung umfassender Prüfungen nicht möglich.` * `keine Angabe` #### `documents[]` | Field | Description | | - | - | | `document_id` | Stable UUID for this document | | `url` | Short-lived download URL | | `format` | e.g. `pdf` (human-readable extract), `json` (structured extract feeding `report`), `svg` (Eigentums- und Kontrollstrukturübersicht when present — EiS § 9), `xml` when returned by TR | | `filename` | Suggested filename | # Filtering Guide Source: https://docs.openregister.de/filtering The search endpoints accept structured filters to narrow down results. This guide explains how filters work and which fields you can filter on. It applies to: * [Company search](/endpoint/filter-company) (`POST /v1/search/company`) * [Person search](/endpoint/filter-person) (`POST /v1/search/person`) * [Insolvency search](/endpoint/search-insolvency) (`POST /v1/search/insolvency`) All three share the same request structure and filter types; they differ only in which fields are filterable (see [Filterable Fields](#filterable-fields)). ## Request Structure Filters go into the `filters` array of the request body. Each object in the array is one condition and must contain a `field` plus one of the [filter types](#filter-types) (`value`, `values`, `keywords`, or `min`/`max`). ```json theme={"dark"} { "filters": [ { "field": "status", "value": "active" } ] } ``` All conditions in the `filters` array are combined with **AND** — a result must satisfy every one of them: ```json theme={"dark"} { "filters": [ { "field": "legal_form", "value": "gmbh" }, { "field": "employees", "min": "50" } ] } ``` For an **OR** across several values of the same field, use `values` (see below). ## Filter Types ### Exact Match: `value` For a simple exact match, use the `value` property. ```json theme={"dark"} { "field": "legal_form", "value": "gmbh" } ``` ### Multiple Values: `values` To match any one of a list of values ("OR" within a field), use the `values` array. ```json theme={"dark"} { "field": "city", "values": ["Berlin", "Hamburg", "München"] } ``` ### Keyword Matching: `keywords` For free-text fields, `keywords` finds records whose field **contains** any of the specified words — unlike `values`, which requires the whole field to match exactly. Use it on fields like `purpose` or `address`. ```json theme={"dark"} { "field": "purpose", "keywords": ["Photovoltaik", "Solar"] } ``` This matches companies whose business purpose mentions "Photovoltaik" or "Solar" anywhere in the text. ### Range Filtering: `min` and `max` For numerical and date fields, specify a range using `min` and/or `max`. Both bounds are optional — use just one for an open-ended range. ```json theme={"dark"} { "field": "employees", "min": "10", "max": "100" } ``` ## Value Conventions A few conventions apply across all fields: > [!WARNING] > > **Monetary values are in cents, not euros.** This applies to `capital_amount` and every financial indicator field (`revenue`, `ebitda`, `balance_sheet_total`, …). For example, 1 million EUR = `100000000` cents. * **Dates** use the `DD-MM-YYYY` format, e.g. `"01-01-2026"`. (The ISO `YYYY-MM-DD` format is also accepted.) Date fields support `min`/`max` ranges: ```json theme={"dark"} { "field": "incorporated_at", "min": "01-01-2020", "max": "31-12-2021" } ``` * **Booleans** are passed as the strings `"true"` or `"false"`: ```json theme={"dark"} { "field": "has_open_insolvency", "value": "true" } ``` ## Free-Text Search Query Besides structured filters, you can perform a free-text search using the `query` field. This is useful for finding companies by name or previous names. `query` and `filters` can be combined: ```json theme={"dark"} { "query": { "value": "Descartes" }, "filters": [ { "field": "city", "value": "Berlin" } ] } ``` This searches for companies with "Descartes" in their name or previous names that are located in Berlin. ## Location Filtering For company search, you can filter by geographical location with a `location` object in the request body. It requires `latitude` and `longitude`, and optionally accepts a `radius` in kilometers. ```json theme={"dark"} { "location": { "latitude": 52.5200, "longitude": 13.4050, "radius": 10 } } ``` ## Estimated Financials Most German companies publish a balance sheet but no income statement, so revenue, EBITDA and often headcount are missing. For those companies, OpenRegister estimates the missing figures from what they do publish, with models trained on the companies that report them. Estimates are available as filters: `estimated_revenue`, `estimated_ebitda` and `estimated_employees` for the figure, and `estimated_revenue_confidence`, `estimated_ebitda_confidence` and `estimated_employees_confidence` for how reliable it is. The estimates themselves are returned by the [company](/endpoint/company) and [financials](/endpoint/company-financials) endpoints. A few rules keep reported and estimated figures apart: * **Reported figures are included.** `estimated_revenue` matches the best available figure: the reported revenue where a company publishes one, the estimate everywhere else. The same rule applies to EBITDA and headcount. A company never has both for one metric, so nothing is counted twice and no fiscal years are mixed. Use `revenue`, `ebitda` or `employees` if you want published figures only. * **Same freshness as reported figures.** An estimate refers to the company's latest fiscal year with a filing and, like reported indicators, ages out after four years. * **Units.** Revenue and EBITDA are in cents, like every other monetary field. `estimated_employees` is a headcount, like `employees`. * **Not estimated:** companies in an open insolvency proceeding, and companies under a profit transfer agreement (their reported profit is zero by contract, so nothing can be inferred from it). ### How confidence works Every estimate is a range, not just a number: a median plus an **80% interval** from the 10th to the 90th percentile. The models are calibrated on companies they never saw during training so that the true figure falls inside this interval for roughly 80 of 100 companies. Range filters on `estimated_revenue`, `estimated_ebitda` and `estimated_employees` apply to the median, which the API returns as `value`. How wide that interval is varies a lot between companies: a GmbH with a detailed balance sheet, a headcount and an industry code gets a tight band, a holding with three balance sheet lines does not. The `confidence` tier summarises the width so you can filter on it without reasoning about quantiles: | Tier | Revenue | EBITDA | Employees | | :- | :- | :- | :- | | `high` | the likely range spans at most a factor of **4**, e.g. 1 to 4 million EUR | the likely range is at most **10%** of the balance sheet total | the likely range spans at most a factor of **3** | | `medium` | at most a factor of **8** | at most **30%** | at most a factor of **6** | | `low` | anything wider | anything wider, or no balance sheet total to compare with | anything wider | Revenue and headcount use a ratio because they scale with company size. Headcount adds one person at each edge of the band before taking the ratio, so a lower bound of zero still has a width. EBITDA is measured against the balance sheet total instead, because its median is often close to zero, where a relative width would say nothing. ### Reading estimates The [company](/endpoint/company) and [financials](/endpoint/company-financials) endpoints return `estimates` with one entry per metric. Each entry is the estimate the filters match on: `value` is the figure, `min` and `max` bound the 80% interval (the true figure lies outside it for about 1 in 5 companies), `confidence` is the tier from the table above, and `date` is the end of the fiscal year it refers to. ```json theme={"dark"} "estimates": { "revenue": { "value": 250000000, "min": 120000000, "max": 410000000, "confidence": "high", "date": "2024-12-31" }, "ebitda": null, "employees": { "value": 18, "min": 9, "max": 31, "confidence": "medium", "date": "2024-12-31" } } ``` A metric is `null` when the company's latest report states it (read it from `indicators` instead), when the company is not estimated, or when the estimate is more than four years old. Only the latest fiscal year is returned. Search results do not include estimates; fetch the company to read them. Use `estimated_revenue_confidence`, `estimated_ebitda_confidence` and `estimated_employees_confidence` with `value` or `values` to pick the tiers you accept. Companies with a reported figure pass whichever tiers you pick — a published number is the most confident value there is — so `["high"]` means reported figures plus tight estimates. For lead lists, where a wrong size costs an outreach, `["high"]` or `["high", "medium"]` is the usual choice. For market sizing across many companies, all tiers are fine: the errors average out, the individual ranges do not. Combine the tier with a range on the figure itself, here 1 to 5 million EUR in cents: ```json theme={"dark"} { "filters": [ { "field": "estimated_revenue", "min": "100000000", "max": "500000000" }, { "field": "estimated_revenue_confidence", "values": ["high", "medium"] } ] } ``` Headcount works the same way, in persons rather than cents. This matches companies whose best available headcount is 10 to 50, reported or estimated, and whose estimate (if that is what they have) is in the tightest tier: ```json theme={"dark"} { "filters": [ { "field": "estimated_employees", "min": "10", "max": "50" }, { "field": "estimated_employees_confidence", "value": "high" } ] } ``` ## Insolvency risk `insolvency_risk` is a class for the chance that a company starts an insolvency proceeding in the next 12 months. It is a statistical reading of public register and filing data. It is a filter on [company search](/endpoint/filter-company); search results list the company, its address and its purpose, and do not include the class. | Value | 12-month probability | | :- | :- | | `very_low` | under 0.1% | | `low` | 0.1% to under 0.3% | | `average` | 0.3% to under 0.8% | | `elevated` | 0.8% to under 2.5% | | `high` | 2.5% to under 7% | | `very_high` | 7% or more | Pass one class with `value`, or several with `values` (OR). A range is not accepted. The class is present for active companies that have no insolvency proceeding on record and whose score is at most two months old. Scored legal forms are GmbH, gGmbH, UG, AG, SE, KGaA, and a KG whose general partners are all companies (GmbH & Co. KG). Sole traders and partnerships of natural persons are unscored, so a filter on this field does not match them. A company that already has a proceeding, open or closed, is matched through `had_insolvency`, `has_open_insolvency` and `insolvency_stage` instead. ```json theme={"dark"} { "filters": [ { "field": "insolvency_risk", "values": ["high", "very_high"] } ] } ``` ## Examples Common company search recipes, combining the building blocks above. ### All Restaurants Filter by the `industry_codes` field (WZ2025 codes): ```json theme={"dark"} { "filters": [ { "field": "industry_codes", "value": "56.11" } ] } ``` Codes can be given at any WZ 2025 level. This matches all of gastronomy (division `56`) plus one subclass of software development: ```json theme={"dark"} { "filters": [ { "field": "industry_codes", "values": ["56", "62.10.4"] } ] } ``` `industry_codes` matches any of a company's activities. To match only companies whose main activity is in a code, use `primary_industry_codes`. This finds beverage wholesalers, but not manufacturers that also wholesale beverages: ```json theme={"dark"} { "filters": [ { "field": "primary_industry_codes", "value": "46.34" } ] } ``` ### Newly Founded Companies Companies incorporated since the start of 2026, using a range filter on `incorporated_at`: ```json theme={"dark"} { "filters": [ { "field": "incorporated_at", "min": "01-01-2026" } ] } ``` ### High-Revenue Companies with a Large Workforce Companies with more than 100 employees and over 100 million EUR in revenue (remember: monetary values are in cents — 100 million EUR = 10,000,000,000 cents): ```json theme={"dark"} { "filters": [ { "field": "employees", "min": "100" }, { "field": "revenue", "min": "10000000000" } ] } ``` ### Companies in a Specific Location All companies with a registered address in a specific postal code: ```json theme={"dark"} { "filters": [ { "field": "zip", "value": "10117" } ] } ``` ### Companies with a Specific Legal Form and Capital All GmbH companies with a capital of more than 1 million EUR (= 100,000,000 cents): ```json theme={"dark"} { "filters": [ { "field": "legal_form", "value": "gmbh" }, { "field": "capital_amount", "min": "100000000" }, { "field": "capital_currency", "value": "EUR" } ] } ``` ### Companies With or Without a Legal Entity Identifier (LEI) Use `has_lei` with `"true"` or `"false"` to restrict results to companies that have been indexed with a non-empty LEI (`true`) or without one (`false`): ```json theme={"dark"} { "filters": [ { "field": "has_lei", "value": "true" } ] } ``` Or match one or more exact LEIs (20-character GLEIF identifiers) via `lei`: ```json theme={"dark"} { "filters": [ { "field": "lei", "values": ["5493001HCMGWDQ4MX390", "529900T8BM49AURSDO55"] } ] } ``` ### Companies by Auditor Use `auditor` to match one or more audit firms by their exact registered name. It matches the firm of the company's most recent report whose auditor could be matched to a registered company, so sole practitioners are not searchable by name: ```json theme={"dark"} { "filters": [ { "field": "auditor", "values": ["KPMG AG Wirtschaftsprüfungsgesellschaft"] } ] } ``` ### Companies by VAT ID Use `vat_id` to look up companies by their VAT identification number (Umsatzsteuer-Identifikationsnummer). VAT IDs are collected from company websites, so they are only available for companies whose website has been indexed. ```json theme={"dark"} { "filters": [ { "field": "vat_id", "values": ["DE265054603", "DE812708193"] } ] } ``` ### Companies by Estimated Revenue Companies with revenue between 5 and 20 million EUR (cents: 5 million EUR = 500,000,000), reported or estimated, keeping reported figures and the tighter confidence tiers — see [How confidence works](#how-confidence-works): ```json theme={"dark"} { "filters": [ { "field": "estimated_revenue", "min": "500000000", "max": "2000000000" }, { "field": "estimated_revenue_confidence", "values": ["high", "medium"] } ] } ``` ### Companies with an Open Insolvency Proceeding Companies that currently have an open insolvency proceeding, opened since the start of 2026: ```json theme={"dark"} { "filters": [ { "field": "has_open_insolvency", "value": "true" }, { "field": "insolvency_opened_at", "min": "01-01-2026" } ] } ``` You can also target specific stages of a proceeding, e.g. all companies in preliminary or opened proceedings: ```json theme={"dark"} { "filters": [ { "field": "insolvency_stage", "values": ["preliminary", "opened"] } ] } ``` ### Owner-Managed Companies for Succession Planning Owner-managed businesses with an older owner — ideal for identifying succession opportunities: ```json theme={"dark"} { "filters": [ { "field": "has_representative_owner", "value": "true" }, { "field": "is_family_owned", "value": "false" }, { "field": "youngest_owner_age", "min": "60" } ] } ``` ## Filterable Fields ### Company Search The [company search](/endpoint/filter-company) supports general company fields, financial indicator fields and estimated financial fields. #### Company Fields | Field | Description | | :- | :- | | `status` | The current status of the company (e.g., `active`, `inactive`, `liquidation`). | | `legal_form` | The legal form of the company (e.g., `gmbh`, `ag`). | | `register_number` | The company's registration number. | | `register_court` | The court where the company is registered. | | `register_type` | The type of register (e.g., `HRB`, `HRA`). | | `city` | The city where the company is located. | | `active` | A boolean indicating if the company is active. | | `incorporated_at` | The date of incorporation. | | `purpose` | The business purpose of the company. | | `zip` | The postal code of the company's address. | | `address` | The full address of the company. | | `industry_codes` | The company's industry codes (WZ 2025). Accepts a division (`62`), class (`62.10`) or subclass (`62.10.4`), with or without dots; a company matches if any of its codes falls under one of them. | | `capital_amount` | The amount of the company's capital (in **cents**). | | `capital_currency` | The currency of the company's capital. | | `number_of_owners` | The number of company owners/shareholders. (enterprise only) | | `has_sole_owner` | Boolean indicating if the company has only one owner. (enterprise only) | | `has_representative_owner` | Boolean indicating if an owner is also in management (owner-managed). (enterprise only) | | `is_family_owned` | Boolean indicating if the company is family-owned. (enterprise only) | | `youngest_owner_age` | The age of the youngest owner/shareholder. (enterprise only) | | `youngest_director_age` | The age of the youngest person currently in management (Geschäftsführer, Vorstand, board members, liquidators). Excludes Prokuristen and owners who hold no management role. (enterprise only) | | `vat_id` | VAT identification number (Umsatzsteuer-Identifikationsnummer), sourced from the company's website imprint. Exact match via `value`, or `values` for multiple VAT IDs (OR). Only available for companies whose website has been indexed. | | `has_lei` | Boolean: company has a non-empty LEI indexed (`"true"`) or not (`"false"`). | | `lei` | Legal Entity Identifier (GLEIF). Exact match via `value`, or `values` for multiple LEIs (OR). | | `auditor` | Registered name of the audit firm on the company's most recent report with a matched auditor. Exact match via `value`, or `values` for multiple firms (OR). See [Companies by Auditor](#companies-by-auditor). | | `had_insolvency` | Boolean: company has ever had an insolvency proceeding. | | `has_open_insolvency` | Boolean: company currently has an open insolvency proceeding. | | `insolvency_stage` | Stage of the company's most relevant proceeding (e.g., `preliminary`, `opened`, `plan_supervised`, `lifted`, `discharge_granted`). Use `value`, or `values` for multiple stages (OR). | | `insolvency_opened_at` | The date the insolvency proceeding was opened. Range via `min`/`max`. | | `insolvency_risk` | Class of the 12-month insolvency risk: `very_low`, `low`, `average`, `elevated`, `high`, `very_high`. Use `value`, or `values` for several classes (OR). See [Insolvency risk](#insolvency-risk). | #### Financial Indicator Fields Every financial indicator can be used as a range filter via `min`/`max`, based on the company's most recent available fiscal year. > [!WARNING] > > All financial indicator fields use values in **cents**, not euros — except `employees` and `apprentices`. | Field | Description | | :- | :- | | `balance_sheet_total` | Balance sheet total (Bilanzsumme). | | `revenue` | Revenue (Umsatzerlöse). | | `net_income` | Net income (Jahresüberschuss). | | `parent_net_income` | Net income attributable to the parent company. | | `income_before_tax` | Income before taxes. | | `income_after_tax` | Income after taxes. | | `ebit` | Earnings before interest and taxes. | | `ebitda` | Earnings before interest, taxes, depreciation, and amortization. | | `employees` | The number of employees. | | `apprentices` | The number of apprentices (Auszubildende). | | `equity` | Equity (Eigenkapital). | | `cash` | Cash reserves. | | `fixed_assets` | Fixed assets (Anlagevermögen). | | `current_assets` | Current assets (Umlaufvermögen). | | `intangible_assets` | Intangible assets (immaterielle Vermögensgegenstände). | | `tangible_assets` | Tangible assets (Sachanlagen). | | `financial_assets` | Financial assets (Finanzanlagen). | | `securities` | Securities (Wertpapiere). | | `real_estate` | Real estate (Grundstücke und Bauten). | | `inventory` | Inventory (Vorräte). | | `receivables` | Receivables (Forderungen). | | `trade_receivables` | Trade receivables (Forderungen aus Lieferungen und Leistungen). | | `active_accruals` | Prepaid expenses (aktive Rechnungsabgrenzungsposten). | | `passive_accruals` | Deferred income (passive Rechnungsabgrenzungsposten). | | `liabilities` | Liabilities (Verbindlichkeiten). | | `other_liabilities` | Other liabilities (sonstige Verbindlichkeiten). | | `bank_debt` | Liabilities to banks (Verbindlichkeiten gegenüber Kreditinstituten). | | `trade_payables` | Trade payables (Verbindlichkeiten aus Lieferungen und Leistungen). | | `shareholder_liabilities` | Liabilities to shareholders (Verbindlichkeiten gegenüber Gesellschaftern). | | `affiliated_liabilities` | Liabilities to affiliated companies (Verbindlichkeiten gegenüber verbundenen Unternehmen). | | `financial_debt` | Financial debt (Finanzverbindlichkeiten). | | `provisions` | Provisions (Rückstellungen). | | `other_provisions` | Other provisions (sonstige Rückstellungen). | | `pension_provisions` | Pension provisions (Pensionsrückstellungen). | | `capital_reserves` | Capital reserves (Kapitalrücklage). | | `retained_earnings` | Retained earnings (Gewinnrücklagen). | | `profit_carryforward` | Profit carried forward (Gewinnvortrag). | | `materials` | Cost of materials (Materialaufwand). | | `salaries` | Personnel expenses (Personalaufwand). | | `operating_depreciation` | Depreciation and amortization on fixed assets (Abschreibungen). | | `financial_depreciation` | Depreciation on financial assets (Abschreibungen auf Finanzanlagen). | | `other_operating_income` | Other operating income (sonstige betriebliche Erträge). | | `other_operating_expenses` | Other operating expenses (sonstige betriebliche Aufwendungen). | | `interest_income` | Interest income (Zinserträge). | | `interest_expense` | Interest expense (Zinsaufwendungen). | | `commission_income` | Commission income (Provisionserträge). | | `commission_expense` | Commission expense (Provisionsaufwendungen). | | `taxes` | Income taxes (Steuern vom Einkommen und vom Ertrag). | | `other_taxes` | Other taxes (sonstige Steuern). | #### Estimated Financial Fields Where a company reports neither figure, the search carries model estimates; these filters match the reported figure where there is one and the estimate otherwise — see [Estimated Financials](#estimated-financials) for the rules and how the confidence tiers are defined. Monetary values are in **cents**. | Field | Description | | :- | :- | | `estimated_revenue` | Best available revenue: the reported figure where the company publishes one, the median of the estimate otherwise. Range via `min`/`max`. | | `estimated_revenue_confidence` | Confidence tier of the revenue estimate: `high`, `medium` or `low`. Reported figures pass every tier. Use `value`, or `values` for several tiers (OR). | | `estimated_ebitda` | Best available EBITDA: the reported figure where the company publishes one, the median of the estimate otherwise. Range via `min`/`max`. | | `estimated_ebitda_confidence` | Confidence tier of the EBITDA estimate: `high`, `medium` or `low`. Reported figures pass every tier. Use `value`, or `values` for several tiers (OR). | | `estimated_employees` | Best available headcount: the reported figure where the company publishes one, the median of the estimate otherwise. A person count. Range via `min`/`max`. | | `estimated_employees_confidence` | Confidence tier of the headcount estimate: `high`, `medium` or `low`. Reported figures pass every tier. Use `value`, or `values` for several tiers (OR). | ### Person Search The [person search](/endpoint/filter-person) supports the following filterable fields: | Field | Description | | :- | :- | | `city` | The city of the person. | | `date_of_birth` | The person's date of birth. Range via `min`/`max`. | | `active` | Boolean indicating if the person is active. | ### Insolvency Search The [insolvency search](/endpoint/search-insolvency) supports the following filterable fields. The date fields (`opened_at`, `closed_at`, `last_event_at`, `claims_filing_deadline`) support `min`/`max` ranges. | Field | Description | | :- | :- | | `current_status` | The current status of the proceeding (e.g., `preliminary`, `opened`, `lifted`, `discharge_granted`). | | `has_open_insolvency` | Boolean indicating if the proceeding is currently open. | | `proceeding_kind` | The kind of proceeding (`regular_insolvency`, `consumer_insolvency`). | | `administration_kind` | The kind of administration (`external_administration`, `self_administration`, `protective_shield`). | | `insolvency_grounds` | The legal grounds for the insolvency (e.g., `Zahlungsunfähigkeit`). | | `debtor_kind` | The kind of debtor (`legal_person`, `natural_person`). | | `debtor_legal_form` | The legal form of the debtor (e.g., `gmbh`). | | `court` | The insolvency court handling the proceeding. | | `city` | The city of the debtor. | | `opened_at` | The date the proceeding was opened. | | `closed_at` | The date the proceeding was closed. | | `last_event_at` | The date of the most recent announcement. | | `claims_filing_deadline` | The deadline for filing claims. | | `company_id` | The OpenRegister company ID of the debtor. | | `person_id` | The OpenRegister person ID of the debtor. | # Monitoring Source: https://docs.openregister.de/guide/monitoring Monitor companies and people for updates via webhook ## What is Monitoring? The monitoring API lets you subscribe to changes on specific companies or persons. When the entity is updated in the official register, OpenRegister delivers a webhook notification to your configured endpoint — no polling required. > [!NOTE] > > API monitors are completely separate from the Watchlist feature in the OpenRegister platform. They are independent systems and do not share state. Monitors created via the API only deliver webhooks to your configured endpoint; they do not appear in the platform Watchlist, and entries in your platform Watchlist do not trigger API webhooks. ## Getting Started ### Step 1: Configure your webhook URL Before creating any monitors you must configure a webhook endpoint in your [OpenRegister dashboard](https://openregister.de/keys). Your webhook endpoint must: * Accept `POST` requests * Return a `2xx` HTTP response within 15 seconds * Be publicly reachable over HTTPS ### Step 2: Create a monitor Call `POST /v1/monitor` with the entity you want to watch, its type, and the data categories (preferences) you care about. The monitor stays active and delivers notifications until you explicitly delete it. ```mermaid theme={"dark"} flowchart LR A["Create Monitor"] --> B[Entity updated in register] B --> C[Webhook delivered to your URL] C --> D{Still needed?} D -->|Yes| B D -->|No| E["Delete Monitor"] ``` ## Receiving Webhooks OpenRegister uses [Svix](https://www.svix.com) to deliver webhook notifications. Svix is a reliable webhook infrastructure service that handles signing, retries, and delivery guarantees on your behalf. For a full overview of consuming Svix-powered webhooks, see the [Svix receiving introduction](https://docs.svix.com/receiving/introduction). ### Delivery behaviour * OpenRegister sends a `POST` request to your configured endpoint with a JSON body. * Your endpoint must respond with a `2xx` status code within **15 seconds**. If it does not, Svix treats the delivery as failed and retries automatically with exponential back-off. * Disable **CSRF protection** for your webhook route — the requests come from Svix servers, not a browser, so CSRF tokens are never present. ### Webhook headers Every delivery includes three Svix-specific headers used for signature verification: | Header | Description | | - | - | | `svix-id` | Unique message ID. Identical across all retry attempts for the same event. | | `svix-timestamp` | Unix timestamp (seconds) of when the webhook was sent. | | `svix-signature` | One or more base64-encoded HMAC-SHA256 signatures. | ## Webhook Payloads Each delivery carries one of the following event types in its JSON body. [Jobs](/endpoint/job-create#webhook-payload) send `job.completed` and `job.failed` to the same endpoint. ### `monitor.company.updated` Sent when a company on your monitor is updated. **entity\_id** `string` *required* Company register ID (e.g. `DE-HRB-F1103-267645`). **entity\_type** `string` *required* Type of entity. Always `company` for this event. **event\_type** `string` *required* Event type identifier: `monitor.company.updated`. **timestamp** `string` *required* When the update occurred (ISO 8601 / RFC 3339). **updates** `string[]` *required* Which aspects of the company were updated, as [company preferences](#preferences). ```json Example theme={"dark"} { "entity_id": "DE-HRB-F1103-267645", "entity_type": "company", "event_type": "monitor.company.updated", "timestamp": "2026-03-30T12:00:00Z", "updates": ["basic"] } ``` ### `monitor.person.updated` Sent when a person on your monitor is updated. **entity\_id** `string` *required* Person UUID. **entity\_type** `string` *required* Type of entity. Always `person` for this event. **event\_type** `string` *required* Event type identifier: `monitor.person.updated`. **timestamp** `string` *required* When the update occurred (ISO 8601 / RFC 3339). **updates** `string[]` *required* Which aspects of the person were updated, as [person preferences](#preferences). ```json Example theme={"dark"} { "entity_id": "7dff6e4d-c5aa-4adc-989e-85953c36634f", "entity_type": "person", "event_type": "monitor.person.updated", "timestamp": "2026-03-30T12:00:00Z", "updates": ["management_positions"] } ``` ## Verifying Webhook Signatures Verifying the signature on each incoming webhook is important for two reasons: 1. **Authenticity** — confirms the request genuinely came from OpenRegister and not an attacker who found your endpoint URL. 2. **Replay protection** — Svix embeds a timestamp in every signature and the official libraries automatically reject messages with a timestamp more than five minutes old, preventing replay attacks. For a deeper explanation, see [Why Verify Webhooks](https://docs.svix.com/receiving/verifying-payloads/why) in the Svix docs. ### How to verify Install the Svix library for your language and call the verify method on the webhook instance. Find your signing secret in your [OpenRegister dashboard](https://openregister.de/keys) under the webhook endpoint you created. > [!WARNING] > > Always pass the **raw** (unparsed) request body to `verify`. If your framework parses the JSON and you pass a re-serialised string, the cryptographic signature will not match and verification will fail. ```typescript TypeScript (Node.js / Next.js) theme={"dark"} import { Webhook } from "svix"; const secret = process.env.WEBHOOK_SECRET!; // whsec_... export async function POST(req: Request) { const svixId = req.headers.get("svix-id") ?? ""; const svixTimestamp = req.headers.get("svix-timestamp") ?? ""; const svixSignature = req.headers.get("svix-signature") ?? ""; const body = await req.text(); // raw body — do not parse first const wh = new Webhook(secret); let event; try { event = wh.verify(body, { "svix-id": svixId, "svix-timestamp": svixTimestamp, "svix-signature": svixSignature, }); } catch { return new Response("Bad Request", { status: 400 }); } // Process event... return new Response("OK", { status: 200 }); } ``` ```python Python (FastAPI) theme={"dark"} from fastapi import Request, Response, status from svix.webhooks import Webhook, WebhookVerificationError secret = "whsec_..." # from your dashboard async def webhook_handler(request: Request, response: Response): headers = request.headers payload = await request.body() # raw bytes — do not parse first try: wh = Webhook(secret) event = wh.verify(payload, headers) except WebhookVerificationError: response.status_code = status.HTTP_400_BAD_REQUEST return # Process event... ``` ```go Go theme={"dark"} package main import ( "io" "net/http" svix "github.com/svix/svix-webhooks/go" ) const secret = "whsec_..." // from your dashboard func webhookHandler(w http.ResponseWriter, r *http.Request) { payload, err := io.ReadAll(r.Body) if err != nil { w.WriteHeader(http.StatusBadRequest) return } wh, err := svix.NewWebhook(secret) if err != nil { w.WriteHeader(http.StatusInternalServerError) return } err = wh.Verify(payload, r.Header) if err != nil { w.WriteHeader(http.StatusBadRequest) return } // Process event... w.WriteHeader(http.StatusNoContent) } ``` For examples in Python (Django/Flask), Ruby, PHP, Rust, and others, see the [full Svix verification guide](https://docs.svix.com/receiving/verifying-payloads/how). ## Testing with Svix Play [Svix Play](https://play.svix.com) is a free, no-signup webhook debugger. Use it during development to inspect incoming payloads before you have a publicly reachable endpoint. **To get started:** 1. Go to [play.svix.com](https://play.svix.com) — you'll receive a unique URL instantly. 2. Set that URL as your webhook endpoint in your [OpenRegister dashboard](https://openregister.de/keys). 3. Trigger an event (e.g. create a monitor and wait for an update, or replay a test event). Every delivery appears in the Svix Play UI with full headers, body, and response details. ### Relay to localhost with the Svix CLI For end-to-end local testing, install the [Svix CLI](https://github.com/svix/svix-cli) and run: ```bash theme={"dark"} svix listen http://localhost:8080/webhook ``` The CLI prints a public `play.svix.com` URL. Paste it into your dashboard as the endpoint and all deliveries are forwarded to your local server in real time. ### Simulating failures Append the `force_status_code` query parameter to your Svix Play URL to make it return a specific error code. This lets you verify that OpenRegister's retry logic works end-to-end: ```text theme={"dark"} https://api.play.svix.com/api/v1/in/{your-token}/?force_status_code=500 ``` For the full set of advanced options — echo mode, random failure rate, programmatic history API — see the [Svix Play docs](https://docs.svix.com/play). ## Pricing | Action | Cost | | - | - | | Create a weekly monitor | 25 credits | | Create a daily monitor | 50 credits | | Active weekly monitor | 25 credits per month | | Active daily monitor | 50 credits per month | | List monitors | 0 credits | | Delete a monitor | 0 credits | [Contact us](mailto:founders@openregister.de) if you have questions about pricing. ## Update Frequency How often OpenRegister checks an entity for changes depends on the entity type: **Companies** — checked for changes at least once per week by default. For faster detection, set `update_frequency: daily` when creating the monitor to have the company checked once per day. Daily monitors are billed at a premium (50 credits at creation and per month instead of 25). **Persons** — all entities are fully checked at least once per month. When a person incorporates a new company, that change is detected daily. Person monitors do not support the `update_frequency` field; including it returns a `400 Bad Request`. Need even faster updates? [Contact us](mailto:founders@openregister.de) to discuss custom frequencies. ## Preferences Preferences control which data categories trigger a notification. You must specify at least one preference when creating a monitor, and all preferences must match the `entity_type`. ### Company preferences (`entity_type: company`) | Preference | What triggers a notification | | - | - | | `basic` | Core firmographic data — name, registered address, legal form, or company status | | `representation` | Directors, officers, managing partners, or authorised signatories | | `financials` | Annual accounts or financial statements filed | | `documents` | New documents or publications filed with the register | | `ownership` | Direct owners (shareholders) of the company | | `holdings` | Companies in which this company holds a stake | | `insolvencies` | Insolvency proceedings of the company | ### Person preferences (`entity_type: person`) | Preference | What triggers a notification | | - | - | | `management_positions` | Board or management roles the person holds across any company | | `holdings` | Companies in which this person holds a stake | | `insolvencies` | Insolvency proceedings of the person | > [!WARNING] > > Passing a preference that does not apply to the given `entity_type` returns a `400 Bad Request` validation error. For example, you cannot use `representation` when monitoring a person. ## Use Cases **Compliance & KYC refresh** — Monitor the companies and persons in your portfolio. When a director change, ownership update, or new financial filing is detected you receive an immediate notification, letting you trigger a re-verification workflow without scheduling periodic re-checks. **Portfolio monitoring** — Subscribe to `basic` and `representation` changes across all portfolio companies to track legal form conversions, address moves, insolvency filings, or management changes as they appear in the register. **Ownership chain alerting** — Combine `ownership` and `holdings` preferences to detect restructuring events in complex ownership chains. Useful for banks, investors, and compliance teams that need to know when a beneficial ownership chain changes. **Due diligence pipelines** — Automatically re-fetch company data and refresh documents when you receive a `documents` or `financials` notification, ensuring your internal records stay in sync with the official register. ## Managing Monitors Use the three monitor endpoints together to manage your subscriptions: | Action | Endpoint | | - | - | | Create a monitor | [`POST /v1/monitor`](/endpoint/monitor-create) | | List all monitors | [`GET /v1/monitor`](/endpoint/monitor-list) | | Delete a monitor | [`DELETE /v1/monitor/{entity_id}`](/endpoint/monitor-delete) | ### The `disabled` flag Each monitor item in the list response includes a `disabled` boolean. A monitor is disabled when your account is downgraded to a plan that no longer includes monitoring access. Disabled monitors are preserved in your list so you do not lose your configuration, but they stop delivering notifications. Monitors are **not** automatically re-enabled on upgrade — this is intentional to prevent unexpected billing. To re-enable a disabled monitor, contact [founders@openregister.de](mailto:founders@openregister.de). # CLI Source: https://docs.openregister.de/integration/cli Official CLI for the OpenRegister API The OpenRegister CLI is the official command-line interface for the OpenRegister REST API. ## Installation Requires Go 1.22 or later. ```bash theme={"dark"} go install 'github.com/oregister/openregister-cli/cmd/openregister@latest' ``` The binary is placed in your Go bin directory after installation: * **Default location:** `$HOME/go/bin` (or `$GOPATH/bin` if `GOPATH` is set) * **Check your path:** Run `go env GOPATH` to see the base directory If the `openregister` command is not found after installation, add the Go bin directory to your `PATH`: > [tab] .zshrc > > ```bash theme={"dark"} > export PATH="$PATH:$(go env GOPATH)/bin" > ``` > [tab] .bashrc > > ```bash theme={"dark"} > export PATH="$PATH:$(go env GOPATH)/bin" > ``` ## Usage The CLI follows a resource-based command structure: ```bash theme={"dark"} openregister [resource] [flags...] ``` Example — fetch company details: ```bash theme={"dark"} openregister company get-details-v1 \ --api-key 'My API Key' \ --company-id DE-HRB-F1103-267645 ``` For details about any command, use the `--help` flag: ```bash theme={"dark"} openregister --help openregister company --help ``` ## Environment Variables | Variable | Description | Required | | - | - | - | | `OPENREGISTER_API_KEY` | Your API key, sent as a Bearer token in the `Authorization` header | Yes | ## Global Flags | Flag | Description | | - | - | | `--api-key` | API key (can also be set with `OPENREGISTER_API_KEY`) | | `--help` | Show command line usage | | `--debug` | Enable debug logging, including HTTP request/response details | | `--version`, `-v` | Show the CLI version | | `--base-url` | Use a custom API backend URL | | `--format` | Output format: `auto`, `explore`, `json`, `jsonl`, `pretty`, `raw`, `yaml` | | `--format-error` | Output format for errors: `auto`, `explore`, `json`, `jsonl`, `pretty`, `raw`, `yaml` | | `--transform` | Transform output using [GJSON](https://github.com/tidwall/gjson) syntax | | `--transform-error` | Transform error output using GJSON syntax | # MCP Source: https://docs.openregister.de/integration/mcp Connect OpenRegister to your AI assistant or agent The OpenRegister MCP server gives AI assistants and agents access to company search and data through the [Model Context Protocol](https://modelcontextprotocol.io/introduction). It runs remotely, so there is nothing to install. ``` https://mcp.openregister.de/mcp ``` When you connect, you enter your API key from [OpenRegister Keys](https://openregister.de/keys). ## Connect your assistant > [tab] Claude > > 1. Open [OpenRegister in the Claude directory](https://claude.ai/directory/openregister) > 2. Click **Connect** and enter your API key > > The connector is then available in Claude on the web, Claude Desktop and the mobile apps. > [tab] ChatGPT > > 1. Open [OpenRegister in ChatGPT](https://chatgpt.com/plugins/plugin_asdk_app_6a32829b2bec81919ce34b47e19ab9b7) > 2. Click **Add to ChatGPT** and enter your API key > [tab] Claude Code > > If you connected OpenRegister in Claude, it already shows up in `/mcp`. > > Otherwise, add it and run `/mcp` to enter your API key: > > ```bash theme={"dark"} > claude mcp add --transport http openregister https://mcp.openregister.de/mcp > ``` > [tab] Cursor > > Add this to `~/.cursor/mcp.json` and restart Cursor: > > ```json theme={"dark"} > { > "mcpServers": { > "openregister": { > "url": "https://mcp.openregister.de/mcp" > } > } > } > ``` > > To skip the sign-in, add `"headers": { "Authorization": "Bearer YOUR_API_KEY" }` next to `url`. > [tab] Other clients > > Clients that support remote MCP servers take the URL directly. For clients that only run local commands, bridge with [`mcp-remote`](https://www.npmjs.com/package/mcp-remote) (requires [Node.js 18+](https://nodejs.org)): > > ```json theme={"dark"} > { > "mcpServers": { > "openregister": { > "command": "npx", > "args": ["-y", "mcp-remote@latest", "https://mcp.openregister.de/mcp"] > } > } > } > ``` > > If the connection fails, clear the auth cache with `rm -rf ~/.mcp-auth` and try again. ## Build with it In your own agents, send your API key in the `Authorization` header. The server then skips the OAuth sign-in. > [tab] cURL > > ```bash theme={"dark"} > curl https://mcp.openregister.de/mcp \ > -H "Authorization: Bearer YOUR_API_KEY" \ > -H "Content-Type: application/json" \ > -H "Accept: application/json, text/event-stream" \ > -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"curl","version":"1.0"}}}' > ``` > [tab] OpenAI Agents SDK > > ```python theme={"dark"} > from agents import Agent, Runner > from agents.mcp import MCPServerStreamableHttp > > async def main(): > async with MCPServerStreamableHttp( > url="https://mcp.openregister.de/mcp", > headers={"Authorization": "Bearer YOUR_API_KEY"}, > ) as mcp_server: > agent = Agent( > name="company-researcher", > instructions="Use OpenRegister tools to look up German company data.", > mcp_servers=[mcp_server], > ) > result = await Runner.run(agent, "Find information about Trade Republic Bank GmbH") > print(result.final_output) > ``` > [tab] Vercel AI SDK > > ```typescript theme={"dark"} > import { createOpenAI } from "@ai-sdk/openai"; > import { experimental_createMCPClient, generateText } from "ai"; > > const mcpClient = await experimental_createMCPClient({ > transport: { > type: "sse", > url: "https://mcp.openregister.de/sse", > headers: { Authorization: "Bearer YOUR_API_KEY" }, > }, > }); > > const tools = await mcpClient.tools(); > > const { text } = await generateText({ > model: createOpenAI({ apiKey: process.env.OPENAI_API_KEY })("gpt-4o"), > tools, > prompt: "Find information about Trade Republic Bank GmbH", > }); > > await mcpClient.close(); > ``` > [!NOTE] > > `https://mcp.openregister.de/sse` serves the legacy SSE transport for clients that don't support Streamable HTTP yet. Prefer `/mcp` where you can. # n8n Source: https://docs.openregister.de/integration/n8n Use the OpenRegister API in your n8n workflows with the official verified node ## Overview n8n is a workflow automation tool to connect services and build automations without writing code. The official OpenRegister node for n8n lets you search for companies, fetch company details, owners, holdings, financials, and documents directly inside your flows. OpenRegister is available as an **official verified node** on n8n, meaning it's pre-installed and ready to use on n8n Cloud without any manual installation required. * n8n Integration: [n8n.io/integrations/openregister](https://n8n.io/integrations/openregister/) * Repository: [oregister/n8n-nodes-openregister](https://github.com/oregister/n8n-nodes-openregister) * Example workflow: [openregister-example-workflow.json](https://github.com/oregister/n8n-nodes-openregister/blob/master/examples/openregister-example-workflow.json) ## Prerequisites * An OpenRegister API key — get one in the [OpenRegister Keys](https://openregister.de/keys) * For n8n Cloud: No additional prerequisites (node is pre-installed) * For self-hosted n8n: Admin approval for verified nodes (one-time setup) ## Installation ### n8n Cloud (Hosted) **No installation required!** The OpenRegister node is pre-installed on all n8n Cloud instances. Simply search for "OpenRegister" in the node palette and start using it. ### Self-Hosted n8n The verified node needs a one-time setup by an instance owner: 1. In n8n, go to Settings → Community Nodes. 2. Enable verified nodes if not already enabled. 3. The OpenRegister node will be available to all users on the instance. Alternatively, you can install the community package manually: 1. Go to Settings → Community Nodes → Install. 2. Enter the package name: `@oregister/n8n-nodes-openregister` and confirm. 3. Restart n8n if prompted. ## Authentication 1. In n8n, open Credentials → New → search for “OpenRegister”. 2. Paste your API key into the API Key field. 3. Save the credentials and select them in your OpenRegister nodes. ## Available nodes The package provides nodes that map to common OpenRegister API endpoints. Typical actions include: * Company search (simple) * Company information * Company owners * Company holdings * Company financials Exact inputs and outputs are documented in each node within n8n and align with the API responses described in this documentation. ## Example: Enrich companies with details and financials This example shows a simple flow to search a company and fetch its details and financials. 1. Add a Trigger (e.g., Manual Trigger). 2. Add “OpenRegister: Search Companies” with a query (e.g., “Miles Mobility”). 3. Add “OpenRegister: Get Company” and set Company ID to the first result from step 2. 4. (Optional) Add “OpenRegister: Get Financials” using the Company ID from step 3. 5. Continue your flow (e.g., store data, send notification, or enrich a CRM). To try a ready‑made flow, import the example workflow from the repository’s examples folder linked above. ## Troubleshooting * 401 Unauthorized: Check that your credentials are set and selected in the node. * 402 Payment Required: Your account lacks credits for this endpoint. Top up credits. * 429 Too Many Requests: You have hit a rate limit. Add a Wait node or lower concurrency. * 5xx Server Error: Retry with a Wait/Retry pattern. If persistent, contact support. ## Links * Keys: [openregister.de/keys](https://openregister.de/keys) * API docs home: [docs.openregister.de](https://docs.openregister.de) * n8n nodes repository: [oregister/n8n-nodes-openregister](https://github.com/oregister/n8n-nodes-openregister) # SDKs Source: https://docs.openregister.de/integration/sdks Official SDKs for the OpenRegister API We provide official SDKs for TypeScript, Go, and Python to make it easy to integrate with the OpenRegister API. These SDKs are published and maintained by our team. ### Python * [openregister-sdk](https://pypi.org/project/openregister-sdk/) - Official Python SDK > [tab] uv > > ```bash theme={"dark"} > uv add openregister-sdk > ``` > [tab] pip > > ```bash theme={"dark"} > pip install openregister-sdk > ``` ```python theme={"dark"} import os from openregister import Openregister client = Openregister( api_key=os.environ.get("OPENREGISTER_API_KEY"), # This is the default and can be omitted ) response = client.search.find_companies() print(response.results) ``` ### TypeScript/JavaScript * [openregister](https://www.npmjs.com/package/openregister) - Official TypeScript/JavaScript SDK > [tab] npm > > ```bash theme={"dark"} > npm install openregister > ``` > [tab] pnpm > > ```bash theme={"dark"} > pnpm add openregister > ``` > [tab] bun > > ```bash theme={"dark"} > bun add openregister > ``` ```typescript theme={"dark"} import Openregister from 'openregister'; const client = new Openregister({ apiKey: process.env['OPENREGISTER_API_KEY'], // This is the default and can be omitted }); const response = await client.search.findCompanies(); console.log(response.results); ``` ### Go * [github.com/oregister/openregister-go](https://github.com/oregister/openregister-go) - Official Go SDK ```bash theme={"dark"} go get github.com/oregister/openregister-go ``` ```go theme={"dark"} package main import ( "context" "fmt" "github.com/oregister/openregister-go" "github.com/oregister/openregister-go/option" ) func main() { client := openregister.NewClient( option.WithAPIKey("My API Key"), // defaults to os.LookupEnv("OPENREGISTER_API_KEY") ) response, err := client.Search.FindCompanies(context.TODO(), openregister.SearchFindCompaniesParams{}) if err != nil { panic(err.Error()) } fmt.Printf("%+v\n", response.Results) } ``` # Zapier Source: https://docs.openregister.de/integration/zapier Use the OpenRegister API in your Zapier workflows with official actions ## Overview Zapier lets you connect apps and automate workflows without code. The OpenRegister Zapier integration provides actions to search companies and fetch company data (details, owners, holdings, financials, and documents) so you can enrich, route, and process data inside your Zaps. The OpenRegister integration is **publicly available** to all Zapier users and can be found directly in the Zapier app directory. * Zapier Integration: [zapier.com/apps/openregister/integrations](https://zapier.com/apps/openregister/integrations) ## Prerequisites * An OpenRegister API key — get one in the [OpenRegister Keys](https://openregister.de/keys) * A Zapier account (free or paid) ## Authentication OpenRegister uses API key authentication. Create a connection when adding your first OpenRegister action: 1. In a Zap, add an "OpenRegister" action. 2. When prompted to "Choose account", click "Connect a new account". 3. Paste your API key into the API Key field and confirm. 4. The connection will be reused across OpenRegister steps. If you need an API key, see the [Authentication guide](/authentication). ## Available actions Actions map to common OpenRegister API endpoints. Typical actions include: * Company search (simple) * Get company information * Get company owners * Get company holdings * Get company financials Each action's inputs and outputs are documented in Zapier and align with the responses described in this API documentation. ## Example: Search and enrich a company This example searches a company name, then fetches details and financials. 1. Trigger: choose any trigger (e.g., Schedule → Every day). 2. Action: OpenRegister → Search Companies. Set "Query" (e.g., "Miles Mobility"). 3. Action: OpenRegister → Get Company. Set "Company ID" from step 2's first result. 4. (Optional) Action: OpenRegister → Get Financials. Set "Company ID" from step 3. 5. Continue your Zap (e.g., filter, store to Airtable/Sheets/DB, send a notification, enrich a CRM). ## Troubleshooting * 401 Unauthorized: Reconnect the OpenRegister account and verify the API key. * 402 Payment Required: Your account lacks credits for this endpoint. Top up credits. * 429 Too Many Requests: You hit a rate limit. Add a delay or reduce concurrency. * 5xx Server Error: Retry with Zapier's built‑in retry/delay. If persistent, contact support. ## Links * Keys: [openregister.de/keys](https://openregister.de/keys) * Zapier Integration: [zapier.com/apps/openregister/integrations](https://zapier.com/apps/openregister/integrations) * API docs home: [docs.openregister.de](https://docs.openregister.de) # Introduction Source: https://docs.openregister.de/introduction Getting started with the OpenRegister API ## Welcome to OpenRegister Get instant access to data on 4+ million German companies from official sources. Search for companies, check ownership structures, view financials, and retrieve official documents - all through a simple API. ## Getting Started Ready to start? Check out our [Quickstart Guide](/quickstart) to get up and running in minutes. 1. [Sign up](https://openregister.de) and grab your API key (no credit card required) 2. Start with 500 free credits per month 3. Follow the [Quickstart](/quickstart) to integrate ## What You Can Do **Company Information** - Names, registration details, management teams, addresses, and contact info **Find Companies** - Search by name, website, or location. Filter by industry, size, and legal form **Ownership** - See who owns what, track beneficial owners, explore corporate structures **Financials** - Balance sheets, revenue, and key metrics from published reports **Documents** - Official register documents directly from the source ## Popular Use Cases Companies use OpenRegister for **compliance and KYC**, **sales intelligence**, **due diligence**, **market research**, and **legal services**. If you work with German companies, we probably have the data you need. ## Need Help? Questions? Want to discuss your use case? Just reach out at [founders@openregister.de](mailto:founders@openregister.de). We're here to help you succeed. ## Data Sources Access many data sources through our API: > [card] [Handelsregister](sources/handelsregister) > > Official register data for 4+ million companies - management, ownership, registration details, and documents > [card] [Bundesanzeiger](sources/bundesanzeiger) > > Financial statements and reports - balance sheets, revenue, and key metrics published by companies > [card] [Web Data](sources/web-data) > > Real-world contact details - emails, phone numbers, and social media profiles from company websites > [card] [Transparenzregister](sources/transparenzregister) > > Beneficial ownership records - structured UBO data plus the official source documents > [card] [Insolvenzregister](sources/insolvenzregister) > > Insolvency proceedings - current status, full event timeline, and administrators, linked to companies # Pricing Source: https://docs.openregister.de/pricing Pricing for the OpenRegister API ## Credit-Based Pricing The OpenRegister API uses a credit-based pricing model. Each API call consumes a certain number of credits depending on the endpoint and parameters used. This provides transparent, predictable costs that scale with your usage. ## Credit Costs by Endpoint | Endpoint Type | Base Cost | With Realtime | | - | - | - | | [Autocomplete Search](/endpoint/autocomplete-company) | 1 credit | N/A | | [Advanced Filter Search](/endpoint/filter-company) (Company/Person) | 10 credits | N/A | | [Company Details](/endpoint/company) | 10 credits | 20 credits | | [Company Owners](/endpoint/company-owners) | 10 credits | 20 credits | | [Company Historical Owners](/endpoint/company-historical-owners) | 25 credits | N/A | | [Company Holdings](/endpoint/company-holdings) | 10 credits | N/A | | [Company Financials](/endpoint/company-financials) | 10 credits | N/A | | [Company UBO](/endpoint/company-ubo) | 25 credits | N/A | | [Person Details](/endpoint/person) | 10 credits | N/A | | [Person Holdings](/endpoint/person-holdings) | 10 credits | N/A | | [Documents](/endpoint/document-realtime) | 10 credits | N/A | | [Start Job](/endpoint/job-create) (company, owners) | 20 credits | N/A | | [Start Job](/endpoint/job-create) (document) | 10 credits | N/A | | [Get Job](/endpoint/job-get) | 0 credits | N/A | | [Create Monitor](/endpoint/monitor-create) (weekly) | 25 credits | N/A | | [Create Monitor](/endpoint/monitor-create) (daily) | 50 credits | N/A | | [List Monitors](/endpoint/monitor-list) | 0 credits | N/A | | [Delete Monitor](/endpoint/monitor-delete) | 0 credits | N/A | | Active weekly monitor (monthly) | 25 credits | N/A | | Active daily monitor (monthly) | 50 credits | N/A | | [Store Transparenzregister credentials](/endpoint/transparenzregister-credentials) | 0 credits | N/A | | [Order Transparenzregister extract](/endpoint/transparenzregister-extract-create) | 25 credits | N/A | | [Get Transparenzregister extract](/endpoint/transparenzregister-extract-get) | 0 credits | N/A | ### Monitoring [Monitoring](/guide/monitoring) is available on Pro Plan and above. Each active monitor costs 25 credits per month with the default weekly update frequency, or 50 credits per month for company monitors created with `update_frequency: daily`. See the [Create Monitor](/endpoint/monitor-create) endpoint for details. ### Realtime Parameter For select endpoints (Company Details and Company Owners), you can add `realtime=true` to fetch data directly from the Handelsregister in real-time. This ensures you get the most current information available and costs an additional 10 credits. ### Jobs [Jobs](/endpoint/job-create) run a realtime request in the background and are available on paid API plans only. A job is charged when it completes, at the price of the matching realtime request. Failed jobs and polling are free. ### Transparenzregister [Transparenzregister](/api/transparenzregister-api) access is available on paid API plans only. Ordering an extract costs 25 credits; polling the result and downloading documents are free. Sandbox extracts (`X-Credential-Name: sandbox`) cost 0 credits and do not count toward any limits. Default limits per account: | Limit | Default | | - | - | | Stored credential sets | 1 | | Production extracts per rolling 30 days | 30 | Sandbox traffic does not count toward the extract quota. [Email us](mailto:founders@openregister.de) if you need higher limits. ## Pricing Plans ### Free Plan * **500 credits per month** included * Credits are consumed per request based on the credit costs above * Perfect for testing and small-scale integrations * No credit card required ### Pro Plan * **5,000 credits per month** included * Additional credits at **€0.01 per credit** * [Sign up](https://openregister.de/pricing) ### Business Plan * **30,000 credits per month** included * Additional credits at **€0.01 per credit** * [Sign up](https://openregister.de/api) ### Volume Discounts For high-volume usage, we offer custom pricing with volume discounts. If you need more than 50,000 credits per month, contact us at [founders@openregister.de](mailto:founders@openregister.de) to discuss pricing tailored to your needs. ## Integration Support We want to help you succeed with your integration. If you're building a production integration and need additional credits for testing and development, we're happy to support you. **Reach out to us at [founders@openregister.de](mailto:founders@openregister.de)** and let us know: * What you're building * Your expected usage patterns We'll work with you to ensure you have the resources needed to build and test your integration properly. ## Tracking Your Usage Monitor your credit consumption and view detailed usage statistics in real-time through your [API Dashboard](https://openregister.de/keys). # Quickstart Source: https://docs.openregister.de/quickstart Get started with the OpenRegister API in minutes OpenRegister provides multiple integration options to fit your technical setup and use case. Whether you're building a custom application, automating workflows, or adding AI capabilities, we have you covered. ## Set Up with an AI Agent The fastest way to integrate: paste this prompt into Claude Code, Cursor, or any coding agent, and it will handle the setup for you — API key configuration, SDK installation, and a verified first request. ```text theme={"dark"} Add OpenRegister to my app: openregister.de/skill.md ``` ## Choose Your Integration > [card] [SDKs](/integration/sdks) > > Official libraries for Python, TypeScript/JavaScript, and Go > [card] [n8n](/integration/n8n) > > Verified node for workflow automation without code > [card] [Zapier](/integration/zapier) > > Pre-built actions to connect with 6,000+ apps > [card] [MCP](/integration/mcp) > > Enable AI assistants to query German company data ## Choosing the Right Integration ### For Developers **Use our SDKs** if you're building a custom application and want: * Full type safety and autocompletion * Native language integration * Complete control over API calls Available in **Python**, **TypeScript/JavaScript**, and **Go**. [View SDK Documentation →](/integration/sdks) ### For No-Code Automation **Use n8n or Zapier** if you want to: * Automate workflows without writing code * Connect OpenRegister with other tools (CRMs, databases, spreadsheets) * Build data enrichment pipelines Both platforms offer visual workflow builders with pre-built OpenRegister actions. [n8n Documentation →](/integration/n8n) | [Zapier Documentation →](/integration/zapier) ### For AI Assistants **Use the MCP Server** if you want to: * Enable AI assistants like Claude and ChatGPT to query company data * Build AI-powered tools with access to German company information * Integrate with Model Context Protocol-compatible clients Connect with one click from the [Claude directory](https://claude.ai/directory/openregister) or as a [ChatGPT plugin](https://chatgpt.com/plugins/plugin_asdk_app_6a32829b2bec81919ce34b47e19ab9b7). [MCP Documentation →](/integration/mcp) ### Direct REST API **Use the REST API directly** if you: * Need maximum flexibility * Work in a language without an official SDK * Prefer making raw HTTP requests All SDKs and integrations are built on top of our REST API. [API Reference →](/endpoint/autocomplete-company) ## Authentication All integration methods require an API key. Get yours in under a minute: 1. Create an account at [openregister.de](https://openregister.de) 2. Go to [API Keys](https://openregister.de/keys) 3. Generate your key The free plan includes **500 credits per month** - perfect for testing. [Authentication Guide →](/authentication) ## Need Help? * Check our [API Reference](/endpoint/company) for endpoint details * Review [pricing and credit costs](/pricing) * Contact us at [founders@openregister.de](mailto:founders@openregister.de) # Roles Source: https://docs.openregister.de/roles How representative roles are structured, and the full list of role codes and titles Wherever the API returns a person or company acting for a company, it describes their role twice: once as a coarse bucket you can match on exhaustively, and once as the precise office the register records. This applies to `representation` in [company information](/endpoint/company) and to `management_positions` in [person information](/endpoint/person). > [!NOTE] > > On [person information](/endpoint/person) the plain `role` field is > deprecated. It carries the raw stored value, which is a German string for > Prokura (`"Einzelprokura"`, `"Gesamtprokura"`, `"Prokura"`) and a code > otherwise. Use `role_detail.code` instead. ## The two fields ```json theme={"dark"} "role": "DIRECTOR", "role_detail": { "code": "EXECUTIVE", "label_de": "Vorstand", "label_de_short": "Vst.", "label_en": "Executive Board Member", "label_en_short": "Exec. Board" } ``` | Field | Description | | - | - | | `role` | The coarse bucket: `DIRECTOR`, `PROKURA`, `SHAREHOLDER`, `OWNER`, `PARTNER`, `PERSONAL_LIABLE_DIRECTOR`, `LIQUIDATOR` or `OTHER`. | | `role_detail.code` | The register-level office, e.g. `EXECUTIVE`. See the [full list](#role-reference). | | `role_detail.label_de` | German title, e.g. `"Vorstand"` — the term the register uses. | | `role_detail.label_de_short` | Abbreviated German title, e.g. `"Vst."`. | | `role_detail.label_en` | English title, e.g. `"Executive Board Member"`. A translation for display, not a legal term. | | `role_detail.label_en_short` | Abbreviated English title, e.g. `"Exec. Board"`. | `role_detail` is always present. > [!NOTE] > > The `role` set is stable: a new register role is folded into an existing > bucket rather than added, so you can match on it exhaustively. `role_detail.code` > grows as new roles appear in the register — treat an unrecognised code as > `OTHER`. ## Why both A Vorstand and a Geschäftsführer:in are both authorised to act for the company, so both are `role: "DIRECTOR"` — that is the field to use when you want *"can this person represent the company?"* in one branch. They are different offices, though, and `role_detail` is where that shows. The same holds for Einzelprokura and Gesamtprokura: both are `role: "PROKURA"`, while `role_detail.code` distinguishes the sole signing authority from the joint one. Deriving the German title from the company's legal form does not work as a substitute. An AG can appoint a Geschäftsführer:in for a branch, and an association carries board offices that no legal form implies. `role_detail` reports what the register actually recorded. ## Role reference > [tab] Management & boards > > All of these are `role: "DIRECTOR"`. > > | `role_detail.code` | `label_de` | `label_en` | > | - | - | - | > | `DIRECTOR` | Geschäftsführer:in | Managing Director | > | `EMERGENCY_DIRECTOR` | Notgeschäftsführer:in | Emergency Managing Director | > | `EXECUTIVE` | Vorstand | Executive Board Member | > | `CHAIRMAN` | Vorsitzende:r | Chair | > | `DEPUTY_CHAIRMAN` | Stellvertretende:r Vorsitzende:r | Deputy Chair | > | `BOARD` | Verwaltungsrat | Administrative Board Member | > | `PRESIDENT_BOARD` | Präsident:in des Verwaltungsrats | President of the Administrative Board | > | `VICE_PRESIDENT_BOARD` | Vizepräsident:in des Verwaltungsrats | Vice President of the Administrative Board | > | `PRESIDENT` | Präsident:in | President | > | `MEMBER` | Mitglied | Board Member | > | `NON_EXECUTIVE_DIRECTOR` | Beisitzer:in | Non-Executive Board Member | > | `BOARD_SECRETARY` | Schriftführer:in | Board Secretary | > | `BOARD_TREASURER` | Kassenwart:in | Board Treasurer | > | `BOARD_SPORTS` | Sportwart:in | Sports Officer | > | `BOARD_OTHER` | Vertreter:in | Other Board Officer | > | `REPRESENTATIVE` | Ständige:r Vertreter:in | Permanent Branch Representative | > | `SECONDARY_REPRESENTATIVE` | Stellvertreter:in | Deputy Representative | > | `COURT_ORDERED_REPRESENTATIVE` | Vertreter:in | Court-Appointed Representative | > [tab] Prokura > > All of these are `role: "PROKURA"`. > > | `role_detail.code` | `label_de` | `label_en` | > | - | - | - | > | `PROKURA` | Prokura | Authorised Signatory (Prokura) | > | `PROKURA_SINGLE` | Einzelprokura | Sole Authorised Signatory (Prokura) | > | `PROKURA_JOINT` | Gesamtprokura | Joint Authorised Signatory (Prokura) | > [tab] Wind-down > > All of these are `role: "LIQUIDATOR"`. > > | `role_detail.code` | `label_de` | `label_en` | > | - | - | - | > | `LIQUIDATOR` | Liquidator:in | Liquidator | > | `INSOLVENCY_DIRECTOR` | Insolvenzvertreter:in | Insolvency Administrator | > | `PRELIMINARY_INSOLVENCY_DIRECTOR` | Vorl. Insolvenzvertreter:in | Preliminary Insolvency Administrator | > [tab] Ownership & other > > Here the bucket and the code agree. > > | `role` | `role_detail.code` | `label_de` | `label_en` | > | - | - | - | - | > | `OWNER` | `OWNER` | Inhaber:in | Owner | > | `SHAREHOLDER` | `SHAREHOLDER` | Gesellschafter:in | Shareholder | > | `PARTNER` | `PARTNER` | Partner:in | Partner | > | `PERSONAL_LIABLE_DIRECTOR` | `PERSONAL_LIABLE_DIRECTOR` | Persönlich haftende:r Gesellschafter:in | Personally Liable Partner | > | `OTHER` | `OTHER` | Sonstige | Other | > [!NOTE] > > Kommanditisten are an ownership stake rather than a right to represent the > company, so they are not part of `representation`. Retrieve them from > [company owners](/endpoint/company-owners) as > `relation_type: "limited_partner"`. ## Choosing a field > [card] Use role > > Filtering, branching and aggregation — anything where you need every case > handled and the set to stay put. > [card] Use role\_detail.code > > Telling offices apart: a Vorstand from a Geschäftsführer:in, a sole Prokura > from a joint one. > [card] Use label\_de > > Showing the role to users. The German term is the one the register uses and > the one German users expect. > [card] Use the short labels > > Tables, badges and other dense layouts where the full title does not fit. # Bundesanzeiger Source: https://docs.openregister.de/sources/bundesanzeiger The OpenRegister API provides comprehensive access to financial data from the German Bundesanzeiger. The Bundesanzeiger (Federal Gazette) is the official publication platform where German companies publish their annual financial statements when legally required. Our API provides structured access to this financial data, making it easy to analyze company financials and track performance over time. ## What You Get * **Complete balance sheets** - Detailed asset and liability breakdowns * **Income statements** - Revenue, expenses, and profitability data * **Key financial indicators** - Balance sheet total, revenue, net income, equity, cash, employees, and more * **Multi-year data** - Track trends and compare financial performance over time * **Structured format** - JSON data instead of PDF documents for easy automated analysis Coverage includes **hundreds of thousands of German companies** that publish their financials. Not all companies are required to publish financials - publication requirements depend on company size and legal form. Generally, medium to large companies must publish detailed statements. ## Use Cases **Credit Assessment** - Banks, suppliers, and financial institutions analyze financial health, liquidity ratios, and debt levels to make credit decisions and set credit limits. **Investment Research** - Investors and analysts identify financially strong companies, analyze profitability trends, and compare companies within industries. **Market Analysis** - Consultants and researchers benchmark companies against peers, identify industry trends, and segment markets by financial characteristics like revenue or employee ranges. ## API Endpoints > [card] [Financial indicators](/endpoint/company) > > Access key financial indicators > [card] [Detailed financial reports](/endpoint/company-financials) > > Access detailed financial reports including balance sheet & income statement ## Update Frequency * **Source**: bundesanzeiger.de (official Federal Gazette) * **Updates**: Daily * Financial statements are added as companies publish them in the Bundesanzeiger # Handelsregister Source: https://docs.openregister.de/sources/handelsregister The OpenRegister API provides comprehensive access to data from the German Handelsregister. The German Handelsregister (Commercial Register) is the official public register maintained by local courts for all commercial entities in Germany. Our API provides programmatic access to this register data, allowing you to search, retrieve, and monitor company information at scale. ## What You Get * **Company registration details** - Register number, court, legal form, and registration dates * **Management information** - All legal representatives (Geschäftsführer, Vorstände, etc.) * **Ownership structures** - Complete shareholder information for applicable legal forms * **Historical changes** - Track how companies have evolved over time * **Official documents** - Company extracts, shareholder lists, and articles of association * **Real-time data** - Request the most current information directly from the register Access to **over 4 million registered German companies** across all 16 federal states and all register courts. ## Use Cases **Legal & Compliance** - Law firms, notaries, and compliance officers verify company information, retrieve official documents, and perform due diligence checks for client onboarding and transactions. **Business Intelligence** - Sales teams and business developers identify prospects, verify business partners, and research market segments using advanced company filters and ownership data. **Financial Services** - Banks and financial institutions automate KYC processes, assess creditworthiness using register data, and monitor corporate structures for risk management. ## API Endpoints > [card] [Company Search](/endpoint/filter-company) > > Search and filter companies by name, location, legal form, registration date, and more > [card] [Company Details](/endpoint/company) > > Retrieve comprehensive company information including management, registration details, and history > [card] [Company Owners](/endpoint/company-owners) > > Access complete ownership structures with shareholder names, shares, and participation percentages > [card] [Company Holdings](/endpoint/company-holdings) > > Discover all investments and subsidiaries held by a company > [card] [Real-time Documents](/endpoint/document-realtime) > > Request and download official documents directly from the register on demand > [card] [Ultimate Beneficial Owners](/endpoint/company-ubo) > > Identify the natural persons who ultimately own or control the company ## Update Frequency * **Source**: handelsregister.de (official German Commercial Register) * **Regular updates**: At least once per month * **Newly founded companies**: Added within **24 hours** of registration ## Supported Legal Forms & Register Types > [accordion] Supported Legal Forms > > Our API supports all German legal entities: > > * **GmbH** ("gmbh") - Limited liability company > * **gGmbH** ("ggmbh") - Non-profit GmbH > * **KG** ("kg") - Limited partnership > * **KGaA** ("kgaa") - Partnership limited by shares > * **GbR** ("gbr") - Civil law partnership > * **eG** ("eg") - Registered cooperative > * **OHG** ("ohg") - General partnership > * **e.K.** ("ek") - Registered merchant > * **SE** ("se") - European company > * **SCE** ("sce") - European cooperative > * **AG** ("ag") - Stock corporation > * **LLP** ("llp") - Limited liability partnership > * **EWIV** ("ewiv") - European economic interest grouping > * **Municipal** ("municipal") > * **Foreign** ("foreign") > * **Stiftung** ("foundation") - Foundation > * **Unknown** ("unknown") > [accordion] Supported Register Types > > * **HRA** (Handelsregister Abteilung A) - Partnerships > * **HRB** (Handelsregister Abteilung B) - Corporations > * **GsR** (Gesellschaftsregister) - Registered civil law partnerships > * **GnR** (Genossenschaftsregister) - Cooperatives > * **PR** (Partnerschaftsregister) - Professional partnerships > * **VR** (Vereinsregister) - Associations # Insolvenzregister Source: https://docs.openregister.de/sources/insolvenzregister The OpenRegister API provides structured access to all German insolvency proceedings, sourced from the official insolvency announcements. German insolvency courts (Insolvenzgerichte) are legally required to publish every decision in insolvency proceedings on the official portal neu.insolvenzbekanntmachungen.de. Our API turns these raw announcements (Insolvenzbekanntmachungen) into structured, trackable insolvency proceedings: search across all cases, retrieve complete event histories, and resolve proceedings directly to companies in OpenRegister. ## What You Get * **Complete proceedings** - One record per court case (court and case number, Aktenzeichen), covering all published insolvency proceedings of German companies * **Current status** - Where the case stands (`preliminary`, `opened`, `rejected_no_assets`, `lifted`, and more), derived from the full event history * **Structured event timeline** - Every published announcement as a typed event, from the first security measures through opening, distributions, and closure * **Company links** - Proceedings resolved to OpenRegister companies (`company_id`) for direct lookup of the debtor company * **Administration data** - Administrator name and address, plus the administration kind: external administration, self administration (Eigenverwaltung), or protective shield (Schutzschirmverfahren) * **Key dates and figures** - Opening and closing dates, claims filing deadlines, distribution amounts, and insolvency grounds ## Use Cases **Risk Monitoring** - Banks, insurers, and credit teams screen customers and suppliers for open insolvency proceedings before extending credit, and monitor their portfolio for new filings via webhooks. **Restructuring & Distressed Assets** - Investors and advisors identify newly opened proceedings by region, court, or date to source restructuring and acquisition opportunities early. **Claims Management & Legal** - Law firms and creditors track claims filing deadlines, follow individual cases event by event, and reconstruct the full insolvency history of a counterparty. ## API Endpoints > [card] [Insolvency Search](/endpoint/search-insolvency) > > Search all proceedings with free text and filters for status, court, dates, debtor attributes, and more > [card] [Insolvency Proceeding](/endpoint/insolvency) > > Retrieve a single proceeding with its complete event history > [card] [Company Details](/endpoint/company) > > Company profiles include all insolvency proceedings linked to the company > [card] [Monitoring](/guide/monitoring) > > Receive webhook notifications when new insolvency events are published for companies you watch See the [filtering guide](/filtering#insolvency-search-fields) for the full list of insolvency search filters. ## Update Frequency * **Source**: neu.insolvenzbekanntmachungen.de (official publication portal of the German insolvency courts) * **New announcements**: Imported daily across all publication categories ## Proceeding Lifecycle & Classifications > [accordion] Proceeding Lifecycle > > Every case starts with an insolvency application (Antrag), filed by the debtor itself or by a creditor. From there: > > * **Preliminary phase** - Before deciding on the application, the court may order security measures such as appointing a preliminary administrator (vorläufiger Insolvenzverwalter) > * **Opening** - The proceeding is opened if the estate at least covers the costs of the proceeding > * **Rejection** - Otherwise the application is rejected for insufficiency of assets (Abweisung mangels Masse, § 26 InsO); a large share of corporate applications end here > * **Closure** - An opened proceeding normally ends with its lifting (Aufhebung) after the final distribution, or earlier by discontinuation (Einstellung) > * **Insolvency plan** - Alternatively a confirmed insolvency plan (Insolvenzplan) lets the company survive restructured, often under court-ordered plan supervision > [accordion] Proceeding Classifications > > * **Administration kind** - `external_administration` (a court-appointed Insolvenzverwalter takes over the estate), `self_administration` (Eigenverwaltung, § 270 InsO), or `protective_shield` (Schutzschirmverfahren, § 270d InsO) > * **Insolvency grounds** - `illiquidity` (Zahlungsunfähigkeit, § 17 InsO), `imminent_illiquidity` (drohende Zahlungsunfähigkeit, § 18 InsO), or `over_indebtedness` (Überschuldung, § 19 InsO) # Transparenzregister Source: https://docs.openregister.de/sources/transparenzregister The OpenRegister API provides structured access to beneficial ownership records from the German Transparenzregister. The German Transparenzregister is the official register for beneficial ownership information in Germany. OpenRegister gives you simple API access to request extracts and receive structured UBO data plus official source documents. OpenRegister is officially certified by **Bundesanzeiger Verlag GmbH**, the publisher of the Transparenzregister API. Access to live data still requires **berechtigtes Interesse** (legitimate interest) under the *Geldwäschegesetz* (GwG). ## What You Get * **Structured UBO records** — Get full name, date of birth, city, country, and percentage hints where available in the register text. * **Official source documents** — Download original Transparenzregister artifacts (PDF, JSON, optional SVG) through `documents[]`. * **Sandbox mode** — Test the full integration flow without live credentials and without credit usage. * **Credential isolation** — Store multiple credential sets under different `name` values (default `default`) for separate clients or environments. ## Getting Started Live Transparenzregister extracts run through your own account at [transparenzregister.de](https://www.transparenzregister.de). Three prerequisites must be met before the first extract request succeeds: 1. **Legitimate interest** — You need a *berechtigtes Interesse* in inspecting the register under the *Geldwäschegesetz* (GwG). The Transparenzregister verifies this for your account. 2. **Einsichtnahmeschnittstelle enabled** — The inspection API must be activated on your Transparenzregister account. Log in to transparenzregister.de and go to **„Meine Aktionen“ → „Einsichtnahmeschnittstelle freischalten“**. The activation is complete once the status shown there is **„Abgeschlossen“**. 3. **Credentials stored with OpenRegister** — Store your personal Transparenzregister username and password via the [Store Credentials](/endpoint/transparenzregister-credentials) endpoint. You can store multiple credential sets under different `name` values (e.g. one per client account). After that, production extract requests use your stored credentials automatically (unless you choose another credential via `X-Credential-Name`). > [!WARNING] > > Storing credentials validates them against the Transparenzregister inspection API. If the Einsichtnahmeschnittstelle is not yet enabled on your account, that login is rejected and the endpoint returns `401` — wait until the status shows **„Abgeschlossen“** before storing credentials. > [!NOTE] > > You can test the integration without live credentials by sending **`X-Credential-Name: sandbox`** on [Order extract](/endpoint/transparenzregister-extract-create). This uses the Transparenzregister test environment and costs **0 credits**. ## Use Cases **AML & KYC** — Retrieve structured beneficial ownership records as part of customer onboarding, periodic review, and risk-based due diligence processes. **Compliance Operations** — Centralize Transparenzregister retrieval across teams and clients in a single API flow. Track every extract by `extract_id` and audit outcomes programmatically. **Due Diligence** — Combine Transparenzregister UBO data with Handelsregister company details and Bundesanzeiger financials for complete entity profiles. ## API Endpoints > [card] [Store Credentials](/endpoint/transparenzregister-credentials) > > Save Transparenzregister credentials with an optional name > [card] [Order extract](/endpoint/transparenzregister-extract-create) > > Create a new Transparenzregister extract and get an extract id > [card] [Get extract](/endpoint/transparenzregister-extract-get) > > Poll by extract id and retrieve structured UBO data and source documents when completed ## Update Frequency * **Source**: Transparenzregister official API * **Updates**: On-demand per extract submission * **Processing**: Async workflow; poll [Get extract](/endpoint/transparenzregister-extract-get) until `status` is `completed` or `failed` # Web Data Source: https://docs.openregister.de/sources/web-data The OpenRegister API provides access to contact information and social media data extracted from company websites. OpenRegister crawls and analyzes company websites to extract publicly available contact information and social media profiles. Our API enriches official register data with real-world contact details and online presence, bridging the gap between official registrations and current business operations. ## What You Get * **Contact information** - Email addresses and phone numbers * **Tax identifiers** - VAT ID and Tax ID from company websites * **Social media profiles** - LinkedIn, Instagram, GitHub, Twitter, Facebook, YouTube, Xing, TikTok * **Website verification** - Link websites to official company entities * **Source tracking** - See where each piece of information was found This data is particularly valuable for sales, marketing, and due diligence when you need current contact details beyond what's in official registers. ## Use Cases **Sales & Marketing** - Enrich CRM data with contact information and social media profiles for targeted outreach campaigns. Build prospect lists with verified email addresses and phone numbers. **Due Diligence** - Verify company legitimacy by matching websites to official register entries and checking online presence. Identify inconsistencies between registered information and current web presence. **Lead Enrichment** - Start with a website URL and discover the company's full profile including ownership structures, financial reports, and contact details. Perfect for lead scoring and qualification workflows. **Competitive Intelligence** - Track competitors' social media presence and online activities. Monitor changes in contact information and web presence over time. ## API Endpoints > [card] [Find company by website](/endpoint/search-lookup) > > Reverse lookup to find a company using its website URL > [card] [Company details with contact](/endpoint/company) > > Get company information including contact details and social media profiles ## Update Frequency * **Source**: Company websites and public web data * **Updates**: Monthly crawls * Data reflects current online presence and contact information