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

# Ingest KYC/KYB Verifications

> Push KYC and KYB verification results from your identity providers into Corsa to keep client compliance records current.

This guide walks you through ingesting **KYC/KYB Verifications** — records that capture the outcome of identity checks performed by external providers such as SumSub, Persona, or any other KYC/KYB vendor.

Full API endpoint details are available in the [API Reference](https://api.corsa.finance/api-spec.json) (requires API credentials).

<Note>
  Before ingesting verifications, make sure the related client has already been ingested. See the [Ingesting Clients](/api/ingesting-clients) guide.
  All SDK examples assume you have initialized the Corsa client as shown in the [Node.js SDK Configuration](/sdk/configuration) or [Python SDK Configuration](/sdk/python-configuration) guide.
</Note>

***

## Overview

A verification represents a single identity check run against a client by an external KYC/KYB provider. Corsa normalizes the result into a unified `status` field while also preserving the provider's raw status for audit purposes.

Each verification belongs to exactly one client and is uniquely identified by the combination of `provider` + `providerId`.

**Verification statuses:**

| Status      | Meaning                                             |
| ----------- | --------------------------------------------------- |
| `REQUESTED` | Verification has been requested but not yet started |
| `PENDING`   | Verification is in progress at the provider         |
| `APPROVED`  | Client passed the verification check                |
| `REJECTED`  | Client failed the verification check                |
| `EXPIRED`   | Verification expired before completion              |
| `CANCELLED` | Verification was cancelled                          |

***

## Step 1: Create a Verification

**Endpoint:** `POST /v1/clients/{clientId}/verifications`

Returns `409 Conflict` if a verification with the same `provider` + `providerId` already exists for this client.

<CodeGroup>
  ```json REST API theme={null}
  POST /v1/clients/123e4567-e89b-12d3-a456-426614174000/verifications
  Content-Type: application/json

  {
    "provider": "SUMSUB",
    "providerId": "applicant_abc123",
    "providerStatus": "completed",
    "providerLink": "https://cockpit.sumsub.com/checkus/#/applicant/applicant_abc123",
    "status": "APPROVED",
    "startedAt": "2024-01-15T09:00:00Z",
    "completedAt": "2024-01-15T09:05:00Z",
    "checks": [
      { "title": "Identity Verification", "status": "Approved" },
      { "title": "Document Check", "status": "Approved" }
    ]
  }
  ```

  ```typescript Javascript theme={null}
  const verification = await corsa.verifications.createVerification(
    "123e4567-e89b-12d3-a456-426614174000",
    {
      provider: "SUMSUB",
      providerId: "applicant_abc123",
      providerStatus: "completed",
      providerLink: "https://cockpit.sumsub.com/checkus/#/applicant/applicant_abc123",
      status: "APPROVED",
      startedAt: "2024-01-15T09:00:00Z",
      completedAt: "2024-01-15T09:05:00Z",
      checks: [
        { title: "Identity Verification", status: "Approved" },
        { title: "Document Check", status: "Approved" },
      ],
    }
  );
  ```

  ```python Python theme={null}
  from corsa_sdk.api.verifications.create_verification import _get_kwargs
  from corsa_sdk.models.create_verification_dto import CreateVerificationDto

  resp = http.request(**_get_kwargs(
      client_id="123e4567-e89b-12d3-a456-426614174000",
      body=CreateVerificationDto(
          provider="SUMSUB",
          provider_id="applicant_abc123",
          provider_status="completed",
          provider_link="https://cockpit.sumsub.com/checkus/#/applicant/applicant_abc123",
          status="APPROVED",
          started_at="2024-01-15T09:00:00Z",
          completed_at="2024-01-15T09:05:00Z",
          checks=[
              {"title": "Identity Verification", "status": "Approved"},
              {"title": "Document Check", "status": "Approved"},
          ],
      ),
  ))
  verification = resp.json()
  ```
</CodeGroup>

### Request Fields

| Field            | Required | Description                                                                                        |
| ---------------- | -------- | -------------------------------------------------------------------------------------------------- |
| `provider`       | Yes      | KYC/KYB provider name (e.g. `SUMSUB`, `PERSONA`)                                                   |
| `providerId`     | Yes      | Unique verification ID in the provider's system                                                    |
| `providerStatus` | Yes      | Raw status string from the provider (e.g. `completed`, `pending`)                                  |
| `status`         | Yes      | Corsa-normalized status: `REQUESTED`, `PENDING`, `APPROVED`, `REJECTED`, `EXPIRED`, or `CANCELLED` |
| `providerLink`   | No       | Direct link to this verification in the provider's dashboard                                       |
| `reviewComment`  | No       | Summary of the verification outcome                                                                |
| `rejectLabels`   | No       | Array of provider-specific rejection reason labels                                                 |
| `startedAt`      | No       | ISO 8601 timestamp when the verification was initiated                                             |
| `completedAt`    | No       | ISO 8601 timestamp when the verification was completed                                             |
| `checks`         | No       | Array of individual checks performed (e.g. identity, document, liveness)                           |
| `metadata`       | No       | Additional provider-specific data as a JSON string                                                 |

***

## Step 2: Update a Verification

**Endpoint:** `PUT /v1/clients/{clientId}/verifications/{verificationId}`

Use this endpoint to update a verification when its status changes at the provider — for example, when a `PENDING` check is completed.

<CodeGroup>
  ```json REST API theme={null}
  PUT /v1/clients/123e4567-e89b-12d3-a456-426614174000/verifications/ver_789xyz
  Content-Type: application/json

  {
    "providerStatus": "rejected",
    "status": "REJECTED",
    "rejectLabels": ["FORGERY", "FACE_MISMATCH"],
    "reviewComment": "Document appears tampered. Face does not match ID photo.",
    "completedAt": "2024-01-15T09:10:00Z"
  }
  ```

  ```typescript Javascript theme={null}
  const updated = await corsa.verifications.updateVerification(
    "123e4567-e89b-12d3-a456-426614174000",
    "ver_789xyz",
    {
      providerStatus: "rejected",
      status: "REJECTED",
      rejectLabels: ["FORGERY", "FACE_MISMATCH"],
      reviewComment: "Document appears tampered. Face does not match ID photo.",
      completedAt: "2024-01-15T09:10:00Z",
    }
  );
  ```

  ```python Python theme={null}
  from corsa_sdk.api.verifications.update_verification import _get_kwargs
  from corsa_sdk.models.update_verification_dto import UpdateVerificationDto

  resp = http.request(**_get_kwargs(
      client_id="123e4567-e89b-12d3-a456-426614174000",
      verification_id="ver_789xyz",
      body=UpdateVerificationDto(
          provider_status="rejected",
          status="REJECTED",
          reject_labels=["FORGERY", "FACE_MISMATCH"],
          review_comment="Document appears tampered. Face does not match ID photo.",
          completed_at="2024-01-15T09:10:00Z",
      ),
  ))
  updated = resp.json()
  ```
</CodeGroup>

***

## Step 3: Look Up a Verification

**Endpoint:** `GET /v1/clients/{clientId}/verifications/lookup?provider={provider}&providerId={providerId}`

Use this to retrieve an existing verification by provider + `providerId` without storing the Corsa verification ID on your side.

<CodeGroup>
  ```json REST API theme={null}
  GET /v1/clients/123e4567-e89b-12d3-a456-426614174000/verifications/lookup
    ?provider=SUMSUB
    &providerId=applicant_abc123
  ```

  ```typescript Javascript theme={null}
  const verification = await corsa.verifications.getVerification(
    "123e4567-e89b-12d3-a456-426614174000",
    "SUMSUB",
    "applicant_abc123"
  );
  ```

  ```python Python theme={null}
  from corsa_sdk.api.verifications.lookup_verification import _get_kwargs

  resp = http.request(**_get_kwargs(
      client_id="123e4567-e89b-12d3-a456-426614174000",
      provider="SUMSUB",
      provider_id="applicant_abc123",
  ))
  verification = resp.json()
  ```
</CodeGroup>

***

## Verification Response

A successful create or update returns the full verification object:

```json theme={null}
{
  "id": "ver_789xyz",
  "platformId": "platform_abc",
  "clientId": "123e4567-e89b-12d3-a456-426614174000",
  "provider": "SUMSUB",
  "providerId": "applicant_abc123",
  "providerStatus": "completed",
  "providerLink": "https://cockpit.sumsub.com/checkus/#/applicant/applicant_abc123",
  "status": "APPROVED",
  "reviewComment": null,
  "rejectLabels": [],
  "startedAt": "2024-01-15T09:00:00Z",
  "completedAt": "2024-01-15T09:05:00Z",
  "checks": [
    { "title": "Identity Verification", "status": "Approved" },
    { "title": "Document Check", "status": "Approved" }
  ],
  "metadata": null,
  "createdAt": "2024-01-15T09:05:30Z",
  "updatedAt": "2024-01-15T09:05:30Z"
}
```

***

## Integration Pattern

The typical flow when integrating with a KYC provider:

1. **Client submits** verification at your platform — create a `PENDING` verification in Corsa.
2. **Provider webhook fires** with the result — update the verification status in Corsa.
3. **Corsa reflects** the updated status on the client profile for compliance review.

This keeps the client's verification history in Corsa synchronized with your KYC provider in real time.
