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

# Create a customer

> Create a new customer. Verification stays `PENDING` until the type-specific verification flow completes.

**For `type=individual`**, `id_type` and `id_number` are required. After creation, upload identity files via the legacy KYC flow (see [Creating your first payout](/guides/creating-first-payout)). Only Driver's License, Passport, or Resident Permit are accepted as `id_type`.

**For `type=business`**, `business_name` + `registration_number` + `incorporation_country` are required. The legacy `id_type` / `id_number` fields are no longer required (still accepted for back-compat — when supplied, `id_type` must be `certificate_of_incorporation`). After creation, follow the [Business customer KYB](/guides/kyb/overview) flow: register beneficial owners, upload owner ID files, register KYB documents, then call `/submit`.

ID cards (National Identity Cards) are not accepted at any stage. All uploaded documents must be clear, legible, and authentic — unclear images will be rejected. Fraudulent or falsified documents will result in the customer being permanently blacklisted from the platform.

Required scope: `customer:write`.



## OpenAPI

````yaml /api-reference/customer/create-openapi.json post /api/external/customer
openapi: 3.1.0
info:
  title: Blaaiz Platform API - Create Customer
  version: 1.0.0
  description: >-
    Create a new customer. The required fields and the verification flow that
    follows depend on the customer type.


    **Individual customers** (`type=individual`) require `id_type`, `id_number`,
    and `country` at the customer level — Driver's License, Passport, or
    Resident Permit. The customer's `country` must match the country on the
    identity document. They follow the legacy KYC flow: create the customer,
    upload identity files via `POST /api/external/file/get-presigned-url` and
    `POST /api/external/customer/{id}/files`, and verification triggers
    automatically when `id_file` is included.


    **Business-type customers** (`type=business`) require `business_name`,
    `registration_number`, `incorporation_country`, and `country`. Both
    `country` and `incorporation_country` are explicit and must be equal — a
    company's registered office sits in its country of incorporation by company
    law. The cross-field check is enforced at validation time. Business
    customers follow the KYB flow: create the customer (include the `owners`
    array now or attach owners later via `PUT`), upload owner ID files via the
    dedicated owner-file endpoints, register KYB documents via the dedicated
    document endpoints, and call `POST /api/external/customer/{id}/submit` when
    ready. The legacy `/files` endpoint does not work for business customers —
    see the [Business customer KYB guide](/guides/kyb/overview).


    **Two countries, two addresses.** A business carries up to three ISO country
    codes, each with a distinct meaning:


    - `incorporation_country` — the legal jurisdiction the company is registered
    in. Top-level, business-only, required.

    - `country` — the registered-address country. Top-level. For businesses,
    must equal `incorporation_country`.

    - `operating_country` — the operating-address country, which can differ when
    the business operates from elsewhere. Lives on KYC data alongside the other
    `operating_*` fields, business-only, required whenever any other
    `operating_*` field is supplied.


    Postal-code validation runs against the country the address belongs to:
    `zip_code` against `country`, `operating_zip_code` against
    `operating_country`. Each address is self-describing.


    **Type-specific fields.** Sending fields that don't apply to the customer
    type fails the entire request with `422`. Business KYB fields
    (`registration_number`, `incorporation_country`, `owners`, etc.) and
    operating-address fields (`operating_*`) are rejected on `type=individual`
    requests. Likewise, for back-compat, the legacy `id_type` is still accepted
    on a business customer but only if set to `certificate_of_incorporation` —
    new integrations should omit it.


    **Document quality.** ID cards (National Identity Cards) are not accepted at
    the customer level. All uploaded documents must be clear, legible, and
    authentic — unclear images will be rejected. Fraudulent or falsified
    documents will result in the customer being permanently blacklisted from the
    platform.
servers:
  - url: https://api-prod.blaaiz.com
  - url: https://api-dev.blaaiz.com
security: []
tags:
  - name: Customer
paths:
  /api/external/customer:
    post:
      tags:
        - Customer
      summary: Create a customer
      description: >-
        Create a new customer. Verification stays `PENDING` until the
        type-specific verification flow completes.


        **For `type=individual`**, `id_type` and `id_number` are required. After
        creation, upload identity files via the legacy KYC flow (see [Creating
        your first payout](/guides/creating-first-payout)). Only Driver's
        License, Passport, or Resident Permit are accepted as `id_type`.


        **For `type=business`**, `business_name` + `registration_number` +
        `incorporation_country` are required. The legacy `id_type` / `id_number`
        fields are no longer required (still accepted for back-compat — when
        supplied, `id_type` must be `certificate_of_incorporation`). After
        creation, follow the [Business customer KYB](/guides/kyb/overview) flow:
        register beneficial owners, upload owner ID files, register KYB
        documents, then call `/submit`.


        ID cards (National Identity Cards) are not accepted at any stage. All
        uploaded documents must be clear, legible, and authentic — unclear
        images will be rejected. Fraudulent or falsified documents will result
        in the customer being permanently blacklisted from the platform.


        Required scope: `customer:write`.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateCustomerRequest'
            examples:
              individual:
                value:
                  type: individual
                  first_name: John
                  last_name: Doe
                  email: john.doe@company.com
                  country: NG
                  id_type: passport
                  id_number: '6733823632872'
                  phone: '+2348012345678'
                  dob: '1990-01-15'
                  street: 123 Main Street
                  city: Lagos
                  state: Lagos
                  zip_code: '100001'
                  id_expiry_date: '2030-01-15'
                  id_issue_date: '2020-01-15'
              business_minimal:
                summary: Business customer — MINIMAL (allow-listed, NGN-only)
                value:
                  type: business
                  kyb_scope: MINIMAL
                  business_name: Acme Nigeria Limited
                  country: NG
                  incorporation_country: NG
                  registration_number: RC123456
                  email: ops@acme.example.ng
                  phone: '+2348012345678'
              business:
                summary: Business customer — FULL (Standard KYB)
                value:
                  type: business
                  kyb_scope: FULL
                  business_name: Acme Corp
                  trading_name: Acme
                  business_type: llc
                  registration_number: RC123456
                  incorporation_country: NG
                  country: NG
                  incorporation_date: '2019-03-12'
                  industry_type: Software & SaaS
                  business_description: B2B SaaS platform for African logistics operators.
                  website: https://acme.example.com
                  source_of_funds: business_revenue
                  estimated_annual_revenue: '1000000_4999999'
                  expected_monthly_payments: 250
                  account_purpose: send_receive_funds_related_parties
                  email: contact@acme.com
                  phone: '+2348012345678'
                  tin: 12345678-0001
                  street: 456 Business Ave
                  city: Lagos
                  state: Lagos
                  zip_code: '100001'
                  operating_street: 789 Operations Blvd
                  operating_city: Lagos
                  operating_state: Lagos
                  operating_zip_code: '100002'
                  operating_country: NG
                  owners:
                    - first_name: Jane
                      last_name: Doe
                      email: jane@acme.example.com
                      date_of_birth: '1985-04-22'
                      nationality: NG
                      title: CEO
                      ownership_percentage: 60
                      has_control: true
                      is_signer: true
                      is_beneficial_owner: true
                      id_document_type: passport
                      id_document_number: A12345678
                      id_document_country: NG
                      id_expiry_date: '2030-01-15'
                      is_pep: false
                    - first_name: John
                      last_name: Smith
                      ownership_percentage: 40
                      is_beneficial_owner: true
      responses:
        '201':
          description: Customer created successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateCustomerResponse'
              example:
                message: Customer created successfully.
                data:
                  id: 9d4c4ec5-59ea-4130-bf8a-6a5edec401ee
                  business_id: 9d4c4ec5-572d-49de-a362-f01ed09f2b1b
                  first_name: John
                  last_name: Doe
                  business_name: null
                  type: individual
                  email: john.doe@company.com
                  country: NG
                  id_type: passport
                  id_number: '6733823632872'
                  verification_status: PENDING
                  kyb_scope: null
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                status: false
                message: Invalid request parameters
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                status: false
                message: Invalid or missing access token
      security:
        - oauth2ClientCredentials:
            - customer:write
components:
  schemas:
    CreateCustomerRequest:
      type: object
      properties:
        type:
          type: string
          enum:
            - individual
            - business
          description: Customer type.
        kyb_scope:
          type: string
          enum:
            - FULL
            - MINIMAL
          description: >-
            Business-only. Selects what data we require to onboard the customer,
            and which currencies they can hold a Virtual Bank Account in.


            - `FULL` (Standard KYB) — Business identity (name, registration
            number, country of incorporation), beneficial owners summing to 100%
            ownership, an ID file for each owner, plus a formation document.
            Eligible for NGN / USD / GBP / EUR VBAs.

            - `MINIMAL` — Same business identity as Full, **without owners or
            per-owner ID files**, plus a formation document. Eligible for NGN
            VBAs only.


            **Who can use `MINIMAL`:** Minimal is gated by an admin-controlled
            allow list. Allow-listed platforms who omit `kyb_scope` default to
            `MINIMAL` and can pass `FULL` explicitly when they need a customer
            to qualify for non-NGN currencies. Platforms not on the list get
            `FULL` by default — sending `MINIMAL` returns `422`. Forbidden on
            `type=individual` (returns `422`).


            Direction is one-way: a `MINIMAL` customer can be upgraded via `POST
            /customer/{id}/upgrade-kyb-scope`. There is no downgrade. See the
            [Business customer KYB guide](/guides/kyb/overview).
        email:
          type: string
          format: email
        country:
          type: string
          description: >-
            ISO alpha-2 country code of the **registered address**. Required for
            both `type=individual` and `type=business`. For individuals, must
            match the country on the identity document. For businesses, must
            equal `incorporation_country` — a company's registered office sits
            in its country of incorporation by company law (cross-field check at
            validation time).
        id_type:
          type: string
          enum:
            - drivers_license
            - passport
            - resident_permit
          description: >-
            Personal identity document type. **Individual customers only.**


            - **`type=individual`** — required. Must be `drivers_license`,
            `passport`, or `resident_permit`.

            - **`type=business`** — prohibited. Businesses identify via
            `registration_number` + `incorporation_country` regardless of
            `kyb_scope`. Sending `id_type` on a business returns `422`.
        id_number:
          type: string
          description: >-
            Personal identity document number. **Individual customers only.**


            - **`type=individual`** — required. The number on the document
            supplied via `id_type`.

            - **`type=business`** — prohibited. Businesses identify via
            `registration_number`. Sending `id_number` on a business returns
            `422`.
        first_name:
          type: string
          description: Required if type is individual.
        last_name:
          type: string
          description: Required if type is individual.
        business_name:
          type: string
          description: Required if type is business.
        phone:
          type: string
        tin:
          type: string
          description: >-
            Tax identification number (varies by country). Where applicable, use
            the Get Identification Type endpoint to determine the correct label
            or field to collect for the customer's country and type.
        dob:
          type: string
          format: date
        street:
          type: string
        city:
          type: string
        state:
          type: string
        zip_code:
          type: string
        id_expiry_date:
          type: string
          format: date
        id_issue_date:
          type: string
          format: date
        operating_street:
          type: string
          description: >-
            Business operating address — street. Use when the operating address
            differs from the registered (`street`) address.
        operating_city:
          type: string
          description: Business operating city.
        operating_state:
          type: string
          description: Business operating state.
        operating_zip_code:
          type: string
          description: >-
            Business operating zip / postal code. Validated against
            `operating_country` (not `country`) — the operating address is
            self-describing.
        operating_country:
          type: string
          description: >-
            Business operating address country, as ISO alpha-2. **Required
            whenever any other `operating_*` field is supplied.** Can differ
            from `country` and `incorporation_country` when the business
            operates from a different jurisdiction. Anchors postal-code
            validation for `operating_zip_code`.
        trading_name:
          type: string
          description: Business KYB field. Trading or 'doing business as' name.
        business_type:
          type: string
          enum:
            - corporation
            - government_entity
            - llc
            - non_profit
            - other
            - partnership
            - sole_proprietorship
          description: Business KYB field. Legal entity type.
        registration_number:
          type: string
          description: >-
            Business registration / company number from the issuing authority.
            **Required for every business customer regardless of `kyb_scope`.**
            Together with `incorporation_country`, this is the canonical
            identifier for a business customer.


            Unique per platform: two of your customers cannot share the same
            `(registration_number, incorporation_country)` pair. The same number
            is fine across different incorporation countries (jurisdictions
            overlap), and across different platforms.
        incorporation_country:
          type: string
          description: >-
            Legal jurisdiction of incorporation, as ISO alpha-2. **Required for
            every business customer regardless of `kyb_scope`.** Distinct from
            `country` (registered-address country) and `operating_country`
            (operating-address country); for businesses, `country` must equal
            `incorporation_country` (a company's registered office sits in its
            country of incorporation).
        incorporation_date:
          type: string
          format: date
          description: Business KYB field. Must be in the past.
        industry_type:
          type: string
          description: Business KYB field. Free-form industry/sector descriptor.
        business_description:
          type: string
          description: >-
            Business KYB field. Description of the business activity (max 2000
            chars).
        website:
          type: string
          format: uri
          description: Business KYB field. Public website URL.
        source_of_funds:
          type: string
          enum:
            - business_revenue
            - business_loans
            - investment_income
            - third_party_funds
            - other
          description: Business KYB field. Where the business's funds originate.
        estimated_annual_revenue:
          type: string
          enum:
            - '0_99999'
            - '100000_499999'
            - '500000_999999'
            - '1000000_4999999'
            - '5000000_24999999'
            - '25000000_99999999'
            - '100000000_249999999'
            - 250000000_plus
          description: Business KYB field. Estimated annual revenue band, in USD.
        expected_monthly_payments:
          type: integer
          description: >-
            Business KYB field. Expected monthly payment count
            (0–1,000,000,000).
        account_purpose:
          type: string
          enum:
            - receive_payments_for_goods_and_services
            - send_payments_for_goods_and_services
            - send_receive_funds_related_parties
            - other
          description: Business KYB field. Stated purpose of the Blaaiz account.
        owners:
          type: array
          maxItems: 5
          description: >-
            Business KYB field. Beneficial owners, signatories, and directors.
            Up to 5 entries. Each entry's `ownership_percentage` must sum across
            all owners to exactly 100 before `/submit` will accept the customer.
          items:
            type: object
            required:
              - first_name
              - last_name
            properties:
              first_name:
                type: string
                maxLength: 255
              last_name:
                type: string
                maxLength: 255
              email:
                type: string
                format: email
              phone:
                type: string
              date_of_birth:
                type: string
                format: date
                description: Must be at least 18 years ago.
              nationality:
                type: string
                description: ISO alpha-2 country code.
              title:
                type: string
                description: e.g. 'CEO', 'Director'.
              ownership_percentage:
                type: number
                minimum: 0
                maximum: 100
              has_control:
                type: boolean
              is_signer:
                type: boolean
              is_beneficial_owner:
                type: boolean
              street:
                type: string
                minLength: 9
                maxLength: 255
              city:
                type: string
              state:
                type: string
              zip_code:
                type: string
              country:
                type: string
                description: ISO alpha-2 country code.
              id_document_type:
                type: string
                enum:
                  - passport
                  - drivers_license
                  - id_card
                  - resident_permit
                description: >-
                  Owner-level ID type. Note that `id_card` is allowed at the
                  owner level (unlike the customer-level `id_type`).
              id_document_number:
                type: string
              id_document_country:
                type: string
                description: ISO alpha-2.
              id_expiry_date:
                type: string
                format: date
                description: Must be in the future.
              tin:
                type: string
                minLength: 5
                maxLength: 50
              is_pep:
                type: boolean
                description: Politically exposed person.
              usa_tax_residency:
                type: boolean
      required:
        - type
        - email
    CreateCustomerResponse:
      type: object
      properties:
        message:
          type: string
        data:
          $ref: '#/components/schemas/Customer'
      required:
        - message
        - data
    Error:
      type: object
      properties:
        status:
          type: boolean
        message:
          type: string
      required:
        - status
        - message
    Customer:
      type: object
      properties:
        id:
          type: string
        business_id:
          type: string
        first_name:
          type: string
          nullable: true
        last_name:
          type: string
          nullable: true
        business_name:
          type: string
          nullable: true
        type:
          type: string
        email:
          type: string
        country:
          type: string
        id_type:
          type: string
          nullable: true
          description: >-
            Set for individual customers. May be null on business customers
            (which identify via `registration_number` +
            `incorporation_country`).
        id_number:
          type: string
          nullable: true
          description: Set for individual customers. May be null on business customers.
        verification_status:
          type: string
        kyb_scope:
          type: string
          enum:
            - FULL
            - MINIMAL
          nullable: true
          description: >-
            Set for business customers; `null` for individuals. Determines KYB
            data set + VBA currency eligibility.
      required:
        - id
        - business_id
        - type
        - email
        - country
        - verification_status
  securitySchemes:
    oauth2ClientCredentials:
      type: oauth2
      description: >-
        Use your OAuth client credentials to obtain a short-lived Bearer token
        from POST /oauth/token.
      flows:
        clientCredentials:
          tokenUrl: /oauth/token
          scopes:
            customer:write: Create and update customers and KYC data.

````