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

# Customers

> Create Customer records, send pairing links, and move Numbers between Customers with the team client.

A Customer represents one of your own customers inside a project. Each Customer
owns the Numbers they connect. Use `platform.customers` on a team client.

| Task | Permission |
| - | - |
| Read Customers, their Numbers, events, and pairing links | `customers:read` |
| Enable Customers; create, update, archive, and restore Customers; create and revoke pairing links; transfer Numbers | `customers:manage` |

## Turn on Customers for a project

```typescript theme={null}
const status = await platform.customers.status("<project-id>");

if (!status.data.data.enabled) {
  await platform.customers.enable("<project-id>", { idempotencyKey: "enable-customers-<project-id>" });
}
```

## Create a Customer

```typescript theme={null}
const customer = await platform.customers.create(
  { projectId: "<project-id>", name: "Ada", externalCustomerId: "crm_456" },
  { idempotencyKey: "create-customer-crm_456" },
);

const customerId = customer.data.data.id;
```

`externalCustomerId` is your own ID for the Customer. A Customer has no phone
number. Phone numbers belong to Numbers and pairing links.

`create`, `enable`, `archive`, `restore`, `createPairingLink`, and
`transferNumber` take a required request options argument. Pass an
`idempotencyKey` in it. Customer and pairing-link creation require one.

## Send a pairing link

A pairing link lets the Customer connect their WhatsApp account:

```typescript theme={null}
const link = await platform.customers.createPairingLink(
  customerId,
  { projectId: "<project-id>", expectedPhone: "+15551234567", methods: ["qr", "phone"] },
  { idempotencyKey: "pairing-crm_456-1" },
);

console.log(link.data.data.url);
```

The URL is returned only in the first response. A repeat with the same
idempotency key returns `url: null`.

Polymorfa checks `expectedPhone` with one of your connected Numbers. A number
confirmed as not on WhatsApp fails with `400 phone_not_registered`. When no
connected Number can check it, the link is created anyway.

List links with `listPairingLinks(customerId, projectId)` and withdraw one with
`revokePairingLink(customerId, pairingLinkId, projectId)`. See
[Pairing links](/guides/customers/pairing-links).

## List Customers

```typescript theme={null}
const page = await platform.customers.list({ projectId: "<project-id>", search: "Ada" });

for (const summary of page.data.data) {
  console.log(summary.id, summary.name, summary.numberCount);
}
```

Follow `page.data.page.nextCursor` for more results. See
[Read every page](/sdks/typescript/errors#read-every-page).

## Read a Customer's Numbers and events

```typescript theme={null}
const numbers = await platform.customers.listNumbers(customerId, "<project-id>");
for (const number of numbers.data.data) console.log(number.sessionId, number.status);

const events = await platform.customers.listEvents(customerId, { projectId: "<project-id>", limit: 20 });
console.log(events.data.data.length);
```

## Move a Number to another Customer

```typescript theme={null}
await platform.customers.transferNumber(
  "<target-customer-id>",
  "<number-id>",
  { projectId: "<project-id>", sourceCustomerId: customerId, confirm: true },
  { idempotencyKey: "transfer-<number-id>-to-<target-customer-id>" },
);
```

## Archive and restore a Customer

```typescript theme={null}
await platform.customers.archive(customerId, { projectId: "<project-id>" }, { idempotencyKey: "archive-crm_456" });
await platform.customers.restore(customerId, { projectId: "<project-id>" }, { idempotencyKey: "restore-crm_456" });
```

See [Customers](/guides/customers/overview) for what each Customer state means.


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