Skip to main content
Beta. Discrepancy reports are available in Germany only for now, and we will extend coverage to more countries soon. The request and response shapes may still change. Access is enabled per account with a subscription that includes a monthly allowance of reports: contact support@topograph.co to request it. If you need another country, tell us at the same address: we are looking for teams to shape the next registers with.
As an obliged entity, you must report to a beneficial-ownership register any discrepancy between what the register lists and what your own due diligence established. Each country has its own register and its own reporting form. POST /v2/discrepancy-reports files that report for you, with one request shape for every country. You send the beneficial owners you identified in the same shape you receive them from POST /v2/company. We write the explanation in the register’s language, file the report under your own register account, keep the register’s acknowledgement of receipt, and tell you the outcome by webhook or polling. All examples on this page use fictitious data.

Before you start

  1. Access. The beta must be enabled on your account. Without it, every call answers 403 with feature_not_enabled.
  2. Your register credentials, on a workspace. See Register credentials and workspaces below.
  3. Your allowance. Your subscription allows a number of reports per monthly period. Once they are used up, a report answers 429 with quota_exceeded. GET /v2/discrepancy-reports/usage shows the limit, what is used and when the allowance renews. Reports that fail are not counted.

Register credentials and workspaces

The duty to report is yours, so every report is filed under your own account at the register, never under Topograph’s. The register records you as the reporter, and the report appears in your account there. You store that account’s credentials on a workspace, once per register, through the vault:
The credential key names the register (de_transparenzregister for Germany, see Supported countries). Credentials are encrypted at rest, never returned by the API, and used only to file and follow your reports. See Register credentials for how they are stored. When you file a report, the workspace decides which credentials are used:
  1. The workspace you select with the x-topograph-workspace-id header, if it holds credentials for that country’s register.
  2. Otherwise, those of your account’s default workspace.
  3. Otherwise, the report is refused with 428 account_configuration_required, and nothing is filed.
So if several legal entities of your group report separately, give each its own workspace with its own register account, and send each report from the right workspace. A report always stays with the workspace that filed it: it is followed and its receipt fetched with the same credentials. If the register rejects the stored credentials, the report fails with account_configuration_required and nothing is filed. Update them on the workspace and send the report again with a new Idempotency-Key.

File a report

The report is filed as soon as it is accepted. There is no draft step: validate on your side before you send it.

The explanation we file

The explanation is written in the register’s language, from the facts you send and only from them. The response shows it in filing.text from the moment the report is accepted. For the German example above:
Percentages come from control.details. When you have not established a percentage, omit details: none is ever assumed. Where the language has grammatical gender, as German does, gender decides the form. Each register limits the length of the explanation; a longer one is refused with 400 before anything is filed.

Follow the report

POST answers 201 with status: "in_progress". Filing usually takes under two minutes. You learn the outcome in either of two ways:
  • Webhook. discrepancy_report.updated carries the report exactly as GET returns it.
  • Polling. GET /v2/discrepancy-reports/{id} is free. GET /v2/discrepancy-reports lists your reports, filtered by companyId, countryCode or status, with first and after for pagination.

The receipt

filing.receipt.url downloads the register’s acknowledgement of receipt as a PDF. The link is valid for 15 minutes; fetch the report again for a fresh one. filing.receipt.sha256 identifies the file, so you can prove later that a stored copy is the one received. We keep the receipt after the register stops serving it. A receipt confirms that the register received your report. It is not the register’s decision on the discrepancy.

Retries and idempotency

Idempotency-Key is required, and a UUID per report is recommended. Sending the same body again with the same key returns the original report with 200 and files nothing new, so a request that timed out on your side is safe to resend as is. Reusing a key with a different body answers 409. A report is filed at most once, whatever happens in between. If we cannot confirm right away whether the register received a report, it stays in_progress while we check with the register; it is never filed a second time.

Errors

Errors found before the report is accepted are returned by POST. Errors found while filing appear on the report as status: "failed" with error. See Reliability and errors for the full list.

Supported countries

In Germany, the report is an Unstimmigkeitsmeldung under § 23a GwG. incorrect_or_incomplete_information is filed as “Angaben nach § 19 Abs. 1 GwG sind fehlerhaft/unvollständig”, and different_beneficial_owners as “Abweichende Liste wirtschaftlich Berechtigter wurde ermittelt”. The Transparenzregister account must be allowed to file discrepancy reports. More countries are coming, with the same request and response shapes.

Test in your development environment

A development environment accepts the same requests without register credentials and files nothing. It generates a register reference and a receipt PDF marked as a sandbox artefact, and sends the real discrepancy_report.updated webhook. Put a test identifier in companyId to force an outcome: any public error code in upper case, such as RESOURCE_NOT_FOUND, SOURCE_UNAVAILABLE, ACCOUNT_CONFIGURATION_REQUIRED or QUOTA_EXCEEDED, or a delay such as DELAY_1M.