The KYC Genie API
Full programmatic control over your due diligence pipeline. Create entities, build and send KYC questionnaires, capture responses, run sanctions and PEP screening, and automate approve/reject decisions - all via REST API. Use your test environment while you build, then switch to live when you're ready to ship. Python SDK available now, with more languages on the way.
Make your first call
1. Get your API key
- Log in to your KYC Genie account.
- To use the test environment, click your profile in the top right and select Switch to Test. Your dashboard will switch to the test environment.
- Go to Settings → API Keys and create a new key. Keys created in the test environment never charge credits. Some features will be simulated and return mock data such as Screenings or Verifications, but you can build and test your integration end-to-end without worrying about costs or affecting real customers.
-
When you're ready for production, switch back to your live environment
and create a
kycg_live_key the same way.
All data is completely isolated between them. Build and verify everything in test before switching your key.
2. Install
Python 3.10 or higher required.
Install
pip install kycgenie
3. Set your key
Never hardcode API keys in source. Set it as an environment variable:
Environment variable
export API_KEY="kycg_test_your_key_here"
Not using Python? Switch to the cURL or JavaScript tabs on the right - the same pattern applies to any language or HTTP tool.
List your questionnaire templates
from kycgenie import KYCGenie
client = KYCGenie(api_key="YOUR_API_KEY")
result = client.questionnaire_templates.list()
for t in result.results:
print(f"{t.name} ({t.uuid}) - {t.question_count} questions")
curl https://api.kycgenie.com/api/v1/questionnaires/ \
-H "Authorization: Bearer $API_KEY"
const resp = await fetch(
'https://api.kycgenie.com/api/v1/questionnaires/',
{
headers: {
Authorization: 'Bearer YOUR_API_KEY'
}
}
);
const data = await resp.json();
data.results.forEach(t => console.log(t.id, t.name));
Response
{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"id": 55,
"name": "Standard DDQ",
"questionnaire_type": "ddq",
"question_count": 42,
"is_active": true
}
]
}
Authentication error
{
"detail": "Authentication credentials were not provided."
}
HTTP 401. Check that your key is set correctly and that you're using the right environment's key.
Errors
Every error response from the API uses the same envelope, regardless of
the endpoint. Check the HTTP status code first, then use code
to branch in your code.
| Field | Type | Description |
|---|---|---|
error |
string | Human-readable summary of what went wrong. |
code |
string | Machine-readable error code - safe to switch on. |
request_id |
string | Include this when contacting support to correlate logs. |
errors |
object | Field-level validation messages, keyed by field name. Only present on validation_error. |
details |
object | Extra context to help you act on the error - e.g. the conflicting resource ID on a 409, or the current status on an invalid state transition. Shape varies by error; present when there is actionable context beyond error and code. |
| HTTP status | code | Meaning |
|---|---|---|
| 400 | validation_error | Request body failed validation - check errors. |
| 400 | invalid_request | Request is structurally valid but logically invalid (e.g. wrong state, unsupported operation) - check details. |
| 401 | authentication_failed | Missing or invalid API key. |
| 402 | insufficient_credits | Your account has no remaining credits. |
| 403 | permission_denied | Your key doesn't have access to this resource. |
| 404 | not_found | Resource doesn't exist or isn't accessible to your tenant. |
| 409 | conflict | Action conflicts with current state - check details. |
| 409 | idempotency_conflict | Same Idempotency-Key reused with a different request body. |
| 429 | rate_limited | Too many requests - back off and retry. |
| 500 | server_error | Something went wrong on our end. |
| 502 | upstream_error | An external service (e.g. a webhook endpoint) returned an error or was unreachable - check details. |
Authentication error (401)
{
"error": "Authentication credentials were not provided.",
"code": "authentication_failed",
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}
Validation error (400)
{
"error": "Validation failed.",
"code": "validation_error",
"request_id": "550e8400-e29b-41d4-a716-446655440001",
"errors": {
"legal_name": ["This field is required."],
"entity_type": ["Must be 'company' or 'individual'."]
}
}
Invalid request (400) - with details
{
"error": "This response has already been submitted and cannot be modified.",
"code": "invalid_request",
"request_id": "550e8400-e29b-41d4-a716-446655440003",
"details": {
"current_status": "submitted"
}
}
Conflict error (409)
{
"error": "A check is already in progress.",
"code": "conflict",
"request_id": "550e8400-e29b-41d4-a716-446655440002",
"details": {
"existing_check_id": "d67177bf-6871-45bf-85f2-95a1e52ccc64",
"status": "pending"
}
}