> For the complete documentation index, see [llms.txt](https://support.swisspay.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://support.swisspay.ai/api-reference/customers.md).

# Customers

Create, retrieve, and list customers. A customer represents the end shopper for whom you make payments.

## The Customer object

```json
{
  "id": "cus_01HCUSXYZ...",
  "email": "jane@example.com",
  "name": "Jane Doe",
  "phone": "+41 79 555 12 34",
  "locale": "de-CH",
  "external_id": "user_42",
  "billing_address": {
    "line1": "Bahnhofstrasse 1",
    "city": "Zürich",
    "postal_code": "8001",
    "country": "CH"
  },
  "delivery_address": null,
  "date_of_birth": null,
  "metadata": { "plan": "pro" },
  "created_at": "2026-05-20T12:00:00Z"
}
```

| Field              | Type   | Notes                                                           |
| ------------------ | ------ | --------------------------------------------------------------- |
| `id`               | string | Stable, prefixed with `cus_`.                                   |
| `email`            | string | **Unique per merchant**, case-insensitive.                      |
| `name`             | string | Free text.                                                      |
| `phone`            | string | Free text. International format recommended.                    |
| `locale`           | string | `xx-XX` (e.g. `de-CH`, `en-US`).                                |
| `external_id`      | string | Your own ID for this customer. Unique per merchant if provided. |
| `billing_address`  | object | Free-text address fields; `country` is ISO 3166-1 alpha-2.      |
| `delivery_address` | object | Same shape as `billing_address`.                                |
| `date_of_birth`    | string | ISO 8601 date (`1990-04-25`).                                   |
| `metadata`         | object | ≤ 20 keys, values ≤ 500 chars.                                  |
| `created_at`       | string | ISO 8601 UTC.                                                   |

***

## Create a customer

```
POST /api/v1/customers
```

### Required headers

```
Authorization: Bearer sk_test_...
Content-Type: application/json
Idempotency-Key: <recommended>
```

### Required body fields

| Field   | Type   |
| ------- | ------ |
| `email` | string |

That's it. Everything else is optional.

### Example — minimal

```bash
curl -X POST https://app.swisspay.ai/api/v1/customers \
  -H "Authorization: Bearer sk_test_..." \
  -H "Content-Type: application/json" \
  -d '{
    "email": "jane@example.com",
    "name": "Jane Doe"
  }'
```

### Example — full

```json
{
  "email": "jane@example.com",
  "name": "Jane Doe",
  "phone": "+41 79 555 12 34",
  "locale": "de-CH",
  "external_id": "user_42",
  "billing_address": {
    "line1": "Bahnhofstrasse 1",
    "city": "Zürich",
    "postal_code": "8001",
    "country": "CH"
  },
  "metadata": { "plan": "pro" }
}
```

### Example — with delivery address and date of birth

A mismatch between `billing_address` and `delivery_address` is a well-known fraud signal; passing both lets the risk engine reason about it. `date_of_birth` is required by some payment methods.

```json
{
  "email": "jane@example.com",
  "name": "Jane Doe",
  "billing_address": {
    "line1": "Bahnhofstrasse 1",
    "city": "Zürich",
    "postal_code": "8001",
    "country": "CH"
  },
  "delivery_address": {
    "line1": "Rue du Mont-Blanc 4",
    "city": "Genève",
    "postal_code": "1201",
    "country": "CH"
  },
  "date_of_birth": "1990-04-25"
}
```

Both fields are persisted, echoed back on read, and forwarded automatically whenever this customer is attached to a payment.

### Validation errors

| Error                            | Cause                                                                                          |
| -------------------------------- | ---------------------------------------------------------------------------------------------- |
| `422 customer_email_taken`       | Email already on file for this account.                                                        |
| `422 customer_external_id_taken` | `external_id` already on file for this account.                                                |
| `422 invalid_params: locale`     | `locale` not in `xx-XX` form.                                                                  |
| `422 invalid_params: country`    | `billing_address.country` or `delivery_address.country` isn't a valid ISO 3166-1 alpha-2 code. |

***

## Retrieve a customer

```
GET /api/v1/customers/{id}
```

```bash
curl https://app.swisspay.ai/api/v1/customers/cus_01HCUSXYZ \
  -H "Authorization: Bearer sk_test_..."
```

Unknown IDs return `404 Not Found`.

***

## List customers

```
GET /api/v1/customers?page=1&per_page=20
```

### Query parameters

| Param      | Default | Notes                                              |
| ---------- | ------- | -------------------------------------------------- |
| `page`     | `1`     |                                                    |
| `per_page` | `20`    | Max 100.                                           |
| `email`    | —       | Exact match, case-insensitive. URL-encode the `@`. |

### Example — filter by email

```bash
curl 'https://app.swisspay.ai/api/v1/customers?email=jane%40example.com' \
  -H "Authorization: Bearer sk_test_..."
```

### Response

```json
{
  "data": [ /* customer objects */ ],
  "page": 1,
  "per_page": 20,
  "total_count": 7,
  "has_more": false
}
```

***

## Attaching customers to payments

Two ways:

1. **Reference an existing customer** — pass `customer: "cus_01HCUSXYZ..."` on `POST /payments`.
2. **Create inline** — pass an inline `customer` object on `POST /payments`. We create the customer if it doesn't already exist (matched by `email`) and attach it.

Either way, the customer's `delivery_address` and `date_of_birth` (when present) are automatically forwarded to the upstream risk engine.
