Use case · Compliance & AML

Beneficial Ownership Verification API

The UK's PSC register for real beneficial ownership, officers for Spain, France, Norway and Poland, GLEIF parents for LEI holders, and sanctions screening for every name you collect — one key, and a plain answer everywhere else.

Published 15 September 2026

TL;DR

Real beneficial-ownership data exists here for one country: the UK, via the Persons with Significant Control (PSC) register returned with the company profile and by name search. Spain, France, Norway and Poland give you officers and directors — a real signal, but not beneficial ownership. Ireland is company-level, with no officer data at all. GLEIF Level-2 adds a reported corporate parent for entities holding a Legal Entity Identifier — a group link, not an ownership percentage. Prometiam does not hold Spain's Registro Central de Titularidades Reales, France's Registre des bénéficiaires effectifs, Ireland's RBO, Poland's CRBR, or Norway's register of beneficial owners — combine this API with one of those, or a document request, to close the gap.

The problem

Beneficial-ownership verification usually lands on the compliance lead or the AML analyst running KYB, and it asks one specific question: who ultimately owns or controls this counterparty above a regulatory threshold — not who happens to be listed as a director. The two get conflated constantly, because a director list is easy to buy and a UBO register mostly is not: after a 2022 CJEU ruling, most EU member states restricted public access to their beneficial-ownership registers, so a lookup that used to be a free search is now a self-declaration or a document request.

The United Kingdom is the exception: its PSC register is public, and Prometiam serves it through the same endpoints as every other country. That makes the UK the one place here where "beneficial owner" means what it says — everywhere else, what you get is officers, or nothing.

The pattern

Two calls carry the UK beneficial-ownership signal. GET /people/search?country=GB resolves a name to candidate person records — officers and PSCs together, ranked by match_score. GET /companies/{id}?country=GB returns the full company profile with every officer and PSC appointment embedded in its contacts array. Both need country=GB to reach the PSC layer: the same calls against ES, FR or NO return officers only; against IE or PL, nothing (company-level).

# Search UK PSC / officer records by name
curl 'https://api.prometiam.com/functions/v1/risk-api/people/search?country=GB&name=Jane+Smith' \
  -H 'Authorization: Bearer rk_live_...'

# Full company profile — {id} is the internal id from a /companies/search hit, not the
# company number. contacts[] holds officer AND PSC rows together.
curl 'https://api.prometiam.com/functions/v1/risk-api/companies/{id}?country=GB' \
  -H 'Authorization: Bearer rk_live_...'

Two related signals: GET /people/{id} pulls one flagged person's full appointment history, and GET /directors/network finds the same person directing an unusual number of other companies — a concentration signal, not ownership. See director-network analysis for that pattern.

A real example

For a UK company number, the script below resolves the internal id, lists everyone in contacts (officers and PSCs together — role says which), resolves the company's GLEIF parent chain if it holds an LEI, and screens every name collected — PSCs, officers, and the LEI parent's legal name — in a single sanctions batch call.

# ubo_check.py -- UK beneficial-ownership check: profile, PSC/officers, LEI parent, sanctions
import os, requests

API = 'https://api.prometiam.com/functions/v1/risk-api'
HEAD = {'Authorization': f'Bearer {os.environ["PROMETIAM_API_KEY"]}'}

def get(path, **params):
    r = requests.get(f'{API}{path}', params=params, headers=HEAD)
    r.raise_for_status()
    return r.json()['data']

def ubo_check(company_number):
    # 1. Resolve the internal id behind a UK company number
    hits = get('/companies/search', country='GB', company_number=company_number)
    if not hits:
        return {'error': 'company not found'}
    company = hits[0]

    # 2. Full profile -- officer AND PSC rows live together in contacts
    profile = get(f"/companies/{company['id']}", country='GB')
    people = [{'name': c['full_name'], 'role': c['role']} for c in profile.get('contacts', [])]
    names_to_screen = {p['name'] for p in people if p['name']}

    # 3. LEI parent chain -- only exists if the company holds an LEI
    parents = None
    candidates = get('/lei/search', name=profile['company_name'])
    if candidates:
        rel = get(f"/lei/{candidates[0]['lei']}/relationships")
        parents = {'direct_parent': rel.get('direct_parent'), 'ultimate_parent': rel.get('ultimate_parent')}
        if rel.get('ultimate_parent'):
            names_to_screen.add(rel['ultimate_parent']['legal_name'])

    # 4. One batch call screens every collected name (beta; needs the sanctions scope)
    resp = requests.post(f'{API}/sanctions/screen', headers=HEAD,
                          json={'names': sorted(names_to_screen), 'group': 'entity'})
    resp.raise_for_status()

    return {'company': profile['company_name'], 'people': people,
            'lei_parents': parents, 'screening': resp.json()['data']}

if __name__ == '__main__':
    import sys, json
    print(json.dumps(ubo_check(sys.argv[1]), indent=2, ensure_ascii=False))

About 30 lines. Step 4's POST /sanctions/screen needs the sanctions scope outright — unlike the single-name GET form, the batch call skips the free trial allowance, so this script needs a Professional key to reach step 4. Swap in a loop of GET /sanctions/screen calls (same trial allowance as /people/search) to prototype the rest on Free.

What comes back

  • GET /people/search and GET /people/{id} return a person: full_name, nif, is_legal_entity, match_score on a name search, first_seen_date / last_seen_date, and appointments[].
  • Each appointment — in appointments[] or a company's contacts[] — carries full_name, role, appointment_date, end_date, is_current, company_name and company_number. On a UK row, role names the office held or, for a PSC entry, the nature of control recorded — say, more than 25% of shares, or the right to appoint directors.
  • GET /lei/search returns candidates with lei, legal_name, jurisdiction, entity_status, city and country. GET /lei/{lei}/relationships returns direct_parent and ultimate_parent in the same shape, plus direct_children (up to 15) — populated only when the entity reported the relationship to GLEIF; many report none.
  • POST /sanctions/screen returns one result per name, in order: status (match, clear, error or timeout — clear means no hit above your threshold, not a certification), hits[] shaped like the single-name endpoint (entity_name, aliases, source_list, program, listing_date, is_active, match_score), plus hit_count, distinct_entities and best_match_score.

Pricing fit

On raw credit volume — four calls per check: profile (1 credit), PSC/officer search (2), LEI (1), sanctions screen (3), so 7 credits — the trial's 500 credits would cover roughly 70 checks and Starter's 1,000 a month roughly 140. That overstates what the two tiers actually run, because two of the four calls are scope-gated: /people/search needs the people scope (Starter and up; Free gets a 25-call/month trial), and full /sanctions/screen access needs the sanctions scope (Professional and up; the batch call above needs it outright, with no trial).

So Free is for building and testing the pattern above, not running it. Starter (€9.99/month, 1,000 credits/month) lifts the cap on PSC/officer search but still lacks full sanctions screening. Professional (€29.99/month, 10,000 credits/month, full sanctions and export-control screening) runs all four steps — about 20 to 22 credits per check once you screen five or six names (3 credits each), so roughly 450 to 500 checks a month; Scale (50,000 credits a month) about 2,300 to 2,500.

Scope limits, stated plainly

  • Beneficial ownership is real only for the UK, through the PSC register returned with the company profile and via /people/search / /people/{id}.
  • Spain, France, Norway and Poland return officers and directors through the same endpoints — that is not beneficial ownership, only who holds an office.
  • Ireland is company-level: no officers, no PSC, nothing about who runs or owns the company.
  • GLEIF Level-2 (/lei/{lei}/relationships) gives the direct and ultimate parent, and up to 15 direct children, for an entity that holds an LEI and has reported the relationship — a corporate-group link, not a shareholding percentage or a natural-person owner, and many entities report none.
  • Prometiam does not hold Spain's Registro Central de Titularidades Reales, France's Registre des bénéficiaires effectifs, Ireland's RBO, Poland's CRBR, or Norway's register of beneficial owners. None of these registers is queryable through this API, at any tier.
  • Sanctions screening is beta. PEP screening is available separately (see sanctions screening), and is beta, Spain only, and carries no relatives or close associates.
  • No shareholder registers, no ownership percentages beyond PSC and LEI Level-2, no adverse media, no identity-document verification, and no credit score or risk score — a sanctions hit carries a match_score, which is a name-match confidence, not a risk rating.
  • AMLR (Regulation (EU) 2024/1624, applying from 10 July 2027) sets the beneficial-ownership bar at 25% of ownership or voting rights, 15% in higher-risk sectors — see the AMLR compliance timeline. This page is not legal advice: it describes what the API returns, not whether a given structure meets your obligation.

FAQ

Does Prometiam have a beneficial-ownership register?
Only for the United Kingdom. The Persons with Significant Control (PSC) register is returned with the company profile (GET /companies/{id}?country=GB) and searchable by name (GET /people/search?country=GB). Spain, France, Norway and Poland return officers and directors through the same endpoints — a real signal, but not beneficial ownership. Ireland is company-level, with no officer or PSC data.

How do I check beneficial ownership for a Spanish, French, Irish, Polish or Norwegian company?
Combine what the API returns — identity, status, officers where available, LEI parents, and sanctions screening on the names you collect — with the country's own register or a document request: Spain's Registro Central de Titularidades Reales, France's Registre des bénéficiaires effectifs, Ireland's RBO, Poland's CRBR, or Norway's register of beneficial owners. None of these registers is queryable through this API.

What does the GLEIF LEI parent chain add?
For an entity that holds a Legal Entity Identifier and has reported the relationship to GLEIF, GET /lei/{lei}/relationships returns its direct and ultimate parent and up to 15 direct children. That is a reported corporate-group link, not an ownership percentage or a natural-person beneficial owner, and many entities report no relationship at all.

What beneficial-ownership threshold does AMLR use?
Regulation (EU) 2024/1624 (AMLR), which applies across the EU from 10 July 2027, sets the beneficial-ownership bar at 25% of ownership, voting rights or other interest, with the Commission able to lower it to 15% in higher-risk sectors. See the AMLR compliance timeline. This is not legal advice.

What does a UK beneficial-ownership check cost?
Company profile and LEI lookups run on every tier including Free. /people/search needs the people scope from Starter (€9.99/month); full /sanctions/screen access needs the sanctions scope from Professional (€29.99/month), which also includes export-control screening. A trial key tries /people/search 25 times a month; the batch sanctions call needs Professional outright.

Related