REST API Source JSON Configuration Examples

The REST API source allows you to index virtually any remote repository exposing its data through an API. When creating your source, you must provide a JSON REST configuration instructing Coveo to retrieve items from the repository REST services and their respective resource endpoints. This configuration indicates which API calls to execute to fetch the desired items, how to parse the responses to extract relevant metadata, and which content type these items represent.

This article offers examples that you can use to build your JSON configuration. In particular, it links to Coveo’s Open-Source Connectivity Library, which contains complete configuration examples for several repositories. You can start from these examples and tailor them to your needs.

The article contains:

See also the REST API source tutorial for a step-by-step overview of the entire source creation process.

Open-Source Connectivity Library

Coveo has created a GitHub connectivity library that contains source configuration examples. To index the content of a repository in the library, create a REST API cloud source with the corresponding configuration example, and then tailor it to your needs.

Should an example configuration not be relevant anymore, leave a comment on GitHub, commit your own changes, or contact the Coveo Support team.

JSON Responses and Corresponding REST Configurations

The following examples show the REST configuration that one could provide to match the format of the JSON response returned by the repository API.

For the sake of clarity, all these examples use the same base REST API URL (http://example.com/api/v1) and don’t have any query parameters (other than pagination-specific parameters under Paging) or headers.

Minimal Configuration

Minimal configuration with one service and one endpoint.

JSON response

[
  { "id": 1, "name": "alice", "updated": "2016-11-14 11:29:49" },
  { "id": 2, "name": "bob", "updated": "2016-11-15 13:51:24" },
  { "id": 3, "name": "jack", "updated": "2016-11-15 13:59:44" },
  { "id": 4, "name": "eve", "updated": "2016-11-15 16:09:08" },
  { "id": 5, "name": "isaac", "updated": "2016-11-16 17:02:35" }
]

Corresponding REST configuration

{
  "Services": [
    {
      "Url": "http://example.com/api/v1",
      "Endpoints": [
        {
          "Path": "/users",
          "Method": "GET",
          "ItemType": "User",
          "Uri": "%[coveo_url]/users/%[id]",
          "ClickableUri": "%[coveo_url]/users/%[id]",
          "Title": "%[name]",
          "ModifiedDate": "%[updated]",
          "Metadata": {
            "id": "%[id]",
            "username": "%[name]"
          }
        }
      ]
    }
  ]
}

Paging

Offset Based on Page Numbers

Paging configuration at the Services level. See the Paging object reference for details on its properties. The offset is based on page numbers.

JSON response

[
  { "id": 1, "name": "alice", "updated": "2016-11-14 11:29:49" },
  { "id": 2, "name": "bob", "updated": "2016-11-15 13:51:24" },
  { "id": 3, "name": "jack", "updated": "2016-11-15 13:59:44" },
  { "id": 4, "name": "eve", "updated": "2016-11-15 16:09:08" },
  ...Many more entries...
  { "id": 500, "name": "isaac", "updated": "2016-11-16 17:02:35" }
]

Corresponding REST configuration

{
  "Services": [
    {
      "Url": "http://example.com/api/v1",
      "Paging": {
        "PageSize": 20,
        "OffsetStart": 0,
        "OffsetType": "page",
        "Parameters": {
          "Limit": "limit",
          "Offset": "page"
        }
      },
      "Endpoints": [
        {
          "Path": "/users",
          "Method": "GET",
          "ItemType": "User",
          "Uri": "%[coveo_url]/users/%[id]",
          "ClickableUri": "%[coveo_url]/users/%[id]",
          "Title": "%[name]",
          "ModifiedDate": "%[updated]",
          "Metadata": {
            "id": "%[id]",
            "username": "%[name]"
          }
        }
      ]
    }
  ]
}

Offset Based on Page Cursor

Paging configuration at the Services level. See the Paging object reference for details on its properties. The offset page is based on page cursor (token).

JSON response

{
  "nextPageToken": "3d170d80-7b3b-4371-9499-2ec6a78c507e&",
  "items": [
    { "id": 1, "name": "alice", "updated": "2016-11-14 11:29:49" },
    { "id": 2, "name": "bob", "updated": "2016-11-15 13:51:24" },
    { "id": 3, "name": "jack", "updated": "2016-11-15 13:59:44" },
    { "id": 4,"name": "eve", "updated": "2016-11-15 16:09:08" },
    { "id": 5, "name": "isaac", "updated": "2016-11-16 17:02:35" }
  ]
}

Corresponding REST configuration

{
  "Services": [
    {
      "Url": "http://example.com/api/v1",
      "Paging": {
        "PageSize": 5,
        "OffsetType": "cursor",
        "NextPageKey": "nextPageToken",
        "Parameters": {
          "Limit": "limit",
          "Offset": "pageToken"
        }
      },
      "Endpoints": [
        {
          "Path": "/users",
          "Method": "GET",
          "ItemType": "User",
          "ItemPath": "items",
          "Uri": "%[coveo_url]/users/%[id]",
          "ClickableUri": "%[coveo_url]/users/%[id]",
          "Title": "%[name]",
          "ModifiedDate": "%[updated]",
          "Metadata": {
            "id": "%[id]",
            "username": "%[name]"
          }
        }
      ]
    }
  ]
}

Collection of Items

If the items of an endpoint aren’t at the root of the JSON response, you must specify the path to the array of items using the ItemPath property. In the configuration below, the ItemPath property indicates that the items are in the entries[0].results array.

JSON response

{
  "count": 4,
  "entries": [
    {
      "results": [
        { "id": 1, "name": "item #1" },
        { "id": 2, "name": "item #2" },
        { "id": 3, "name": "item #3" },
        { "id": 4, "name": "item #4" }
      ]
    }
  ]
}

Corresponding REST configuration

{
  "Services": [
    {
      "Url": "http://example.com/api/v1",
      "Endpoints": [
        {
          "Path": "/items",
          "Method": "GET",
          "ItemPath": "entries[0].results",
          "ItemType": "Item",
          "Uri": "%[coveo_url]/items/%[id]",
          "ClickableUri": "%[coveo_url]/items/%[id]",
          "Title": "%[name]",
          "Metadata": {
            "id": "%[id]"
          }
        }
      ]
    }
  ]
}

JSON Response Object Containing a Single Item

You can use the Metadata property to retrieve item metadata provided in the JSON response.

JSON response

{
  "id": 1,
  "firstname": "Loyd",
  "lastname": "Sweeney",
  "age": 26,
  "address": {
    "streetAddress": "6974 Rutrum Dr",
    "city": "Ashburn",
    "state": "VA",
    "zip": "25581"
  },
  "email": "JWeakliem@lectus.org",
  "username": "GHohmann",
  "phone": "9556676434",
  "created": "2009-09-12T05:29:48.688Z"
}

Corresponding REST configuration

{
  "Services": [
    {
      "Url": "http://example.com/api/v1",
      "Endpoints": [
        {
          "Path": "/users/1",
          "Method": "GET",
          "ItemType": "User",
          "Uri": "%[coveo_url]/users/%[id]",
          "ClickableUri": "%[coveo_url]/users/%[id]",
          "Title": "%[username]",
          "ModifiedDate": "%[created]",
          "Metadata": {
            "id": "%[id]",
            "firstname": "%[firstname]",
            "lastname": "%[lastname]",
            "age": "%[age]",
            "address": "%[address]",
            "email": "%[email]",
            "phonenumber": "%[phone]"
          }
        }
      ]
    }
  ]
}

In the configuration above, the address metadata contains the whole JSON object. So, to flatten the metadata, you could also write the following configuration:

{
	"Metadata": [{
		"id": "%[id]",
		"firstname": "%[firstname]",
		"lastname": "%[lastname]",
		"age": "%[age]",
		"address.street": "%[address.streetAddress]",
		"address.city": "%[address.city]",
		"address.state": "%[address.state]",
		"address.zip": "%[address.zip]",
		"email": "%[email]",
		"phonenumber": "%[phone]"
	}]
}

IndexingAction

With this configuration, although 100 posts are available, only the first one will be indexed: all posts with an id greater than 1 are ignored. See the IndexingAction object reference for details on its properties.

{
  "Services": [
    {
      "Url": "https://jsonplaceholder.typicode.com",
      "Endpoints": [
        {
          "Path": "/posts",
          "Method": "GET",
          "ItemType": "Post",
          "Uri": "%[coveo_url]/posts/%[id]",
          "ClickableUri": "%[coveo_url]/posts/%[id]",
          "IndexingAction": {
            "ActionOnItem": "Ignore",
            "Condition": "%[id] > 1"
          },
          "Title": "%[title]",
          "Body": "%[body]",
          "Metadata": {
            "id": "%[id]",
            "userid": "%[userId]"
          }
        }
      ]
    }
  ]
}

API Key Authentication

When the web application to make searchable requires you to authenticate using an API key, there are different ways to provide the key in your source JSON configuration, depending on the application API.

As there’s no standard for API key authentication, there’s no standard way to provide the key in the REST API source. You must therefore manually configure the HTTP headers, query parameters, or payload parameters. Below are examples of the most common API key authentication methods and the corresponding JSON configuration to provide when creating your REST API source (see Add or Edit a REST API Source). You can use the @APIKey mapping to retrieve the API key you entered in the Add a REST API Source panel.

Important

Regardless of the API key authentication method you use, you must avoid entering the API key directly in the JSON configuration, as it won’t be encrypted. Instead, you must enter the API key in the API key box of the Add/Edit a REST API Source panel, and then use the @APIkey placeholder in your JSON configuration.

For example:

API key placeholder in JSON configuration

API Key in the HTTP Authorization Header

Bearer is the authorization type and is most commonly used with OAuth 2.0 tokens.

GET /users HTTP/1.1
Host: http://example.com/api/v1
Authorization: Bearer Az4adfSyBhZX8fTThUJ4Kb2TC3Ax0RshgrZtUiqM
{
  "Services": [
    {
      "Url": "http://example.com/api/v1",
      "Headers": {
        "Authorization": "Bearer @ApiKey"
      },
      "Endpoints": [
        {
          "Path": "/users",
          "Method": "GET",
          "ItemType": "User",
          "Uri": "%[coveo_url]/users/%[id]",
          "ClickableUri": "%[coveo_url]/users/%[id]"
        }
      ]
    }
  ]
}

API Key in a Custom HTTP Header

GET /users HTTP/1.1
Host: http://example.com/api/v1
X-Api-Key: Az4adfSyBhZX8fTThUJ4Kb2TC3Ax0RshgrZtUiqM
{
  "Services": [
    {
      "Url": "http://example.com/api/v1",
      "Headers": {
        "X-Api-Key": "@ApiKey"
      },
      "Endpoints": [
        {
          "Path": "/users",
          "Method": "GET",
          "ItemType": "User",
          "Uri": "%[coveo_url]/users/%[id]",
          "ClickableUri": "%[coveo_url]/users/%[id]"
        }
      ]
    }
  ]
}
Note

Not all custom HTTP headers contain the X- prefix, as this practice was deprecated in 2012.

API Key as a Query Parameter

GET /users?api_key=Az4adfSyBhZX8fTThUJ4Kb2TC3Ax0RshgrZtUiqM HTTP/1.1
Host: http://example.com/api/v1

{
  "Services": [
    {
      "Url": "http://example.com/api/v1",
      "Endpoints": [
        {
          "Path": "/users",
          "Method": "GET",
          "ItemType": "User",
          "Uri": "%[coveo_url]/users/%[id]",
          "ClickableUri": "%[coveo_url]/users/%[id]",
          "QueryParameters": {
            "api_key": "@ApiKey"
          }
        }
      ]
    }
  ]
}

API Key as a Payload Parameter

POST /users HTTP/1.1
Host: http://example.com/api/v1
api_key=Az4adfSyBhZX8fTThUJ4Kb2TC3Ax0RshgrZtUiqM

Payload

{
  "Services": [
    {
      "Url": "http://example.com/api/v1",
      "Endpoints": [
        {
          "Path": "/users",
          "Method": "GET",
          "ItemType": "User",
          "Uri": "%[coveo_url]/users/%[id]",
          "ClickableUri": "%[coveo_url]/users/%[id]",
          "PayloadParameters": {
            "api_key": "@ApiKey"
          }
        }
      ]
    }
  ]
}

OAuth 2.0 Authentication

When the web application to make searchable requires authenticating with OAuth 2.0, your source configuration must include, in the Authentication object, a Query object detailing the OAuth 2.0 query Coveo should send to your web application. Your source configuration can also include a Response object if data must be extracted from the web application response to your authentication query.

Note

When you provide an OAuth 2.0 configuration, Coveo automatically adds an Authorization header on each request to your web application. The access token in this request is extracted from the web application response following the Coveo authentication query. In this response, the token appears as the value of the key specified under AccessToken in the Response object. Moreover, if the Response object doesn’t specify a TokenType, Bearer is used by default.

You could write the following configuration to index content from an Azure DevOps (previously Visual Studio Team Services) project. The @ placeholders (e.g., @RefreshToken) are replaced with the information provided in the REST API source configuration panel.


{
  "Services": [
    {
      "Authentication": {
        "OAuth": {
          "Query": {
            "Headers": {
            "User-Agent": "Coveobot/2.0"
            },
            "RefreshUrl": "https://app.vssps.visualstudio.com/oauth2/token",
            "Method": "POST",
            "Parameters": {
              "client_assertion_type": {
                "Type": "Payload",
                "Value": "urn:ietf:params:oauth:client-assertion-type:jwt-bearer"
              },
              "client_assertion": {
                "Type": "Payload",
                "Value": "@ClientSecret"
              },
              "grant_type": {
                "Type": "Payload",
                "Value": "refresh_token"
              },
              "assertion": {
                "Type": "Payload",
                "Value": "@RefreshToken",
                "IsRefreshToken": true
              },
              "redirect_uri": {
                "Type": "Payload",
                "Value": "<YOUR_REDIRECT_URI>"
              }
            }
          },
          "Response": {
            "AccessToken": "access_token",
            "SupportsRefreshToken" : "true",
            "RefreshToken": "refresh_token",
            "ExpiresIn": "expires_in",
            "TokenType": "token_type"
          }
        }
      },
      "Url": "https://<ACCOUNT_NAME>.visualstudio.com/<PROJECT>/<TEAM>}/_apis",
      "Endpoints": [
        {
          "Path": "/wit/wiql/<QUERY_ID>",
          "Method": "GET",
          "QueryParameters": {
            "api-version": "5.0-preview.2"
          },
          "ItemType": "WorkItem",
          "ItemPath": "workItems",
          "Uri": "%[url]",
          "ClickableUri": "%[url]",
          "Metadata": {
            "id": "%[id]",
            "url": "%[url]"
          }
        }
      ]
    }
  ]
}

Complete Example

The REST configuration below results in the execution of these two queries (each along with the two specified headers):

  • GET http://example.com/api/v1/posts?type=post&expand=true&id=120

  • POST http://example.com/api/v1/users?expand=true

{
  "Services": [
    {
      "Url": "http://example.com/api/v1",
      "Headers": {
        "key": "value",
        "authentication": "basic"
      },
      "Authentication": {
        "Username": "admin",
        "Password": "password",
        "ForceBasicAuthentication": true
      },
      "Endpoints": [
        {
          "Path": "/posts",
          "Method": "GET",
          "Paging": {
            "PageSize": 10,
            "OffsetStart": 0,
            "OffsetType": "page",
            "Parameters": {
              "Limit": "limit",
              "Offset": "page"
            }
          },
          "QueryParameters": {
            "id": "120",
            "type": "user",
            "expand": true
          },
          "ItemType": "Post",
          "Uri": "%[coveo_url]/repository/posts/%[id]",
          "ClickableUri": "%[coveo_url]/posts/%[id]",
          "Title": "%[title]",
          "ModifiedDate": "%[updated]",
          "Body": "%[html.content]",
          "Metadata": {
            "author": "%[author]",
            "id": "%[id]"
          }
        },
        {
          "Path": "/users",
          "Method": "POST",
          "ItemPath": "results",
          "PayloadParameters": {
            "id": "120",
            "type": "user",
            "expand": true
          },
          "ItemType": "User",
          "Uri": "%[coveo_url]/repository/users/%[id]",
          "ClickableUri": "%[coveo_url]/users/%[id]",
          "Title": "%[name]",
          "ModifiedDate": "%[updated]",
          "Metadata": {
            "id": "%[id]",
            "name": "%[name]"
          }
        }
      ]
    }
  ]
}

Other Realistic Examples

The following JSON configuration examples are realistic configurations. They could be entered with few changes in the Add a REST API source panel to create a source (see Add or Edit a REST API Source). If you do so, you can then open the indexed items in the Content Browser to see how the content retrieved by the JSON configuration appears the Coveo Administration Console (see Inspect items with the Content Browser).

Blog Posts and the Corresponding Comments as Sub-Items

Note

This example uses the JSONPlaceholder REST API in place of that of a blog.

{
   "Services": [
      {
         "Url": "https://jsonplaceholder.typicode.com",
         "Endpoints": [
            {
               "Path": "/posts",
               "Method": "GET",
               "ItemType": "Post",
               "Uri": "%[coveo_url]/posts/%[id]",
               "ClickableUri": "%[coveo_url]/posts/%[id]",
               "Title": "%[title]",
               "Body": "%[body]",
               "Metadata": {
                  "id": "%[id]",
                  "userid": "%[userId]"
               },
               "SubItems":[
                  {
                     "Path": "/posts/%[coveo_parent.id]/comments",
                     "Method": "GET",
                     "ItemType": "Comment",
                     "Uri": "%[coveo_url]/posts/%[coveo_parent.id]/comments/%[id]",
                     "ClickableUri": "%[coveo_url]/comments/%[id]",
                     "Title": "%[name]",
                     "Body": "%[body]",
                     "Metadata": {
                        "id": "%[id]",
                        "postid": "%[postId]",
                        "name": "%[name]",
                        "email": "%[email]"
                     }
                  }
               ]
            }
         ]
      }
   ]
}

JSONPath With Filter Expression

The JSONPath syntax allows including a filter expression in dynamic values.

The following is a truncated response example from SmartSheet table. In this response, each row corresponds to a project. The cells of a row contain project data such as its name and status. Each column contains a certain type of data regarding the projects in the table.

{
	"id": 952283761449296,
	"name": "MY SMARTSHEET",
	"permalink": "https://app.smartsheet.com/sheets/mC8mcf4M8j37dbnHbBe77fP0bw939PMw96pq961",
	"columns": [{
			"id": 7323702856574852,
			"version": 0,
			"index": 0,
			"title": "Project name",
			"type": "TEXT_NUMBER"
		},
		{
			"id": 1694203322361732,
			"version": 0,
			"index": 1,
			"title": "Status",
			"type": "TEXT_NUMBER"
		},
		"..."
	],
	"rows": [{
			"id": 2314743682492292,
			"rowNumber": 1,
			"cells": [{
					"columnId": 7323702856574852,
					"value": "ERP Vendor Selection",
					"displayValue": "ERP Vendor Selection"
				},
				{
					"columnId": 1694203322361732,
					"value": "Closed",
					"displayValue": "Closed"
				},
				"..."
			]
		},
		{
			"id": 6818343309862788,
			"rowNumber": 2,
			"siblingId": 2314743682492292,
			"cells": [{
					"columnId": 7323702856574852,
					"value": "IS Dashboard",
					"displayValue": "IS Dashboard"
				},
				{
					"columnId": 1694203322361732,
					"value": "On Hold",
					"displayValue": "On Hold"
				},
				"..."
			]
		}
	]
}

You want to index the name, status, etc. of each project item. Therefore, you use a JSONPath with a filter expression based on columnId to retrieve the value of the value field of each column. Your JSON source configuration therefore contains:

{
	"Endpoints": [{
		"Path": "/sheets/952283761449296",
		"Method": "GET",
		"ItemPath": "rows",
		"ItemType": "Project",
		"Uri": "https://app.smartsheet.com/sheets/mC8mcf4M8j37dbnHbBe77fP0bw939PMw96pq961?rowId=%[id]",
		"ClickableUri": "https://app.smartsheet.com/sheets/mC8mcf4M8j37dbnHbBe77fP0bw939PMw96pq961?rowId=%[id]",
		"Title": "%[cells[?(@.columnId==7323702856574852)].value]",
		"CreatedDate": "%[createdAt]",
		"ModifiedDate": "%[modifiedAt]",
		"Metadata": {
			"rowId": "%[id]",
			"rowNumber": "%[rowNumber]",
			"projectName": "%[cells[?(@.columnId==7323702856574852)].value]",
			"projectStatus": "%[cells[?(@.columnId==1694203322361732)].value]"
		}
	}
  ]
}

ServiceNow Incidents and Knowledge Articles

Note

This JSON configuration is meant to be used as an example only, since the Coveo Support team doesn’t provide help with REST API sources retrieving ServiceNow content. To make ServiceNow content searchable with a proper ServiceNow source, see the Coveo for ServiceNow documentation.

{
   "Services": [
      {
         "Url": "https://YOUR_INSTANCE.service-now.com/api/now/",
         "Authentication": {
            "ForceBasicAuthentication": "true",
            "Username": "admin",
            "Password": "PASSWORD_HERE"
         },
         "Endpoints": [
            {
               "Path": "/table/incident",
               "Method": "GET",
               "ItemPath": "result",
               "ItemType": "Incident",
               "Uri": "%[coveo_url]/incident/%[sysid]",
               "ClickableUri": "https://YOUR_INSTANCE.service-now.com/nav_to.do?uri=incident.do?sys_id=%[sysid]%26sysparm_view=ess",
               "Title": "%[short_description]",
               "Body": "%[description]",
               "Paging": {
                  "PageSize": 100,
                  "OffsetStart": 0,
                  "OffsetType": "item",
                  "Parameters": {
                     "Limit": "sysparm_limit",
                     "Offset": "sysparm_offset"
                  }
               },
               "Metadata": {
                  "sysid": "%[sys_id]",
                  "number": "%[number]",
                  "closecode": "%[close_code]",
                  "closenotes": "%[close_notes]",
                  "resolvedat": "%[resolved_at]",
                  "description": "%[description]",
                  "category": "%[category]"
               },
               "SubQueries": [
                  {
                     "Path": "%[coveo_parent.raw.opened_by.link]",
                     "Method": "GET",
                     "Metadata": {
                        "openedbyname": "%[result.name]",
                        "openedbyemail": "%[result.email]"
                     }
                  }
               ]
            },
            {
               "Path": "/table/kb_knowledge",
               "Method": "GET",
               "ItemPath": "result",
               "ItemType": "KB",
               "Uri": "%[coveo_url]/kb/%[sysid]",
               "ClickableUri": "https://YOUR_INSTANCE.service-now.com/nav_to.do?uri=incident.do?sys_id=%[sysid]%26sysparm_view=ess",
               "Title": "%[short_description]",
               "Body": "%[text]",
               "Paging": {
                  "PageSize": 50,
                  "OffsetStart": 0,
                  "OffsetType": "item",
                  "Parameters": {
                     "Limit": "sysparm_limit",
                     "Offset": "sysparm_offset"
                  }
               },
               "Metadata": {
                  "sysid": "%[sys_id]",
                  "number": "%[number]",
                  "description": "%[description]",
                  "published": "%[published]",
                  "meta": "%[meta]",
                  "topic": "%[topic]",
                  "category": "%[category]"
               },
               "SubQueries": [
                  {
                     "Path": "%[coveo_parent.raw.author.link]",
                     "Method": "GET",
                     "Metadata": {
                        "authorname": "%[result.name]",
                        "authoremail": "%[result.email]"
                     }
                  }
               ]
            }
         ]
      }
   ]
}

ServiceNow With RefreshEndpoints

Note

This JSON configuration is meant to be used as an example only, since the Coveo Support team doesn’t provide help with REST API sources retrieving ServiceNow content. To make ServiceNow content searchable with a proper ServiceNow source, see the Coveo for ServiceNow documentation.

The following example includes RefreshEndpoints properties so that only added, modified, and deleted items are updated in the Coveo index (see RefreshEndpoints).


{
  "Services": [
    {
      "Url": "@ServiceUrl",
      "Authentication": {
        "Username": "@Username",
        "Password": "@Password"
      },
      "Endpoints": [
        {
          "Path": "/api/now/table/kb_knowledge",
          "Method": "GET",
          "ItemPath": "result",
          "ItemType": "kbknowledge",
          "Uri": "%[coveo_url]/kb_knowledge/%[sys_id]",
          "PermanentId": "%[sys_id]",
          "ModifiedDate": "%[sys_updated_on]",
          "ClickableUri": "%[coveo_url]/nav_to.do?uri=kb_knowledge.do?sys_id=%[sys_id]%26sysparam_view-ess",
          "Title": "%[short_description]",
          "Body": "%[text]",
          "QueryParameters": {
            "sysparm_query": "workflow_state=published"
          },
          "Paging": {
            "PageSize": 100,
            "OffsetStart": 0,
            "OffsetType": "item",
            "TotalCountHeaderKey": "x-total-count",
            "Parameters": {
              "Limit": "sysparam_limit",
              "Offset": "sysparam_offset"
            }
          },
          "Metadata": {
            "short_description": "%[short_description]",
            "wiki": "%[wiki]",
            "roles": "%[roles]",
            "rating": "%[rating]",
            "description": "%[description]",
            "source": "%[source]",
            "sys_updated_on": "%[sys_updated_on]",
            "related_products": "%[related_products]",
            "number": "%[number]",
            "sys_id": "%[sys_id]",
            "flagged": "%[flagged]",
            "workflow_state": "%[workflow_state]",
            "text": "%[text]",
            "image": "%[image]",
            "article_type": "%[article_type]",
            "author": "%[author]",
            "published": "%[published]",
            "sys_tags": "%[sys_tags]",
            "kb_knowledge_base": "%[kb_knowledge_base]",
            "meta": "%[meta]",
            "topic": "%[topic]",
            "category": "%[category]",
            "kb_category": "%[kb_category]"
          },
          "RefreshEndpoints": [
            {
              "DateFormat": "\\'yyyy-MM-dd\\',\\'hh:mm:ss\\'",
              "QueryParameters": {
                "sysparm_query": "workflow_state=published^sys_updated_on>javascript:gs.dateGenerate(@RefreshDate)"
              }
            },
            {
              "IsDeletionQuery": true,
              "DateFormat": "\\'yyyy-MM-dd\\',\\'hh:mm:ss\\'",
              "QueryParameters": {
                "sysparm_query": "workflow_state!=published^sys_updated_on>javascript:gs.dateGenerate(@RefreshDate)"
              }
            },
            {
              "IsDeletionQuery": true,
              "DateFormat": "\\'yyyy-MM-dd\\',\\'hh:mm:ss\\'",
              "Path": "/api/now/table/sys_audit_delete",
              "QueryParameters": {
                "tablename": "kb_knowledge",
                "sysparm_query": "sys_updated_on>javascript:gs.dateGenerate(@RefreshDate)"
              }
            }
          ],
          "SubQueries": [
            {
              "Path": "%[coveo_parent.raw.source.link]",
              "Method": "GET",
              "Metadata": {
                "source.sys_id": "%[result.sys_id]"
              }
            },
            {
              "Path": "%[coveo_parent.raw.related_products.link]",
              "Method": "GET",
              "Metadata": {
                "related_product.sys_id": "%[result.sys_id]"
              }
            },
            {
              "Path": "%[coveo_parent.raw.author.link]",
              "Method": "GET",
              "Metadata": {
                "author.name": "%[result.name]",
                "author.user_name": "%[result.user_name]",
                "author.title": "%[result.title]",
                "author.sys_id": "%[result.sys_id]",
                "author.email": "%[result.email]"
              }
            },
            {
              "Path": "%[coveo_parent.raw.kb_knowledge_base.link]",
              "Method": "GET",
              "Metadata": {
                "kb_knowledge_base.sys_id": "%[result.sys_id]"
              }
            },
            {
              "Path": "%[coveo_parent.raw.kb_category.link]",
              "Method": "GET",
              "Metadata": {
                "kb_category.sys_id": "%[result.sys_id]"
              }
            }
          ]
        },
        {
          "Path": "/api/now/table/kb_social_qa_question",
          "Method": "GET",
          "ItemPath": "result",
          "ItemType": "kbsocialqaquestion",
          "Uri": "%[coveo_url]/kb_social_qa_question/%[sys_id]",
          "PermanentId": "%[sys_id]",
          "ModifiedDate": "%[sys_updated_on]",
          "ClickableUri": "%[coveo_url]/nav_to.do?uri=kb_social_qa_question.do?sys_id=%[sys_id]%26sysparam_view-ess",
          "Title": "%[sys_id]",
          "Body": "<p>%[question]</p>%[question_details]",
          "Paging": {
            "PageSize": 100,
            "OffsetStart": 0,
            "OffsetType": "item",
            "TotalCountHeaderKey": "x-total-count",
            "Parameters": {
              "Limit": "sysparam_limit",
              "Offset": "sysparam_offset"
            }
          },
          "Metadata": {
            "question": "%[question]",
            "question_details": "%[question_details]",
            "last_activity": "%[last_activity]",
            "profile": "%[profile]",
            "active": "%[active]",
            "sys_tags": "%[sys_tags]",
            "accepted_answer_id": "%[accepted_answer.value]",
            "top_answer_id": "%[top_answer.value]",
            "has_comment": "%[has_comment]",
            "votes": "%[votes]",
            "views": "%[views]",
            "kb_category_id": "%[kb_category.value]",
            "kb_knowledge_base_id": "%[kb_knowledge_base.value]"
          },
          "RefreshEndpoints":
          [
            {
              "DateFormat": "\\'yyyy-MM-dd\\',\\'hh:mm:ss\\'",
              "QueryParameters": {
                "sysparm_query": "sys_updated_on>javascript:gs.dateGenerate(@RefreshDate)"
              }
            },
            {
              "IsDeletionQuery": true,
              "DateFormat": "\\'yyyy-MM-dd\\',\\'hh:mm:ss\\'",
              "Path": "/api/now/table/sys_audit_delete",
              "QueryParameters": {
                "tablename": "kb_social_qa_question",
                "sysparm_query": "sys_updated_on>javascript:gs.dateGenerate(@RefreshDate)"
              }
            }
          ]
        },
        {
          "Path": "/api/now/table/kb_social_qa_answer",
          "Method": "GET",
          "ItemPath": "result",
          "ItemType": "kbsocialqaanswer",
          "Uri": "%[coveo_url]/kb_social_qa_answer/%[sys_id]",
          "PermanentId": "%[sys_id]",
          "ModifiedDate": "%[sys_updated_on]",
          "ClickableUri": "%[coveo_url]/nav_to.do?uri=kb_social_qa_answer.do?sys_id=%[sys_id]%26sysparam_view-ess",
          "Title": "%[sys_id]",
          "Body": "%[answer]",
          "Paging": {
            "PageSize": 100,
            "OffsetStart": 0,
            "OffsetType": "item",
            "TotalCountHeaderKey": "x-total-count",
            "Parameters": {
              "Limit": "sysparam_limit",
              "Offset": "sysparam_offset"
            }
          },
          "Metadata": {
            "question_id": "%[question.value]",
            "profile": "%[profile]",
            "active": "%[active]",
            "accepted": "%[accepted]",
            "sys_tags": "%[sys_tags]",
            "answer": "%[answer]",
            "has_comment": "%[has_comment]",
            "votes": "%[votes]"
          },
          "RefreshEndpoints": [
            {
              "DateFormat": "\\'yyyy-MM-dd\\',\\'hh:mm:ss\\'",
              "QueryParameters": {
                "sysparm_query": "sys_updated_on>javascript:gs.dateGenerate(@RefreshDate)"
              }
            },
            {
              "IsDeletionQuery": true,
              "DateFormat": "\\'yyyy-MM-dd\\',\\'hh:mm:ss\\'",
              "Path": "/api/now/table/sys_audit_delete",
              "QueryParameters": {
                "tablename": "kb_social_qa_answer",
                "sysparm_query": "sys_updated_on>javascript:gs.dateGenerate(@RefreshDate)"
              }
            }
          ]
        },
        {
          "Path": "/api/now/table/kb_social_qa_comment",
          "Method": "GET",
          "ItemPath": "result",
          "ItemType": "kbsocialqacomment",
          "Uri": "%[coveo_url]/kb_social_qa_comment/%[sys_id]",
          "PermanentId": "%[sys_id]",
          "ModifiedDate": "%[sys_updated_on]",
          "ClickableUri": "%[coveo_url]/nav_to.do?uri=kb_social_qa_comment.do?sys_id=%[sys_id]%26sysparam_view-ess",
          "Title": "%[sys_id]",
          "Body": "%[comment]",
          "Paging": {
            "PageSize": 100,
            "OffsetStart": 0,
            "OffsetType": "item",
            "TotalCountHeaderKey": "x-total-count",
            "Parameters": {
              "Limit": "sysparam_limit",
              "Offset": "sysparam_offset"
            }
          },
          "Metadata": {
            "reference_name": "%[reference_name]",
            "reference_id": "%[reference_id.value]",
            "sys_mod_count": "%[sys_mod_count]",
            "sys_tags": "%[sys_tags]",
            "sys_id": "%[sys_id]",
            "comment": "%[comment]"
          },
          "RefreshEndpoints": [
            {
              "DateFormat": "\\'yyyy-MM-dd\\',\\'hh:mm:ss\\'",
              "QueryParameters": {
                "sysparm_query": "sys_updated_on>javascript:gs.dateGenerate(@RefreshDate)"
              }
            },
            {
              "IsDeletionQuery": true,
              "DateFormat": "\\'yyyy-MM-dd\\',\\'hh:mm:ss\\'",
              "Path": "/api/now/table/sys_audit_delete",
              "QueryParameters": {
                "tablename": "kb_social_qa_comment",
                "sysparm_query": "sys_updated_on>javascript:gs.dateGenerate(@RefreshDate)"
              }
            }
          ]
        },
        {
          "Path": "/api/now/table/sc_cat_item",
          "Method": "GET",
          "ItemPath": "result",
          "ItemType": "sccatitem",
          "Uri": "%[coveo_url]/sc_cat_item/%[sys_id]",
          "PermanentId": "%[sys_id]",
          "ModifiedDate": "%[sys_updated_on]",
          "ClickableUri": "%[coveo_url]/nav_to.do?uri=sc_cat_item.do?sys_id=%[sys_id]%26sysparam_view-ess",
          "Title": "%[short_description]",
          "Body": "%[description]",
          "Paging": {
            "PageSize": 100,
            "OffsetStart": 0,
            "OffsetType": "item",
            "TotalCountHeaderKey": "x-total-count",
            "Parameters": {
              "Limit": "sysparam_limit",
              "Offset": "sysparam_offset"
            }
          },
          "Metadata": {
            "delivery_time": "%[delivery_time]",
            "type": "%[type]",
            "no_search": "%[no_search]",
            "sys_updated_by": "%[sys_updated_by]",
            "price": "%[price]",
            "sys_created_on": "%[sys_created_on]",
            "recurring_frequency": "%[recurring_frequency]",
            "sys_name": "%[sys_name]",
            "image": "%[image]",
            "sys_update_name": "%[sys_update_name]",
            "meta": "%[meta]",
            "name": "%[name]",
            "short_description": "%[short_description]",
            "roles": "%[roles]",
            "icon": "%[icon]",
            "description": "%[description]",
            "mobile_picture": "%[mobile_picture]",
            "sys_id": "%[sys_id]",
            "sc_catalogs": "%[sc_catalogs]",
            "cost": "%[cost]",
            "sys_mod_count": "%[sys_mod_count]",
            "recurring_price": "%[recurring_price]",
            "billable": "%[billable]",
            "picture": "%[picture]",
            "category": "%[category]"
          },
          "RefreshEndpoints": [
            {
              "DateFormat": "\\'yyyy-MM-dd\\',\\'hh:mm:ss\\'",
              "QueryParameters": {
                "sysparm_query": "sys_updated_on>javascript:gs.dateGenerate(@RefreshDate)"
              }
            },
            {
              "IsDeletionQuery": true,
              "DateFormat": "\\'yyyy-MM-dd\\',\\'hh:mm:ss\\'",
              "Path": "/api/now/table/sys_audit_delete",
              "QueryParameters": {
                "tablename": "sc_cat_item",
                "sysparm_query": "sys_updated_on>javascript:gs.dateGenerate(@RefreshDate)"
              }
            }
          ],
          "SubQueries": [
            {
              "Path": "%[coveo_parent.raw.category.link]",
              "Method": "GET",
              "Metadata": {
                "category.title": "%[result.title]",
                "category.sys_id": "%[result.sys_id]",
                "category.sys_name": "%[result.sys_name]"
              }
            }
          ]
        },
        {
          "Path": "/api/now/table/sn_customerservice_case",
          "Method": "GET",
          "ItemPath": "result",
          "ItemType": "sncustomerservicecase",
          "Uri": "%[coveo_url]/sn_customerservice_case/%[sys_id]",
          "PermanentId": "%[sys_id]",
          "ModifiedDate": "%[sys_updated_on]",
          "ClickableUri": "%[coveo_url]/nav_to.do?uri=sn_customerservice_case.do?sys_id=%[sys_id]%26sysparam_view-ess",
          "Title": "%[short_description]",
          "Body": "%[close_notes]",
          "Paging": {
            "PageSize": 100,
            "OffsetStart": 0,
            "OffsetType": "item",
            "TotalCountHeaderKey": "x-total-count",
            "Parameters": {
              "Limit": "sysparam_limit",
              "Offset": "sysparam_offset"
            }
          },
          "Metadata": {
            "parent": "%[parent]",
            "caused_by": "%[caused_by]",
            "sys_updated_on": "%[sys_updated_on]",
            "support_manager": "%[support_manager]",
            "skills": "%[skills]",
            "number": "%[number]",
            "resolved_by": "%[resolved_by]",
            "problem": "%[problem]",
            "opened_by": "%[opened_by]",
            "contact": "%[contact]",
            "case": "%[case]",
            "knowledge": "%[knowledge]",
            "expected_start": "%[expected_start]",
            "opened_at": "%[opened_at]",
            "first_response_time": "%[first_response_time]",
            "resolved_at": "%[resolved_at]",
            "work_notes": "%[work_notes]",
            "short_description": "%[short_description]",
            "correlation_display": "%[correlation_display]",
            "work_start": "%[work_start]",
            "description": "%[description]",
            "close_notes": "%[close_notes]",
            "sys_id": "%[sys_id]",
            "company": "%[company]",
            "consumer": "%[consumer]",
            "assigned_to": "%[assigned_to]",
            "product": "%[product]",
            "comments": "%[comments]",
            "sla_due": "%[sla_due]",
            "comments_and_work_notes": "%[comments_and_work_notes]",
            "due_date": "%[due_date]",
            "sys_tags": "%[sys_tags]",
            "partner_contact": "%[partner_contact]",
            "account": "%[account]"
          },
          "RefreshEndpoints": [
            {
              "DateFormat": "\\'yyyy-MM-dd\\',\\'hh:mm:ss\\'",
              "QueryParameters": {
                "sysparm_query": "sys_updated_on>javascript:gs.dateGenerate(@RefreshDate)"
              }
            },
            {
              "IsDeletionQuery": true,
              "DateFormat": "\\'yyyy-MM-dd\\',\\'hh:mm:ss\\'",
              "Path": "/api/now/table/sys_audit_delete",
              "QueryParameters": {
                "tablename": "sn_customerservice_case",
                "sysparm_query": "sys_updated_on>javascript:gs.dateGenerate(@RefreshDate)"
              }
            }
          ],
          "SubQueries": [
            {
              "Path": "%[coveo_parent.raw.parent.link]",
              "Method": "GET",
              "Metadata": {
                "parent.number": "%[result.number]",
                "parent.sys_id": "%[result.sys_id]"
              }
            },
            {
              "Path": "%[coveo_parent.raw.caused_by.link]",
              "Method": "GET",
              "Metadata": {
                "caused_by.reason": "%[result.reason]",
                "caused_by.type": "%[result.type]",
                "caused_by.number": "%[result.number]",
                "caused_by.short_description": "%[result.short_description]",
                "caused_by.sys_id": "%[result.sys_id]"
              }
            },
            {
              "Path": "%[coveo_parent.raw.support_manager.link]",
              "Method": "GET",
              "Metadata": {
                "support_manager.name": "%[result.name]",
                "support_manager.user_name": "%[result.user_name]",
                "support_manager.sys_id": "%[result.sys_id]"
              }
            }
          ]
        }
      ]
    }
  ]
}