# Customers

## Customer Object

Customers are represented as JSON objects with the following properties

<table data-full-width="true"><thead><tr><th width="200">Name</th><th width="104">Type</th><th>Description</th></tr></thead><tbody><tr><td>id</td><td>integer</td><td>The ID of the customer.</td></tr><tr><td>name</td><td>string</td><td>The name of the customer.</td></tr><tr><td>owner</td><td>string | null</td><td>Slack/MS Teams User ID of the owner for the customer. Can be null. If null, the system will use the owner of the collection that this customer belongs to.</td></tr><tr><td>domains</td><td>string array</td><td>List of domain names associated with this customer.</td></tr><tr><td>channel_ids</td><td>string array</td><td>List of Slack channel IDs or MS Teams channel IDs associated with this customer.</td></tr><tr><td>revisit</td><td>boolean</td><td>Flag indicating if this customer requires revisiting.</td></tr><tr><td>portal_config</td><td>object</td><td>Configuration object for customer portal settings. Details about the object can be found <a href="#portal-config-object">here</a>.</td></tr><tr><td>custom_field_values</td><td>object</td><td>An object containing custom field values. The object will have custom field IDs as keys and the values of the custom fields as values. Details about the object can be found <a href="#custom-field-values-object">here</a>.</td></tr><tr><td>is_portal_available_to_all_users</td><td>boolean</td><td>Whether portal access is available to all users of this customer.</td></tr><tr><td>portal_allowed_user_emails</td><td>string array</td><td>List of email addresses that are allowed to access the customer portal. It is recommended to use the <code>portal_users</code> field instead, which also includes role information. This field is maintained for backward compatibility and contains a list of all emails from <code>portal_users</code>. Emails added this way will be considered as <code>ADMIN</code> role.</td></tr><tr><td>portal_users</td><td>object array</td><td>List of users with their email addresses and roles that are allowed to access the customer portal. Details about the object can be found <a href="#portal-users-object">here</a>.</td></tr><tr><td>collection_id</td><td>integer</td><td>Optional. The ID of the collection this customer belongs to.</td></tr><tr><td>external_system</td><td>string</td><td>Optional. External CRM system identifier (e.g., <code>hubspot</code>, <code>salesforce</code>). Null if not linked to external system.</td></tr><tr><td>external_entity_id</td><td>string</td><td>Optional. External CRM entity identifier. Null if not linked to external system.</td></tr><tr><td>external_deal_id</td><td>string</td><td>Optional. External CRM deal identifier. Null if not linked to external deal.</td></tr><tr><td>version</td><td>integer</td><td>Version number of the customer object, increments with each update. Used for optimistic locking.</td></tr><tr><td>created_at</td><td>string</td><td>The creation timestamp of the customer in ISO 8601 format.</td></tr><tr><td>updated_at</td><td>string</td><td>The last update timestamp of the customer in ISO 8601 format.</td></tr></tbody></table>

## Portal Config Object

The portal\_config is represented as a JSON object with the following properties

<table data-full-width="true"><thead><tr><th width="145">Name</th><th width="104">Type</th><th>Description</th></tr></thead><tbody><tr><td>enabled</td><td>boolean</td><td>Whether portal access is enabled for this customer.</td></tr></tbody></table>

## Custom Field Values Object

The custom\_field\_values object contains custom field data for the customer. The object uses custom field IDs as keys and the corresponding field values as values.

**Note:** For `select` and `multi_select` type custom fields, the values are option IDs (strings), not the display text.

### Custom Field Value Format Guide

The table below outlines the expected value formats for different custom field types:

<table data-full-width="true"><thead><tr><th width="200">Custom Field Type</th><th width="250">Expected Value Format</th><th>Example Value</th></tr></thead><tbody><tr><td>select</td><td>String (option ID)</td><td><code>"1"</code></td></tr><tr><td>multi_select</td><td>Array of strings (option IDs)</td><td><code>["1", "2"]</code></td></tr><tr><td>text</td><td>String</td><td><code>"Sample text"</code></td></tr><tr><td>number</td><td>Number</td><td><code>500000</code></td></tr><tr><td>date</td><td>String (ISO 8601 date format)</td><td><code>"2024-10-30"</code></td></tr></tbody></table>

## Portal Users Object

The `portal_users` array contains JSON objects with the following properties

<table data-full-width="true"><thead><tr><th width="145">Name</th><th width="104">Type</th><th>Description</th></tr></thead><tbody><tr><td>email</td><td>string</td><td>The email address of the user.</td></tr><tr><td>role</td><td>enum</td><td>The role of the user (e.g., <code>ADMIN</code>, <code>USER</code>).</td></tr></tbody></table>

## Get All Customers

<mark style="color:blue;">`GET`</mark> `https://api.clearfeed.app/v1/rest/customers`

Get all customers in an account with pagination support

#### Query Parameters

<table data-full-width="true"><thead><tr><th width="145">Name</th><th width="104">Type</th><th>Description</th></tr></thead><tbody><tr><td>before</td><td>string</td><td>Optional. Fetch records created before this timestamp (ISO 8601 format).</td></tr><tr><td>after</td><td>string</td><td>Optional. Fetch records created after this timestamp (ISO 8601 format).</td></tr><tr><td>sort_order</td><td>enum</td><td>Optional. Sort order for results. Can be <code>asc</code> or <code>desc</code>. Defaults to <code>desc</code>.</td></tr><tr><td>limit</td><td>integer</td><td>Optional. Number of results to return (1-100). Defaults to 50.</td></tr><tr><td>next_cursor</td><td>string</td><td>Optional. Base64-encoded cursor for pagination.</td></tr></tbody></table>

{% tabs %}
{% tab title="200 " %}

```json
{
  "customers": [
    {
      "id": 123,
      "name": "Acme Corp",
      "owner": "U03AB1CD2EF",
      "domains": ["acme.com"],
      "channel_ids": ["C01ABC2DEF3", "C04GHI5JKL6"],
      "revisit": false,
      "portal_config": { "enabled": true },
      "custom_field_values": { "3011": "Enterprise", "3012": 500000 },
      "is_portal_available_to_all_users": true,
      "portal_allowed_user_emails": ["admin@acme.com"],
      "portal_users": [
        {
          "email": "admin@acme.com",
          "role": "ADMIN"
        }
      ],
      "collection_id": 21,
      "external_system": null,
      "external_entity_id": null,
      "external_deal_id": null,
      "version": 0,
      "created_at": "2024-10-30T18:18:10.839Z",
      "updated_at": "2024-10-30T18:18:10.839Z"
    }
  ],
  "response_metadata": {
    "next_cursor": "MTI0",
    "count": 1
  }
}
```

{% endtab %}

{% tab title="403: Forbidden Permission denied" %}

{% endtab %}
{% endtabs %}

## Search Customers

<mark style="color:green;">`POST`</mark> `https://api.clearfeed.app/v1/rest/customers/search`

Search customers with advanced filtering capabilities. Multiple filters are applied as AND conditions.

#### Request Body

<table data-full-width="true"><thead><tr><th width="145">Name</th><th width="104">Type</th><th>Description</th></tr></thead><tbody><tr><td>filters</td><td>array</td><td>Optional. Array of filter objects. See <a href="#filter-objects">Filter Objects</a> for details.</td></tr><tr><td>before</td><td>string</td><td>Optional. Fetch records created before this timestamp (ISO 8601 format).</td></tr><tr><td>after</td><td>string</td><td>Optional. Fetch records created after this timestamp (ISO 8601 format).</td></tr><tr><td>sort_order</td><td>enum</td><td>Optional. Sort order for results. Can be <code>asc</code> or <code>desc</code>. Defaults to <code>desc</code>.</td></tr><tr><td>limit</td><td>integer</td><td>Optional. Number of results to return (1-100). Defaults to 50.</td></tr><tr><td>next_cursor</td><td>string</td><td>Optional. Base64-encoded cursor for pagination.</td></tr></tbody></table>

### Filter Objects

#### Domain Filter

Filter customers by domain names with array comparison operators.

<table data-full-width="true"><thead><tr><th width="145">Name</th><th width="104">Type</th><th>Description</th></tr></thead><tbody><tr><td>field</td><td>literal</td><td>Must be exactly: <code>'domains'</code></td></tr><tr><td>operator</td><td>enum</td><td>Array comparison operator. Options:<br>- <code>overlaps</code>: Matches if any input domain exists in customer's domains<br>- <code>contains_all</code>: Matches if customer's domains contain all input domains</td></tr><tr><td>values</td><td>string array</td><td>Array of domain names to filter by. Must be valid FQDNs (Fully Qualified Domain Names).</td></tr></tbody></table>

#### External Entity Filter

Filter customers by their external CRM system identifiers.

<table data-full-width="true"><thead><tr><th width="145">Name</th><th width="104">Type</th><th>Description</th></tr></thead><tbody><tr><td>field</td><td>literal</td><td>Must be exactly: <code>'external_entity'</code></td></tr><tr><td>entity_type</td><td>enum</td><td>External CRM system. Can be <code>hubspot</code> or <code>salesforce</code>.</td></tr><tr><td>entity_id</td><td>string</td><td>The external entity identifier from the CRM system (max 255 characters).</td></tr></tbody></table>

Example request body with domain filter:

```json
{
  "filters": [
    {
      "field": "domains",
      "operator": "overlaps",
      "values": ["acme.com", "acme.io"]
    }
  ],
  "sort_order": "desc",
  "limit": 50
}
```

Example request body with external entity filter:

```json
{
  "filters": [
    {
      "field": "external_entity",
      "entity_type": "hubspot",
      "entity_id": "12345678"
    }
  ],
  "limit": 50
}
```

Example request body with multiple filters (AND condition):

```json
{
  "filters": [
    {
      "field": "domains",
      "operator": "overlaps",
      "values": ["acme.com"]
    },
    {
      "field": "external_entity",
      "entity_type": "hubspot",
      "entity_id": "12345678"
    }
  ],
  "before": "2025-11-11T10:00:00Z",
  "after": "2025-11-01T00:00:00Z",
  "sort_order": "desc",
  "limit": 50
}
```

{% tabs %}
{% tab title="200: Success" %}

```json
{
  "customers": [
    {
      "id": 123,
      "name": "Acme Corp",
      "owner": "U03AB1CD2EF",
      "domains": ["acme.com"],
      "channel_ids": ["C01ABC2DEF3", "C04GHI5JKL6"],
      "revisit": false,
      "portal_config": { "enabled": true },
      "custom_field_values": { "3011": "Enterprise", "3012": 500000 },
      "is_portal_available_to_all_users": true,
      "portal_allowed_user_emails": ["admin@acme.com"],
      "portal_users": [
        {
          "email": "admin@acme.com",
          "role": "ADMIN"
        }
      ],
      "collection_id": 21,
      "external_system": null,
      "external_entity_id": null,
      "external_deal_id": null,
      "version": 0,
      "created_at": "2024-10-30T18:18:10.839Z",
      "updated_at": "2024-10-30T18:18:10.839Z"
    }
  ],
  "response_metadata": {
    "next_cursor": "MTI0",
    "count": 1
  }
}
```

{% endtab %}

{% tab title="400: Bad Request Invalid filter parameters" %}

{% endtab %}

{% tab title="403: Forbidden Permission denied" %}

{% endtab %}
{% endtabs %}

## Create Customer

<mark style="color:green;">`POST`</mark> `https://api.clearfeed.app/v1/rest/customers`

Create a new customer in your account.

#### Request Body

<table data-full-width="true"><thead><tr><th width="200">Name</th><th width="104">Type</th><th>Description</th></tr></thead><tbody><tr><td>name*</td><td>string</td><td>Name of the customer.</td></tr><tr><td>owner</td><td>string | null</td><td>Optional. Slack/MS Teams User ID of the owner for the customer. Can be null. If null or not provided, the system will use the owner of the collection that this customer belongs to.</td></tr><tr><td>domains</td><td>string array</td><td>Optional. List of domain names associated with this customer.</td></tr><tr><td>channel_ids</td><td>string array</td><td>Optional. List of Slack channel IDs or MS Teams channel IDs to associate with this customer.</td></tr><tr><td>portal_config</td><td>object</td><td>Optional. Portal configuration object. Details about the object can be found <a href="#portal-config-object">here</a>.</td></tr><tr><td>custom_field_values</td><td>object</td><td>Optional. An object containing custom field values. Details about the object can be found <a href="#custom-field-values-object">here</a>.</td></tr><tr><td>is_portal_available_to_all_users</td><td>boolean</td><td>Optional. Whether portal access is available to all users of this customer.</td></tr><tr><td>portal_allowed_user_emails</td><td>string array</td><td>Optional. List of email addresses that are allowed to access the customer portal. It is recommended to use the <code>portal_users</code> field instead, which also includes role information. This field is maintained for backward compatibility and contains a list of all emails from <code>portal_users</code>. Emails added this way will be considered as <code>ADMIN</code> role.</td></tr><tr><td>portal_users</td><td>object array</td><td>Optional. List of users with their email addresses and roles allowed to access the customer portal. If both this and <code>portal_allowed_user_emails</code> are provided, priority is given to <code>portal_users</code>. Details about the object can be found <a href="#portal-users-object">here</a>.</td></tr><tr><td>collection_id</td><td>integer</td><td>Optional. The ID of the collection to assign this customer to.</td></tr></tbody></table>

Example request body:

```json
{
  "name": "Acme Corp",
  "owner": "U03AB1CD2EF",
  "domains": ["acme.com"],
  "channel_ids": ["C01ABC2DEF3", "C04GHI5JKL6"],
  "portal_config": {
    "enabled": true
  },
  "custom_field_values": {
    "3011": "Enterprise",
    "3012": 500000
  },
  "is_portal_available_to_all_users": true,
  "portal_users": [
    {
      "email": "admin@acme.com",
      "role": "ADMIN"
    }
  ],
  "collection_id": 21
}
```

{% tabs %}
{% tab title="201: Created" %}

```json
{
  "customer": {
    "id": 123,
    "name": "Acme Corp",
    "owner": "U03AB1CD2EF",
    "domains": ["acme.com"],
    "channel_ids": ["C01ABC2DEF3", "C04GHI5JKL6"],
    "revisit": false,
    "portal_config": { "enabled": true },
    "custom_field_values": { "3011": "Enterprise", "3012": 500000 },
    "is_portal_available_to_all_users": true,
    "portal_allowed_user_emails": ["admin@acme.com"],
    "portal_users": [
    {
      "email": "admin@acme.com",
      "role": "ADMIN"
    }
  ],
    "collection_id": 21,
    "external_system": null,
    "external_entity_id": null,
    "external_deal_id": null,
    "version": 0,
    "created_at": "2024-10-30T18:18:10.839Z",
    "updated_at": "2024-10-30T18:18:10.839Z"
  }
}
```

{% endtab %}

{% tab title="400: Bad Request Invalid request body" %}

{% endtab %}

{% tab title="403: Forbidden Permission denied" %}

{% endtab %}
{% endtabs %}

## Get Customer by ID

<mark style="color:blue;">`GET`</mark> `https://api.clearfeed.app/v1/rest/customers/:id`

Retrieve details of a specific customer by ID.

#### Path Parameters

<table data-full-width="true"><thead><tr><th width="100">Name</th><th width="100">Type</th><th>Description</th></tr></thead><tbody><tr><td>id*</td><td>integer</td><td>The ID of the customer to retrieve</td></tr></tbody></table>

{% tabs %}
{% tab title="200: Success" %}

```json
{
  "customer": {
    "id": 123,
    "name": "Acme Corp",
    "owner": "U03AB1CD2EF",
    "domains": ["acme.com"],
    "channel_ids": ["C01ABC2DEF3", "C04GHI5JKL6"],
    "revisit": false,
    "portal_config": { "enabled": true },
    "custom_field_values": { "3011": "Enterprise", "3012": 500000 },
    "is_portal_available_to_all_users": true,
    "portal_allowed_user_emails": ["admin@acme.com"],
    "portal_users": [
      {
        "email": "admin@acme.com",
        "role": "ADMIN"
      }
    ],
    "collection_id": 21,
    "external_system": null,
    "external_entity_id": null,
    "external_deal_id": null,
    "version": 0,
    "created_at": "2024-10-30T18:18:10.839Z",
    "updated_at": "2024-10-30T18:18:10.839Z"
  }
}
```

{% endtab %}

{% tab title="403: Forbidden Permission denied" %}

{% endtab %}

{% tab title="404: Not Found Customer not found" %}

{% endtab %}
{% endtabs %}

## Update Customer

<mark style="color:yellow;">`PATCH`</mark> `https://api.clearfeed.app/v1/rest/customers/:id`

Update an existing customer. All fields are optional - only provided fields will be updated.

#### Path Parameters

<table data-full-width="true"><thead><tr><th width="100">Name</th><th width="100">Type</th><th>Description</th></tr></thead><tbody><tr><td>id*</td><td>integer</td><td>The ID of the customer to update</td></tr></tbody></table>

#### Request Body

<table data-full-width="true"><thead><tr><th width="200">Name</th><th width="104">Type</th><th>Description</th></tr></thead><tbody><tr><td>version*</td><td>integer</td><td>Current version number of the customer. Used for optimistic locking to prevent concurrent updates.</td></tr><tr><td>name</td><td>string</td><td>Optional. Name of the customer.</td></tr><tr><td>owner</td><td>string | null</td><td>Optional. Slack/MS Teams User ID of the owner for the customer. Can be set to null. If null, the system will use the owner of the collection that this customer belongs to.</td></tr><tr><td>domains</td><td>string array</td><td>Optional. List of domain names associated with this customer.</td></tr><tr><td>channel_ids</td><td>string array</td><td>Optional. List of Slack channel IDs or MS Teams channel IDs.</td></tr><tr><td>portal_config</td><td>object</td><td>Optional. Portal configuration object. Details about the object can be found <a href="#portal-config-object">here</a>.</td></tr><tr><td>custom_field_values</td><td>object</td><td>Optional. An object containing custom field values. Set a field to <code>null</code> to clear its value. Details about the object can be found <a href="#custom-field-values-object">here</a>.</td></tr><tr><td>is_portal_available_to_all_users</td><td>boolean</td><td>Optional. Whether portal access is available to all users.</td></tr><tr><td>portal_allowed_user_emails</td><td>string array</td><td>Optional. List of email addresses that are allowed to access the customer portal. It is recommended to use the <code>portal_users</code> field instead, which also includes role information. This field is maintained for backward compatibility and contains a list of all emails from <code>portal_users</code>. Emails added this way will be considered as <code>ADMIN</code> role.</td></tr><tr><td>portal_users</td><td>object array</td><td>Optional. List of users with their email addresses and roles allowed to access the customer portal. If both this and <code>portal_allowed_user_emails</code> are provided, priority is given to <code>portal_users</code>. Details about the object can be found <a href="#portal-users-object">here</a>.</td></tr><tr><td>collection_id</td><td>integer</td><td>Optional. The ID of the collection to assign this customer to.</td></tr></tbody></table>

> **Important:** The `version` field is required to prevent concurrent updates. If the version doesn't match the current customer version, the update will fail with a 409 Conflict error. Retrieve the latest customer data and retry with the updated version number.

Example request body:

```json
{
  "version": 0,
  "name": "Acme International",
  "domains": ["acme.com", "acme.io"],
  "owner": "U07XY8ZA9BC",
  "custom_field_values": {
    "3012": 1200000,
    "3013": null
  },
  "is_portal_available_to_all_users": false,
  "portal_users": [
    {
      "email": "support@acme.com",
      "role": "ADMIN"
    }
  ]
}
```

{% tabs %}
{% tab title="200: Success" %}

```json
{
  "customer": {
    "id": 123,
    "name": "Acme International",
    "owner": "U07XY8ZA9BC",
    "domains": ["acme.com", "acme.io"],
    "channel_ids": ["C01ABC2DEF3", "C04GHI5JKL6"],
    "revisit": false,
    "portal_config": { "enabled": true },
    "custom_field_values": { "3011": "Enterprise", "3012": 1200000 },
    "is_portal_available_to_all_users": false,
    "portal_allowed_user_emails": ["support@acme.com"],
    "portal_users": [
      {
        "email": "support@acme.com",
        "role": "ADMIN"
      }
    ],
    "collection_id": 21,
    "external_system": null,
    "external_entity_id": null,
    "external_deal_id": null,
    "version": 1,
    "created_at": "2024-10-30T18:18:10.839Z",
    "updated_at": "2024-10-30T18:25:15.122Z"
  }
}
```

{% endtab %}

{% tab title="400: Bad Request Invalid request body" %}

{% endtab %}

{% tab title="403: Forbidden Permission denied" %}

{% endtab %}

{% tab title="404: Not Found Customer not found" %}

{% endtab %}

{% tab title="409: Conflict Outdated version" %}

```json
{
  "message": "You are trying to update an outdated version of customer. Please try again."
}
```

{% endtab %}
{% endtabs %}
