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

# Create Customer

> Register a new customer with KYC documents uploaded as files. After approval, the customer can be issued cards.

## Overview

`POST /customers` registers a new customer in your company and submits their KYC documents to Cartevo's verification provider. This endpoint accepts the documents as **uploaded files** (`multipart/form-data`). For URL-based document submission, use [`POST /customers/enroll`](/api-reference/endpoint/post-enroll-customer) instead.

After creation, the customer's `kyc_status` starts as `PENDING` and transitions to `APPROVED` (or `REJECTED`) once the upstream verification completes — typically within minutes for automated checks.

## When to use it

* You hold the customer's KYC documents locally as image/PDF files (e.g. uploaded by the customer through your app).
* You want a single round-trip rather than uploading documents to your own storage first.

For comparison:

| Use this endpoint when…                                    | Use `POST /customers/enroll` when…                       |
| ---------------------------------------------------------- | -------------------------------------------------------- |
| Documents are local files in your server's memory or disk. | Documents are already hosted at public HTTPS URLs.       |
| You want one HTTP call.                                    | You want JSON-only requests for easier auditing/logging. |

## Prerequisites

* Your company has completed KYB and is in `APPROVED` status.
* You have a government-issued ID document for the customer (front; back required for some types).

## Request

### Headers

| Name            | Required | Description             |
| --------------- | -------- | ----------------------- |
| `Authorization` | Yes      | `Bearer <access_token>` |
| `Content-Type`  | Yes      | `multipart/form-data`   |

### Query parameters

| Name     | Type    | Default | Description                                                                                                                                                      |
| -------- | ------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `enroll` | boolean | `false` | If `true`, also enroll the customer on the upstream card-issuer immediately after creation. Otherwise enrollment happens lazily before the first card is issued. |

### Body fields

| Field                   | Type          | Required | Constraints                                                                                 |
| ----------------------- | ------------- | -------- | ------------------------------------------------------------------------------------------- |
| `first_name`            | string        | Yes      | 3–255 chars                                                                                 |
| `last_name`             | string        | Yes      | 3–255 chars                                                                                 |
| `email`                 | string        | Yes      | Valid email                                                                                 |
| `country`               | string        | Yes      | 2–255 chars. Full country name, e.g. `"Cameroon"`                                           |
| `street`                | string        | Yes      | 2–255 chars                                                                                 |
| `city`                  | string        | Yes      | 2–255 chars                                                                                 |
| `state`                 | string        | Yes      | 2–255 chars                                                                                 |
| `postal_code`           | string        | Yes      | 3–255 chars                                                                                 |
| `country_iso_code`      | string        | Yes      | ISO 3166-1 alpha-2, e.g. `CM`, `NG`                                                         |
| `country_phone_code`    | string        | Yes      | Dial code with `+`, e.g. `+237`                                                             |
| `phone_number`          | string        | Yes      | Local subscriber number (no country code), 3–255 chars                                      |
| `identification_number` | string        | Yes      | 1–255 chars. Format depends on `id_document_type`                                           |
| `id_document_type`      | string        | Yes      | Enum: `NIN`, `PASSPORT`, `VOTERS_CARD`, `DRIVERS_LICENSE`                                   |
| `date_of_birth`         | string (date) | Yes      | `YYYY-MM-DD`. Customer must be 18+                                                          |
| `id_document_front`     | file          | Yes      | Image (JPG/PNG) or PDF of the front of the ID document                                      |
| `id_document_back`      | file          | No       | Image or PDF of the back. Required for `DRIVERS_LICENSE` and `NIN`; not used for `PASSPORT` |

### File constraints

* **Accepted MIME types:** `image/jpeg`, `image/png`, `application/pdf`.
* **Recommended resolution:** ≥ 200 DPI; the entire document edge-to-edge visible; no glare; legible text.
* **Max file size:** 10 MB per file (operational guidance — the upstream verifier may reject larger or lower-quality files).

### Example

```bash theme={null}
curl -X POST https://api.cartevo.co/api/v1/customers \
  -H "Authorization: Bearer $TOKEN" \
  -F "first_name=John" \
  -F "last_name=Doe" \
  -F "email=john.doe@example.com" \
  -F "country=Cameroon" \
  -F "country_iso_code=CM" \
  -F "country_phone_code=+237" \
  -F "phone_number=600000000" \
  -F "street=123 Main Street" \
  -F "city=Yaoundé" \
  -F "state=Centre" \
  -F "postal_code=00237" \
  -F "identification_number=12345678901" \
  -F "id_document_type=NIN" \
  -F "date_of_birth=1990-01-15" \
  -F "id_document_front=@/path/to/front.jpg" \
  -F "id_document_back=@/path/to/back.jpg"
```

## Response

### 201 — Customer created

```json theme={null}
{
  "success": true,
  "statusCode": 201,
  "message": "Customer created successfully",
  "data": {
    "id": "8d4f2a1b-5c3e-4d7f-9a6b-2e1c8f9d0a3b",
    "first_name": "John",
    "last_name": "Doe",
    "email": "john.doe@example.com",
    "country": "Cameroon",
    "street": "123 Main Street",
    "city": "Yaoundé",
    "state": "Centre",
    "postal_code": "00237",
    "phone_country_code": "+237",
    "phone_number": "600000000",
    "identification_number": "12345678901",
    "type": "NIN",
    "number": "12345678901",
    "image": "https://cdn.cartevo.co/kyc/.../front.jpg",
    "photo": "https://cdn.cartevo.co/kyc/.../back.jpg",
    "date_of_birth": "1990-01-15T00:00:00.000Z",
    "is_active": true,
    "created_at": "2026-05-09T10:15:00.000Z",
    "updated_at": "2026-05-09T10:15:00.000Z"
  }
}
```

| Field             | Description                                                                       |
| ----------------- | --------------------------------------------------------------------------------- |
| `id`              | Cartevo customer ID (UUID). Use for all future calls — `POST /cards`, etc.        |
| `type`            | The `id_document_type` you submitted.                                             |
| `number`          | The `identification_number` you submitted (preserved as-is).                      |
| `image` / `photo` | Cartevo-hosted URLs for the front and back of the ID, available for your records. |
| `is_active`       | `true` for newly created customers.                                               |

> **Note on KYC status:** This response does **not** include a `kyc_status` field. KYC verification runs asynchronously after creation. Listen for the relevant webhook (`customer.created` is fired immediately; KYC outcome events will be added separately) or poll [`GET /customers/{id}`](/api-reference/endpoint/get-customer-by-id) to check the status.

### Error responses

| Status | `message` example                                           | Trigger                                                  | Recommended action                                   |
| ------ | ----------------------------------------------------------- | -------------------------------------------------------- | ---------------------------------------------------- |
| `400`  | `"first_name must be at least 3 characters"`                | Field validation failure.                                | Fix the request.                                     |
| `400`  | `"Customer must be 18 or older"`                            | `date_of_birth` is less than 18 years ago.               | The customer cannot be onboarded.                    |
| `409`  | `"Customer with this email already exists"`                 | A customer with the same `email` exists in your company. | Fetch the existing customer instead of creating new. |
| `409`  | `"Customer with this identification_number already exists"` | Duplicate ID number in your company.                     | Fetch the existing customer instead of creating new. |
| `413`  | `"File too large"`                                          | A document file exceeds the size limit.                  | Compress the file and retry.                         |
| `415`  | `"Unsupported file type"`                                   | A document is not JPG/PNG/PDF.                           | Convert and retry.                                   |
| `422`  | `"KYC document unreadable"`                                 | The upstream verifier rejected the document quality.     | Resubmit with a clearer scan.                        |

## Webhooks fired

* [`customer.created`](/api-reference/endpoint/webhook#customer-created) — emitted immediately after the customer record is persisted.

## Related

* [`POST /customers/enroll`](/api-reference/endpoint/post-enroll-customer) — JSON variant with hosted document URLs.
* [`GET /customers`](/api-reference/endpoint/get-customers) — list your customers.
* [`POST /cards`](/api-reference/endpoint/post-create-card) — issue a card to an approved customer.


## OpenAPI

````yaml POST /customers
openapi: 3.1.0
info:
  title: Cartevo API
  description: Essential endpoints for wallets, transactions, customers and conversion.
  version: 1.0.0
servers:
  - url: https://api.cartevo.co/api/v1
security:
  - bearerAuth: []
paths:
  /customers:
    post:
      summary: Register new customer
      description: Register a new customer under the business account
      parameters:
        - name: enroll
          in: query
          required: false
          schema:
            type: string
            example: 'true'
          description: Enroll customer on Provider
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              required:
                - email
                - first_name
                - last_name
                - country
                - street
                - city
                - state
                - postal_code
                - country_iso_code
                - country_phone_code
                - phone_number
                - identification_number
                - id_document_type
                - date_of_birth
                - id_document_front
              properties:
                email:
                  type: string
                  format: email
                  example: john.doe@example.com
                first_name:
                  type: string
                  minLength: 3
                  maxLength: 255
                  example: John
                last_name:
                  type: string
                  minLength: 3
                  maxLength: 255
                  example: Doe
                country:
                  type: string
                  minLength: 2
                  maxLength: 255
                  example: Nigeria
                street:
                  type: string
                  minLength: 2
                  maxLength: 255
                  example: 123 Main Street
                city:
                  type: string
                  minLength: 2
                  maxLength: 255
                  example: Lagos
                state:
                  type: string
                  minLength: 2
                  maxLength: 255
                  example: Lagos State
                postal_code:
                  type: string
                  minLength: 3
                  maxLength: 255
                  example: '100001'
                country_iso_code:
                  type: string
                  minLength: 1
                  maxLength: 255
                  example: CM
                country_phone_code:
                  type: string
                  minLength: 1
                  maxLength: 255
                  example: '+234'
                phone_number:
                  type: string
                  minLength: 3
                  maxLength: 255
                  example: '8012345678'
                identification_number:
                  type: string
                  minLength: 1
                  maxLength: 255
                  example: '12345678901'
                id_document_type:
                  type: string
                  enum:
                    - NIN
                    - PASSPORT
                    - VOTERS_CARD
                    - DRIVERS_LICENSE
                  example: NIN
                date_of_birth:
                  type: string
                  format: date
                  example: '1990-01-15'
                id_document_front:
                  type: string
                  format: binary
                id_document_back:
                  type: string
                  format: binary
      responses:
        '201':
          description: Customer registered successfully
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/StandardResponse'
                  - type: object
                    properties:
                      data:
                        $ref: '#/components/schemas/CustomerResponseDto'
        '409':
          description: Customer with this email or ID already exists
components:
  schemas:
    StandardResponse:
      type: object
      properties:
        success:
          type: boolean
          example: true
        statusCode:
          type: integer
          example: 200
        message:
          type: string
          example: Data retrieved successfully
    CustomerResponseDto:
      type: object
      properties:
        id:
          type: string
          format: uuid
        first_name:
          type: string
        last_name:
          type: string
        country:
          type: string
        email:
          type: string
          format: email
        street:
          type: string
        city:
          type: string
        state:
          type: string
        postal_code:
          type: string
        phone_country_code:
          type: string
        phone_number:
          type: string
        identification_number:
          type: string
        type:
          type: string
        image:
          type: string
          nullable: true
        photo:
          type: string
          nullable: true
        number:
          type: string
        date_of_birth:
          type: string
          format: date-time
        is_active:
          type: boolean
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer

````