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.

Database-Driven Verification

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

POST /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

POST /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

GET /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

GET /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

GET /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

POST /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
decisionstringYesReview decision: approved, rejected, or flagged
notesstringYesDetailed 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

GET /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_initiatedCheck has been initiatedWhen check is successfully submitted to verification provider
non_document.check_completedCheck has completedWhen verification provider completes the check with results
non_document.check_failedCheck failedWhen check cannot be completed due to data issues or errors
non_document.reviewedManual review submittedWhen 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": {}
}