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.

Client Report vs Assessment Report

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_generated webhook fires when complete, containing the document_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:

SectionSource
Subject & Report InfoEntity metadata
OverviewVerification session outcome & summary stats
Identity ChecksVerification session checks
AML ScreeningScreening summary, case findings, risk breakdown
Non-Document VerificationMulti-bureau check history & results
Related EntitiesDirectors, shareholders & UBOs (companies only)
Personal / Company InformationEntity fields & registered address
Reviewer NotesAnalyst review decisions & notes
Verified DocumentsIdentity 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.

POST /api/v2/entities/{entity_id}/report/generate/

Path Parameters

ParameterTypeDescription
entity_id uuid The entity to generate the report for

Request Body

No request body required.

Response Fields

FieldTypeDescription
statusstringAlways pending on initiation
messagestringHuman-readable confirmation
task_iduuidInternal trace reference - not needed for normal usage
entity_iduuidEchoed back for convenience
No polling required

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.

GET /api/v2/entities/{entity_id}/report/download/

Path Parameters

ParameterTypeDescription
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"
}