REST API source configuration examples

The REST API source allows you to index virtually any content system exposing its data through an API. When creating your source, you must provide a JSON configuration detailing how the Coveo Platform should request content from the API and index the returned items. This configuration indicates which API calls to execute to obtain the desired items, how to parse the responses to extract relevant metadata, and which type of content these items represent.

This article offers realistic JSON configuration examples. You can either start from these examples and tailor them to your needs, or use them as a reference to create your own configuration from scratch.

Tip

In addition to the examples provided here, you can find more examples in Coveo’s connectivity library on GitHub.

When building your configuration, you may also want to refer to the following resources:

  • The Create a REST API source article for a step-by-step guide on how to create a REST API source in the Coveo Administration Console.

  • The Concepts article for descriptions of the concepts and terminology used in the REST API source configuration.

  • The source configuration reference for a detailed description of the properties to include in your source configuration.

  • The permission configuration reference for a detailed description of the the properties to include in the JSON configuration that retrieves your permission data.

  • The REST API source tutorial.

Basic example

The 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

Source configuration
{
  "Services": [
    {
      "Url": "http://example.com/api/v1",
      "Headers": {
        "key": "value",
        "authentication": "basic"
      },
      "Authentication": {
        "Username": "@Username",
        "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]"
          }
        }
      ]
    }
  ]
}

Blog posts and comments

The following configuration indexes blog posts and their comments. The comments are subitems of the blog posts.

Source configuration
{
   "Services": [
      {
         "Url": "https://example.com/blog",
         "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.

SmartSheet response
{
	"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:

Source configuration
{
	"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]"
		}
	}
  ]
}

Azure DevOps project

The following configuration indexes work items from an Azure DevOps (previously Visual Studio Team Services) project.

This configuration instructs Coveo to authenticate to Azure DevOps using OAuth, and then to retrieve work items using the Work Item Query Language (WIQL) API.

Source configuration
{
  "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]"
          }
        }
      ]
    }
  ]
}

ServiceNow incidents and knowledge articles

The following configuration requests ServiceNow incidents and knowledge articles. The configuration includes subqueries retrieving the name and email of the user who opened the incident or authored the article.

Important

This JSON configuration is meant to be used as an example only. To index ServiceNow content, see Create a ServiceNow source. The Coveo Support team doesn’t provide help with REST API sources indexing ServiceNow content.

Source configuration
{
   "Services": [
      {
         "Url": "https://YOUR_INSTANCE.service-now.com/api/now/",
         "Authentication": {
            "ForceBasicAuthentication": "true",
            "Username": "@Username",
            "Password": "@Password"
         },
         "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

The following configuration indexes the following ServiceNow content:

  • Knowledge articles

  • Questions, answers, and comments

  • Catalog items

  • Customer service cases

It also includes RefreshEndpoints to update the index when content is modified or deleted.

Important

This JSON configuration is meant to be used as an example only. To index ServiceNow content, see Create a ServiceNow source. The Coveo Support team doesn’t provide help with REST API sources indexing ServiceNow content.

Source configuration
{
  "Services": [
    {
      "Url": "https://YOUR_INSTANCE.service-now.com/api/now/",
      "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]"
              }
            }
          ]
        }
      ]
    }
  ]
}

Yammer messages, attachments, and permissions

The following configuration indexes a specific Yammer group’s messages and their attachments, as well as the responses to these messages and the responses' attachments.

The message attachments and responses are subitems of the messages, and the response attachments are subitems of the responses. This results in the following content structure:

  • Message

    • Attachment

    • Response

      • Attachment

This configuration also applies the same Permissions object to all items. This object hardcodes the rule that only members of the Yammer group Tech_Team can access the content.

Source configuration
{
  "services": [
    {
      "url": "https://www.yammer.com/api/v1",
      "Headers": {
        "Authorization": "Bearer @ApiKey"
      },
      "endpoints": [
        {
          "path": "/messages/in_group/01234567890.json",
          "QueryParameters": {
            "threaded": "true"
          },
          "Paging": {
            "PageSize": 20,
            "OffsetType": "cursor",
            "NextPageKey": "$.messages[-1:].id",
            "Parameters": {
              "Limit": "limit",
              "Offset": "older_than"
            }
          },
          "method": "GET",
          "itemPath": "messages",
          "itemType": "message",
          "uri": "example.com/%[id]",
          "title": "thread-strart-%[id]",
          "ClickableUri": "%[url]",
          "modifiedDate": "%[created_at]",
          "body": "%[body.parsed]",
          "metadata": {
            "messageid": "%[id]",
            "groupid": "%[group_id]",
            "threadid": "%[thread_id]"
          },
          "Permissions": [
            {
              "Name": "AllowedMemberLevel",
              "PermissionsSets": [
                {
                  "Name": "AllowedMembersSet",
                  "PermissionsFromMetadata": [
                    {
                      "Name": "Tech_Team",
                      "Type": "Group",
                      "PermissionType": "YammerGroup",
                      "IsAllowedMember": true,
                      "AdditionalInfo": {
                        "group_id": "%[groupid]"
                      }
                    }
                  ],
                  "isAnonymousAllowed": "false"
                }
              ]
            }
          ],
          "SubItems": [
            {
              "ItemPath": "attachments",
              "ItemType": "Attachments",
              "uri": "example.com/attachement/%[id]",
              "title": "attachment-%[id]-%[name]",
              "ClickableUri": "%[url]",
              "modifiedDate": "%[created_at]",
              "body": "%[description]",
              "metadata": {
                "messageid": "%[id]",
                "groupid": "%[group_id]",
                "threadid": "%[thread_id]"
              },
              "Permissions": [
                {
                  "Name": "AllowedMemberLevel",
                  "PermissionsSets": [
                    {
                      "Name": "AllowedMembersSet",
                      "PermissionsFromMetadata": [
                        {
                          "Name": "Tech_Team",
                          "Type": "Group",
                          "PermissionType": "YammerGroup",
                          "IsAllowedMember": true,
                          "AdditionalInfo": {
                            "group_id": "%[groupid]"
                          }
                        }
                      ],
                      "isAnonymousAllowed": "false"
                    }
                  ]
                }
              ]
            },
            {
              "Path": "/messages/in_thread/%[coveo_parent.threadid].json",
              "method": "GET",
              "itemPath": "messages",
              "itemType": "message",
              "uri": "example.com/%[id]",
              "title": "reply-%[id]",
              "ClickableUri": "%[url]",
              "modifiedDate": "%[created_at]",
              "body": "%[body.parsed]",
              "metadata": {
                "messageid": "%[id]",
                "groupid": "%[group_id]",
                "threadid": "%[thread_id]"
              },
              "Permissions": [
                {
                  "Name": "AllowedMemberLevel",
                  "PermissionsSets": [
                    {
                      "Name": "AllowedMembersSet",
                      "PermissionsFromMetadata": [
                        {
                          "Name": "Tech_Team",
                          "Type": "Group",
                          "PermissionType": "YammerGroup",
                          "IsAllowedMember": true,
                          "AdditionalInfo": {
                            "group_id": "%[groupid]"
                          }
                        }
                      ],
                      "isAnonymousAllowed": "false"
                    }
                  ]
                }
              ],
              "SubItems": [
                {
                  "ItemPath": "attachments",
                  "ItemType": "Attachments",
                  "uri": "example.com/attachement/%[id]",
                  "title": "attachment-%[id]-%[name]",
                  "ClickableUri": "%[url]",
                  "modifiedDate": "%[created_at]",
                  "body": "%[description]",
                  "metadata": {
                    "messageid": "%[id]",
                    "groupid": "%[group_id]",
                    "threadid": "%[thread_id]"
                  },
                  "Permissions": [
                    {
                      "Name": "AllowedMemberLevel",
                      "PermissionsSets": [
                        {
                          "Name": "AllowedMembersSet",
                          "PermissionsFromMetadata": [
                            {
                              "Name": "Tech_Team",
                              "Type": "Group",
                              "PermissionType": "YammerGroup",
                              "IsAllowedMember": true,
                              "AdditionalInfo": {
                                "group_id": "%[groupid]"
                              }
                            }
                          ],
                          "isAnonymousAllowed": "false"
                        }
                      ]
                    }
                  ]
                }
              ]
            }
          ]
        }
      ]
    }
  ]
}

Then, in the Content security tab of the source, the following permission configuration would instruct Coveo to retrieve the members of the Tech_Team group, and then each member’s email address.

Permission configuration
{
  "url": "https://www.yammer.com/api/v1",
  "Headers": {
     "Authorization": "Bearer @ApiKey"
  },
  "Identities": {
    "YammerGroup": {
      "PermissionSubQueries": [{
        "Path": "/users/in_group/%[coveo_parent.group_id].json",
        "Method": "GET",
        "itemPath": "users",
        "Name": "%[email]",
        "additionalInfo": {
          "email": "%[email]"
        },
        "Type": "User",
        "PermissionType": "Employees"
      }
      ]
    },
    "Employees": {
      "PermissionsFromMetadata": [{
        "Name": "%[coveo_parent.email]",
        "Type": "User"
      }]
    }
  }
}