---
title: Customize data returned to clients
slug: cms-12/api/how-to-customize-data-returned-to-clients
docTags: 
createdAt: 2026-08-07T16:45:42.000Z
---

The following approaches customize how response data is returned for requests.

1. Use Select parameter in endpoints.
2. Use `IContentFilter` and `IContentApiModelFilter`.
3. Use `IPropertyConverter` and `IPropertyConverterProvider` to convert from `IContent` to `ContentApiModel`. This approach is not addressed in this article.

(1) and (2) are described below, respectively, while (3) is addressed in [Customize conversion from IContent to ContentApiModel](docId\:rQjpokYPn4MRSi50uxGck).

## Select parameter in endpoints

Endpoints in Content Delivery API let you filter data returned to requests by using the `select` parameter.

Assign the property names expected in the response to the parameter, separated by a comma. The value of this parameter is extracted and passed to `ConverterContext.SelectedProperties` for later use.

The following image shows an example with a `Get` endpoint, but the result format is the same for others also. For endpoints related to `GetChildren` and `GetAncestor`, data filtering is applied for each item returned to clients. Property names are not case-sensitive, and contentLink, name, and language are returned regardless of parameter value.

![](https://api.archbee.com/api/optimize/BrbvVORKJ5iIeSMZye5kI/He8yo8hbQ351crGj7nUg7_ff508ad-imagequ6uh.png)

This feature cannot be applied to expanded values. Where clients send a request and expect properties to be expanded, the expanded value still shows full data without filtering it according to `select`. The following image shows this. Although some properties are passed in param, the expanded value `pageImage` still shows full data as normal.

![](https://api.archbee.com/api/optimize/BrbvVORKJ5iIeSMZye5kI/OP8nsD-JJ9JJ_3bPt-vtx_34b69cb-image0sst.png)

## Use IContentFilter and IContentApiModelFilter

Although `IContentFIlter` and `IContentApiModelFilter` was marked as **Preview** for safety purposes; they were stable and worth being used for customization. The preview may be removed in a coming .NET Core version of Content Delivery API.

The following diagram shows how `IContent` is converted into `ContentAPIModel`, which is then serialized and returned to clients. The `select` parameter in the request (described in `Select` parameter in endpoints) is extracted and passed to `ConverterContext`. It is then used by `ContentApiModelMinifier` to filter data.

This section focuses on two other ways to filter data with `IContentFilter` and `IContentApiModelFilter`.

![](https://api.archbee.com/api/optimize/BrbvVORKJ5iIeSMZye5kI/xxh_awiU-lhTjyG2_Q9SL-20260722-175336.png "imageqb5gh3.png")

### IContentFilter

The **IContent Filtering** phase takes responsibility to filter `IContent` data before it is converted to `ContentApiModel`. Within this phase, the `IContent` properties can be filtered according to specific rules. The following code sample shows an example of how to filter data using `IContentFilter`. The filter impacts`ExpandedValue` also.

```csharp
[ServiceConfiguration(typeof (IContentFilter), Lifecycle = ServiceInstanceScope.Singleton)]
internal class CustomContentFilter: ContentFilter<IContent> {
  public override void Filter(IContent content, ConverterContext converterContext) {
    content.Property.Remove("PageImage");
    content.Property.Remove("MainContentArea");
  }
}
```

The code sample is simple, but you can use other services or `HttpContext` to do more filtering within the class (for example, pass some parameters in the request and extract them by using `HttpContext` or injected services for more data manipulation).

With the previous code example, the properties `PageImage` and `MainContentArea` are removed from `IContent`, meaning that they will not display in the conversion phase later. As a result, they will disappear in the result returned to clients. The downside of `IContentFilter` is that it is still not possible to remove some default properties of `ContentApiModel` like `ExistingLanguages`, `MasterLanguage`, and so on.

:::hint{type="info"}
**Note**
Some properties are mandatory (such as, `PageLink` and `PageTypeID`, if content is a page) and those should not be removed in the filter. Otherwise, exceptions are thrown in the conversion phase later on.
:::

### IContentApiModelFilter

After `IContent` is converted to `ContentApiModel`, and before data is returned to clients (or minified based on a select parameter), you can filter the `ContentApiModel` data in the `ContentApiModel` filtering phase, as shown in the following code sample. The sample uses the `select` parameter.

```csharp
[ServiceConfiguration(typeof (IContentApiModelFilter), Lifecycle = ServiceInstanceScope.Singleton)]
internal class CustomContentApiModelFilter: ContentApiModelFilter<ContentApiModel> {
  public override void Filter(ContentApiModel contentApiModel, ConverterContext converterContext) {
    // Select param mentioned in the first part of article is retrieved and passed to ConverterContext.SelectedProperties
    // but it's only for the parent content. In case that clients contain child content that can be expanded, the param value is not served for them.
    // so that we need to extract param like the following if we want to apply select param for child elements.

    var selectedParamValue = string.Empty;
    if (HttpContext.Current.Request.QueryString["select"] == null) {
      return;

    }
    selectedParamValue = HttpContext.Current.Request.QueryString["select"].ToString();
    var selectedProperties = string.IsNullOrWhiteSpace(selectedParamValue) ? new HashSet<string>() : new HashSet<string>(selectedParamValue.Split(',').Select(x => x.Trim()), StringComparer.OrdinalIgnoreCase);

    try {
      var dictProp = new Dictionary<string, object>();
      contentApiModel.Properties = contentApiModel.Properties.Where(entry => selectedProperties.Contains(entry.Key))
        .ToDictionary(entry => entry.Key, entry => entry.Value);

      // Set those values below as null, and configure ContentApiOption.IncludeNullValues = false in Initialization
      // then, response data will not include those ones. 
      contentApiModel.ExistingLanguages = null;
      contentApiModel.MasterLanguage = null;
      contentApiModel.ParentLink = null;
      contentApiModel.Language = null;
      contentApiModel.StartPublish = null;
      contentApiModel.StopPublish = null;
    } catch (Exception ex) {
      Console.WriteLine(ex.Message);
    }
  }
}
```

As in the previous example, `IContentApiModelFilter` lets you remove the default `ContentApiModel` properties and filter data returned by using select parameters. The filter is activated each time an `IContent` is converted to `ContentApiModel`. This means it affects nested elements or items in `ContentArea` in an expanded scenario, which also makes the response body much cleaner and lighter. `ContentApiOption.IncludeNullValue` should be set to **false** in the configuration for this sample.

:::hint{type="info"}
**Note**
In a case where the whole conversion phase should be customized for a specific reason,  you can use `ContentConvertingService` (a public service) to fulfill the requirement. However, this is not recommended due to the complexity to handle `IContent`.
:::
