---
sidebar_position: 3
title: Contacts
description: Manage contacts scoped to your ownership — create, update, search, look up by phone number, and delete contacts via the Firetell Agent API.
---

# Contacts

Manage contacts within your workspace. Contacts store customer or lead information including phone numbers, emails, and custom metadata. They can be organized into [Address Books](/docs/rest-api/agent-api/address-books).

:::info
**Data Scoping**
Agents can only see contacts within [Address Books](/docs/rest-api/agent-api/address-books) they have access to (books owned by them `owner_type: agent`, books owned by teams they belong to `owner_type: team`, or shared books `owner_type: everyone`).
:::

## Endpoints

| Method   | Endpoint                            | Description                     |
| -------- | ----------------------------------- | ------------------------------- |
| `GET`    | `/call-center/contacts`             | List all contacts               |
| `GET`    | `/call-center/contacts/lookup`      | Look up contact by phone number |
| `GET`    | `/call-center/contacts/:id`         | Get contact details             |
| `POST`   | `/call-center/contacts`             | Create a new contact            |
| `POST`   | `/call-center/contacts/assign-list` | Batch assign contacts to a list |
| `PUT`    | `/call-center/contacts/:id`         | Update a contact                |
| `DELETE` | `/call-center/contacts/:id`         | Delete a contact                |

## Authentication

All endpoints require `Bearer` JWT with `agent-api` audience.

## Contact Object

| Field               | Type     | Description                                                             |
| ------------------- | -------- | ----------------------------------------------------------------------- |
| `id`                | string   | Unique contact ID (prefixed with `ct_`)                                 |
| `workspace_id`      | string   | Workspace identifier                                                    |
| `address_book_id`   | string   | ID of the address book this contact belongs to (defaults to Default book if omitted) |
| `first_name`        | string   | Contact first name                                                       |
| `last_name`         | string   | Contact last name                                                        |
| `company`           | string   | Company name                                                             |
| `title`             | string   | Job title                                                                |
| `emails`            | object[] | List of email addresses (see [Email Object](#email-object))             |
| `phone_numbers`     | object[] | List of phone numbers (see [Phone Number Object](#phone-number-object)) |
| `tags`              | string[] | Tags for categorization                                                 |
| `notes`             | string   | Free-text notes (max 1000 chars)                                        |
| `timezone`          | string   | Contact timezone (e.g., `"Asia/Ho_Chi_Minh"`)                           |
| `language`          | string   | Preferred language (e.g., `"vi"`, `"en"`)                               |
| `country_code`      | string   | ISO 3166-1 alpha-2 country code (e.g., `"VN"`)                          |
| `assigned_agent_id` | string   | Optional ID of the assigned agent responsible for this contact         |
| `source`            | string   | Origin of this contact (e.g., `"manual"`, `"import"`, `"call"`)         |
| `custom_fields`     | object   | Key-value pairs for custom data                                         |
| `created_at`        | string   | ISO 8601 creation timestamp                                             |
| `updated_at`        | string   | ISO 8601 last update timestamp                                          |

### Phone Number Object

| Field          | Type    | Description                                       |
| -------------- | ------- | ------------------------------------------------- |
| `phone_number` | string  | Phone number string (e.g., `"+84901234567"`)      |
| `type`         | string  | Type label: `mobile`, `work`, `home`, `fax`, etc. |
| `is_primary`   | boolean | Whether this is the primary phone number          |

### Email Object

| Field        | Type    | Description                          |
| ------------ | ------- | ------------------------------------ |
| `email`      | string  | Email address                        |
| `type`       | string  | Type label: `work`, `personal`, etc. |
| `is_primary` | boolean | Whether this is the primary email    |

---

## List Contacts

```
GET /call-center/contacts
```

Retrieve a paginated list of all contacts in the workspace.

### Query Parameters

| Parameter    | Type   | Default | Description                                                 |
| ------------ | ------ | ------- | ----------------------------------------------------------- |
| `page`       | number | `1`     | Page number (min: 1)                                        |
| `limit`      | number | `20`    | Items per page (min: 1, max: 100)                           |
| `search`     | string | —       | Search by name, phone number, or email (text search)        |
| `sort_field` | string | —       | Sort by: `created_at`, `first_name`, `last_name`, `company` |
| `sort_order` | string | `desc`  | Sort order: `asc` or `desc`                                 |

### Request

```bash
curl -X GET "https://{workspace_id}.firetell.app/api/v1/call-center/contacts?page=1&limit=10&search=john" \
  -H "Authorization: Bearer YOUR_AGENT_JWT"
```

### Response `200 OK`

```json
{
  "data": [
    {
      "id": "ct_a1b2c3d4e5f6g7h8i9j0k1",
      "workspace_id": "my_workspace",
      "address_book_id": "ab_x1y2z3w4v5u6t7s8",
      "first_name": "John",
      "last_name": "Doe",
      "company": "Acme Corp",
      "title": "CTO",
      "emails": [
        { "email": "john@acme.com", "type": "work", "is_primary": true }
      ],
      "phone_numbers": [
        { "phone_number": "+84901234567", "type": "mobile", "is_primary": true }
      ],
      "tags": ["vip", "enterprise"],
      "notes": "Key decision maker",
      "timezone": "Asia/Ho_Chi_Minh",
      "language": "en",
      "country_code": "VN",
      "owner_id": "ag_abc123",
      "owner_type": "agent",
      "source": "manual",
      "custom_fields": { "deal_size": "50000" },
      "created_at": "2026-01-15T08:30:00.000Z",
      "updated_at": "2026-07-13T09:00:00.000Z"
    }
  ],
  "meta": {
    "total": 1,
    "page": 1,
    "limit": 10,
    "total_pages": 1
  }
}
```

---

## Lookup Contact by Phone Number

```
GET /call-center/contacts/lookup
```

Find a contact by their phone number. The phone number is automatically normalized for matching, so formats like `+84901234567`, `0901234567`, or `84901234567` all match the same contact.

### Query Parameters

| Parameter | Type   | Required | Description             |
| --------- | ------ | -------- | ----------------------- |
| `number`  | string | ✅       | Phone number to look up |

### Request

```bash
curl -X GET "https://{workspace_id}.firetell.app/api/v1/call-center/contacts/lookup?number=84901234567" \
  -H "Authorization: Bearer YOUR_AGENT_JWT"
```

### Response `200 OK`

Returns the matching contact object, or `null` if no contact is found.

```json
{
  "id": "ct_a1b2c3d4e5f6g7h8i9j0k1",
  "first_name": "John",
  "last_name": "Doe",
  "company": "Acme Corp",
  "phone_numbers": [
    { "phone_number": "+84901234567", "type": "mobile", "is_primary": true }
  ]
}
```

:::tip
This endpoint is commonly used during incoming calls to display caller information. The call flow engine also uses it internally for the **Contact Lookup** node.
:::

---

## Get Contact Details

```
GET /call-center/contacts/:id
```

Retrieve detailed information about a specific contact.

### Path Parameters

| Parameter | Type   | Description                       |
| --------- | ------ | --------------------------------- |
| `id`      | string | Contact ID (e.g., `ct_a1b2c3...`) |

### Request

```bash
curl -X GET "https://{workspace_id}.firetell.app/api/v1/call-center/contacts/ct_a1b2c3d4e5f6g7h8i9j0k1" \
  -H "Authorization: Bearer YOUR_AGENT_JWT"
```

### Response `200 OK`

Returns the full contact object.

### Error Responses

| Status | Description       |
| ------ | ----------------- |
| `404`  | Contact not found |

---

## Create a Contact

```
POST /call-center/contacts
```

Create a new contact in the workspace. All fields except the basic identity fields are optional.

### Request Body

| Field             | Type           | Required | Description                                                     |
| ----------------- | -------------- | -------- | --------------------------------------------------------------- |
| `first_name`      | string         |          | First name (max 100 chars)                                      |
| `last_name`       | string         |          | Last name (max 100 chars)                                       |
| `company`         | string         |          | Company name (max 100 chars)                                    |
| `title`           | string         |          | Job title (max 100 chars)                                       |
| `emails`          | object[]       |          | Email addresses (see [Email Object](#email-object))             |
| `phone_numbers`   | object[]       |          | Phone numbers (see [Phone Number Object](#phone-number-object)) |
| `tags`            | string[]       |          | Tags for categorization                                         |
| `notes`           | string         |          | Free-text notes (max 1000 chars)                                |
| `timezone`        | string         |          | Timezone identifier (max 50 chars)                              |
| `language`        | string         |          | Language code (max 10 chars)                                    |
| `country_code`    | string         |          | ISO country code (max 10 chars)                                 |
| `address_book_id`   | string |          | Assign to an address book (defaults to Default book if omitted) |
| `assigned_agent_id` | string |          | Optional assigned agent responsible for this contact            |
| `source`            | string |          | Origin label (max 50 chars)                                     |
| `custom_fields`     | object |          | Key-value pairs for custom data                                 |

### Request

```bash
curl -X POST "https://{workspace_id}.firetell.app/api/v1/call-center/contacts" \
  -H "Authorization: Bearer YOUR_AGENT_JWT" \
  -H "Content-Type: application/json" \
  -d '{
    "first_name": "Jane",
    "last_name": "Smith",
    "company": "TechStart Inc.",
    "title": "Product Manager",
    "emails": [
      { "email": "jane@techstart.io", "type": "work", "is_primary": true }
    ],
    "phone_numbers": [
      { "phone_number": "+84912345678", "type": "mobile", "is_primary": true },
      { "phone_number": "+84281234567", "type": "work" }
    ],
    "tags": ["lead", "tech"],
    "notes": "Met at TechConf 2026",
    "timezone": "Asia/Ho_Chi_Minh",
    "language": "vi",
    "country_code": "VN",
    "address_book_id": "ab_x1y2z3w4v5u6t7s8",
    "owner_type": "agent",
    "source": "manual"
  }'
```

### Response `201 Created`

Returns the created contact object.

```json
{
  "id": "ct_n3w1d2e3f4g5h6i7j8k9l0",
  "workspace_id": "my_workspace",
  "first_name": "Jane",
  "last_name": "Smith",
  "company": "TechStart Inc.",
  "title": "Product Manager",
  "emails": [
    { "email": "jane@techstart.io", "type": "work", "is_primary": true }
  ],
  "phone_numbers": [
    {
      "phone_number": "+84912345678",
      "type": "mobile",
      "is_primary": true,
      "normalized_number": "84912345678"
    },
    {
      "phone_number": "+84281234567",
      "type": "work",
      "normalized_number": "84281234567"
    }
  ],
  "tags": ["lead", "tech"],
  "notes": "Met at TechConf 2026",
  "address_book_id": "ab_x1y2z3w4v5u6t7s8",
  "owner_type": "agent",
  "source": "manual",
  "created_at": "2026-07-21T08:00:00.000Z",
  "updated_at": "2026-07-21T08:00:00.000Z"
}
```

### Error Responses

| Status | Description                                     |
| ------ | ----------------------------------------------- |
| `400`  | Validation error or address book does not exist |

:::info
Phone numbers are automatically normalized for consistent lookup. The `normalized_number` field is generated server-side and used for the [Lookup](#lookup-contact-by-phone-number) endpoint.
:::

---

## Update a Contact

```
PUT /call-center/contacts/:id
```

Update an existing contact. All fields are optional — only include the fields you want to change.

### Path Parameters

| Parameter | Type   | Description |
| --------- | ------ | ----------- |
| `id`      | string | Contact ID  |

### Request Body

Same fields as [Create a Contact](#create-a-contact). All fields are optional.

### Request

```bash
curl -X PUT "https://{workspace_id}.firetell.app/api/v1/call-center/contacts/ct_a1b2c3d4e5f6g7h8i9j0k1" \
  -H "Authorization: Bearer YOUR_AGENT_JWT" \
  -H "Content-Type: application/json" \
  -d '{
    "company": "TechStart Global",
    "title": "VP of Product",
    "tags": ["vip", "enterprise", "tech"]
  }'
```

### Response `200 OK`

Returns the updated contact object.

### Error Responses

| Status | Description                                     |
| ------ | ----------------------------------------------- |
| `400`  | Validation error or address book does not exist |
| `404`  | Contact not found                               |

---

## Delete a Contact

```
DELETE /call-center/contacts/:id
```

Permanently delete a contact from the workspace. This action cannot be undone.

### Path Parameters

| Parameter | Type   | Description |
| --------- | ------ | ----------- |
| `id`      | string | Contact ID  |

### Request

```bash
curl -X DELETE "https://{workspace_id}.firetell.app/api/v1/call-center/contacts/ct_a1b2c3d4e5f6g7h8i9j0k1" \
  -H "Authorization: Bearer YOUR_AGENT_JWT"
```

### Response `200 OK`

Returns the deleted contact object.

### Error Responses

| Status | Description       |
| ------ | ----------------- |
| `404`  | Contact not found |

:::caution
Deleting a contact is **irreversible**. Consider updating the contact's `tags` or moving it to a different address book instead if you need to archive it.
:::

---

## Assign Contacts to an Address Book

```
POST /call-center/contacts/assign-list
```

Batch assign multiple contacts to an address book (or unassign by passing `null`). You can assign up to **50 contacts** per request.

### Request Body

| Field             | Type           | Required | Description                                                              |
| ----------------- | -------------- | -------- | ------------------------------------------------------------------------ |
| `address_book_id` | string \| null | ✅       | Target address book ID. Pass `null` to unassign contacts from their book |
| `contact_ids`     | string[]       | ✅       | Array of contact IDs to assign (min: 1, max: 50)                         |

### Request

```bash
curl -X POST "https://{workspace_id}.firetell.app/api/v1/call-center/contacts/assign-list" \
  -H "Authorization: Bearer YOUR_AGENT_JWT" \
  -H "Content-Type: application/json" \
  -d '{
    "address_book_id": "ab_x1y2z3w4v5u6t7s8",
    "contact_ids": [
      "ct_a1b2c3d4e5f6g7h8i9j0k1",
      "ct_n3w1d2e3f4g5h6i7j8k9l0",
      "ct_z9y8x7w6v5u4t3s2r1q0p9"
    ]
  }'
```

### Response `200 OK`

```json
{
  "matched": 3,
  "modified": 3
}
```

| Field      | Type   | Description                                           |
| ---------- | ------ | ----------------------------------------------------- |
| `matched`  | number | Number of contacts found that you have access to      |
| `modified` | number | Number of contacts actually updated (excludes no-ops) |

:::tip
If `matched` is less than the number of `contact_ids` you sent, it means some contacts don't exist or you don't have access to them.
:::

### Unassign Contacts

To remove contacts from their current address book, pass `null` as the `address_book_id`:

```bash
curl -X POST "https://{workspace_id}.firetell.app/api/v1/call-center/contacts/assign-list" \
  -H "Authorization: Bearer YOUR_AGENT_JWT" \
  -H "Content-Type: application/json" \
  -d '{
    "address_book_id": null,
    "contact_ids": ["ct_a1b2c3d4e5f6g7h8i9j0k1"]
  }'
```

### Error Responses

| Status | Description                                |
| ------ | ------------------------------------------ |
| `400`  | Validation error or address book not found |
