Use case · Compliance & AML
Ongoing Due Diligence API
Turn the AMLR's ongoing-monitoring duty into a scheduled job: re-verify each business customer on a risk-based cycle, watch for trigger events daily, and re-screen sanctions lists automatically — with an audit trail you can show a regulator.
The problem
Compliance and MLRO teams at fintechs, payment providers, CASPs, lenders and marketplaces already run KYB at signup: resolve the company, screen it, decide. The gap is what happens after approval. The EU AMLR (Regulation (EU) 2024/1624), applying from 10 July 2027, is explicit that a business customer's file must stay current: re-verified on a risk-based cycle, updated when something changes. Today's AMLD5/6 transpositions already point the same way, as does the UK MLR 2017 for UK-regulated firms.
In practice, most teams treat re-verification as an annual spreadsheet exercise: export the list, re-check each company by hand, hope nothing moved in between. A director resigns or a customer enters insolvency eight months into the cycle, and nobody notices until the next scheduled review — or until a regulator asks for the audit trail and there isn't one.
This page describes what the obligation asks for in general terms, not legal advice; see the AMLR compliance timeline for the dates and thresholds.
The pattern
Run the same checks used at onboarding, on a schedule instead of once. Four endpoints do the work, plus one thing kept on your own side:
- 1. Calendar-driven re-verification. Re-resolve each customer with
POST /companies/lookup(up to 100 items per call) and diffstatus,dissolution_date,address,legal_formandprevious_namesagainst what was stored at onboarding — annually for low-risk customers, quarterly for high-risk ones. - 2. Trigger-based monitoring.
POST /monitorpushes HMAC-SHA256-signed webhooks (X-Prometiam-Signature) for customers in every live country except France and Chile: Spain defaults tocorporate_event,status_changeandsanctions_match; Ireland and Poland (company-level) default tostatus_change,dissolutionandsanctions_match. For Spanish, French and British customers, a dailyGET /company-events/search?date_from=sweep catches dissolution, insolvency, director, capital, name and address changes instead. - 3. Sanctions re-screening.
GET /sanctions/changes?since=reports what was listed, delisted or updated since the last run;POST /sanctions/screenthen re-checks the book due this cycle, up to 50 names per call. - 4. Insolvency.
POST /insolvency/checkcovers corporate insolvency across sixteen markets (FR, DE, GB, AT, CH, NO, FI, US, NL, DK, HR, SE, ES, LV, EE, SG) in one batch call, up to 5 notices per item. DE, AT, US and NL have no company registry behind these notices, so this is the only signal available there. Finland, Denmark, Croatia, Sweden and Switzerland have company records (company records only: with register-change events and monitoring, but no officers and no registry-compliance signal) and their notices are linked by business ID, CVR number, MBS, organisationsnummer and UID (Switzerland, where the notice names the debtor's UID). Slovakia and the United States are company records only too (with register-change events and monitoring), but have no insolvency notices: their bankruptcy shows in the company status. Estonia, Latvia and Spain have insolvency notices as well, linked by registry code, registration number and NIF. - 5. Audit trail. Store each response with its
match_score, thethresholdused, and the review date — the record a regulator will ask to see.
# 1. Re-resolve up to 100 customers per call and diff against the stored record
curl -X POST 'https://api.prometiam.com/functions/v1/risk-api/companies/lookup' \
-H 'Authorization: Bearer rk_live_...' -H 'Content-Type: application/json' \
-d '{"items":[{"country":"ES","company_number":"A28015865"},{"country":"FR","siren":"552032534"}]}'
# 2. What moved on the sanctions lists since the last run?
curl 'https://api.prometiam.com/functions/v1/risk-api/sanctions/changes?since=2026-08-15' \
-H 'Authorization: Bearer rk_live_...'
# 3. Corporate insolvency across the sixteen covered markets, same batch shape
curl -X POST 'https://api.prometiam.com/functions/v1/risk-api/insolvency/check' \
-H 'Authorization: Bearer rk_live_...' -H 'Content-Type: application/json' \
-d '{"items":[{"country":"FR","company_number":"552032534"},{"country":"GB","name":"Example Ltd"}]}'Two quirks worth knowing. French records can come back with status: non_diffusible when INSEE has restricted publication of that entity's identity — treat it as unknown, not a status change. And GET /sanctions/changes is a cue, not a lookup: it reports what moved on the lists, not which of your customers it affects, so the practical pattern is re-screening the book due this cycle whenever the feed shows activity. PEP screening stays beta, Spain only, with no relatives or close associates, so a clear PEP result is not a FATF determination by itself. For the mechanics of screening a large list in one call, see batch screening.
A real example
The review job: batch-resolve, diff, conditionally re-screen, check insolvency, and log every result. A scheduler — cron, a Cloudflare Cron Trigger, or a queue worker — calls review() once a day with the customers due under the calendar.
import os, requests
from datetime import date
API = 'https://api.prometiam.com/functions/v1/risk-api'
HEAD = {'Authorization': f'Bearer {os.environ["PROMETIAM_API_KEY"]}'}
TRACKED = ('status', 'dissolution_date', 'address', 'legal_form', 'previous_names')
TWELVE_MARKETS = {'FR', 'DE', 'GB', 'AT', 'CH', 'NO', 'FI', 'US', 'NL', 'DK', 'HR', 'SE'}
def review(customers, last_run):
# 1. Re-resolve up to 100 at a time; diff the tracked fields against the stored row
for i in range(0, len(customers), 100):
chunk = customers[i:i + 100]
items = [{'country': c['country'], 'company_number': c['company_number']} for c in chunk]
r = requests.post(f'{API}/companies/lookup', json={'items': items}, headers=HEAD).json()
for stored, result in zip(chunk, r['data']):
company = result.get('company') or {}
changed = {f: company.get(f) for f in TRACKED if company.get(f) != stored.get(f)}
audit(stored, 'lookup', result, changed or None)
# 2. Only re-screen if a sanctions list actually moved since the last run
changes = requests.get(f'{API}/sanctions/changes', params={'since': last_run}, headers=HEAD).json()
if changes.get('data'):
names = [c['legal_name'] for c in customers]
batch = requests.post(f'{API}/sanctions/screen', headers=HEAD,
json={'names': names, 'threshold': 85, 'group': 'entity'}).json()
for stored, hit in zip(customers, batch['data']):
audit(stored, 'sanctions', hit, threshold=85)
# 3. Corporate insolvency, sixteen markets only
watched = [c for c in customers if c['country'] in TWELVE_MARKETS]
if watched:
items = [{'country': c['country'], 'company_number': c['company_number']} for c in watched]
r = requests.post(f'{API}/insolvency/check', json={'items': items}, headers=HEAD).json()
for stored, result in zip(watched, r['data']):
if result['status'] == 'found':
audit(stored, 'insolvency', result)
def audit(customer, check, response, changed=None, threshold=None):
# 4. Append-only: the raw response, the score/threshold used, and today's date
db.review_log.insert({'customer_id': customer['id'], 'check': check, 'response': response,
'match_score': response.get('best_match_score'), 'threshold': threshold,
'changed_fields': changed, 'reviewed_on': date.today().isoformat()})42 lines including imports. db and the customer rows are your own store — Prometiam has no concept of "your book"; it resolves, screens and checks whatever is sent to it.
What comes back
Each check returns a status to branch on, plus the detail an audit trail should keep:
- POST /companies/lookup —
status(found/not_found/error/timeout) and, when found, the usual company object:status,dissolution_date,address,legal_form,previous_names, and amatch_scorenormally null here since the call resolves by identifier. - POST /sanctions/screen —
status(match/clear/error/timeout) per name,hits[],hit_count,distinct_entities, and abest_match_score— log this next to thethresholdthat was set. - POST /insolvency/check —
status(found/none/error/timeout), up to 5notices[]newest first, andlatest_filing_date.nonemeans no corporate notice in the sixteen covered markets — not proof of solvency. - POST /monitor webhooks —
alert_type(corporate_event/status_change/dissolution/sanctions_match),event_date, adetailobject, andwebhook_status.


Pricing fit
Take a 5,000-customer book. Annual re-verification is 5,000 POST /companies/lookup items a year — negligible against a monthly quota. Quarterly re-screening of the same book is 5,000 × 4 = 20,000 POST /sanctions/screen items a year, which can land as a burst of up to 5,000 in one month. The real driver is the daily trigger sweep: 1,500 Spanish, French and British names polled once a day through GET /company-events/search runs to about 45,000 calls a month, or 90,000 credits at 2 credits a call. Stack a quarter-end screening burst (up to 5,000 names at 3 credits, 15,000) on top and the busiest month sits near 105,000 credits — beyond Scale (€99.99/month, 50,000 credits a month, 300 requests/minute), so negotiate an Enterprise allowance or put the sweep on webhooks. The same shape at a 500-customer book is about 9,000 credits for the sweep plus a 1,500-credit screening burst, 10,500 in the busiest month: the edge of Professional (€29.99/month, 10,000 credits a month, 120 requests/minute), with Scale comfortably above it.
One more limit to plan around: POST /monitor caps active subscriptions by tier (Free 3, Starter 25, Professional 250, Scale 2,500). A 5,000-customer book with every name in a monitored country (every live country except France and Chile) under webhook monitoring is beyond even Scale (€99.99/month)'s cap; put the highest-risk subset on webhooks and leave the rest to the daily sweep or a scheduled GET /search pass.
Scope limits, stated plainly
- Insolvency notices are corporate only, across sixteen markets (FR, DE, GB, AT, CH, NO, FI, US, NL, DK, HR, SE, ES, LV, EE, SG). Spanish concursal notices are on
/insolvency/searchand also onGET /search. - Webhook monitoring (
POST /monitor) covers every live country except France and Chile, with a per-tier cap on active subscriptions. - Sanctions screening is beta. PEP screening is beta, Spain only, and holds no relatives or close associates — a clear result is not a FATF PEP determination by itself.
- Ireland is company-level: there are no officers to re-verify yet, so the periodic diff is limited to the company record.
- Norway has register-change events only, from 14 Oct 2026 (no gazette) and sits outside the countries
POST /monitorcovers, so Norwegian customers get the calendar-driven lookup diff plus sanctions and insolvency checks, not the daily sweep or webhooks. - None of this is legal advice. It describes what the API returns; whether a program satisfies the AMLR, AMLD5/6 or UK MLR 2017 is a question for your compliance function — see the AMLR compliance timeline.
FAQ
What does "ongoing due diligence" mean under the AMLR?
The EU AMLR (Regulation (EU) 2024/1624, from 10 July 2027) treats a business customer's file as something to keep current, not a one-time gate: re-verify on a risk-based cycle and act on trigger events such as a dissolution or a new sanctions match. This describes the obligation in general terms, not legal advice — see the AMLR compliance timeline.
How often should I re-verify a business customer?
A common risk-based cadence is annual for low-risk customers and quarterly for high-risk ones, re-running the same checks used at onboarding. The exact cadence is a decision for your compliance function.
Can sanctions re-screening be automated?
Yes: GET /sanctions/changes?since= reports what was listed, delisted or updated since the last run, and POST /sanctions/screen re-checks up to 50 names per call. Sanctions screening is beta; PEP screening is beta, Spain only, and holds no relatives or close associates, so a clear result is not a FATF determination by itself.
Does ongoing monitoring work the same way in every country?
No. POST /monitor webhooks cover every live country except France and Chile. GET /company-events/search covers Spain, France and the United Kingdom, plus register-change events for every other live country except Chile (none before 14 Oct 2026 for Ireland, Poland and Norway; Argentina is read monthly, none before 28 Oct 2026; Mexico covers its LEI-registered entities only). Norway has register-change events only, from 14 Oct 2026 (no gazette), plus monitoring, so Norwegian customers also get status, dissolution and sanctions alerts. Ireland is company-level, with no officers to re-verify yet.
What happens if a review batch is bigger than my remaining quota?POST /companies/lookup, POST /sanctions/screen and POST /insolvency/check count every item as one request. A batch larger than what is left on your plan is refused up front with a 429 (batch_exceeds_quota) and max_items_now, so the call can be resized instead of losing partial results.
Related
- KYB onboarding — the upstream verification step this job re-runs
- Counterparty monitoring — the same event-sweep pattern applied to vendors and suppliers
- Sanctions screening — the standalone screening pattern this job calls on a schedule
- Batch screening — screening a large list in one call
- Customer insolvency monitoring — insolvency in detail
- EU fintech onboarding checklist — step 18 is this page, in checklist form
- The AMLR compliance timeline
- For fintechs · for payment providers