Generic REST API Source JSON Configuration Examples

The Generic 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 Cloud 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 Generic 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. Should you want to index the content of a repository listed in the table below, you should start with the corresponding configuration example and tailor it to your needs. The GitHub folder also contains instructions.

If the GitHub folder also contains an indexing pipeline extension (IPE), add it to your Coveo organization.

As you test your source configuration, you might also find you need extra configurations such as an IPE or a permission configuration to index the desired content properly.

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

Repository Links
AppDirect Coveo GitHub folder and instructions
API documentation
Azure Active Directory Coveo GitHub folder and instructions
API documentation
Azure DevOps Coveo GitHub folder and instructions
API documentation
ClickHelp Coveo GitHub folder and instructions
API documentation
Cornerstone Coveo GitHub folder and instructions
API documentation
Discourse Coveo GitHub folder and instructions
API documentation
Docebo LMS Coveo GitHub folder and instructions
API documentation
DynamoDB Coveo GitHub folder and instructions
API documentation
Exchange Online Coveo GitHub folder and instructions
API documentation
GitHub Coveo GitHub folder and instructions
API documentation
GoMoxie Knowledgebase Coveo GitHub folder and instructions
Google Sheets Coveo GitHub folder and instructions
API documentation
LearnUpon Coveo GitHub folder and instructions
API documentation
LinkedIn Learning Coveo GitHub folder and instructions
API documentation
MindTickle Coveo GitHub folder and instructions
Pendo Coveo GitHub folder and instructions
API documentation
Skilljar LMS Coveo GitHub folder and instructions
API documentation
Spigit Coveo GitHub folder and instructions
Stack Overflow Coveo GitHub folder and instructions
API documentation
UserVoice Coveo GitHub folder and instructions
API documentation
Vidyard Coveo GitHub folder and instructions
API documentation
Vimeo Coveo GitHub folder and instructions
API documentation
Wistia Coveo GitHub folder and instructions
API documentation
Workplace from Facebook Coveo GitHub folder and instructions
API documentation

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",
          "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 Generic 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 Generic REST API source (see Add or Edit a Generic REST API Source). You can use the @APIKey mapping to retrieve the API key you entered in the Add a Generic REST API Source panel.

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 Generic 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",
      "Endpoints": [
        {
          "Path": "/users",
          "Method": "GET",
          "ItemType": "User",
          "Uri": "%[coveo_url]/users/%[id]",
          "ClickableUri": "%[coveo_url]/users/%[id]",
          "Headers": {
            "Authorization": "Bearer @ApiKey"
          }
        }
      ]
    }
  ]
}

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",
      "Endpoints": [
        {
          "Path": "/users",
          "Method": "GET",
          "ItemType": "User",
          "Uri": "%[coveo_url]/users/%[id]",
          "ClickableUri": "%[coveo_url]/users/%[id]",
          "Headers": {
            "X-Api-Key": "@ApiKey"
          }
        }
      ]
    }
  ]
}

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 Cloud 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.

When you provide an OAuth 2.0 configuration, Coveo Cloud 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 Cloud 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 Generic REST API source configuration panel.


{
  "Services": [
    {
      "Authentication": {
        "OAuth": {
          "Headers": {
            "Content-Type": "application/x-www-form-urlencoded"
          },
          "Query": {
            "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",
      "Authentication": {
        "Username": "admin",
        "Password": "password",
        "ForceBasicAuthentication": true
      },
      "Endpoints": [
        {
          "Path": "/posts",
          "Method": "GET",
          "Paging": {
            "PageSize": 10,
            "OffsetStart": 0,
            "OffsetType": "page",
            "Parameters": {
              "Limit": "limit",
              "Offset": "page"
            }
          },
          "Headers": {
            "key": "value",
            "authentication": "basic"
          },
          "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 Generic REST API source panel to create a source (see Add or Edit a Generic 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

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]"
                     }
                  }
               ]
            }
         ]
      }
   ]
}

Photos with a Binary Body

This example uses the JSONPlaceholder REST API in place of that of an online photo album.

{
   "Services": [
      {
         "Url": "https://jsonplaceholder.typicode.com",
         "Endpoints": [
            {
               "Path": "/photos",
               "Method": "GET",
               "ItemType": "Photo",
               "Uri": "%[coveo_url]/photos/%[id]",
               "ClickableUri": "%[url]",
               "Title": "%[title]",
               "Body": "%[content]",
               "Metadata": {
                  "id": "%[id]",
                  "albumid": "%[albumId]",
                  "thumbnailurl": "%[thumbnailUrl]",
                  "url": "%[url]"
               },
               "SubQueries": [
                  {
                     "Path": "%[coveo_parent.url]",
                     "Method": "GET",
                     "IsBinaryBody": true
                  }
               ]
            }
         ]
      }
   ]
}

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

This JSON configuration is meant to be used as an example only, since the Coveo Support team doesn’t provide help with Generic 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

This JSON configuration is meant to be used as an example only, since the Coveo Support team doesn’t provide help with Generic 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 Cloud 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]"
              }
            }
          ]
        }
      ]
    }
  ]
}
Recommended Articles