VerifyTrust — Stateless Screening API
VerifyTrust provides AML, PEP, sanctions, RCA, and watchlist screening signals through a privacy-first API.
VerifyTrust does not make final compliance decisions, manage cases, file SARs, store customer screening profiles, or replace a regulated compliance program. Clients remain responsible for final review, escalation, retention, and regulatory obligations.
Looking for the original KYC + screening flow? That endpoint (
POST /api/kyc/v1/submit_plus) and its companionPOST /api/kyc/v1/generate_reportare unchanged. The new API documented here is a separate, additive surface.
Endpoints
| Method | Path | Purpose |
|---|---|---|
| POST | /api/compliance/v1/screen |
Stateless individual screening |
| POST | /api/compliance/v1/rescreen |
Stateless re-screening of a subject without VerifyHuman holding the prior subject profile |
Both endpoints require an API key with the verifycompliance scope
(X-API-Key header), and bill against your VerifyTrust plan via
the existing per-attempt billing system.
| Endpoint | Default credit cost |
|---|---|
| screen | 60 credits |
| rescreen | 30 credits |
Authentication failures, validation failures, and pre-provider 5xx errors are not billed. Provider unavailability is recorded as a non-billable attempt.
Decision language
The new API uses a screening-signal decision enum, never a final compliance outcome:
| Score range | Level | Decision |
|---|---|---|
| 0–29 | low |
clear |
| 30–59 | medium |
review |
| 60–100 | high |
high_risk_review |
Words like approved, rejected, pass, and fail are deliberately
never emitted by this layer.
POST /api/compliance/v1/screen
Request
POST /api/compliance/v1/screen
X-API-Key: vhk-...
Content-Type: application/json
{
"client_reference_id": "customer_123",
"subject": {
"type": "individual",
"first_name": "Jane",
"last_name": "Doe",
"date_of_birth": "1985-04-12",
"gender": "female",
"country": "US"
},
"screening": {
"lists": ["sanctions", "pep", "rca", "wanted"],
"provider": "default"
},
"metadata": {
"workflow": "onboarding"
}
}
| Field | Required | Notes |
|---|---|---|
subject.type |
yes | Must be individual in this phase. |
subject.first_name |
yes | |
subject.last_name |
yes | |
subject.date_of_birth |
no | YYYY-MM-DD if present. |
subject.gender |
no | |
subject.country |
no | ISO-3166 alpha-2 if present (e.g. US). |
client_reference_id |
no | Opaque client identifier; treated as a reference. |
screening.lists |
no | Subset of sanctions, pep, rca, wanted. |
screening.provider |
no | default (recommended). Contact support for alternative providers. |
metadata |
no | Flat key/value bag, scrubbed for obvious PII. |
Response — clear result
{
"id": "vcmp_01HXX...",
"object": "compliance.screening",
"livemode": true,
"created": 1777057500,
"status": "completed",
"client_reference_id": "customer_123",
"subject_type": "individual",
"provider": {
"normalized": true,
"raw_response_included": false
},
"screening": {
"lists_checked": ["sanctions", "pep", "rca", "wanted"],
"screened_at": "2026-04-24T00:00:00Z",
"search_mode": "standard",
"provider_reference_id": null
},
"risk": {
"score": 0,
"level": "low",
"decision": "clear",
"reasons": []
},
"matches": [],
"flags": [],
"data_retention": {
"input_payload_stored": false,
"result_payload_stored": false,
"raw_provider_response_stored": false,
"biometric_media_stored": false,
"retention_model": "ephemeral_processing_only"
},
"metadata": { "workflow": "onboarding" }
}
Response — PEP review
{
"id": "vcmp_01HXX...",
"object": "compliance.screening",
"status": "completed",
"risk": {
"score": 45,
"level": "medium",
"decision": "review",
"reasons": ["pep_possible_match"]
},
"flags": ["PEP_POSSIBLE_MATCH"]
}
Response — sanctions high-risk review
{
"id": "vcmp_01HXX...",
"object": "compliance.screening",
"status": "completed",
"risk": {
"score": 85,
"level": "high",
"decision": "high_risk_review",
"reasons": ["sanctions_strong_match"]
},
"flags": ["SANCTIONS_STRONG_MATCH"]
}
Errors
{
"error": {
"type": "invalid_request",
"code": "invalid_subject",
"message": "The subject payload is invalid."
}
}
{
"error": {
"type": "provider_unavailable",
"code": "compliance_provider_unavailable",
"message": "Compliance screening provider is temporarily unavailable."
}
}
Validation errors never echo PII — they reference field names only.
Stateless Re-screening
VerifyHuman does not store customer screening profiles. To re-screen a subject, the client sends the subject payload again along with the previous screening ID or previous result summary. VerifyHuman re-runs the screening and returns a new result.
POST /api/compliance/v1/rescreen
{
"previous_screening_id": "vcmp_01HXOLD",
"client_reference_id": "customer_123",
"subject": {
"type": "individual",
"first_name": "Jane",
"last_name": "Doe",
"date_of_birth": "1985-04-12",
"gender": "female",
"country": "US"
},
"screening": {
"lists": ["sanctions", "pep", "rca", "wanted"],
"reason": "periodic_rescreen",
"provider": "default"
},
"previous_result_summary": {
"risk_score": 12,
"risk_level": "low",
"flags": []
},
"metadata": { "workflow": "quarterly_refresh" }
}
screening.reason must be one of:
periodic_rescreenmanual_reviewcustomer_updateregulatory_refreshwebhook_retry
The response is identical to /screen plus an additional rescreen
block:
"rescreen": {
"previous_screening_id": "vcmp_01HXOLD",
"reason": "periodic_rescreen",
"risk_change": "risk_increased"
}
risk_change is one of risk_increased, risk_decreased,
risk_unchanged, or unknown_without_prior_result (when no
previous_result_summary is supplied).
Webhooks
The new stateless endpoints emit four additive webhook event types:
| Event | When |
|---|---|
compliance.screening.completed |
/api/compliance/v1/screen succeeded |
compliance.screening.failed |
/api/compliance/v1/screen failed after auth + validation (e.g. provider unavailable) |
compliance.rescreen.completed |
/api/compliance/v1/rescreen succeeded |
compliance.rescreen.risk_changed |
rescreen succeeded and risk_change is risk_increased or risk_decreased (never for risk_unchanged or unknown_without_prior_result) |
These are delivery notifications for screening results — they do not create a compliance workflow, case record, or customer profile inside VerifyHuman. Webhook payloads are generated from the same public-safe response returned by the API. They do not include the subject payload, raw provider responses, or watchlist source records.
Subscribe to these event types from your existing webhook endpoint
(Dashboard → Webhooks). All payloads use the standard VerifyHuman
HMAC-SHA256 signing scheme. See
webhooks.md
for full payload examples, signature-verification helper code, and
replay-window guidance (5 minutes recommended).
Existing legacy VerifyTrust webhook events
(compliance.completed, compliance.hit_detected,
compliance.report_ready) remain unchanged and continue to flow from
the legacy KYC+ pipeline.
Privacy and data retention
Both new endpoints preserve VerifyHuman's data-processor posture:
- The subject payload exists only for the lifetime of the request.
- No subject data is stored.
- No raw provider response is stored or returned.
- No normalized result body is stored.
- Only the existing per-attempt billing log row is persisted.
client_reference_idis treated as opaque; it is not echoed into logs and should be treated by your application as potentially-PII.
The data_retention block on every response is a constant statement of
these facts.