Reports API
Generate and download PDF compliance reports for entities. Reports aggregate all available due-diligence data - identity checks, AML screening, non-document verification, company information, related entities, and reviewer notes - into a single branded PDF.
The Client Report is entity-centric: it only needs an entity ID and
becomes richer as you add screenings, verifications, and checks. No DDQ required.
The Assessment Report (see Responses API)
is response-centric: it requires a submitted and auto-flagged DDQ and generates an
AI-written risk analysis in DOCX format.
Key Features
- No DDQ required - generate a report for any entity at any stage
- Async generation - reports are queued and generated in the background; no polling needed
- Progressive detail - the more data you add to an entity, the richer the report
- Webhook notification - a
report.client_report_generatedwebhook fires when complete, containing thedocument_id - Stored as a Document - the generated PDF is saved to the entity's documents and can be downloaded immediately after the webhook fires
Report Sections
The client report includes all sections where data is available:
| Section | Source |
|---|---|
| Subject & Report Info | Entity metadata |
| Overview | Verification session outcome & summary stats |
| Identity Checks | Verification session checks |
| AML Screening | Screening summary, case findings, risk breakdown |
| Non-Document Verification | Multi-bureau check history & results |
| Related Entities | Directors, shareholders & UBOs (companies only) |
| Personal / Company Information | Entity fields & registered address |
| Reviewer Notes | Analyst review decisions & notes |
| Verified Documents | Identity documents submitted during verification |
Generate Client Report
Queue PDF generation for an entity. Returns 202 Accepted immediately.
When complete, a report.client_report_generated webhook fires with the
document_id. Download the PDF using the endpoint below.
/api/v2/entities/{entity_id}/report/generate/
Path Parameters
| Parameter | Type | Description |
|---|---|---|
entity_id |
uuid | The entity to generate the report for |
Request Body
No request body required.
Response Fields
| Field | Type | Description |
|---|---|---|
status | string | Always pending on initiation |
message | string | Human-readable confirmation |
task_id | uuid | Internal trace reference - not needed for normal usage |
entity_id | uuid | Echoed back for convenience |
Listen for the report.client_report_generated webhook event instead of polling. The webhook payload contains document_id, entity_id, and entity_name.
Generate Report
curl -X POST https://api.kycgenie.com/api/v1/entities/550e8400-e29b-41d4-a716-446655440000/report/generate/ \
-H "Authorization: Bearer YOUR_API_KEY"
curl -X POST https://api.kycgenie.com/api/v2/entities/550e8400-e29b-41d4-a716-446655440000/report/generate/ \
-H "Authorization: Bearer YOUR_API_KEY"
import requests
resp = requests.post(
"https://api.kycgenie.com/api/v2/entities/550e8400-e29b-41d4-a716-446655440000/report/generate/",
headers={"Authorization": "Bearer YOUR_API_KEY"},
)
resp.raise_for_status() # 202 Accepted
# Wait for report.client_report_generated webhook to fire
from kycgenie import KYCGenie
client = KYCGenie(api_key="YOUR_API_KEY")
client.reports.generate(
entity_id="550e8400-e29b-41d4-a716-446655440000",
)
# Wait for report.client_report_generated webhook to fire
await fetch(
'https://api.kycgenie.com/api/v1/entities/550e8400-e29b-41d4-a716-446655440000/report/generate/',
{ method: 'POST', headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
);
// Wait for report.client_report_generated webhook to fire
await fetch(
'https://api.kycgenie.com/api/v2/entities/550e8400-e29b-41d4-a716-446655440000/report/generate/',
{ method: 'POST', headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
);
// Wait for report.client_report_generated webhook to fire
Response (202 Accepted)
{
"status": "pending",
"message": "Client report generation initiated",
"task_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"entity_id": "550e8400-e29b-41d4-a716-446655440000"
}
Download Client Report
Download the most recently generated client report for an entity as a PDF binary stream. A report must be generated first.
/api/v2/entities/{entity_id}/report/download/
Path Parameters
| Parameter | Type | Description |
|---|---|---|
entity_id |
uuid | The entity whose report to download |
Response
Returns the PDF as a binary stream with standard download headers.
Error Response
A 404 Not Found is returned when no client report has been generated yet for this entity.
Download Report
curl -O https://api.kycgenie.com/api/v1/entities/550e8400-e29b-41d4-a716-446655440000/report/download/ \
-H "Authorization: Bearer YOUR_API_KEY"
curl -O https://api.kycgenie.com/api/v2/entities/550e8400-e29b-41d4-a716-446655440000/report/download/ \
-H "Authorization: Bearer YOUR_API_KEY"
resp = requests.get(
"https://api.kycgenie.com/api/v2/entities/550e8400-e29b-41d4-a716-446655440000/report/download/",
headers={"Authorization": "Bearer YOUR_API_KEY"},
stream=True,
)
resp.raise_for_status()
with open("client_report.pdf", "wb") as f:
for chunk in resp.iter_content(chunk_size=8192):
f.write(chunk)
pdf_bytes = client.entities.get_client_report(
entity_id="550e8400-e29b-41d4-a716-446655440000",
)
with open("client_report.pdf", "wb") as f:
f.write(pdf_bytes)
const resp = await fetch(
'https://api.kycgenie.com/api/v1/entities/550e8400-e29b-41d4-a716-446655440000/report/download/',
{ headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
);
// resp is a PDF binary stream
console.log(resp.status);
const resp = await fetch(
'https://api.kycgenie.com/api/v2/entities/550e8400-e29b-41d4-a716-446655440000/report/download/',
{ headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
);
// resp is a PDF binary stream
console.log(resp.status);
Error - 404 Not Found
{
"error": "not_found",
"message": "No client report found for this entity.",
"details": {
"message": "Generate a client report first using POST /entities/{entity_id}/report/generate/"
}
}
Webhook Event
When a client report is successfully generated, KYC Genie fires a
report.client_report_generated event to all active webhook
subscriptions for your tenant. This means you can react to completion without polling.
See the Webhooks API for how to create a subscription and validate the HMAC signature.
Event Payload
{
"data": {
"document_id": "057b1101-f1cf-4820-b3c7-0cc69240c980",
"entity_id": "f719358d-580e-4ae9-8bb9-99d2b579146e",
"entity_name": "John Doe",
"object": "document",
"report_type": "client"
},
"event": "report.client_report_generated",
"timestamp": "2026-01-01T20:20:15.230825+00:00"
}