Skip to main content
POST
http://api.gu1.ai
/
api
/
kyc
/
validations
/
{id}
/
sync
Sync KYC Validation
curl --request POST \
  --url http://api.gu1.ai/api/kyc/validations/{id}/sync \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '{
  "force": true
}'

Overview

This endpoint allows you to manually synchronize a KYC validation with the verification provider to get the latest status and decision data. When you sync:
  • Fetches latest data from the KYC provider in real-time
  • Refreshes expired image URLs (provider URLs expire after ~4 hours)
  • Updates validation status if the provider has made a decision
  • Preserves manual decisions - won’t overwrite manually approved/rejected/cancelled validations
  • Returns updated verification data including documents, biometrics, and risk assessment
Syncing is useful when you need fresh data immediately without waiting for webhooks, or when image URLs have expired and you need to view verification documents.

When to Use This

  • Check latest status: Get real-time status updates from the provider
  • Refresh expired images: Image URLs from the provider expire after 4 hours
  • Force update: Manually trigger a sync if webhook delivery failed
  • Debug verification: Review the most recent verification data and decisions
  • Before manual decision: Sync before approving/rejecting to see latest provider data

Request

Endpoint

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

Path Parameters

id
string
required
The validation ID to synchronize

Headers

{
  "Authorization": "Bearer YOUR_API_KEY",
  "Content-Type": "application/json"
}

Body Parameters

force
boolean
Force synchronization even if recently synced (optional)Type: boolean (default: false)Example: true

Response

Success Response (200 OK)

Returns the updated validation object with latest data from the provider:
{
  "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",
  "decision": {
    "status": "Approved",
    "features": ["id_verification", "liveness", "face_match"],
    "id_verification": {
      "status": "Approved",
      "document_type": "Identity Card",
      "first_name": "John",
      "last_name": "Doe",
      "date_of_birth": "1990-05-15",
      "nationality": "US",
      "front_image": "https://provider.com/fresh-url-1.jpg",
      "portrait_image": "https://provider.com/fresh-url-2.jpg"
    },
    "liveness": {
      "status": "Approved",
      "score": 98,
      "method": "PASSIVE",
      "reference_image": "https://provider.com/fresh-url-3.jpg"
    },
    "face_match": {
      "status": "Approved",
      "score": 95
    }
  },
  "extractedData": {
    "firstName": "John",
    "lastName": "Doe",
    "dateOfBirth": "1990-05-15",
    "nationality": "US",
    "documentNumber": "AB123456",
    "documentType": "Identity Card"
  },
  "documentsVerified": [
    {
      "type": "Identity Card",
      "verified": true,
      "verifiedAt": "2025-01-27T10:30:00Z"
    }
  ],
  "biometricResult": {
    "livenessScore": 0.98,
    "faceMatchScore": 0.95,
    "passed": true,
    "timestamp": "2025-01-27T10:30:00Z"
  },
  "riskAssessment": {
    "riskLevel": "low"
  },
  "verifiedFields": ["firstName", "lastName", "dateOfBirth", "nationality", "documentNumber"],
  "warnings": [],
  "isCurrent": true,
  "verifiedAt": "2025-01-27T10:30:00Z",
  "createdAt": "2025-01-15T10:30:00Z",
  "updatedAt": "2025-01-27T10:30:00Z"
}

Example Request

const validationId = '550e8400-e29b-41d4-a716-446655440000';

const response = await fetch(
  `https://api.gu1.ai/api/kyc/validations/${validationId}/sync`,
  {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer YOUR_API_KEY',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      force: false
    })
  }
);

const synced = await response.json();
console.log('Validation synced:', synced.status);
console.log('Updated at:', synced.updatedAt);

Error Responses

Validation Not Found (404)

{
  "error": "NOT_FOUND",
  "message": "Validation not found"
}

No Session ID (400)

Validation has no provider session to sync:
{
  "error": "NO_SESSION_ID",
  "message": "Validation has no session ID"
}

Provider Integration Not Configured (400)

{
  "error": "INTEGRATION_NOT_CONFIGURED",
  "message": "Integration not configured for organization: kyc_provider_code"
}

Important Notes

Validations are automatically synced when fetched via GET if images are older than 3.5 hours. Manual sync is useful when you need immediate updates.
If a validation was manually approved, rejected, or cancelled, syncing will NOT overwrite that decision. Manual decisions are preserved to maintain audit trails.
Provider image URLs (document photos, selfies) expire after ~4 hours. Syncing fetches fresh URLs so you can view documents again.
If the provider has made a decision since the last sync, the validation status will be updated automatically (unless it has a manual status).
Syncing does NOT charge credits. Credits are only charged when a validation reaches a final state (approved/rejected) for the first time.

Use Cases

1. Refresh Expired Images

// User wants to review documents but images expired
const validation = await fetch(
  `https://api.gu1.ai/api/kyc/validations/${validationId}/sync`,
  {
    method: 'POST',
    headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
  }
);

const data = await validation.json();
// Fresh image URLs available in data.decision.id_verification.front_image

2. Check Status Before Manual Decision

// Sync before making a manual approval decision
const synced = await fetch(
  `https://api.gu1.ai/api/kyc/validations/${validationId}/sync`,
  { method: 'POST', headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
);

const data = await synced.json();

// Review latest provider data
console.log('Provider status:', data.status);
console.log('Risk level:', data.riskAssessment?.riskLevel);
console.log('Warnings:', data.warnings);

// Then approve if satisfied
if (data.status === 'in_progress' && data.warnings.length === 0) {
  await approveValidation(validationId, 'All checks passed');
}

3. Force Update After Webhook Failure

// If you suspect webhooks didn't deliver
const validations = await getValidationsWithStatus('in_progress');

for (const validation of validations) {
  // Sync each to get latest status
  await fetch(
    `https://api.gu1.ai/api/kyc/validations/${validation.id}/sync`,
    {
      method: 'POST',
      headers: { 'Authorization': 'Bearer YOUR_API_KEY' },
      body: JSON.stringify({ force: true })
    }
  );
}

Next Steps