Multi-Level Related Entities — Migration Guide & FAQ

Last updated: June 16, 2026

Who this is for

This guide is for customers who consume AiPrise Business Verification (KYB) over the API. It explains what's changing with Multi-Level Related Entities (v2), what (if anything) you need to update in your integration, and how to migrate quickly. If you only use the AiPrise Dashboard, you don't need to do anything — the new experience is automatic.


TL;DR

  • AiPrise is upgrading how related entities (owners, officers, parent/child companies, beneficial owners) are represented — moving from a flat, single-level list to a multi-level network where each related entity can itself have its own related entities.

  • This unlocks the Related Entities Network view (full ownership graph) and gives you a much richer ownership and control picture for complex corporate structures.

  • The new shape is exposed through v2 response fields and v2 API endpoints.

  • Nothing changes until you opt in. Until you opt in to v2, you'll receive the response exactly as you're getting it now. Nothing breaks on day one.

  • Want a head start? A ready-made prompt at the end of this guide lets you scaffold most of the v2 integration using an AI coding assistant (Claude Code, Cursor, etc.).


What is changing?

Before: Single-Level (v1)

In the v1 model, a business profile had two flat lists:

  • related_people — directors, officers, beneficial owners, etc.

  • related_companies — parent/subsidiary/affiliated companies.

Each entry was a self-contained snapshot. A related company could not carry its own related persons or related companies. So a structure like:

Acme Holdings  ->  owned by  ->  Global Parent Ltd  ->  owned by  ->  Apex Trust

…had to be collapsed into a single flat list. You lost the chain of ownership: you could see who was related, but not how entities related to each other.

After: Multi-Level (v2)

In the v2 model, every related entity is a node in a network. Each related person or company can carry its own related_people and related_companies. This lets AiPrise represent real-world ownership and control hierarchies:

Acme Holdings (root business profile)
├── Related Person: Jane Doe        (25%, Beneficial Owner)
├── Related Person: Simon Bailey    (Director)
└── Related Company: Global Parent Ltd   (60%, PARENT)
        ├── Related Person: Andrew Raggett   (Director)
        └── Related Company: Apex Trust      (100%, PARENT)

This is what powers the Related Entities Network visualization in the dashboard.

image.png

A related company is a full business profile of its own. When you add a company as a related company, it gets its own business_profile (and business_profile_id). That means you can do all the usual profile operations on it, just like any top-level business profile: run verification (KYB) on it, fetch it, update it, add its own related persons/companies, and monitor it.

The same is true for a related person: each is a full user profile you can verify (KYC) and manage independently.

You can also link an existing business profile as a related company (or link an existing user as a related person) instead of creating a brand-new one. This is handy when the entity already exists in your account.


Key concepts & new fields

Concept

v1 (single-level)

v2 (multi-level)

Related person identity

Inline fields (first_name, last_name, birth_date, …)

Nested user_profile object (full profile with KYC, identity & AML data)

Related company identity

Inline fields (name, tax_identification_number, …)

Nested business_profile object (full profile, can nest further)

Stable identifier

n/a

person_reference_id / company_reference_id

Relationship kind

Implicit / via roles

Explicit relationship_type

Nesting

Not supported

Each entity carries its own related_people / related_companies

Reverse / cross-source links

other_relationship_data[] (who else points to this entity)

Format marker

n/a

version: "v2" on each entity

relationship_type values

  • For companies: PARENT, CHILD, SIBLING, UNKNOWN

  • For persons: describes the person's relationship to the entity (e.g. BENEFICIAL_OWNER, DIRECTOR, UNKNOWN)

Fields that carry over (unchanged meaning)

ownership_percent, shares_allocated, and roles[] (each role has name, start_date, end_date, is_active) exist in both v1 and v2.


Will my existing integration break?

No. This is the most important point.

Backward compatible by default. Until your account is opted in to the v2 related-entities format, you'll keep receiving the response exactly as you're getting it now for related_people and related_companies. Your current parsing code keeps working with zero changes.

You only need to take action when you want the richer multi-level data. Opting in is a deliberate choice, not a forced upgrade.


What do I need to update if I use the API? (v2 opt-in)

If and when you choose to adopt v2, here's the checklist.

1. Enable the v2 format on your account

The Related Person / Company Response Format is an account-level setting that AiPrise configures for you. It can be set to v1 or v2 (default: v1). Both formats are documented in the response of the Get Business Profile API. Contact your AiPrise representative or support to enable v2 for your company.

This setting controls the shape of related_people / related_companies returned by the Get Business Profile and Get Business Verification Result APIs and in your callbacks. It matters to anyone who reads related-person/company data from the API response or from callbacks.

Rollout happens Sandbox-first. AiPrise enables v2 on your Sandbox environment first. You build and validate against the new APIs there, and only once everything looks good (and you're satisfied) is Production migrated. The migration itself is atomic: if anything fails it rolls back fully, so there's never a partial/half-migrated state. The change is also reversible while you're validating.

2. Update how you read related persons

What you read today (v1)

What to read instead (v2)

related_people[].first_name

related_people[].user_profile.first_name

related_people[].last_name

related_people[].user_profile.last_name

related_people[].full_name

related_people[].user_profile.full_name

related_people[].birth_date

related_people[].user_profile.date_of_birth

related_people[].email

related_people[].user_profile.email_address

related_people[].phone_number

related_people[].user_profile.phone_number

related_people[].address

related_people[].user_profile.address

related_people[].kyc

related_people[].user_profile (KYC / identity / AML live inside the profile)

Plus new fields available in v2: person_reference_id, relationship_type, other_relationship_data[].

3. Update how you read related companies

What you read today (v1)

What to read instead (v2)

related_companies[].name

related_companies[].business_profile.name

related_companies[].tax_identification_number

related_companies[].business_profile.tax_identification_number

related_companies[].formation_date

related_companies[].business_profile.formation_date

related_companies[].country_code

related_companies[].business_profile.country_code

related_companies[].website

related_companies[].business_profile.website

related_companies[].email_addresses

related_companies[].business_profile.email_addresses

related_companies[].phone_numbers

related_companies[].business_profile.phone_numbers

related_companies[].kyb

related_companies[].business_profile.risk_info (verification result lives on the nested profile)

Plus new fields available in v2: company_reference_id, relationship_type, other_relationship_data[], and, crucially, nested business_profile.related_people[] and business_profile.related_companies[].

4. Handle nested entities

This is the real conceptual change. In v1 you iterated one flat list. In v2 a related company's business_profile can itself contain related_people[] and related_companies[], so to capture the full ownership network you should traverse those nested entities rather than reading a single level.

Guard against deep / cyclic graphs. Real ownership networks can be deep and can contain loops (Company A owns B owns A). Cap how deep you traverse and de-duplicate by company_reference_id / person_reference_id to avoid processing the same entity twice.

5. Switch to the v2 management endpoints (if you write data)

If your integration adds, edits, or removes related entities (not just reads results), this is the bulk of the work: move from the legacy endpoints to the new v2 endpoints. Code these up first. Your account is only migrated once your integration is ready to use them.

Related Person APIs

Action

v2 endpoint

Docs

Add related person

POST /verify/related_person_v2

link

Edit related person

PUT /verify/related_person_v2

link

Delete related person (profile + association)

POST /verify/delete_related_person_v2

link

Delete association only (keep the user profile)

DELETE /verify/related_person_association_v2/{business_profile_id}/{person_reference_id}

link

Link an existing user as a related person

POST /verify/link_existing_user_as_related_person_v2

link

Run checks (KYC) on a related person

POST /verify/run_verification_for_user_profile_id

link

Related Company APIs

Action

v2 endpoint

Docs

Add related company

POST /verify/related_company_v2

link

Edit related company

PUT /verify/related_company_v2

link

Delete related company (profile + association)

POST /verify/delete_related_company_v2

link

Delete association only (keep the business profile)

DELETE /verify/related_company_association_v2/{business_profile_id}/{company_reference_id}

link

Link an existing business as a related company

POST /verify/link_existing_business_as_related_company_v2

link

Run checks (KYB) on a related company

POST /verify/run_verification_for_business_profile_id

link

New in v2: delete semantics. v2 separates removing the relationship from deleting the underlying entity. Use the association-only delete to detach a person/company from a profile while keeping their own profile (and history) intact; use the full delete to remove both.

The v2 add-company request now takes a nested business_profile object plus an explicit relationship_type (PARENT / CHILD / SIBLING / UNKNOWN), and returns { business_profile_id, company_reference_id }. The legacy add_* / update_* / remove_* endpoints are flagged as legacy in the API reference, with the note that new integrations should use V2.

6. Update your webhook/callback parsing

Your decision callback (callback_url) and event callback (events_callback_url) carry the same verification response shape as the GET result endpoint. So:

  • Before opt-in: callbacks contain the v1 shape, so no change is needed.

  • After opt-in: callbacks contain the v2 nested shape, so apply the same parsing updates from steps 2 to 4 to your webhook handler.


API endpoints reference

Base URLs: Sandbox https://api-sandbox.aiprise.com/api/v1/, Production https://api.aiprise.com/api/v1/. Auth: send your API key in the X-API-KEY header.

📌 The Get Business Profile API is where the new related-person/company response format (v1 or v2) is documented and returned. Start there when validating your parsing.

Purpose

Endpoint

Docs

Get business profile (returns related entities in v1/v2 format)

GET /verify/get_business_profile/{business_profile_id}

link

Get business verification result

GET /verify/get_business_verification_result/{verification_session_id}

link

Create business profile

POST /verify/create_business_profile

link

Run business verification

POST /verify/run_business_verification

link

For the full v2 Related Person and Related Company management endpoints (add / edit / delete / link / run-checks), see the two tables in step 5 above.

Full API reference: https://docs.aiprise.com/reference · Business Profiles guide: https://docs.aiprise.com/docs/business-profiles


Side-by-side response examples

v1: flat (current default)

{
  "verification_session_id": "vs_abc123",
  "aiprise_summary": { "verification_result": "APPROVED" },
  "related_people": [
    {
      "full_name": "Jane Doe",
      "birth_date": "1980-05-01",
      "email": "jane@acme.com",
      "ownership_percent": 25,
      "roles": [{ "name": "Director", "is_active": true }]
    }
  ],
  "related_companies": [
    {
      "name": "Global Parent Ltd",
      "tax_identification_number": "GB123456",
      "country_code": "GB",
      "ownership_percent": 60,
      "roles": [{ "name": "Parent", "is_active": true }]
    }
  ]
}

v2: multi-level (after opt-in)

{
  "verification_session_id": "vs_abc123",
  "aiprise_summary": { "verification_result": "APPROVED" },
  "related_people": [
    {
      "version": "v2",
      "person_reference_id": "per_9f8e...",
      "relationship_type": "BENEFICIAL_OWNER",
      "ownership_percent": 25,
      "shares_allocated": 250,
      "user_profile": {
        "full_name": "Jane Doe",
        "date_of_birth": "1980-05-01",
        "email_address": "jane@acme.com",
        "phone_number": "+44...",
        "address": { "full_address": "..." }
      },
      "roles": [{ "name": "Director", "is_active": true }],
      "other_relationship_data": []
    }
  ],
  "related_companies": [
    {
      "version": "v2",
      "company_reference_id": "com_1a2b...",
      "relationship_type": "PARENT",
      "ownership_percent": 60,
      "business_profile": {
        "business_profile_id": "bp_parent_001",
        "name": "Global Parent Ltd",
        "tax_identification_number": "GB123456",
        "country_code": "GB",
        "risk_info": { "verification_result": "APPROVED" },

        "related_companies": [
          {
            "version": "v2",
            "company_reference_id": "com_3c4d...",
            "relationship_type": "PARENT",
            "ownership_percent": 100,
            "business_profile": {
              "business_profile_id": "bp_apex_001",
              "name": "Apex Trust",
              "country_code": "GB"
            }
          }
        ],
        "related_people": []
      },
      "roles": [{ "name": "Parent", "is_active": true }],
      "other_relationship_data": []
    }
  ]
}

Notice how Apex Trust is nested inside Global Parent Ltd, which is itself a related company of the root — so the full ownership chain is preserved.


FAQ

Q: Should I migrate? Yes, we recommend it. v1 still works, but v2 unlocks the full ownership network, beneficial-owner chains, and verification + monitoring on every related entity — and it's where all new capabilities will land. Migrate at your own pace, with Sandbox to validate first.

Q: Will my current integration break when this rolls out? No. Until you explicitly opt in to v2, you'll keep receiving the response exactly as you're getting it now.

Q: How do I turn on v2? Ask your AiPrise representative / support to enable the v2 related-entities format on your account. The recommended order is: (1) you code up the new v2 APIs, (2) AiPrise enables v2 on Sandbox and you validate, (3) once you're satisfied, AiPrise migrates Production.

Q: Can I preview v2 without affecting production? Yes. Sandbox is migrated first. Test against the Sandbox base URL (https://api-sandbox.aiprise.com/api/v1/) before Production is touched. If something isn't right, the Sandbox migration can be reversed.

Q: What are the biggest code changes? Two things. (1) The CRUD APIs for managing related entities are changing — if you add, edit, delete, or link related persons/companies, you must move those calls to the new v2 endpoints (see step 5), which also introduce the association-only vs. full-delete distinction. (2) On the read side, you move from iterating one flat list to traversing the nested related-entities tree, reading person/company details from the nested user_profile / business_profile objects instead of top-level fields.


Bonus: Let Claude migrate you from v1 → v2

To help you get started with the v2 integration, paste the prompt below into an AI coding assistant (Claude Code, Cursor, etc.) and fill in the [bracketed] parts. Think of it as a head start, not a finished migration — it gets the bulk of the changes scaffolded, and you should still review, test, and refine the output for your own codebase.

💡 Point the assistant at the code where you call the AiPrise business verification result endpoint and where you handle the verification webhook/callback. The more context you give it about your codebase, the better the starting point.

I integrate with the AiPrise Business Verification (KYB) API. AiPrise is upgrading
"related entities" from a flat single-level list (v1) to a nested multi-level network (v2),
and I want to migrate my integration to consume the v2 response format.

Context on the schema change:
- The verification result endpoint is
  GET /verify/get_business_verification_result/{verification_session_id}
  and the same response shape is delivered to my webhook (callback_url / events_callback_url).
- In v1, related_people[] and related_companies[] are FLAT. Person details
  (first_name, last_name, full_name, birth_date, email, phone_number, address, kyc) and
  company details (name, tax_identification_number, formation_date, country_code, website,
  email_addresses, phone_numbers, kyb) live as TOP-LEVEL fields on each entry.
- In v2, each entry is a node in a network:
    * Each related person has: version:"v2", person_reference_id, relationship_type,
      ownership_percent, shares_allocated, roles[], other_relationship_data[], and a NESTED
      user_profile object holding identity/KYC fields. Mapping:
        first_name      -> user_profile.first_name
        last_name       -> user_profile.last_name
        full_name       -> user_profile.full_name
        birth_date      -> user_profile.date_of_birth
        email           -> user_profile.email_address
        phone_number    -> user_profile.phone_number
        address         -> user_profile.address
        kyc             -> data lives inside user_profile
    * Each related company has: version:"v2", company_reference_id, relationship_type
      (PARENT | CHILD | SIBLING | UNKNOWN), ownership_percent, shares_allocated, roles[],
      other_relationship_data[], and a NESTED business_profile object. Mapping:
        name                        -> business_profile.name
        tax_identification_number   -> business_profile.tax_identification_number
        formation_date              -> business_profile.formation_date
        country_code                -> business_profile.country_code
        website                     -> business_profile.website
        email_addresses             -> business_profile.email_addresses
        phone_numbers               -> business_profile.phone_numbers
        kyb / result                -> business_profile.risk_info
    * CRITICAL: a related company's nested business_profile can itself contain
      related_people[] and related_companies[], recursively (multi-level).
- ownership_percent, shares_allocated, and roles[] (name, start_date, end_date, is_active)
  are unchanged and sit at the relationship level in both versions.

What I want you to do in my code at [PATH(S) TO MY AIPRISE PARSING CODE]:
1. Find every place I read AiPrise related_people / related_companies fields and update
   them to read from the nested user_profile / business_profile objects per the mapping above.
2. Replace any flat single-pass iteration over related_companies with a RECURSIVE traversal
   that also walks each company's nested related_people / related_companies. Cap recursion
   depth (e.g. 25) and de-duplicate by company_reference_id / person_reference_id to handle
   cyclic ownership graphs safely.
3. If I add/update/remove related entities via the API, switch my calls from the legacy
   endpoints to the v2 endpoints:
     Related companies:
       add     POST   /verify/related_company_v2
       edit    PUT    /verify/related_company_v2
       delete (profile + association)  POST /verify/delete_related_company_v2
       delete (association only)       DELETE /verify/related_company_association_v2/{business_profile_id}/{company_reference_id}
       link existing business          POST /verify/link_existing_business_as_related_company_v2
       run KYB on it                   POST /verify/run_verification_for_business_profile_id
     Related persons:
       add     POST   /verify/related_person_v2
       edit    PUT    /verify/related_person_v2
       delete (profile + association)  POST /verify/delete_related_person_v2
       delete (association only)       DELETE /verify/related_person_association_v2/{business_profile_id}/{person_reference_id}
       link existing user              POST /verify/link_existing_user_as_related_person_v2
       run KYC on it                   POST /verify/run_verification_for_user_profile_id
   The v2 add-company body takes a nested business_profile object plus an explicit
   relationship_type. Note the new distinction between deleting the association only
   vs. deleting the underlying profile + association.
4. Apply the same parsing updates to my webhook/callback handler.
5. Add or update unit tests with sample v1 and v2 payloads to prove both parse correctly,
   including a 2+ level nested company example.

My stack is [LANGUAGE/FRAMEWORK]. Show me a diff and explain the changes. Reference the
AiPrise API docs at https://docs.aiprise.com/reference if you need endpoint details.

Need help? Reach out to your AiPrise representative or support@aiprise.com. We can enable the v2 format on a Sandbox account so you can test the migration end-to-end before flipping production.