Enrichment API

Last updated on

The Contentsquare Enrichment API is organized around REST. Our API has predictable resource-oriented URLs, accepts form-encoded request bodies, returns JSON-encoded responses, and uses standard HTTP response codes, authentication, and verbs.

Not a developer? Contact your CSM. They will direct you to the best solution to meet your data needs.

  • Base URL of the API:
  • Current Version of the API: 1.0

What is Contentsquare?

Contentsquare is a next-gen Analytics tool that helps you understand how and why your users are interacting with your app, mobile and website.

What this API is about

Contentsquare relies on a web tracking tag or mobile SDK to track session-based data. By session we mean a user's visit on a website or app.

This API allows for enriching the behavioural data tracked by Contentsquare client-side, with other session-based data that can be sent server-side.

For example, you can start reconciling offline and online journeys by enriching web sessions data with phoning data for calls that were triggered from those sessions. As Contentsquare cannot access phone call data during a web session via its tag or SDK, the related data must be sent to Contentsquare server-side, once the calls are ended and processed. In Contentsquare, you can then create user segments based on this phoning data and start answering questions like: "how does a specific journey on my website impact my conversion on the phone?", or "How do users who end up making a qualitative call behave on my website?"

How it works: an overview

Making an integration based on the Enrichment API up and running goes through the following steps:

  1. As a starting point, the Provider provides an integration schema to Contentsquare and gets listed in the Contentsquare integrations catalog
  2. Customers install the integration and provides the Provider with the generated Contentsquare OAuth credentials (client_id/client_secret)
  3. During web sessions, the Provider pulls Contentsquare session information (project ID, session ID) that will be used by Contentsquare to match the data received server-side
  4. The Provider can then send enrichment data batches:
    1. The Provider authenticates with the OAuth credentials provided by the customer, and receives both a JWT access token valid for 1 hour and the dynamic base URL of the enrichment endpoint (that depends on the cloud the target project is installed on)
    2. The Provider sends the data to the enrichment endpoint with a valid JWT access token

And here is a diagram summarizing the detailed interactions involved in the authentication flow for an integration based on the integration API:

Enrichment API Authentication Flow Diagram

We will detail each step in the following sections.



A provider is the entity (usually a technology partner of Contentsquare) that will send data enrichments to Contentsquare.

A provider will create integrations in order to be able to send data to Contentsquare.


An integration is created by a Provider to declare what data will be sent to Contentsquare. It is represented by a data schema provided by the Provider, in the form of a JSON object.

When sending data to Contentsquare, the authentication token used will identify a specific integration and Contentsquare will check that enrichments abide by the integration schema.

An integration can have multiple integration versions.

When a customer activates an integration on their Contentsquare project, it creates an "instance" of the integration identified by a unique integrationId (this integration ID is important and must be provided to the authentication endpoint)

Integration version

An integration can have multiple schema versions, to allow for updating and versioning an integration while avoiding to break enrichments flows relying on a previous schema.

See the dedicated section to see how to manage an integration schema update.


An enrichment is a data instance that matches an integration schema. It is the data sent by the provider to enrich Contentsquare sessions.

If an enrichment does not meet the specified integration version schema, it will be rejected.

As several enrichments can be sent to enrich the same Contentsquare session, each enrichment for a specific session is indexed with an enrichment number.

Enrichment number

Each new enrichment for a specific session is indexed to be differentiated from the previous enrichments received for the same session.

Currently, no more than 3 enrichments can be sent per session, so enrichments will be indexed with a number from 1 to 3 included. The enrichment number should be specified by the provided but if not, it will be considered as being 1 by default.

The enrichment number can be used to update an existing enrichment: if for a session, an enrichment is pushed with the same index as a existing enrichment, it will get updated with the last enrichment received.

See the dedicated section to see how to manage an enrichment update.

Enrichment field

An enrichment field is a specific key in an enrichments data object.

Enrichment batch

An enrichment batch is a collection of enrichments, in the form of an array of JSON objects. Enrichments are sent in batch to the Enrichment API endpoint. Of course, nothing prevents the Provider from sending a batch of one enrichment only.

For security purposes, if an enrichment gets rejected, the full batch will be rejected.


A session is a visit of a user on a website or mobile app. The purpose of the Enrichment API is to enrich Contentsquare sessions data.

Creating an integration

Get in touch with your Contentsquare contact to provide the required information.

You will need to provide:

  • A data schema (in the form of a JSON object): see below
  • A name, logo and description of what the integration does and related use cases to be listed in the Contentsquare integrations catalog.

Schema format

  "fields": [
    // the list of fields
      "name": "FIELD_NAME_1", // max 50 bytes
      "type": "STRING", // either "DATETIME", "INT", "FLOAT", "STRING" or "BOOL"
      "optional": true, // either true or false to make this field optional or not
      "label": "Field 1", // a business name that can be used in user interfaces
      "description": "A first field" // a business description that can be displayed in documentation pages and user interfaces
      "name": "FIELD_NAME_2",
      "type": "INT",
      "optional": false,
      "label": "Field 2",
      "description": "Another field"

Data types

An enrichment field can be of one of the following types:

  • "STRING":
    • Min length: 0
    • Max length: 50 bytes
  • "INT":
    • Min integer: -2147483648
    • Max integer: 2147483647
  • "FLOAT":
    • Min float: -1.79769e+308
    • Min float: 1.79769eE+308
  • "BOOL":
    • Boolean values: true / false
    • Format: YYYY-MM-DDThh:mm:ssZ, e.g. "2022-07-26T14:47:35Z"


  • A schema cannot include more than 10 fields of each type (so there can be up to 10 strings, 10 integers, 10 booleans etc.)
  • Key names length is limited to 30 bytes
  • Strings are limited to 50 bytes


An example schema for a Provider sending phone call data could look like this:

  "fields": [
      "name": "answered",
      "type": "BOOL",
      "optional": true,
      "label": "Call answered",
      "description": "Whether the call was answered (true) or not (false)"
      "name": "call_duration",
      "type": "INT",
      "optional": false,
      "label": "Call duration",
      "description": "The call duration in milliseconds"
      "name": "call_client_rating",
      "type": "FLOAT",
      "optional": true,
      "label": "Client rating",
      "description": "The call rating left by the client after the call if any"
      "name": "call_center_name",
      "type": "STRING",
      "optional": false,
      "label": "Call center name",
      "description": "The name of the call center that made the call"
      "name": "call_datetime",
      "type": "DATETIME",
      "optional": false,
      "label": "Call date and time",
      "description": "The date and time at which the call started"

Installing an integration

Once an integration has been created by a Provider and is available in the Contentsquare integrations catalog, from there customers can install the integration.

When they go through the installation flow, customers are provided with a project ID and OAuth credentials (a pair client_id / client_secret) in the Contentsquare UI. Those 2 elements have to be provided to the technology partner so that the latter can know which project to send data for, and how to authenticate.

Retrieving Contentsquare session identifiers from the customer's website

Once an integration has been installed, the Provider should start collecting Contentsquare session identifiers during web visits on the common customer's website. These identifiers will be used to attach the enrichment data to the right Contentsquare sessions when data will be received from the Provider.

Those identifiers are:

  • The project ID: identifies the Contentsquare project ID where the data is stored
  • The user ID: identifies the Contentsquare anonymous user ID for the user visiting the website
  • The session number: identifies a specific session (as an ordered index) of the user ID (e.g. if Contentsquare has tracked 4 different sessions of the same anonymous user, the last session number will be 4)

How to get those Contentsquare session identifiers?

During a visit on a website, you can interact with Contentsquare’s tag to pull those identifiers via the afterPageView command (see the detailed documentation here). A JavaScript code using that command should look like this:

const yourCallback = (context) => {
  const projectId = context.projectId;
  const [userId, sessionNumber] = context.sessionKey.split(".");
  // store these Contentsquare session identifiers in your backend
window._uxa = window._uxa || [];
_uxa.push(["afterPageView", yourCallback]);

By calling this function you will get the project ID, user ID and session number of each session that are required to identify the Contentsquare sessions to be enriched.

Sending enrichment data batches to Contentsquare

Once the Provider has collected the required Contentsquare session identifiers, they can start enriching the Contentsquare data with their own data.

Sending a batch of enrichment data falls into 2 steps:

  • Authenticating and retrieving the right enrichment endpoint dynamically
  • Sending the enrichment data to this endpoint with a valid JWT



The Contentsquare APIs use the server-to-server OAuth 2.0 standard for authentication, also know as 2-legged OAuth or OAuth 2LO.

The flow basically consists in calling an authentication endpoint with a pair client_id / client_secret to retrieve an access token that remains valid for 1 hour. This JWT token should then be used as a Bearer token in the headers of your HTTPS requests (in the form Authorization: Bearer YOUR_API_KEY).

Note that the API call to the authentication endpoint will also dynamically return the right base URL that you must use. This base URL depends on which cloud the target project is installed on.

You can refer below to a detailed example of the overall flow to retrieve a token and a base URL, and use those to make query the Metrics API.

You can generate a pair client_id / client_secret from the Contentsquare console, as a Contentsquare administrator. You can find how to generate these credentials in our Help Center documentation.

You can create OAuth credentials either:

  • At the Project level, to request access resources from a specific project only
  • At the Account level: to request access for any project of the account

Refresh your access token

Once you get a JWT access token (see the authentication endpoint below), it's valid for 1 hour. If you try to query the Contentsquare APIs with an access token that has expired, you will receive a 401 Unauthorized error with the error code JWT_EXPIRED, in the form:

  "success": false,
  "errorMessage": "Auth token is expired.",
  "errorCode": "JWT_EXPIRED"

In that case, you should first use your OAuth credentials (your pair client_id / client_secret) to query a new access token. The OAuth credentials don't expire.

Authentication endpoint

POST https://api.contentsquare.com/v1/oauth/token


These parameters have to be provided in the body of the request.


Required. The OAuth client_id generated from the Contentsquare console


Required. The OAuth client_secret generated from the Contentsquare console


Required. Always set it to "client_credentials", as required by the OAuth 2.0 standard


Required. It must be "enrichment".

Note that the enrichment scope cannot be combined with any other scope (e.g. you cannot get an access token with the "enrichment metrics" scope, you will get an error).


Required. The integration ID generated by Contentsquare when the customer creates the integration and that the customer must provide to the Provider.

Request example
curl --location 'https://api.contentsquare.com/v1/oauth/token' \
--header 'Content-Type: application/json' \
--data '{
    "client_id": "c3133d76-a768-4f5a-XXX",
    "client_secret": "0ISL0DEC;UyYKB;riWRS0EXXX",
    "grant_type": "client_credentials",
    "scope": "enrichment",
    "integration_id": 42
Response example
  "access_token": "eyJhbGciOiJSIsImtpY5MTXXX.CNTcKWAUb2mTp2cZyiDRYYOtGCKXXX", // to be used as bearer token to query the APIs
  "token_type": "bearer",
  "expires_in": 3600,
  "scope": "enrichment",
  "integration_id": 42,
  "project_id": 123,
  "endpoint": "https://api.eu-west-1.production.contentsquare.com" // this is the base URL you should use to query the Metrics API endpoints - the providded URL depends on the cloud the project is installed on

Example of authentication flow

Below is a sample of JavaScript code to show a complete API call flow that first retrieves an access token and then use it to retrieve the list of segments on a project:

const clientId = "<your_client_id>";
const clientSecret = "<your_client_secret>";
const authEndpoint = "https://api.contentsquare.com/v1/oauth/token";
const authRequestOptions = {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    client_id: clientId,
    client_secret: clientSecret,
    grant_type: "client_credentials",
    integration_id: 42,
    scope: "enrichment",
const authResponse = await fetch(authEndpoint, authRequestOptions);
const authJsonData = await authResponse.json();
// Below are the access token and base URL that must be used to query the Metrics API endpoints
const accessToken = authJsonData.access_token;
const baseURL = authJsonData.endpoint;
// Using the access token and base URL to query the Metrics API endpoints and get the segments in this example
const metricsApiEndpointResponse = await fetch(`${baseURL}/v1/segments`, {
  headers: { Authorization: `Bearer ${accessToken}` },
const metricsApiEndpointauthJsonData = await metricsApiEndpointResponse.json();
const segments = metricsApiEndpointauthJsonData.payload;

Sending data to the enrichment endpoint


  • Step 3: the Provider must have the knowledge of which Contentsquare project ID and sessions the data will enrich
  • Step 4.1: the Provider must have a valid JWT and base URL for the enrichment endpoint
  • All the enrichments of a batch sent to the enrichment endpoint have to match the schema version of the integration provided in the request (if an enrichment gets rejected, then the full batch will be rejected)

HTTP Request

[tab] Request
  • Endpoint (returned by the authentication call in step 4.1):
  • Method: POST
  • Header: Authorization: Bearer {JWT access token}
  • Body:
  "integrationVersion": 1, // required, provided by Contentsquare when creating a new schema
  "projectId": 1, // retrieved in step 3
  "enrichments": [
      "userId": "{USER_ID}", // string, retrieved in step 3
      "sessionNumber": {SESSION_NUMBER}, // integer, retrieved in step 3
      "enrichmentNumber": 1, // integer, max 3, optional (will be 1 if not specified)
      "enrichment": {
        "field1": "Some string",
        "field2": 42,
        "field3": 3.14,
        "field4": "2022-03-23T00:10:30Z",
        "field5": true
  • integrationVersion: a schema version for the integration must be specified so that Contentsquare can know which schema the data must match. Every time a new schema is created, Contentsquare provides the provider with a new integration version. The Provider must take care of sending data that match the right schema version. If the Provider has only one schema registered, then the integrationVersion should remain 1 by default.
  • enrichmentNumber: as a Contentsquare session can be enriched with up to 3 enrichments, each enrichment must be indexed so that it can potentially be updated later (see the dedicated section on how to update an enrichment). Index should start at 1 and can be max 3. If no enrichment number is specified by the Provider, it will be considered as 1 by default (meaning that if the Provider never specifies any enrichment number, any new enrichment for a session will overwrite the previous one and there will be only 1 enrichment per session - with index 1)
[tab] Response

Success 200

(Empty body)

[tab] Errors
Unauthorized: 401: invalid JWT token
  "message": "Unauthorized"
Bad request 400: data validation failed
  "message": "enrichments don't match expected payload"
Bad request 400: bad integration version
  "message": "bad integration version"


[tab] Request
curl --location --request POST 'https://enrichment-api.ba.contentsquare.com/v1/enrichments' \
--header 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IktJRCJ9.eyJpc3MiOiJlbnJpY2htZW50SW50ZWdyYXRpb24iLCJpYXQiOiJJQVQiLCJleHAiOiJFWFAiLCJ2ZXJzaW9uIjoiMSIsInByb2plY3RJZCI6MTYyLCJpbnRlZ3JhdGlvbklkIjoxMDB9' \
--data-raw '{
    "integrationVersion": 1,
    "projectId": 162,
    "enrichments": [
            "userId": "aaa-aaa-aaa",
            "sessionNumber": 5,
            "enrichmentNumber": 1,
            "enrichment": {
                "has_called": true,
                "call_duration": 3532,
                "call_client_rating": 4.5,
                "call_center_name": "RENNES",
                "call_date": "2022-01-01T20:02:22Z"
            "userId": "aaa-aaa-aaa",
            "sessionNumber": 5,
            "enrichmentNumber": 2,
            "enrichment": {
                "has_called": true,
                "call_duration": 2293,
                "call_client_rating": 2,
                "call_center_name": "RENNES",
                "call_date": "2022-01-01T18:09:54"
[tab] Response

Success 200


  • EnrichmentNumber:
    • Min: 1
    • Max: 3
  • Number of enrichments per batch: max 200
  • Sessions that started more than 7 days ago cannot be enriched (enrichment for those sessions will not be rejected but no data will be available in the Contentsquare platform in the end)

Update an integration schema

If the Provider wants to update the schema of an integration, it can be done thanks to the integrationVersion key. By incrementing the version, the provider can decide to add, delete or edit keys of the data schema while protecting enrichment flows that may prevail based on a previous schema.

Enrichments batches should specify the integrationVersion so that the data is compared to the right schema.


In a scenario where a Provider wants to update its integration to add new enrichment fields, the provider can:

  • Send to Contentsquare a new integration version to be registered
  • While Contentsquare is reviewing and registering the new schema, enrichments can still be sent on the previous schema
  • When the new schema is registered eventually, the Provider can switch to the new schema for all new enrichment by the specifying the right version in the enrichment batches
  • Potentially some customers could still decide to rely on the previous schema if needed (then the Provider would need to keep a mapping of which customer relies on which version)

Update an enrichment

If the Provider wants to update a specific enrichment, it can be done thanks to the enrichmentNumber key.

While incrementing this key represents a whole new "event" for the target session, sending an enrichment with an enrichment number already used for that session will overwrite the enrichment that was sent previously with the same enrichment number.

This is useful to update the data that was sent previously based on some new information the Provider processed for the same event.


In a scenario where the Provider is a company that tracks phone calls, it might happen that some data related to the call gets processed after the original enrichment for this call was sent (e.g. a conversion occurred following the call but was not materialized yet the first time the call data was sent to Contentsquare).

In such a case, as it's still related to the same phone call, the Provider can update the enrichment later instead of sending a whole new enrichment.