Adverse Media Screening
Screens a person or organization against adverse news coverage. This is a separate obligation from sanctions screening: sanctions lists are official, adverse media is an open-source signal that requires interpretation.
POST /api/v1/sanction/intelligence/adverse-mediaAuthentication and token minting: Sanctions Screening API. Required scope: sanction:view_results.
Request
| Field | Type | Required | Notes |
|---|---|---|---|
entityName | string | ✅ | The person or organization name to screen |
entityType | string | — | Person or organization |
tckn · vkn | string | — | Disambiguating identifiers — they cut false positives sharply |
countryCode | string | — | ISO 3166-1 alpha-2 |
limit | number | — | Maximum records to return |
onlyActive | boolean | — | Current/active records only |
customerReference | string | — | Your own record id (written to the audit trail) |
productChannel | string | — | Which product it came from (reporting) |
You cannot force a fresh search. The old forceRefresh field was deliberately removed and its number reserved: forcing a search on every request would bypass the rescreen interval, hit the external provider each time and rate-limit it into an open circuit breaker. Freshness is governed by policy (rescreenIntervalDays), not by the request.
Decision semantics
The decision field takes five values, and two of them do not mean "clear":
allow and not_performed are not the same: the first means "we looked, nothing found", the second means "we could not look". Collapsing them produces a compliance claim you cannot defend — you would be clearing customers while the provider was unreachable.decision | Meaning | What you must do |
|---|---|---|
allow | The check ran, nothing matched | Continue the flow |
observe | Weak / low-severity signal | Record it, keep watching |
review | A match that needs review | Manual decision |
not_performed | The check did not run | Do not treat as clear — retry or check manually |
unavailable | The provider was unreachable | Do not treat as clear — be conservative |
Response
{
"success": true,
"requestId": "am_01J9…",
"matched": true,
"riskScore": 72,
"decision": "review",
"latencyMs": 340,
"hits": [
{
"recordId": "amh_01J9…",
"entityName": "Örnek A.Ş.",
"headline": "…",
"sourceName": "…",
"sourceUrl": "https://…",
"publishedAt": "2026-03-11T08:00:00Z",
"severity": "high",
"riskScore": 72,
"categories": ["fraud"],
"matchBasis": "name+vkn",
"publisher": "…",
"publisherDomain": "…",
"language": "tr",
"capturedAt": "2026-03-11T09:14:00Z",
"firstSeenAt": "2026-03-11T09:14:00Z",
"snapshotTextHash": "sha256:…",
"providerCode": "…"
}
],
"coverageJson": "{…}"
}Evidence fields
Every record carries snapshot evidence: capturedAt, firstSeenAt, snapshotTextHash, publisher, publisherDomain, language. These let you show what your decision rested on even after the source article is taken down — sourceUrl alone is not sufficient evidence.
Coverage manifest
coverageJson states what the screening covered (schema sanction.adverse_media.coverage.v1).
Derive your compliance statement (e.g. the KYC coverage line) only from this field, never from a constant. If it comes back empty or unparseable, fall back to the conservative constant — do not claim "adverse media screened".
Policy
The screening scope is set by the merchant policy:
GET /api/v1/sanction/policy/adverse-media| Field | What it does |
|---|---|
enabled | Whether screening is on |
categoriesInScope | Which categories are in scope |
minimumSeverity | Minimum severity threshold |
languages · sourceCountries | Language and source-country scope |
publisherAllowlist · publisherBlocklist | Publisher allow/block lists |
lookbackDays | How far back to look |
rescreenIntervalDays | Rescreen interval |
stalenessWarnDays | Staleness warning threshold |
unclassifiedHandling | Whether unclassified records are REVIEW or EXCLUDE |
continuousMonitoringEnabled | Whether ongoing monitoring is on |
queryRiskTerms | Risk terms added to the query — leaving it empty means a broad sweep, and that is declared in the coverage note |
Reading the policy is part of the integration surface; writing it happens in the panel. Remember that narrowing the scope (language, category, publisher) shows up in your compliance statement — coverageJson carries the narrowing too.