Non-Document Verification API
Verify individual identities using credit bureaus and government databases without requiring document uploads. Non-document checks validate identity against multiple authoritative sources in real-time.
Non-document verification checks validate identity against credit bureaus and government databases. No document upload required - verification uses name, date of birth, and address data.
Key Features
- Multi-bureau validation - Check against multiple credit bureaus simultaneously
- 2+2 verification - Require 2 identity matches + 2 address matches for higher confidence
- No document upload - Frictionless verification using existing data
- Real-time webhooks - Instant notifications when checks complete
Non-Document Check Object
A non-document check represents a non-document verification workflow that validates identity against credit bureaus and government databases.
Core Attributes
| Field | Type | Description |
|---|---|---|
check_id |
uuid | Unique identifier for the non-document check |
entity_id |
uuid | ID of the individual entity being verified |
entity_name |
string | Name of the individual being verified |
status |
string | Check state: pending, in_progress, completed, failed, error |
outcome |
string | Verification result: pending, clear, consider, attention, error |
two_plus_two |
boolean | Whether 2+2 verification is enabled (2 identity + 2 address matches required) |
failure_details |
string | Detailed explanation if check did not pass |
created_at |
datetime | Check creation timestamp (ISO 8601) |
completed_at |
datetime | Check completion timestamp (ISO 8601), null if not completed |
created_by |
object | Profile who initiated the check (id, name, email) |
Status Values
| Status | Description |
|---|---|
pending |
Check created but not yet submitted to provider |
in_progress |
Check submitted and awaiting results |
completed |
Check finished with results available |
failed |
Check could not be completed (data issues, etc.) |
error |
System error occurred during check processing |
Outcome Values
| Outcome | Description |
|---|---|
pending |
Check not yet completed |
clear |
Identity verified successfully - all checks passed |
consider |
Partial matches found - manual review recommended |
attention |
Identity could not be verified - manual review required |
error |
Technical error prevented verification |
Check Eligibility
/api/v2/non-document/eligibility/
Verify that an entity has the required data to perform a non-document check. This endpoint validates entity type, required fields, and complete address information.
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
entity_id |
uuid | Yes | ID of entity to check eligibility for |
Check Eligibility
curl -X POST https://api.kycgenie.com/api/v1/non-document/eligibility/ \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"entity_id":"550e8400-e29b-41d4-a716-446655440000"}'
curl -X POST https://api.kycgenie.com/api/v2/non-document/eligibility/ \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"entity_id":"550e8400-e29b-41d4-a716-446655440000"}'
import requests
resp = requests.post(
"https://api.kycgenie.com/api/v2/non-document/eligibility/",
headers={"Authorization": "Bearer YOUR_API_KEY"},
json={"entity_id": "550e8400-e29b-41d4-a716-446655440000"},
)
print(resp.json())
from kycgenie import KYCGenie
client = KYCGenie(api_key="YOUR_API_KEY")
result = client.non_document_checks.check_eligibility(
entity_id="550e8400-e29b-41d4-a716-446655440000",
)
print(result.eligible, result.reason)
const resp = await fetch('https://api.kycgenie.com/api/v1/non-document/eligibility/', {
method: 'POST',
headers: { 'Authorization': 'Bearer YOUR_API_KEY', 'Content-Type': 'application/json' },
body: JSON.stringify({ entity_id: '550e8400-e29b-41d4-a716-446655440000' }),
});
console.log(await resp.json());
const resp = await fetch('https://api.kycgenie.com/api/v2/non-document/eligibility/', {
method: 'POST',
headers: { 'Authorization': 'Bearer YOUR_API_KEY', 'Content-Type': 'application/json' },
body: JSON.stringify({ entity_id: '550e8400-e29b-41d4-a716-446655440000' }),
});
console.log(await resp.json());
Eligible Response
{
"eligible": true,
"reason": "Entity meets all requirements for non-document verification",
"entity_id": "550e8400-e29b-41d4-a716-446655440000",
"entity_type": "individual",
"missing_fields": []
}
Not Eligible Response
{
"eligible": false,
"reason": "Entity data is incomplete",
"entity_id": "550e8400-e29b-41d4-a716-446655440000",
"entity_type": "individual",
"missing_fields": ["date_of_birth", "national_id_number", "address_postal_code"]
}
Initiate Non-Document Check
/api/v2/non-document/checks/
Initiate a new non-document identity verification check for an individual entity. The check is processed asynchronously and returns a webhook notification when it completes.
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
entity_id |
uuid | Yes | ID of individual entity to verify |
two_plus_two |
boolean | No | Enable 2+2 verification. Default: false |
Initiate Check
curl -X POST https://api.kycgenie.com/api/v1/non-document/checks/ \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"entity_id":"550e8400-e29b-41d4-a716-446655440000","two_plus_two":true}'
curl -X POST https://api.kycgenie.com/api/v2/non-document/checks/ \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"entity_id":"550e8400-e29b-41d4-a716-446655440000","two_plus_two":true}'
import requests
resp = requests.post(
"https://api.kycgenie.com/api/v2/non-document/checks/",
headers={"Authorization": "Bearer YOUR_API_KEY"},
json={"entity_id": "550e8400-e29b-41d4-a716-446655440000", "two_plus_two": True},
)
print(resp.json())
from kycgenie import KYCGenie
client = KYCGenie(api_key="YOUR_API_KEY")
check = client.non_document_checks.initiate(
entity_id="550e8400-e29b-41d4-a716-446655440000",
two_plus_two=True,
)
print(f"Check ID: {check.check_id}, Status: {check.status}")
const resp = await fetch('https://api.kycgenie.com/api/v1/non-document/checks/', {
method: 'POST',
headers: { 'Authorization': 'Bearer YOUR_API_KEY', 'Content-Type': 'application/json' },
body: JSON.stringify({ entity_id: '550e8400-e29b-41d4-a716-446655440000', two_plus_two: true }),
});
console.log(await resp.json());
const resp = await fetch('https://api.kycgenie.com/api/v2/non-document/checks/', {
method: 'POST',
headers: { 'Authorization': 'Bearer YOUR_API_KEY', 'Content-Type': 'application/json' },
body: JSON.stringify({ entity_id: '550e8400-e29b-41d4-a716-446655440000', two_plus_two: true }),
});
console.log(await resp.json());
Response Example
{
"check_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"entity_id": "550e8400-e29b-41d4-a716-446655440000",
"entity_name": "John Smith",
"status": "in_progress",
"outcome": "pending",
"two_plus_two": true,
"created_at": "2026-01-31T10:30:00Z",
"created_by": {"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "name": "Jane Doe", "email": "jane.doe@example.com"}
}
Error Response - Not Eligible
{
"error": "Entity is not eligible for non-document check",
"detail": "Entity data is incomplete. Missing: date_of_birth, national_id_number",
"missing_fields": ["date_of_birth", "national_id_number"],
"entity_id": "550e8400-e29b-41d4-a716-446655440000"
}
Error Response - Check In Progress
{
"error": "Non-document check already in progress",
"detail": "An active check exists for this entity",
"existing_check_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"status": "in_progress",
"created_at": "2026-01-31T10:15:00Z"
}
Get Check Status
/api/v2/non-document/checks/{check_id}/
Retrieve current status and basic information for a non-document check. Use this endpoint to poll for completion or check current state.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
check_id |
uuid | ID of the non-document check |
Get Check Status
curl https://api.kycgenie.com/api/v1/non-document/checks/7c9e6679-7425-40de-944b-e07fc1f90ae7/ \
-H "Authorization: Bearer YOUR_API_KEY"
curl https://api.kycgenie.com/api/v2/non-document/checks/7c9e6679-7425-40de-944b-e07fc1f90ae7/ \
-H "Authorization: Bearer YOUR_API_KEY"
import requests
resp = requests.get(
"https://api.kycgenie.com/api/v2/non-document/checks/7c9e6679-7425-40de-944b-e07fc1f90ae7/",
headers={"Authorization": "Bearer YOUR_API_KEY"},
)
print(resp.json())
from kycgenie import KYCGenie
client = KYCGenie(api_key="YOUR_API_KEY")
check = client.non_document_checks.get_check(
check_id="7c9e6679-7425-40de-944b-e07fc1f90ae7",
)
print(f"Status: {check.status}, Outcome: {check.outcome}")
const resp = await fetch(
'https://api.kycgenie.com/api/v1/non-document/checks/7c9e6679-7425-40de-944b-e07fc1f90ae7/',
{ headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
);
console.log(await resp.json());
const resp = await fetch(
'https://api.kycgenie.com/api/v2/non-document/checks/7c9e6679-7425-40de-944b-e07fc1f90ae7/',
{ headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
);
console.log(await resp.json());
Response Example
{
"check_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"entity_id": "550e8400-e29b-41d4-a716-446655440000",
"entity_name": "John Smith",
"status": "completed",
"outcome": "clear",
"two_plus_two": true,
"failure_details": "",
"created_at": "2026-01-31T10:30:00Z",
"completed_at": "2026-01-31T10:32:15Z",
"created_by": {"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "name": "Jane Doe", "email": "jane.doe@example.com"}
}
Get Detailed Results
/api/v2/non-document/checks/{check_id}/results/
Retrieve detailed non-document check results including bureau breakdown, match details, and credit scores. Only available when check status is completed.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
check_id |
uuid | ID of the non-document check |
Get Detailed Results
curl https://api.kycgenie.com/api/v1/non-document/checks/7c9e6679-7425-40de-944b-e07fc1f90ae7/results/ \
-H "Authorization: Bearer YOUR_API_KEY"
curl https://api.kycgenie.com/api/v2/non-document/checks/7c9e6679-7425-40de-944b-e07fc1f90ae7/results/ \
-H "Authorization: Bearer YOUR_API_KEY"
import requests
resp = requests.get(
"https://api.kycgenie.com/api/v2/non-document/checks/7c9e6679-7425-40de-944b-e07fc1f90ae7/results/",
headers={"Authorization": "Bearer YOUR_API_KEY"},
)
print(resp.json())
from kycgenie import KYCGenie
client = KYCGenie(api_key="YOUR_API_KEY")
results = client.non_document_checks.get_check_results(
check_id="7c9e6679-7425-40de-944b-e07fc1f90ae7",
)
print(results.outcome, results.full_check_data)
const resp = await fetch(
'https://api.kycgenie.com/api/v1/non-document/checks/7c9e6679-7425-40de-944b-e07fc1f90ae7/results/',
{ headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
);
console.log(await resp.json());
const resp = await fetch(
'https://api.kycgenie.com/api/v2/non-document/checks/7c9e6679-7425-40de-944b-e07fc1f90ae7/results/',
{ headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
);
console.log(await resp.json());
Response Example
{
"check_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"entity_id": "550e8400-e29b-41d4-a716-446655440000",
"entity_name": "John Smith",
"status": "completed",
"outcome": "clear",
"two_plus_two": true,
"result_data": {"id": "64a9f2f8b5e1a3d2c4e7f9a1", "outcome": "clear"},
"full_check_data": {"id": "64a9f2f8b5e1a3d2c4e7f9a1", "type": "non_document_check", "status": "complete", "result": {"outcome": "clear", "breakdown": {"identity_match": {"score": 95, "matches": 2, "sources": ["Experian", "Equifax"]}, "address_match": {"score": 92, "matches": 2, "sources": ["TransUnion", "USPS"]}, "credit_score": 750, "account_age_months": 84, "verification_level": "high"}}, "entityName": "John Smith", "createdAt": "2026-01-31T10:30:00Z", "updatedAt": "2026-01-31T10:32:15Z"},
"failure_details": "",
"created_at": "2026-01-31T10:30:00Z",
"completed_at": "2026-01-31T10:32:15Z",
"created_by": {"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "name": "Jane Doe", "email": "jane.doe@example.com"},
"cached": false
}
Error Response - Not Completed
{
"error": "Check not completed yet",
"detail": "Check status is in_progress. Results are only available for completed checks.",
"check_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"status": "in_progress"
}
List Entity Checks
/api/v2/entities/{entity_id}/non-document-checks/
Retrieve all non-document checks for a specific entity, ordered by creation date (newest first).
Path Parameters
| Parameter | Type | Description |
|---|---|---|
entity_id |
uuid | ID of the entity |
List Entity Checks
curl https://api.kycgenie.com/api/v1/entities/550e8400-e29b-41d4-a716-446655440000/non-document-checks/ \
-H "Authorization: Bearer YOUR_API_KEY"
curl https://api.kycgenie.com/api/v2/entities/550e8400-e29b-41d4-a716-446655440000/non-document-checks/ \
-H "Authorization: Bearer YOUR_API_KEY"
import requests
resp = requests.get(
"https://api.kycgenie.com/api/v2/entities/550e8400-e29b-41d4-a716-446655440000/non-document-checks/",
headers={"Authorization": "Bearer YOUR_API_KEY"},
)
print(resp.json())
from kycgenie import KYCGenie
client = KYCGenie(api_key="YOUR_API_KEY")
data = client.non_document_checks.list(
entity_id="550e8400-e29b-41d4-a716-446655440000",
)
const resp = await fetch(
'https://api.kycgenie.com/api/v1/entities/550e8400-e29b-41d4-a716-446655440000/non-document-checks/',
{ headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
);
console.log(await resp.json());
const resp = await fetch(
'https://api.kycgenie.com/api/v2/entities/550e8400-e29b-41d4-a716-446655440000/non-document-checks/',
{ headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
);
console.log(await resp.json());
Response Example
{
"count": 3,
"entity_id": "049f7df7-0321-43d7-ba71-4f8bdf7bbf0e",
"entity_name": "John Smith",
"results": [
{
"check_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"entity_name": "John Smith",
"status": "completed",
"outcome": "attention",
"two_plus_two": false,
"created_at": "2026-03-15T09:12:44.000000Z",
"completed_at": "2026-03-15T09:13:02.000000Z",
"created_by_name": "Jane Doe"
},
{
"check_id": "8d0e7780-8536-51ef-b55f-f18gd2g01bf8",
"entity_name": "John Smith",
"status": "completed",
"outcome": "clear",
"two_plus_two": false,
"created_at": "2026-02-28T14:05:10.000000Z",
"completed_at": "2026-02-28T14:05:31.000000Z",
"created_by_name": "Jane Doe"
},
{
"check_id": "3a1b2c3d-4e5f-6789-abcd-ef0123456789",
"entity_name": "John Smith",
"status": "error",
"outcome": "pending",
"two_plus_two": false,
"created_at": "2026-01-10T11:00:00.000000Z",
"completed_at": null,
"created_by_name": "Jane Doe"
}
]
}
Submit Review Decision
/api/v2/non-document/checks/{check_id}/reviews/create/
Submit a manual review decision for a non-document check. Allows compliance and risk teams to override or confirm automated outcomes.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
check_id |
uuid | ID of the non-document check to review |
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
decision | string | Yes | Review decision: approved, rejected, or flagged |
notes | string | Yes | Detailed explanation for the decision (minimum 10 characters) |
Submit Review
curl -X POST https://api.kycgenie.com/api/v1/non-document/checks/7c9e6679-7425-40de-944b-e07fc1f90ae7/reviews/create/ \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"decision":"approved","notes":"Manual review confirms identity matches. No adverse findings in credit history."}'
curl -X POST https://api.kycgenie.com/api/v2/non-document/checks/7c9e6679-7425-40de-944b-e07fc1f90ae7/reviews/create/ \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"decision":"approved","notes":"Manual review confirms identity matches. No adverse findings in credit history."}'
import requests
resp = requests.post(
"https://api.kycgenie.com/api/v2/non-document/checks/7c9e6679-7425-40de-944b-e07fc1f90ae7/reviews/create/",
headers={"Authorization": "Bearer YOUR_API_KEY"},
json={
"decision": "approved",
"notes": "Manual review confirms identity matches. No adverse findings in credit history.",
},
)
print(resp.json())
from kycgenie import KYCGenie
client = KYCGenie(api_key="YOUR_API_KEY")
review = client.non_document_checks.submit_review(
check_id="7c9e6679-7425-40de-944b-e07fc1f90ae7",
decision="approved",
notes="Manual review confirms identity matches. No adverse findings in credit history.",
)
print(f"Review ID: {review.review_id}, Outcome: {review.check_outcome}")
const resp = await fetch(
'https://api.kycgenie.com/api/v1/non-document/checks/7c9e6679-7425-40de-944b-e07fc1f90ae7/reviews/create/',
{
method: 'POST',
headers: { 'Authorization': 'Bearer YOUR_API_KEY', 'Content-Type': 'application/json' },
body: JSON.stringify({ decision: 'approved', notes: 'Manual review confirms identity matches. No adverse findings in credit history.' }),
}
);
console.log(await resp.json());
const resp = await fetch(
'https://api.kycgenie.com/api/v2/non-document/checks/7c9e6679-7425-40de-944b-e07fc1f90ae7/reviews/create/',
{
method: 'POST',
headers: { 'Authorization': 'Bearer YOUR_API_KEY', 'Content-Type': 'application/json' },
body: JSON.stringify({ decision: 'approved', notes: 'Manual review confirms identity matches. No adverse findings in credit history.' }),
}
);
console.log(await resp.json());
Response Example
{
"review_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"check_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"decision": "approved",
"notes": "Manual review confirms identity matches. No adverse findings in credit history.",
"reviewed_by": {"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "name": "Jane Doe", "email": "jane.doe@example.com"},
"reviewed_at": "2026-01-31T11:00:00Z",
"check_outcome": "clear"
}
Error Response - Invalid Notes
{
"notes": ["Ensure this field has at least 10 characters."]
}
List Check Reviews
/api/v2/non-document/checks/{check_id}/reviews/
Retrieve all manual reviews submitted for a specific non-document check, ordered by review date (newest first).
Path Parameters
| Parameter | Type | Description |
|---|---|---|
check_id |
uuid | ID of the non-document check |
List Reviews
curl https://api.kycgenie.com/api/v1/non-document/checks/7c9e6679-7425-40de-944b-e07fc1f90ae7/reviews/ \
-H "Authorization: Bearer YOUR_API_KEY"
curl https://api.kycgenie.com/api/v2/non-document/checks/7c9e6679-7425-40de-944b-e07fc1f90ae7/reviews/ \
-H "Authorization: Bearer YOUR_API_KEY"
import requests
resp = requests.get(
"https://api.kycgenie.com/api/v2/non-document/checks/7c9e6679-7425-40de-944b-e07fc1f90ae7/reviews/",
headers={"Authorization": "Bearer YOUR_API_KEY"},
)
print(resp.json())
from kycgenie import KYCGenie
client = KYCGenie(api_key="YOUR_API_KEY")
data = client.non_document_checks.list_reviews(
check_id="7c9e6679-7425-40de-944b-e07fc1f90ae7",
)
for review in data.reviews:
print(f"{review.decision} by {review.reviewed_by_name}")
const resp = await fetch(
'https://api.kycgenie.com/api/v1/non-document/checks/7c9e6679-7425-40de-944b-e07fc1f90ae7/reviews/',
{ headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
);
console.log(await resp.json());
const resp = await fetch(
'https://api.kycgenie.com/api/v2/non-document/checks/7c9e6679-7425-40de-944b-e07fc1f90ae7/reviews/',
{ headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
);
console.log(await resp.json());
Response Example
{
"count": 1,
"check_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"entity_id": "550e8400-e29b-41d4-a716-446655440000",
"entity_name": "John Smith",
"results": [
{"review_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "decision": "approved", "notes": "Manual review confirms identity matches. No adverse findings in credit history.", "reviewed_by_name": "Jane Doe", "reviewed_at": "2026-03-15T09:20:00Z"}
]
}
Webhook Events
Non-document checks trigger webhook events at key points in the verification lifecycle. Configure webhooks in your webhook settings.
Available Events
| Event Type | Description | Trigger |
|---|---|---|
non_document.check_initiated | Check has been initiated | When check is successfully submitted to verification provider |
non_document.check_completed | Check has completed | When verification provider completes the check with results |
non_document.check_failed | Check failed | When check cannot be completed due to data issues or errors |
non_document.reviewed | Manual review submitted | When a compliance/risk team member submits a review decision |
Webhook Payload - Check Completed
{
"event": "non_document.check_completed",
"timestamp": "2026-01-31T10:32:15Z",
"data": {"check_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7", "entity_id": "550e8400-e29b-41d4-a716-446655440000", "status": "completed", "outcome": "clear", "two_plus_two": true, "completed_at": "2026-01-31T10:32:15Z"}
}
Webhook Payload - Review Submitted
{
"event": "non_document.reviewed",
"timestamp": "2026-01-31T11:00:00Z",
"data": {"check_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7", "entity_id": "550e8400-e29b-41d4-a716-446655440000", "review_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "decision": "approved", "outcome": "clear", "reviewed_at": "2026-01-31T11:00:00Z"}
}
Rate Limits
All non-document check endpoints are subject to your plan's rate limits. Limits are enforced at two levels:
- Burst limit - maximum requests per minute across all API endpoints, based on your subscription plan.
- Hourly limit - total requests per hour across all API endpoints, based on your subscription plan.
Rate limit headers are returned on every response. If you exceed your limit, requests return 429 Too Many Requests until the window resets.
Contact support@kycgenie.com if you need higher limits.
Rate Limit Headers
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 995
X-RateLimit-Reset: 1706699460
Exceeded Rate Limit Response
{
"error": "rate_limit_exceeded",
"code": "RATE_LIMIT_EXCEEDED",
"message": "You have exceeded your plan's rate limit. Please try again later.",
"details": {}
}