Loading...
Area: Content Delivery API
Applies to versions: 2 and higher

Content Search API

The Content Search API exposes the ability to query for content in Episerver Find, providing robust filtering and sorting via OData syntax, with support for personalization, proper access control, and a feature for loading referenced content in the same request.

In this topic

Localization

Content can be retrieved in one or many languages within the same request to the Content Search API endpoint. In order to indicate the desired languages of content to return, attach the Accept-Language header to your request. If you wish to receive content in all languages, pass an empty Accept-Language header or pass a wildcard "*" value.

Accept-Language: en
Accept-Language: en, sv
Accept-Language: en-US,fr-CA
Accept-Language: *

Access control

The Content Search API only returns published content that the current user has access to view.

Users can authenticate via Cookie Authentication or Content Delivery API Authorization using OAuth, and either method can be used to call the API from an authenticated context.

Personalization

The Content Search API leverages indexed data within Episerver Find to deliver search results quickly and efficiently. By default, content is not personalized based on Visitor Group criteria since it is loaded directly from Episerver Find. In order to retrieve personalized property values (based on the current user and context), pass the personalize query string parameter as true:

?personalize=true

Free text search

The Content Search API endpoint allows callers to pass in a free text query, which is evaluated by Episerver Find.

?query=apples

Filtering

Search results can be filtered using the OData v4 filter syntax, providing a capability to quickly write queries to filter down to specific subsets of content.

OData filters can be passed in the filter query string, with support for the following operators and functions:

  • Logical Operators: eq, ne, ge, gt, le, lt, and, or
  • String Functions: tolower, contains
  • Collection Functions: any (Limited support - see Filter by Content Type below)

For more information on OData v4 syntax, see URL Conventions for OData v4.

Filter by Content Type

Content can be filtered by a specific content type name, or by the following set of base types: Page, Block, Media, Image, Video.

?filter=ContentType/any(t:t eq 'Page')
?filter=ContentType/any(t:t eq 'ArticlePage')
?filter=ContentType/any(t:t eq 'ArticlePage') or ContentType/any(t:t eq 'CategoryPage')
?filter=ContentType/any(t:t ne 'Block')

Note: any function support is limited to matching single property expressions on built-in simple Collection properties, namely ContentType. To filter in other collections on all properties, such as by Category or by your own Content Area properties, use eq and ne filters (See Filter by Category, Filter by Content Reference, and Filter by Content Area Value below).

When using `any` function, you must use the Pascal Case for property name (for example, ContentType, NOT contentType). This is because `any` function use the property name in filter string to find correct property in C# model class. If you pass a Camel Case property name like contentType, the OData parser will throw an parse exception. When working with other functions and operations, property name with Camel Case should be used.

Filter by Category

?filter=category/value/id eq 2
?filter=category/value/name eq 'Category Name'

Filter by Content Reference

?filter=contentLink/id eq 6
?filter=contentLink/id ne 6
?filter=contentLink/id ge 10

Filter by Content Area Value

?filter=contentAreaProperty/value/contentLink/id eq 17
?filter=contentAreaProperty/value/contentLink/id ne 4

Filter by Date Range

?filter=startPublish ge 2016-01-01T00:00:00Z and startPublish le 2017-01-01T00:00:00Z
?filter=startPublish ge 2016-01-01T00:00:00Z and startPublish le 2017-01-01T00:00:00Z

Filtering with String Matching

?filter=tolower(name) eq 'start'
?filter=contains(mainBody/value, 'Start')
?filter=contains(tolower(mainBody/value), 'bees')

Ordering

Search results can be ordered using the OData v4 orderby syntax, with support for multiple sorting criteria.

Orderby expressions are passed in the orderby query string, with support for indicating sort direction with asc and desc descriptors. If a sort direction is not included when passing an orderby string, the direction is defaulted to Ascending.

If the orderby string is excluded or empty, search results are ordered by relevance.

For more information on OData v4 syntax, see URL Conventions for OData v4.

Order by Name

?orderby=name

Order by Recently Changed

?orderby=changed desc

Order by multiple properties

?orderby=name asc, changed desc

Top/skip

Use the top and skip parameters to paginate through search results returned from the Content Delivery API search endpoint. The totalMatching property of the search response can be used to calculate the total number of pages.

?top=10&skip=10

Expand (returning referenced content)

Use the expand parameter to return data from reference properties in the same request.

?expand=myContentReference
?expand=myContentReference,myContentArea
?expand=*

The following property types can be expanded: Content Area, Content Reference, Content Reference List, Link Collection

When reference properties are expanded, the full object for the referenced IContent instances will be returned in the response on the "expandedValue" property of that property's object.

Expanded properties are fully compatible with the personalize parameter, meaning that only anonymous content is returned when a given property is expanded and personalize is set to false.

Properties on objects that are returned in the ExpandedValue cannot be expanded further in the same request.

Example request/response

All example request use Axios for generating requests in Javascript.

Add Axios (and a polyfill for UrlSearchParams for older browsers) via CDN for easy testing:

<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/url-search-params/0.10.0/url-search-params.js"></script>

Request

    axios.get('/api/episerver/search/content/', {
            params: {
                'query' : 'farmer',
                'skip' : 0,
                'top' : 2,
                'expand' : '*',
                'filter' : 'ContentType/any(t:t eq \'ButtonBlock\')',
                'orderby' : 'changed desc',
                'personalize' : 'true'
            },
            headers: {
                'Accept': 'application/json',
                'Accept-Language': 'en,sv'
            }
        })
        .then(function (response) {
            console.log(response);
        })
        .catch(function (error) {
            console.log(error);
        });

Response

{
    "totalMatching": 2,
    "results": [
        {
            "contentLink": {
                "id": 72,
                "workId": 0,
                "guidValue": "63f70e99-d00a-4bbd-b9b8-ede3f12d28df",
                "providerName": null
            },
            "name": "All events button",
            "language": {
                "displayName": "English",
                "name": "en"
            },
            "existingLanguages": [
                {
                    "displayName": "English",
                    "name": "en"
                }
            ],
            "masterLanguage": {
                "displayName": "English",
                "name": "en"
            },
            "contentType": [
                "Block",
                "ButtonBlock"
            ],
            "parentLink": {
                "id": 69,
                "workId": 0,
                "guidValue": "3ae529f7-1161-430b-945e-df9ecd2f2935",
                "providerName": null
            },
            "routeSegment": null,
            "url": null,
            "changed": "2018-08-09T08:08:39Z",
            "created": "2012-10-02T12:59:10Z",
            "startPublish": "2017-11-27T07:33:11Z",
            "stopPublish": null,
            "saved": "2018-08-09T08:08:39Z",
            "status": "Published",
            "buttonLink": {
                "value": "http://localhost:3581/en/about-us/news-events/events/",
                "propertyDataType": "PropertyUrl"
            },
            "category": {
                "value": [],
                "propertyDataType": "PropertyCategory"
            },
            "buttonText": {
                "value": "all events",
                "propertyDataType": "PropertyLongString"
            }
        },
        {
            "contentLink": {
                "id": 71,
                "workId": 0,
                "guidValue": "21f244ea-09a7-4349-ab2c-6aa149ef4369",
                "providerName": null
            },
            "name": "All news button",
            "language": {
                "displayName": "English",
                "name": "en"
            },
            "existingLanguages": [
                {
                    "displayName": "English",
                    "name": "en"
                }
            ],
            "masterLanguage": {
                "displayName": "English",
                "name": "en"
            },
            "contentType": [
                "Block",
                "ButtonBlock"
            ],
            "parentLink": {
                "id": 67,
                "workId": 0,
                "guidValue": "541c0bbe-dc14-4840-b0d1-c27e3437c70e",
                "providerName": null
            },
            "routeSegment": null,
            "url": null,
            "changed": "2018-08-09T08:08:39Z",
            "created": "2012-10-02T12:58:12Z",
            "startPublish": "2017-11-27T07:33:11Z",
            "stopPublish": null,
            "saved": "2018-08-09T08:08:39Z",
            "status": "Published",
            "buttonLink": {
                "value": "http://localhost:3581/en/about-us/news-events/press-releases/",
                "propertyDataType": "PropertyUrl"
            },
            "category": {
                "value": [],
                "propertyDataType": "PropertyCategory"
            },
            "buttonText": {
                "value": "all news",
                "propertyDataType": "PropertyLongString"
            }
        }
    ]
}

Last updated: Oct 30, 2018

Feedback?