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

# Customers Overview

A customer is a person or a business you collect from. Customers belong to your merchant account: the same email can exist under different merchants, and you can only see your own.

Only `email` and a name are required to create one. Everything else is optional when you create the customer. What a particular virtual account needs is checked when you create the account, see [Virtual account requirements](https://dev-docs.pagoramp.com/virtual-accounts-requirements).

## Endpoints

| Method | Path | Purpose |
| - | - | - |
| `POST` | `/customers` | Create a customer |
| `GET` | `/customers` | List and search customers |
| `GET` | `/customers/{uuid}` | Get one customer |
| `PATCH` | `/customers/{uuid}` | Update any subset of fields |
| `GET` | `/customers/{uuid}/virtual-accounts` | Virtual accounts of a customer |
| `GET` | `/customers/identification-types` | Accepted identification types by country |

## Fields

`type` is `individual` or `business` and defaults to `individual`.

| Field | Applies to | Required | Example | Notes |
| - | - | - | - | - |
| `email` | Both | Yes | `johndoe@example.com` | Unique per merchant, not case sensitive |
| `firstname`, `lastname` | Individual | Yes | `John`, `Doe` | Checked by the [name rules](#name-rules) |
| `businessName` | Business | Yes | `Acme Ltd` | Legal name |
| `phone` | Both | No | `+2348012345678` | Must start with `+` and the country code. Spaces, dots, dashes and brackets are removed before it is stored |
| `country` | Both | No | `NG` | ISO 3166-1 alpha-2 |
| `externalReference` | Both | No | `cust_1001` | Your own id. Unique per merchant |
| `identification` | Both | No | `{ "type": "BVN", "number": "12345678901" }` | See [Identification requirements](https://dev-docs.pagoramp.com/identification-requirements) |
| `address` | Both | No | `{ "line1": "12 Marina Road", "city": "Lagos", "country": "NG" }` | See [Address](#address) |
| `dateOfBirth` | Individual | No | `1990-06-15` | `YYYY-MM-DD` |
| `nationality` | Individual | No | `NG` | ISO 3166-1 alpha-2 |
| `occupation` | Individual | No | `Engineer` | Up to 80 characters |
| `registrationNumber` | Business | No | `BN123456789` | Company registration number |
| `owners` | Business | No | See below | Up to 20 owners and directors |
| `documents` | Both | No | See below | Up to 20 documents, https links |
| `metadata` | Both | No | `{ "plan": "pro" }` | Returned unchanged, 4000 characters of JSON at most |

### Identification

`identification.type` is the kind of document and `identification.number` is its number. The accepted types depend on the customer's country, and whether a virtual account needs one depends on the currency. See [Identification requirements by country](https://dev-docs.pagoramp.com/identification-requirements) for Nigeria, Ghana, Kenya, the United States, Canada, the euro area, the United Kingdom, Tanzania and the rest of the world. `GET /customers/identification-types?country=NG` returns the same lists for building a form.

`identification.number` is stored encrypted and is never returned. Responses show the type and the last four characters only: `{ "type": "BVN", "last4": "8901" }`.

### Address

`line1`, `line2`, `city`, `state`, `postalCode` and `country` (ISO 3166-1 alpha-2). Every part is optional on its own, but some currencies need the full address, for example CAD.

### Owners (business)

```json theme={null}
{ "firstname": "Jane", "lastname": "Roe", "ownershipPercent": 60, "dateOfBirth": "1985-04-12", "nationality": "CA" }
```

`firstname` and `lastname` are required for each owner.

### Documents

```json theme={null}
{ "type": "incorporation", "url": "https://files.example.com/acme-incorporation.pdf" }
```

`type` is for example `id_document`, `utility_bill`, `incorporation` or `proof_of_address`. `url` must be an https link the provider can open.

## Examples

Minimal individual:

```json theme={null}
{ "firstname": "John", "lastname": "Doe", "email": "johndoe@example.com" }
```

Business:

```json theme={null}
{
  "type": "business",
  "businessName": "Acme Ltd",
  "email": "finance@acme.example",
  "country": "CA",
  "registrationNumber": "BN123456789",
  "address": { "line1": "100 King St W", "city": "Toronto", "state": "ON", "postalCode": "M5X 1A9", "country": "CA" },
  "owners": [{ "firstname": "Jane", "lastname": "Roe", "ownershipPercent": 60 }],
  "documents": [{ "type": "incorporation", "url": "https://files.example.com/acme-incorporation.pdf" }]
}
```

Response (`201`):

```json theme={null}
{
  "status": "success",
  "message": "Customer created successfully",
  "data": {
    "uuid": "224ca5c5-f2a6-419b-bf36-73997434d945",
    "type": "individual",
    "firstname": "John",
    "lastname": "Doe",
    "email": "johndoe@example.com",
    "kycStatus": "incomplete",
    "createdAt": "2026-10-16T09:30:00.000Z"
  }
}
```

`kycStatus` is `incomplete` until identification is on file, then `pending`.

## Updating a customer

`PATCH /customers/{uuid}` takes any subset of the fields above.

* **Contact and reference fields** (`phone`, `email`, `address`, `externalReference`, `documents`, `metadata`) can change at any time.
* **Identity fields** (`firstname`, `lastname`, `businessName`, `type`, `country`, `identification`, `dateOfBirth`, `nationality`, `registrationNumber`, `owners`) can change only while the customer has no active virtual account, because the provider account is tied to the identity it was opened with. Otherwise the request returns `409`:

```json theme={null}
{
  "status": "error",
  "message": "Identity details cannot change while the customer has an active virtual account",
  "errors": [{ "field": "lastname", "code": "customer_identity_locked" }]
}
```

Deactivate the virtual account first if the identity really has to change.

## Name rules

Names are checked when you create or update a customer, and again before a name goes to a provider. A rejected name returns `422`:

```json theme={null}
{
  "status": "error",
  "message": "Customer name is not allowed",
  "errors": [{ "field": "firstname", "code": "name_not_allowed" }]
}
```

| Code | Meaning |
| - | - |
| `name_required` | The name is empty |
| `name_too_short` | Too short |
| `name_too_long` | Too long |
| `name_invalid_characters` | Digits or symbols a name does not use |
| `name_not_allowed` | Placeholder (for example "test"), keyboard mashing, or repeated letters |
| `name_script_not_supported` | The provider needs Latin characters |

We can reject names that are clearly not real. We cannot confirm that a name matches a person.

## Other errors

| Status | Code | Meaning |
| - | - | - |
| `409` | `customer_exists` | A customer with this email already exists for your account |
| `409` | `external_reference_exists` | Another customer already uses this `externalReference` |
| `409` | `customer_identity_locked` | See above |
| `404` | | The customer does not exist for your account |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.