# 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://staging.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://staging.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://staging.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.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://support.swisspay.ai/api-reference/customers.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
