> ## Documentation Index
> Fetch the complete documentation index at: https://docs.gu1.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Complete Person (KYC) Flow

> End-to-end guide for creating, enriching, and analyzing person entities with KYC validation — in the gu1 KYC API for identity verification flows.

## Overview

This guide covers the complete flow for person entity management, from creation through enrichment, KYC validation, and risk analysis. The flow is designed to be flexible, supporting both automatic and manual processes at each stage.

## Automatic vs Manual: Which Should You Use?

<Note>
  **Quick Answer**: Use **Automatic** for most cases. It handles everything in one API call and is faster to integrate.
</Note>

| Feature                    | Automatic Creation                    | Manual Creation                                                 |
| -------------------------- | ------------------------------------- | --------------------------------------------------------------- |
| **API Calls Required**     | 1 call (`POST /entities/automatic`)   | 2-3 calls (`POST /entities`, then `POST /entities/:id/analyze`) |
| **Enrichment**             | Automatic - runs in background        | Manual - you trigger it separately                              |
| **Risk Analysis**          | Automatic - executes after enrichment | Manual - you trigger it separately                              |
| **Shareholder Discovery**  | Optional - configure in request       | Not available                                                   |
| **Integration Complexity** | Simple - one-step process             | Complex - orchestrate multiple steps                            |
| **Credits Deduction**      | Automatic                             | Automatic (per operation)                                       |
| **Use When**               | Standard onboarding flows             | Need granular control over timing                               |
| **Best For**               | Production apps, batch processing     | Testing, debugging, custom workflows                            |

**When to use Manual Creation:**

* You need to collect user data incrementally over multiple steps
* You want to show users a progress indicator between stages
* You're debugging and want to inspect data between operations
* You have custom business logic between entity creation and risk analysis

## Risk Matrix Configuration

<Warning>
  **Who Defines the Risk Matrix?** You configure your risk matrix rules in the gu1 dashboard before using the API.
</Warning>

### What is a Risk Matrix?

A **Risk Matrix** is a collection of rules that define how entities are scored for risk. Think of it as your compliance playbook - it determines:

* Which data points to check (PEP status, sanctions, adverse media, etc.)
* What risk score to assign when conditions are met
* Whether to approve, reject, or flag entities for review
* Custom risk labels (Low/Medium/High) based on score ranges

### How to Configure Your Risk Matrix

1. **Log in to the gu1 Dashboard**: [https://app.gu1.ai](https://app.gu1.ai)
2. **Navigate to Risk Matrices**: Settings → Risk Matrices
3. **Create a New Matrix**: Click "New Risk Matrix"
4. **Configure Rules**: Add rules that match your compliance requirements
   * Example: "If PEP detected → add 25 points to risk score"
   * Example: "If sanctions match → reject and create alert"
5. **Set Custom Labels**: Define score ranges (e.g., 0-25: Low, 26-50: Medium, 51-100: High)
6. **Save and Copy ID**: Save the matrix and copy the UUID - you'll use this in API calls

### Using Risk Matrix in API

**Option 1: Specify in API request** (recommended for multi-tenant setups):

```json theme={null}
{
  "riskMatrixId": "uuid-of-risk-matrix"
}
```

**Option 2: Set organization default** in the dashboard:

* Navigate to Settings → Organization
* Set "Default Risk Matrix for Persons"
* All person entities will use this matrix unless overridden

### Tutorial: Setting Up Your First Risk Matrix

For a detailed walkthrough, see our guides:

* [Risk Matrix API Reference](/en/api-reference/risk-matrix/execute-risk-matrix)
* [Person Onboarding with Risk Matrix](/en/use-cases/onboarding/person-automatic-with-risk-matrix)
* [Company Onboarding with Risk Matrix](/en/use-cases/onboarding/company-automatic-with-risk-matrix)

## Flow Diagram

```mermaid theme={null}
graph TD
    A[Create Person] --> B{Automatic Creation?}
    B -->|Yes| C[POST /entities/automatic]
    B -->|No| D[POST /entities]

    C --> E[Basic Enrichment]
    E --> F[Entity Created with Data]
    F --> G[Additional Enrichments]

    D --> H[Entity Created - Basic Info Only]

    G --> I{Shareholders?}
    H --> J{Need Enrichment?}

    I -->|Yes| K[Recursive Shareholder Creation]
    I -->|No| L[Risk Matrix Assignment]

    J -->|Yes| M[POST /entities/:id/analyze with enrichment]
    J -->|No| N{Risk Matrix Assigned?}

    K --> L
    M --> N

    N -->|Yes| O[Auto Risk Analysis]
    N -->|No| P[Manual Risk Analysis]

    O --> Q[Risk Score Calculated]
    P --> R[POST /entities/:id/analyze]
    R --> Q

    Q --> S{Need KYC?}
    S -->|Yes| T[POST /kyc-validations]
    S -->|No| U[Complete]

    T --> V[User Completes KYC]
    V --> W[Webhook: KYC Status Update]
    W --> X[Re-run Risk Analysis]
    X --> U
```

## Step 1: Create Person Entity

### Option A: Automatic Creation (Recommended)

Automatic creation handles enrichment, shareholder discovery, and risk analysis in a single operation.

**Endpoint**: `POST /entities/automatic`

**Request**:

```json theme={null}
{
  "entityType": "person",
  "data": {
    "taxId": "12345678",
    "name": "John Doe",
    "countryCode": "US"
  },
  "enrichmentOptions": {
    "basic": ["identity_verification", "sanctions", "pep"],
    "additional": ["adverse_media", "legal_records"],
    "createShareholders": true,  // ⚠️ Only for company entities (KYB), not persons (KYC)
    "maxShareholderDepth": 2     // ⚠️ Only for company entities (KYB), not persons (KYC)
  },
  "skipRulesExecution": false,
  "riskMatrixId": "uuid-of-risk-matrix"  // Optional - see "Risk Matrix Configuration" below
}
```

**What happens automatically**:

1. **Basic Data Enrichment**: Executes providers from `basic` list
2. **Entity Creation**: Maps normalized data to entity structure
3. **Additional Enrichment**: Executes providers from `additional` list
4. **Shareholder Discovery**: Recursively creates shareholder entities (if enabled) - **⚠️ Companies only**
5. **Risk Matrix Assignment**: Assigns the provided risk matrix (or default)
6. **Risk Analysis**: Executes risk matrix rules automatically (unless `skipRulesExecution: true`)

<Info>
  **Note on Shareholders (createShareholders)**: This feature is only applicable for **company entities (KYB)**, not person entities (KYC).

  When verifying a **company**, you can enable `createShareholders: true` to automatically discover and create entities for all beneficial owners and corporate shareholders.

  For **person entities (KYC)**, this field is ignored since individuals don't have shareholders. If you're implementing person verification (KYC), you can omit this field entirely.
</Info>

**Response**:

```json theme={null}
{
  "entity": {
    "id": "uuid",
    "organizationId": "uuid",
    "type": "person",
    "name": "John Doe",
    "taxId": "12345678",
    "countryCode": "US",
    "riskScore": "45.00",
    "riskFactors": {
      "reasons": ["PEP match found", "Sanctions screening passed"],
      "normalizedScore": 38,
      "originalScore": 45,
      "customLabel": {
        "name": "Medium Risk",
        "color": "#f59e0b"
      }
    },
    "metadata": {
      "enrichment": {
        "hasData": true,
        "executedProviders": ["world_check", "sanctions_api", "pep_database"],
        "lastExecutedAt": "2025-12-24T10:30:00Z"
      }
    }
  },
  "enrichmentResult": {
    "success": true,
    "providers": ["world_check", "sanctions_api", "pep_database"],
    "dataQuality": 85,
    "confidence": 90
  },
  "rulesResult": {
    "success": true,
    "executed": true,
    "rulesTriggered": 3,
    "riskScore": 45
  },
  "shareholders": [
    {
      "id": "shareholder-uuid",
      "name": "Company ABC",
      "ownershipPercentage": 25
    }
  ]
}
```

### Option B: Manual Creation

Create a person entity with basic information only, then enrich and analyze separately.

**Endpoint**: `POST /entities`

**Request**:

```json theme={null}
{
  "type": "person",
  "name": "John Doe",
  "taxId": "12345678",
  "countryCode": "US",
  "entityData": {
    "person": {
      "firstName": "John",
      "lastName": "Doe",
      "dateOfBirth": "1980-01-15",
      "nationality": "US"
    }
  }
}
```

**Response**:

```json theme={null}
{
  "entity": {
    "id": "uuid",
    "organizationId": "uuid",
    "type": "person",
    "name": "John Doe",
    "taxId": "12345678",
    "countryCode": "US",
    "status": "active",
    "riskScore": null,
    "metadata": {
      "enrichment": {
        "hasData": false
      }
    }
  }
}
```

## Step 2: Enrich and Analyze (Manual Flow)

If you created the entity manually, you need to enrich it and execute risk analysis.

**Endpoint**: `POST /entities/:entityId/analyze`

**Request**:

```json theme={null}
{
  "enrichIfNeeded": true,
  "providerCodes": ["world_check", "sanctions_api", "pep_database", "adverse_media"],
  "entityType": "person"
}
```

<Accordion title="Available Provider Codes for KYC">
  **Standard Provider Codes** (most commonly used):

  * `global_gueno_validation_kyc` - **Recommended for full KYC** - Comprehensive identity verification including document + liveness + face match
  * `world_check` - PEP and sanctions screening (Refinitiv WorldCheck)
  * `sanctions_api` - Global sanctions list screening
  * `pep_database` - Politically Exposed Persons detection
  * `adverse_media` - Negative news and media monitoring
  * `legal_records` - Court records and legal proceedings
  * `identity_verification` - Basic identity validation

  **How to Choose Provider Codes:**

  1. **For Complete KYC Verification** (document + selfie + face match):
     ```json theme={null}
     "providerCodes": ["global_gueno_validation_kyc"]
     ```

  2. **For AML Screening Only** (no document upload):
     ```json theme={null}
     "providerCodes": ["world_check", "sanctions_api", "pep_database"]
     ```

  3. **For Enhanced Due Diligence**:
     ```json theme={null}
     "providerCodes": ["world_check", "sanctions_api", "pep_database", "adverse_media", "legal_records"]
     ```

  **Note**: Available providers depend on your organization's subscriptions. Contact support if you need access to specific providers.
</Accordion>

**What happens**:

1. **Optional Enrichment**: If `enrichIfNeeded: true` or `providerCodes` provided, runs enrichment first
2. **Risk Analysis**: Executes risk matrix rules on the entity
3. **Score Update**: Updates entity risk score and status

**Response**:

```json theme={null}
{
  "success": true,
  "executed": true,
  "result": {
    "entityId": "uuid",
    "entityType": "person",
    "riskScore": 45,
    "overallConfidence": 0.9,
    "totalRules": 10,
    "successfulRules": 3,
    "flags": [
      {
        "type": "PEP",
        "severity": "warning",
        "reason": "Person identified as Politically Exposed Person",
        "confidence": 0.95
      }
    ],
    "strategyEvaluation": {
      "normalizedScore": 38,
      "originalScore": 45,
      "customLabel": {
        "name": "Medium Risk",
        "minScore": 25,
        "maxScore": 50,
        "color": "#f59e0b"
      }
    }
  },
  "rulesTriggered": 3,
  "executionTimeMs": 1250
}
```

## Step 3: Enrichment Process (Deep Dive)

### How Enrichment Works

The **EnrichmentOrchestrator** service handles all enrichment operations:

1. **Provider Selection**:
   * If `providerCodes` specified: uses those specific providers
   * Otherwise: auto-selects based on organization subscriptions and entity type

2. **Balance Validation**:
   * Calculates total cost of all selected providers
   * Checks organization's credit balance
   * Throws `InsufficientBalanceError` if balance too low

3. **Parallel Execution**:
   * ALL providers execute concurrently (up to 15 simultaneous)
   * Each provider has individual timeout (default: 7.5s, judicial: 15s)
   * Failures in one provider don't affect others
   * Total execution time = slowest provider

4. **Data Normalization**:
   * Raw provider data normalized to standard format
   * Field-level conflict resolution (highest confidence, most recent, majority)
   * Intelligent merging with existing enrichment data
   * Quality scores calculated from all provider results

5. **Data Storage**:
   * `normalized_enrichment` table: normalized/mapped data
   * `enrichment_data_current` table: current enrichment snapshot
   * `audit_enrichment` table: individual provider execution audit
   * `entities.metadata.enrichment`: execution metadata cache

6. **Credit Deduction**:
   * Balance deducted only AFTER successful execution
   * Costs: varies by provider (e.g., WorldCheck: $0.50, Sanctions: $0.25)

### How Credit Management Works

<Warning>
  **Important**: Credits are deducted from your organization's balance when enrichment providers are executed successfully.
</Warning>

**Credit Deduction Flow:**

1. **Pre-validation**: Before enrichment starts, the system checks if you have sufficient balance
2. **Execution**: Providers run in parallel (you're only charged for successful executions)
3. **Deduction**: Credits are deducted AFTER successful completion (not upfront)
4. **Failed providers**: No charge if a provider fails or times out

**Typical Costs** (varies by subscription plan):

* `global_gueno_validation_kyc`: \$2.00 per verification
* `world_check`: \$0.50 per check
* `sanctions_api`: \$0.25 per screening
* `pep_database`: \$0.25 per check
* `adverse_media`: \$0.30 per search
* `legal_records`: \$0.40 per search

**Check Your Balance:**

```bash theme={null}
GET /api/billing/balance
```

**Monitor Credit Usage:**

```bash theme={null}
GET /api/billing/transactions
```

**Add Credits:**

* Navigate to [Dashboard → Billing → Credits](https://app.gu1.ai/billing/credits)
* Purchase credit packages or set up auto-reload

**Insufficient Balance Error:**

```json theme={null}
{
  "error": "Insufficient balance",
  "required": 100,
  "available": 50,
  "organizationId": "uuid"
}
```

**Solution**: Add credits to your account before running enrichment operations.

For detailed pricing and credit management, see your [Dashboard → Billing → Credits](https://app.gu1.ai/billing/credits).

### Enrichment Result Structure

```json theme={null}
{
  "success": true,
  "entityId": "uuid",
  "normalized": {
    "entityType": "person",
    "normalized": {
      "fullName": "John Doe",
      "dateOfBirth": "1980-01-15",
      "nationality": "US",
      "isPep": true,
      "sanctionsMatch": false,
      "adverseMedia": [
        {
          "title": "Business Investigation",
          "date": "2023-05-10",
          "source": "Financial Times"
        }
      ]
    },
    "providers": ["world_check", "sanctions_api", "adverse_media"],
    "dataQuality": 85,
    "confidence": 90,
    "completeness": 78
  },
  "providers": ["world_check", "sanctions_api", "adverse_media"],
  "totalCostCents": 100,
  "executionTimeMs": 3500,
  "cacheHit": false,
  "metadata": {
    "providersAttempted": 3,
    "providersSucceeded": 3,
    "providersFailed": 0,
    "dataQuality": 85,
    "confidence": 90
  }
}
```

## Step 4: Risk Analysis (Deep Dive)

### How Risk Analysis Works

The **RulesExecutionService** handles all risk analysis operations:

1. **Strategy Selection**:
   * Uses entity's assigned risk matrix
   * Risk matrix defines which rules apply and evaluation strategy

2. **Data Loading**:
   * Loads entity with enrichment data
   * Loads entity with KYC validation (if exists)
   * Prepares execution context

3. **Coverage Validation** (Person/Company only):
   * Extracts all fields required by rule conditions
   * Validates that executed providers cover all required enrichment fields
   * Validates that KYC validation exists if KYC fields required
   * Returns error with missing fields and recommended providers if incomplete

4. **Rules Execution**:
   * Filters rules by trigger event (e.g., "enrichment\_completed", "manual\_evaluation")
   * Executes rules in parallel using UniversalRulesEngine
   * Each rule evaluates conditions and executes actions if matched

5. **Score Calculation**:
   * Accumulates scores from matched rules
   * Applies evaluation strategy (score\_based or confidence\_based)
   * Normalizes score if custom labels configured
   * Calculates custom label based on score range

6. **Status Updates**:
   * Updates entity risk score and risk factors
   * Updates entity status if rules triggered status change
   * Sends ENTITY\_STATUS\_CHANGED notification

7. **Audit Trail**:
   * Creates evaluation record
   * Logs execution event
   * Creates risk analysis audit with full execution details
   * Logs alerts created by rule actions

8. **Alert Consolidation**:
   * After 5-second delay, consolidates related alerts
   * Creates or updates investigations
   * Sends appropriate notifications

### Risk Analysis Result Structure

```json theme={null}
{
  "success": true,
  "executed": true,
  "result": {
    "entityId": "uuid",
    "entityType": "person",
    "riskScore": 45,
    "overallConfidence": 0.9,
    "totalRules": 10,
    "successfulRules": 3,
    "failedRules": 0,
    "rulesExecuted": [
      {
        "ruleId": "rule-uuid",
        "ruleName": "PEP Detection",
        "executed": true,
        "conditionsMet": true,
        "confidence": 0.95,
        "executionTime": 50,
        "actionsExecuted": [
          {
            "type": "add_risk_score",
            "value": 25
          },
          {
            "type": "create_alert",
            "result": {
              "alertId": "alert-uuid"
            }
          }
        ]
      }
    ],
    "flags": [
      {
        "type": "PEP",
        "severity": "warning",
        "reason": "Person identified as Politically Exposed Person",
        "confidence": 0.95
      }
    ],
    "strategyEvaluation": {
      "strategyType": "score_based",
      "normalizedScore": 38,
      "originalScore": 45,
      "customLabel": {
        "name": "Medium Risk",
        "minScore": 25,
        "maxScore": 50,
        "color": "#f59e0b",
        "severity": "medium"
      },
      "displayRange": "25-50"
    }
  },
  "rulesTriggered": 3,
  "executionTimeMs": 1250,
  "auditId": "audit-uuid"
}
```

## Step 5: KYC Validation (Optional)

If your risk matrix rules require KYC validation fields (like `kyc.documentVerified`, `kyc.livenessCheck`), you need to create a KYC validation.

### Create KYC Validation

**Endpoint**: `POST /kyc-validations`

**Request**:

```json theme={null}
{
  "entityId": "uuid",
  "provider": "persona",
  "templateId": "tmpl_ABC123",
  "requiredFields": ["government_id", "selfie"],
  "callbackUrl": "https://your-app.com/webhooks/kyc"
}
```

**Response**:

```json theme={null}
{
  "validation": {
    "id": "kyc-uuid",
    "entityId": "entity-uuid",
    "provider": "persona",
    "status": "pending",
    "validationUrl": "https://kyc-provider.com/start?token=abc123",
    "expiresAt": "2025-12-31T23:59:59Z"
  }
}
```

### User Completes KYC

1. Send user to `validationUrl`
2. User completes KYC flow (uploads documents, takes selfie, etc.)
3. KYC provider sends webhook to your `callbackUrl`

### Webhook: KYC Status Update

When KYC is completed, your webhook receives:

```json theme={null}
{
  "event": "kyc.completed",
  "validationId": "kyc-uuid",
  "entityId": "entity-uuid",
  "status": "approved",
  "data": {
    "documentVerified": true,
    "livenessCheck": true,
    "faceMatch": 98.5,
    "documentType": "passport",
    "documentNumber": "AB1234567",
    "verifiedAt": "2025-12-24T15:30:00Z"
  }
}
```

### Re-run Risk Analysis After KYC

Once KYC is completed, re-run risk analysis to evaluate KYC-dependent rules:

**Endpoint**: `POST /entities/:entityId/analyze`

**Request**:

```json theme={null}
{
  "enrichIfNeeded": false,
  "entityType": "person"
}
```

Now rules that check `kyc.*` fields will evaluate properly and the entity's final risk score will be calculated.

## Step 6: Monitor and Manage

### Query Entity Status

**Endpoint**: `GET /entities/:entityId`

**Response includes**:

* Current risk score (normalized and original)
* Risk factors and flags
* Enrichment status and providers used
* KYC validation status
* Last risk evaluation timestamp

### View Risk Analysis History

**Endpoint**: `GET /risk-analysis-audits?entityId=:entityId`

**Returns**:

* All risk analysis executions
* Rules matched in each execution
* Score changes over time
* Enrichment data used

### View Alerts and Investigations

**Endpoint**: `GET /investigations?entityId=:entityId`

**Returns**:

* Consolidated alerts related to the entity
* Investigation status and priority
* Assigned analysts and resolution notes

## Best Practices

1. **Use Automatic Creation**: For most cases, use `POST /entities/automatic` to handle enrichment and risk analysis in one operation.

2. **Balance Management**: Always ensure sufficient credits before enrichment. Monitor balance using `GET /billing/balance`.

3. **Provider Selection**: Use specific `providerCodes` when you know which data you need. Auto-selection may include unnecessary providers.

4. **Risk Matrix Assignment**: Always assign a risk matrix when creating entities. Without a risk matrix, risk analysis won't execute for person/company entities.

5. **KYC Timing**: Initiate KYC validation early in the onboarding flow. Some rules may require KYC data.

6. **Coverage Validation**: If risk analysis fails due to incomplete coverage, check the `metadata.missingFields` and run the recommended providers.

7. **Webhook Security**: Always validate webhook signatures from KYC providers to prevent spoofing.

8. **Monitoring**: Set up alerts for high-risk entities and failed enrichments.

## Error Handling

### Common Errors

**Insufficient Balance**:

```json theme={null}
{
  "error": "Insufficient balance",
  "required": 100,
  "available": 50,
  "organizationId": "uuid"
}
```

**Solution**: Add credits to organization billing account.

**Incomplete Coverage**:

```json theme={null}
{
  "success": false,
  "error": "Incomplete data coverage",
  "warnings": [
    "Field 'sanctions.matches' requires provider: world_check or sanctions_api",
    "Field 'kyc.documentVerified' requires KYC validation"
  ],
  "metadata": {
    "missingFields": [...],
    "recommendedProviders": ["world_check", "sanctions_api"]
  }
}
```

**Solution**: Run recommended providers or create KYC validation, then re-analyze.

**No Risk Matrix**:

```json theme={null}
{
  "success": true,
  "executed": false,
  "error": "No risk matrix assigned to person entity. Please assign a Risk Matrix to enable rule execution."
}
```

**Solution**: Assign a risk matrix to the entity using `PATCH /entities/:id`.

## Next Steps

* [Risk Matrix API Reference](/en/api-reference/risk-matrix/execute-risk-matrix)
* [Set Up Webhooks](/en/use-cases/kyc/webhook-integration)
* [KYC Client Integration Guide](/en/use-cases/kyc/client-integration)
* [Check KYC Status](/en/use-cases/kyc/check-status)
