Screening API
Perform real-time screening of individuals and organisations against global sanctions lists, PEPs (Politically Exposed Persons), watchlists, and adverse media sources.
Real screening calls are only made in live mode. In test mode, all screenings return deterministic mock results instantly - no credits consumed, no external API calls. Results are controlled by keywords in the entity name. See test mode triggers ↓
What Gets Screened
- Sanctions: OFAC, UN, EU, UK HMT, DFAT and more
- Watchlists: Regulatory enforcement, disqualified directors
- PEPs: Politically Exposed Persons and their relatives/close associates
- Adverse Media: Negative news, fraud allegations, financial crime
How Screening Works
Screening is an asynchronous process:
POST /screening/
asynchronously
Webhook or GET
Each entity can only be screened once. Subsequent requests return 409 Conflict with the existing screening details.
Screen Entity
Submit an existing entity for KYC/AML screening. Returns immediately while screening runs asynchronously.
/api/v1/screening/
/api/v2/screening/
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
entity_id | uuid | Yes | ID of existing entity to screen |
webhook_url | string | No | Webhook URL for completion notification (overrides tenant default) |
monitoring_enabled | boolean | No | Explicitly enable or disable ongoing monitoring. If omitted, the tenant's default setting is used. |
Returns 202 Accepted immediately. The screening runs asynchronously.
Screen Entity
curl -X POST https://api.kycgenie.com/api/v1/screening/ \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: screen-entity-550e8400" \
-d '{
"entity_id": "550e8400-e29b-41d4-a716-446655440000",
"webhook_url": "https://your-domain.com/webhooks/screening"
}'
curl -X POST https://api.kycgenie.com/api/v2/screening/ \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: screen-entity-550e8400" \
-d '{
"entity_id": "550e8400-e29b-41d4-a716-446655440000",
"webhook_url": "https://your-domain.com/webhooks/screening",
"monitoring_enabled": true
}'
import requests
entity_id = "550e8400-e29b-41d4-a716-446655440000"
response = requests.post(
"https://api.kycgenie.com/api/v1/screening/",
headers={
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
"Idempotency-Key": f"screen-entity-{entity_id}",
},
json={
"entity_id": entity_id,
"webhook_url": "https://your-domain.com/webhooks/screening",
},
)
result = response.json()
print(f"Screening ID: {result['screening_id']}")
from kycgenie import KYCGenie
client = KYCGenie(api_key="YOUR_API_KEY")
result = client.screening.screen(
entity_id="550e8400-e29b-41d4-a716-446655440000",
webhook_url="https://your-domain.com/webhooks/screening",
monitoring_enabled=True,
)
print(f"Screening ID: {result.screening_id}")
print(f"Status: {result.screening_status}")
const entityId = "550e8400-e29b-41d4-a716-446655440000";
const res = await fetch("https://api.kycgenie.com/api/v1/screening/", {
method: "POST",
headers: {
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
"Idempotency-Key": `screen-entity-${entityId}`,
},
body: JSON.stringify({
entity_id: entityId,
webhook_url: "https://your-domain.com/webhooks/screening",
}),
});
const result = await res.json();
console.log(`Screening ID: ${result.screening_id}`);
const entityId = "550e8400-e29b-41d4-a716-446655440000";
const res = await fetch("https://api.kycgenie.com/api/v2/screening/", {
method: "POST",
headers: {
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
"Idempotency-Key": `screen-entity-${entityId}`,
},
body: JSON.stringify({
entity_id: entityId,
webhook_url: "https://your-domain.com/webhooks/screening",
monitoring_enabled: true,
}),
});
const result = await res.json();
console.log(`Screening ID: ${result.screening_id}`);
202 Accepted Response
{
"screening_id": "62ee34a4-28f0-4a83-a016-7441e7900d7e",
"entity_id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Acme Corp Ltd",
"entity_type": "company",
"screening_status": "pending",
"message": "Screening initiated"
}
409 - Already Screened
{
"code": "CONFLICT",
"message": "Entity already screened.",
"details": {
"screening_id": "62ee34a4-28f0-4a83-a016-7441e7900d7e",
"entity_id": "550e8400-e29b-41d4-a716-446655440000",
"screening_status": "completed",
"screened_at": "2026-01-15T10:30:00Z"
}
}
Test Mode Triggers
When using a test API key, screenings are simulated. The result is determined by keywords in the entity's name.
The keyword match is case-insensitive and substring-based.
If the entity name contains SANCTION anywhere (e.g. "Maria Sanction Lopez"), the sanction
bucket fires. If no keyword matches, the default pass result is returned.
Trigger Keywords
| Keyword in name | screening_result | Case / Alert / RiskProfile created? | AML types |
|---|---|---|---|
| (none) | CLEAR |
No - clean result, no review needed | - |
REVIEW | HAS_PROFILES |
Yes | ADVERSE_MEDIA, ADVERSE_MEDIA_V2_OTHER_MINOR |
PEP | HAS_PROFILES |
Yes | PEP, PEP_CLASS_1 |
MEDIA | HAS_PROFILES |
Yes | ADVERSE_MEDIA, ADVERSE_MEDIA_V2_NARCOTICS_AML_CFT, ADVERSE_MEDIA_V2_VIOLENCE_AML_CFT |
SANCTION | HAS_PROFILES |
Yes | SANCTION, SANCTION_INDIVIDUAL |
What gets created for non-PASS buckets
For any bucket other than pass, the full review chain is created locally in your test environment - no external calls made:
- One Case (status
open, no case ID) - One Alert (with a
mock_alert_*reference ID) - One RiskProfile (status
not_reviewed, with bucket-appropriate AML types)
The case.opened and alert.created webhooks are fired so you can test your webhook consumer end-to-end.
// PASS - clean, no Case created
{ "name": "Acme Consulting Ltd", "entity_type": "company" }
// REVIEW - adverse media hit, Case + Alert + RiskProfile created
{ "name": "REVIEW Holdings", "entity_type": "company" }
// PEP - politically exposed person hit
{ "name": "Mr PEP Johansson", "entity_type": "individual" }
// FAIL - high-risk adverse media
{ "name": "MEDIA Corp SA", "entity_type": "company" }
// SANCTION - sanctions hit, highest risk score
{ "name": "SANCTION Trading Ltd", "entity_type": "company" }
Get Screening Results
Retrieve screening results for an entity. Returns the most recent screening with a nested hierarchy of Cases → Alerts → RiskProfiles. This is the lightweight summary view - risk profile boolean flags only, no full sensitive data objects.
/api/v1/screening/{entity_id}/
/api/v2/screening/{entity_id}/
Returns 200 OK. Use the detailed endpoint for full PEP / sanctions / media JSON.
Get Screening Results
curl https://api.kycgenie.com/api/v1/screening/550e8400-e29b-41d4-a716-446655440000/ \
-H "Authorization: Bearer YOUR_API_KEY"
curl https://api.kycgenie.com/api/v2/screening/550e8400-e29b-41d4-a716-446655440000/ \
-H "Authorization: Bearer YOUR_API_KEY"
import requests
entity_id = "550e8400-e29b-41d4-a716-446655440000"
response = requests.get(
f"https://api.kycgenie.com/api/v1/screening/{entity_id}/",
headers={"Authorization": "Bearer YOUR_API_KEY"},
)
data = response.json()
print(f"Status: {data['screening']['status']}")
for case in data["screening"]["cases"]:
for alert in case["alerts"]:
for rp in alert["risk_profiles"]:
print(f" Risk profile: {rp['name']} (score={rp['matching_score']})")
from kycgenie import KYCGenie
client = KYCGenie(api_key="YOUR_API_KEY")
data = client.screening.get(
entity_id="550e8400-e29b-41d4-a716-446655440000",
)
const entityId = "550e8400-e29b-41d4-a716-446655440000";
const res = await fetch(
`https://api.kycgenie.com/api/v1/screening/${entityId}/`,
{ headers: { "Authorization": "Bearer YOUR_API_KEY" } }
);
const data = await res.json();
console.log(`Status: ${data.screening.status}`);
const entityId = "550e8400-e29b-41d4-a716-446655440000";
const res = await fetch(
`https://api.kycgenie.com/api/v2/screening/${entityId}/`,
{ headers: { "Authorization": "Bearer YOUR_API_KEY" } }
);
const data = await res.json();
console.log(`Status: ${data.screening.status}`);
Response Example (200 OK)
{
"screening": {
"id": "62ee34a4-28f0-4a83-a016-7441e7900d7e",
"entity": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "John Doe",
"entity_type": "individual"
},
"status": "completed",
"screening_type": "initial",
"latest_case_decision": "acceptable_risk",
"creator_profile": {
"id": "5c4fdd14-93c8-4653-9c2b-a45f58654599",
"name": "Jane Smith",
"email": "jane@example.com"
},
"decider_profile": null,
"created_at": "2026-01-07T14:35:36Z",
"updated_at": "2026-01-09T14:04:11Z",
"cases": [
{
"id": "c8f16c1d-8e55-4ade-afe4-dbc472f49a31",
"title": "Case for John Doe - Onboarding",
"status": "closed",
"decision": "acceptable_risk",
"assigned_to": null,
"closed_by": {
"id": "5c4fdd14-93c8-4653-9c2b-a45f58654599",
"name": "Jane Smith",
"email": "jane@example.com"
},
"closed_at": "2026-01-09T14:04:11Z",
"created_at": "2026-01-07T14:35:39Z",
"updated_at": "2026-01-09T14:04:11Z",
"alerts": [
{
"id": "5bc52924-8a4f-48ae-acaa-13027deae060",
"risk_profiles": [
{
"id": "f67f165d-0d1e-4eb7-81e6-3494a260dcd4",
"name": "John Doe - Adverse Media, PEP",
"entity_type": "individual",
"status": "false_positive",
"matching_score": 0.3,
"matching_name": "John Doe",
"match_type": ["aka_exact", "name_variations_removal"],
"dates_of_birth": ["1975", "1975-06-21"],
"also_known_as": ["Johnathan Doe", "John Doe Jr."],
"all_related_countries": ["AU", "BR", "US"],
"has_pep": true,
"has_sanctions": false,
"has_adverse_media": true,
"has_watchlists": false
}
]
}
]
}
]
}
}
Risk Profile Fields (Summary)
| Field | Type | Description |
|---|---|---|
id | uuid | Unique risk profile identifier |
name | string | Matched entity name with risk types, e.g. "John Doe - PEP, Sanctions" |
entity_type | string | individual or company |
status | string | not_reviewed | in_review | false_positive | true_positive |
matching_score | float | Confidence 0.0–1.0. ≥ 0.8 = high confidence; < 0.5 = likely false positive. |
matching_name | string | Exact name from watchlist that triggered the match |
match_type | array | How the match was made: name_exact, aka_exact, name_variations_removal, etc. |
dates_of_birth | array | Known dates of birth (YYYY or YYYY-MM-DD) |
also_known_as | array | Aliases and alternative names |
all_related_countries | array | ISO 3166-1 alpha-2 country codes associated with the risk |
has_pep | boolean | True if PEP data exists |
has_sanctions | boolean | True if sanctions data exists |
has_adverse_media | boolean | True if adverse media articles exist |
has_watchlists | boolean | True if watchlist data exists |
Get Detailed Results
Retrieve the same screening structure as the summary endpoint, but with full sensitive data included:
pep, sanctions, media, and watchlists JSON objects on each risk profile.
Use this for compliance review and inspection.
/api/v1/screening/{entity_id}/detailed/
/api/v2/screening/{entity_id}/detailed/
Additional Risk Profile Fields (Detailed View)
| Field | Type | Description |
|---|---|---|
aml_types | array | AML type strings e.g. ["sanction", "pep"] |
pep | object | Full PEP data (structure varies) |
sanctions | object | Full sanctions data (structure varies) |
media | array | Adverse media articles |
watchlists | object | Watchlist hit data (structure varies) |
Get Detailed Results
curl https://api.kycgenie.com/api/v1/screening/550e8400-e29b-41d4-a716-446655440000/detailed/ \
-H "Authorization: Bearer YOUR_API_KEY"
curl https://api.kycgenie.com/api/v2/screening/550e8400-e29b-41d4-a716-446655440000/detailed/ \
-H "Authorization: Bearer YOUR_API_KEY"
import requests
entity_id = "550e8400-e29b-41d4-a716-446655440000"
response = requests.get(
f"https://api.kycgenie.com/api/v1/screening/{entity_id}/detailed/",
headers={"Authorization": "Bearer YOUR_API_KEY"},
)
data = response.json()
for case in data["screening"]["cases"]:
for alert in case["alerts"]:
for rp in alert["risk_profiles"]:
if rp["pep"]:
print(f"PEP data: {rp['pep']}")
if rp["sanctions"]:
print(f"Sanctions: {rp['sanctions']}")
from kycgenie import KYCGenie
client = KYCGenie(api_key="YOUR_API_KEY")
data = client.screening.get_detailed(
entity_id="550e8400-e29b-41d4-a716-446655440000",
)
const res = await fetch(
`https://api.kycgenie.com/api/v1/screening/550e8400-e29b-41d4-a716-446655440000/detailed/`,
{ headers: { "Authorization": "Bearer YOUR_API_KEY" } }
);
const data = await res.json();
const res = await fetch(
`https://api.kycgenie.com/api/v2/screening/550e8400-e29b-41d4-a716-446655440000/detailed/`,
{ headers: { "Authorization": "Bearer YOUR_API_KEY" } }
);
const data = await res.json();
Response Example (200 OK)
{
"screening": {
"id": "62ee34a4-28f0-4a83-a016-7441e7900d7e",
"status": "completed",
"cases": [
{
"id": "c8f16c1d-8e55-4ade-afe4-dbc472f49a31",
"status": "closed",
"decision": "acceptable_risk",
"alerts": [
{
"id": "5bc52924-8a4f-48ae-acaa-13027deae060",
"risk_profiles": [
{
"id": "f67f165d-0d1e-4eb7-81e6-3494a260dcd4",
"name": "Jane Smith - PEP, Sanctions",
"status": "not_reviewed",
"matching_score": 0.92,
"aml_types": ["sanction", "pep", "pep-class-1", "adverse-media", "adverse-media-v2-financial-aml-cft", "fitness-probity"],
"pep": [
{
"name": "Example PEP - John Doe",
"aml_types": ["pep", "pep-class-1"],
"country_codes": ["GB"],
"political_positions": ["Member of Parliament"],
"listing_started_utc": "2019-01-01T00:00:00Z",
"listing_ended_utc": null,
"fields": [
{ "name": "Date of Birth", "tag": "date_of_birth", "value": "1975-03-22" },
{ "name": "Country", "tag": null, "value": "United Kingdom" }
]
}
],
"sanctions": [
{
"name": "OFAC SDN List",
"aml_types": ["sanction"],
"country_codes": ["GB"],
"listing_started_utc": "2023-06-15T00:00:00Z",
"listing_ended_utc": null,
"fields": [
{ "name": "Designation Date", "tag": null, "value": "2023-06-15" },
{ "name": "Program", "tag": null, "value": "RUSSIA-EO14024" },
{ "name": "Sanction Type", "tag": null, "value": "Block" }
]
}
],
"media": [
{
"title": "MP faces corruption inquiry over undisclosed payments",
"snippet": "An investigation has been launched following allegations of undisclosed payments...",
"url": "https://news.example.com/article/12345",
"publishing_date": "2024-11-08T00:00:00Z"
}
],
"watchlists": [
{
"name": "UK Companies House Disqualified Directors",
"aml_types": ["fitness-probity"],
"listing_started_utc": "2024-01-10T00:00:00Z",
"listing_ended_utc": null,
"fields": [
{ "name": "Enforcement Agency", "tag": null, "value": "United Kingdom Companies House" }
]
}
]
}
]
}
]
}
]
}
}
Case Management
Cases are review containers created when screening finds potential matches. Update case status and decision as you review the associated risk profiles.
Get Case
/api/v2/cases/{case_id}/
Update Case
/api/v2/cases/{case_id}/
Request Body
| Parameter | Type | Description |
|---|---|---|
status | string | open | in_review | closed |
decision | string | no_risk | acceptable_risk | unacceptable_risk (only when closing) |
closure_reason | string | Analyst's explanation of the decision. Recommended when setting a decision. |
Setting a decision automatically closes the case.
Get Case
curl https://api.kycgenie.com/api/v1/cases/c8f16c1d-8e55-4ade-afe4-dbc472f49a31/ \
-H "Authorization: Bearer YOUR_API_KEY"
curl https://api.kycgenie.com/api/v2/cases/c8f16c1d-8e55-4ade-afe4-dbc472f49a31/ \
-H "Authorization: Bearer YOUR_API_KEY"
import requests
response = requests.get(
"https://api.kycgenie.com/api/v2/cases/c8f16c1d-8e55-4ade-afe4-dbc472f49a31/",
headers={"Authorization": "Bearer YOUR_API_KEY"},
)
case = response.json()
print(f"Case: {case['title']}, Status: {case['status']}")
from kycgenie import KYCGenie
client = KYCGenie(api_key="YOUR_API_KEY")
case = client.screening.get_case(
case_id="c8f16c1d-8e55-4ade-afe4-dbc472f49a31"
)
const res = await fetch(
'https://api.kycgenie.com/api/v1/cases/c8f16c1d-8e55-4ade-afe4-dbc472f49a31/',
{ headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
);
const c = await res.json();
console.log(`${c.title} - ${c.status}`);
const res = await fetch(
'https://api.kycgenie.com/api/v2/cases/c8f16c1d-8e55-4ade-afe4-dbc472f49a31/',
{ headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
);
const c = await res.json();
console.log(`${c.title} - ${c.status}`);
Response Example
{
"id": "c8f16c1d-8e55-4ade-afe4-dbc472f49a31",
"screening_id": "62ee34a4-28f0-4a83-a016-7441e7900d7e",
"title": "Initial Screen - Jane Smith",
"status": "closed",
"decision": "acceptable_risk",
"closure_reason": "DOB and nationality confirmed different individual",
"assigned_to": null,
"closed_by": {
"id": "5c4fdd14-93c8-4653-9c2b-a45f58654599",
"name": "Alex Johnson",
"email": "alex@example.com"
},
"closed_at": "2026-06-14T14:49:24.500411+00:00",
"created_at": "2026-06-13T20:27:24.160119+00:00",
"updated_at": "2026-06-14T14:49:24.505127+00:00"
}
Close Case with Decision
curl -X PATCH https://api.kycgenie.com/api/v1/cases/c8f16c1d-8e55-4ade-afe4-dbc472f49a31/ \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: case-close-c8f16c1d" \
-d '{"decision": "acceptable_risk", "closure_reason": "DOB and nationality confirmed different individual"}'
curl -X PATCH https://api.kycgenie.com/api/v2/cases/c8f16c1d-8e55-4ade-afe4-dbc472f49a31/ \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: case-close-c8f16c1d" \
-d '{"decision": "acceptable_risk", "closure_reason": "DOB and nationality confirmed different individual"}'
import requests
case_id = "c8f16c1d-8e55-4ade-afe4-dbc472f49a31"
response = requests.patch(
f"https://api.kycgenie.com/api/v1/cases/{case_id}/",
headers={
"Authorization": "Bearer YOUR_API_KEY",
"Idempotency-Key": f"case-close-{case_id}",
},
json={
"decision": "acceptable_risk",
"closure_reason": "DOB and nationality confirmed different individual",
},
)
case = response.json()
print(f"Status: {case['status']}, Decision: {case['decision']}")
from kycgenie import KYCGenie
client = KYCGenie(api_key="YOUR_API_KEY")
client.screening.update_case(
case_id="c8f16c1d-8e55-4ade-afe4-dbc472f49a31",
decision="acceptable_risk",
closure_reason="DOB and nationality confirmed different individual",
)
const caseId = "c8f16c1d-8e55-4ade-afe4-dbc472f49a31";
await fetch(`https://api.kycgenie.com/api/v1/cases/${caseId}/`, {
method: "PATCH",
headers: {
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
"Idempotency-Key": `case-close-${caseId}`,
},
body: JSON.stringify({
decision: "acceptable_risk",
closure_reason: "DOB and nationality confirmed different individual",
}),
});
const caseId = "c8f16c1d-8e55-4ade-afe4-dbc472f49a31";
await fetch(`https://api.kycgenie.com/api/v2/cases/${caseId}/`, {
method: "PATCH",
headers: {
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
"Idempotency-Key": `case-close-${caseId}`,
},
body: JSON.stringify({
decision: "acceptable_risk",
closure_reason: "DOB and nationality confirmed different individual",
}),
});
Risk Profile Status
Update the review status of an individual risk profile. Use this to mark matches as false positives, confirm true positives, or move them into review.
/api/v1/risk-profiles/{risk_profile_id}/status/
/api/v2/risk-profiles/{risk_profile_id}/status/
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
status | string | Yes | not_reviewed | in_review | false_positive | true_positive |
note | string | No | Optional note explaining the status change (e.g. "DOB mismatch - confirmed false positive") |
Mark as False Positive
curl -X PATCH https://api.kycgenie.com/api/v1/risk-profiles/f67f165d-0d1e-4eb7-81e6-3494a260dcd4/status/ \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"status": "false_positive",
"note": "DOB mismatch - confirmed false positive"
}'
curl -X PATCH https://api.kycgenie.com/api/v2/risk-profiles/f67f165d-0d1e-4eb7-81e6-3494a260dcd4/status/ \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"status": "false_positive",
"note": "DOB mismatch - confirmed false positive"
}'
import requests
rp_id = "f67f165d-0d1e-4eb7-81e6-3494a260dcd4"
response = requests.patch(
f"https://api.kycgenie.com/api/v1/risk-profiles/{rp_id}/status/",
headers={"Authorization": "Bearer YOUR_API_KEY"},
json={
"status": "false_positive",
"note": "DOB mismatch - confirmed false positive",
},
)
print(response.status_code) # 200
from kycgenie import KYCGenie
client = KYCGenie(api_key="YOUR_API_KEY")
client.risk_profiles.update_status(
risk_profile_id="f67f165d-0d1e-4eb7-81e6-3494a260dcd4",
status="false_positive",
note="DOB mismatch - confirmed false positive",
)
const rpId = "f67f165d-0d1e-4eb7-81e6-3494a260dcd4";
await fetch(`https://api.kycgenie.com/api/v1/risk-profiles/${rpId}/status/`, {
method: "PATCH",
headers: {
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
status: "false_positive",
note: "DOB mismatch - confirmed false positive",
}),
});
const rpId = "f67f165d-0d1e-4eb7-81e6-3494a260dcd4";
await fetch(`https://api.kycgenie.com/api/v2/risk-profiles/${rpId}/status/`, {
method: "PATCH",
headers: {
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
status: "false_positive",
note: "DOB mismatch - confirmed false positive",
}),
});
Batch Screening
Screen multiple existing entities in a single request. Entities that have already been screened are automatically skipped.
/api/v1/screening/batch/
/api/v2/screening/batch/
Get Batch Job Status
/api/v1/screening/batch/{job_id}/
/api/v2/screening/batch/{job_id}/
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
entity_ids | array | Yes | Array of entity UUIDs to screen (1–10,000). Duplicates auto-removed. |
webhook_url | string | No | Overrides the tenant's default webhook URL for this job. |
webhook_progress | boolean | No | Receive progress webhooks during processing. |
Batch Screening
curl -X POST https://api.kycgenie.com/api/v1/screening/batch/ \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: batch-screening-20260127-001" \
-d '{
"entity_ids": [
"550e8400-e29b-41d4-a716-446655440000",
"660f9511-f30c-23e5-b827-537766551111"
],
"webhook_url": "https://your-domain.com/webhooks/batch"
}'
curl -X POST https://api.kycgenie.com/api/v2/screening/batch/ \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: batch-screening-20260127-001" \
-d '{
"entity_ids": [
"550e8400-e29b-41d4-a716-446655440000",
"660f9511-f30c-23e5-b827-537766551111"
],
"webhook_url": "https://your-domain.com/webhooks/batch"
}'
import requests, uuid
entity_ids = [
"550e8400-e29b-41d4-a716-446655440000",
"660f9511-f30c-23e5-b827-537766551111",
]
response = requests.post(
"https://api.kycgenie.com/api/v1/screening/batch/",
headers={
"Authorization": "Bearer YOUR_API_KEY",
"Idempotency-Key": str(uuid.uuid4()),
},
json={
"entity_ids": entity_ids,
"webhook_url": "https://your-domain.com/webhooks/batch",
},
)
job = response.json()
print(f"Job ID: {job['job_id']}, Total: {job['total_count']}")
from kycgenie import KYCGenie
client = KYCGenie(api_key="YOUR_API_KEY")
job = client.screening.batch_screen(
entity_ids=[
"550e8400-e29b-41d4-a716-446655440000",
"660f9511-f30c-23e5-b827-537766551111",
],
webhook_url="https://your-domain.com/webhooks/batch",
webhook_progress=True,
)
print(f"Job ID: {job.job_id}, Total: {job.total_count}")
# Poll for status
status = client.screening.get_batch_status(job_id=job.job_id)
print(f"Progress: {status.processed_count}/{status.total_count}")
const res = await fetch("https://api.kycgenie.com/api/v1/screening/batch/", {
method: "POST",
headers: {
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
"Idempotency-Key": crypto.randomUUID(),
},
body: JSON.stringify({
entity_ids: [
"550e8400-e29b-41d4-a716-446655440000",
"660f9511-f30c-23e5-b827-537766551111",
],
webhook_url: "https://your-domain.com/webhooks/batch",
}),
});
const job = await res.json();
console.log(`Job ID: ${job.job_id}`);
const res = await fetch("https://api.kycgenie.com/api/v2/screening/batch/", {
method: "POST",
headers: {
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
"Idempotency-Key": crypto.randomUUID(),
},
body: JSON.stringify({
entity_ids: [
"550e8400-e29b-41d4-a716-446655440000",
"660f9511-f30c-23e5-b827-537766551111",
],
webhook_url: "https://your-domain.com/webhooks/batch",
}),
});
const job = await res.json();
console.log(`Job ID: ${job.job_id}`);
202 Accepted Response
{
"job_id": "a8d8f1e2-4c5e-4f6a-9b2c-3d4e5f6a7b8c",
"job_type": "screening_batch",
"status": "pending",
"total_count": 2,
"skipped_count": 0,
"skipped_entity_ids": [],
"message": "Screening 2 entities.",
"webhook_url": "https://your-domain.com/webhooks/batch",
"estimated_completion": "2026-01-28T10:30:45Z"
}
Batch Status Response
{
"job_id": "a8d8f1e2-4c5e-4f6a-9b2c-3d4e5f6a7b8c",
"job_type": "screening_batch",
"status": "processing",
"total_count": 2,
"processed_count": 1,
"failed_count": 0,
"progress_percentage": 50.0,
"created_at": "2026-01-28T10:30:00Z",
"started_at": "2026-01-28T10:30:15Z",
"completed_at": null,
"webhook_url": "https://your-domain.com/webhooks/batch"
}
Maximum batch size is 10,000 entities. Entities already screened are automatically skipped and listed in skipped_entity_ids.
Ongoing Monitoring
Ongoing monitoring automatically re-screens an entity when their risk profile changes - for example, when they appear on a new sanctions list or are newly identified as a PEP.
/api/v2/screening/{entity_id}/monitoring/
Set monitoring to an explicit on/off state. This is idempotent - sending the same value twice has no additional effect.
Enabling monitoring for the first time charges a one-time monitoring credit. Toggling it off and back on does not incur an additional charge.
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
enabled | boolean | Yes | true to enable, false to disable |
Response Fields
| Field | Type | Description |
|---|---|---|
entity_id | uuid | Entity the monitoring state was updated for |
screening_id | uuid | Screening record updated |
monitoring_enabled | boolean | Current monitoring state after the update |
Enable Monitoring
curl -X PATCH https://api.kycgenie.com/api/v2/screening/550e8400-e29b-41d4-a716-446655440000/monitoring/ \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"enabled": true}'
import requests
entity_id = "550e8400-e29b-41d4-a716-446655440000"
# Note: monitoring endpoint is v2 only
response = requests.patch(
f"https://api.kycgenie.com/api/v2/screening/{entity_id}/monitoring/",
headers={"Authorization": "Bearer YOUR_API_KEY"},
json={"enabled": True},
)
result = response.json()
print(f"Monitoring enabled: {result['monitoring_enabled']}")
from kycgenie import KYCGenie
client = KYCGenie(api_key="YOUR_API_KEY")
result = client.screening.update_monitoring(
entity_id="550e8400-e29b-41d4-a716-446655440000",
enabled=True,
)
print(f"Monitoring enabled: {result.monitoring_enabled}")
// Note: monitoring endpoint is v2 only
const entityId = "550e8400-e29b-41d4-a716-446655440000";
const res = await fetch(
`https://api.kycgenie.com/api/v2/screening/${entityId}/monitoring/`,
{
method: "PATCH",
headers: {
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({ enabled: true }),
}
);
const result = await res.json();
console.log(`Monitoring enabled: ${result.monitoring_enabled}`);
Success Response (200 OK)
{
"entity_id": "550e8400-e29b-41d4-a716-446655440000",
"screening_id": "62ee34a4-28f0-4a83-a016-7441e7900d7e",
"monitoring_enabled": true
}