Installation
Requires Python 3.9+. The SDK uses httpx under the hood for both sync and async support.
Configuration
from verilock import Verilock
client = Verilock(
api_key="qi_live_...", # or set VERILOCK_API_KEY env var
base_url="https://verilock.io/api/v1", # optional
timeout=30, # optional, seconds (default: 30)
max_retries=2, # optional, retries on 429/5xx
)
Use a qi_test_ key during development. Test keys return simulated results and are free to use.
Quick Start
from verilock import Verilock
with Verilock(api_key="qi_live_...") as client:
# Create a KYC session
session = client.sessions.create({
"applicant_email": "john@example.com",
"applicant_name": "John Doe",
"redirect_url": "https://example.com/callback",
})
# Redirect the user to complete verification
print(session["session_url"])
# Later, retrieve the result
result = client.sessions.retrieve(session["id"])
print(result["status"]) # 'approved' | 'rejected' | 'pending' | ...
KYC Sessions
Create a session
session = client.sessions.create({
"applicant_email": "jane@example.com",
"applicant_name": "Jane Smith",
"redirect_url": "https://example.com/done",
})
# session["session_url"] -> hosted verification link
List sessions
response = client.sessions.list(status="approved", page=1, per_page=25)
for item in response["data"]:
print(f"{item['id']}: {item['status']}")
Retrieve a session
session = client.sessions.retrieve("sess_abc123")
Upload a document
with open("id_front.jpg", "rb") as f:
client.sessions.upload_document(
session_id="sess_abc123",
file=f.read(),
side="front",
document_type="passport",
)
Upload a selfie
with open("selfie.jpg", "rb") as f:
client.sessions.upload_selfie(session_id="sess_abc123", file=f.read())
Submit for evaluation
result = client.sessions.submit("sess_abc123")
print(result["status"]) # 'processing'
Call submit() only after all required documents and selfie have been uploaded. The session enters asynchronous processing and you will receive a webhook when it completes.
AML Screening
Screen a person
result = client.aml.screen({
"name": "John Doe",
"date_of_birth": "1990-01-15",
"nationality": "US",
})
if result["status"] == "match":
print(f"Found {result['matches_found']} matches")
Retrieve a screening
screening = client.aml.retrieve("aml_abc123")
Submit a decision
client.aml.decide("aml_abc123", {
"decision": "false_positive",
"reason": "Name similarity only, different date of birth.",
})
Transaction Monitoring
Screen a transaction
result = client.transactions.screen({
"transaction_ref": "TX-001",
"sender_name": "Alice Corp",
"receiver_name": "Bob Ltd",
"amount": 15000,
"currency": "USD",
})
if result["risk_level"] == "high":
print(f"{result['alerts_count']} alerts triggered")
Batch screening
batch = client.transactions.screen_batch({
"transactions": [
{"transaction_ref": "TX-002", "sender_name": "Alice", "receiver_name": "Bob", "amount": 500, "currency": "EUR"},
{"transaction_ref": "TX-003", "sender_name": "Carol", "receiver_name": "Dave", "amount": 12000, "currency": "USD"},
],
})
List, retrieve, and decide
response = client.transactions.list(risk_level="high")
detail = client.transactions.retrieve("txn_abc123")
client.transactions.decide("txn_abc123", {
"decision": "approve",
"reason": "Verified sender identity manually.",
})
Premium Features
Premium features require a paid plan. Calls made without an active subscription raise an InsufficientBalanceError.
# Biometric face authentication
match = client.biometric.verify(session_id="sess_abc123", selfie=selfie_bytes)
# Government database validation
db_check = client.database.validate(document_number="AB123456", country="US")
# 1:N face duplicate detection
duplicates = client.face_search.search(selfie=selfie_bytes)
# Crypto wallet compliance screening
wallet_result = client.wallet.screen(address="0xabc...", chain="ethereum")
# Reusable KYC credentials
credential = client.credentials.issue(session_id="sess_abc123")
# Age verification from selfie
age = client.age_verify.verify(selfie=selfie_bytes, min_age=18)
Error Handling
All SDK errors extend VerilockError. Use specific classes for granular handling.
from verilock.errors import (
VerilockError,
AuthenticationError,
InsufficientBalanceError,
NotFoundError,
ValidationError,
RateLimitError,
)
try:
session = client.sessions.create({
"applicant_email": "john@example.com",
"redirect_url": "https://example.com/callback",
})
except InsufficientBalanceError as e:
print(f"Balance: {e.balance}, required: {e.required}")
except ValidationError as e:
print(f"Field errors: {e.errors}")
except RateLimitError as e:
print(f"Retry after {e.retry_after}s")
except AuthenticationError:
print("Invalid API key")
except NotFoundError:
print("Resource not found")
except VerilockError as e:
print(f"API error [{e.code}]: {e.message}")
Context Managers
Both the sync and async clients support context managers that automatically close the underlying httpx connection pool.
from verilock import Verilock
with Verilock(api_key="qi_live_...") as client:
session = client.sessions.create({...})
# Connection pool is closed automatically
Using context managers is recommended to avoid resource leaks. Alternatively, call client.close() (or await client.close() for async) when you are done.