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

# Customers

> Create and manage customer records server-side.

## createCustomer

```typescript theme={null}
const customer = await billing.createCustomer({
  externalUserId: "user_123",
  email: "jane@example.com",
  name: "Jane Smith",
  metadata: { company: "Acme Inc" },
});
```

### Parameters

| Name                     | Type                  | Required | Description             |
| ------------------------ | --------------------- | -------- | ----------------------- |
| `externalUserId`         | `string`              | Yes      | Your user's unique ID   |
| `externalOrganizationId` | `string`              | No       | Organization ID for B2B |
| `email`                  | `string`              | No       | Customer email          |
| `name`                   | `string`              | No       | Customer name           |
| `metadata`               | `Record<string, any>` | No       | Custom key-value pairs  |

***

## getCustomer

```typescript theme={null}
const customer = await billing.getCustomer("cus_123");
```

***

## getCustomerByExternalId

Look up a customer by their ID in your system.

```typescript theme={null}
const customer = await billing.getCustomerByExternalId("user_123");
```

***

## updateCustomer

```typescript theme={null}
const updated = await billing.updateCustomer("cus_123", {
  name: "Jane Doe",
  metadata: { company: "Acme Inc" },
});
```

***

## deleteCustomer

```typescript theme={null}
await billing.deleteCustomer("cus_123");
```

***

## listUnresolvedCustomers

List customers imported from Stripe that don't yet have an `external_id` bound to your user ID. Pair with `bindCustomer()` to resolve them. See [Migrating from Stripe](/guides/stripe-migration) for context.

```typescript theme={null}
const { customers } = await billing.listUnresolvedCustomers();

for (const c of customers) {
  if (!c.email) continue;
  const user = await db.users.findByEmail(c.email);
  if (user) {
    await billing.bindCustomer(c.id, user.id);
  }
}
```

### Response

```typescript theme={null}
{
  customers: Array<{
    id: string
    stripe_customer_id: string | null
    email: string | null
    name: string | null
    created_at: string
  }>
}
```

***

## bindCustomer

Bind an imported customer to your internal user ID. The customer must currently have no `external_id` set; binding is one-way and immutable.

```typescript theme={null}
await billing.bindCustomer(unresolved.id, user.id);
```

### Parameters

| Name         | Type     | Required | Description                                            |
| ------------ | -------- | -------- | ------------------------------------------------------ |
| `customerId` | `string` | Yes      | BillingOS customer ID (from `listUnresolvedCustomers`) |
| `externalId` | `string` | Yes      | Your user's ID from your database                      |

<Warning>
  External IDs are immutable once set. There's no `unbind` operation — double-check before binding.
</Warning>

***

## Customer object

```typescript theme={null}
interface Customer {
  id: string
  externalUserId: string
  externalOrganizationId?: string
  email?: string
  name?: string
  stripeCustomerId?: string
  metadata?: Record<string, any>
  createdAt: Date
  updatedAt: Date
}
```
