# My Customers

In the Frontline mobile application, you can access a list of Customers and get their Customer Details. In order to populate the Customer Details and Customers List screens with data, the Frontline application needs information about your customers.

## Configuring the CRM Callback URL

To grab the data for the Customers List and Customer Details screens, the app will make an API call to the configured **CRM Callback URL** to fetch customer data for each screen. Based on the `Location` parameter, your server can tell which information was requested.

![Twilio Frontline diagram shows POST crm\_callback\_url and Customers data exchange with a customer database.](https://docs-resources.prod.twilio.com/b3829e460643731e70e343ff34c7b62fe8e8ac09dfcf7156871dd1a147957144.jpg)

To configure the CRM Callback URL, [open the Frontline console](https://www.twilio.com/console/frontline) and set the CRM Callback URL configuration option to a URL that will return customer data in JSON format:

![Configure callbacks page with CRM, Outgoing Conversations, and Templates callback URLs and options to reset or save settings.](https://docs-resources.prod.twilio.com/ea2d0d4536844c672d5d7c69fce17c39f84af3de9077ff59732503668dea4645.png)

For an example of a Customer object, check out the [Node.js Quickstart section on populating the My Customers list](/docs/frontline/nodejs-demo-quickstart#populate-the-my-customers-list).

## Customer ID and Participant properties

[Customer](/docs/frontline/data-transfer-objects#customer) objects returned from the CRM callback URL contain the property `customer_id`. This ID is an important part of the Frontline application as some features, such as Customer Details, rely on it. It's also a way to tie together the Conversations API and CRM data under the hood. A Customer ID is not restricted to any particular format, the only requirement is that it's unique.\
An additional property of the Customer object is the [Participant](/docs/frontline/data-transfer-objects#participant). The Participant resource allows the user to navigate from the conversation screen to the Customer Details screen, which shows individual information for that particular Customer.

> \[!NOTE]
>
> Each Customer Conversation Participant needs to have a configured `customer_id` attribute set on a participant each time a new conversation with a customer is created.

## Responding to the CRM Callback

When the Frontline application makes a `POST` HTTP request to your server, it includes information about the action that triggered the callback to your Frontline Integration Service. Each action has its own `Location` type. The `Location` will be sent with the rest of the parameters in the request body in `application/x-www-urlencoded` format.

In addition to the location-specific parameters, each request also contains the following parameters and information:

| **Parameter name** | **Type** | **Description**                                                                                                       |
| ------------------ | -------- | --------------------------------------------------------------------------------------------------------------------- |
| Location           | string   | A single callback URL might be used for different purposes. Use this parameter to determine how to process a request. |
| Worker             | string   | The app user identity                                                                                                 |

In what follows, we'll describe two possible actions: [GetCustomerDetailsByCustomerId](#getcustomerdetailsbycustomerid) and [GetCustomersList](#getcustomerslist).

> \[!NOTE]
>
> Frontline will send a request with **`Content-Type`** header of `application/x-www-urlencoded` and will expect a response with **`Content-Type`** header of `application/json` and a body based on the `Location` parameter.

## GetCustomerDetailsByCustomerId

Gets details for an individual Customer using the `customer_id` attribute.

**Request parameters**

| **Parameter name** | **Type** | **Description**                         |
| ------------------ | -------- | --------------------------------------- |
| Location           | string   | Always `GetCustomerDetailsByCustomerId` |
| CustomerId         | string   | Customer Id provided by the server      |
| Worker             | string   | The app user identity                   |

**Response format**

| **Parameter name** | **Type**                                                   | **Description**                                                                              |
| ------------------ | ---------------------------------------------------------- | -------------------------------------------------------------------------------------------- |
| objects.customer   | [Customer](/docs/frontline/data-transfer-objects#customer) | Customer details to display. *If some of the fields are missing, the line won't be rendered* |

**JSON response example**

```json
{
 "objects": {
   "customer": {
     "display_name": "Bobby S.",
     "customer_id": "1",
     "channels": [{ type: "sms", "value":"+123456789" }]
   }
 }
}
```

**In App example**

![Customer details page showing Bobby S. with initials "BS" and contact number +123456789.](https://docs-resources.prod.twilio.com/51bcc4b30fb82dd265f9aed4ca2a02acb529ac1bb2a8fc3044d019caa53c95a8.png)

## GetCustomersList

Gets a list of Customers and returns them as an array of objects based on a worker identity.

**Request parameters**

| **Parameter name** | **Type**         | **Description**                                                                                                                      |
| ------------------ | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| Location           | string           | Always `GetCustomersList`                                                                                                            |
| PageSize           | string           | The number of customers to return in a response                                                                                      |
| Anchor             | string, optional | The Customer ID of the last customer that was loaded                                                                                 |
| NextPageToken      | string, optional | A string for pagination. [See **Custom pagination**](#custom-pagination), below                                                      |
| Worker             | string           | The app user identity                                                                                                                |
| Query              | string, optional | Frontline user's search query in case it is a search request. [See **Customer search**](#customer-search)[, below](#customer-search) |

**Response format**

| **Parameter name**        | **Type**                                                           | **Description**                                                                                                          |
| ------------------------- | ------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------ |
| objects.customers         | Array\<[Customer](/docs/frontline/data-transfer-objects#customer)> | List of customers to display. For example: `[{ display_name: ‘John D.', customer_id: '13' }]`                            |
| objects.searchable        | Boolean                                                            | Whether the integration service is handling search or not. [See **Customer search**](#customer-search), below            |
| objects.next\_page\_token | string                                                             | A string for pagination which will be sent with the next request. [See **Custom pagination**](#custom-pagination), below |

**JSON response example**

```json
{
  "objects": {
    "customers": [
      {
        "display_name":"Bobby S.",
        "customer_id":"1"
      }
    ]
  }
}
```

## Customer search

The Frontline app has built-in search functionality which filters customers locally. We recommend implementing your own search functionality for better performance, especially if your Frontline users have more than 100 customers, or if you'd like to search across additional fields in your CRM.

![Search bar under 'My Customers' with a contact named Bobby S.](https://docs-resources.prod.twilio.com/e28a375f44a05555749c6cc8a6f1a24c1cb7f536a77986a8d437b9b3511dba9f.png)

Frontline uses the [**GetCustomerList**](/docs/frontline/my-customers#getcustomerslist) location for searching customers with an additional **Query** parameter. Your integration service can interpret that as a search operation by checking for the existence of this parameter. If your integration service handles the search, the response should contain the property `searchable` and set it equal to `true`.

**Response payload example**

```json
{ 
  "objects": {
    "customers":[
      {
        "display_name":"Bobby S.",
        "customer_id":"1"
      }
    ],
    "searchable": true
  }
}
```

## Contact addresses and Phone Number Masking

Phone number masking is a Frontline Administration feature that applies masking to the last four digits of any [Channel Address](/docs/frontline/data-transfer-objects#channel) supplied to Frontline from the [CRM callback](/docs/frontline/my-customers#getcustomerdetailsbycustomerid) `GetCustomerDetailsByCustomerId`. Phone number masking applies to all channel addresses including phone numbers and WhatsApp numbers on the Frontline customer details screen.\
In App example:

![Customer details for Bobby S. with contact number partially hidden as +12345XXXX.](https://docs-resources.prod.twilio.com/c376853113e0fed7337a830a0f2386d767dff0bafb56ad0a9508ab679fc1a3b1.jpg)

### How to set up Phone Number Masking as an account owner or admin

You can follow the next steps to enable or disable Phone Number masking for all users in the account:

1. Sign in to the [Twilio Console](https://www.twilio.com/login) as an admin with the privilege to edit account settings.
2. In the **Develop** menu, navigate to the [Frontline console](https://console.twilio.com/us1/develop/frontline/overview?frameUrl=%2Fconsole%2Ffrontline%2Foverview%3Fx-target-region%3Dus1&_ga=2.246808711.2002154833.1666355503-1983405419.1642425625). Go to the **Manage >** **Callbacks** section.
3. Under **Contact phone number display setting**, click **Mask contact phone numbers** to enable masking or click **Show full contact phone numbers** to disable masking.
4. Click **Save**.

![Configure callbacks interface for Frontline app with options for displaying or masking contact phone numbers.](https://docs-resources.prod.twilio.com/ec37e081e021c74041c9bca32150ef49b97d0fa5c64d7c9bf215750e0281ea5f.png)

## Custom pagination

If the Anchor-based pagination in the Frontline Integration Service (see [customers.js](https://github.com/twilio/frontline-demo-service/blob/main/src/providers/customers.js)) doesn't suit your needs, you can use the `objects.next_page_token` field to implement your custom pagination logic. It can be used for token/offset based pagination.\
**Example request**

```bash
curl --location --request POST 'https://example.com/callbacks/crm' \
  --header 'Content-Type: application/x-www-form-urlencoded' \
  --data-urlencode 'Location=GetCustomersList' \
  --data-urlencode 'Worker=alice' \
  --data-urlencode 'PageSize=30'
```

**Example response**

```json
{
  "objects":{
    "customers":[
      {
        "display_name":"Bobby S.",
        "customer_id":"1"
      }
        ...
    ],
    "next_page_token": "PAGE_TWO_TOKEN"
  }
}
```

If `next_page_token` is defined, the app adds the passed next page token as the `NextPageToken` attribute to the payload, instead of `Anchor`, to every consecutive request after the first page load.

```bash
curl --location --request POST 'https://example.com/callbacks/crm' \
  --header 'Content-Type: application/x-www-form-urlencoded' \
  --data-urlencode 'Location=GetCustomersList' \
  --data-urlencode 'Worker=alice' \
  --data-urlencode 'PageSize=30' \
  --data-urlencode 'NextPageToken=PAGE_TWO_TOKEN'
```

Response:

```json
{
   "objects":{
      "customers":[
         {
            "display_name":"John S.",
            "customer_id":"31"
         }
        ...
      ],
      "next_page_token": "PAGE_THREE_TOKEN"
   }
}
```
