# Customers

> Manage your customer (contact) records.

Source: https://tickos.dev/docs/customers

The Customer object represents a person you support -- the requester of tickets and the recipient of emails and campaigns. Customers can be organized into contact groups.

## POST /v1/customers -- Create or update a customer

Permission: write. If a customer with the same email already exists, the existing record is updated with the name, phone and metadata you provide instead of creating a duplicate (returns 200 instead of 201). When updating, metadata replaces the stored object.

| Field | Type | Required | Description |
|---|---|---|---|
| email | string | Yes | Customer email address. |
| name | string | No | Display name. Defaults to the local part of the email on creation. |
| phone | string | No | Phone number. |
| metadata | object | No | Arbitrary JSON metadata. Default: {}. |
| group | string | No | Name of an active contact group (case-insensitive match). Adds the customer to this group. |

```bash
curl https://api.tickos.dev/v1/customers \
  -H 'Authorization: Bearer sk_your_api_key' \
  -H 'Content-Type: application/json' \
  -d '{
    "email": "jane@example.com",
    "name": "Jane Doe",
    "phone": "+1234567890",
    "metadata": { "company": "Acme Inc" },
    "group": "VIP Customers"
  }'
```

Returns the customer object plus group: { id, name } when the customer was added to (or already belonged to) the group, or null when no group was given. If the group is not found among your active groups, the customer is still created or updated and the response includes group: null and a warning field (for example: Group "VIP" not found. Customer was created but not added to any group.)

## GET /v1/customers -- List customers

Permission: read. Ordered by created_at, newest first. Query params: email (partial, case-insensitive match), limit (default 50, max 100) and offset. Returns { data: [...], pagination: { limit, offset, total } }.

## GET /v1/customers/{id} -- Get a customer

Permission: read. Returns the customer record with its tickets embedded. Each ticket includes id, client_id, subject, status, priority and created_at.

| Query param | Description |
|---|---|
| include | Comma-separated extra data. surveys: CSAT surveys of the customer (newest first). emails: the last 50 emails linked to the customer (id, direction, from_address, to_address, subject, status, related_type, related_id, created_at). Default: surveys. Passing include replaces the default, so use include=surveys,emails to get both. |

```bash
curl 'https://api.tickos.dev/v1/customers/cst-xxxxxxxx?include=surveys,emails' \
  -H 'Authorization: Bearer sk_your_api_key'
```

Returns 404 if the customer does not exist in your account.

## PATCH /v1/customers/{id} -- Update a customer

Permission: write. Accepts name, email, phone, metadata and group. Only provided fields are updated (metadata replaces the stored object). Sending no recognized field returns 400. Returns the customer plus group: { id, name } | null.

> **group on PATCH:** On PATCH, group must match the group name exactly (case-sensitive). If no group matches, the request still succeeds and the customer is not added to any group: the response has group: null and no warning. PATCH only adds the customer to a group; it never removes existing memberships.

## DELETE /v1/customers/{id} -- Delete a customer

Permission: admin. Permanently deletes the customer record. Returns { deleted: true, id }.

## Implicit creation

You rarely need to create customers upfront: creating a ticket with customer_email creates the customer automatically if it does not exist yet. Sending an email with POST /v1/emails also links (or creates) a customer for the first recipient.

## Blocking

Blocked customers (is_blocked: true) cannot open new tickets: POST /v1/tickets returns HTTP 403 when the customer_id or customer_email belongs to a blocked customer. Blocked customers are also excluded from campaigns. Blocking and unblocking is done from the dashboard; the API does not change the blocked state.
