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

# Approve KYC Validation

> Manually approve a KYC validation — in the gu1 KYC API for identity verification flows, with examples for approve validation use cases.

## Overview

This endpoint allows you to manually approve a KYC validation. When you approve:

* **Automatic sync with provider**: The system first syncs with the KYC provider to get the latest verification status
* **Status validation**: You can only approve if provider status is `in_review` (user has completed verification and requires manual review from compliance team)
* The validation status changes to `approved`
* The validation is marked as verified with timestamp
* The approval reason is saved in metadata and audit logs
* With **`doubleCheckRenaper`**: RENAPER is **not** re-run and cross-check enforcement is **not** re-applied; the API reuses `metadata.responseDoubleChecks.renaper` and `warnings` already computed in `in_review`. The decision is human after reviewing that data in the UI.

<Warning>
  Manual approval should only be used when you've performed additional verification or have sufficient reason to override the automated process. The approval reason is required for audit compliance.
</Warning>

## When to Use This

* **Additional verification completed**: You've performed manual review of documents or biometric data
* **Business exception**: You have business reasons to approve despite minor issues
* **Risk assessment override**: Your risk team has approved the validation
* **Provider delay**: The verification provider is taking too long but your internal review is complete

## Request

### Endpoint

```
POST https://api.gu1.ai/api/kyc/validations/{id}/approve
```

### Path Parameters

<ParamField path="id" type="string" required>
  The validation ID to approve
</ParamField>

### Headers

```json theme={null}
{
  "Authorization": "Bearer YOUR_API_KEY",
  "Content-Type": "application/json"
}
```

### Body Parameters

<ParamField body="reason" type="string" required>
  Reason for manually approving the validation (minimum 5 characters)

  **Type**: `string` (min length: 5)

  **Example**: `"Manual review completed successfully - all documents verified"`
</ParamField>

## Response

### Success Response (200 OK)

Returns the updated validation object with `approved` status:

```json theme={null}
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "entityId": "123e4567-e89b-12d3-a456-426614174000",
  "organizationId": "org_abc123",
  "validationSessionId": "session_xyz789",
  "status": "approved",
  "provider": "kyc_provider",
  "providerSessionUrl": "https://verify.example.com/session_xyz789",
  "isCurrent": true,
  "verifiedAt": "2025-01-27T10:30:00Z",
  "metadata": {
    "manuallyApprovedBy": "user_123",
    "manuallyApprovedAt": "2025-01-27T10:30:00Z",
    "approvalReason": "Manual review completed successfully - all documents verified"
  },
  "createdAt": "2025-01-15T10:30:00Z",
  "updatedAt": "2025-01-27T10:30:00Z"
}
```

## Example Request

<CodeGroup>
  ```javascript Node.js theme={null}
  const validationId = '550e8400-e29b-41d4-a716-446655440000';

  const response = await fetch(
    `https://api.gu1.ai/api/kyc/validations/${validationId}/approve`,
    {
      method: 'POST',
      headers: {
        'Authorization': 'Bearer YOUR_API_KEY',
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        reason: 'Manual review completed successfully - all documents verified'
      })
    }
  );

  const approved = await response.json();
  console.log('Validation approved:', approved.status);
  ```

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

  validation_id = '550e8400-e29b-41d4-a716-446655440000'

  response = requests.post(
      f'https://api.gu1.ai/api/kyc/validations/{validation_id}/approve',
      headers={
          'Authorization': 'Bearer YOUR_API_KEY',
          'Content-Type': 'application/json',
      },
      json={
          'reason': 'Manual review completed successfully - all documents verified'
      }
  )

  approved = response.json()
  print('Validation approved:', approved['status'])
  ```

  ```curl cURL theme={null}
  curl -X POST https://api.gu1.ai/api/kyc/validations/550e8400-e29b-41d4-a716-446655440000/approve \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "reason": "Manual review completed successfully - all documents verified"
    }'
  ```
</CodeGroup>

## Error Responses

### Validation Not Found (404)

```json theme={null}
{
  "error": "NOT_FOUND",
  "message": "Validation not found"
}
```

### Invalid Status (400)

Validation can only be approved if provider status is `in_review` (user has completed verification and requires manual review from compliance team):

```json theme={null}
{
  "error": "INVALID_STATUS",
  "message": "Cannot manually approve. Current status is \"approved\". Manual approval is only allowed when status is \"in_review\" (validation requires manual review from compliance team)."
}
```

**What this means:**

* If the provider already approved (`approved`) or rejected (`rejected`) the validation, you cannot override that decision
* If the validation is `cancelled`, you cannot approve it
* If it's `expired` or `abandoned`, it also cannot be manually approved
* If it's `in_progress`, the user is still filling out the verification form
* **You can only approve** when the provider reports the validation as `in_review` (user has completed all verification steps and requires manual review from compliance team)

### Invalid Reason (400)

Reason must be at least 5 characters:

```json theme={null}
{
  "error": "VALIDATION_ERROR",
  "message": "Reason must be at least 5 characters"
}
```

## Important Notes

<AccordionGroup>
  <Accordion title="Automatic Sync Before Approval">
    Before approving, the system automatically syncs with the KYC provider to get the latest verification data. This ensures you're making decisions based on the most recent information.
  </Accordion>

  <Accordion title="Status Protection">
    You cannot approve validations that are already `approved`, `rejected`, or `cancelled`. These statuses are protected to maintain data integrity.
  </Accordion>

  <Accordion title="Audit Trail">
    The approval reason is saved in both the validation metadata and audit logs. This is critical for compliance and regulatory requirements.
  </Accordion>

  <Accordion title="Only for In-Review Validations">
    Manual approval is only allowed when the provider reports the validation as `in_review`. This prevents approving validations that:

    * The provider has already declined or completed
    * Don't have complete verification data (status `pending` or `in_progress`)
    * The user is still filling out the form (status `in_progress`)
  </Accordion>

  <Accordion title="Verification Timestamp">
    When approved, the validation receives a `verifiedAt` timestamp and becomes the current validation for the entity.
  </Accordion>
</AccordionGroup>

## Best Practices

* **Always provide detailed reasons**: Include specific details about why manual approval is necessary
* **Document your process**: Maintain internal documentation for manual approval criteria
* **Review fresh data**: The automatic sync ensures you see the latest documents and biometric results
* **Use sparingly**: Manual approval should be the exception, not the rule
* **Train your team**: Ensure staff understand when manual approval is appropriate

## Next Steps

<CardGroup cols={2}>
  <Card title="Reject Validation" icon="xmark" href="/en/use-cases/kyc/reject-validation">
    Manually reject a validation
  </Card>

  <Card title="Check Verification Status" icon="magnifying-glass" href="/en/use-cases/kyc/check-status">
    Query validation results
  </Card>
</CardGroup>
