> ## 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.

# Automatic Person Onboarding with Risk Assessment

> Onboard persons automatically with enrichment, compliance screening, and risk matrix execution in the gu1 automated onboarding flow with risk scoring.

## Overview

This guide demonstrates the complete automated onboarding flow for persons (individuals/customers) using gu1's automatic entity creation with integrated risk assessment. The system will:

1. **Fetch official data** from government registries (e.g., CPF in Brazil)
2. **Execute enrichments** to gather additional information
3. **Run compliance enrichments** (PEP, sanctions, adverse media screening)
4. **Execute risk matrix rules** to assess risk automatically
5. **Generate alerts and investigations** if rules are triggered
6. **Send notifications** via Socket.IO and webhooks

This is ideal for KYC (Know Your Customer) processes where you want complete automation from data collection to risk assessment.

## Prerequisites

Before starting, you need:

1. **API Key** - Get one from [API Keys (`/org-api-keys`)](https://app.gu1.ai/org-api-keys)
2. **Risk Matrix** - Create and configure a risk matrix with rules for the `entity_created` trigger
3. **Active Integrations** - Enable enrichment providers from the Marketplace
4. **Valid Tax ID** - A real tax ID from a supported country (e.g., CPF for Brazil)

## The Complete Flow

Here's what happens when you create a person automatically with a risk matrix:

```mermaid theme={null}
sequenceDiagram
    participant API as Your App
    participant Gu1 as gu1 API
    participant Registry as Gov Registry
    participant Providers as Data Providers
    participant Rules as Rules Engine
    participant Notify as Notifications

    API->>Gu1: POST /entities/automatic
    Note over Gu1: 1. Validate request

    Gu1->>Registry: Fetch basic data (CPF)
    Registry-->>Gu1: Person details

    Note over Gu1: 2. Create entity
    Gu1->>Gu1: Insert into database

    Note over Gu1: 3. Execute enrichments
    Gu1->>Providers: serpro_cpf, bureau_credit
    Providers-->>Gu1: Enriched data

    Note over Gu1: 4. Execute enrichments (PEP, sanctions)
    Gu1->>Providers: br_amldd_pep_enrichment, global_gueno_sanctions_enrichment
    Providers-->>Gu1: Enrichment results

    Note over Gu1: 5. Execute risk matrix
    Gu1->>Rules: Trigger: entity_created
    Rules->>Rules: Evaluate all rules
    Rules-->>Gu1: Risk score + alerts

    Note over Gu1: 6. Update entity
    Gu1->>Gu1: Update risk score & status

    Note over Gu1: 7. Send notifications
    Gu1->>Notify: Socket.IO event
    Gu1->>Notify: Webhook event
    Gu1->>Notify: Email/SMS (optional)

    Gu1-->>API: Complete result
```

## Quick Start Example

### Basic Person Onboarding with Risk Assessment

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.gu1.ai/entities/automatic \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "taxId": "123.456.789-00",
      "country": "BR",
      "type": "person",
      "isClient": true,
      "riskMatrixId": "risk_matrix_uuid",
      "autoExecuteIntegrations": {
        "executeAllActiveEnrichments": true,
      }
    }'
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch('https://api.gu1.ai/entities/automatic', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      taxId: '123.456.789-00',
      country: 'BR',
      type: 'person',
      isClient: true,
      riskMatrixId: 'risk_matrix_uuid',
      autoExecuteIntegrations: {
        executeAllActiveEnrichments: true,
      }
    })
  });

  const result = await response.json();
  console.log('Person created:', result.data.entity);
  console.log('Risk score:', result.rulesResult?.result?.riskScore);
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      'https://api.gu1.ai/entities/automatic',
      headers={
          'Authorization': 'Bearer YOUR_API_KEY',
          'Content-Type': 'application/json'
      },
      json={
          'taxId': '123.456.789-00',
          'country': 'BR',
          'type': 'person',
          'isClient': True,
          'riskMatrixId': 'risk_matrix_uuid',
          'autoExecuteIntegrations': {
              'executeAllActiveEnrichments': True,
          }
      }
  )

  result = response.json()
  print('Person created:', result['data']['entity'])
  print('Risk score:', result['rulesResult']['result']['riskScore'])
  ```
</CodeGroup>

## Complete Response Example

When the process completes successfully, you'll receive a comprehensive response:

```json theme={null}
{
  "success": true,
  "data": {
    "entity": {
      "id": "person_uuid_abc123",
      "organizationId": "org_uuid",
      "type": "person",
      "name": "João Silva",
      "taxId": "12345678900",
      "countryCode": "BR",
      "status": "under_review",
      "riskScore": 35,
      "isClient": true,
      "entityData": {
        "person": {
          "firstName": "João",
          "lastName": "Silva",
          "dateOfBirth": "1985-05-15",
          "nationality": "BR",
          "gender": "M",
          "motherName": "Maria Silva"
        }
      },
      "enrichmentData": {
        "serpro_cpf": {
          "status": "REGULAR",
          "situation": "ATIVA"
        },
        "bureau_credit": {
          "score": 720,
          "rating": "GOOD"
        },
        "br_amldd_pep_enrichment": {
          "isPep": false
        },
        "global_gueno_sanctions_enrichment": {
          "hasMatches": false
        }
      },
      "createdAt": "2024-12-23T10:30:00.000Z",
      "updatedAt": "2024-12-23T10:30:05.000Z"
    },
    "summary": {
      "entitiesCreated": 1,
      "relationshipsCreated": 0,
      "errorsCount": 0
    }
  },
  "rulesResult": {
    "success": true,
    "executed": true,
    "result": {
      "entityId": "person_uuid_abc123",
      "entityType": "person",
      "riskScore": 35,
      "overallConfidence": 0.95,
      "totalRules": 12,
      "successfulRules": 3,
      "failedRules": 0,
      "rulesExecuted": [
        {
          "ruleId": "rule_age_verification",
          "ruleName": "Age Verification",
          "matched": true,
          "score": 0,
          "confidence": 1.0
        },
        {
          "ruleId": "rule_high_credit_score",
          "ruleName": "High Credit Score",
          "matched": true,
          "score": -15,
          "confidence": 0.9
        },
        {
          "ruleId": "rule_br_amldd_pep_enrichment",
          "ruleName": "PEP screening",
          "matched": true,
          "score": 50,
          "confidence": 1.0,
          "alert": {
            "id": "alert_uuid",
            "severity": "MEDIUM",
            "message": "Person has PEP match"
          }
        }
      ],
      "flags": [
        {
          "type": "AGE_VERIFIED",
          "severity": "INFO",
          "message": "Person is over 18 years old"
        }
      ]
    },
    "executionTimeMs": 2450,
    "rulesTriggered": 3
  }
}
```

## Step-by-Step Implementation

### Step 1: Set Up Your Risk Matrix

Before creating entities, configure your risk matrix with rules:

```javascript theme={null}
// Create a risk matrix for person onboarding
const riskMatrix = await fetch('https://api.gu1.ai/risk-matrices', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    name: 'Person Onboarding Risk Matrix',
    description: 'Evaluate risk for new person entities',
    enabled: true,
    rules: [
      {
        name: 'PEP screening',
        description: 'Flag if person is politically exposed',
        condition: 'enrichment.br_amldd_pep_enrichment.isPep === true',
        score: 50,
        severity: 'HIGH',
        triggers: ['entity_created'],
        targetEntityTypes: ['person'],
        enabled: true
      },
      {
        name: 'Sanctions screening',
        description: 'Flag if person is in sanctions lists',
        condition: 'enrichment.global_gueno_sanctions_enrichment.hasMatches === true',
        score: 100,
        severity: 'CRITICAL',
        triggers: ['entity_created'],
        targetEntityTypes: ['person'],
        enabled: true
      },
      {
        name: 'Low Credit Score',
        description: 'Flag if credit score is below 600',
        condition: 'enrichment.bureau_credit.score < 600',
        score: 30,
        severity: 'MEDIUM',
        triggers: ['entity_created'],
        targetEntityTypes: ['person'],
        enabled: true
      }
    ]
  })
});

const { id: riskMatrixId } = await riskMatrix.json();
console.log('Risk Matrix created:', riskMatrixId);
```

See [Risk Matrix API Reference](/en/api-reference/risk-matrix/create) for more details.

### Step 2: Create Person with Specific Integrations

Instead of running all active integrations, you can specify which ones to execute:

```javascript theme={null}
async function onboardPerson(taxId) {
  const response = await fetch('https://api.gu1.ai/entities/automatic', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      taxId: taxId,
      country: 'BR',
      type: 'person',
      externalId: `customer_${Date.now()}`,
      isClient: true,
      riskMatrixId: 'your_risk_matrix_id',
      status: 'under_review',
      autoExecuteIntegrations: {
        executeAllActiveEnrichments: false,
        enrichments: [
          'serpro_cpf',
          'bureau_credit',
          'br_amldd_pep_enrichment',
          'global_gueno_sanctions_enrichment',
          'br_bdc_negative_media_enrichment'
        ]
      }
    })
  });

  const result = await response.json();

  if (!result.success) {
    throw new Error(result.error);
  }

  return result;
}

// Usage
try {
  const result = await onboardPerson('123.456.789-00');

  console.log('✅ Person onboarded successfully!');
  console.log('Entity ID:', result.data.entity.id);
  console.log('Risk Score:', result.rulesResult?.result?.riskScore);
  console.log('Status:', result.data.entity.status);

  // Check if any alerts were generated
  const alerts = result.rulesResult?.result?.rulesExecuted
    ?.filter(rule => rule.alert)
    .map(rule => rule.alert);

  if (alerts && alerts.length > 0) {
    console.log('⚠️  Alerts generated:', alerts.length);
    alerts.forEach(alert => {
      console.log(`  - [${alert.severity}] ${alert.message}`);
    });
  }

} catch (error) {
  console.error('❌ Onboarding failed:', error.message);
}
```

### Step 3: Handle Real-Time Updates with Socket.IO

Listen for real-time events during the onboarding process:

```javascript theme={null}
import { io } from 'socket.io-client';

// Connect to gu1's Socket.IO server
const socket = io('https://api.gu1.ai', {
  auth: {
    token: 'YOUR_API_KEY'
  },
  query: {
    organizationId: 'your_org_id'
  }
});

// Listen for entity creation started
socket.on('entity:creation-started', (data) => {
  console.log('🚀 Creation started:', data.taxId);
  // Show loading UI
});

// Listen for entity creation completed
socket.on('entity:creation-completed', (data) => {
  console.log('✅ Creation completed:', {
    entityId: data.mainEntityId,
    name: data.mainEntityName,
    riskScore: data.riskScore
  });
  // Update UI with entity details
});

// Listen for risk matrix execution completed
socket.on('risk-matrix:executed', (data) => {
  console.log('🎯 Risk assessment completed:', {
    entityId: data.entityId,
    riskScore: data.riskScore,
    alertsCount: data.alertsGenerated
  });
  // Show risk score in UI
});

// Listen for new alerts
socket.on('alert:created', (data) => {
  console.log('⚠️  New alert:', {
    severity: data.severity,
    message: data.message,
    entityId: data.entityId
  });
  // Show alert notification
});

// Listen for investigations
socket.on('investigation:created', (data) => {
  console.log('🔍 Investigation created:', {
    id: data.investigationId,
    priority: data.priority,
    alertsCount: data.consolidatedAlerts
  });
  // Redirect to investigation page
});
```

### Step 4: Handle Risk-Based Workflows

Based on the risk score and alerts, implement different workflows:

```javascript theme={null}
async function handleOnboardingResult(result) {
  const { entity } = result.data;
  const riskScore = result.rulesResult?.result?.riskScore || 0;
  const alerts = result.rulesResult?.result?.rulesExecuted
    ?.filter(rule => rule.alert) || [];

  // Risk-based decision logic
  if (riskScore >= 80) {
    // High Risk - Manual Review Required
    await createManualReviewTask(entity.id, {
      priority: 'HIGH',
      reason: 'High risk score detected',
      riskScore,
      alerts: alerts.length
    });

    await notifyComplianceTeam(entity, riskScore, alerts);
    await updateEntityStatus(entity.id, 'under_review');

    return {
      decision: 'MANUAL_REVIEW',
      action: 'HOLD',
      message: 'Manual review required due to high risk'
    };

  } else if (riskScore >= 50 || alerts.length > 0) {
    // Medium Risk - Enhanced Due Diligence
    await requestAdditionalDocuments(entity.id, [
      'proof_of_address',
      'proof_of_income',
      'bank_statement'
    ]);

    await updateEntityStatus(entity.id, 'under_review');

    return {
      decision: 'ENHANCED_DUE_DILIGENCE',
      action: 'REQUEST_DOCS',
      message: 'Additional documentation required'
    };

  } else {
    // Low Risk - Auto-Approve
    await updateEntityStatus(entity.id, 'active');
    await enableCustomerAccount(entity.id);
    await sendWelcomeEmail(entity);

    return {
      decision: 'APPROVED',
      action: 'ACTIVATE',
      message: 'Customer approved and activated'
    };
  }
}

// Helper functions
async function createManualReviewTask(entityId, details) {
  await fetch('https://api.gu1.ai/tasks', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      type: 'manual_review',
      entityId: entityId,
      priority: details.priority,
      assignTo: 'compliance_team',
      dueDate: new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString(),
      context: details
    })
  });
}

async function updateEntityStatus(entityId, status) {
  await fetch(`https://api.gu1.ai/entities/${entityId}`, {
    method: 'PATCH',
    headers: {
      'Authorization': 'Bearer YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ status })
  });
}
```

## Understanding the Rules Engine Integration

### How Risk Matrices Work

When you set `riskMatrixId` in your request, the system automatically:

1. **Creates the entity** with basic data from official registries
2. **Executes enrichments** to gather additional information
3. **Executes enrichments** for compliance screening (PEP, sanctions, etc.)
4. **Triggers the risk matrix** with the `entity_created` trigger
5. **Evaluates all rules** that match:
   * `triggers` includes `"entity_created"`
   * `targetEntityTypes` includes `"person"`
   * `enabled` is `true`
6. **Calculates risk score** by summing scores from matched rules
7. **Generates alerts** for rules that match and have high severity
8. **Consolidates alerts** into investigations (after 3 seconds)
9. **Updates entity** with final risk score and status
10. **Sends notifications** via Socket.IO and webhooks

### Rule Condition Examples

Rules can access enrichment results in their conditions:

```javascript theme={null}
// Access enrichment data
enrichment.serpro_cpf.status === 'REGULAR'
enrichment.bureau_credit.score < 600
enrichment.bureau_credit.rating === 'POOR'

// Access compliance screening enrichments
enrichment.br_amldd_pep_enrichment.isPep === true
enrichment.global_gueno_sanctions_enrichment.hasMatches === true
enrichment.br_bdc_negative_media_enrichment.hasNegativeMedia === true

// Access entity basic data
entity.type === 'person'
entity.countryCode === 'BR'
entity.isClient === true

// Combine multiple conditions
enrichment.br_amldd_pep_enrichment.isPep === true && enrichment.bureau_credit.score < 500
```

See [Rules API Reference](/en/api-reference/rules/create) for complete condition syntax.

## Error Handling

### Common Errors and Solutions

```javascript theme={null}
async function createPersonWithErrorHandling(taxId) {
  try {
    const response = await fetch('https://api.gu1.ai/entities/automatic', {
      method: 'POST',
      headers: {
        'Authorization': 'Bearer YOUR_API_KEY',
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        taxId: taxId,
        country: 'BR',
        type: 'person',
        riskMatrixId: 'risk_matrix_id',
        autoExecuteIntegrations: {
          executeAllActiveEnrichments: true,
        }
      })
    });

    const result = await response.json();

    if (!result.success) {
      // Handle different error types
      switch (response.status) {
        case 400:
          // Invalid request
          console.error('Invalid request:', result.error);
          throw new Error(`Invalid data: ${result.error}`);

        case 404:
          // Person not found in registry
          console.error('Person not found:', result.details);
          throw new Error('CPF not found in official registry');

        case 409:
          // Person already exists
          console.log('Person already exists:', result.details.existingEntityId);
          return {
            success: true,
            entity: await getEntity(result.details.existingEntityId),
            alreadyExisted: true
          };

        case 429:
          // Rate limit exceeded
          console.error('Rate limit exceeded');
          throw new Error('Too many requests. Please try again later.');

        default:
          throw new Error(result.error || 'Unknown error');
      }
    }

    // Check for partial failures (enrichments that failed)
    if (result.data.errors) {
      const { enrichmentFailed, creationFailed } = result.data.errors;

      if (enrichmentFailed.length > 0) {
        console.warn('Some enrichments failed:', enrichmentFailed);
        // Continue anyway - entity was created
      }

      if (creationFailed.length > 0) {
        console.error('Some entities failed to create:', creationFailed);
        // This shouldn't happen for the main entity
      }
    }

    return result;

  } catch (error) {
    console.error('Onboarding error:', error);
    throw error;
  }
}
```

## Best Practices

### 1. Always Set a Risk Matrix

```javascript theme={null}
// ❌ Bad: No risk assessment
const result = await createPerson({
  taxId: '123.456.789-00',
  country: 'BR',
  type: 'person'
  // Missing riskMatrixId
});

// ✅ Good: Risk assessment included
const result = await createPerson({
  taxId: '123.456.789-00',
  country: 'BR',
  type: 'person',
  riskMatrixId: 'your_risk_matrix_id' // Always include
});
```

### 2. Use Specific Integrations for Better Performance

```javascript theme={null}
// ❌ Slower: Execute all active integrations
autoExecuteIntegrations: {
  executeAllActiveEnrichments: true,
}

// ✅ Faster: Specify only what you need
autoExecuteIntegrations: {
  enrichments: ['serpro_cpf', 'bureau_credit'],
}
```

### 3. Handle Async Operations

The creation is synchronous, but notifications are async:

```javascript theme={null}
// ✅ Good: Don't wait for notifications
const result = await createPerson(data);
// Entity is created and risk matrix executed
// Notifications will arrive via Socket.IO

// ❌ Bad: Trying to wait for notifications
await createPerson(data);
await sleep(5000); // Don't do this
// Notifications are async and unpredictable
```

### 4. Monitor Data Coverage

If rules fail due to missing data, check coverage:

```javascript theme={null}
if (!result.rulesResult.executed) {
  const { metadata } = result.rulesResult;

  if (metadata?.missingFields) {
    console.log('Missing fields:', metadata.missingFields);
    console.log('Recommended providers:', metadata.recommendedProviders);

    // Enable missing providers and try again
    await enableProviders(metadata.recommendedProviders);
  }
}
```

## Related Documentation

<CardGroup cols={2}>
  <Card title="Person API Reference" icon="user" href="/en/api-reference/person/create-automatic">
    Complete API documentation for person creation
  </Card>

  <Card title="Risk Matrix Guide" icon="shield" href="/en/api-reference/risk-matrix/list">
    Learn how to configure risk matrices and rules
  </Card>

  <Card title="Integrations Marketplace" icon="plug" href="/en/api-reference/integrations/provider-codes">
    Browse available enrichment providers
  </Card>

  <Card title="Webhooks Setup" icon="webhook" href="/en/webhooks/overview">
    Configure webhooks for event notifications
  </Card>
</CardGroup>
