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

# KYC / KYB Verification

> Verify individual customers (KYC) and business customers (KYB) to unlock virtual accounts and payment rails

Yativo requires identity verification before customers can access payment services such as virtual accounts, send money, and payment rails. Individual users go through **KYC** (Know Your Customer) and businesses go through **KYB** (Know Your Business).

## Environments

| Environment    | Base URL                         |
| -------------- | -------------------------------- |
| Production API | `https://api.yativo.com/api/v1`  |
| Sandbox API    | `https://smtp.yativo.com/api/v1` |
| KYC Platform   | `https://kyc.yativo.com`         |

<Note>
  KYC and KYB submissions are sent to **`https://kyc.yativo.com`**, not the main API base URL. All other endpoints (status check, update) use the standard base URL. Include `Authorization: Bearer {token}` in every request.
</Note>

***

## Integration approaches

| Approach                | Best for                        | Effort |
| ----------------------- | ------------------------------- | ------ |
| **Hosted KYC/KYB link** | Quick integration, iframe embed | Low    |
| **API submission**      | Programmatic flow, native UI    | High   |

**Hosted URLs:**

* Individual: `https://kyc.yativo.com/individual/{customer_id}`
* Business: `https://kyc.yativo.com/business/{customer_id}`

***

## Verification flow

<Steps>
  <Step title="Create a customer">
    Call `POST /customer` to create a customer record and receive a `customer_id`.
  </Step>

  <Step title="Upload documents (if using API)">
    Use `POST /storage/upload` to upload files and receive back a hosted URL. Pass those URLs in the KYC payload. Alternatively, embed files as base64-encoded strings.
  </Step>

  <Step title="Submit KYC or KYB">
    POST to `https://kyc.yativo.com/api/individual-kyc/submit` or `https://kyc.yativo.com/api/business-kyc/submit`.
  </Step>

  <Step title="Poll or receive webhook">
    Check `GET /customer/kyc/{customer_id}` or listen for the `kyc.status_updated` webhook event.
  </Step>

  <Step title="Customer approved">
    When `status` is `"approved"` and `is_va_approved` is `true`, service endorsements are activated and payment rails become available.
  </Step>
</Steps>

***

## Upload documents

Before submitting KYC, upload any document files you will reference. Files must be PDF, JPG, JPEG, PNG, HEIC, or TIF and must not exceed **5 MB** each.

```
POST /storage/upload
```

Send the file as `multipart/form-data` with the field name `document`.

<RequestExample>
  ```bash cURL theme={null}
  curl -X POST 'https://api.yativo.com/api/v1/storage/upload' \
    -H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
    -F 'document=@/path/to/passport_front.jpg'
  ```
</RequestExample>

<ResponseExample>
  ```json Success theme={null}
  {
    "status": "success",
    "status_code": 200,
    "message": "Request successful",
    "data": {
      "url": "https://storage.yativo.com/documents/abc123/passport_front.jpg"
    }
  }
  ```
</ResponseExample>

Use the returned `url` value in the `selfie_image`, `image_front_file`, `proof_of_address_file`, and similar fields below.

***

## Individual KYC

### Submit

```
POST https://kyc.yativo.com/api/individual-kyc/submit
```

This is a five-step data model submitted in one payload. All required fields must be present in a single request.

#### Step 1 — Personal details

| Field          | Type               | Required | Notes                                                                    |
| -------------- | ------------------ | -------- | ------------------------------------------------------------------------ |
| `customer_id`  | string             | ✓        | UUID from `POST /customer`                                               |
| `first_name`   | string             | ✓        | Max 1024 chars                                                           |
| `last_name`    | string             | ✓        | Max 1024 chars                                                           |
| `middle_name`  | string             |          | Optional                                                                 |
| `email`        | string             | ✓        | Valid email address                                                      |
| `calling_code` | string             | ✓        | Dial code, e.g. `"+1"`, `"+234"`. Must match `^\+\d{1,4}$`               |
| `phone`        | string             | ✓        | Digits only, 8–15 characters                                             |
| `birth_date`   | string             | ✓        | `YYYY-MM-DD`, must be before today                                       |
| `nationality`  | string             | ✓        | ISO 3166-1 alpha-2, e.g. `"US"`, `"NG"`, `"BR"`                          |
| `gender`       | string             | ✓        | `"male"` or `"female"`                                                   |
| `taxId`        | string             | ✓        | Tax identification number, max 100 chars                                 |
| `selfie_image` | file URL or base64 | ✓        | Selfie photo. PDF/JPG/JPEG/PNG/HEIC/TIF, max 5 MB                        |
| `bvn`          | string             | NG only  | 11-digit Bank Verification Number. Required when `nationality` is `"NG"` |
| `nin`          | string             | NG only  | 11-digit National ID Number. Required when `nationality` is `"NG"`       |

#### Step 2 — Residential address

| Field                                       | Type               | Required | Notes                                                                  |
| ------------------------------------------- | ------------------ | -------- | ---------------------------------------------------------------------- |
| `residential_address.street_line_1`         | string             | ✓        | Max 256 chars                                                          |
| `residential_address.street_line_2`         | string             |          | Optional                                                               |
| `residential_address.city`                  | string             | ✓        | Max 256 chars                                                          |
| `residential_address.state`                 | string             | ✓        | Accepts `"US-CA"` or `"CA"` — both are valid                           |
| `residential_address.postal_code`           | string             | ✓        | Validated per country                                                  |
| `residential_address.country`               | string             | ✓        | ISO 3166-1 alpha-2                                                     |
| `residential_address.proof_of_address_file` | file URL or base64 | ✓        | Utility bill, bank statement, etc. PDF/JPG/JPEG/PNG/HEIC/TIF, max 5 MB |

#### Step 3 — Identifying information

At least one government-issued ID document is required.

| Field                                         | Type               | Required | Notes                                           |
| --------------------------------------------- | ------------------ | -------- | ----------------------------------------------- |
| `identifying_information[*].type`             | string             | ✓        | See [ID types by country](#id-types-by-country) |
| `identifying_information[*].issuing_country`  | string             | ✓        | ISO 3166-1 alpha-2                              |
| `identifying_information[*].number`           | string             | ✓        | Document number                                 |
| `identifying_information[*].date_issued`      | string             | ✓        | `YYYY-MM-DD`, must be before today              |
| `identifying_information[*].expiration_date`  | string             | ✓        | `YYYY-MM-DD`, must be after today               |
| `identifying_information[*].image_front_file` | file URL or base64 | ✓        | PDF/JPG/JPEG/PNG, max 5 MB                      |
| `identifying_information[*].image_back_file`  | file URL or base64 |          | Required for cards with a back side             |

#### Step 4 — Risk and purpose

| Field                           | Type    | Required                          | Notes                                                       |
| ------------------------------- | ------- | --------------------------------- | ----------------------------------------------------------- |
| `employment_status`             | string  | ✓                                 | See [enum values](#employment_status)                       |
| `most_recent_occupation_code`   | string  | ✓                                 | 6-digit code from `GET /auth/occupation-codes`              |
| `expected_monthly_payments_usd` | string  | ✓                                 | See [enum values](#expected_monthly_payments_usd)           |
| `source_of_funds`               | string  | ✓                                 | See [enum values](#source_of_funds)                         |
| `account_purpose`               | string  | ✓                                 | See [enum values](#account_purpose)                         |
| `account_purpose_other`         | string  | If `account_purpose` is `"other"` | Description of the purpose                                  |
| `acting_as_intermediary`        | boolean |                                   | Whether the customer acts as intermediary for third parties |

#### Step 5 — Supporting documents

| Field                        | Type               | Required | Notes                      |
| ---------------------------- | ------------------ | -------- | -------------------------- |
| `uploaded_documents[*].type` | string             | ✓        | Document type identifier   |
| `uploaded_documents[*].file` | file URL or base64 | ✓        | PDF/JPG/JPEG/PNG, max 5 MB |

***

### KYC example request

<RequestExample>
  ```bash cURL theme={null}
  curl -X POST 'https://kyc.yativo.com/api/individual-kyc/submit' \
    -H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
    -H 'Content-Type: application/json' \
    -H 'Idempotency-Key: kyc-ind-2026-001' \
    -d '{
      "customer_id": "c586066b-0f29-468f-b775-15483871a202",
      "first_name": "Alex",
      "last_name": "Smith",
      "email": "alex.smith@example.com",
      "calling_code": "+1",
      "phone": "5551234567",
      "gender": "male",
      "birth_date": "1990-01-15",
      "nationality": "US",
      "taxId": "998-88-7766",
      "selfie_image": "https://storage.yativo.com/documents/abc/selfie.jpg",
      "residential_address": {
        "street_line_1": "123 Maple Street",
        "city": "Austin",
        "state": "TX",
        "postal_code": "78701",
        "country": "US",
        "proof_of_address_file": "https://storage.yativo.com/documents/abc/utility-bill.pdf"
      },
      "identifying_information": [
        {
          "type": "passport",
          "issuing_country": "US",
          "number": "P12345678",
          "date_issued": "2019-06-01",
          "expiration_date": "2029-06-01",
          "image_front_file": "https://storage.yativo.com/documents/abc/passport-front.jpg"
        }
      ],
      "employment_status": "employed",
      "most_recent_occupation_code": "151252",
      "expected_monthly_payments_usd": "0_4999",
      "source_of_funds": "salary",
      "account_purpose": "receive_salary",
      "acting_as_intermediary": false,
      "uploaded_documents": [
        {
          "type": "bank_statement",
          "file": "https://storage.yativo.com/documents/abc/bank-statement.pdf"
        }
      ]
    }'
  ```

  ```javascript Node.js theme={null}
  const response = await fetch('https://kyc.yativo.com/api/individual-kyc/submit', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${token}`,
      'Content-Type': 'application/json',
      'Idempotency-Key': `kyc-${customerId}-${Date.now()}`,
    },
    body: JSON.stringify({
      customer_id: customerId,
      first_name: 'Alex',
      last_name: 'Smith',
      email: 'alex.smith@example.com',
      calling_code: '+1',
      phone: '5551234567',
      gender: 'male',
      birth_date: '1990-01-15',
      nationality: 'US',
      taxId: '998-88-7766',
      selfie_image: selfieUrl,          // URL from /storage/upload
      residential_address: {
        street_line_1: '123 Maple Street',
        city: 'Austin',
        state: 'TX',
        postal_code: '78701',
        country: 'US',
        proof_of_address_file: addressProofUrl,
      },
      identifying_information: [{
        type: 'passport',
        issuing_country: 'US',
        number: 'P12345678',
        date_issued: '2019-06-01',
        expiration_date: '2029-06-01',
        image_front_file: passportFrontUrl,
      }],
      employment_status: 'employed',
      most_recent_occupation_code: '151252',
      expected_monthly_payments_usd: '0_4999',
      source_of_funds: 'salary',
      account_purpose: 'receive_salary',
      acting_as_intermediary: false,
      uploaded_documents: [{ type: 'bank_statement', file: statementUrl }],
    }),
  });
  ```
</RequestExample>

<ResponseExample>
  ```json Success theme={null}
  {
    "success": true,
    "message": "KYC submission received successfully",
    "errors": {
      "submission": {
        "id": "sub_8f3b2a1c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
        "type": "individual",
        "status": "submitted",
        "customer_id": "c586066b-0f29-468f-b775-15483871a202",
        "first_name": "Alex",
        "last_name": "Smith",
        "email": "alex.smith@example.com",
        "endorsements": [
          {
            "service": "base",
            "status": "pending",
            "link": "https://kyc.yativo.com/endorsement/base/c586066b-0f29-468f-b775-15483871a202"
          }
        ],
        "created_at": "2026-06-01T10:00:00.000000Z"
      }
    }
  }
  ```
</ResponseExample>

***

## Business KYB

### Submit

```
POST https://kyc.yativo.com/api/business-kyc/submit
```

#### Step 1 — Business basics

| Field                  | Type    | Required | Notes                                                                                |
| ---------------------- | ------- | -------- | ------------------------------------------------------------------------------------ |
| `customer_id`          | string  | ✓        | UUID from `POST /customer` (must be `customer_type: "business"`)                     |
| `business_legal_name`  | string  | ✓        | Official registered legal name, max 255 chars                                        |
| `business_trade_name`  | string  | ✓        | Trade / DBA name, max 255 chars                                                      |
| `business_description` | string  | ✓        | What the business does, max 1000 chars                                               |
| `email`                | string  | ✓        | Business contact email                                                               |
| `business_type`        | string  | ✓        | `cooperative`, `corporation`, `llc`, `partnership`, `sole_prop`, `trust`, or `other` |
| `registration_number`  | string  | ✓        | Government registration / incorporation number, max 100 chars                        |
| `incorporation_date`   | string  | ✓        | `YYYY-MM-DD`, must be before today                                                   |
| `tax_id`               | string  |          | Business tax ID, max 100 chars                                                       |
| `phone_calling_code`   | string  |          | Must match `^\+[1-9]\d{0,3}$`                                                        |
| `phone_number`         | string  |          | Digits only, 7–15 characters                                                         |
| `business_industry`    | string  |          | Industry category                                                                    |
| `primary_website`      | string  |          | Full URL                                                                             |
| `is_dao`               | boolean |          | Whether the business is a DAO                                                        |
| `statement_descriptor` | string  |          | How the name appears on statements, max 22 chars                                     |

#### Step 2 — Addresses

Both `registered_address` and `physical_address` use the same structure:

| Field                   | Type               | Required | Notes                                             |
| ----------------------- | ------------------ | -------- | ------------------------------------------------- |
| `street_line_1`         | string             | ✓        | Max 255 chars                                     |
| `street_line_2`         | string             |          | Optional                                          |
| `city`                  | string             | ✓        | Max 100 chars                                     |
| `state`                 | string             | ✓        | Accepts `"US-CA"` or `"CA"`                       |
| `postal_code`           | string             | ✓        | Validated per country                             |
| `country`               | string             | ✓        | ISO 3166-1 alpha-2                                |
| `proof_of_address_file` | file URL or base64 |          | Optional for registered, recommended for physical |

#### Step 3 — Associated persons

At least one person is required. Include all UBOs, directors, and authorized signers.

| Field                         | Type    | Required | Notes                                                  |
| ----------------------------- | ------- | -------- | ------------------------------------------------------ |
| `first_name`                  | string  | ✓        | Max 100 chars                                          |
| `last_name`                   | string  | ✓        | Max 100 chars                                          |
| `birth_date`                  | string  | ✓        | `YYYY-MM-DD`, before today                             |
| `nationality`                 | string  | ✓        | ISO 3166-1 alpha-2                                     |
| `email`                       | string  | ✓        | Personal email                                         |
| `phone`                       | string  |          | Optional                                               |
| `title`                       | string  |          | E.g. `"CEO"`, `"Director"`                             |
| `ownership_percentage`        | number  | ✓        | 0–100                                                  |
| `relationship_established_at` | string  |          | `YYYY-MM-DD`, must not be in the future                |
| `residential_address`         | object  | ✓        | Same structure as Step 2                               |
| `identifying_information`     | array   | ✓        | ID documents (same structure as individual KYC Step 3) |
| `has_ownership`               | boolean |          | Has ownership stake                                    |
| `has_control`                 | boolean |          | Has operational control                                |
| `is_signer`                   | boolean |          | Authorized signer                                      |
| `is_director`                 | boolean |          | Director                                               |

#### Step 4 — Risk and purpose

| Field                                 | Type    | Required                               | Notes                                                                                   |
| ------------------------------------- | ------- | -------------------------------------- | --------------------------------------------------------------------------------------- |
| `account_purpose`                     | string  | ✓                                      | See [enum values](#account_purpose)                                                     |
| `account_purpose_other`               | string  | If `account_purpose` is `"other"`      |                                                                                         |
| `source_of_funds`                     | string  | ✓                                      | See [enum values](#source_of_funds)                                                     |
| `high_risk_activities`                | array   | ✓                                      | See [enum values](#high_risk_activities-kyb). Use `["none_of_the_above"]` if none apply |
| `high_risk_activities_explanation`    | string  | If any high-risk activities listed     |                                                                                         |
| `conducts_money_services`             | boolean |                                        |                                                                                         |
| `conducts_money_services_description` | string  | If `conducts_money_services` is `true` |                                                                                         |
| `compliance_screening_explanation`    | string  | If `conducts_money_services` is `true` |                                                                                         |
| `estimated_annual_revenue_usd`        | string  |                                        |                                                                                         |
| `expected_monthly_payments_usd`       | number  |                                        | Expected monthly volume in USD                                                          |
| `operates_in_prohibited_countries`    | string  |                                        | `"yes"` or `"no"`                                                                       |
| `ownership_threshold`                 | integer |                                        | UBO reporting threshold (5–25)                                                          |
| `has_material_intermediary_ownership` | boolean |                                        |                                                                                         |

#### Step 5 — Regulated activity

| Field                                                     | Type   | Notes              |
| --------------------------------------------------------- | ------ | ------------------ |
| `regulated_activity.regulated_activities_description`     | string | Optional           |
| `regulated_activity.primary_regulatory_authority_country` | string | ISO 3166-1 alpha-2 |
| `regulated_activity.primary_regulatory_authority_name`    | string |                    |
| `regulated_activity.license_number`                       | string |                    |

#### Step 6 — Business documents

At least one document is required.

| Field                      | Type               | Required | Notes                                                                                               |
| -------------------------- | ------------------ | -------- | --------------------------------------------------------------------------------------------------- |
| `documents[*].purpose`     | string             | ✓        | `"business_registration"`, `"tax_documents"`, `"compliance_documents"`, or `"financial_statements"` |
| `documents[*].description` | string             | ✓        | Human-readable description                                                                          |
| `documents[*].file`        | file URL or base64 |          | File attachment                                                                                     |

#### Step 7 — Business identifying information (optional)

Business-level ID documents (e.g. business licence).

| Field                                        | Type               | Notes                     |
| -------------------------------------------- | ------------------ | ------------------------- |
| `identifying_information[*].type`            | string             |                           |
| `identifying_information[*].issuing_country` | string             | ISO 3166-1 alpha-2        |
| `identifying_information[*].number`          | string             |                           |
| `identifying_information[*].description`     | string             |                           |
| `identifying_information[*].expiration`      | string             | `YYYY-MM-DD`, after today |
| `identifying_information[*].image_front`     | file URL or base64 |                           |
| `identifying_information[*].image_back`      | file URL or base64 |                           |

***

### KYB example request

<RequestExample>
  ```bash cURL theme={null}
  curl -X POST 'https://kyc.yativo.com/api/business-kyc/submit' \
    -H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
    -H 'Content-Type: application/json' \
    -H 'Idempotency-Key: kyb-acme-2026-001' \
    -d '{
      "customer_id": "d47f8a2b-1c3e-4f5a-9b8c-7d6e5f4a3b2c",
      "business_legal_name": "Acme Payments LLC",
      "business_trade_name": "Acme Pay",
      "business_description": "International payment processing for SMEs",
      "email": "compliance@acmepay.com",
      "business_type": "llc",
      "registration_number": "LLC-2018-00987",
      "incorporation_date": "2018-03-12",
      "tax_id": "47-1234567",
      "phone_calling_code": "+1",
      "phone_number": "3055551234",
      "primary_website": "https://acmepay.com",
      "registered_address": {
        "street_line_1": "100 Brickell Ave",
        "city": "Miami",
        "state": "FL",
        "postal_code": "33131",
        "country": "US"
      },
      "physical_address": {
        "street_line_1": "100 Brickell Ave",
        "city": "Miami",
        "state": "FL",
        "postal_code": "33131",
        "country": "US",
        "proof_of_address_file": "https://storage.yativo.com/documents/abc/lease.pdf"
      },
      "associated_persons": [
        {
          "first_name": "Jane",
          "last_name": "Doe",
          "birth_date": "1978-07-22",
          "nationality": "US",
          "email": "jane.doe@acmepay.com",
          "title": "CEO",
          "ownership_percentage": 60,
          "relationship_established_at": "2018-03-12",
          "residential_address": {
            "street_line_1": "456 Coral Way",
            "city": "Miami",
            "state": "FL",
            "postal_code": "33133",
            "country": "US"
          },
          "identifying_information": [
            {
              "type": "passport",
              "issuing_country": "US",
              "number": "P87654321",
              "date_issued": "2020-01-10",
              "expiration_date": "2030-01-10",
              "image_front_file": "https://storage.yativo.com/documents/abc/jane-passport.jpg"
            }
          ],
          "has_ownership": true,
          "has_control": true,
          "is_signer": true,
          "is_director": true
        }
      ],
      "account_purpose": "business_transactions",
      "source_of_funds": "business_income",
      "high_risk_activities": ["none_of_the_above"],
      "conducts_money_services": false,
      "regulated_activity": {},
      "documents": [
        {
          "purpose": "business_registration",
          "description": "Certificate of Incorporation",
          "file": "https://storage.yativo.com/documents/abc/certificate.pdf"
        },
        {
          "purpose": "tax_documents",
          "description": "EIN confirmation letter",
          "file": "https://storage.yativo.com/documents/abc/ein.pdf"
        }
      ]
    }'
  ```
</RequestExample>

<ResponseExample>
  ```json Success theme={null}
  {
    "success": true,
    "message": "Business KYC submission received successfully",
    "business_data": {
      "customer_id": "d47f8a2b-1c3e-4f5a-9b8c-7d6e5f4a3b2c",
      "type": "business",
      "business_legal_name": "Acme Payments LLC",
      "status": "submitted",
      "created_at": "2026-06-01T10:00:00.000000Z"
    }
  }
  ```
</ResponseExample>

***

## Check KYC / KYB status

```
GET /customer/kyc/{customer_id}
```

<ParamField path="customer_id" type="string" required>
  The customer UUID.
</ParamField>

### Status values

| Status          | Description                            |
| --------------- | -------------------------------------- |
| `not_started`   | No submission has been made            |
| `submitted`     | Received, awaiting review              |
| `manual_review` | Under manual compliance review         |
| `approved`      | Customer is fully verified             |
| `rejected`      | Rejected — see `kyc_rejection_reasons` |
| `under_review`  | Additional review in progress          |

<Note>
  Check both `status === "approved"` **and** `is_va_approved === true` before enabling payment features for a customer.
</Note>

<RequestExample>
  ```bash cURL theme={null}
  curl -X GET 'https://api.yativo.com/api/v1/customer/kyc/c586066b-0f29-468f-b775-15483871a202' \
    -H 'Authorization: Bearer YOUR_ACCESS_TOKEN'
  ```
</RequestExample>

<ResponseExample>
  ```json Approved theme={null}
  {
    "status": "success",
    "status_code": 200,
    "data": {
      "first_name": "Alex",
      "last_name": "Smith",
      "status": "approved",
      "kyc_rejection_reasons": [],
      "kyc_requirements_due": [],
      "bio_data": {
        "customer_kyc_status": "approved",
        "kyc_verified_date": "2026-06-01T12:00:00.000000Z"
      },
      "kyc_link": "https://kyc.yativo.com/individual/c586066b-0f29-468f-b775-15483871a202",
      "is_va_approved": true
    }
  }
  ```

  ```json Rejected theme={null}
  {
    "status": "success",
    "status_code": 200,
    "data": {
      "first_name": "Alex",
      "last_name": "Smith",
      "status": "rejected",
      "kyc_rejection_reasons": [
        "Selfie image does not clearly show the customer's face",
        "Document expiration date is invalid"
      ],
      "kyc_requirements_due": ["selfie_image", "identifying_information"],
      "bio_data": {
        "customer_kyc_status": "rejected",
        "kyc_verified_date": null
      },
      "kyc_link": "https://kyc.yativo.com/individual/c586066b-0f29-468f-b775-15483871a202",
      "is_va_approved": false
    }
  }
  ```
</ResponseExample>

***

## Update a KYC submission

Use this endpoint to correct information or provide missing documents after a rejection.

```
PUT /customer/kyc/update
```

Send only the fields you need to correct. `customer_id` is always required.

<RequestExample>
  ```bash cURL theme={null}
  curl -X PUT 'https://api.yativo.com/api/v1/customer/kyc/update' \
    -H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
    -H 'Content-Type: application/json' \
    -H 'Idempotency-Key: kyc-update-2026-002' \
    -d '{
      "customer_id": "c586066b-0f29-468f-b775-15483871a202",
      "selfie_image": "https://storage.yativo.com/documents/abc/selfie-v2.jpg",
      "identifying_information": [
        {
          "type": "passport",
          "issuing_country": "US",
          "number": "P12345678",
          "date_issued": "2019-06-01",
          "expiration_date": "2029-06-01",
          "image_front_file": "https://storage.yativo.com/documents/abc/passport-front-hd.jpg"
        }
      ]
    }'
  ```
</RequestExample>

***

## Service endorsements

After approval, customers receive service endorsements that unlock specific payment rails.

| Service        | Description                       |
| -------------- | --------------------------------- |
| `base`         | USD base payment access           |
| `sepa`         | European SEPA transfers           |
| `spei`         | Mexico SPEI transfers             |
| `brazil`       | Brazilian payment rails           |
| `eurde`        | EUR/DE virtual accounts           |
| `usd_latam`    | USD Latin America transfers       |
| `eur_latam`    | EUR Latin America transfers       |
| `virtual_card` | Virtual card issuance             |
| `asian`        | Asian region payments             |
| `native`       | Native payment rails              |
| `cobo_pobo`    | Collection / payment-on-behalf-of |

### Endorsement statuses

| Status         | Description                   |
| -------------- | ----------------------------- |
| `not_started`  | Not yet initiated             |
| `pending`      | Awaiting review               |
| `approved`     | Active for this customer      |
| `rejected`     | Rejected                      |
| `declined`     | Customer declined             |
| `under_review` | Additional review in progress |

### Regenerate an endorsement link

If an endorsement link has expired, regenerate it and share the new URL with the customer:

```
GET https://kyc.yativo.com/api/kyc/regenerate/{customer_id}/{service}
```

<RequestExample>
  ```bash cURL theme={null}
  curl -X GET 'https://kyc.yativo.com/api/kyc/regenerate/c586066b-0f29-468f-b775-15483871a202/sepa' \
    -H 'Authorization: Bearer YOUR_ACCESS_TOKEN'
  ```
</RequestExample>

<ResponseExample>
  ```json Success theme={null}
  {
    "success": true,
    "message": "Endorsement link regenerated successfully",
    "data": {
      "service": "sepa",
      "customer_id": "c586066b-0f29-468f-b775-15483871a202",
      "link": "https://kyc.yativo.com/endorsement/sepa/c586066b-0f29-468f-b775-15483871a202?token=abc123"
    }
  }
  ```
</ResponseExample>

***

## Reference lookups

### Occupation codes

Get the full list of valid occupation codes for `most_recent_occupation_code`:

```
GET /auth/occupation-codes
```

<RequestExample>
  ```bash cURL theme={null}
  curl -X GET 'https://api.yativo.com/api/v1/auth/occupation-codes' \
    -H 'Authorization: Bearer YOUR_ACCESS_TOKEN'
  ```
</RequestExample>

<ResponseExample>
  ```json theme={null}
  {
    "status": "success",
    "status_code": 200,
    "data": [
      { "display_name": "Software developer", "code": "151252" },
      { "display_name": "Accountant and auditor", "code": "132011" },
      { "display_name": "Financial manager", "code": "113031" },
      { "display_name": "Registered nurse", "code": "291141" }
    ]
  }
  ```
</ResponseExample>

### Supported countries

Get the list of countries supported for customer registration and verification:

```
GET /auth/verification-locations
```

<RequestExample>
  ```bash cURL theme={null}
  curl -X GET 'https://api.yativo.com/api/v1/auth/verification-locations' \
    -H 'Authorization: Bearer YOUR_ACCESS_TOKEN'
  ```
</RequestExample>

<ResponseExample>
  ```json theme={null}
  {
    "status": "success",
    "status_code": 200,
    "data": [
      { "country": "United States", "code": "US" },
      { "country": "Brazil", "code": "BR" },
      { "country": "Nigeria", "code": "NG" },
      { "country": "Mexico", "code": "MX" },
      { "country": "Colombia", "code": "CO" }
    ]
  }
  ```
</ResponseExample>

***

## Enum reference values

### `employment_status`

| API value       | Description   |
| --------------- | ------------- |
| `employed`      | Employed      |
| `exempt`        | Exempt        |
| `homemaker`     | Homemaker     |
| `retired`       | Retired       |
| `self_employed` | Self-Employed |
| `student`       | Student       |
| `unemployed`    | Unemployed    |

### `expected_monthly_payments_usd`

| API value     | Range             |
| ------------- | ----------------- |
| `0_4999`      | Less than \$5,000 |
| `5000_9999`   | $5,000 – $9,999   |
| `10000_49999` | $10,000 – $49,999 |
| `50000_plus`  | \$50,000 or more  |

### `source_of_funds`

| API value                    | Description                   |
| ---------------------------- | ----------------------------- |
| `business_income`            | Business Income               |
| `company_funds`              | Company Funds                 |
| `ecommerce_reseller`         | Ecommerce Reseller            |
| `gambling_proceeds`          | Gambling Proceeds             |
| `gifts`                      | Gifts                         |
| `government_benefits`        | Government Benefits           |
| `inheritance`                | Inheritance                   |
| `investments_loans`          | Investments / Loans           |
| `pension_retirement`         | Pension / Retirement          |
| `salary`                     | Salary                        |
| `sale_of_assets_real_estate` | Sale of Assets or Real Estate |
| `savings`                    | Savings                       |
| `someone_elses_funds`        | Someone Else's Funds          |

### `account_purpose`

| API value                              | Description                              |
| -------------------------------------- | ---------------------------------------- |
| `business_transactions`                | Business Transactions                    |
| `charitable_donations`                 | Charitable Donations                     |
| `ecommerce_retail_payments`            | Ecommerce / Retail Payments              |
| `investment_purposes`                  | Investment Purposes                      |
| `operating_a_company`                  | Operating a Company                      |
| `other`                                | Other (requires `account_purpose_other`) |
| `payments_to_friends_or_family_abroad` | Payments to Friends or Family Abroad     |
| `personal_or_living_expenses`          | Personal / Living Expenses               |
| `protect_wealth`                       | Protect Wealth                           |
| `purchase_goods_and_services`          | Purchase Goods and Services              |
| `receive_payment_for_freelancing`      | Receive Payment for Freelancing          |
| `receive_salary`                       | Receive Salary                           |

### `high_risk_activities` (KYB)

| API value                                                   | Description                               |
| ----------------------------------------------------------- | ----------------------------------------- |
| `adult_entertainment`                                       | Adult entertainment                       |
| `gambling`                                                  | Gambling                                  |
| `hold_client_funds`                                         | Holding client funds                      |
| `investment_services`                                       | Investment services                       |
| `lending_banking`                                           | Lending or banking                        |
| `marijuana_or_related_services`                             | Marijuana-related services                |
| `money_services`                                            | Money services                            |
| `operate_foreign_exchange_virtual_currencies_brokerage_otc` | Foreign exchange / crypto brokerage / OTC |
| `pharmaceuticals`                                           | Pharmaceuticals                           |
| `precious_metals_precious_stones_jewelry`                   | Precious metals / stones / jewelry        |
| `safe_deposit_box_rentals`                                  | Safe deposit box rentals                  |
| `weapons_firearms_and_explosives`                           | Weapons / firearms / explosives           |
| `none_of_the_above`                                         | None of the above                         |

### `business_type` (KYB)

`cooperative`, `corporation`, `llc`, `partnership`, `sole_prop`, `trust`, `other`

***

## ID types by country

The accepted `type` values under `identifying_information` depend on the issuing country. Common types available globally:

| Type          | Description                |
| ------------- | -------------------------- |
| `passport`    | Passport                   |
| `national_id` | National ID card           |
| `other`       | Other government-issued ID |

Countries also accept country-specific types, for example:

| Country               | Extra types available |
| --------------------- | --------------------- |
| `NG` (Nigeria)        | `tin`, `nin`, `bvn`   |
| `US` (United States)  | `ssn`, `itin`         |
| `BR` (Brazil)         | `cpf`                 |
| `GB` (United Kingdom) | `nino`, `utr`         |
| `IN` (India)          | `pan`                 |
| `MX` (Mexico)         | `rfc`, `curp`, `ine`  |
| `DE` (Germany)        | `steuer_id`           |
| `AE` (UAE)            | `emirates_id`         |

Use `GET /auth/verification-locations` to check which countries are supported, and consult the full ID type reference in the API reference section.

***

## Webhooks

Configure your webhook endpoint in the Yativo dashboard to receive status updates automatically.

### Events

| Event                     | Description                                   |
| ------------------------- | --------------------------------------------- |
| `kyc.status_updated`      | KYC/KYB verification status changed           |
| `kyc.endorsement_updated` | A specific service endorsement status changed |

### Payload example

```json theme={null}
{
  "event": "kyc.status_updated",
  "data": {
    "customer_id": "c586066b-0f29-468f-b775-15483871a202",
    "status": "approved",
    "type": "individual",
    "endorsements": ["base", "sepa"],
    "rejection_reasons": [],
    "updated_at": "2026-06-01T15:00:00.000000Z"
  }
}
```

***

## Error handling

```json theme={null}
{
  "status": "failed",
  "status_code": 422,
  "message": "Request failed",
  "data": {
    "email": ["The email field is required."],
    "nationality": ["The nationality must be 2 characters."],
    "identifying_information": ["The identifying information field is required."]
  }
}
```

### Common errors and fixes

| Error                                        | Fix                                                       |
| -------------------------------------------- | --------------------------------------------------------- |
| `customer_id does not exist`                 | Create the customer first with `POST /customer`           |
| `nationality must be 2 characters`           | Use ISO 3166-1 alpha-2 (e.g. `"US"`, `"NG"`)              |
| `birth_date must be a date before today`     | Ensure the date is in the past                            |
| `expiration_date must be a date after today` | ID document must not be expired                           |
| `bvn is required`                            | Required for Nigerian nationals — exactly 11 digits       |
| `nin is required`                            | Required for Nigerian nationals — exactly 11 digits       |
| `calling_code is invalid`                    | Must be `+` followed by 1–4 digits, e.g. `"+1"`, `"+234"` |
| `identifying_information is required`        | At least one ID document must be included                 |
| `documents is required`                      | KYB requires at least one business document               |

***

## Implementation notes

* KYC review typically completes within **24 hours**. Complex cases may take longer.
* Use `Idempotency-Key` on all POST and PUT requests to prevent duplicate submissions.
* Files can be passed as hosted URLs (from `POST /storage/upload`) or base64-encoded strings — both are accepted.
* For Nigerian customers (`nationality: "NG"`), `bvn` and `nin` are mandatory regardless of which ID type is provided.
* The `state` field accepts both `"US-CA"` and `"CA"` — the API normalizes both forms.
* Access tokens expire in 600 seconds. Implement token refresh before making KYC submissions in long-running flows.
