Entities API

Entities represent companies or individuals in your due diligence workflows. They are the subjects of KYC assessments, screening checks, and risk profiling.

Two Entity Types

Companies: Legal entities - corporations, LLCs, partnerships, funds, and more.
Individuals: Natural persons - directors, beneficial owners, controllers, and beneficiaries.

Entity Object

Fields returned by GET /entities/{entity_id}/. Company-specific and individual-specific fields are returned only for the relevant entity type.

Common fields (all entities)

FieldTypeDescription
iduuidUnique identifier
namestringComputed display name (auto-calculated; cannot be set directly)
entity_typestringcompany or individual. Immutable after creation.
entity_subtypestring | nullSub-classification. See Entity Subtypes.
external_idstring | nullYour internal reference ID for this entity
emailstringContact email address
phonestringContact phone number
address_line_1stringAddress line 1
address_line_2stringAddress line 2
address_citystringCity
address_statestringState / province
address_postal_codestringPostal / ZIP code
address_countrystringISO 3166-1 alpha-2 country code
is_primarybooleanWhether this is a primary entity for your tenant. Once set to true, cannot be demoted.
screening_statusstringLatest screening decision: not_screened, not_reviewed, pending, approved, conditional, rejected
response_countintegerNumber of DDQ responses linked to this entity
risk_profiles_countintegerNumber of risk profiles from screening
created_atdatetimeISO 8601 creation timestamp
updated_atdatetimeISO 8601 last-updated timestamp

Company-only fields

FieldTypeDescription
legal_namestringRegistered legal name
trading_namestringTrading / DBA name. Used as name when present.
registration_numberstringCompany registration / incorporation number
jurisdictionstringISO 3166-1 alpha-2 country of incorporation
incorporation_datedate | nullDate of incorporation (YYYY-MM-DD)

Individual-only fields

FieldTypeDescription
titlestringHonorific (Mr, Ms, Dr …)
first_namestringFirst / given name
middle_namestringMiddle name
last_namestringLast / family name
genderstringGender
date_of_birthdate | nullDate of birth (YYYY-MM-DD)
nationalitystringISO 3166-1 alpha-2 nationality code
country_of_birthstringISO 3166-1 alpha-2 country of birth
national_id_numberstringNational ID / passport number. Masked by default; use ?reveal_sensitive=true for full value.
tax_idstringTax identification number. Masked by default.
ssnstringSocial Security Number (US). Masked by default.
social_insurance_numberstringSocial Insurance Number (Canada). Masked by default.
Sensitive identity fields are masked by default

Fields national_id_number, tax_id, ssn, and social_insurance_number return only the last 4 characters unless you pass ?reveal_sensitive=true on a retrieve call. Every reveal access is audit-logged.

Create Entity

Create a new company or individual entity. The name field is computed automatically and cannot be set directly.

Request body

FieldTypeRequiredDescription
entity_typestringYescompany or individual. Immutable after creation.
legal_namestringCompany*Registered legal name
trading_namestringCompany*Trading / DBA name. Used as the entity's display name if provided.
first_namestringIndividualFirst name (required for individuals)
last_namestringIndividualLast name (required for individuals)
middle_namestringNoMiddle name
titlestringNoHonorific (Mr, Ms, Dr …)
genderstringNoGender
date_of_birthdateNoYYYY-MM-DD, must be in the past
incorporation_datedateNoYYYY-MM-DD
registration_numberstringNoCompany registration number
jurisdictionstringNoISO 3166-1 alpha-2 country code
nationalitystringNoISO 3166-1 alpha-2 nationality
country_of_birthstringNoISO 3166-1 alpha-2 country of birth
national_id_numberstringNoNational ID / passport number
tax_idstringNoTax identification number
ssnstringNoSocial Security Number (US)
social_insurance_numberstringNoSocial Insurance Number (Canada)
entity_subtypestringNoSee Entity Subtypes
emailstringNoContact email address
phonestringNoContact phone number
address_line_1stringNoAddress line 1
address_line_2stringNoAddress line 2
address_citystringNoCity
address_statestringNoState / province
address_postal_codestringNoPostal / ZIP code
address_countrystringNoISO 3166-1 alpha-2 country code
external_idstringNoYour internal reference ID (max 255 chars)
is_primarybooleanNoDefault true. Once set to true, cannot be demoted.

* For company entities, at least one of legal_name or trading_name is required. For individual entities, both first_name and last_name are required.

Use idempotency keys

Pass Idempotency-Key to safely retry without creating duplicate entities. The SDK auto-generates one if you don't provide it.

Create Company Entity

curl -X POST https://api.kycgenie.com/api/v1/entities/ \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: company-acme-12345678" \
  -d '{
    "entity_type": "company",
    "legal_name": "Acme Corporation Ltd",
    "trading_name": "Acme Corp",
    "entity_subtype": "Private Limited Company",
    "jurisdiction": "GB",
    "incorporation_date": "2020-01-15",
    "registration_number": "12345678",
    "address_line_1": "123 Business Street",
    "address_city": "London",
    "address_postal_code": "SW1A 1AA",
    "address_country": "GB",
    "email": "contact@acme.com",
    "is_primary": true
  }'
curl -X POST https://api.kycgenie.com/api/v2/entities/ \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: company-acme-12345678" \
  -d '{
    "entity_type": "company",
    "legal_name": "Acme Corporation Ltd",
    "trading_name": "Acme Corp",
    "entity_subtype": "Private Limited Company",
    "jurisdiction": "GB",
    "incorporation_date": "2020-01-15",
    "registration_number": "12345678",
    "address_line_1": "123 Business Street",
    "address_city": "London",
    "address_postal_code": "SW1A 1AA",
    "address_country": "GB",
    "email": "contact@acme.com",
    "is_primary": true
  }'
import requests

response = requests.post(
    "https://api.kycgenie.com/api/v1/entities/",
    headers={
        "Authorization": "Bearer YOUR_API_KEY",
        "Idempotency-Key": "company-acme-12345678",
    },
    json={
        "entity_type": "company",
        "legal_name": "Acme Corporation Ltd",
        "trading_name": "Acme Corp",
        "entity_subtype": "Private Limited Company",
        "jurisdiction": "GB",
        "incorporation_date": "2020-01-15",
        "registration_number": "12345678",
        "address_line_1": "123 Business Street",
        "address_city": "London",
        "address_postal_code": "SW1A 1AA",
        "address_country": "GB",
        "email": "contact@acme.com",
        "is_primary": True,
    },
)

entity = response.json()
print(f"Created: {entity['name']}")  # "Acme Corp"
from kycgenie import KYCGenie

client = KYCGenie(api_key="YOUR_API_KEY")

entity = client.entities.create(
    entity_type="company",
    legal_name="Acme Corporation Ltd",
    trading_name="Acme Corp",
    entity_subtype="Private Limited Company",
    jurisdiction="GB",
    incorporation_date="2020-01-15",
    registration_number="12345678",
    address_line_1="123 Business Street",
    address_city="London",
    address_postal_code="SW1A 1AA",
    address_country="GB",
    email="contact@acme.com",
    is_primary=True,
)

print(f"Created: {entity.name}")  # "Acme Corp"
const response = await fetch('https://api.kycgenie.com/api/v1/entities/', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json',
    'Idempotency-Key': 'company-acme-12345678',
  },
  body: JSON.stringify({
    entity_type: 'company',
    legal_name: 'Acme Corporation Ltd',
    trading_name: 'Acme Corp',
    entity_subtype: 'Private Limited Company',
    jurisdiction: 'GB',
    incorporation_date: '2020-01-15',
    registration_number: '12345678',
    address_line_1: '123 Business Street',
    address_city: 'London',
    address_postal_code: 'SW1A 1AA',
    address_country: 'GB',
    email: 'contact@acme.com',
    is_primary: true,
  }),
});
const entity = await response.json();
console.log(`Created: ${entity.name}`);  // "Acme Corp"
const response = await fetch('https://api.kycgenie.com/api/v2/entities/', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json',
    'Idempotency-Key': 'company-acme-12345678',
  },
  body: JSON.stringify({
    entity_type: 'company',
    legal_name: 'Acme Corporation Ltd',
    trading_name: 'Acme Corp',
    entity_subtype: 'Private Limited Company',
    jurisdiction: 'GB',
    incorporation_date: '2020-01-15',
    registration_number: '12345678',
    address_line_1: '123 Business Street',
    address_city: 'London',
    address_postal_code: 'SW1A 1AA',
    address_country: 'GB',
    email: 'contact@acme.com',
    is_primary: true,
  }),
});
const entity = await response.json();
console.log(`Created: ${entity.name}`);  // "Acme Corp"

Create Individual Entity

curl -X POST https://api.kycgenie.com/api/v1/entities/ \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: individual-john-smith-1985-06-15" \
  -d '{
    "entity_type": "individual",
    "first_name": "John",
    "last_name": "Smith",
    "date_of_birth": "1985-06-15",
    "nationality": "GB",
    "email": "john.smith@example.com",
    "address_country": "GB"
  }'
curl -X POST https://api.kycgenie.com/api/v2/entities/ \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: individual-john-smith-1985-06-15" \
  -d '{
    "entity_type": "individual",
    "first_name": "John",
    "last_name": "Smith",
    "date_of_birth": "1985-06-15",
    "nationality": "GB",
    "email": "john.smith@example.com",
    "address_country": "GB"
  }'
entity = requests.post(
    "https://api.kycgenie.com/api/v1/entities/",
    headers={
        "Authorization": "Bearer YOUR_API_KEY",
        "Idempotency-Key": "individual-john-smith-12345678",
    },
    json={
        "entity_type": "individual",
        "first_name": "John",
        "last_name": "Smith",
        "date_of_birth": "1985-06-15",
        "nationality": "GB",
        "email": "john.smith@example.com",
        "address_country": "GB",
    },
).json()
# name auto-calculated as "John Smith"
print(entity["name"])
from kycgenie import KYCGenie

client = KYCGenie(api_key="YOUR_API_KEY")

entity = client.entities.create(
    entity_type="individual",
    first_name="John",
    last_name="Smith",
    date_of_birth="1985-06-15",
    nationality="GB",
    email="john.smith@example.com",
    address_country="GB",
)
print(entity.name)  # "John Smith"
const entity = await fetch('https://api.kycgenie.com/api/v1/entities/', {
  method: 'POST',
  headers: { 'Authorization': 'Bearer YOUR_API_KEY', 'Content-Type': 'application/json' },
  body: JSON.stringify({
    entity_type: 'individual', first_name: 'John', last_name: 'Smith',
    date_of_birth: '1985-06-15', nationality: 'GB',
    email: 'john.smith@example.com', address_country: 'GB',
  }),
}).then(r => r.json());
console.log(entity.name); // "John Smith"
const entity = await fetch('https://api.kycgenie.com/api/v2/entities/', {
  method: 'POST',
  headers: { 'Authorization': 'Bearer YOUR_API_KEY', 'Content-Type': 'application/json' },
  body: JSON.stringify({
    entity_type: 'individual', first_name: 'John', last_name: 'Smith',
    date_of_birth: '1985-06-15', nationality: 'GB',
    email: 'john.smith@example.com', address_country: 'GB',
  }),
}).then(r => r.json());
console.log(entity.name); // "John Smith"

Response (201 Created)

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "name": "Acme Corp",
  "entity_type": "company",
  "legal_name": "Acme Corporation Ltd",
  "trading_name": "Acme Corp",
  "first_name": "",
  "middle_name": "",
  "last_name": "",
  "email": "contact@acme.com",
  "phone": "",
  "external_id": null,
  "is_primary": true,
  "address_line_1": "123 Business Street",
  "address_line_2": "",
  "address_city": "London",
  "address_state": "",
  "address_postal_code": "SW1A 1AA",
  "address_country": "GB",
  "nationality": "",
  "date_of_birth": null,
  "incorporation_date": "2020-01-15",
  "jurisdiction": "GB",
  "registration_number": "12345678",
  "created_at": "2026-01-14T12:41:56.456529Z"
}

List Entities

Returns a paginated list of entities for your tenant.

GET /api/v1/entities/
GET /api/v2/entities/

Query parameters

ParameterTypeDescription
entity_typestringFilter by company or individual
is_primarybooleanFilter by primary status
searchstringName/email keyword search
external_idstringFilter by your external reference ID
created_afterdatetimeISO 8601 - only entities created after this time
created_beforedatetimeISO 8601 - only entities created before this time
pageintegerPage number (default: 1)
page_sizeintegerResults per page (default: 20, max: 100)
afterstringCursor - return results after this cursor (from next_cursor)
beforestringCursor - return results before this cursor (from prev_cursor)
page_sizeintegerResults per page (default: 50, max: 100)

Response

FieldTypeDescription
countintegerTotal number of matching entities
pageintegerCurrent page number
page_sizeintegerNumber of results in this page
total_pagesintegerTotal number of pages
resultsarrayArray of entity summary objects

Response

Each item in results contains: id, name, entity_type, external_id, is_primary, screening_status, response_count, risk_profiles_count, created_at.

List Entities

curl "https://api.kycgenie.com/api/v1/entities/?entity_type=company&page=1&page_size=20" \
  -H "Authorization: Bearer YOUR_API_KEY"
# First page
curl "https://api.kycgenie.com/api/v2/entities/?entity_type=company&page_size=50" \
  -H "Authorization: Bearer YOUR_API_KEY"

# Next page - pass next_cursor from the previous response as 'after'
curl "https://api.kycgenie.com/api/v2/entities/?entity_type=company&page_size=50&after=eyJpZCI6IjU1MWU4NTAwIn0" \
  -H "Authorization: Bearer YOUR_API_KEY"
import requests

headers = {"Authorization": "Bearer YOUR_API_KEY"}

# First page
data = requests.get(
    "https://api.kycgenie.com/api/v1/entities/",
    headers=headers,
    params={"entity_type": "company", "page": 1, "page_size": 20},
).json()

print(f"Total: {data['count']} | Pages: {data['total_pages']}")
for entity in data["results"]:
    print(f"  {entity['name']} ({entity['entity_type']})")

# v1 - next page by page number
if data["page"] < data["total_pages"]:
    page2 = requests.get(
        "https://api.kycgenie.com/api/v1/entities/",
        headers=headers,
        params={"entity_type": "company", "page": data["page"] + 1, "page_size": 20},
    ).json()
from kycgenie import KYCGenie

client = KYCGenie(api_key="YOUR_API_KEY")

# Returns cursor-paginated response
page = client.entities.list(entity_type="company", page_size=50)
print(f"Has more: {page.has_more}")
for entity in page.results:
    print(f"  {entity.name}")

# Paginate
if page.has_more:
    page2 = client.entities.list(
        entity_type="company",
        after=page.next_cursor,
        page_size=50,
    )
const params = new URLSearchParams({
  entity_type: 'company',
  page: '1',
  page_size: '20',
});
const data = await fetch(
  `https://api.kycgenie.com/api/v1/entities/?${params}`,
  { headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
).then(r => r.json());

console.log(`Total: ${data.count} | Pages: ${data.total_pages}`);
data.results.forEach(e => console.log(e.name));
// First page
let data = await fetch(
  `https://api.kycgenie.com/api/v2/entities/?entity_type=company&page_size=50`,
  { headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
).then(r => r.json());

data.results.forEach(e => console.log(e.name));

// Next page - pass next_cursor as 'after'
if (data.has_more) {
  const next = await fetch(
    `https://api.kycgenie.com/api/v2/entities/?entity_type=company&page_size=50&after=${data.next_cursor}`,
    { headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
  ).then(r => r.json());
  next.results.forEach(e => console.log(e.name));
}

Retrieve Entity

Returns the full Entity Object for a single entity by ID.

Query parameters

ParameterTypeDescription
reveal_sensitivebooleanPass true to receive unmasked values for national_id_number, tax_id, ssn, and social_insurance_number. Access is audit-logged. Default: false.

Retrieve Entity

curl "https://api.kycgenie.com/api/v1/entities/550e8400-e29b-41d4-a716-446655440000/" \
  -H "Authorization: Bearer YOUR_API_KEY"

# Reveal masked sensitive identity fields (audit-logged)
curl "https://api.kycgenie.com/api/v1/entities/550e8400-e29b-41d4-a716-446655440000/?reveal_sensitive=true" \
  -H "Authorization: Bearer YOUR_API_KEY"
curl "https://api.kycgenie.com/api/v2/entities/550e8400-e29b-41d4-a716-446655440000/" \
  -H "Authorization: Bearer YOUR_API_KEY"
import requests

entity_id = "550e8400-e29b-41d4-a716-446655440000"

entity = requests.get(
    f"https://api.kycgenie.com/api/v1/entities/{entity_id}/",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
).json()

print(entity["name"])

# To unmask sensitive fields (audit-logged)
entity_full = requests.get(
    f"https://api.kycgenie.com/api/v1/entities/{entity_id}/",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
    params={"reveal_sensitive": "true"},
).json()

# national_id_number, tax_id, ssn, social_insurance_number now fully unmasked
print(entity_full.get("national_id_number"))
from kycgenie import KYCGenie

client = KYCGenie(api_key="YOUR_API_KEY")

entity = client.entities.get(
    entity_id="550e8400-e29b-41d4-a716-446655440000",
)
print(entity.name)

# Unmask sensitive fields (audit-logged)
entity_full = client.entities.get(
    entity_id="550e8400-e29b-41d4-a716-446655440000",
    reveal_sensitive=True,
)
print(entity_full.national_id_number)  # fully unmasked
const entityId = '550e8400-e29b-41d4-a716-446655440000';
const entity = await fetch(
  `https://api.kycgenie.com/api/v1/entities/${entityId}/`,
  { headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
).then(r => r.json());

// Unmask sensitive fields
const entityFull = await fetch(
  `https://api.kycgenie.com/api/v1/entities/${entityId}/?reveal_sensitive=true`,
  { headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
).then(r => r.json());
const entityId = '550e8400-e29b-41d4-a716-446655440000';
const entity = await fetch(
  `https://api.kycgenie.com/api/v2/entities/${entityId}/`,
  { headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
).then(r => r.json());

Response (200 OK)

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "name": "Acme Corp",
  "entity_type": "company",
  "entity_subtype": null,
  "legal_name": "Acme Corporation Ltd",
  "trading_name": "Acme Corp",
  "registration_number": "12345678",
  "jurisdiction": "GB",
  "incorporation_date": "2020-01-15",
  "external_id": null,
  "address_line_1": "123 Business Street",
  "address_line_2": "",
  "address_city": "London",
  "address_state": "",
  "address_postal_code": "SW1A 1AA",
  "address_country": "GB",
  "is_primary": true,
  "screening_status": "not_screened",
  "response_count": 0,
  "risk_profiles_count": 0,
  "created_at": "2026-01-10T09:30:00Z",
  "updated_at": "2026-01-27T14:00:00Z"
}
{
  "id": "661f9511-f30c-52e5-b827-557766551111",
  "name": "Jane Smith",
  "entity_type": "individual",
  "entity_subtype": null,
  "title": "Ms",
  "first_name": "Jane",
  "middle_name": "",
  "last_name": "Smith",
  "gender": "",
  "date_of_birth": "1985-06-15",
  "nationality": "GB",
  "country_of_birth": "GB",
  "national_id_number": "****6789",
  "tax_id": "",
  "ssn": "",
  "social_insurance_number": "",
  "external_id": null,
  "address_line_1": "45 Elm Road",
  "address_line_2": "",
  "address_city": "Manchester",
  "address_state": "",
  "address_postal_code": "M1 2AB",
  "address_country": "GB",
  "is_primary": true,
  "screening_status": "not_screened",
  "response_count": 0,
  "risk_profiles_count": 0,
  "created_at": "2026-02-01T11:00:00Z",
  "updated_at": "2026-02-01T11:00:00Z"
}

Sensitive fields are masked to last 4 characters by default. Add ?reveal_sensitive=true for full values (access is audit-logged).

Update Entity

Partially update entity fields. Only the fields you include are modified.

Field update constraints
  • name and entity_type are immutable - cannot be updated after creation.
  • is_primary can only be promoted (false → true). Once primary, it cannot be demoted.
  • jurisdiction, nationality, and address_country must be ISO 3166-1 alpha-2 codes.

Response (200 OK)

FieldTypeDescription
iduuidEntity ID
namestringComputed display name
entity_typestringEntity type
updated_fieldsarrayList of field names that were changed
updated_atdatetimeISO 8601 timestamp of the update

Update Entity

curl -X PATCH https://api.kycgenie.com/api/v1/entities/550e8400-e29b-41d4-a716-446655440000/ \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: update-address-20260127" \
  -d '{
    "trading_name": "Acme Financial Corp",
    "address_line_1": "789 New Business Plaza",
    "address_city": "Birmingham",
    "address_postal_code": "B1 1AA"
  }'
curl -X PATCH https://api.kycgenie.com/api/v2/entities/550e8400-e29b-41d4-a716-446655440000/ \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "trading_name": "Acme Financial Corp",
    "address_line_1": "789 New Business Plaza"
  }'
import requests

entity_id = "550e8400-e29b-41d4-a716-446655440000"
result = requests.patch(
    f"https://api.kycgenie.com/api/v1/entities/{entity_id}/",
    headers={
        "Authorization": "Bearer YOUR_API_KEY",
        "Idempotency-Key": "update-address-20260127",
    },
    json={
        "trading_name": "Acme Financial Corp",
        "address_line_1": "789 New Business Plaza",
        "address_city": "Birmingham",
        "address_postal_code": "B1 1AA",
    },
).json()

print(f"Updated: {result['name']}")
print(f"Changed: {result['updated_fields']}")
from kycgenie import KYCGenie

client = KYCGenie(api_key="YOUR_API_KEY")

result = client.entities.update(
    entity_id="550e8400-e29b-41d4-a716-446655440000",
    trading_name="Acme Financial Corp",
    address_line_1="789 New Business Plaza",
    address_city="Birmingham",
    address_postal_code="B1 1AA",
)
print(result.updated_fields)
const result = await fetch(
  `https://api.kycgenie.com/api/v1/entities/550e8400-e29b-41d4-a716-446655440000/`,
  {
    method: 'PATCH',
    headers: {
      'Authorization': 'Bearer YOUR_API_KEY',
      'Content-Type': 'application/json',
      'Idempotency-Key': 'update-address-20260127',
    },
    body: JSON.stringify({
      trading_name: 'Acme Financial Corp',
      address_line_1: '789 New Business Plaza',
      address_city: 'Birmingham',
      address_postal_code: 'B1 1AA',
    }),
  }
).then(r => r.json());

console.log(result.updated_fields);
const result = await fetch(
  `https://api.kycgenie.com/api/v2/entities/550e8400-e29b-41d4-a716-446655440000/`,
  {
    method: 'PATCH',
    headers: { 'Authorization': 'Bearer YOUR_API_KEY', 'Content-Type': 'application/json' },
    body: JSON.stringify({ trading_name: 'Acme Financial Corp' }),
  }
).then(r => r.json());

Response (200 OK)

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "name": "Acme Financial Corp",
  "entity_type": "company",
  "updated_fields": ["trading_name", "address_line_1", "address_city", "address_postal_code"],
  "updated_at": "2026-01-27T14:22:00Z"
}

Delete Entity

Delete or archive an entity. The behaviour depends on whether the entity has associated KYC activity.

Compliance-safe deletion

If an entity has any KYC activity - screening results, identity verifications, multi-bureau checks, or DDQ responses - it cannot be hard-deleted. Instead, it is archived: all data is retained for the required regulatory retention period, then purged automatically. The response body includes a purge_after date when the data will be destroyed.

Response behaviour

ScenarioStatusBody
Entity has KYC activity (screening / verification / multi-bureau / responses) 200 OK {"status": "archived", "purge_after": "2033-01-27T00:00:00Z"}
Entity has no KYC activity - clean delete 204 No Content No body

Delete Entity

curl -X DELETE https://api.kycgenie.com/api/v1/entities/550e8400-e29b-41d4-a716-446655440000/ \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -w "\nHTTP Status: %{http_code}"
curl -X DELETE https://api.kycgenie.com/api/v2/entities/550e8400-e29b-41d4-a716-446655440000/ \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -w "\nHTTP Status: %{http_code}"
import requests

entity_id = "550e8400-e29b-41d4-a716-446655440000"
response = requests.delete(
    f"https://api.kycgenie.com/api/v1/entities/{entity_id}/",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
)

if response.status_code == 200:
    data = response.json()
    if data["status"] == "deleted":
        # Clean delete - no KYC activity existed
        print("Entity permanently deleted.")
    else:
        # Archived for regulatory retention (FATF/AMLD)
        print(f"Archived. Data will be purged after: {data['purge_after']}")
else:
    print(f"Error: {response.json()}")
from kycgenie import KYCGenie

client = KYCGenie(api_key="YOUR_API_KEY")

result = client.entities.delete(
    entity_id="550e8400-e29b-41d4-a716-446655440000",
)

if result.status == "deleted":
    print("Entity permanently deleted.")
elif result.status == "archived":
    print(f"Archived. Purge after: {result.purge_after}")
const entityId = '550e8400-e29b-41d4-a716-446655440000';
const response = await fetch(
  `https://api.kycgenie.com/api/v1/entities/${entityId}/`,
  { method: 'DELETE', headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
);

if (response.status === 200) {
  const data = await response.json();
  if (data.status === 'deleted') {
    console.log('Entity permanently deleted.');
  } else {
    console.log(`Archived. Purge after: ${data.purge_after}`);
  }
}
const entityId = '550e8400-e29b-41d4-a716-446655440000';
const response = await fetch(
  `https://api.kycgenie.com/api/v2/entities/${entityId}/`,
  { method: 'DELETE', headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
);

if (response.status === 200) {
  const data = await response.json();
  if (data.status === 'deleted') {
    console.log('Entity permanently deleted.');
  } else {
    console.log(`Archived. Purge after: ${data.purge_after}`);
  }
}

Response - Archived (200 OK)

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "archived",
  "purge_after": "2033-01-27T00:00:00Z"
}

Response - Clean Delete (200 OK)

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "deleted",
  "purge_after": null
}

Search Entities

Fuzzy search across entity names using similarity matching. Useful for deduplication checks before creating new entities.

GET /api/v1/entities/search/

Query parameters

ParameterTypeRequiredDescription
qstringYesSearch query string
entity_typestringNoFilter by company or individual
thresholdfloatNoSimilarity threshold 0.0–1.0 (default: 0.7). Higher = stricter matching.
limitintegerNoMax results (default: 10, max: 50)

Response

Returns matching entities sorted by similarity score, descending.

Search Entities

curl "https://api.kycgenie.com/api/v1/entities/search/?q=Acme+Corp&threshold=0.7&limit=10" \
  -H "Authorization: Bearer YOUR_API_KEY"
import requests

results = requests.get(
    "https://api.kycgenie.com/api/v1/entities/search/",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
    params={
        "q": "Acme Corp",
        "entity_type": "company",
        "threshold": 0.7,
        "limit": 10,
    },
).json()

print(f"Query: {results['query']} | Threshold: {results['threshold']}")
for match in results["results"]:
    print(f"  {match['name']} - similarity: {match['similarity']}")
from kycgenie import KYCGenie

client = KYCGenie(api_key="YOUR_API_KEY")

results = client.entities.search(
    q="Acme Corp",
    entity_type="company",
    threshold=0.7,
    limit=10,
)

for match in results.results:
    print(f"{match.name} - similarity: {match.similarity}")
const params = new URLSearchParams({
  q: 'Acme Corp',
  entity_type: 'company',
  threshold: '0.7',
  limit: '10',
});
const results = await fetch(
  `https://api.kycgenie.com/api/v1/entities/search/?${params}`,
  { headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
).then(r => r.json());

results.results.forEach(m =>
  console.log(`${m.name} - similarity: ${m.similarity}`)
);

Response (200 OK)

{
  "query": "Acme Corp",
  "results": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "name": "Acme Corp",
      "entity_type": "company",
      "entity_subtype": "Private Limited Company",
      "similarity": 1.0,
      "is_primary": true
    },
    {
      "id": "770e8400-e29b-41d4-a716-446655440002",
      "name": "Acme Finance Ltd",
      "entity_type": "company",
      "entity_subtype": "LLC",
      "similarity": 0.818,
      "is_primary": false
    }
  ]
}

Batch Create Entities

Create up to 200 entities in a single synchronous request. Ideal for onboarding workflows and bulk imports.

Limits
  • Max per request: 200 entities
  • Daily limit: 1,000 entities per tenant (resets at midnight UTC)
  • Duplicate detection: Automatic fuzzy matching on name + entity_type (enabled by default)

Request body

FieldTypeRequiredDescription
entitiesarrayYes1–200 entity objects. Each follows the same schema as Create Entity.
skip_duplicatesbooleanNoWhen true (default), entities matching an existing record by name/type are skipped rather than erroring.

Response fields

FieldDescription
summaryObject with requested, created, skipped, failed, and remaining_daily_quota counts
created_entitiesArray of successfully created entity objects
skippedArray of entries that were skipped as duplicates, with index, reason, existing_entity_id, matching_name, and similarity_score (0.0–1.0)
errorsArray of validation errors, with index and errors

Batch Create Entities

curl -X POST https://api.kycgenie.com/api/v1/entities/batch/ \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: batch-import-2026-01-27" \
  -d '{
    "entities": [
      {
        "entity_type": "company",
        "legal_name": "Acme Corp",
        "jurisdiction": "GB"
      },
      {
        "entity_type": "individual",
        "first_name": "Jane",
        "last_name": "Doe",
        "date_of_birth": "1990-03-22",
        "nationality": "US"
      }
    ],
    "skip_duplicates": true
  }'
curl -X POST https://api.kycgenie.com/api/v2/entities/batch/ \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "entities": [
      {"entity_type": "company", "legal_name": "Acme Corp", "jurisdiction": "GB"},
      {"entity_type": "individual", "first_name": "Jane", "last_name": "Doe", "date_of_birth": "1990-03-22"}
    ],
    "skip_duplicates": true
  }'
import requests

result = requests.post(
    "https://api.kycgenie.com/api/v1/entities/batch/",
    headers={
        "Authorization": "Bearer YOUR_API_KEY",
        "Idempotency-Key": "batch-import-2026-01-27",
    },
    json={
        "entities": [
            {"entity_type": "company", "legal_name": "Acme Corp", "jurisdiction": "GB"},
            {"entity_type": "individual", "first_name": "Jane", "last_name": "Doe",
             "date_of_birth": "1990-03-22", "nationality": "US"},
        ],
        "skip_duplicates": True,
    },
).json()

summary = result["summary"]
print(f"Created: {summary['created']}, Skipped: {summary['skipped']}, "
      f"Errors: {summary['failed']}, Remaining quota: {summary['remaining_daily_quota']}")

for entity in result["created_entities"]:
    print(f"  ✓ {entity['name']} ({entity['id']})")

for skipped in result["skipped"]:
    print(f"  ⊘ [{skipped['index']}] {skipped['matching_name']} (similarity: {skipped['similarity_score']})")

for error in result["errors"]:
    print(f"  ✗ [{error['index']}] {error['errors']}")
from kycgenie import KYCGenie

client = KYCGenie(api_key="YOUR_API_KEY")

result = client.entities.batch_create(
    entities=[
        {"entity_type": "company", "legal_name": "Acme Corp", "jurisdiction": "GB"},
        {"entity_type": "individual", "first_name": "Jane", "last_name": "Doe",
         "date_of_birth": "1990-03-22", "nationality": "US"},
    ],
    skip_duplicates=True,
)

print(f"Created: {result.summary['created']}")
for entity in result.created_entities:
    print(f"  {entity.name}")
const result = await fetch('https://api.kycgenie.com/api/v1/entities/batch/', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json',
    'Idempotency-Key': 'batch-import-2026-01-27',
  },
  body: JSON.stringify({
    entities: [
      { entity_type: 'company', legal_name: 'Acme Corp', jurisdiction: 'GB' },
      { entity_type: 'individual', first_name: 'Jane', last_name: 'Doe',
        date_of_birth: '1990-03-22', nationality: 'US' },
    ],
    skip_duplicates: true,
  }),
}).then(r => r.json());

console.log(`Created: ${result.summary.created}, Remaining: ${result.summary.remaining_daily_quota}`);
const result = await fetch('https://api.kycgenie.com/api/v2/entities/batch/', {
  method: 'POST',
  headers: { 'Authorization': 'Bearer YOUR_API_KEY', 'Content-Type': 'application/json' },
  body: JSON.stringify({
    entities: [
      { entity_type: 'company', legal_name: 'Acme Corp', jurisdiction: 'GB' },
    ],
    skip_duplicates: true,
  }),
}).then(r => r.json());

console.log(`Created: ${result.summary.created}`);

Response (200 OK)

{
  "summary": {
    "requested": 2,
    "created": 1,
    "skipped": 1,
    "failed": 0,
    "remaining_daily_quota": 998
  },
  "created_entities": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "name": "Acme Corp",
      "entity_type": "company",
      "created_at": "2026-01-27T12:00:00Z"
    }
  ],
  "skipped": [
    {
      "index": 1,
      "reason": "duplicate",
      "existing_entity_id": "0571139b-88bc-4fc0-92d4-3fffc1cb5feb",
      "matching_name": "Jane Doe",
      "similarity_score": 1.0
    }
  ],
  "errors": []
}

Entity Documents

Upload, list, download, and delete documents stored directly on an entity - such as certificates, passports, and financial statements.

Upload Entity Document

Request body (multipart/form-data)

FieldTypeRequiredDescription
filefileYesFile to upload (max 10 MB)
document_typestringYesDocument type label (e.g. "Certificate of Incorporation")
expiry_datedateNoYYYY-MM-DD expiry for the document

Upload Document

curl -X POST https://api.kycgenie.com/api/v1/entities/550e8400-e29b-41d4-a716-446655440000/documents/upload/ \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Idempotency-Key: upload-cert-inc-550e8400" \
  -F "file=@certificate_of_incorporation.pdf" \
  -F "document_type=Certificate of Incorporation"
curl -X POST https://api.kycgenie.com/api/v2/entities/550e8400-e29b-41d4-a716-446655440000/documents/ \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Idempotency-Key: upload-cert-inc-550e8400" \
  -F "file=@certificate_of_incorporation.pdf" \
  -F "document_type=Certificate of Incorporation"
import requests

entity_id = "550e8400-e29b-41d4-a716-446655440000"
with open("certificate_of_incorporation.pdf", "rb") as f:
    response = requests.post(
        f"https://api.kycgenie.com/api/v1/entities/{entity_id}/documents/upload/",
        headers={
            "Authorization": "Bearer YOUR_API_KEY",
            "Idempotency-Key": "upload-cert-inc-550e8400",
        },
        files={"file": ("certificate_of_incorporation.pdf", f, "application/pdf")},
        data={
            "document_type": "Certificate of Incorporation",
        },
    )
print(response.json())
from kycgenie import KYCGenie

client = KYCGenie(api_key="YOUR_API_KEY")

with open("certificate_of_incorporation.pdf", "rb") as f:
    doc = client.entities.upload_document(
        entity_id="550e8400-e29b-41d4-a716-446655440000",
        file=f,
        document_type="Certificate of Incorporation",
    )
print(doc.id)
const formData = new FormData();
formData.append('file', fileInput.files[0]);
formData.append('document_type', 'Certificate of Incorporation');

const doc = await fetch(
  'https://api.kycgenie.com/api/v1/entities/550e8400-e29b-41d4-a716-446655440000/documents/upload/',
  {
    method: 'POST',
    headers: { 'Authorization': 'Bearer YOUR_API_KEY', 'Idempotency-Key': 'upload-cert-inc-550e8400' },
    body: formData,
  }
).then(r => r.json());
const formData = new FormData();
formData.append('file', fileInput.files[0]);
formData.append('document_type', 'Certificate of Incorporation');

const doc = await fetch(
  'https://api.kycgenie.com/api/v2/entities/550e8400-e29b-41d4-a716-446655440000/documents/',
  {
    method: 'POST',
    headers: { 'Authorization': 'Bearer YOUR_API_KEY', 'Idempotency-Key': 'upload-cert-inc-550e8400' },
    body: formData,
  }
).then(r => r.json());

List Entity Documents

Returns all documents attached to the entity, ordered by upload date descending. Both v1 and v2 return an envelope with count and documents - no cursor pagination is needed given the naturally bounded document count per entity.

List Documents

curl "https://api.kycgenie.com/api/v1/entities/550e8400-e29b-41d4-a716-446655440000/documents/" \
  -H "Authorization: Bearer YOUR_API_KEY"
curl "https://api.kycgenie.com/api/v2/entities/550e8400-e29b-41d4-a716-446655440000/documents/" \
  -H "Authorization: Bearer YOUR_API_KEY"
import requests

entity_id = "550e8400-e29b-41d4-a716-446655440000"
data = requests.get(
    f"https://api.kycgenie.com/api/v1/entities/{entity_id}/documents/",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
).json()

print(f"{data['entity_name']} - {data['count']} document(s)")
# v1: key is 'documents' | v2: key is 'results'
for doc in data["documents"]:
    print(f"{doc['document_type_name']}: {doc['name']} ({doc['size']} bytes)")
from kycgenie import KYCGenie

client = KYCGenie(api_key="YOUR_API_KEY")

result = client.entities.list_documents(
    entity_id="550e8400-e29b-41d4-a716-446655440000",
)
print(f"{result.entity_name} - {result.count} document(s)")
# SDK wraps v2 - documents are under .results
for doc in result.results:
    print(f"{doc.document_type_name}: {doc.name}")
const entityId = '550e8400-e29b-41d4-a716-446655440000';
const data = await fetch(
  `https://api.kycgenie.com/api/v1/entities/${entityId}/documents/`,
  { headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
).then(r => r.json());

console.log(`${data.entity_name} - ${data.count} document(s)`);
data.documents.forEach(d => console.log(`${d.document_type_name}: ${d.name}`));
const entityId = '550e8400-e29b-41d4-a716-446655440000';
const data = await fetch(
  `https://api.kycgenie.com/api/v2/entities/${entityId}/documents/`,
  { headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
).then(r => r.json());

console.log(`${data.entity_name} - ${data.count} document(s)`);
// v2 uses 'results' (v1 uses 'documents')
data.results.forEach(d => console.log(`${d.document_type_name}: ${d.name}`));

Get Document Download URL

Generate a short-lived pre-signed URL (valid 15 minutes) for downloading an entity document. The URL is safe to pass directly to a browser or file download client.

Get Download URL

curl "https://api.kycgenie.com/api/v1/entities/550e8400-e29b-41d4-a716-446655440000/documents/770f0622-g49d-63f6-c938-668877662222/download/" \
  -H "Authorization: Bearer YOUR_API_KEY"
curl "https://api.kycgenie.com/api/v2/entities/550e8400-e29b-41d4-a716-446655440000/documents/770f0622-g49d-63f6-c938-668877662222/download/" \
  -H "Authorization: Bearer YOUR_API_KEY"
import requests

entity_id = "550e8400-e29b-41d4-a716-446655440000"
document_id = "770f0622-g49d-63f6-c938-668877662222"

result = requests.get(
    f"https://api.kycgenie.com/api/v1/entities/{entity_id}/documents/{document_id}/download/",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
).json()

# Use the URL directly - valid for 15 minutes
print(result["download_url"])
print(f"Expires: {result['expires_at']}")
from kycgenie import KYCGenie

client = KYCGenie(api_key="YOUR_API_KEY")

result = client.entities.get_document_download_url(
    entity_id="550e8400-e29b-41d4-a716-446655440000",
    document_id="770f0622-g49d-63f6-c938-668877662222",
)
print(result.download_url)  # valid for 15 minutes
const entityId = '550e8400-e29b-41d4-a716-446655440000';
const documentId = '770f0622-g49d-63f6-c938-668877662222';

const result = await fetch(
  `https://api.kycgenie.com/api/v1/entities/${entityId}/documents/${documentId}/download/`,
  { headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
).then(r => r.json());

// result.download_url is valid for 15 minutes
window.location.href = result.download_url;
const entityId = '550e8400-e29b-41d4-a716-446655440000';
const documentId = '770f0622-g49d-63f6-c938-668877662222';

const result = await fetch(
  `https://api.kycgenie.com/api/v2/entities/${entityId}/documents/${documentId}/download/`,
  { headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
).then(r => r.json());

window.location.href = result.download_url;

Response (200 OK)

{
  "download_url": "https://app.kycgenie.com/api/v1/files/dl_B7c9d2e3f4a5b6c7/",
  "expires_at": "2026-01-27T15:30:00+00:00",
  "filename": "certificate_of_incorporation.pdf",
  "content_type": "application/pdf",
  "size": 1048576
}

Delete Entity Document

Returns 204 No Content on success.

Delete Document

curl -X DELETE https://api.kycgenie.com/api/v1/entities/{entity_id}/documents/{document_id}/ \
  -H "Authorization: Bearer YOUR_API_KEY"
curl -X DELETE https://api.kycgenie.com/api/v2/entities/{entity_id}/documents/{document_id}/ \
  -H "Authorization: Bearer YOUR_API_KEY"
response = requests.delete(
    f"https://api.kycgenie.com/api/v1/entities/{entity_id}/documents/{document_id}/",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
)
# 204 No Content on success
from kycgenie import KYCGenie

client = KYCGenie(api_key="YOUR_API_KEY")

client.entities.delete_document(
    entity_id="550e8400-e29b-41d4-a716-446655440000",
    document_id="770f0622-g49d-63f6-c938-668877662222",
)
# Returns None on success (204 No Content)
await fetch(
  `https://api.kycgenie.com/api/v1/entities/${entityId}/documents/${documentId}/`,
  { method: 'DELETE', headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
);
// 204 No Content
await fetch(
  `https://api.kycgenie.com/api/v2/entities/${entityId}/documents/${documentId}/`,
  { method: 'DELETE', headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
);

Entity Subtypes

The entity_subtype field is a free-text string used for business classification. The values below are commonly used conventions - use the Value column in your API requests.

ValueDescriptionCategory
LLCLimited Liability CompanyCorporate
CorporationCorporationCorporate
Private Limited CompanyPrivate Limited Company (Ltd.)Corporate
Public Limited CompanyPublic Limited Company (PLC)Corporate
Sole ProprietorshipSole ProprietorshipCorporate
FundInvestment FundInvestment
Hedge FundHedge FundInvestment
Private Equity FundPrivate Equity FundInvestment
Mutual FundMutual FundInvestment
SPCSegregated Portfolio CompanyInvestment
SICAVSICAVInvestment
Unit TrustUnit TrustInvestment
General PartnershipGeneral PartnershipPartnership
Limited PartnershipLimited Partnership (LP)Partnership
Limited Liability PartnershipLimited Liability Partnership (LLP)Partnership
TrustTrustTrust
Investment TrustInvestment TrustTrust
Family TrustFamily TrustTrust
Holding CompanyHolding CompanySpecialized
Special Purpose VehicleSpecial Purpose Vehicle (SPV)Specialized
Joint VentureJoint VentureSpecialized
Fund AdministratorFund AdministratorService Provider
Service ProviderService ProviderService Provider
Financial InstitutionFinancial InstitutionFinancial
BankBankFinancial
RegulatorRegulatory AuthorityRegulatory
Non-ProfitNon-Profit OrganizationNon-Profit
CharityCharityNon-Profit
Government EntityGovernment EntityGovernment
Government AgencyGovernment AgencyGovernment
OtherOtherOther

Entity Relationships

Link two entities with a directional role to model your corporate ownership structure, board composition, UBO chains, and more. The typical pattern is from_entity holding a role at to_entity.

Relationship Object

FieldTypeDescription
iduuidUnique relationship ID
from_entityobjectThe entity holding the role - contains id, name, entity_type
to_entityobjectThe entity the role is held at - same shape as from_entity
rolestringMachine-readable role value. See Role Values.
role_labelstringHuman-readable label
role_titlestring | nullOptional free-text job title override
ownership_percentagestring | nullPercentage ownership (0–100), returned as a decimal string
statusstringactive, inactive, resigned, or deceased
created_atdatetimeISO 8601 creation timestamp

Role Values

ValueLabelCategory
ultimate_beneficial_ownerUltimate Beneficial OwnerOwnership
beneficial_ownerBeneficial OwnerOwnership
shareholderShareholderOwnership
partnerPartnerOwnership
limited_partnerLimited PartnerOwnership
general_partnerGeneral PartnerOwnership
memberMemberOwnership
CEOChief Executive OfficerC-Suite
CFOChief Financial OfficerC-Suite
COOChief Operating OfficerC-Suite
CTOChief Technology OfficerC-Suite
CIOChief Investment OfficerC-Suite
CCOChief Compliance OfficerC-Suite
CROChief Risk OfficerC-Suite
PresidentPresidentC-Suite
VPVice PresidentC-Suite
ChairmanChairmanBoard
DirectorDirectorBoard
Managing DirectorManaging DirectorBoard
Independent DirectorIndependent DirectorBoard
Non-Executive DirectorNon-Executive DirectorBoard
Senior ManagerSenior ManagerManagement
General ManagerGeneral ManagerManagement
Portfolio ManagerPortfolio ManagerManagement
Investment ManagerInvestment ManagerManagement
Fund ManagerFund ManagerManagement
Operations ManagerOperations ManagerManagement
Head of Client ServicesHead of Client ServicesManagement
MLROMoney Laundering Reporting OfficerCompliance
Compliance OfficerCompliance OfficerCompliance
Risk ManagerRisk ManagerCompliance
Legal CounselLegal CounselCompliance
SecretarySecretaryOperational
TreasurerTreasurerOperational
ControllerControllerOperational
signatorySignatoryOperational
officerOfficerOperational
pepPolitically Exposed PersonSpecial
key_personnelKey PersonnelSpecial
fund_personnelFund PersonnelSpecial
gp_personnelGeneral Partner PersonnelSpecial
fund_admin_personnelFund Administrator PersonnelSpecial
otherOtherOther

Add Relationship

curl -X POST https://api.kycgenie.com/api/v1/entities/550e8400-e29b-41d4-a716-446655440000/relationships/ \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: rel-shareholder-660e8400-550e8400" \
  -d '{
    "from_entity": "660e8400-e29b-41d4-a716-446655440001",
    "to_entity": "550e8400-e29b-41d4-a716-446655440000",
    "role": "shareholder",
    "ownership_percentage": 25,
    "status": "active"
  }'
import requests

entity_id = "550e8400-e29b-41d4-a716-446655440000"
rel = requests.post(
    f"https://api.kycgenie.com/api/v1/entities/{entity_id}/relationships/",
    headers={
        "Authorization": "Bearer YOUR_API_KEY",
        "Idempotency-Key": "rel-shareholder-660e8400-550e8400",
    },
    json={
        "from_entity": "660e8400-e29b-41d4-a716-446655440001",
        "to_entity": entity_id,
        "role": "shareholder",
        "ownership_percentage": 25,
        "status": "active",
    },
).json()
print(rel["id"])
from kycgenie import KYCGenie

client = KYCGenie(api_key="YOUR_API_KEY")

# entity_id is auto-derived from from_entity - no need to pass it separately
rel = client.entities.create_relationship(
    from_entity="660e8400-e29b-41d4-a716-446655440001",  # the individual (UBO/director)
    to_entity="550e8400-e29b-41d4-a716-446655440000",    # the company
    role="shareholder",
    ownership_percentage=25,
    status="active",
)
print(rel.id)
const entityId = '550e8400-e29b-41d4-a716-446655440000';
const rel = await fetch(
  `https://api.kycgenie.com/api/v1/entities/${entityId}/relationships/`,
  {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer YOUR_API_KEY',
      'Content-Type': 'application/json',
      'Idempotency-Key': 'rel-shareholder-660e8400-550e8400',
    },
    body: JSON.stringify({
      from_entity: '660e8400-e29b-41d4-a716-446655440001',
      to_entity: entityId,
      role: 'shareholder',
      ownership_percentage: 25,
      status: 'active',
    }),
  }
).then(r => r.json());

Response (201 Created)

{
  "id": "aa1b2c3d-e4f5-6789-abcd-ef0123456789",
  "from_entity": {
    "id": "660e8400-e29b-41d4-a716-446655440001",
    "name": "Jane Smith",
    "entity_type": "individual"
  },
  "to_entity": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "Acme Corp",
    "entity_type": "company"
  },
  "role": "shareholder",
  "role_label": "Shareholder",
  "role_title": null,
  "ownership_percentage": "25.00",
  "status": "active",
  "created_at": "2026-06-11T14:30:00Z"
}

List Relationships

curl "https://api.kycgenie.com/api/v1/entities/550e8400-e29b-41d4-a716-446655440000/relationships/" \
  -H "Authorization: Bearer YOUR_API_KEY"
import requests

entity_id = "550e8400-e29b-41d4-a716-446655440000"
data = requests.get(
    f"https://api.kycgenie.com/api/v1/entities/{entity_id}/relationships/",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
).json()

print(f"{data['count']} relationship(s)")
for rel in data["results"]:
    print(f"  {rel['from_entity']['name']} → {rel['role_label']} → {rel['to_entity']['name']}")
import kycgenie

client = kycgenie.KYCGenie(api_key="YOUR_API_KEY")

data = client.entities.list_relationships(
    entity_id="550e8400-e29b-41d4-a716-446655440000",
)
print(f"{data.count} relationship(s)")
for rel in data.results:
    print(f"{rel.from_entity.name} → {rel.role_label} → {rel.to_entity.name}")
const entityId = '550e8400-e29b-41d4-a716-446655440000';
const data = await fetch(
  `https://api.kycgenie.com/api/v1/entities/${entityId}/relationships/`,
  { headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
).then(r => r.json());

console.log(`${data.count} relationship(s)`);
data.results.forEach(r =>
  console.log(`${r.from_entity.name} → ${r.role_label} → ${r.to_entity.name}`)
);
const entityId = '550e8400-e29b-41d4-a716-446655440000';
const data = await fetch(
  `https://api.kycgenie.com/api/v1/entities/${entityId}/relationships/`,
  { headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
).then(r => r.json());

console.log(`${data.count} relationship(s)`);
data.results.forEach(r =>
  console.log(`${r.from_entity.name} → ${r.role_label} → ${r.to_entity.name}`)
);

List Response (200 OK)

{
  "count": 1,
  "results": [
    {
      "id": "aa1b2c3d-e4f5-6789-abcd-ef0123456789",
      "from_entity": { "id": "660e8400-e29b-41d4-a716-446655440001", "name": "Jane Smith", "entity_type": "individual" },
      "to_entity": { "id": "550e8400-e29b-41d4-a716-446655440000", "name": "Acme Corp", "entity_type": "company" },
      "role": "shareholder",
      "role_label": "Shareholder",
      "role_title": null,
      "ownership_percentage": "25.00",
      "status": "active",
      "created_at": "2026-06-11T14:30:00Z"
    }
  ]
}

Delete Relationship

curl -X DELETE "https://api.kycgenie.com/api/v1/entities/550e8400-e29b-41d4-a716-446655440000/relationships/aa1b2c3d-e4f5-6789-abcd-ef0123456789/" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Idempotency-Key: delete-rel-aa1b2c3d-20260611"
# 204 No Content on success
import requests

entity_id = "550e8400-e29b-41d4-a716-446655440000"
relationship_id = "aa1b2c3d-e4f5-6789-abcd-ef0123456789"

response = requests.delete(
    f"https://api.kycgenie.com/api/v1/entities/{entity_id}/relationships/{relationship_id}/",
    headers={
        "Authorization": "Bearer YOUR_API_KEY",
        "Idempotency-Key": "delete-rel-aa1b2c3d-20260611",
    },
)
# 204 No Content on success
import kycgenie

client = kycgenie.KYCGenie(api_key="YOUR_API_KEY")

client.entities.delete_relationship(
    entity_id="550e8400-e29b-41d4-a716-446655440000",
    relationship_id="aa1b2c3d-e4f5-6789-abcd-ef0123456789",
)
# 204 No Content - no return value
const entityId = '550e8400-e29b-41d4-a716-446655440000';
const relationshipId = 'aa1b2c3d-e4f5-6789-abcd-ef0123456789';

await fetch(
  `https://api.kycgenie.com/api/v1/entities/${entityId}/relationships/${relationshipId}/`,
  {
    method: 'DELETE',
    headers: {
      'Authorization': 'Bearer YOUR_API_KEY',
      'Idempotency-Key': 'delete-rel-aa1b2c3d-20260611',
    },
  }
);
// 204 No Content