Skip to content
Business RadarLog in

Run a compliance check on a company

Resolve a company, start a screening, wait for it by polling or webhook, and read the sanctions, PEP and adverse-media hits it found.

Last updated

A compliance check screens a company — and optionally its directors and ultimate beneficial owners — against sanctions lists, PEP data, enforcement actions and adverse media. It runs in the background: you post it, wait for it, then read the findings.

Before you start

Step 1: Find the company

Compliance checks reference a company by its Business Radar external_id. If the company is already tracked, search for it.

Search tracked companies

curl -sS -G https://api.businessradar.com/ext/v3/companies \
  -H "Authorization: Bearer $BUSINESSRADAR_API_KEY" \
  --data-urlencode "query=Acme Industries" \
  --data-urlencode "country=NL"

If you have identifying details rather than a search term, GET /ext/v3/companies/match/ resolves them to the single best match — internally first, then against Dun & Bradstreet. A company that exists only at D&B comes back with external_id: null and a duns_number you can register with.

Match on identifying details

curl -sS -G https://api.businessradar.com/ext/v3/companies/match/ \
  -H "Authorization: Bearer $BUSINESSRADAR_API_KEY" \
  --data-urlencode "name=Acme Industries B.V." \
  --data-urlencode "country=NL" \
  --data-urlencode "address_locality=Amsterdam"

At least one of name, duns_number, registration_number or customer_reference is required, and country must accompany a name or registration_number lookup. The endpoint returns 404 when nothing matches.

Step 2: Register the company if it is new

POST /ext/v3/companies registers a company and returns a registration, not a company: the work happens in the background. Posting the same company again returns the existing registration rather than creating a second one.

Register a company

curl -sS -X POST https://api.businessradar.com/ext/v3/companies \
  -H "Authorization: Bearer $BUSINESSRADAR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "duns_number": "123456789",
    "customer_reference": "erp-4711",
    "submit_investigation_when_not_identified": true
  }'

Poll GET /ext/v3/registrations/{registration_id} until status is registered; the response then carries the company object with the external_id you need. Registration moves through a long list of intermediate states (searching, registering, searching_directors, …) and can end in company_not_found, invalid_input or failed.

{
  "external_id": "0e3c2b6a-58f3-4c21-9a4a-9d5f2a1c0b77",
  "status": "registered",
  "status_text": "Registered",
  "progress": 1.0,
  "finished_at": "2026-09-17T09:12:44Z",
  "duns_number": "123456789",
  "customer_reference": "erp-4711",
  "company": {
    "external_id": "a7b1f2c4-1e3d-4f5a-8b9c-0d1e2f3a4b5c",
    "duns_number": "123456789",
    "name": "Acme Industries B.V.",
    "country": "NL"
  }
}

With submit_investigation_when_not_identified: true, a company we cannot identify becomes a missing-company investigation instead of a failure — track it through GET /ext/v3/companies/investigations.

Step 3: Start the check

POST /ext/v3/compliance takes either a company_id or a list of entities. With a company_id you can also screen the people around the company: UBOs above an ownership threshold and registered directors.

Start a compliance check

curl -sS -X POST https://api.businessradar.com/ext/v3/compliance \
  -H "Authorization: Bearer $BUSINESSRADAR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "company_id": "a7b1f2c4-1e3d-4f5a-8b9c-0d1e2f3a4b5c",
    "name": "Acme onboarding 2026-Q3",
    "ubo_screening_enabled": true,
    "directors_screening_enabled": true,
    "ownership_screening_threshold": 25
  }'

To screen people or organisations that are not a company in our data, leave company_id out and pass entities instead — each entity takes a name, an entity_type, and optionally country, date_of_birth (full or partial: 1974, 1974-03 or 1974-03-11) and aliases.

The response is deliberately small: the external_id of the check.

{ "external_id": "3f9a1c77-2b44-4e6d-8f0a-5c7d9e1b2a33" }

Step 4: Wait for it

Two ways to find out that a check has finished. Poll while you are prototyping; subscribe a webhook once you are in production.

Poll the check

GET /ext/v3/compliance/{external_id} returns status — one of pending, queued, in_progress, searching_directors, completed or failed — plus a progress fraction and the high-level scores.

Poll until completed

CHECK_ID=3f9a1c77-2b44-4e6d-8f0a-5c7d9e1b2a33

curl -sS "https://api.businessradar.com/ext/v3/compliance/$CHECK_ID" \
  -H "Authorization: Bearer $BUSINESSRADAR_API_KEY"

Or subscribe to the event

Register a webhook once and Business Radar posts to it as the check moves. compliance_check.status_completed fires when the check reaches completed; compliance_check.results.new fires when monitoring later turns up something new.

Subscribe to compliance events

curl -sS -X POST https://api.businessradar.com/ext/v3/webhooks/ \
  -H "Authorization: Bearer $BUSINESSRADAR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/hooks/businessradar",
    "enabled": true,
    "subscriptions": [
      { "event_type": "compliance_check.status_completed" },
      { "event_type": "compliance_check.results.new" }
    ]
  }'

Deliveries arrive as an envelope with the event name and the payload under a named field:

{
  "event_type": "compliance_check.status_completed",
  "compliance_check": {
    "external_id": "3f9a1c77-2b44-4e6d-8f0a-5c7d9e1b2a33",
    "name": "Acme onboarding 2026-Q3",
    "status": "completed",
    "created_at": "2026-09-17T09:15:02Z",
    "finished_at": "2026-09-17T09:18:41Z",
    "company": {
      "external_id": "a7b1f2c4-1e3d-4f5a-8b9c-0d1e2f3a4b5c",
      "name": "Acme Industries B.V.",
      "country": "NL"
    },
    "compliance_score": "medium",
    "sanction_score": "low",
    "pep_score": "medium",
    "adverse_media_score": "medium",
    "unreviewed_results_count": 7,
    "reviewed_results_count": 0
  }
}

Verify every delivery before trusting it: each carries an X-Signature-SHA256: sha256=<hex> header, an HMAC-SHA256 of the raw body keyed with the webhook secret shown once at creation. Non-2xx responses are retried up to three times with exponential back-off, then marked failed.

Step 5: Read the hits

GET /ext/v3/compliance/{external_id}/results lists the findings, newest first by default. Filter by result_type (sanction, pep, adverse_media, enforcement, govt_owned), by entity, or by min_confidence, and keep exclude_automated_false_positives on to drop matches our models already rated as false positives.

List sanction hits above 80% confidence

CHECK_ID=3f9a1c77-2b44-4e6d-8f0a-5c7d9e1b2a33

curl -sS -G "https://api.businessradar.com/ext/v3/compliance/$CHECK_ID/results" \
  -H "Authorization: Bearer $BUSINESSRADAR_API_KEY" \
  --data-urlencode "result_type=sanction" \
  --data-urlencode "min_confidence=0.8" \
  --data-urlencode "exclude_automated_false_positives=true" \
  --data-urlencode "sorting=confidence" \
  --data-urlencode "order=desc"

What you get

{
  "total_results": 3,
  "next_key": "eyJvZmZzZXQiOjIwfQ",
  "results": [
    {
      "external_id": "5d2f7c91-4b6e-4c1f-9a2b-7e8d3f0a1b23",
      "entity": {
        "external_id": "c1d2e3f4-5a6b-47c8-9d0e-1f2a3b4c5d6e",
        "name": "Jan de Vries"
      },
      "result_type": "sanction",
      "confidence": 0.93,
      "name": "Jan de Vries",
      "title": "Consolidated list of persons subject to EU financial sanctions",
      "text": "Listed under regulation 269/2014, entry added 2024-06-11.",
      "source_name": "EU Consolidated Sanctions List",
      "source_date": "2024-06-11",
      "url": "https://example.org/eu-sanctions/entry/4711",
      "addresses": [{ "country": "NL", "city": "Amsterdam" }],
      "tags": [{ "tag": "asset-freeze" }],
      "sources": [
        {
          "title": "Council Implementing Regulation (EU) 2024/1234",
          "url": "https://example.org/eur-lex/2024-1234",
          "domain": "example.org",
          "publication_date": "2024-06-11"
        }
      ],
      "automated_false_positive_rating": "no",
      "created_at": "2026-09-17T09:18:39Z"
    }
  ]
}

While a check is still running, exclude_automated_false_positives=true returns only results our models have already validated — expect the list to grow until status is completed.

The whole thing

One onboarding run end to end: register the company, wait for it, screen it, wait for that, and print the sanction hits worth a human’s time.

Complete onboarding run

#!/usr/bin/env bash
set -euo pipefail

: "${BUSINESSRADAR_API_KEY:?export your API key first}"
BASE=https://api.businessradar.com/ext/v3
AUTH="Authorization: Bearer $BUSINESSRADAR_API_KEY"

registration=$(curl -fsS -X POST "$BASE/companies" \
  -H "$AUTH" -H "Content-Type: application/json" \
  -d '{
    "duns_number": "123456789",
    "customer_reference": "erp-4711",
    "submit_investigation_when_not_identified": true
  }' | jq -r '.external_id')

while :; do
  body=$(curl -fsS "$BASE/registrations/$registration" -H "$AUTH")
  status=$(echo "$body" | jq -r '.status')
  [ "$status" = "registered" ] && break
  case "$status" in
    company_not_found|invalid_input|failed)
      echo "registration ended as $status" >&2; exit 1 ;;
  esac
  sleep 10
done

company=$(echo "$body" | jq -r '.company.external_id')

check=$(curl -fsS -X POST "$BASE/compliance" \
  -H "$AUTH" -H "Content-Type: application/json" \
  -d "{
    \"company_id\": \"$company\",
    \"name\": \"Acme onboarding 2026-Q3\",
    \"ubo_screening_enabled\": true,
    \"directors_screening_enabled\": true,
    \"ownership_screening_threshold\": 25
  }" | jq -r '.external_id')

while :; do
  status=$(curl -fsS "$BASE/compliance/$check" -H "$AUTH" | jq -r '.status')
  [ "$status" = "completed" ] || [ "$status" = "failed" ] && break
  sleep 10
done

curl -fsS -G "$BASE/compliance/$check/results" -H "$AUTH" \
  --data-urlencode "result_type=sanction" \
  --data-urlencode "min_confidence=0.8" \
  --data-urlencode "exclude_automated_false_positives=true" \
  | jq -r '.results[] | "\(.confidence)\t\(.name)\t\(.source_name)"'

Next steps