NAV
shell ruby javascript

SaleMove API

SaleMove provides a robust set of APIs that allow for two-way data integrations with the SaleMove platform via secure REST API calls. This documentation provides information and examples for each of the available APIs delivered by SaleMove. These APIs allow clients to create integrations for areas of the platform such as Visitors, Operators, Engagements, Statistics, and Single Sign On. The APIs allow clients to keep SaleMove synchronized with their systems of record with minimal development effort.

This documentation is for SaleMove API v1 and includes example responses for each API method illustrating the attributes returned by that method. If you have any issues, requests or concerns with the documentation please contact our Customer Support team at support@salemove.com.

Current Version

Accept: application/vnd.salemove.v1+json

The current API version is v1 and it must be explicitly requested via the Accept header.

Schema

HTTP/1.1 200 OK
Date: Thu, 29 Jan 2015 11:44:37 GMT
Status: 200 OK
Connection: close
Content-Type: text/html;charset=utf-8
Access-Control-Allow-Origin: https://salemove.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS, PATCH
Access-Control-Allow-Headers: *, Content-Type, Accept, AUTHORIZATION, Cache-Control, X-Salemove-Visit-Session-Id
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 1728000
Access-Control-Expose-Headers: Cache-Control, Content-Language, Content-Type, Expires, Last-Modified, Pragma
Content-Length: 0
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
YYYY-MM-DDTHH:MM:SSZ

All API access is over HTTPS and accessed from the https://api.salemove.com endpoint. All data is sent and received as JSON. The only supported cryptographic protocol is TLS 1.2.

Blank fields are included as null instead of being omitted.

All timestamps use the ISO 8601 format.

Parameters

Many API methods take optional parameters. For GET requests, any parameters not specified as part of the path can be passed as an HTTP query string parameter. For POST, PATCH, PUT, and DELETE requests, parameters not included in the URL should be encoded as JSON with a content-type of application/json.

Client Errors

HTTP/1.1 400 400
[
  {
    "error": "BadRequest",
    "message": "Invalid api version used",
    "debug_message": "Invalid api version used. Make sure you set the 'Accept' header with API version e.g. 'application/vnd.salemove.v1+json'"
  }
]

If the request is malformed, then the server responds with an error. The response contains a description of the error. In general, the response includes two attributes: namely, error which contains a short description of the error encountered; and a debug_message which contains a more detailed explanation of the error.

HTTP Verbs

Where possible, the SaleMove APIs strive to use appropriate HTTP verbs for each action.

Verbs Description
HEAD Can be issued against any resource to get just the HTTP header info.
GET Used for retrieving resources.
POST Used for creating resources.
PATCH Used for updating resources with partial JSON data. For instance, an Issue resource has title and body attributes. A PATCH request may accept one or more of the attributes to update the resource. PATCH is a relatively new and uncommon HTTP verb, so resource endpoints also accept POST requests.
PUT Used for replacing resources or collections. For PUT requests with no body attribute, be sure to set the Content-Length header to zero.
DELETE Used for deleting resources.

Headers

  curl --request GET \
    --header "Authorization: Token $token" \
    --header "Accept: application/vnd.salemove.v1+json" \
    "https://api.salemove.com/operators"
$.ajax({
  type: 'GET',
  url: 'https://api.salemove.com/engagements',
  headers: {
    'Accept': 'application/vnd.salemove.v1+json',
    'Authorization': 'Token $token'
  },
  success: function(response){
    ajaxResponse = response;
  }
});

Along with the request, the following headers must be sent:

Header Description
Accept Specifies the response format and the API version. See Accept for more information.
Authorization API token for Operator or session ID for Visitor. See Authorization for more information.

Authorization

Operators must specify their API Token in the Authorization header. The API tokens are provided by the Site success manager.

curl --request GET \
  --header "Authorization: Token $api_token" \
  --header "Accept: application/vnd.salemove.v1+json" \
  "https://api.salemove.com/operators?site_ids[]=$site_id&include_offline=false"

Visitors must specify their access token in the Authorization header. This header can be acquired using either JS API or REST API when creating a new Site Visitor.

curl --request GET \
  --header "Authorization: Bearer $access_token" \
  --header "Accept: application/vnd.salemove.v1+json" \
  "https://api.salemove.com/visitor/visit"

Accept

Unless otherwise specified, all endpoints require Accept: application/vnd.salemove.v1+json header.

Value Description
application/vnd.salemove.v$version+json Specifies the API version for JSON response. For the version 1 of the API the header value is application/vnd.salemove.v1+json
application/$content_type Specifies the returned content type. Possible values for $content_type are described under specific endpoints

Cross Origin Resource Sharing

The API supports Cross Origin Resource Sharing (CORS) for AJAX requests from any origin. More information about CORS is available in the CORS W3C Recommendation and in the intro to the HTML 5 Security Guide.

Pagination

GET /operators

Generates the output

[
  {
    "next_page" : "http://api.salemove.com/operators?page=2",
    "last_page" : "http://api.salemove.com/operators?page=3",
    "collection" : [
      {
        "href" : "http://api.salemove.com/operators/f42811bc-8519-4d33-bbb1-36d4555ecb0a",
        "attribute" : "value",
        "..." : "..."
      },
      {
        "href" : "http://api.salemove.com/operators/c8b52f0b-ad05-4c71-8c98-5056f07c4d1a",
        "attribute" : "value",
        "..." : "..."
      },
    ]
  }
]

Some requests that return a large collection of items are paginated. The following parameters are supported:

Parameter Type Description
page number Requests a specific page.
per_page number Sets the quantity of items returned with each page.
Minimum value is 1,
maximum value is 100,
default value is 30.
order string Supported values are asc or desc.

For example, to fetch the second page of the Operators which the Token in the query is authorized to view, the parameter page should be set to a value of 2 (page=2) as shown below.

GET /operators?page=2

The responses for collections that are paginated include an attribute next_page that points to the next page of items for the collection. In addition, the response includes a last_page attribute that points to the last page of the collection.

Operators

Create a New Operator

curl --request POST \
    --header "Authorization: Token $token" \
    --header "Content-Type: application/json" \
    --header "Accept: application/vnd.salemove.v1+json" \
    --data-binary '{
      "name": "Jared Grey",
      "email": "jared@institution.com",
      "phone": "+19174743334", // must be E.164 format
      "password": "password",
      "password_confirmation": "password",
      "picture_data": "data:image/png;base64,[Base64 encoded image]",
      "assignments": [
        {
          "site_id": "$site_id"
        }
      ]
    }' \
    "https://api.salemove.com/operators"
require 'httparty'

ENDPOINT = 'https://api.salemove.com/operators'

token = ARGV[0].strip
site_id = ARGV[1].strip

headers = {
  :authorization => "Token #{token}",
  :content_type => "application/json",
  :accept => "application/vnd.salemove.v1+json"
}

options = {
  headers: headers,
  query: {
    "name": "Jared Grey",
    "email": "jared@institution.com",
    "phone": "+19174743334",
    "password": "password",
    "password_confirmation": "password",
    "assignments": [
      "site_id": "#{site_id}"
    ]
  }
}

raw_response = HTTParty.post(
  ENDPOINT,
  options
)

response = JSON.parse raw_response.body

puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('POST','https://api.salemove.com/operators',false);

xhr.setRequestHeader('authorization','Token $token');
xhr.setRequestHeader('content-type','application/json');
xhr.setRequestHeader('accept','application/vnd.salemove.v1+json');

var data = {
  "name": "Jared Grey",
  "email": "jared@institution.com",
  "phone": "+19174743334",
  "password": "password",
  "password_confirmation": "password",
  "assignments": [
    {
      "site_id": "$site_id"
    }
  ]
};

var query = JSON.stringify(data);

xhr.send(query);

var response = JSON.parse(xhr.responseText);

console.log(response);

Generates the output

{
  "href": "https://api.salemove.com/operators/f42811bc-8519-4d33-bbb1-36d4555ecb0a",
  "id": "f42811bc-8519-4d33-bbb1-36d4555ecb0a",
  "name": "Jared Grey",
  "email": "jared.grey@institution.com",
  "available": true,
  "enabled": true,
  "available_media_types": [],
  "max_engagement_count": null,
  "multi_engagement_default_availability": null,
  "visible_in_operator_editor": true,
  "engagements": [],
  "engagement_requests": [],
  "role": "operator",
  "picture":
  {
    "url": "https://uploads.salemove.com/user_assets/operator-1-jared-f42811bc-8519-4d33-bbb1-36d4555ecb0a.jpg"
  },
  "phone": "+19174743334",
  "teams": [
    {"id": "00535468-76d2-438b-bea7-ed9f91c234dc", "name": "General", "site_id": "7d5635b0-88ed-4109-8398-dcd151754640"}
  ]
}

Action: POST /operators

Creates a new Operator. The following parameters can be sent along with this request:

Parameter Type Description
name string The name of the Operator.
email string The email of the Operator. It must be unique.
phone string The phone of the Operator. The supported format is E.164 Format
password string The password of the Operator.
password_confirmation string The password of the Operator. The value of the fields password and password_confirmation must be identical.
picture_data string The Operator’s picture in base 64 format.
assignments array An array of site_ids that will be assigned to the Operator.
max_engagement_count integer Maximum number of conccurent Engagements allowed for this Operator. If omitted, minimum allowed Engagement count from assigned Sites configuration will be used.
multi_engagement_default_availability string Availability behaviour when Operator engages and multi-Engagement is allowed. Allowed values are ‘unavailable’ - Operator is set to be unavailable, 'chat’ - Operator availability is set to chat media, 'retain’ - previous availability is retained. If omitted, value from the assigned Site configuration will be used.

List Operators

curl --request GET \
    --header "Authorization: Token $token" \
    --header "Accept: application/vnd.salemove.v1+json" \
    "https://api.salemove.com/operators?page=1"
require 'httparty'

ENDPOINT = 'https://api.salemove.com/operators'

token = ARGV[0].strip

headers = {
  :authorization => "Token #{token}",
  :accept => "application/vnd.salemove.v1+json"
}

raw_response = HTTParty.get(
  ENDPOINT,
  headers: headers
)

response = JSON.parse raw_response.body

puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

function getOperators(url) {
  var xhr = new XMLHttpRequest();

  xhr.open('GET',url,false);

  xhr.setRequestHeader('authorization','Token $token');
  xhr.setRequestHeader('accept','application/vnd.salemove.v1+json');

  xhr.send();

  var response = JSON.parse(xhr.responseText);

  console.log(response);
};

for (page = 1; page <= $last_page; page++) {
  var url = "https://api.salemove.com/operators?page=" + page;
  getOperators(url);
};

Generates the output

{
  "last_page": "https://api.salemove.com/operators?page=1",
  "operators":
  [
    {
      "id": "f42811bc-8519-4d33-bbb1-36d4555ecb0a",
      "href": "https://api.salemove.com/operators/f42811bc-8519-4d33-bbb1-36d4555ecb0a",
      "name": "Jared Grey",
      "email": "jared.grey@institution.com",
      "available": true,
      "enabled": true,
      "role": "operator",
      "picture": {
        "url": "https://uploads.salemove.com/user_assets/salemove_com-salemove_models_operator-6036d2ae-6c97-4555-83a2-bc8006b9acc8-jared_grey-f42811bc-8519-4d33-bbb1-36d4555ecb0a.png"
      },
      "phone": "+19174743334",
      "available_media_types": ["video", "audio", "chat"],
      "engaged_since": "2017-02-20T00:00:00Z",
      "engagements": [{
        "id": "eea868ad-9d58-4db9-a663-5fd766728980",
        "site_id": "7d5635b0-88ed-4109-8398-dcd151754640",
        "visitor_id": "1e1315aa-630e-4a13-a64b-1cdb034d3e0e",
        "operator_id": "f42811bc-8519-4d33-bbb1-36d4555ecb0a",
        "started_at": "2017-02-20T00:00:00Z",
        "audio_used": true,
        "video_used": false
      }],
      "engagement_requests": [
        {
          "visitor_id": "02cebb3a-7f7d-4be8-9445-911daa26ac1f",
          "site_id": "7d5635b0-88ed-4109-8398-dcd151754640",
          "created_at": "2017-02-20T00:00:00Z"
        },
        {
          "visitor_id": "45b595ae-48c3-401d-ae16-89ea1ab80119",
          "site_id": "7d5635b0-88ed-4109-8398-dcd151754640",
          "created_at": "2017-02-20T00:01:00Z"
        }
      ]
    },
    {
      "id": "c8b52f0b-ad05-4c71-8c98-5056f07c4d1a",
      "href": "https://api.salemove.com/operators/c8b52f0b-ad05-4c71-8c98-5056f07c4d1a",
      "name": "Jordan Green",
      "email": "jordan.green@institution.com",
      "available": false,
      "enabled": true,
      "role": "operator",
      "picture": {
        "url": "https://uploads.salemove.com/user_assets/salemove_com-salemove_models_operator-c4ef4812-91e3-42cf-88d2-1f5bbbf144fd-jordan_green-c8b52f0b-ad05-4c71-8c98-5056f07c4d1a.jpg"
      },
      "phone": "+13236654111",
      "unavailability_reason": "offline",
      "unavailable_since": "2017-02-20T00:00:00Z",
      "available_media_types": [],
      "engagements": [],
      "engagement_requests": []
    }
  ]
}

Action: GET /operators

Lists all Operators which are visible to the caller given associated Sites and permissions. Please note that for this endpoint, pagination is used.

Parameter Type Description
include_engagements boolean If true, fetches data for engagements, engagement_requests and engaged_since. The default value is false.
include_disabled boolean If true, includes Operators that have been disabled. The default value is false.
include_offline boolean If true, includes Operators that are offline. The default value is true.
include_support boolean If true, includes Operators from SaleMove support staff. The default value is true.
site_ids array Only Operators from the specified Sites will be included in the response. Operators from all Sites will be included if this option is not specified.
team_ids array Only Operators from the specified Teams will be included in the response. Operators from all Teams will be included if this option is not specified.

Get Operator

curl --request GET \
    --header "Authorization: Token $token" \
    --header "Accept: application/vnd.salemove.v1+json" \
    "https://api.salemove.com/operators/$operator_id"
require 'httparty'

ENDPOINT = 'https://api.salemove.com/operators'

token = ARGV[0].strip
operator_id= ARGV[1].strip

headers = {
  :authorization => "Token #{token}",
  :accept => "application/vnd.salemove.v1+json"
}

raw_response = HTTParty.get(
  "#{ENDPOINT}/#{operator_id}",
  headers: headers
)

response = JSON.parse raw_response.body

puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('GET','https://api.salemove.com/operators/$operator_id', false);

xhr.setRequestHeader('authorization','Token $token');
xhr.setRequestHeader('accept','application/vnd.salemove.v1+json');

xhr.send();

var response = JSON.parse(xhr.responseText);

console.log(response);

Generates the Output

{
  "id": "f42811bc-8519-4d33-bbb1-36d4555ecb0a",
  "href": "https://api.salemove.com/operators/f42811bc-8519-4d33-bbb1-36d4555ecb0a",
  "name": "Jared Grey",
  "email": "jared.grey@institution.com",
  "available": false,
  "enabled": true,
  "role": "operator",
  "picture":
  {
    "url": "https://uploads.salemove.com/user_assets/salemove_com-salemove_models_operator-6036d2ae-6c97-4555-83a2-bc8006b9acc8-jared_grey-f42811bc-8519-4d33-bbb1-36d4555ecb0a.png"
  },
  "phone": "+19174743334",
  "available_media_types": ["video", "audio", "chat"],
  "engaged_since": "2017-02-20T00:00:00Z",
  "engagements": [{
    "id": "eea868ad-9d58-4db9-a663-5fd766728980",
    "site_id": "7d5635b0-88ed-4109-8398-dcd151754640",
    "visitor_id": "1e1315aa-630e-4a13-a64b-1cdb034d3e0e",
    "operator_id": "f42811bc-8519-4d33-bbb1-36d4555ecb0a",
    "started_at": "2017-02-20T00:00:00Z",
    "audio_used": true,
    "video_used": false
  }],
  "engagement_requests": [
    {
      "visitor_id": "1b23830d-2aa9-4340-9712-bf23daf4f28e",
      "site_id": "7d5635b0-88ed-4109-8398-dcd151754640",
      "created_at": "2017-02-20T00:00:00Z"
    },
    {
      "visitor_id": "00d8bf30-6412-45f8-b2ad-87ed7719a5d7",
      "site_id": "7d5635b0-88ed-4109-8398-dcd151754640",
      "created_at": "2017-02-20T00:01:00Z"
    }
  ],
  "teams": [
    {"id": "00535468-76d2-438b-bea7-ed9f91c234dc", "name": "General", "site_id": "7d5635b0-88ed-4109-8398-dcd151754640"}
  ]
}

Action: GET /operators/{operator_id}

Fetches an Operator configuration. The caller must have admin privileges on the Operator that is being requested.

Output

Field Type Required Description
id string Yes Operator ID.
href string Yes URI for the Operator.
name string Yes Operator name.
email string Yes Operator email.
available boolean Yes Whether Operator is available or not.
enabled boolean Yes true, if Operator is not disabled.
role string Yes Operator role. Can be one of operator, manager, super_manager.
picture object Yes Operator picture. See Picture.
phone string Yes Operator phone number.
unavailability_reason string No Operator unavailability reason.
unavailable_since string No An ISO-8601 timestamp of when the Operator first went unavailable. Changing the unavailable status from one to another does not reset this.
available_media_types array Yes A list of media types Operator is available for. Can contain video, audio, chat.
engaged_since string No An ISO-8601 timestamp of when the Operator first started an engagement. In case of multiple Engagements, this is the start time of the first Engagement even if the first Engagement has ended. When Operator is not engaged, this field will not be present.
engagements array Yes A list of ongoing Engagements. See Engagements.
engagement_requests array Yes A list of ongoing Engagement Requests. See Engagement Requests.
max_engagement_count integer No Maximum concurrent Engagement count allowed for the Operator.
multi_engagement_default_availability string No Availability behaviour when Operator uses multi-Engagement.

Picture

Field Type Required Description
url string Yes URL of the current Operator picture. null if no picture is currently set.

Engagements

Field Type Required Description
id string Yes Engagement ID.
started_at string Yes An ISO-8601 timestamp of when the Engagement started.
audio_used boolean Yes true, if audio is used in the Engagement.
video_used boolean Yes true, if video is used in the Engagement.

Engagement Requests

Field Type Required Description
site_id string Yes ID of the Engagement Request Site.
visitor_id string Yes ID of the Visitor.
created_at string Yes An ISO-8601 timestamp of when the Engagement Request was created.

Update an Operator

curl --request POST \
    --header "Authorization: Token $token" \
    --header "Content-Type: application/json" \
    --header "Accept: application/vnd.salemove.v1+json" \
    --data-binary '{
      "name": "Jared H. Grey",
      "role": "manager",
      "assignments": [
        {
          "site_id": "$site_id"
        }
      ]
    }' \
    "https://api.salemove.com/operators/$operator_id"
require 'httparty'

ENDPOINT = 'https://api.salemove.com/operators'

token = ARGV[0].strip
operator_id = ARGV[1].strip
values = {
  "name": "Jared H. Grey",
  "role": "manager",
  "assignments": [
    {
      "site_id": "$site_id"
    }
  ]
}

headers = {
  :authorization => "Token #{token}",
  :content_type => "application/json",
  :accept => "application/vnd.salemove.v1+json"
}

options = {
  headers: headers,
  query: values
}

raw_response = HTTParty.post(
  "#{ENDPOINT}/#{operator_id}",
  options
)

response = JSON.parse raw_response.body

puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('POST','https://api.salemove.com/operators/$operator_id',false);

xhr.setRequestHeader('authorization','Token $token');
xhr.setRequestHeader('content-type','application/json');
xhr.setRequestHeader('accept','application/vnd.salemove.v1+json');

var data = {
  "name": "Jared H. Grey",
  "role": "manager",
  "assignments": [
    {
      "site_id": "$site_id"
    }
  ]
};

var query = JSON.stringify(data);

xhr.send(query);

var response = xhr.responseText;

console.log(response);

Generates the Output

{
  "href": "https://api.salemove.com/operators/f42811bc-8519-4d33-bbb1-36d4555ecb0a",
  "id": "f42811bc-8519-4d33-bbb1-36d4555ecb0a",
  "name": "Jared H. Grey",
  "email": "jared.grey@institution.com",
  "available": true,
  "enabled": true,
  "available_media_types": [],
  "max_engagement_count": null,
  "multi_engagement_default_availability": null,
  "visible_in_operator_editor": true,
  "engagements": [],
  "engagement_requests": [],
  "role": "manager",
  "picture":
  {
    "url": "https://uploads.salemove.com/user_assets/salemove_com-salemove_models_operator-6036d2ae-6c97-4555-83a2-bc8006b9acc8-jared_grey-f42811bc-8519-4d33-bbb1-36d4555ecb0a.png"
  },
  "phone": "+19174743334",
  "teams": [
    {"id": "00535468-76d2-438b-bea7-ed9f91c234dc", "name": "General", "site_id": "7d5635b0-88ed-4109-8398-dcd151754640"}
  ]
}

Action: POST /operators/{operator_id}

Updates Operator settings. The caller must have admin privileges on the Operator that is being updated. The following parameters can be sent along with the request:

Parameter Type Description
name string The name of the Operator.
email string The email of the Operator. It must be unique.
phone string The phone of the Operator. The supported format is E.164 Format
enabled boolean Enables (when the value of the parameter is true) or disables (when the value of the parameter is false) the Operator’s use of the platform.
available boolean Sets engagement availability. true indicates that the Operator is available for a new Engagement. false indicates that the Operator is unavailable for a new Engagement.
assignments array An array of site_ids that are assigned to the Operator. The provided array of site_ids will replace the existing assignments. The admin updating the Operator must have access to the Sites being assigned to the Operator. Specifying an empty array returns a validation error as at least one Site needs to remain assigned to the Operator being updated.
max_engagement_count integer Maximum number of conccurent Engagements allowed for this Operator. If omitted, minimum allowed Engagement count from assigned Sites configuration will be used.
multi_engagement_default_availability string Availability behaviour when Operator engages and multi-Engagement is allowed. Allowed values are 'unavailable’ - Operator is set to be unavailable, 'chat’ - Operator availability is set to chat media, 'retain’ - previous availability is retained. If omitted, value from the assigned Site configuration will be used.

Delete an Operator

curl --request DELETE \
    --header "Authorization: Token $token" \
    --header "Accept: application/vnd.salemove.v1+json" \
    "https://api.salemove.com/operators/$operator_id"
require 'httparty'

ENDPOINT = 'https://api.salemove.com/operators'

token = ARGV[0].strip
operator_id = ARGV[1].strip

headers = {
  :authorization => "Token #{token}",
  :accept => "application/vnd.salemove.v1+json"
}

raw_response = HTTParty.delete(
  "#{ENDPOINT}/#{operator_id}",
  headers: headers
)

response = JSON.parse raw_response.body

puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('DELETE','https://api.salemove.com/operators/$operator_id',false);

xhr.setRequestHeader('authorization','Token $token');
xhr.setRequestHeader('accept','application/vnd.salemove.v1+json');

xhr.send();

var response = xhr.responseText;

console.log(response);

Generates the Output


Action: DELETE /operators/{operator_id}

Disables an Operator that a manager can manage and configure.

Visitor

GET Visitor Information

Action: GET /sites/{site_id}/visitors/{visitor_id}

Fetches an identified Visitor’s information for a specific Site.

curl --request GET \
      --header "Authorization: Token $token" \
      --header "Accept: application/vnd.salemove.v1+json" \
      "https://api.salemove.com/sites/$site_id/visitors/$visitor_id"
require 'httparty'

ENDPOINT = "https://api.salemove.com/sites"

token = ARGV[0].strip
site_id = ARGV[1].strip
visitor_id = ARGV[2].strip

headers = {
  :authorization => "Token #{token}",
  :accept => 'application/vnd.salemove.v1+json'
}

raw_response = HTTParty.get(
  "#{ENDPOINT}/#{site_id}/visitors/#{visitor_id}",
  headers: headers
)

response = JSON.parse raw_response.body

puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('GET','https://api.salemove.com/sites/$site_id/visitors/$visitor_id',false);

xhr.setRequestHeader('authorization','Token $token');
xhr.setRequestHeader('accept','application/vnd.salemove.v1+json');

xhr.send();

var response = JSON.parse(xhr.responseText);

console.log(response);

Generates the Output

{
  "href":"https://api.salemove.com/sites/2e56b224-6708-4755-b6c9-35f9889e42dd/visitors/039124e6-b4e8-4a0d-b420-5b6696c7ecb4",
  "name": "Sasha Brown",
  "email": "sasha.brown@email.com",
  "phone": null,
  "note": "Looking for a new home, asked about mortgage rates",
  "custom_attributes": {},
  "id": "039124e6-b4e8-4a0d-b420-5b6696c7ecb4"
}

Current Visitor

The endpoints used to manipulate a Visitor who is currently online can only be used from the Visitor’s browser, and require a different authentication header.

The online visitor and the site the Visitor is browsing are identified from the access token.

GET Visitor Information - Current Visit

curl --request GET \
    --header "Authorization: Bearer $access_token" \
    --header "Accept: application/vnd.salemove.v1+json" \
    "https://api.salemove.com/visitor"
require 'httparty'

ENDPOINT = "https://api.salemove.com/visitor"

access_token = ARGV[0].strip

headers = {
  :authorization => "Bearer #{access_token}",
  :accept => "application/vnd.salemove.v1+json"
}

raw_response = HTTParty.get(
  ENDPOINT,
  headers: headers
)

response = JSON.parse raw_response.body

puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('GET', 'https://api.salemove.com/visitor', false);

xhr.setRequestHeader('authorization','Bearer $access_token');
xhr.setRequestHeader('accept','application/vnd.salemove.v1+json');

xhr.send();

var response = JSON.parse(xhr.responseText);

console.log(response);

Generates the Output

{
  "href": "https://api.salemove.com/visitors/039124e6-b4e8-4a0d-b420-5b6696c7ecb4",
  "name": "Sasha",
  "email": null,
  "phone": null,
  "note": "Moved to bind",
  "custom_attributes": {
    "custom_field_example": "...",
    "home_address": "Brooklyn, New York",
    "vip": "false"
  },
  "id":"039124e6-b4e8-4a0d-b420-5b6696c7ecb4"
}

Action: GET /visitor

Fetches a Visitor’s information for the Site the Visitor is currently browsing.

POST Update Information - Current Visit

curl --request POST \
    --header "Authorization: Bearer $access_token" \
    --header "Accept: application/vnd.salemove.v1+json" \
    --header "Content-Type: application/json" \
    --data-binary '{
      "name": "Sasha Brown",
      "email": "sashabrown@email.com",
      "phone": "12024561111",
      "note": "wants to refinance. completed application.",
      "custom_attributes":
        {
          "vip": "true"
        }
    }' \
    "https://api.salemove.com/visitor"
require 'httparty'

ENDPOINT = "https://api.salemove.com/visitor"

access_token = ARGV[0].strip

headers = {
  :authorization => "Bearer #{access_token}",
  :content_type => "application/json",
  :accept => "application/vnd.salemove.v1+json"
}

options = {
  headers: headers,
  query: {
    "name": "Sasha Brown",
    "email": "sashabrown8@email.com",
    "phone": "12024561111",
    "note": "wants to refinance. completed application.",
    "custom_attributes": {
      "vip": "true"
    }
  }
}

raw_response = HTTParty.post(
  ENDPOINT,
  options
)

response = JSON.parse raw_response.body

puts response
/************************************************************/
/************ Using JavaScript API (Recommended) ************/
var installSaleMove = function(callback) {
  const salemoveIntegrationScriptUrl = 'https://api.salemove.com/salemove_integration.js';
  var scriptElement = document.createElement('script');

  scriptElement.async = 1;
  scriptElement.src = salemoveIntegrationScriptUrl;
  scriptElement.type = "text/javascript";
  scriptElement.addEventListener("load", callback);

  document.body.append(scriptElement);
};

installSaleMove(function() {
  /* Updating Visitor Information */
  sm.getApi({version: 'v1'}).then(function(salemove) {
    salemove.updateInformation({
      phone: '+15559175555',
      name: 'Alice',
      email: 'alice@corp.com',
      externalId: 'EX-001',
      customAttributes: {
        policyNumber: '9392',
        region: 'east'
      }
    }).then(function() {
      console.log('Visitor information updated');
    }).catch(function(error) {
      if (error.cause == salemove.ERRORS.NETWORK_TIMEOUT) {
      }
      else {
      }
    });
  });
});

/************************************************************/
/**************** Using XHR Requests ******************/
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('POST','https://api.salemove.com/visitor',false);

xhr.setRequestHeader('authorization','Bearer $access_token');
xhr.setRequestHeader('content-type','application/json');
xhr.setRequestHeader('accept','application/vnd.salemove.v1+json');

var data = {
  "name": "Sasha Brown",
    "email": "sashabrown7@email.com",
    "phone": "12024561111",
    "note": "wants to refinance. completed application.",
    "custom_attributes": {
      "vip": "true"
    }
};

var query = JSON.stringify(data);

xhr.send(query);

var response = xhr.responseText;

console.log(query);

Generates the Output

{
  "href": "https://api.salemove.com/visitor",
  "name": "Sasha Brown",
  "email": "sashabrown@email.com",
  "phone": "12024561111",
  "note": "wants to refinance. completed application.",
  "custom_attributes": {
    "vip": "true"
  },
  "id": "039124e6-b4e8-4a0d-b420-5b6696c7ecb4"
}

Action: POST /visitor

Updates a Visitor’s information for the Site where the Visitor is currently online. Later this information is available to all the Operators observing or interacting with the Visitor. This means that this endpoint can be used to provide additional context about the Visitor to the Operators.

In case of updating the Visitor’s information from the browser it is strongly recommended to use the SaleMove JavaScript API. The method Salemove::updateInformation updates the Visitor’s information including: name, email, phone, external ID and custom attributes.

Custom attributes can be updated by sending them as key-value pairs in the request. All keys and values must be submitted as strings. (They are also returned as strings). Nested key-value pairs are not supported. The parameter with name note_update_method can take two values: replace, which replaces existing notes; and append, which adds the new note to existing notes. If this field is omitted, the value will default to replace.

The JavaScript example in this section shows two snippets. The first snippet injects SaleMove dynamically by creating a script tag with source pointing to the SaleMove Integration URL and immediately after updates the Visitor’s information using the JavaScript API (recommended). The second snippet simply makes a XHR request to update the Visitor’s information via REST.

Sites

GET Sites by Hostname

curl --request GET \
    --header "Authorization: Token $token" \
    --header "Accept: application/vnd.salemove.v1+json" \
    "https://api.salemove.com/sites?hostname=$hostname"
require 'httparty'

ENDPOINT = "https://api.salemove.com/sites"

token = ARGV[0].strip
hostname = ARGV[1].strip

headers = {
  :authorization => "Token #{token}",
  :accept => "application/vnd.salemove.v1+json"
}

raw_response = HTTParty.get(
  "#{ENDPOINT}?hostname=#{hostname}",
  headers: headers
)

response = JSON.parse raw_response.body

puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('GET','https://api.salemove.com/sites?hostname=$hostname',false);

xhr.setRequestHeader('authorization','Token $token');
xhr.setRequestHeader('accept','application/vnd.salemove.v1+json');

xhr.send();

var response = JSON.parse(xhr.responseText);

console.log(response);

Generates the output

{
  "last_page": "https://api.salemove.com/sites?hostname=company.com&page=1",
  "sites": [
    {
      "href": "https://api.salemove.com/sites/2e56b224-6708-4755-b6c9-35f9889e42dd",
      "id": "2e56b224-6708-4755-b6c9-35f9889e42dd",
      "addresses":
      [
        "company.com",
        "service.company.com",
        "company.mobi",
        "company.io"
      ]
    }
  ]
}

Action: GET /sites?hostname=$hostname

Fetches an array of Sites that have the given hostname assigned to them.

A Site can have one or more addresses, where an address is a combination of hostname + path. For example, a valid address could be salemove.com/auto where hostname=salemove.com and path=/auto.

POST New Site

curl --request POST \
    --header "Authorization: Token $token" \
    --header "Content-Type: application/json" \
    --header "Accept: application/vnd.salemove.v1+json" \
    --data-binary '{
      "name": "Institution",
      "addresses": ["institution.com","login.institution.com"]
    }' \
    "https://api.salemove.com/sites"
require 'httparty'

ENDPOINT = "https://api.salemove.com/sites"


token = ARGV[0].strip

headers = {
  :authorization => "Token #{token}",
  :content_type => "application/json",
  :accept => "application/vnd.salemove.v1+json"
}

options = {
  headers: headers,
  query: {
    "name": "Institution",
    "addresses": ["institution.com","login.institution.com"]
  }
}

raw_response = HTTParty.post(
  ENDPOINT,
  options
)

response = JSON.parse raw_response.body

puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('POST','https://api.salemove.com/sites',false);

xhr.setRequestHeader('authorization','Token $token');
xhr.setRequestHeader('content-type','application/json');
xhr.setRequestHeader('accept','application/vnd.salemove.v1+json');

var data = {
  "name": "Institution",
  "addresses": ["institution.com","login.institution.com"]
};

var query = JSON.stringify(data);

xhr.send(query);

var response = JSON.parse(xhr.responseText);

console.log(response);

Generates the output

{
  "href": "https://api.salemove.com/sites/3a5c1497-a0f8-470c-af10-c5c2b8fe88cc",
  "id": "3a5c1497-a0f8-470c-af10-c5c2b8fe88cc",
  "hostnames": ["institution.com","login.institution.com"],
  "name": "Institution",
  "salemove_enabled": false
}

Action: POST /sites

An Operator with manager privileges can use the API token associated with the account to create new Sites.

Parameter Type Required Description
name string Yes The name for the new Site.
addresses array Yes A list of the Site’s addresses.
clone_from_id string No The new Site will be configured using this site_id as a template. The new Site will copy the visuals, teams and business rules from the site_id passed in this parameter.

GET Site

curl --request GET \
    --header "Authorization: Token $token" \
    --header "Accept: application/vnd.salemove.v1+json" \
    "https://api.salemove.com/sites/$site_id"
require 'httparty'

ENDPOINT = "https://api.salemove.com/sites"

token = ARGV[0].strip
site_id = ARGV[1].strip

headers = {
  :authorization => "Token #{token}",
  :accept => "application/vnd.salemove.v1+json"
}

raw_response = HTTParty.get(
  "#{ENDPOINT}/#{site_id}",
  headers: headers
)

response = JSON.parse raw_response.body

puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('GET','https://api.salemove.com/sites/$site_id',false);

xhr.setRequestHeader('authorization','Token $token');
xhr.setRequestHeader('accept','application/vnd.salemove.v1+json');

xhr.send();

var response = JSON.parse(xhr.responseText);

console.log(response);

Generates the output

{
  "href": "https://api.salemove.com/sites/3a5c1497-a0f8-470c-af10-c5c2b8fe88cc",
  "id": "3a5c1497-a0f8-470c-af10-c5c2b8fe88cc",
  "hostnames": ["institution.com","login.institution.com"],
  "name": "Institution",
  "salemove_enabled": false,
  "map": {
    "latitude": 46.8772000,
    "longitude": 96.7898000,
    "zoom": 4
  },
  "always_use_default_operator_picture": false,
  "default_operator_picture": {
    "url": null
  },
  "logo": {
    "url": null
  }
}

Action: GET /sites/{id}

This request fetches the Site with the ID of id. The Operator whose API token is used to send the request must have access to the Site with with ID of id.

Parameter Type Required Description
id string Yes The Site id that is requested

PUT Update Site

curl --request PUT \
    --header "Authorization: Token $token" \
    --header "Content-Type: application/json" \
    --header "Accept: application/vnd.salemove.v1+json" \
    --data-binary '{
      "salemove_enabled": true,
      "addresses": ["institution.com", "login.institution.com", "m.institution.com"],
      "default_operator_picture": "data:image/png;base64,iVBORw0KGgoAAA+Mg7SGKOzewAAAABJRU5ErkJggg==",
      "logo": "data:image/png;base64,iVBORw0KGgoAAA+Mg7SGKOzewAAAABJRU5ErkJggg==",
      "map": {
        "zoom": 3
      }
    }' \
    "https://api.salemove.com/sites/$site_id"
require 'httparty'

ENDPOINT = "https://api.salemove.com/sites"

token = ARGV[0].strip
site_id = ARGV[1].strip

headers = {
  :authorization => "Token #{token}",
  :content_type => "application/json",
  :accept => "application/vnd.salemove.v1+json"
}

options = {
  headers: headers,
  query: {
    "addresses": ["institution.com", "login.institution.com", "m.institution.com"],
    "default_operator_picture": "data:image/png;base64,iVBORw0KGgoAAA+Mg7SGKOzewAAAABJRU5ErkJggg==",
    "logo": "data:image/png;base64,iVBORw0KGgoAAA+Mg7SGKOzewAAAABJRU5ErkJggg==",
    "salemove_enabled": true,
    "map": {
      "zoom": 3
    }
  }
}

raw_response = HTTParty.put(
  "#{ENDPOINT}/#{site_id}",
  options
)

response = JSON.parse raw_response.body

puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('PUT','https://api.salemove.com/sites/$site_id',false);

xhr.setRequestHeader('authorization','Token $token');
xhr.setRequestHeader('content-type','application/json');
xhr.setRequestHeader('accept','application/vnd.salemove.v1+json');

var data = {
  "salemove_enabled": false,
  "addresses": ["institution.com","login.institution.com","m.institution.com"],
  "default_operator_picture": "data:image/png;base64,iVBORw0KGgoAAA+Mg7SGKOzewAAAABJRU5ErkJggg==",
  "logo": "data:image/png;base64,iVBORw0KGgoAAA+Mg7SGKOzewAAAABJRU5ErkJggg==",
  "map": {
    "zoom": 3
  }
};

var query = JSON.stringify(data);

xhr.send(query);

var response = JSON.parse(xhr.responseText);

console.log(response);

Generates the output

{
  "href": "https://api.salemove.com/sites/3a5c1497-a0f8-470c-af10-c5c2b8fe88cc",
  "id": "2e56b224-6708-4755-b6c9-35f9889e42dd",
  "hostnames": ["institution.com", "login.institution.com", "m.institution.com"],
  "name": "Institution",
  "salemove_enabled": true,
  "map": {
    "latitude": 46.8772000,
    "longitude": 96.7898000,
    "zoom": 3
  },
  "always_use_default_operator_picture": false,
  "default_operator_picture": {
    "url": "https://uploads.salemove.com/user_assets/site-3a5c1497-a0f8-470c-af10-c5c2b8fe88cc/site_default_operator_picture-1538999078.png"
  },
  "logo": {
    "url": "https://uploads.salemove.com/user_assets/site-3a5c1497-a0f8-470c-af10-c5c2b8fe88cc/site_logo-1539074994.png"
  }
}

Action: PUT /sites/{id}

This request updates the Site with the ID of id. The Operator whose API token is used to send the request must have access to the Site with the ID of id.

Parameter Type Required Description
id string Yes The Site id that is being updated.
salemove_enabled boolean No If true then it enables SaleMove for the Site, if false it disables SaleMove for the Site. When SaleMove is enabled the SaleMove integration is delivered otherwise a 204 No-Content is delivered.
reactive_enabled boolean No If true then the Reactive Tab is shown to the Visitor. If false then the Reactive Tab is hidden from the Visitor.
name string No The Site name that is being updated.
addresses array No A list of Site’s addresses that are being updated.
map object No An object with three possible attributes latitude, longitude, zoom. Describes the platform console map center coordinate and the zoom level.
latitude float No A float defining the latitude coordinate of site’s operator map center. Latitude ranges between -90 and 90 degrees, inclusive
longitude float No A float defining the longitude coordinate of site’s operator map center. Longitude ranges between -180 and 180 degrees, inclusive.
zoom integer No An integer defining the zoom level of the site’s operator map. Zoom ranges between 1 and 18. Zoom levels 4 to 8 are recommended.
always_use_default_operator_picture boolean No Always use default operator picture instead of operator profile picture.
default_operator_picture string No The Site’s default operator picture in base 64 format. If null then the picture is deleted.
logo string No The Site’s logo in base 64 format. If null then the picture is deleted.

POST Create Site Application Token

curl --request POST \
     --header "Authorization: Token $token" \
     --header "Content-Type: application/json" \
     --header "Accept: application/vnd.salemove.v1+json" \
     --data-binary '{
       "site_id": "$site_id",
       "acls": ["omnibrowse:start_session"]
     }' \
     "https://api.salemove.com/application_tokens"
require 'httparty'

token = ARGV[0].strip
site_id = ARGV[1].strip

raw_response = HTTParty.post(
  "https://api.salemove.com/application_tokens",
  headers: {
    'Authorization' => "Token #{token}",
    'Accept' => 'application/vnd.salemove.v1+json',
    'Content-Type' => 'application/json'
  },
  query: {
    "site_id": site_id,
    "acls": ["omnibrowse:start_session"]
  }
)

puts = JSON.parse(raw_response.body)

Generates the output

{
  "id": "2e56b224-6708-4755-b6c9-35f9889e42dd",
  "site_id": "275ba146-6053-41ef-bfc3-d7ae8d3d6494",
  "acls": ["omnibrowse:start_session"],
  "token": "38omYbnTZJL1Ugvn"
}

Action: POST /application_tokens

This request creates an application token for a site. Application Tokens are useful for integrating an external application with SaleMove. It allows creating new site visitors, starting OmniBrowse sessions, etc. The Operator whose API token is used to send the request must have manager access to the Site.

Parameter Type Required Description
site_id string Yes The Site id.
acls array Yes A list of access controls granted to the application token.

Access Control List:

Name Desription
visitors:create Allows creating new visitors for the Site
omnibrowse:start_session Allows starting a new OmniBrowse session

Site Reactive Tab

A Site’s Reactibe Tab visuals and behavior can be configured by means of the following endpoints:

PUT Tab Visuals

curl --request PUT \
    --header "Authorization: Token $token" \
    --header "Content-Type: application/json" \
    --header "Accept: application/vnd.salemove.v1+json" \
    --data-binary '{
      "visible_operator_count": 3,
      "text": "Let\u0027s Talk!",
      "front_color": "#53a0fd"
    }' \
    "https://api.salemove.com/sites/$site_id/reactive_tab"
require 'httparty'

ENDPOINT = 'https://api.salemove.com/sites'

token = ARGV[0].strip
site_id = ARGV[1].strip

headers = {
  :authorization => "Token #{token}",
  :content_type => "application/json",
  :accept => "application/vnd.salemove.v1+json"
}

options = {
  headers: headers,
  query: {
    "visible_operator_count": 3,
    "text": "Let's Talk!",
    "front_color": "#53a0fd"
  }
}

raw_response = HTTParty.put(
    "#{ENDPOINT}/#{site_id}/reactive_tab",
    options
  )

response = JSON.parse raw_response.body

puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('PUT','https://api.salemove.com/sites/$site_id/reactive_tab',false);

xhr.setRequestHeader('authorization','Token $token');
xhr.setRequestHeader('content-type','application/json');
xhr.setRequestHeader('accept','application/vnd.salemove.v1+json');

var data = {
      "visible_operator_count": 3,
      "text": "Let's Talk!",
      "front_color": "#53a0fd"
    }
};

var query = JSON.stringify(data);

xhr.send(query);

var response = JSON.parse(xhr.responseText);

console.log(response);

Generates the Output

{
  "visible_operator_count": 3,
  "format": "mix",
  "vertical_offset": 50,
  "front_color": "#53a0fd",
  "back_color": "#ffffff",
  "hover_color": "#e6e6e6",
  "text": "Let's Talk!",
  "font_size": 20,
  "icon_class": "ico-video",
  "size": 100,
  "placement": "left"
}

Action: PUT /sites/{site_id}/reactive_tab

This updates the Reactive Tab visuals and behavior for the Site with ID site_id. The Operator whose API Token is used must have access to the Site.

Parameter Type Required Description
site_id string Yes ID of the Site to be updated
visible_operator_count integer No The maximum number of Operators to be displayed at any given time. Must be a positive integer.
text text string No
front_color string No The color of the text and icons present on the Reactive Tab in hex format

Note: Several values relevant to v1 of the Visitor App are returned in the output, but are deprecated as of VA2. They may be disregarded for all practical purposes.

Site Visitor

POST Create Visitor

curl --request POST \
     --header "Authorization: ApplicationToken $token" \
     --header "Content-Type: application/json" \
     --header "Accept: application/vnd.salemove.v1+json" \
     "https://api.salemove.com/visitors"
require 'httparty'

application_token = ARGV[0].strip

raw_response = HTTParty.post(
  "https://api.salemove.com/visitors",
  headers: {
    'Authorization' => "ApplicationToken #{application_token}",
    'Accept' => 'application/vnd.salemove.v1+json',
    'Content-Type' => 'application/json'
  }
)

puts JSON.parse(raw_response.body)
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('POST','https://api.salemove.com/visitors',false);

xhr.setRequestHeader('authorization','ApplicationToken $application_token');
xhr.setRequestHeader('accept','application/vnd.salemove.v1+json');
xhr.setRequestHeader('content-type','application/json');

xhr.send();

var response = JSON.parse(xhr.responseText);

console.log(response);

Generates the output

{
  "id": "5ec10423-f0b8-4f8e-8526-e52146d5cb4d",
  "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJhcHBsaWNhdGlvbjpkMTdiOWEyNS00MjY5LTQ5M2ItOTg1ZC0wNzhmYWI3MGMxNGEiLCJyb2xlcyI6W3sidHlwZSI6InZpc2l0b3IiLCJ2aXNpdG9yX2lkIjoiMjk1OTYyYzctODg3NS00MjgwLWI5ZjMtMjM4Y2MyZDkxMTY3In0seyJ0eXBlIjoic2l0ZV92aXNpdG9yIiwic2l0ZV9pZCI6ImVhMGNhYjE3LTMwMWMtNGMzYi1iNmViLTZjZWY2ZGQ5M2I1YyJ9XSwiaXNzIjoiU2FsZU1vdmUgQVBJIiwiaWF0IjoxNTM1NDQwOTA4LCJleHAiOjE1MzY2NTA1MDh9.iL1NVrcokaajkLBPASFeK7aB8W5Ryxll4dlIK6-kuby_yShO6erINSVct-GSHukdtRu_cKD6FRJ5nk_PsYOAGQ"
}

Action: POST /visitors

Integrators of the SaleMove system might want to engage Operators with Visitors outside of the context of a web browser or without using the SaleMove JavaScript API.

In this case the Integrator can create a Visitor entity. The Authorization header must contain the developer API token. The response will contain a temporary token which can be used for all following requests. The tokens should be renewed once every 24 hours.

POST Renew Visitor Access Token

curl --request POST \
     --header "Authorization: ApplicationToken $application_token" \
     --header "Content-Type: application/json" \
     --header "Accept: application/vnd.salemove.v1+json" \
     "https://api.salemove.com/visitors/$visitor_id/token"
require 'httparty'

application_token = ARGV[0].strip
visitor_id = ARGV[1].strip

raw_response = HTTParty.post(
  "https://api.salemove.com/visitors/#{visitor_id}/token",
  headers: {
    'Authorization' => "ApplicationToken #{application_token}",
    'Accept' => 'application/vnd.salemove.v1+json',
    'Content-Type' => 'application/json'
  }
)

puts JSON.parse(raw_response.body)
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('POST','https://api.salemove.com/visitors/$visitor_id/token',false);

xhr.setRequestHeader('authorization','ApplicationToken $application_token');
xhr.setRequestHeader('accept','application/vnd.salemove.v1+json');
xhr.setRequestHeader('content-type','application/json');

xhr.send();

var response = JSON.parse(xhr.responseText);

console.log(response);

Generates the output

{
  "id": "5ec10423-f0b8-4f8e-8526-e52146d5cb4d",
  "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJhcHBsaWNhdGlvbjpkMTdiOWEyNS00MjY5LTQ5M2ItOTg1ZC0wNzhmYWI3MGMxNGEiLCJyb2xlcyI6W3sidHlwZSI6InZpc2l0b3IiLCJ2aXNpdG9yX2lkIjoiMjk1OTYyYzctODg3NS00MjgwLWI5ZjMtMjM4Y2MyZDkxMTY3In0seyJ0eXBlIjoic2l0ZV92aXNpdG9yIiwic2l0ZV9pZCI6ImVhMGNhYjE3LTMwMWMtNGMzYi1iNmViLTZjZWY2ZGQ5M2I1YyJ9XSwiaXNzIjoiU2FsZU1vdmUgQVBJIiwiaWF0IjoxNTM1NDQwOTA4LCJleHAiOjE1MzY2NTA1MDh9.iL1NVrcokaajkLBPASFeK7aB8W5Ryxll4dlIK6-kuby_yShO6erINSVct-GSHukdtRu_cKD6FRJ5nk_PsYOAGQ"
}

Action: POST /visitors/{$visitor_id}/token

Visitors created by the Integrator have temporary access tokens. These tokens should be renewed once in every 24 hours before starting a new engagement or changing Visitor details.

GET Visitor Information

curl --request GET \
     --header "Authorization: Token $operator_api_token" \
     --header "Accept: application/vnd.salemove.v1+json" \
     "https://api.salemove.com/sites/$site_id/visitors/$visitor_id"
require 'httparty'

operator_api_token = ARGV[0].strip
site_id = ARGV[1].strip
visitor_id = ARGV[2].strip

raw_response = HTTParty.get(
  "https://api.salemove.com/sites/#{site_id}/visitors/#{visitor_id}",
  headers: {
    'Authorization' => "Token #{operator_api_token}",
    'Accept' => 'application/vnd.salemove.v1+json'
  }
)

puts JSON.parse(raw_response.body)
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('GET','https://api.salemove.com/sites/$site_id/visitors/$visitor_id',false);

xhr.setRequestHeader('authorization','Token $operator_api_token');
xhr.setRequestHeader('accept','application/vnd.salemove.v1+json');

xhr.send();

var response = JSON.parse(xhr.responseText);

console.log(response);

Generates the output

{
  "href":"https://api.salemove.com/sites/2e56b224-6708-4755-b6c9-35f9889e42dd/visitors/41fb129c-fd0c-4f8b-8ca5-657787917c4b",
  "name": "Visitor #6",
  "email": null,
  "phone": null,
  "note": null,
  "custom_attributes": {},
  "id": "41fb129c-fd0c-4f8b-8ca5-657787917c4b",
  "banned": false
}

Action: GET /sites/{site_id}/visitors/{visitor_id}

This request fetches the Visitor’s information for a Visitor that has an ID of visitor_id for the Site with ID site_id. The Operator whose API Token is used for making this request must have access to the Site.

PUT Visitor Information

curl --request PUT \
     --header "Authorization: Token $operator_api_token" \
     --header "Content-Type: application/json" \
     --header "Accept: application/vnd.salemove.v1+json" \
     --data-binary '{
       "name": "Mark White",
       "email": "mark.white@lawoffice.com",
       "phone": "+12024561111",
       "note": "bought insurance previously; considering upgrade.",
       "note_update_method": "append",
       "custom_attributes": {
         "home_address": "Washington, DC",
         "vip": "true",
         "profession": "attorney"
       }
     }' \
     "https://api.salemove.com/sites/$site_id/visitors/$visitor_id"
require 'httparty'

operator_api_token = ARGV[0].strip
site_id = ARGV[1].strip
visitor_id = ARGV[2].strip

raw_response = HTTParty.put(
  "https://api.salemove.com/sites/#{site_id}/visitors/#{visitor_id}",
  headers: {
    'Authorization' => "Token #{operator_api_token}",
    'Accept' => 'application/vnd.salemove.v1+json',
    'Content-Type' => 'application/json'
  },
  query: {
    name: 'Mark White',
    email: 'mark.white@lawoffice.com',
    phone: '+12024561111',
    note: 'bought insurance previously; considering upgrade',
    note_update_method: 'append',
    custom_attributes: {
      home_address: 'Washington, DC',
      vip: 'true',
      profession: 'attorney'
    }
  }
)

puts JSON.parse(raw_response.body)
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('PUT','https://api.salemove.com/sites/$site_id/visitors/$visitor_id',false);

xhr.setRequestHeader('authorization','Token $token');
xhr.setRequestHeader('content-type','application/json');
xhr.setRequestHeader('accept','application/vnd.salemove.v1+json');

var data = {
  "name": "Mark White",
  "email": "mark.white@lawoffice.com",
  "phone": "+12024561111",
  "note": "bought insurance previously, considering upgrade.",
  "note_update_method": "append",
  "custom_attributes": {
    "home_address": "Washington, DC",
    "vip": "true",
    "profession": "attorney"
  }
};

var query = JSON.stringify(data);

xhr.send(query);

var response = JSON.parse(xhr.responseText);

console.log(response);

Generates the output

{
  "href":"https://api.salemove.com/sites/2e56b224-6708-4755-b6c9-35f9889e42dd/visitors/41fb129c-fd0c-4f8b-8ca5-657787917c4b",
  "name": "Mark White",
  "email": "mark.white@lawoffice.com",
  "phone": "12024561111",
  "note": "Moved to bind.\nbought insurance previously; considering upgrade",
  "custom_attributes": {
    "home_address": "Washington, DC",
    "vip": "true",
    "profession": "attorney"
  },
  "id": "41fb129c-fd0c-4f8b-8ca5-657787917c4b",
  "banned": false
}

Action: PUT /sites/{site_id}/visitors/{visitor_id}

Updates the Visitor’s information for a specific visitor_id and matching the Site with a matching site_id. The Operator whose API token is used for making the request must have access to the Site.

Paramter Type Required Description
site_id string Yes The Site where the Visitor’s information will be updated.
visitor_id string Yes The Visitor whose information will be updated
name string No The Visitor’s name.
email string No The Visitor’s email.
phone string No The Visitor’s phone.
note string No The Visitor’s notes.
note_updated_method enum No Specifies a method for updating the Visitor’s note. The default value is replace. Available values are replace and append. If the method is replace then the notes for the Visitor will be overwritten by the field note in the request. If the method is append then the field note in the request will append to the existing Visitor’s notes.
custom_attributes object No An object with custom key-value pairs to be assigned to the Visitor. The server treats all keys and values as strings and also returns them as strings. Nested key-value pairs are not supported.

Queues

Create a Queue

Action: POST /queues

Creates a new Queue with a set of specified properties (see Queue Parameters). The Operator whose credentials are provided in Authorization header must have admin privileges on the Site that the Queue is defined for.

curl --request POST \
    --header "Authorization: ApiToken $token" \
    --header "Content-Type: application/json" \
    --data-binary '{
      "site_id": "51138845-3c46-4c21-8bd8-1cf45957f62e",
      "name": "Technical support queue (rich media)",
      "capacity": 15,
      "routing_policy": {
        "media": ["phone", "audio", "video"]
      },
      "when_unstaffed": "reject",
      "operator_ranking_enabled": false,
      "welcome_message": "Welcome to our company",
      "scheduling_policy_id": "db46cede-0927-46a2-ae02-3d93dbb6648d"
    }' \
    "https://api.salemove.com/queues"
require 'httparty'
ENDPOINT = 'https://api.salemove.com/queues'

token = ARGV[0].strip

headers = {
  'Authorization' => "ApiToken #{token}",
  'Content-Type' => 'application/json'
}

options = {
  headers: headers,
  query: {
    "site_id": "51138845-3c46-4c21-8bd8-1cf45957f62e",
    "name": "Technical support queue (rich media)",
    "capacity": 15,
    "routing_policy": {
      "media": ["phone", "audio", "video"]
    },
    "when_unstaffed": "reject",
    "operator_ranking_enabled": false,
    "welcome_message": "Welcome to our company",
    "scheduling_policy_id": "db46cede-0927-46a2-ae02-3d93dbb6648d"
  }
}

raw_response = HTTParty.post(
  ENDPOINT,
  options
)

response = JSON.parse(raw_response.body)
puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('POST', 'https://api.salemove.com/queues', false);

xhr.setRequestHeader('authorization','ApiToken $token');
xhr.setRequestHeader('content-type','application/json');

var data = {
  "site_id": "51138845-3c46-4c21-8bd8-1cf45957f62e",
  "name": "Technical support queue (rich media)",
  "capacity": 15,
  "routing_policy": {
    "media": ["phone", "audio", "video"]
  },
  "when_unstaffed": "reject",
  "operator_ranking_enabled": false,
  "welcome_message": "Welcome to our company",
  "scheduling_policy_id": "db46cede-0927-46a2-ae02-3d93dbb6648d"
};

var query = JSON.stringify(data);

xhr.send(query);

var response = JSON.parse(xhr.responseText);

console.log(response);

Generates the output

{
  "id": "59b0d786-e59a-4c62-a064-05e4f47488a2",
  "name": "Technical support queue (rich media)",
  "site_id": "51138845-3c46-4c21-8bd8-1cf45957f62e",
  "capacity": 15,
  "routing_policy": {
    "media": ["phone", "audio", "video"]
  },
  "when_unstaffed": "reject",
  "status": "closed",
  "operator_ranking_enabled": false,
  "welcome_message": "Welcome to our company",
  "scheduling_policy_id": "db46cede-0927-46a2-ae02-3d93dbb6648d",
  "created_at": "2017-02-20T00:00:00Z",
  "updated_at": "2017-02-20T00:00:00Z"
}

Output

See Queue Output.

List Queues

Action: GET /queues

Fetches a collection of Queues. The endpoint requires an array of site_ids.

Authorization

See corresponding section.

Visitors

A Visitor can only request collection of Queues for the Site he is currently on.

Operators

An Operator can request collection of Queues for the Sites specified in the request. The Operator must be authorized to access the requested Sites.

Request

The endpoint accepts the following filters when requested by Operator:

Parameter Required Type Description
site_ids Yes Array of strings A list of site IDs whose Queues are requested.
curl --request GET \
    --header "Authorization: ApiToken $token" \
    --header "Content-Type: application/json" \
    "https://api.salemove.com/queues?site_ids\[\]=51138845-3c46-4c21-8bd8-1cf45957f62e"
require 'httparty'
ENDPOINT = 'https://api.salemove.com/queues'

token = ARGV[0].strip

headers = {
  'Authorization' => "ApiToken #{token}",
  'Content-Type' => 'application/json'
}

options = {
  headers: headers,
  query: {
    site_ids: ['51138845-3c46-4c21-8bd8-1cf45957f62e']
  }
}

raw_response = HTTParty.get(
  ENDPOINT,
  options
)

response = JSON.parse(raw_response.body)
puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('GET', 'https://api.salemove.com/queues?site_ids[]=51138845-3c46-4c21-8bd8-1cf45957f62e', false);

xhr.setRequestHeader('authorization', 'ApiToken $token');
xhr.setRequestHeader('content-type', 'application/json');

xhr.send();

var response = JSON.parse(xhr.responseText);

console.log(response);

Generates the output

{
  "queues": [
    {
      "id": "59b0d786-e59a-4c62-a064-05e4f47488a2",
      "name": "Technical support queue (rich media)",
      "site_id": "51138845-3c46-4c21-8bd8-1cf45957f62e",
      "capacity": 15,
      "routing_policy": {
        "media": ["phone", "audio", "video"]
      },
      "when_unstaffed": "reject",
      "status": "closed",
      "operator_ranking_enabled": false,
      "welcome_message": "Welcome to our company",
      "scheduling_policy_id": "db46cede-0927-46a2-ae02-3d93dbb6648d",
      "created_at": "2017-02-20T00:00:00Z",
      "updated_at": "2017-02-20T00:00:00Z"
    },
    {
      "id": "3f82ad26-fada-4f77-a293-9a7a84fb3d1e",
      "name": "Technical support queue (text)",
      "site_id": "51138845-3c46-4c21-8bd8-1cf45957f62e",
      "capacity": 15,
      "routing_policy": {
        "media": ["text"]
      },
      "when_unstaffed": "reject",
      "status": "closed",
      "operator_ranking_enabled": false,
      "welcome_message": null,
      "scheduling_policy_id": null,
      "created_at": "2017-02-20T00:00:00Z",
      "updated_at": "2017-02-20T00:00:00Z"
    }
  ]
}

Output

Field Type Required Description
queues Array Yes List of Queue Outputs.

Get a Queue

Action: GET /queues/:queue_id

Retrieves the properties of the Queue with the given ID. The Operator whose credentials are provided in Authorization header must have admin privileges on the Site that the Queue is defined for.

curl --request GET \
    --header "Authorization: ApiToken $token" \
    --header "Content-Type: application/json" \
    "https://api.salemove.com/queues/59b0d786-e59a-4c62-a064-05e4f47488a2"
require 'httparty'
ENDPOINT = 'https://api.salemove.com/queues/59b0d786-e59a-4c62-a064-05e4f47488a2'

token = ARGV[0].strip

headers = {
  'Authorization' => "ApiToken #{token}",
  'Content-Type' => 'application/json'
}

options = {
  headers: headers
}

raw_response = HTTParty.get(
  ENDPOINT,
  options
)

response = JSON.parse(raw_response.body)
puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('GET', 'https://api.salemove.com/queues/59b0d786-e59a-4c62-a064-05e4f47488a2', false);

xhr.setRequestHeader('authorization','ApiToken $token');
xhr.setRequestHeader('content-type','application/json');

xhr.send();

var response = JSON.parse(xhr.responseText);

console.log(response);

Generates the output

{
  "id": "59b0d786-e59a-4c62-a064-05e4f47488a2",
  "name": "Technical support queue (rich media)",
  "site_id": "51138845-3c46-4c21-8bd8-1cf45957f62e",
  "capacity": 15,
  "routing_policy": {
    "media": ["phone", "audio", "video"]
  },
  "when_unstaffed": "reject",
  "status": "closed",
  "operator_ranking_enabled": false,
  "welcome_message": "Welcome to our company",
  "scheduling_policy_id": "db46cede-0927-46a2-ae02-3d93dbb6648d",
  "created_at": "2017-02-20T00:00:00Z",
  "updated_at": "2017-02-20T00:00:00Z"
}

Output

See Queue Output.

Delete a Queue

Action: DELETE /queues/:queue_id

Removes a Queue with the given ID if the Queue is empty. If the queue is not empty or associated to an Incoming Phone Number a 409 Conflict response is returned. The Operator whose credentials are provided in Authorization header must have admin privileges on the Site that the Queue is defined for.

curl --request DELETE \
    --header "Authorization: ApiToken $token" \
    "https://api.salemove.com/queues/59b0d786-e59a-4c62-a064-05e4f47488a2"
require 'httparty'
ENDPOINT = 'https://api.salemove.com/queues/59b0d786-e59a-4c62-a064-05e4f47488a2'

token = ARGV[0].strip

headers = {
  'Authorization' => "ApiToken #{token}"
}

options = {
  headers: headers
}

raw_response = HTTParty.delete(
  ENDPOINT,
  options
)

response = JSON.parse(raw_response.body)
puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('DELETE', 'https://api.salemove.com/queues/59b0d786-e59a-4c62-a064-05e4f47488a2', false);

xhr.setRequestHeader('authorization','ApiToken $token');

xhr.send();

var response = JSON.parse(xhr.responseText);

console.log(response);

Generates the output

204 No Content

Update a Queue

Action: PUT /queues/:queue_id

Updates the properties of the Queue with the given ID with a set of specified properties (see Queue Parameters). Note that the Site ID of a Queue can not be changed. The Operator whose credentials are provided in Authorization header must have admin privileges on the Site that the Queue is defined for.

curl --request PUT \
    --header "Authorization: ApiToken $token" \
    --header "Content-Type: application/json" \
    --data-binary '{
      "name": "Technical support queue (text)",
      "description": "Text queue for technical support team",
      "capacity": 10,
      "routing_policy": {
        "media": ["text"],
        "team_ids": ["ca98bb0c-187e-4db9-9662-b33e7f2326c0"]
      },
      "when_unstaffed": "reject",
      "operator_ranking_enabled": true,
      "welcome_message": "Welcome to our company",
      "scheduling_policy_id": "db46cede-0927-46a2-ae02-3d93dbb6648d"
    }' \
    "https://api.salemove.com/queues/59b0d786-e59a-4c62-a064-05e4f47488a2"
require 'httparty'
ENDPOINT = 'https://api.salemove.com/queues/59b0d786-e59a-4c62-a064-05e4f47488a2'

token = ARGV[0].strip

headers = {
  'Authorization' => "ApiToken #{token}",
  'Content-Type' => 'application/json'
}

options = {
  headers: headers,
  query: {
    "name": "Technical support queue (text)",
    "description": "Text queue for technical support team",
    "capacity": 10,
    "routing_policy": {
      "media": ["text"],
      "team_ids": ["ca98bb0c-187e-4db9-9662-b33e7f2326c0"]
    },
    "when_unstaffed": "reject",
    "operator_ranking_enabled": true,
    "welcome_message": "Welcome to our company"
  }
}

raw_response = HTTParty.put(
  ENDPOINT,
  options
)

response = JSON.parse(raw_response.body)
puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('PUT', 'https://api.salemove.com/queues/59b0d786-e59a-4c62-a064-05e4f47488a2', false);

xhr.setRequestHeader('authorization','ApiToken $token');
xhr.setRequestHeader('content-type','application/json');

var data = {
  "name": "Technical support queue (text)",
  "description": "Text queue for technical support team",
  "capacity": 10,
  "routing_policy": {
    "media": ["text"],
    "team_ids": ["ca98bb0c-187e-4db9-9662-b33e7f2326c0"]
  },
  "when_unstaffed": "reject",
  "operator_ranking_enabled": true,
  "welcome_message": "Welcome to our company",
  "scheduling_policy_id": "db46cede-0927-46a2-ae02-3d93dbb6648d"
};

var query = JSON.stringify(data);

xhr.send(query);

var response = JSON.parse(xhr.responseText);

console.log(response);

Generates the output

{
  "id": "59b0d786-e59a-4c62-a064-05e4f47488a2",
  "name": "Technical support queue (text)",
  "description": "Text queue for technical support team",
  "site_id": "51138845-3c46-4c21-8bd8-1cf45957f62e",
  "capacity": 10,
  "routing_policy": {
    "media": ["text"],
    "team_ids": ["ca98bb0c-187e-4db9-9662-b33e7f2326c0"]
  },
  "when_unstaffed": "reject",
  "status": "closed",
  "operator_ranking_enabled": true,
  "welcome_message": "Welcome to our company",
  "scheduling_policy_id": "db46cede-0927-46a2-ae02-3d93dbb6648d",
  "created_at": "2017-02-20T00:00:00Z",
  "updated_at": "2017-02-21T00:00:00Z"
}

Output

See Queue Output.

List Queue Operator Rankings

Action: GET /queues/:id/rankings

Fetches a collection of Operators with their ranks in the Queue. The Operator collection includes only the Operators that have been assigned a rank in the queue at some point in time. This means that the collection might not include all of the Operators that are associated with the queue and it might include Operators that are no longer associated with the queue. The Operator whose credentials are provided in Authorization header must have admin privileges on the Site that the Queue is defined for.

Operators

The Operator must be authorized to access the Site of the Queue.

curl --request GET \
    --header "Authorization: ApiToken $token" \
    --header "Content-Type: application/json" \
    "https://api.salemove.com/queues/59b0d786-e59a-4c62-a064-05e4f47488a2/rankings"
require 'httparty'
ENDPOINT = 'https://api.salemove.com/queues/59b0d786-e59a-4c62-a064-05e4f47488a2/rankings'

token = ARGV[0].strip

headers = {
  'Authorization' => "ApiToken #{token}",
  'Content-Type' => 'application/json'
}

options = {
  headers: headers
}

raw_response = HTTParty.get(
  ENDPOINT,
  options
)

response = JSON.parse(raw_response.body)
puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('GET', 'https://api.salemove.com/queues/59b0d786-e59a-4c62-a064-05e4f47488a2/rankings', false);

xhr.setRequestHeader('authorization', 'ApiToken $token');
xhr.setRequestHeader('content-type', 'application/json');

xhr.send();

var response = JSON.parse(xhr.responseText);

console.log(response);

Generates the output

{
  "operators": [
    {
      "id": "c8b52f0b-ad05-4c71-8c98-5056f07c4d1a",
      "rank": 10
    },
    {
      "id": "f42811bc-8519-4d33-bbb1-36d4555ecb0a",
      "rank": 2
    }
  ]
}

Output

Field Type Required Description
operators Array Yes List of Queue Operator Rankings.

Update Queue Operator Rankings

Action: PATCH /queues/:id/rankings

Updates Operators rankings of the Queue. Input is an Array of Queue Operator Rankings). Operators must be assigned to the Site that The Queue is defined for. The Operator whose credentials are provided in Authorization header must have admin privileges on the Site that the Queue is defined for.

curl --request PATCH \
    --header "Authorization: ApiToken $token" \
    --header "Content-Type: application/json" \
    --data-binary '{
      "operators": [
        {
          "id": "c8b52f0b-ad05-4c71-8c98-5056f07c4d1a",
          "rank": 5
        },
        {
          "id": "f42811bc-8519-4d33-bbb1-36d4555ecb0a",
          "rank": null
        }
      ]
    }' \
    "https://api.salemove.com/queues/59b0d786-e59a-4c62-a064-05e4f47488a2/rankings"
require 'httparty'
ENDPOINT = 'https://api.salemove.com/queues/59b0d786-e59a-4c62-a064-05e4f47488a2/rankings'

token = ARGV[0].strip

headers = {
  'Authorization' => "ApiToken #{token}",
  'Content-Type' => 'application/json'
}

options = {
  headers: headers,
  query: {
    "operators": [
      {
        "id": "c8b52f0b-ad05-4c71-8c98-5056f07c4d1a",
        "rank": 5
      }
    ]
  }
}

raw_response = HTTParty.patch(
  ENDPOINT,
  options
)

response = JSON.parse(raw_response.body)
puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('PATCH', 'https://api.salemove.com/queues/59b0d786-e59a-4c62-a064-05e4f47488a2/rankings', false);

xhr.setRequestHeader('authorization','ApiToken $token');
xhr.setRequestHeader('content-type','application/json');

var data = {
  "operators": [
    {
      "id": "c8b52f0b-ad05-4c71-8c98-5056f07c4d1a",
      "rank": 5
    },
    {
      "id": "f42811bc-8519-4d33-bbb1-36d4555ecb0a",
      "rank": 1
    }
  ]
};

var query = JSON.stringify(data);

xhr.send(query);

var response = JSON.parse(xhr.responseText);

console.log(response);

Generates the output

{
  "operators": [
    {
      "id": "c8b52f0b-ad05-4c71-8c98-5056f07c4d1a",
      "rank": 5
    },
    {
      "id": "f42811bc-8519-4d33-bbb1-36d4555ecb0a",
      "rank": 1
    }
  ]
}

Output

Field Type Required Description
operators Array Yes List of Queue Operator Rankings.

Queue Parameters

Parameter Type Required Description
site_id String Yes ID of the Site to create queue on. Can not be modified.
name String Yes Queue name.
description String No Queue description.
capacity Integer Yes The maximum number of concurrent Visitors allowed into the queue.
routing_policy Object Yes A collection of properties which determine whether Visitor should be put into this Queue when enqueued and whether Operator can serve Visitors from this Queue. Note, that one Visitor may be put into multiple Queues at once, based on Queue routing policy and Visitor’s attributes. See Routing Policy. When an empty object is given, all enqueueing Visitors will be put into created Queue.
when_unstaffed String No A strategy to apply to Visitors when Queue becomes unstaffed (i.e. when no Operators, that match Queue routing policy, are online). Allowed values are:
  • reject (default) - new Visitors aren’t allowed to enter the Queue, all enqueued Visitors are removed from this Queue.
  • accept - Visitors are allowed to enter the Queue, existing Visitors are kept in the Queue until an Operator becomes online.
operator_ranking_enabled Boolean No If true, queued Visitor will be Engaged with the first available Operator who has the highest rank in the Queue. The default value is false.
welcome_message String No If specified, this message will be sent automatically at the start of each Engagement in this Queue.
scheduling_policy_id String No ID of the Queue scheduling policy (in UUID v4 format). See Queues Scheduling Policy on how to create a scheduling policy for the queue.

Queue Output

Field Type Description
id String ID of the created Queue (in UUID v4 format).
site_id String Site ID, which created Queue belongs to.
name String Name of the created Queue.
description String Queue description.
capacity Integer The maximum number of concurrent Visitors allowed into the queue.
routing_policy Object Routing policy of the created Queue. See Routing Policy.
available_properties Object Description of current queue availability. See Available Properties.
status String Current Queue status. Always closed for new Queues.
when_unstaffed String A strategy to apply to Visitors when Queue becomes unstaffed. See Queue Parameters for more details.
operator_ranking_enabled Boolean If true, queued Visitor will be Engaged with the first available Operator who has the highest rank in the Queue.
welcome_message String If specified, this message will be sent automatically at the start of each Engagement in this Queue.
scheduling_policy_id String ID of the Queue scheduling policy (in UUID v4 format). See Queues Scheduling Policy on how to create a scheduling policy for the queue.
created_at String An ISO-8601 timestamp of when the Queue was created.
updated_at String An ISO-8601 timestamp of when the Queue was last updated.

Routing Policy

Field Type Required Description
media Array of strings No The allowed Engagement media types. Must be a set of strings where each element is one of text, phone, audio, video. When this routing policy is applied to the Queue, Visitors who request Engagement with insufficient media level, won’t be placed into the Queue.

Example 1

A Queue has routing_policy.media = ["text"], Visitor requests Engagement with media type audio. Because Queue doesn’t have audio in the list of allowed media types, such Visitor can’t be put into the Queue.

Example 2

A Queue has routing_policy.media = ["text", "phone", "audio"], Visitor requests Engagement with media type audio. In this case Visitor can be put into the Queue, because the Queue allowed media types includes audio.
team_ids Array of strings No The allowed Team IDs. Must be a set of strings, where each element refers to a Team by its ID (in UUID v4 format). This routing policy allows Visitors to be put into the Queue only if they are assigned to at least one Team from the specified list. Similarly, only Operators who belong to at least one Team from the specified list can serve Visitors from the Queue.

Available Properties

Field Type Description
media Array of strings The currently available Engagement media types. A set of strings where each element is one of text, phone, audio, video. Visitors cannot request Engagements with media that is not currently available.

Queue Operator Rankings

Field Type Description
id String Operator ID.
rank Integer Operator rank. Operators with a smaller rank number will be considered for Engagement before Operators with a high rank number. Can be null or from 1 to 10. If null is set as a rank, the Operator rank will be removed and not be included in the collection anymore. Operators with rank 10 and no rank are treated as having the same priority.

Queue Tickets

Queue Ticket represents Visitor’s request for Engagement with any available Operator.

Create a Queue Ticket

Action: POST /queue_tickets

Creates a new Queue Ticket entity and puts Visitor into the Queue. The Visitor, whose credentials are contained in Authorization header, must be present on the same Site, that the Queue Ticket is created on. See Authorization section for more information.

Parameter Type Required Description
site_id String Yes ID of the Site, that the Visitor enqueues on.
media String Yes The initial Engagement media type. One of text, phone, audio, video. Can only be text or phone if the request is made by a Visitor integrator.
media_options Object No Any additional parameters for the desired media type. See Engagement Requests for more information.
team_ids Array of strings No A set of Team IDs (in UUID v4 format) to restrict Engagement request to. An Operator must belong to at least one of the specified Team IDs to be able to serve the Visitor. This parameter can’t be used together with parameter queue_id.
queue_id String No A Queue ID (in UUID v4 format), which Queue Ticket will be assigned to. This parameter can’t be used together with parameter team_ids.
source String No Engagement starting source (tab, hotlink, button_embed, callout, external_call, sdk, offline_phone, visitor_integrator). See Engagement sources.
webhooks Array of webhooks No A list of webhooks that will subscribe to Queue Ticket or Engagement events. Only events regarding this Queue Ticket and the resulting Engagement that is created by accepting this Queue Ticket will be sent. Webhooks can have overlapping sets of events. A maximum of 10 webhooks are allowed.

Status codes

Status code Status name Description
200 OK Visitor already has an existing active Queue Ticket with the same request criteria.
201 Created A new Queue Ticket has been created.
409 Conflict Visitor has an active Queue Ticket with criteria conflicting with what was requested. The active Queue Ticket can be deleted and a subsequent request made with new criteria to replace it.

Output

Field Type Required Description
id String Yes Queue Ticket ID.
site_id String Yes ID of the Site, that the Visitor queued for.
source String Yes Engagement starting source (tab, hotlink, button_embed, callout, external_call, sdk, offline_phone, visitor_integrator). See Engagement sources.
media String Yes The initial Engagement media type. One of text, phone, audio, video. Can only be text or phone if the request is made by a Visitor integrator.
team_ids Array Yes A set of Team IDs (in UUID v4 format) for which the Visitor is queueing for.
created_at String Yes An ISO-8601 timestamp. Defines the creation time of the Queue Ticket.
visitor_authentication Object Yes Headers which are required to make subsequent requests that modify the Queue Ticket and an eventual Engagement.
curl --request POST \
    --header "Authorization: Bearer $access_token" \
    --header "Accept: application/vnd.salemove.v1+json" \
    --header "Content-Type: application/json" \
    --data-binary '{
      "site_id": "51138845-3c46-4c21-8bd8-1cf45957f62e",
      "source": "hotlink",
      "media": "video",
      "team_ids": [
        "cd564dd0-c8c1-44d2-88a9-074243e029b8",
        "22ff2c56-037c-467c-9346-7309a23335b6"
      ]
    }' \
    "https://api.salemove.com/queue_tickets"
require 'httparty'
ENDPOINT = 'https://api.salemove.com/queue_tickets'

access_token = ARGV[0].strip

headers = {
  'Authorization' => "Bearer #{access_token}",
  'Accept' => 'application/vnd.salemove.v1+json',
  'Content-Type' => 'application/json'
}

options = {
  headers: headers,
  query: {
    "site_id": "51138845-3c46-4c21-8bd8-1cf45957f62e",
    "source": "hotlink",
    "media": "video",
    "team_ids": [
      "cd564dd0-c8c1-44d2-88a9-074243e029b8",
      "22ff2c56-037c-467c-9346-7309a23335b6"
    ]
  }
}

raw_response = HTTParty.post(
  ENDPOINT,
  options
)

response = JSON.parse(raw_response.body)
puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('POST', 'https://api.salemove.com/queue_tickets', false);

xhr.setRequestHeader('authorization', 'Bearer $access_token');
xhr.setRequestHeader('accept', 'application/vnd.salemove.v1+json');
xhr.setRequestHeader('content-type', 'application/json');

var data = {
  "site_id": "51138845-3c46-4c21-8bd8-1cf45957f62e",
  "source": "hotlink",
  "media": "video",
  "team_ids": [
    "cd564dd0-c8c1-44d2-88a9-074243e029b8",
    "22ff2c56-037c-467c-9346-7309a23335b6"
  ]
};

var query = JSON.stringify(data);

xhr.send(query);

var response = JSON.parse(xhr.responseText);

console.log(response);

Generates the output

{
  "id": "59b0d786-e59a-4c62-a064-05e4f47488a2",
  "site_id": "51138845-3c46-4c21-8bd8-1cf45957f62e",
  "source": "hotlink",
  "media": "video",
  "team_ids": [
    "cd564dd0-c8c1-44d2-88a9-074243e029b8",
    "22ff2c56-037c-467c-9346-7309a23335b6"
  ],
  "created_at": "2017-02-20T00:00:00Z",
  "visitor_authentication": {
    "Authorization": "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ2aXNpdG9yOjVmOGE2YmM2LTAxNTYtNDM0ZC04N2RkLWMyYWEzMjQwMDJkOSIsInJvbGVzIjpbeyJ0eXBlIjoidmlzaXRvciIsInZpc2l0b3JfaWQiOiI1ZjhhNmJjNi0wMTU2LTQzNGQtODdkZC1jMmFhMzI0MDAyZDkifSx7InR5cGUiOiJzaXRlX3Zpc2l0b3IiLCJzaXRlX2lkIjoiZWEwY2FiMTctMzAxYy00YzNiLWI2ZWItNmNlZjZkZDkzYjVjIn1dLCJpc3MiOiJTYWxlTW92ZSBWaXNpdC1SZWdpc3RyeSIsImlhdCI6MTU0MTE2NDE1NSwiZXhwIjoxNTQyMzczNzU1fQ.hjILobSmfLBTZwQtMSHxdg6bAo7W5UysLOmIaktRdPNuAN3iEWOC6A-PXfwPM98MKFs5QgKX_H-q4JJ_gixB0w"
  }
}

Delete a Queue Ticket

Action: DELETE /queue_tickets/:queue_ticket_id

Deletes the Queue Ticket and removes Visitor from the Queue.

curl --request DELETE \
    --header "Authorization: Bearer $access_token" \
    --header "Accept: application/vnd.salemove.v1+json" \
    "https://api.salemove.com/queue_tickets/1bb4631a-40c7-4011-b7e6-b9e789901949"
require 'httparty'
ENDPOINT = 'https://api.salemove.com/queue_tickets/1bb4631a-40c7-4011-b7e6-b9e789901949'

access_token = ARGV[0].strip

headers = {
  'Authorization' => "Bearer #{access_token}",
  'Accept' => 'application/vnd.salemove.v1+json'
}

options = {
  headers: headers,
}

response = HTTParty.delete(
  ENDPOINT,
  options
)

puts response.code
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('DELETE', 'https://api.salemove.com/queue_tickets/1bb4631a-40c7-4011-b7e6-b9e789901949', false);

xhr.setRequestHeader('authorization', 'Bearer $access_token');
xhr.setRequestHeader('accept', 'application/vnd.salemove.v1+json');

xhr.send();

console.log(xhr.status);

Generates the output

204 No Content

Queue Scheduling Policies

List Queue Scheduling Policies

Action: GET /queues/scheduling_policies

Fetches a collection of Queue Scheduling Policies. The endpoint requires an array of site_ids. The Operator whose credentials are provided in Authorization header must have admin privileges on the requested Sites.

Request

The endpoint accepts the following filters when requested by Operator:

Parameter Required Type Description
site_ids Yes Array of strings A list of site IDs whose Queue Scheduling Policies are requested.
curl --request GET \
    --header "Authorization: ApiToken $token" \
    --header "Content-Type: application/json" \
    "https://api.salemove.com/queues/scheduling_policies?site_ids\[\]=51138845-3c46-4c21-8bd8-1cf45957f62e"
require 'httparty'
ENDPOINT = 'https://api.salemove.com/queues/scheduling_policies'

token = ARGV[0].strip

headers = {
  'Authorization' => "ApiToken #{token}",
  'Content-Type' => 'application/json'
}

options = {
  headers: headers,
  query: {
    site_ids: ['51138845-3c46-4c21-8bd8-1cf45957f62e']
  }
}

raw_response = HTTParty.get(
  ENDPOINT,
  options
)

response = JSON.parse(raw_response.body)
puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open(
  'GET',
  'https://api.salemove.com/queues/scheduling_policies?site_ids[]=51138845-3c46-4c21-8bd8-1cf45957f62e',
  false
);

xhr.setRequestHeader('authorization', "ApiToken $token");
xhr.setRequestHeader('content-type', 'application/json');

xhr.send();

var response = JSON.parse(xhr.responseText);

console.log(response);

Generates the output

{
  "scheduling_policies": [
    {
      "id": "dafcae2c-56cb-4cc7-8162-f2d37a96b030",
      "site_id": "aa1df566-2106-47d2-86e8-58e4cc996012",
      "name": "Default Policy",
      "description": "08-18, with a lunch-break",
      "timezone": "America/New_York",
      "business_hours": [
        {
          "opens_at": "08:00",
          "closes_at": "12:00",
          "days_of_week": ["mon", "tue", "wed", "thu", "fri"]
        },
        {
          "opens_at": "13:00",
          "closes_at": "18:00",
          "days_of_week": ["mon", "tue", "wed", "thu", "fri"]
        }
      ],
      "created_at": "2017-02-20T00:00:00Z",
      "updated_at": "2017-02-20T00:00:00Z"
    },
    {
      "id": "38d8980f-8248-456a-bc4f-17258874539c",
      "site_id": "aa1df566-2106-47d2-86e8-58e4cc996012",
      "name": "Weekend Policy",
      "description": "From 10:00 to 14:00 without lunch",
      "timezone": "America/New_York",
      "business_hours": [
        {
          "opens_at": "10:00",
          "closes_at": "14:00",
          "days_of_week": ["sat", "sun"]
        }
      ],
      "created_at": "2017-02-20T00:00:00Z",
      "updated_at": "2017-02-20T00:00:00Z"
    }
  ]
}

Output

Field Type Description
scheduling_policies Array List of Queue Scheduling Policies.

Get a Queue Scheduling Policy

Action: GET /queues/scheduling_policies/:scheduling_policy_id

Retrieves the properties of the Queue Scheduling Policy with the given ID. The Operator whose credentials are provided in Authorization header must have admin privileges on the Site that the Queue Scheduling Policy is defined for.

curl --request GET \
    --header "Authorization: ApiToken $token" \
    --header "Content-Type: application/json" \
    "https://api.salemove.com/queues/scheduling_policies/dafcae2c-56cb-4cc7-8162-f2d37a96b030"
require 'httparty'
ENDPOINT =
  'https://api.salemove.com/queues/scheduling_policies/dafcae2c-56cb-4cc7-8162-f2d37a96b030'

token = ARGV[0].strip

headers = {
  'Authorization' => "ApiToken #{token}",
  'Content-Type' => 'application/json'
}

options = {
  headers: headers
}

raw_response = HTTParty.get(
  ENDPOINT,
  options
)

response = JSON.parse(raw_response.body)
puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open(
  'GET',
  'https://api.salemove.com/queues/scheduling_policies/dafcae2c-56cb-4cc7-8162-f2d37a96b030',
  false
);

xhr.setRequestHeader('authorization', "ApiToken $token");
xhr.setRequestHeader('content-type', 'application/json');

xhr.send();

var response = JSON.parse(xhr.responseText);

console.log(response);

Generates the output

{
  "id": "dafcae2c-56cb-4cc7-8162-f2d37a96b030",
  "site_id": "aa1df566-2106-47d2-86e8-58e4cc996012",
  "name": "Default Policy",
  "description": "08-18, with a lunch-break",
  "timezone": "America/New_York",
  "business_hours": [
    {
      "opens_at": "08:00",
      "closes_at": "12:00",
      "days_of_week": ["mon", "tue", "wed", "thu", "fri"]
    },
    {
      "opens_at": "13:00",
      "closes_at": "18:00",
      "days_of_week": ["mon", "tue", "wed", "thu", "fri"]
    }
  ],
  "created_at": "2017-02-20T00:00:00Z",
  "updated_at": "2017-02-20T00:00:00Z"
}

Output

See Queue Scheduling Policy Output.

Create a Queue Scheduling Policy

Action: POST /queues/scheduling_policies

Creates a new Queue Scheduling Policy with a set of specified properties (see Queue Scheduling Policy parameters). The Operator whose credentials are provided in Authorization header must have admin privileges on the Site that the Queue Scheduling Policy is defined for.

curl --request POST \
    --header "Authorization: ApiToken $token" \
    --header "Content-Type: application/json" \
    --data-binary '{
      "site_id": "aa1df566-2106-47d2-86e8-58e4cc996012",
      "name": "Default Policy",
      "description": "08-18, with a lunch-break",
      "timezone": "America/New_York",
      "business_hours": [
        {
          "opens_at": "08:00",
          "closes_at": "12:00",
          "days_of_week": ["mon", "tue", "wed", "thu", "fri"]
        },
        {
          "opens_at": "13:00",
          "closes_at": "18:00",
          "days_of_week": ["mon", "tue", "wed", "thu", "fri"]
        }
      ]
    }' \
    "https://api.salemove.com/queues/scheduling_policies"
require 'httparty'
ENDPOINT = 'https://api.salemove.com/queues/scheduling_policies'

token = ARGV[0].strip

headers = {
  'Authorization' => "ApiToken #{token}",
  'Content-Type' => 'application/json'
}

options = {
  headers: headers,
  query: {
    site_id: "aa1df566-2106-47d2-86e8-58e4cc996012",
    name: "Default Policy",
    description: "08-18, with a lunch-break",
    timezone: "America/New_York",
    business_hours: [
      {
        opens_at: "08:00",
        closes_at: "12:00",
        days_of_week: ["mon", "tue", "wed", "thu", "fri"]
      },
      {
        opens_at: "13:00",
        closes_at: "18:00",
        days_of_week: ["mon", "tue", "wed", "thu", "fri"]
      }
    ]
  }
}

raw_response = HTTParty.post(
  ENDPOINT,
  options
)

response = JSON.parse(raw_response.body)
puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('POST', 'https://api.salemove.com/queues/scheduling_policies', false);

xhr.setRequestHeader('authorization','ApiToken $token');
xhr.setRequestHeader('content-type','application/json');

var data = {
  "site_id": "aa1df566-2106-47d2-86e8-58e4cc996012",
  "name": "Default Policy",
  "description": "08-18, with a lunch-break",
  "timezone": "America/New_York",
  "business_hours": [
    {
      "opens_at": "08:00",
      "closes_at": "12:00",
      "days_of_week": ["mon", "tue", "wed", "thu", "fri"]
    },
    {
      "opens_at": "13:00",
      "closes_at": "18:00",
      "days_of_week": ["mon", "tue", "wed", "thu", "fri"]
    }
  ]
};

var query = JSON.stringify(data);

xhr.send(query);

var response = JSON.parse(xhr.responseText);

console.log(response);

Generates the output

{
  "id": "dafcae2c-56cb-4cc7-8162-f2d37a96b030",
  "site_id": "aa1df566-2106-47d2-86e8-58e4cc996012",
  "name": "Default Policy",
  "description": "08-18, with a lunch-break",
  "timezone": "America/New_York",
  "business_hours": [
    {
      "opens_at": "08:00",
      "closes_at": "12:00",
      "days_of_week": ["mon", "tue", "wed", "thu", "fri"]
    },
    {
      "opens_at": "13:00",
      "closes_at": "18:00",
      "days_of_week": ["mon", "tue", "wed", "thu", "fri"]
    }
  ],
  "created_at": "2017-02-20T00:00:00Z",
  "updated_at": "2017-02-20T00:00:00Z"
}

Output

See Queue Scheduling Policy Output.

Update a Queue Scheduling Policy

Action: PUT /queues/scheduling_policies/:scheduling_policy_id

Updates the properties of the Queue Scheduling Policy with the given ID with a set of specified properties (see Queue Scheduling Policy parameters). Note that the Site ID of a Queue Scheduling Policy can not be changed. The Operator whose credentials are provided in Authorization header must have admin privileges on the Site that the Queue Scheduling Policy is defined for.

curl --request PUT \
    --header "Authorization: ApiToken $token" \
    --header "Content-Type: application/json" \
    --data-binary '{
      "name": "Default Policy",
      "description": "08-18, with a lunch-break",
      "timezone": "America/New_York",
      "business_hours": [
        {
          "opens_at": "08:00",
          "closes_at": "12:00",
          "days_of_week": ["mon", "tue", "wed", "thu", "fri"]
        },
        {
          "opens_at": "13:00",
          "closes_at": "18:00",
          "days_of_week": ["mon", "tue", "wed", "thu", "fri"]
        }
      ]
    }' \
    "https://api.salemove.com/queues/scheduling_policies/dafcae2c-56cb-4cc7-8162-f2d37a96b030"
require 'httparty'
ENDPOINT =
  'https://api.salemove.com/queues/scheduling_policies/dafcae2c-56cb-4cc7-8162-f2d37a96b030'

token = ARGV[0].strip

headers = {
  'Authorization' => "ApiToken #{token}",
  'Content-Type' => 'application/json'
}

options = {
  headers: headers,
  query: {
    name: "Default Policy",
    description: "08-18, with a lunch-break",
    timezone: "America/New_York",
    business_hours: [
      {
        opens_at: "08:00",
        closes_at: "12:00",
        days_of_week: ["mon", "tue", "wed", "thu", "fri"]
      },
      {
        opens_at: "13:00",
        closes_at: "18:00",
        days_of_week: ["mon", "tue", "wed", "thu", "fri"]
      }
    ]
  }
}

raw_response = HTTParty.put(
  ENDPOINT,
  options
)

response = JSON.parse(raw_response.body)
puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open(
  'POST',
  'https://api.salemove.com/queues/scheduling_policies/dafcae2c-56cb-4cc7-8162-f2d37a96b030',
  false
);

xhr.setRequestHeader('authorization','ApiToken $token');
xhr.setRequestHeader('content-type','application/json');

var data = {
  "name": "Default Policy",
  "description": "08-18, with a lunch-break",
  "timezone": "America/New_York",
  "business_hours": [
    {
      "opens_at": "08:00",
      "closes_at": "12:00",
      "days_of_week": ["mon", "tue", "wed", "thu", "fri"]
    },
    {
      "opens_at": "13:00",
      "closes_at": "18:00",
      "days_of_week": ["mon", "tue", "wed", "thu", "fri"]
    }
  ]
};

var query = JSON.stringify(data);

xhr.send(query);

var response = JSON.parse(xhr.responseText);

console.log(response);

Generates the output

{
  "id": "dafcae2c-56cb-4cc7-8162-f2d37a96b030",
  "site_id": "aa1df566-2106-47d2-86e8-58e4cc996012",
  "name": "Default Policy",
  "description": "08-18, with a lunch-break",
  "timezone": "America/New_York",
  "business_hours": [
    {
      "opens_at": "08:00",
      "closes_at": "12:00",
      "days_of_week": ["mon", "tue", "wed", "thu", "fri"]
    },
    {
      "opens_at": "13:00",
      "closes_at": "18:00",
      "days_of_week": ["mon", "tue", "wed", "thu", "fri"]
    }
  ],
  "created_at": "2017-02-20T00:00:00Z",
  "updated_at": "2017-02-20T00:00:00Z"
}

Output

See Queue Scheduling Policy Output.

Delete a Queue Scheduling Policy

Action: DELETE /queues/scheduling_policies/:scheduling_policy_id

Removes a Queue Scheduling Policy with the given ID if there are no Queues using this Scheduling Policy. The Operator whose credentials are provided in Authorization header must have admin privileges on the Site that the Queue Scheduling Policy is defined for.

curl --request DELETE \
    --header "Authorization: ApiToken $token" \
    "https://api.salemove.com/queues/scheduling_policies/dafcae2c-56cb-4cc7-8162-f2d37a96b030"
require 'httparty'
ENDPOINT =
  'https://api.salemove.com/queues/scheduling_policies/dafcae2c-56cb-4cc7-8162-f2d37a96b030'

token = ARGV[0].strip

headers = {
  'Authorization' => "ApiToken #{token}"
}

options = {
  headers: headers
}

raw_response = HTTParty.delete(
  ENDPOINT,
  options
)

response = JSON.parse(raw_response.body)
puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open(
  'DELETE',
  'https://api.salemove.com/queues/scheduling_policies/dafcae2c-56cb-4cc7-8162-f2d37a96b030',
  false
);

xhr.setRequestHeader('authorization', "ApiToken $token");

xhr.send();

var response = JSON.parse(xhr.responseText);

console.log(response);

Generates the output

204 No Content

Queue Scheduling Policy Parameters

Parameter Type Required Description
site_id String Yes ID of the Site to create a Queue Scheduling Policy on. Can not be modified.
name String Yes Queue Scheduling Policy name.
description String No Queue Scheduling Policy description.
timezone String Yes The timezone of Queue Scheduling Policy business hours. Must be a valid timezone name in Olson format. Example: America/New_York.
business_hours Array of Business Hours Yes A collection of rules determining the days of week and daily time intervals during which all the Queues with the current Scheduling Policy must be opened.

Queue Scheduling Policy Output

Parameter Type Description
site_id String ID of the Site to create a Queue Scheduling Policy on.
name String Queue Scheduling Policy name.
description String Queue Scheduling Policy description.
timezone String The timezone name of Queue Scheduling Policy business hours in Olson format. Example: America/New_York.
business_hours Array of Business Hours A collection of rules determining the days of week and daily time intervals during which all the Queues with the current Scheduling Policy must be opened.

Example: ["mon", "tue", "wed"].
created_at String An ISO-8601 timestamp of when the Queue Scheduling Policy was created.
updated_at String An ISO-8601 timestamp of when the Queue Scheduling Policy was last updated.

Business Hours Object

Parameter Type Required Description
opens_at String Yes Start of the interval, must be in format of HH:MM, where HH is an hour of the day, 24-hour clock (00..24), and MM is a minute of the hour (00..59). The interval is closed-open (inclusive lower bound, exclusive upper bound).

Examples: 09:05, 15:30
closes_at String Yes End of the interval, must be in the same format as the start of the interval (see parameter opens_at).
days_of_week Array of String Yes A list of weekdays which current rule applies to. Weekdays must be in format of 3-letter weekday case-insensitive abbreviations (mon, tue, wed, thu, fri, sat, sun). The list must contain at least 1 element, duplicates are ignored.

Engagement Requests

Authentication

Engagement Requests can be created by

Operators using the SaleMove platform

Operators using the SaleMove system are provided an API token upon Operator creation. When creating an Engagement Request, the Authorization header must contain the Operator API token.

curl --request POST \
    --header "Authorization: Token $token" \
    --header "Accept: application/vnd.salemove.v1+json" \
    --header "Content-Type: application/json" \
    --data-binary '{
      "visitor_id": "c62b4a91-a0d7-4137-80e3-c281393b71c2",
      "site_id": "51138845-3c46-4c21-8bd8-1cf45957f62e",
      "media": "text",
    }' \
  "https://api.salemove.com/engagement_requests"

Visitors with a SaleMove session

Visitors connected to a SaleMove enabled Site using a web browser are provided session IDs to uniquely identify the Visitor and the Site. Currently there is no way to register Visitor sessions as a integrator using the REST API, instead use the Visitors from external system method. When creating an Engagement Request, the Authorization header must contain the Visitor Session ID and the X-Salemove-Visit-Session-Id headers must contain the Visitor Visit Session ID. These headers are set automatically when creating Engagement Requests using the SaleMove JavaScript API.

curl --request POST \
    --header "Authorization: Bearer $access_token" \
    --header "Accept: application/vnd.salemove.v1+json" \
    --header "Content-Type: application/json' \
    --data-binary '{
      "operator_id": "c62b4a91-a0d7-4137-80e3-c281393b71c2",
      "media": "text",
      "source": "sdk"
    }' \
  "https://api.salemove.com/engagement_requests"

Visitors from external systems - SaleMove integrators

Integrators of the SaleMove system might want to engage Operators with Visitors outside of the context of a web browser or without using the SaleMove JavaScript API.

In this case the Integrator can create a Visitor using Create Site Visitor endpoint. By specifying visitor_integrator as a source parameter and using an access token provided in the response the Integrator can create an Engagement Request on behalf the Visitor.

curl --request POST \
    --header "Authorization: Bearer $visitor_access_token" \
    --header "Accept: application/vnd.salemove.v1+json" \
    --header "Content-Type: application/json" \
    --data-binary '{
      "operator_id": "c62b4a91-a0d7-4137-80e3-c281393b71c2",
      "media": "text",
      "site_id": "51138845-3c46-4c21-8bd8-1cf45957f62e",
      "source": "visitor_integrator"
    }' \
  "https://api.salemove.com/engagement_requests"

POST /engagement_requests

curl --request POST \
    --header "Authorization: Bearer $visitor_access_token" \
    --header "Accept: application/vnd.salemove.v1+json" \
    --header "Content-Type: application/json" \
    --data-binary '{
      "operator_id": "c62b4a91-a0d7-4137-80e3-c281393b71c2",
      "media": "text",
      "site_id": "51138845-3c46-4c21-8bd8-1cf45957f62e",
      "source": "visitor_integrator",
      "webhooks": [
        {
          "url": "https://server.com/salemove/events/engagement_start",
          "method": "POST",
          "headers": {"header_name": "header_value"},
          "events": ["engagement.start"]
        },
        {
          "url": "https://server.com/salemove/events/chat_message",
          "method": "PUT",
          "events": ["engagement.chat.message"]
        }
      ]
    }' \
  "https://api.salemove.com/engagement_requests"
require 'httparty'

ENDPOINT = 'https://api.salemove.com/engagement_requests'

visitor_access_token = ARGV[0].strip

headers = {
  :authorization => "Bearer #{visitor_access_token}",
  :accept => "application/vnd.salemove.v1+json",
  'Content-Type' => 'application/json'
}

options = {
  headers: headers,
  query: {
    "operator_id": "c62b4a91-a0d7-4137-80e3-c281393b71c2",
    "site_id": "51138845-3c46-4c21-8bd8-1cf45957f62e",
    "source": "visitor_integrator",
    "media": "text",
    "webhooks": [
      {
        "url": "https://server.com/salemove/events/engagement_start",
        "method": "POST",
        "headers": {"header_name": "header_value"},
        "events": ["engagement.start"]
      },
      {
        "url": "https://server.com/salemove/events/chat_message",
        "method": "PUT",
        "events": ["engagement.chat.message"]
      }
    ]
  }
}

raw_response = HTTParty.post(
  ENDPOINT,
  options
)

response = JSON.parse raw_response.body
puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('POST', 'https://api.salemove.com/engagement_requests', false);

xhr.setRequestHeader('authorization','Bearer $visitor_access_token');
xhr.setRequestHeader('accept','application/vnd.salemove.v1+json');
xhr.setRequestHeader('content-type','application/json');

var data = {
  "operator_id": "c62b4a91-a0d7-4137-80e3-c281393b71c2",
  "site_id": "51138845-3c46-4c21-8bd8-1cf45957f62e",
  "source": "visitor_integrator",
  "media": "text",
  "webhooks": [
    {
      "url": "https://server.com/salemove/events/engagement_start",
      "method": "POST",
      "headers": {"header_name": "header_value"},
      "events": ["engagement.start"]
    },
    {
      "url": "https://server.com/salemove/events/chat_message",
      "method": "PUT",
      "events": ["engagement.chat.message"]
    }
  ]
};

var query = JSON.stringify(data);

xhr.send(query);

var response = JSON.parse(xhr.responseText);

console.log(response);

Generates the output

{
  "id": "59b0d786-e59a-4c62-a064-05e4f47488a2",
  "timeout": 30,
  "site_id": "51138845-3c46-4c21-8bd8-1cf45957f62e",
  "platform": "omnicore
}

Action: POST /engagement_requests

Creates an Engagement Request and notifies the target Operator or Visitor. The endpoint requires different parameters based on the requester. The timeout field in the response notes in how many seconds (counting from the moment that SaleMove servers received the request) the Engagement Request will automatically time out unless the Engagement Request is accepted, acknowledged, canceled or declined.

The endpoint accepts the following parameters:

Parameter Required Type Description
visitor_id Yes if request made by Operator, ignored otherwise String The ID of the Visitor who the request will be sent to.
operator_id Yes if request made by Visitor or Visitor integrator, ignored otherwise String The operator ID who the request will be sent to.
site_id Yes String The Site ID of the Visitor who the request will be sent to.
media Yes String The initial Engagement media type. One of text, phone, audio, video. Can only be text or phone if the request is made by a Visitor integrator.
media_options No Object Any additional parameters for the desired media type. Further described below.
source Yes if request made by Visitor or Visitor integrator, ignored otherwise String Engagement starting source (tab, hotlink, button_embed, callout, external_call, sdk, offline_phone, visitor_integrator). See Engagement sources.
webhooks No Array of webhooks A list of webhooks that will subscribe to Engagement Request or Engagement events. Only events regarding this Engagement Request and the Engagement that is created by accepting this Engagement Request will be sent. Webhooks can have overlapping sets of events. A maximum of 10 webhooks are allowed.

media_options

Field Required Type Description
phone_number Yes if media is phone String The phone number (including the country prefix) that will be called.

Accept Engagement Request

curl --request PATCH \
    --header "Authorization: Bearer $access_token" \
    --header "Accept: application/vnd.salemove.v1+json" \
    --header "Content-Type: application/json" \
    --data-binary '{
      "action": "accept",
      "media": "text",
      "webhooks": [
        {
          "url": "https://server.com/salemove/events/chat_message",
          "method": "PUT",
          "events": ["engagement.chat.message"]
        }
      ]
    }' \
  "https://api.salemove.com/engagement_requests/$engagement_request_id"
require 'httparty'

ENDPOINT = 'https://api.salemove.com/engagement_requests'

access_token = ARGV[0].strip
engagement_request_id = ARGV[1].strip

headers = {
  :authorization => "Bearer #{access_token}",
  :accept => "application/vnd.salemove.v1+json",
  "Content-Type" => 'application/json'
}

options = {
  headers: headers,
  query: {
    "action": "accept",
    "media": "text"
  }
}

raw_response = HTTParty.patch(
  "#{ENDPOINT}/#{engagement_request_id}",
  options
)

response = JSON.parse raw_response.body
puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('PATCH', 'https://api.salemove.com/engagement_requests/' + $engagement_request_id, false);

xhr.setRequestHeader('authorization','Bearer $access_token');
xhr.setRequestHeader('accept','application/vnd.salemove.v1+json');
xhr.setRequestHeader('content-type','application/json');

var data = {
  "action": "accept",
  "media": "text"
};

var query = JSON.stringify(data);

xhr.send(query);

var response = JSON.parse(xhr.responseText);

console.log(response);

Generates the output

{
  "id": "59b0d786-e59a-4c62-a064-05e4f47488a2",
  "engagement_id": "37035d9f-2dfc-47f1-9290-0555b5106997",
  "sub_engagement_id": "51138845-3c46-4c21-8bd8-1cf45957f62e"
}

Action: PATCH /engagement_requests with action: "accept"

Accepts the Engagement Request and starts an Engagement. The endpoint requires the media parameter. Only the recipient of the Engagement Request can accept it, i.e if an Engagement Request was sent by Operator O to Visitor V, then only Visitor V is authorized to accept the Engagement Request.

The endpoint accepts the following parameters:

Parameter Required Type Description
media Yes String The initial Engagement media type. Must be one of text, phone, audio, video. Can only be text if the request is made by a Visitor integrator.
media_options No Object Any additional parameters for the desired media type. Further described below.
webhooks No Array of webhooks A list of webhooks that will subscribe to Engagement events in addition to the list of webhooks specified when this Engagement Request was created. Only events regarding the Engagement that is created by accepting this Engagement Request will be sent. Webhooks can have overlapping sets of events. A maximum of 10 webhooks are allowed.

media_options

Field Required Type Description
phone_number Yes if media is phone String The phone number (including the country prefix) that will be called.

To end the Engagement, see End Engagement.

Decline Engagement Request

curl --request PATCH \
    --header "Authorization: Bearer $access_token" \
    --header "Accept: application/vnd.salemove.v1+json" \
    --header "Content-Type: application/json" \
    --data-binary '{
      "action": "decline"
    }' \
  "https://api.salemove.com/engagement_requests/$engagement_request_id"
require 'httparty'

ENDPOINT = 'https://api.salemove.com/engagement_requests'

access_token = ARGV[0].strip
engagement_request_id = ARGV[1].strip

headers = {
  :authorization => "Bearer #{access_token}",
  :accept => "application/vnd.salemove.v1+json",
  "Content-Type" => 'application/json'
}

options = {
  headers: headers,
  query: {
    "action": "decline"
  }
}

raw_response = HTTParty.patch(
  "#{ENDPOINT}/#{engagement_request_id}",
  options
)

response = JSON.parse raw_response.body
puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('PATCH', 'https://api.salemove.com/engagement_requests/' + $engagement_request_id, false);

xhr.setRequestHeader('authorization','Bearer $access_token');
xhr.setRequestHeader('accept','application/vnd.salemove.v1+json');
xhr.setRequestHeader('content-type','application/json');

var data = {
  "action": "decline"
};

var query = JSON.stringify(data);

xhr.send(query);

var response = JSON.parse(xhr.responseText);

console.log(response);

Generates the output

{
  "id": "59b0d786-e59a-4c62-a064-05e4f47488a2"
}

Action: PATCH /engagement_requests with action: "decline"

Declines the Engagement Request (i.e if the recipient of the Engagement Request is unable to engage at this time). Only the recipient of the Engagement Request can decline it, i.e if an Engagement Request was sent by Operator O to Visitor V, then only Visitor V is authorized to decline the Engagement Request.

Cancel Engagement Request

curl --request PATCH \
    --header "Authorization: Bearer $access_token" \
    --header "Accept: application/vnd.salemove.v1+json" \
    --header "Content-Type: application/json" \
    --data-binary '{
      "action": "cancel"
    }' \
  "https://api.salemove.com/engagement_requests/$engagement_request_id"
require 'httparty'

ENDPOINT = 'https://api.salemove.com/engagement_requests'

access_token = ARGV[0].strip
engagement_request_id = ARGV[1].strip

headers = {
  :authorization => "Bearer #{access_token}",
  :accept => "application/vnd.salemove.v1+json",
  "Content-Type" => 'application/json'
}

options = {
  headers: headers,
  query: {
    "action": "cancel"
  }
}

raw_response = HTTParty.patch(
  "#{ENDPOINT}/#{engagement_request_id}",
  options
)

response = JSON.parse raw_response.body
puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('PATCH', 'https://api.salemove.com/engagement_requests/' + $engagement_request_id, false);

xhr.setRequestHeader('authorization','Bearer $access_token');
xhr.setRequestHeader('accept','application/vnd.salemove.v1+json');
xhr.setRequestHeader('content-type','application/json');

var data = {
  "action": "cancel"
};

var query = JSON.stringify(data);

xhr.send(query);

var response = JSON.parse(xhr.responseText);

console.log(response);

Generates the output

{
  "id": "59b0d786-e59a-4c62-a064-05e4f47488a2"
}

Action: PATCH /engagement_requests with action: "cancel"

Cancels the Engagement Request.

Only the originator of the Engagement Request can cancel it, i.e if an Engagement Request was sent by Visitor V to Visitor O, then only Visitor V is allowed to cancel the Engagement Request. Note that if an Engagement is already started, canceling the Engagement Request will end the Engagement instead. This functionality is provided due to possible data races between accepting and canceling an Engagement Request.

Engagements

GET Engagement List

curl --request GET \
    --header "Authorization: Token $token" \
    --header "Accept: application/vnd.salemove.v1+json" \
    "https://api.salemove.com/engagements?operator_ids\[\]=$operator_id&site_ids\[\]=$site_id&start_date=2017-01-01T00:00:00Z"
require 'httparty'

ENDPOINT = 'https://api.salemove.com/engagements'

api_token = ARGV[0]

headers = {
  :authorization => "Token #{api_token}",
  :accept => "application/vnd.salemove.v1+json"
}

options = {
  headers: headers,
  query: {
    site_ids: ['2e56b224-6708-4755-b6c9-35f9889e42dd'],
    operator_ids: ['f42811bc-8519-4d33-bbb1-36d4555ecb0a'],
    page: 1
  }
}

raw_response = HTTParty.get(
  ENDPOINT,
  options
)

response = JSON.parse raw_response.body
puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

function getEngagements(url) {
  var xhr = new XMLHttpRequest();

  xhr.open('GET',url,false);

  xhr.setRequestHeader('authorization','Token $token');
  xhr.setRequestHeader('accept','application/vnd.salemove.v1+json');

  xhr.send();

  var response = JSON.parse(xhr.responseText);

  console.log(response);
};

for (page = 1; page <= $last_page; page++) {
  var url = "https://api.salemove.com/engagements?operator_ids\[\]=$operator_id&site_ids\[\]=$site_id&start_date=2017-01-01T00:00:00Z&page=" + page;
  getEngagements(url);
};

Generates the output

{
  "next_page": "https://api.salemove.com/engagements?page=2&per_page=3",
  "last_page": "https://api.salemove.com/engagements?page=22&per_page=3",
  "engagements": [
    {
      "id": "eea868ad-9d58-4db9-a663-5fd766728980",
      "engagement_type": "proactive",
      "created_at": "2017-07-07T13:47:21.150Z",
      "duration": 10,
      "visitor_name": "Sasha Brown",
      "visitor_browser": "Chrome",
      "visitor_device_type": "mobile",
      "visitor_id": "039124e6-b4e8-4a0d-b420-5b6696c7ecb4",
      "cobrowsing_used": true,
      "video_used": true,
      "audio_used": true,
      "flagged": false,
      "queue_wait_time": 42,
      "platform": "omnicore",
      "audio_recording_urls": [
        "https://api.salemove.com/sub_engagements/1122834/recordings/XaMiTQI"
      ],
      "crm_forwarded": false,
      "summary_forwarded": false,
      "visitor": {
        "href": "https://api.salemove.com/visitors/039124e6-b4e8-4a0d-b420-5b6696c7ecb4"
      },
      "chat_transcript": {
        "href": "https://api.salemove.com/engagements/eea868ad-9d58-4db9-a663-5fd766728980/chat_transcript"
      },
      "operators": [
        {
          "href": "https://api.salemove.com/operators/f42811bc-8519-4d33-bbb1-36d4555ecb0a"
        }
      ],
      "queues": [
        {
          "id": "82af2b5d-4ea5-40c8-bab2-a87d39598a81",
          "name": "Queue name"
        }
      ]
    },
    {
      "id": "dc71edb4-9c54-4ead-9d03-4c31a69315be",
      "engagement_type": "reactive",
      "created_at": "2017-07-06T11:46:37.569Z",
      "duration": 1,
      "visitor_name": "Visitor #6",
      "visitor_browser": "Firefox",
      "visitor_device_type": "desktop",
      "visitor_id": "41fb129c-fd0c-4f8b-8ca5-657787917c4b",
      "cobrowsing_used": false,
      "video_used": false,
      "flagged": false,
      "audio_recording_urls": ["https://api.salemove.com/sub_engagements/1120220/twilio_recordings/4994"],
      "crm_forwarded": false,
      "summary_forwarded": true,
      "queue_wait_time": 10,
      "platform": "omnicore",
      "visitor": {
        "href": "https://api.salemove.com/visitors/41fb129c-fd0c-4f8b-8ca5-657787917c4b"
      },
      "source": "tab",
      "chat_transcript": {
        "href": "https://api.salemove.com/engagements/dc71edb4-9c54-4ead-9d03-4c31a69315be/chat_transcript"
      },
      "operators": [
        {
          "href": "https://api.salemove.com/operators/c8b52f0b-ad05-4c71-8c98-5056f07c4d1a"
        }
      ],
      "queues": [
        {
          "id": "82af2b5d-4ea5-40c8-bab2-a87d39598a81",
          "name": "Queue name"
        }
      ]
    },
    {
      "id": "c0828e2e-3e29-4881-8dcc-3d96563a68fe",
      "engagement_type": "proactive",
      "created_at": "2017-07-06T11:23:54.508Z",
      "duration": 330,
      "visitor_name": "Jordan Green",
      "visitor_browser": "Chrome",
      "visitor_device_type": "mobile",
      "visitor_id": "41fb129c-fd0c-4f8b-8ca5-657787917c4b",
      "cobrowsing_used": true,
      "video_used": false,
      "audio_used": false,
      "flagged": false,
      "audio_recording_urls": [],
      "crm_forwarded": false,
      "summary_forwarded": true,
      "platform": "omnicore",
      "visitor": {
        "href": "https://api.salemove.com/visitors/41fb129c-fd0c-4f8b-8ca5-657787917c4b"
      },
      "chat_transcript": {
        "href": "https://api.salemove.com/engagements/c0828e2e-3e29-4881-8dcc-3d96563a68fe/chat_transcript"
      },
      "operators": [
        {
          "href": "https://api.salemove.com/operators/f42811bc-8519-4d33-bbb1-36d4555ecb0a"
        }
      ]
    }
  ]
}

Action: GET /engagements

Fetches a collection of Engagements and related data. The endpoint requires an array of site_ids, and accepts an optional array of operator_ids.

The Operator whose credentials are contained in the Authorization request header must be authorized to access the provided Sites. If the Operator is a manager on the Sites, the operator_ids filter can be either omitted or be an empty array to query Engagements conducted by any Operator. If the Operator is not a manager, they must specify their own ID in operator_ids filter.

The results are paginated, and sorted by start_date in descending order.

The endpoint accepts the following filters:

Parameter Required Type Description
site_ids Yes Array of strings A list of site IDs whose Engagements are requested.
operator_ids No Array of strings A list of operator IDs whose Engagements are requested.
start_date No Date The response will include Engagements that happened from start_date forward in time.
end_date No Date The response will include Engagements that happened on or before the end_date and after the start_date.
page No Number If pagination is used then this parameter specifies what page is requested.
per_page No Number If pagination is used then this parameter specifies the number of Engagements per page.
order No Array Specifies whether the results should be sorted in ascending (asc) or descending (desc) order. By default, Engagements are sorted by their start time in descending order.

GET Engagement

curl --request GET \
    --header "Authorization: Token $token" \
    --header "Accept: application/vnd.salemove.v1+json" \
    "https://api.salemove.com/engagements/$engagement_id"
require 'httparty'

ENDPOINT = 'https://api.salemove.com/engagements'

api_token = ARGV[0]
engagement_id = ARGV[1]

headers = {
  :authorization => "Token #{api_token}",
  :accept => "application/vnd.salemove.v1+json"
}

raw_response = HTTParty.get(
  "#{ENDPOINT}/#{engagement_id}",
  headers: headers
)

response = JSON.parse raw_response.body

puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('GET', 'https://api.salemove.com/engagements/$engagement_id', false);

xhr.setRequestHeader('authorization','Token $token');
xhr.setRequestHeader('accept','application/vnd.salemove.v1+json');

xhr.send();

var response = JSON.parse(xhr.responseText);

console.log(response);

Generates the output

{
  "id": "eea868ad-9d58-4db9-a663-5fd766728980",
  "engagement_type": "proactive",
  "created_at": "2017-07-07T13:47:21.150Z",
  "duration": 10,
  "visitor_name": "Sasha Brown",
  "visitor_browser": "Chrome",
  "visitor_device_type": "mobile",
  "visitor_id": "039124e6-b4e8-4a0d-b420-5b6696c7ecb4",
  "cobrowsing_used": true,
  "video_used": true,
  "audio_used": true,
  "flagged": false,
  "queue_wait_time": 42,
  "platform": "omnicore",
  "audio_recording_urls": [
    "https://api.salemove.com/sub_engagements/1122834/recordings/XaMiTQI"
  ],
  "crm_forwarded": false,
  "summary_forwarded": false,
  "visitor": {
    "href": "https://api.salemove.com/visitors/039124e6-b4e8-4a0d-b420-5b6696c7ecb4"
  },
  "chat_transcript": {
    "href": "https://api.salemove.com/engagements/eea868ad-9d58-4db9-a663-5fd766728980/chat_transcript"
  },
  "operators": [
    {
      "href": "https://api.salemove.com/operators/f42811bc-8519-4d33-bbb1-36d4555ecb0a"
    }
  ],
  "queues": [
    {
      "id": "82af2b5d-4ea5-40c8-bab2-a87d39598a81",
      "name": "Queue name"
    }
  ]
}

Request Audio Recording URL

curl --request GET \
    --header "Authorization: Token $token" \
    --header "Accept: application/vnd.salemove.v1+json" \
    "https://api.salemove.com/sub_engagements/1122834/recordings/XaMiTQI"
require 'httparty'

ENDPOINT = 'https://api.salemove.com/engagements'

api_token = ARGV[0]

headers = {
  :authorization => "Token #{api_token}",
  :accept => "application/vnd.salemove.v1+json"
}

raw_response = HTTParty.get(
  "#{ENDPOINT}/sub_engagements/2212637/recordings/f1914747-bdd4-421e-bef0-3b9bccd691b0/2212637.ogg",
  headers: headers
)

response = JSON.parse raw_response.body

puts response

Generates the output

{
  "url": "https://company.com/temporary_url_to_recording_file"
}

Output

Field Type Required Description
id string Yes Engagement ID.
engagement_type string Yes Engagement type. Can be one of proactive, reactive.
created_at string Yes An ISO-8601 timestamp of when the Engagement Request was created.
duration integer Yes Engagement duration.
visitor_name string Yes Visitor name.
visitor_browser string Yes Visitor browser.
visitor_device_type string Yes Visitor device type.
visitor_id string Yes Visitor ID.
cobrowsing_used boolean Yes Whether CoBrowsing was used or not.
video_used boolean Yes Whether video was used or not.
audio_used boolean Yes Whether audio was used or not.
flagged boolean Yes Whether the Engagement has been flagged or not.
queue_wait_time integer No The time Visitor spent in queue before the Engagement. This value is present only for reactive Engagements started via queueing.
audio_recording_urls array Yes A list of audio recordings URLs.
crm_forwarded boolean Yes Whether the CRM Export has already occurred or not.
summary_forwarded boolean Yes Whether the summary has already been forwarded.
platform string Yes The platform where the Engagement was initiated. Possible values are omnicore and omnibrowse.
visitor object Yes Engagement Visitor. See Visitor.
chat_transcript object Yes Operator picture. See Chat Transcript.
operators array Yes A list of Engagement Operators. See Operators.
source string No One of Engagement sources
queues array No A list of Queues that the Visitor was enqueued in before starting the Engagement. This value is present only for reactive Engagements started via queueing. See Queues.

Visitor

Field Type Required Description
href string Yes URL of the Engagement Visitor.

Chat Transcript

Field Type Required Description
href string Yes URL of the Engagement chat transcript.

Operators

Field Type Required Description
href string Yes URL of the Engagement Operator.

Engagement sources

Type Engagement type Description
button_embed reactive Engagement started via Contact Operator Button
callout reactive Engagement started via business rules
hotlink reactive Engagement started via hotlink
external_button reactive [Deprecated]
tab reactive Engagement started in the browser tab
sdk reactive Engagement started using the JS SDK
offline_phone reactive Visitor called the operator or sent an SMS
visitor_integrator reactive Engagement started by a visitor integrator
outbound_call proactive Operator called Visitor’s phone

Queues

Field Type Required Description
id string Yes Queue ID.
name string Yes Queue name.

Action: GET /engagements/:engagement_id

Fetches a single Engagement by engagement_id. The Operator whose credentials are contained in the Authorization request header must be authorized to access the Site on which the Engagement occurred.

Note: Due to post-processing, audio recordings are available shortly after an Engagement ends.

In a case where the recording URL is immediately fulfilled with recording, requesting a URL provided by the response in audio_recording_urls will generate and return a temporary URL to the recording file. The generated URL expires in 15 minutes.

In a case where the recording is not yet available due to post-processing, a GET request for a recording URL will return 204 No Content.

Send Chat Message

curl --request PUT \
    --header "Authorization: Bearer $access_token" \
    --header "Accept: application/vnd.salemove.v1+json" \
    --header "Content-Type: application/json" \
    --data-binary '{
      "content": "Message content",
      "target": "operator",
      "type": "chat"
    }' \
    "https://api.salemove.com/engagements/$engagement_id/chat_messages/$id"
require 'httparty'
require 'securerandom'

access_token = ARGV[0].strip
engagement_id = ARGV[1].strip
message_id = SecureRandom.uuid

response = HTTParty.put(
  "https://api.salemove.com/engagements/#{engagement_id}/chat_messages/#{message_id}",
  body: {
    content: 'Message Content',
    target: 'operator',
    type: 'chat'
  },
  headers: {
    "Authorization" => "Bearer #{access_token}",
    "Accept" => "application/vnd.salemove.v1+json",
    "Content-Type" => 'application/json'
  }
)

puts response.body
var accessToken = process.argv[0];
var engagementId = process.argv[1];

var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;
var uuidv4 = require('uuid/v4');

var messageId = uuidv4();
var url = `https://api.salemove.com/engagements/${engagementId}/chat_messages/${messageId}`;

var xhr = new XMLHttpRequest();
xhr.open('PUT', url, false);
xhr.setRequestHeader('Authorization', `Bearer ${accessToken}`);
xhr.setRequestHeader('Accept', 'application/vnd.salemove.v1+json');
xhr.setRequestHeader('Content-Type', 'application/json');

xhr.send(JSON.stringify({
  content: 'Message Content',
  target: 'operator',
  type: 'chat'
});

var response = JSON.parse(xhr.responseText);
console.log(response);

Generates the output

{
  "timestamp": "2017-09-21T12:43:01Z",
  "id": "4cf0d3fe-8f2f-4aad-8e10-c2ffab8929c6",
  "engagement_id": "202a50af-8c0e-4e04-9be1-c174a3aabe1a",
  "sub_engagement_id": "29f6f027-b3f2-484e-b353-ad993462a4a5",
  "content": "Message Content",
  "target": "operator",
  "type": "chat",
  "status": "sent",
  "sender": {
    "type": "visitor"
  }
}

Action: PUT /engagements/:engagement_id/chat_messages/:message_id

Sends a chat message to an Engagement participant. This endpoint can be used by either the Operator or the Visitor. The endpoint infers the sender from the authorization headers.

This endpoint requires a client-generated message ID in the URL. Message ID must be a Version 4 UUID. Submitting a Chat Message twice with the same ID does not create duplicate messages.

See Webhooks section for receiving chat messages via webhook events.

The endpoint accepts the following parameters:

Parameter Required Type Description
content Yes String The content the sender wishes to send to the recipient.
target No* String Recipient of the message. Can be one of “operator”, “visitor”. If target is not specified, the chat message will be sent to the other participant. Target must be specified when the sender is not Operator or Visitor.
type No String Chat message type. Type is only used when the target is “operator”. Default value is “chat”.

Chat Message Types

Type Description
chat Regular chat message.
suggestion A suggested response to the Visitor. Suggestion is visible only to Operator and can then be selected and sent to the Visitor. Also see OmniGuide Suggestion.
prompt A message that is only visible to Operator. Prompts are typically used to guide the Operator through an Engagement. For example, a prompt might suggest offering CoBrowsing to the Visitor. Also see OmniGuide Prompt.

GET Chat Transcript

curl --request GET \
    --header "Authorization: Token $token" \
    --header "Accept: application/vnd.salemove.v1+json" \
    "https://api.salemove.com/engagements/$engagement_id/chat_transcript"
require 'httparty'

ENDPOINT = 'https://api.salemove.com/engagements'

api_token = ARGV[0]
engagement_id = ARGV[1]

headers = {
  :authorization => "Token #{api_token}",
  :accept => "application/vnd.salemove.v1+json"
}

raw_response = HTTParty.get(
  "#{ENDPOINT}/#{engagement_id}/chat_transcript",
  headers: headers
)

response = JSON.parse raw_response.body

puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('GET', 'https://api.salemove.com/engagements/$engagement_id/chat_transcript', false);

xhr.setRequestHeader('authorization','Token $token');
xhr.setRequestHeader('accept','application/vnd.salemove.v1+json');

xhr.send();

var response = JSON.parse(xhr.responseText);

console.log(response);

Generates the output

[
  {
    "message": "Do you do a count, or what kind of a routine do you have here?",
    "created_at": "2017-07-07T13:47:28.000Z",
    "type":"user",
    "sender": {
      "href": "https://api.salemove.com/visitors/039124e6-b4e8-4a0d-b420-5b6696c7ecb4",
      "name": "Sasha Brown"
      "type": "visitor"
    }
  },
  {
    "message": "Why don't I show you?",
    "created_at": "2017-07-07T13:47:29.000Z",
    "type":"suggestion",
    "sender": {
      "type":"omniguide",
      "name":"omniguide"
    }
  },
  {
    "message": "Why don't I show you?",
    "created_at": "2017-07-07T13:47:30.000Z",
    "type":"user",
    "sender": {
      "href": "https://api.salemove.com/operators/f42811bc-8519-4d33-bbb1-36d4555ecb0a",
      "name": "Jared Grey",
      "type": "operator"
    }
  },
  {
    "message": "CoBrowsing Started",
    "created_at": "2017-07-01T13:47:37.000Z",
    "type":"user",
    "sender": {
      "type": "system",
      "name": "system"
    }
  },
  {
    "message": "Upgraded to One-Way Video",
    "created_at": "2017-07-01T13:48:13.000Z",
    "type":"user",
    "sender": {
      "type": "system",
      "name": "system"
    }
  }
]

Action: GET /engagements/:engagement_id/chat_transcript

Fetches a single Engagement’s chat transcript. The Operator whose credentials are contained in the Authorization request header must be authorized to access the Site on which the identified Engagement occurred.

End Engagement

curl --request PATCH \
    --header "Authorization: Bearer $access_token" \
    --header "Accept: application/vnd.salemove.v1+json" \
    --header "Content-Type: application/json" \
    --data-binary '{
      "action": "end"
    }' \
  "https://api.salemove.com/engagements/$engagement_id"
require 'httparty'

ENDPOINT = 'https://api.salemove.com/engagements'

access_token = ARGV[0].strip
engagement_id = ARGV[1]

headers = {
  :authorization => "Bearer #{access_token}",
  :accept => "application/vnd.salemove.v1+json",
  'Content-Type' => 'application/json'
}

options = {
  headers: headers,
  query: {
    "action": "end"
  }
}

raw_response = HTTParty.post(
  "#{ENDPOINT}/#{engagement_id}",
  options
)

response = JSON.parse raw_response.body
puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('POST', 'https://api.salemove.com/engagements/' + $engagement_id, false);

xhr.setRequestHeader('authorization','Bearer $access_token');
xhr.setRequestHeader('accept','application/vnd.salemove.v1+json');
xhr.setRequestHeader('content-type','application/json');

var data = {
  "action": "end"
};

var query = JSON.stringify(data);

xhr.send(query);

var response = JSON.parse(xhr.responseText);

console.log(response);

Generates the output

{
  "id": "59b0d786-e59a-4c62-a064-05e4f47488a2",
  "sub_engagement_id": "aa4fe613-298b-4556-98ba-150250edf10b"
}

Action: PATCH /engagements with action: "end"

Ends the Engagement. Only a current participant of an Engagement can end it, if the Engagement was transferred then the Operator prior to the transfer is not allowed to end the Engagement. If the participant application suffered an error when starting the Engagement, provide ‘error’ as the 'reason’ for ending the Engagement to distinguish such failures from Engagement ending normally.

The endpoint accepts the following parameters:

Parameter Required Type Description
reason No String Must be exactly error.

POST Export Engagement

curl --request POST \
    --header "Authorization: Token $token" \
    --header "Content-Type: application/json" \
    --header "Accept: application/vnd.salemove.v1+json" \
    "https://api.salemove.com/engagements/$engagement_id/export"
require 'httparty'

ENDPOINT = 'https://api.salemove.com/engagements'

api_token = ARGV[0]
engagement_id = ARGV[1]

headers = {
  :authorization => "Token #{api_token}",
  :content_type => "application/json",
  :accept => "application/vnd.salemove.v1+json"
}

raw_response = HTTParty.post(
  "#{ENDPOINT}/#{engagement_id}/export",
  headers: headers
)

response = JSON.parse raw_response.body

puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('POST','https://api.salemove.com/engagements/$engagement_id/export',false);

xhr.setRequestHeader('authorization','Token $token');
xhr.setRequestHeader('content-type','application/json');
xhr.setRequestHeader('accept','application/vnd.salemove.v1+json');

xhr.send();

var response = JSON.parse(xhr.responseText);

console.log(response);

Generates the output

{"success":true}

Action: POST /engagements/:engagement_id/export

Exports the identified Engagement. The format and destination of the export are specified by the configuration of the Site on which the Engagement began. The Operator whose credentials are contained in the Authorization request header must be authorized to access the Site on which the identified Engagement occurred. If the Engagement is transferred to other Sites, and the requesting Operator does not have access to all of them, then the Export will contain only the data that belongs to the Site(s) for which the Operator is authorized.

GET Fetch Queue Average Wait Duration

curl --request GET \
    --header "Authorization: Bearer $access_token" \
    --header "Accept: application/vnd.salemove.v1+json" \
    "https://api.salemove.com/engagements/queue/wait_duration"

Generates the output

{
  "average_duration_in_seconds": 122
}

Action: GET /engagements/queue/wait_duration

This request fetches the average duration that other visitors on the same site have had to wait in the queue. This value can be used to estimate the waiting time for the current visitor if they were to request an engagement. The average value is calculated from all wait times observed between now and some time in the past, where how far back it goes is configurable per site.

This endpoint is accepted only from the Visitor’s browser. The Visitor and the Site are identified from the value in the header X-Salemove-Visit-Session-Id.

Statistics

Queries are made in JSON using an HTTP REST-style request. The query language is based on Druid query language.

Query Types

There are two types of query: Timeseries and Group By.

Query Type: Timeseries

{
  "query_type": "timeseries",
  "granularity": "day",
  "start_date": "2017-01-20T00:00:00Z",
  "end_date": "2017-02-24T00:00:00Z",
  "filter": {
    "type": "selector",
    "dimension": "type",
    "value": "reactive"
  }
}
curl --request POST \
    --header "Authorization: Token $token" \
    --header "Accept: application/vnd.salemove.v1+json" \
    --data-binary '{
      "query_type": "timeseries",
      "granularity": "day",
      "start_date": "2017-02-20T00:00:00Z",
      "end_date": "2017-02-24T00:00:00Z",
      "filter": {
        "type": "selector",
        "dimension": "type",
        "value": "reactive"
      }
    }' \
    "https://api.salemove.com/engagements/stats/count"
require 'httparty'

ENDPOINT = "https://api.salemove.com/engagements"

token = ARGV[0].strip

headers = {
  :authorization => "Token #{token}",
  :content_type => "application/json",
  :accept => 'application/vnd.salemove.v1+json'
}

options = {
  headers: headers,
  query: {
    "query_type": "timeseries",
    "granularity": "day",
    "start_date": "2017-01-20T00:00:00Z",
    "end_date": "2017-02-24T00:00:00Z",
    "filter": {
      "type": "selector",
      "dimension": "type",
      "value": "reactive"
    }
  }
}

raw_response = HTTParty.post(
  "#{ENDPOINT}/stats/count",
  options
)

response = JSON.parse raw_response.body

puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('POST','https://api.salemove.com/engagements/stats/count',false);

xhr.setRequestHeader('authorization','Token $token');
xhr.setRequestHeader('content-type','application/json');
xhr.setRequestHeader('accept','application/vnd.salemove.v1+json');

var data = {
  "query_type": "timeseries",
  "granularity": "day",
  "start_date": "2017-02-20T00:00:00Z",
  "end_date": "2017-02-24T00:00:00Z",
  "filter": {
    "type": "selector",
    "dimension": "type",
    "value": "reactive"
  }
};

var query = JSON.stringify(data);

xhr.send(query);

var response = JSON.parse(xhr.responseText);

console.log(response);

Generates the Output

[
  {
    "timestamp": "2017-02-20T00:00:00.000Z",
    "count": 5
  },
  {
   "timestamp": "2017-02-21T00:00:00.000Z",
   "count": 4
  },
  {
    "timestamp": "2017-02-22T00:00:00.000Z",
    "count": 2
  },
  {
    "timestamp": "2017-02-23T00:00:00.000Z",
    "count": 2
  }
]

This type of query takes a timeseries query object and returns an array of JSON objects, where each object represents a value requested by the query.

An example timeseries query object against the /engagements/stats/count endpoint can be found on the right:

A timeseries query includes the following parts:

Property Required Description
query_type Yes This String should always be “timeseries”.
granularity Yes Defines the granularity to bucket query results. See Granularities.
start_date Yes An ISO-8601 timestamp. Defines the query start date (inclusive).
end_date Yes An ISO-8601 timestamp. Defines the query end date (exclusive).
filter Yes See Filters.

Query Type: Group By

{
  "query_type": "group_by",
  "dimensions": ["operator_id"],
  "granularity": "all",
  "start_date": "2017-02-20T00:00:00Z",
  "end_date": "2017-02-24T00:00:00Z",
  "filter":
  {
    "type": "selector",
    "dimension": "type",
    "value": "proactive"
  }
}
curl --request POST \
    --header "Authorization: Token $token" \
    --header "Accept: application/vnd.salemove.v1+json" \
    --data-binary '{
      "query_type": "group_by",
      "dimensions": ["operator_id"],
      "granularity": "all",
      "start_date": "2017-02-20T00:00:00Z",
      "end_date": "2017-02-24T00:00:00Z",
      "filter":
      {
        "type": "selector",
        "dimension": "type",
        "value": "reactive"
      }
    }' \
    "https://api.salemove.com/engagements/stats/count"
require 'httparty'

ENDPOINT = "https://api.salemove.com/engagements"

token = ARGV[0].strip

headers = {
  :authorization => "Token #{token}",
  :content_type => "application/json",
  :accept => 'application/vnd.salemove.v1+json'
}

options = {
  headers: headers,
  query: {
    "query_type": "group_by",
    "dimensions": ["operator_id"],
    "granularity": "all",
    "start_date": "2017-02-20T00:00:00Z",
    "end_date": "2017-02-24T00:00:00Z",
    "filter":
    {
      "type": "selector",
      "dimension": "type",
      "value": "reactive"
    }
  }
}

raw_response = HTTParty.post(
  "#{ENDPOINT}/stats/count",
  options
)

response = JSON.parse raw_response.body

puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('POST','https://api.salemove.com/engagements/stats/count',false);

xhr.setRequestHeader('authorization','Token $token');
xhr.setRequestHeader('content-type','application/json');
xhr.setRequestHeader('accept','application/vnd.salemove.v1+json');

var data = {
  "query_type": "group_by",
  "dimensions": ["operator_id"],
  "granularity": "all",
  "start_date": "2017-02-20T00:00:00Z",
  "end_date": "2017-02-24T00:00:00Z",
  "filter":
  {
    "type": "selector",
    "dimension": "type",
    "value": "reactive"
  }
};

var query = JSON.stringify(data);

xhr.send(query);

var response = JSON.parse(xhr.responseText);

console.log(response);

Generates the Output

[
  {
    "timestamp": "2017-02-20T00:00:00.000Z",
    "count": 3,
    "operator_id": "f42811bc-8519-4d33-bbb1-36d4555ecb0a"
  },
  {
    "timestamp": "2017-02-20T00:00:00.000Z",
    "count": 2,
    "operator_id": "c8b52f0b-ad05-4c71-8c98-5056f07c4d1a"
  },
  {
    "timestamp": "2017-02-20T00:00:00.000Z",
    "count": 2,
    "operator_id": "efd1d1d0-dd45-43a3-a028-b4233eaed76b"
  }
]

This type of query takes a group by query object and returns an array of JSON objects, where each object represents a grouping asked for by the query. Note: If you only want to do straight aggregates for a given time range, it is highly recommended to use timeseries queries instead. The performance will be substantially better.

An example group_by query object against /engagements/stats/count endpoint can be found on the right:

A group by query includes the following parts:

Parameter Required Description
query_type Yes This string should always be “group_by”.
dimensions Yes A JSON list of dimensions over which to perform a group-by query.
granularity Yes Defines the granularity by which to bucket query results. See Granularities
start_date Yes An ISO-8601 timestamp. Defines the query start date (inclusive).
end_date Yes An ISO-8601 timestamp. Defines the query end date (exclusive).
filter Yes See Filters

Granularities

The granularity field determines how data is aggregated. Supported granularities are all, day, hour, week, and month. all aggregates the data returned into a single bucket. Other granularities may return multiple buckets in a response. Each bucket contains a timestamp field marking the starting point of the bucket. For example, after submitting hour as a granularity:

{
  "query_type": "timeseries",
  "granularity": "hour",
  "start_date": "2017-01-01T05:00:00Z",
  "end_date": "2017-01-01T09:00:00Z",
  "filter": {}
}

you may get:

[
  {
    "timestamp" : "2017-01-01T05:00:00.000Z",
    "count" : 20
  },
    {
    "timestamp" : "2017-01-01T09:00:00.000Z",
    "count": 30
  }
]

All empty buckets are discarded. Note that the response may contain only two buckets, although there is a four hour difference between 2017-01-01T05:00:00Z and 2017-01-01T09:00:00Z.

Period Granularities

By default, results are bucketed by their UTC time (e.g., days start at 00:00 UTC). To bucket results in another time zone

{
  "type": "period",
  "period": $period,
  "timeZone": $timezone
}

Where $period is one of:

Value Description
“PT1H” Hour.
“P1D” Day.
“P1W” Week.
“P1M” Month.

And $timezone is standard IANA time zone. List of supported time zones

For example, $granularity could be:

{
  "type": "period",
  "period": "P1D",
  "timeZone": "America/Los_Angeles"
}

Filters

A filter is a JSON object indicating which rows of data should be included in the computation for a query. It is essentially the equivalent of the WHERE clause in SQL. You can use the following types of filters.

Selector Filter

"filter":
  {
    "type": "selector",
    "dimension": "$dimension",
    "value": "$dimension_value"
  }

The simplest filter is a SELECTOR filter. The SELECTOR filter will match a specific dimension with a specific value. SELECTOR filters can be used as the base filters for more complex Boolean expressions of filters.

The grammar for a SELECTOR filter is as shown in the right:

In Filter

"filter":
{
  "type": "in",
  "dimension": "$dimension",
  "values":
  [
    "$a_dimension_value",
    "$a_dimension_value",
    "$a_dimension_value"
  ]
}

IN filter is similar to SELECTOR filter, but instead of matching specific dimension with just one specific value, it matches dimension with multiple possible values.

The grammar for an IN filter is as shown to the right.

Bound filter

Property Type Required Description
type String Yes This should always be “bound”.
dimension String Yes The dimension to filter on.
ordering String No Specifies the sorting order to use when comparing values against the bound. Can be one of the following values: “lexicographic”, “alphanumeric”, “numeric”, “strlen”
lower String No The lower bound for the filter.
upper String No The upper bound for the filter.
lowerStrict Boolean No Perform strict comparison on the lower bound (“<” instead of “<=”).
upperStrict Boolean No Perform strict comparison on the upper bound (“>” instead of “>=”).
  "filter": {
    "type": "bound",
    "dimension": <dimension_string>,
    "upper": <upper_string>
  }

Bound filters can be used to filter on ranges of dimension values. It can be used for comparison filtering like greater than, less than, greater than or equal to, less than or equal to, and “between” (if both “lower” and “upper” are set).

The grammar for a BOUND filter is as shown in the right:

Logical Expression Filters

Logical expression filters AND, OR and NOT can be used to determine whether to include and bucket, include and separate, or exclude data, respectively, based on the selectors you include in your query.

AND

"filter":
{
  "type": "and",
  "fields":
  [
    {$a_filter},
    {$a_filter},
    {$a_filter}
  ]
}

The grammar for an AND filter is as shown to the right

OR

"filter":
{
  "type": "or",
  "fields":
  [
    {$a_filter},
    {$a_filter},
    {$a_filter}
  ]
}

The grammar for an OR filter is shown to the right.

NOT

"filter":
{
  "type": "not",
  "field": {$a_filter}
}

The grammar for a NOT filter is as shown to the right.

The filter specified in a field object can be any other filter defined in this section.

POST Engagement Count

curl --request POST \
    --header "Authorization: Token $token" \
    --header "Content-Type: application/json" \
    --header "Accept: application/vnd.salemove.v1+json" \
    --data-binary '{
      "query_type": "group_by",
      "dimensions": ["operator_id"],
      "granularity": "all",
      "start_date": "2017-02-20T00:00:00Z",
      "end_date": "2017-02-24T00:00:00Z",
      "filter": {
        "type": "and",
        "fields": [
          {
            "type": "selector",
            "dimension": "type",
            "value": "transfer"
          },
          {
            "type": "selector",
            "dimension": "accepted_media",
            "value": "video"
          }
        ]
      }
    }' \
    "https://api.salemove.com/engagements/stats/count"
require 'httparty'

ENDPOINT = "https://api.salemove.com/engagements"

token = ARGV[0].strip

headers = {
  :authorization => "Token #{token}",
  :content_type => "application/json",
  :accept => 'application/vnd.salemove.v1+json'
}

options = {
  headers: headers,
  query: {
    "query_type": "group_by",
    "dimensions": ["operator_id"],
    "granularity": "all",
    "start_date": "2017-02-20T00:00:00Z",
    "end_date": "2017-02-24T00:00:00Z",
    "filter": {
      "type": "and",
      "fields": [
        {
          "type": "selector",
          "dimension": "type",
          "value": "transfer"
        },
        {
          "type": "selector",
          "dimension": "accepted_media",
          "value": "video"
        }
      ]
    }
  }
}

raw_response = HTTParty.post(
  "#{ENDPOINT}/stats/count",
  options
)

response = JSON.parse raw_response.body

puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('POST','https://api.salemove.com/engagements/stats/count',false);

xhr.setRequestHeader('authorization','Token $token');
xhr.setRequestHeader('content-type','application/json');
xhr.setRequestHeader('accept','application/vnd.salemove.v1+json');

var data = {
  "query_type": "group_by",
  "dimensions": ["operator_id"],
  "granularity": "all",
  "start_date": "2017-02-20T00:00:00Z",
  "end_date": "2017-02-24T00:00:00Z",
  "filter": {
    "type": "and",
    "fields": [
      {
        "type": "selector",
        "dimension": "type",
        "value": "transfer"
      },
      {
        "type": "selector",
        "dimension": "accepted_media",
        "value": "video"
      }
    ]
  }
};

var query = JSON.stringify(data);

xhr.send(query);

var response = JSON.parse(xhr.responseText);

console.log(response);

Generates the Output

[
  {
    "timestamp":"2017-02-20T00:00:00.000Z",
    "count":17,
    "operator_id":"f42811bc-8519-4d33-bbb1-36d4555ecb0a"
  },
  {
    "timestamp":"2017-02-20T00:00:00.000Z",
    "count":23,
    "operator_id":"c8b52f0b-ad05-4c71-8c98-5056f07c4d1a"
  },
  {
    "timestamp":"2017-02-20T00:00:00.000Z",
    "count":26,
    "operator_id":"efd1d1d0-dd45-43a3-a028-b4233eaed76b"
  }
]

Action: POST /engagements/stats/count

Returns Engagement count. Possible dimensions that can be used in the filters are:

Dimension Description
site_id See Engagements for a specific Site
operator_id See Engagements for a specific Operator
type Type of Engagements. Possible values are proactive, reactive, transfer
source reactive Engagement starting source (button_embed, callout, hotlink, external_button, tab). See Engagement sources.
outcome Engagement outcome (accepted, rejected, timed_out, visitor_left, visitor_cancel, operator_cancel, operator_left)
offered_media See Engagements where video, audio, phone, or chat was offered
accepted_media See Engagements where video, audio, phone, or chat was used

POST Engagement Duration

curl --request POST \
    --header "Authorization: Token $token" \
    --header "Content-Type: application/json" \
    --header "Accept: application/vnd.salemove.v1+json" \
    --data-binary '{
      "query_type": "timeseries",
      "granularity": "day",
      "start_date": "2017-02-20T00:00:00Z",
      "end_date": "2017-02-24T00:00:00Z",
      "filter": {
        "type": "selector",
        "dimension": "highest_visitor_media",
        "value": "audio"
      }
    }' \
    "https://api.salemove.com/engagements/stats/duration"
require 'httparty'

ENDPOINT = "https://api.salemove.com/engagements"

token = ARGV[0].strip

headers = {
  :authorization => "Token #{token}",
  :content_type => "application/json",
  :accept => 'application/vnd.salemove.v1+json'
}

options = {
  headers: headers,
  query: {
    "query_type": "timeseries",
    "granularity": "day",
    "start_date": "2017-02-20T00:00:00Z",
    "end_date": "2017-02-24T00:00:00Z",
    "filter": {
      "type": "selector",
      "dimension": "highest_visitor_media",
      "value": "audio"
    }
  }
}

raw_response = HTTParty.post(
  "#{ENDPOINT}/stats/duration",
  options
)

response = JSON.parse raw_response.body

puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('POST','https://api.salemove.com/engagements/stats/duration',false);

xhr.setRequestHeader('authorization','Token $token');
xhr.setRequestHeader('content-type','application/json');
xhr.setRequestHeader('accept','application/vnd.salemove.v1+json');

var data = {
  "query_type": "timeseries",
  "granularity": "day",
  "start_date": "2017-02-20T00:00:00Z",
  "end_date": "2017-02-24T00:00:00Z",
  "filter": {
    "type": "selector",
    "dimension": "highest_visitor_media",
    "value": "audio"
  }
};

var query = JSON.stringify(data);

xhr.send(query);

var response = JSON.parse(xhr.responseText);

console.log(response);

Generates the Output

[
  {
    "timestamp": "2017-02-20T00:00:00.000Z",
    "count": 9,
    "seconds": 1334,
    "average_duration_in_seconds": 152,
    "total_duration_in_seconds": 1334,

  },
  {
    "timestamp": "2017-02-21T00:00:00.000Z",
    "count": 3,
    "seconds": 568,
    "average_duration_in_seconds": 192,
    "total_duration_in_seconds": 568,
  }
]

Action: POST /engagements/stats/duration

Returns the sum and the average of Engagement durations in seconds. Possible dimensions that can be used in filters are:

Dimension Type Required Description
site_id string Yes A site_id whose Engagements will be included in the calculations
operator_id strings Yes An operator_id whose Engagements will be included in the calculations
queue_id string No If specified, then the considered Engagements will be limited to Engagements that resulted from Queues of given Queue IDs. Transferred Engagements are also considered to be resulted from that Queue
highest_operator_media string No If specified, then the considered Engagements will be limited to Engagements during which the highest media used by the Operator was the specified media. Possible media types, from highest to lowest, are video, audio, chat)
highest_visitor_media string No If specified, then the considered Engagements will be limited to Engagements during which the highest media used by the Visitor was the specified media. Possible media types from highest to lowest are video, audio, chat)

Output

Field Type Description
average_duration_in_seconds integer Average duration of Engagements (in seconds)
total_duration_in_seconds integer Total duration of Engagements (in seconds)
seconds integer deprecated Use the field total_duration_in_seconds instead

POST CoBrowsing Count

curl --request POST \
    --header "Authorization: Token $token" \
    --header "Content-Type: application/json" \
    --header "Accept: application/vnd.salemove.v1+json" \
    --data-binary '{
      "query_type": "timeseries",
      "granularity": "all",
      "start_date": "2017-01-29T00:00:00Z",
      "end_date": "2017-02-02T00:00:00Z",
      "filter": {
        "type": "selector",
        "dimension": "site_id",
        "value": "2e56b224-6708-4755-b6c9-35f9889e42dd"
      }
    }' \
    "https://api.salemove.com/engagements/stats/cobrowsing"
require 'httparty'

ENDPOINT = "https://api.salemove.com/engagements"

token = ARGV[0].strip

headers = {
  :authorization => "Token #{token}",
  :content_type => "application/json",
  :accept => 'application/vnd.salemove.v1+json'
}

options = {
  headers: headers,
  query: {
    "query_type": "timeseries",
    "granularity": "all",
    "start_date": "2017-02-20T00:00:00Z",
    "end_date": "2017-02-24T00:00:00Z",
    "filter": {
      "type": "selector",
      "dimension": "site_id",
      "value": "2e56b224-6708-4755-b6c9-35f9889e42dd"
    }
  }
}

raw_response = HTTParty.post(
  "#{ENDPOINT}/stats/cobrowsing",
  options
)

response = JSON.parse raw_response.body

puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('POST','https://api.salemove.com/engagements/stats/cobrowsing',false);

xhr.setRequestHeader('authorization','Token $token');
xhr.setRequestHeader('content-type','application/json');
xhr.setRequestHeader('accept','application/vnd.salemove.v1+json');

var data = {
  "query_type": "timeseries",
  "granularity": "day",
  "start_date": "2017-02-20T00:00:00Z",
  "end_date": "2017-02-24T00:00:00Z",
  "filter": {
    "type": "selector",
    "dimension": "site_id",
    "value": "2e56b224-6708-4755-b6c9-35f9889e42dd"
  }
};

var query = JSON.stringify(data);

xhr.send(query);

var response = JSON.parse(xhr.responseText);

console.log(response);

Generates the Output

[
  {
    "timestamp": "2017-02-20T00:00:00.000Z",
    "count": 198
  }
]

Action: POST /engagements/stats/cobrowsing

Returns approximate count of Engagements where CoBrowsing was used. Possible dimensions that can be used in filters are:

Filters Type Required Description
site_id string Yes A site_id whose Engagements will be included in the calculations
operator_id strings Yes An operator_id whose Engagements will be included in the calculations

POST Media Event Count

curl --request POST \
    --header "Authorization: Token $token" \
    --header "Content-Type: application/json" \
    --header "Accept: application/vnd.salemove.v1+json" \
    --data-binary '{
      "query_type": "timeseries",
      "granularity": "day",
      "start_date": "2017-02-20T00:00:00Z",
      "end_date": "2017-02-24T00:00:00Z",
      "filter": {
        "type": "selector",
        "dimension": "type",
        "value": "operator_media_upgrade"
      }
    }' \
    "https://api.salemove.com/engagements/media_events/stats/count"
require 'httparty'

ENDPOINT = "https://api.salemove.com/engagements"

token = ARGV[0].strip

headers = {
  :authorization => "Token #{token}",
  :content_type => "application/json",
  :accept => 'application/vnd.salemove.v1+json'
}

options = {
  headers: headers,
  query: {
    "query_type": "timeseries",
    "granularity": "day",
    "start_date": "2017-02-20T00:00:00Z",
    "end_date": "2017-02-24T00:00:00Z",
    "filter": {
      "type": "selector",
      "dimension": "type",
      "value": "operator_media_upgrade"
    }
  }
}

raw_response = HTTParty.post(
  "#{ENDPOINT}/media_events/stats/count",
  options
)

response = JSON.parse raw_response.body

puts response

var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('POST','https://api.salemove.com/engagements/media_events/stats/count',false);

xhr.setRequestHeader('authorization','Token $token');
xhr.setRequestHeader('content-type','application/json');
xhr.setRequestHeader('accept','application/vnd.salemove.v1+json');

var data = {
  "query_type": "timeseries",
  "granularity": "day",
  "start_date": "2017-02-20T00:00:00Z",
  "end_date": "2017-02-22T00:00:00Z",
  "filter": {
    "type": "selector",
    "dimension": "type",
    "value": "operator_media_upgrade"
  }
};

var query = JSON.stringify(data);

xhr.send(query);

var response = JSON.parse(xhr.responseText);

console.log(response);

Generates the Output

[
  {
    "timestamp":"2017-02-20T00:00:00.000Z",
    "count": 1334
  },
  {
    "timestamp":"2017-02-21T00:00:00.000Z",
    "count": 568
  },

Action: POST /engagements/media_events/stats/count

Returns the count of various events relating to Engagement media. This includes Engagement invitations from both Operators and Visitors with a given media option, and upgrades from one media to another. At lease one dimension must be included in filters for each query. Possible dimensions that can be used in filters are:

Dimension Type Required Description
site_id string No A site_id whose Engagements will be included in the calculations.
operator_id string No An operator_id whose Engagements will be included in the calculations.
media string No The types of media that will be used for the filter. Possible values are (video, audio, phone, and chat).
type enum No The Engagement event type. See possible types below.
Engagement Event Type Description
visitor_requested Reactive engagement request event
operator_requested Proactive engagement request event
visitor_accepted Proactive engagement accept event
operator_accepted Reactive engagement accept event
visitor_media_upgrade Visitor media upgrade event
operator_media_upgrade Operator media upgrade event
operator_media_upgrade_offer Operator offer for both to use given media

POST Visitor Count

curl --request POST \
    --header "Authorization: Token $token" \
    --header "Content-Type: application/json" \
    --header "Accept: application/vnd.salemove.v1+json" \
    --data-binary '{
      "query_type": "timeseries",
      "granularity": "day",
      "start_date": "2017-02-20T00:00:00Z",
      "end_date": "2017-02-22T00:00:00Z",
      "filter": {
        "type": "selector",
        "dimension": "site_id",
        "value": "2e56b224-6708-4755-b6c9-35f9889e42dd"
      }
    }' \
    "https://api.salemove.com/visitors/stats/count"
require 'httparty'

ENDPOINT = "https://api.salemove.com/visitors"

token = ARGV[0].strip

headers = {
  :authorization => "Token #{token}",
  :content_type => "application/json",
  :accept => 'application/vnd.salemove.v1+json'
}

options = {
  headers: headers,
  query: {
    "query_type": "timeseries",
    "granularity": "day",
    "start_date": "2017-02-20T00:00:00Z",
    "end_date": "2017-02-22T00:00:00Z",
    "filter": {
      "type": "selector",
      "dimension": "site_id",
      "value": "2e56b224-6708-4755-b6c9-35f9889e42dd"
    }
  }
}

raw_response = HTTParty.post(
  "#{ENDPOINT}/stats/count",
  options
)

response = JSON.parse raw_response.body

puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('POST','https://api.salemove.com/visitors/stats/count',false);

xhr.setRequestHeader('authorization','Token $token');
xhr.setRequestHeader('content-type','application/json');
xhr.setRequestHeader('accept','application/vnd.salemove.v1+json');

var data = {
  "query_type": "timeseries",
  "granularity": "day",
  "start_date": "2017-02-20T00:00:00Z",
  "end_date": "2017-02-22T00:00:00Z",
  "filter": {
    "type": "selector",
    "dimension": "site_id",
    "value": "2e56b224-6708-4755-b6c9-35f9889e42dd"
  }
};

var query = JSON.stringify(data);

xhr.send(query);

var response = JSON.parse(xhr.responseText);

console.log(response);

Generates the Output

[
  {
    "timestamp":"2017-02-20T00:00:00.000Z",
    "count": 1898
  },
  {
    "timestamp":"2017-02-21T00:00:00.000Z",
    "count": 2034
  }
]

Action: POST /visitors/stats/count

Returns approximate distinct Visitor count. This endpoint is using HyperLogLog algorithm to calculate cardinality. Possible dimensions that can be used in filters are:

Dimension Type Required Description
site_id string Yes The site_id of the Site whose Visitors are included in the calculations

POST Queue Wait Time

curl --request POST \
    --header "Authorization: Token $token" \
    --header "Content-Type: application/json" \
    --header "Accept: application/vnd.salemove.v1+json" \
    --data-binary '{
      "query_type": "timeseries",
      "granularity": "day",
      "start_date": "2017-02-20T00:00:00Z",
      "end_date": "2017-02-22T00:00:00Z",
      "filter": {
        "type": "and",
        "fields": [
          {
            "type": "selector",
            "dimension": "site_id",
            "value": "2e56b224-6708-4755-b6c9-35f9889e42dd"
          },
          {
            "type": "selector",
            "dimension": "outcome",
            "value": "finished"
          }
        ]
      }
    }' \
    "https://api.salemove.com/engagements/stats/queue/wait_duration"
require 'httparty'

ENDPOINT = "https://api.salemove.com/engagements"

token = ARGV[0].strip

headers = {
  :authorization => "Token #{token}",
  :content_type => "application/json",
  :accept => 'application/vnd.salemove.v1+json'
}

options = {
  headers: headers,
  query: {
    "query_type": "timeseries",
    "granularity": "day",
    "start_date": "2017-02-20T00:00:00Z",
    "end_date": "2017-02-22T00:00:00Z",
    "filter": {
      "type": "and",
      "fields": [
        {
          "type": "selector",
          "dimension": "site_id",
          "value": "2e56b224-6708-4755-b6c9-35f9889e42dd"
        },
        {
          "type": "selector",
          "dimension": "outcome",
          "value": "finished"
        }
      ]
    }
  }
}

raw_response = HTTParty.post(
  "#{ENDPOINT}/stats/queue/wait_duration",
  options
)

response = JSON.parse raw_response.body

puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('POST','https://api.salemove.com/engagements/stats/queue/wait_duration',false);

xhr.setRequestHeader('authorization','Token $token');
xhr.setRequestHeader('content-type','application/json');
xhr.setRequestHeader('accept','application/vnd.salemove.v1+json');

var data = {
  "query_type": "timeseries",
  "granularity": "day",
  "start_date": "2017-02-20T00:00:00Z",
  "end_date": "2017-02-22T00:00:00Z",
  "filter": {
    "type": "and",
    "fields": [
      {
        "type": "selector",
        "dimension": "site_id",
        "value": "2e56b224-6708-4755-b6c9-35f9889e42dd"
      },
      {
        "type": "selector",
        "dimension": "outcome",
        "value": "finished"
      }
    ]
  }
};

var query = JSON.stringify(data);

xhr.send(query);

var response = JSON.parse(xhr.responseText);

console.log(response);

Generates the Output

[
  {
    "timestamp":"2017-02-20T00:00:00.000Z",
    "count": 7,
    "seconds": 0,
    "average_duration_in_seconds": 13,
    "maximum_duration_in_seconds": 29,
    "total_duration_in_seconds": 91
  },
  {
    "timestamp":"2017-02-21T00:00:00.000Z",
    "count": 11,
    "seconds": 0,
    "average_duration_in_seconds": 15,
    "maximum_duration_in_seconds": 27,
    "total_duration_in_seconds": 165
  }
]

Action: POST /engagements/stats/queue/wait_duration

Returns statistics on how much time Visitors have spent waiting on the queue, including average and maximum duration. Possible dimensions that can be used in the filters are:

Dimension Type Description
site_id string Site ID
team_id string Team ID
queue_id string Queue ID
media string Media type of engagement visitor is queued for (video, audio, chat)
outcome enum Queuing Outcome. See Outcome descriptions below
Outcome Description
finished Visitor successfully engaged with Operator
canceled Visitor abandoned the queue
unstaffed Visitor was forced from the queue, as all Operators became unavailable
closed Visitor was forced from the queue, which was closed by administrative action
disconnected Visitor disconnected
failed Visitor failed to join the queue

POST Visit Count

curl --request POST \
    --header "Authorization: Token $token" \
    --header "Content-Type: application/json" \
    --header "Accept: application/vnd.salemove.v1+json" \
    --data-binary '{
      "query_type": "timeseries",
      "granularity": "day",
      "start_date": "2017-02-20T00:00:00Z",
      "end_date": "2017-02-22T00:00:00Z",
      "filter": {
        "type": "selector",
        "dimension": "site_id",
        "value": "2e56b224-6708-4755-b6c9-35f9889e42dd"
      }
    }' \
    "https://api.salemove.com/visits/stats/count"
require 'httparty'

ENDPOINT = "https://api.salemove.com/visits"

token = ARGV[0].strip

headers = {
  :authorization => "Token #{token}",
  :content_type => "application/json",
  :accept => 'application/vnd.salemove.v1+json'
}

options = {
  headers: headers,
  query: {
    "query_type": "timeseries",
    "granularity": "day",
    "start_date": "2017-02-20T00:00:00Z",
    "end_date": "2017-02-22T00:00:00Z",
    "filter": {
      "type": "selector",
      "dimension": "site_id",
      "value": "2e56b224-6708-4755-b6c9-35f9889e42dd"
    }
  }
}

raw_response = HTTParty.post(
  "#{ENDPOINT}/stats/count",
  options
)

response = JSON.parse raw_response.body

puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('POST','https://api.salemove.com/visits/stats/count',false);

xhr.setRequestHeader('authorization','Token $token');
xhr.setRequestHeader('content-type','application/json');
xhr.setRequestHeader('accept','application/vnd.salemove.v1+json');

var data = {
  "query_type": "timeseries",
  "granularity": "day",
  "start_date": "2017-02-20T00:00:00Z",
  "end_date": "2017-02-22T00:00:00Z",
  "filter": {
    "type": "selector",
    "dimension": "site_id",
    "value": "2e56b224-6708-4755-b6c9-35f9889e42dd"
  }
};

var query = JSON.stringify(data);

xhr.send(query);

var response = JSON.parse(xhr.responseText);

console.log(response);

Generates the Output

[
  {
    "timestamp":"2017-02-20T00:00:00.000Z",
    "count": 2023
  },
  {
    "timestamp":"2017-02-21T00:00:00.000Z",
    "count": 2094
  }
]

Action: POST /visits/stats/count

Returns Visitor session count. Possible dimensions that can be used in filters are:

Dimension Type Required Description
site_id string Yes The site_id of the Site whose visits are included in the calculations

POST Staffed Visits Count

curl --request POST \
    --header "Authorization: Token $token" \
    --header "Content-Type: application/json" \
    --header "Accept: application/vnd.salemove.v1+json" \
    --data-binary '{
      "query_type": "timeseries",
      "granularity": "all",
      "dimensions": ["type"],
      "start_date": "2017-02-20T00:00:00Z",
      "end_date": "2017-02-24T00:00:00Z",
      "filter": {
        "type": "and",
        "fields":
        [
          {
            "type": "selector",
            "dimension": "site_id",
            "value": "2e56b224-6708-4755-b6c9-35f9889e42dd"
          },
          {
            "type": "selector",
            "dimension": "type",
            "value": "staffed"
          }
        ]
      }
    }' \
    "https://api.salemove.com/visits/stats/staffed_count"
require 'httparty'

ENDPOINT = "https://api.salemove.com/visits"

token = ARGV[0].strip

headers = {
  :authorization => "Token #{token}",
  :content_type => "application/json",
  :accept => 'application/vnd.salemove.v1+json'
}

options = {
  headers: headers,
  query: {
    "query_type": "timeseries",
    "granularity": "all",
    "dimensions": ["type"],
    "start_date": "2017-02-20T00:00:00Z",
    "end_date": "2017-02-24T00:00:00Z",
    "filter": {
      "type": "and",
      "fields":
      [
        {
          "type": "selector",
          "dimension": "site_id",
          "value": "2e56b224-6708-4755-b6c9-35f9889e42dd"
        },
        {
          "type": "selector",
          "dimension": "type",
          "value": "staffed"
        }
      ]
    }
  }
}

raw_response = HTTParty.post(
  "#{ENDPOINT}/stats/staffed_count",
  options
)

response = JSON.parse raw_response.body

puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('POST','https://api.salemove.com/visits/stats/staffed_count',false);

xhr.setRequestHeader('authorization','Token $token');
xhr.setRequestHeader('content-type','application/json');
xhr.setRequestHeader('accept','application/vnd.salemove.v1+json');

var data = {
  "query_type": "timeseries",
  "granularity": "all",
  "dimensions": ["type"],
  "start_date": "2017-02-20T00:00:00Z",
  "end_date": "2017-02-24T00:00:00Z",
  "filter": {
    "type": "and",
    "fields":
    [
      {
        "type": "selector",
        "dimension": "site_id",
        "value": "2e56b224-6708-4755-b6c9-35f9889e42dd"
      },
      {
        "type": "selector",
        "dimension": "type",
        "value": "staffed"
      }
    ]
  }
};

var query = JSON.stringify(data);

xhr.send(query);

var response = JSON.parse(xhr.responseText);

console.log(response);

Generates the Output

[
  {
    "timestamp": "2017-02-20T00:00:00.000Z",
    "count": 49
  }
]

Action: POST /visits/stats/staffed_count

Returns approximate count of staffed visits. Possible dimensions that can be used in filters are:

Filters Type Required Description
site_id string Yes A site_id whose Engagements will be included in the calculations
type enum Yes staffed for the visits with Operator staffed or general for visits without Operators staffed

The sum of general and staffed visits is equal to the unique visitors count. The staffing percentage is calculated with the unique visitors count and the staffed visits count.

POST Operator Alert Count

curl --request POST \
    --header "Authorization: Token $token" \
    --header "Content-Type: application/json" \
    --header "Accept: application/vnd.salemove.v1+json" \
    --data-binary '{
      "query_type": "timeseries",
      "granularity": "day",
      "start_date": "2017-02-20T00:00:00Z",
      "end_date": "2017-02-22T00:00:00Z",
      "filter": {
        "type": "selector",
        "dimension": "operator_id",
        "value": "f42811bc-8519-4d33-bbb1-36d4555ecb0a"
      }
    }' \
    "https://api.salemove.com/alerts/stats/count"
require 'httparty'

ENDPOINT = "https://api.salemove.com/alerts"

token = ARGV[0].strip

headers = {
  :authorization => "Token #{token}",
  :content_type => "application/json",
  :accept => 'application/vnd.salemove.v1+json'
}

options = {
  headers: headers,
  query: {
    "query_type": "timeseries",
    "granularity": "day",
    "start_date": "2017-02-20T00:00:00Z",
    "end_date": "2017-02-22T00:00:00Z",
    "filter": {
      "type": "selector",
      "dimension": "operator_id",
      "value": "f42811bc-8519-4d33-bbb1-36d4555ecb0a"
    }
  }
}

raw_response = HTTParty.post(
  "#{ENDPOINT}/stats/count",
  options
)

response = JSON.parse raw_response.body

puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('POST','https://api.salemove.com/alerts/stats/count',false);

xhr.setRequestHeader('authorization','Token $token');
xhr.setRequestHeader('content-type','application/json');
xhr.setRequestHeader('accept','application/vnd.salemove.v1+json');

var data = {
  "query_type": "timeseries",
  "granularity": "day",
  "start_date": "2017-02-20T00:00:00Z",
  "end_date": "2017-02-22T00:00:00Z",
  "filter": {
    "type": "selector",
    "dimension": "operator_id",
    "value": "f42811bc-8519-4d33-bbb1-36d4555ecb0a"
  }
};

var query = JSON.stringify(data);

xhr.send(query);

var response = JSON.parse(xhr.responseText);

console.log(response);

Generates the Output

[
  {
    "timestamp":"2017-02-20T00:00:00.000Z",
    "count": 119
  },
  {
    "timestamp": "2017-02-21T00:00:00.000Z",
    "count": 258
  }
]

Action: POST /alerts/stats/count

Returns Operator alert count. Possible dimensions that can be used in filters are:

Dimensions Type Required Description
site_id string Yes The site_id whose alerts will be included in the calculations.
operator_id string Yes The operator_id who received the alerts from the Site with site_id

POST Operator Online Time

curl --request POST \
    --header "Authorization: Token $token" \
    --header "Content-Type: application/json" \
    --header "Accept: application/vnd.salemove.v1+json" \
    --data-binary '{
      "query_type": "group_by",
      "dimensions": ["operator_id"],
      "granularity": "all",
      "start_date": "2017-02-20T00:00:00Z",
      "end_date": "2017-02-22T00:00:00Z",
      "filter": {
        "type": "and",
        "fields":
        [
          {
            "type": "selector",
            "dimension": "site_id",
            "value": "2e56b224-6708-4755-b6c9-35f9889e42dd"
          },
          {
            "type": "selector",
            "dimension": "type",
            "value": "engaged"
          }
        ]
      }
    }' \
    "https://api.salemove.com/operators/stats/online_duration"
require 'httparty'

ENDPOINT = "https://api.salemove.com/operators"

token = ARGV[0].strip

headers = {
  :authorization => "Token #{token}",
  :content_type => "application/json",
  :accept => 'application/vnd.salemove.v1+json'
}

options = {
  headers: headers,
  query: {
    "query_type": "group_by",
    "dimensions": ["operator_id"],
    "granularity": "all",
    "start_date": "2017-02-20T00:00:00Z",
    "end_date": "2017-02-22T00:00:00Z",
    "filter": {
      "type": "and",
      "fields":
      [
        {
          "type": "selector",
          "dimension": "site_id",
          "value": "2e56b224-6708-4755-b6c9-35f9889e42dd"
        },
        {
          "type": "selector",
          "dimension": "type",
          "value": "engaged"
        }
      ]
    }
  }
}

raw_response = HTTParty.post(
  "#{ENDPOINT}/stats/online_duration",
  options
)

response = JSON.parse raw_response.body

puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('POST','https://api.salemove.com/operators/stats/online_duration',false);

xhr.setRequestHeader('authorization','Token $token');
xhr.setRequestHeader('content-type','application/json');
xhr.setRequestHeader('accept','application/vnd.salemove.v1+json');

var data = {
  "query_type": "group_by",
  "dimensions": ["operator_id"],
  "granularity": "all",
  "start_date": "2017-02-20T00:00:00Z",
  "end_date": "2017-02-22T00:00:00Z",
  "filter": {
    "type": "and",
    "fields":
    [
      {
        "type": "selector",
        "dimension": "site_id",
        "value": "2e56b224-6708-4755-b6c9-35f9889e42dd"
      },
      {
        "type": "selector",
        "dimension": "type",
        "value": "engaged"
      }
    ]
  }
};

var query = JSON.stringify(data);

xhr.send(query);

var response = JSON.parse(xhr.responseText);

console.log(response);

Generates the Output

[
  { timestamp: '2017-02-20T00:00:00.000Z',
    operator_id: 'f42811bc-8519-4d33-bbb1-36d4555ecb0a',
    seconds: 12171
  },
  { timestamp: '2017-02-20T00:00:00.000Z',
    operator_id: 'c8b52f0b-ad05-4c71-8c98-5056f07c4d1a',
    seconds: 9083
  },
  { timestamp: '2017-02-20T00:00:00.000Z',
    operator_id: 'efd1d1d0-dd45-43a3-a028-b4233eaed76b',
    seconds: 7647
  }
]

Action: POST /operators/stats/online_duration

Returns Operator online duration in seconds. Possible dimensions that can be used in filters are:

Dimension Type Required Description
site_id string Yes A site_id whose Operator(s) will be included in the calculations.
operator_id string Yes An operator_id whose online duration is being requested
type enum Yes Operator online status.

There are three groups of types an online Operator can have:

Operator Status Type Description
available media type Describes what the Operator is available for. Possible values are video, audio, chat
engaged if the Operator is currently in an Engagement. Possible values (true, false)
unavailable type Describes what kind of unavailiabity the Operator selected while being marked as away or busy. E.g. Quick Break, Training, With Customer

Reporting

Reporting endpoints are divided into two types: historical and live:

Historical

Historical reporting endpoints return data calculated over a specified window of time, aggregated by specified time units (granularity). Every historical reporting endpoint has at least these three required parameters:

Parameter Description
start_date An ISO-8601 timestamp. Defines the query start date (inclusive).
end_date An ISO-8601 timestamp. Defines the query end date (exclusive).
granularity Defines the granularity by which to bucket query results. See Granularities

Live

Live reporting endpoints return data which reflects the current state of the system, such as “Number of Operators that are currently engaged”.

Download CSV

By specifying the Accept header application/vnd.salemove.v1+csv data will be returned in CSV format. CSV format is only available for historical data.

curl --request POST \
    --header "Authorization: Token $token" \
    --header "Content-Type: application/json" \
    --header "Accept: application/vnd.salemove.v1+csv" \
    --data-binary "{
      \"start_date\": $start_date,
      \"end_date\": $end_date,
      \"granularity\": $granularity,
      \"site_ids\": [$site_id],
      \"team_ids\": [$team_id]
    }" \
    "https://api.salemove.com/reporting/$endpoint"

Generates the output

start,end,chat,audio_video
2017-06-28T00:00:00.000Z,2017-06-29T00:00:00.000Z,20,15
2017-06-29T00:00:00.000Z,2017-06-30T00:00:00.000Z,45,21

POST Engagement Count

curl --request POST \
    --header "Authorization: Token $token" \
    --header "Content-Type: application/json" \
    --header "Accept: application/vnd.salemove.v1+json" \
    --data-binary "{
      \"start_date\": $start_date,
      \"end_date\": $end_date,
      \"granularity\": $granularity,
      \"site_ids\": [$site_id],
      \"team_ids\": [$team_id],
      \"queue_ids\": [$queue_id],
      \"include_without_queues\": $include_without_queues
    }" \
    "https://api.salemove.com/reporting/engagements"

Generates the output

{
  "data": [
    {
      "timestamp": "2017-06-28T00:00:00.000Z",
      "chat": 20,
      "audio_video": 15
    },
    {
      "timestamp": "2017-06-29T00:00:00.000Z",
      "chat": 45,
      "audio_video": 21
    },
  ],
  "chat": 65,
  "audio_video": 36,
  "total": 101
}

Action: POST /reporting/engagements

Returns an array of Engagement counts. The endpoint requires a list of site_ids.

Optionally the parameter queue_ids can be provided. In this case the endpoint returns Engagement counts for Engagements which resulted from any of the specified Queues.

Optionally the parameter team_ids can be provided. In this case the endpoint returns Engagement counts only for Operators belonging to the specified Teams.

Engagement counts are grouped by the highest media used by the Operator during the Engagement.

To download the data as CSV, see Download CSV.

Parameter Type Required Description
site_ids array Yes A list of Site IDs. Must not be empty.
team_ids array No A list of Team IDs. All Teams must belong to provided Sites.
start_date string Yes An ISO-8601 timestamp. Defines the query start date (inclusive).
end_date string Yes An ISO-8601 timestamp. Defines the query end date (exclusive).
granularity string Yes Defines the granularity to bucket query results. Can be one of month, week, day, hour
queue_ids array No A list of Queue IDs. All Queues must belong to provided Sites.
include_without_queues boolean No If true, includes results that are not associated with any Queues. If false, excludes results that are not associated with Queues. Default value is true.

Output

Field Type Description
data array Count of Engagements during the period. Elements are described below.
chat integer Total count of Chat Engagments during the period.
audio_video integer Total count of Audio/Video Engagements during the period.
total integer Total count of Engagements during the period.

data

Field Type Description
start string An ISO-8601 timestamp. Start of the period (inclusive).
end string An ISO-8601 timestamp. End of the period (exclusive).
chat integer Count of Chat Engagements.
audio_video integer Count of Audio/Video Engagements.

POST Queued Visitors Count

curl --request POST \
    --header "Authorization: Token $token" \
    --header "Content-Type: application/json" \
    --header "Accept: application/vnd.salemove.v1+json" \
    --data-binary "{
      \"start_date\": $start_date,
      \"end_date\": $end_date,
      \"granularity\": $granularity,
      \"site_ids\": [$site_id],
      \"team_ids\": [$team_id],
      \"queue_ids\": [$queue_id]
    }" \
    "https://api.salemove.com/reporting/queued_visitors"

Generates the output

{
  "data": [
    {
      "start": "2017-06-28T00:00:00.000Z",
      "end": "2017-06-29T00:00:00.000Z",
      "chat": 20,
      "audio_video": 15
    },
    {
      "start": "2017-06-29T00:00:00.000Z",
      "end": "2017-06-30T00:00:00.000Z",
      "chat": 45,
      "audio_video": 21
    },
  ],
  "chat": 65,
  "audio_video": 36,
  "total": 101
}

Action: POST /reporting/queued_visitors

Returns an array of counts of Visitors queued for Engagements, regardless of whether waiting in Queue eventually resulted in Engagement or not.

The endpoint requires a list of site_ids.

Optionally the parameter queue_ids can be provided, in which case only the count of Visitors queued for Engagements in any of the specified Queues are returned. E.g. if queue_ids was ["ce06d2a0-f9cf-4e4b-91b8-92a0543462a7"], then the request would return queued Visitors counts aggregated over Visitors that were queued in Queue ce06d2a0-f9cf-4e4b- 91b8-92a0543462a7.

Also, optionally the parameter team_ids can be provided, in which case only the count of Visitors queued for Engagements in any of the specified Teams are returned. E.g. if team_ids was set to ["5db50064-8bf8-4c4a-98fc- 79cd04a089c5"], then the request would return counts of Visitors that were queued to have Engagements with Team 5db50064-8bf8-4c4a-98fc-79cd04a089c5. This would also include all Visitors that were queued to have Engagements with any Team.

Queued Visitor counts are grouped by media requested by the Visitor.

To download the data as CSV, see Download CSV.

Parameter Type Required Description
site_ids array Yes A list of Site IDs. Must not be empty.
team_ids array No A list of Team IDs. All Teams must belong to provided Sites.
queue_ids array No A list of Queue IDs. All Queues must belong to provided Sites.
start_date string Yes An ISO-8601 timestamp. Defines the query start date (inclusive).
end_date string Yes An ISO-8601 timestamp. Defines the query end date (exclusive).
granularity string Yes Defines the granularity to bucket query results. Can be one of month, week, day, hour

Output

Field Type Description
data array Count of queued Visitors during the period. Elements are described below.
chat integer Total count of Visitors queued for Chat Engagements during the period.
audio_video integer Total count of Visitors queued for Audio/Video Engagements during the period.
total integer Total count of queued Visitors during the period.

data

Field Type Description
start string An ISO-8601 timestamp. Start of the period (inclusive).
end string An ISO-8601 timestamp. End of the period (exclusive).
chat integer Count of Visitors queued for Chat Engagements.
audio_video integer Count of visitor queued for Audio/Video Engagements.

POST Queue Average Wait Time

curl --request POST \
    --header "Authorization: Token $token" \
    --header "Content-Type: application/json" \
    --header "Accept: application/vnd.salemove.v1+json" \
    --data-binary "{
      \"start_date\": $start_date,
      \"end_date\": $end_date,
      \"granularity\": $granularity,
      \"site_ids\": [$site_id],
      \"team_ids\": [$team_id],
      \"queue_ids\": [$queue_id]
    }" \
    "https://api.salemove.com/reporting/average_wait_time"

Generates the output

{
  "data": [
    {
      "start": "2017-06-28T00:00:00.000Z",
      "end": "2017-06-29T00:00:00.000Z",
      "chat": 60,
      "audio_video": 45
    },
    {
      "start": "2017-06-29T00:00:00.000Z",
      "end": "2017-06-30T00:00:00.000Z",
      "chat": 20,
      "audio_video": 60
    },
  ],
  "chat": 40,
  "audio_video": 50,
  "total": 30
}

Action: POST /reporting/average_wait_time

Returns an array of average times Visitors spent in Queue before being engaged with.

The endpoint requires a list of site_ids.

Optionally the parameter queue_ids can be provided, in which case only the average wait time of Visitors queued for Engagements in any of the specified Queues are returned. E.g. if queue_ids was ["ce06d2a0-f9cf-4e4b- 91b8-92a0543462a7"], then the request would return average wait times aggregated over Visitors that were queued in Queue ce06d2a0-f9cf-4e4b- 91b8-92a0543462a7.

Also, optionally the parameter team_ids can be provided, in which case only the average wait time of Visitors queued for Engagements in any of the specified Teams are returned. E.g. if team_ids was set to ["5db50064-8bf8-4c4a-98fc- 79cd04a089c5"], then the request would return average wait times aggregated over Visitors that were queued to have Engagements with Team 5db50064-8bf8-4c4a-98fc-79cd04a089c5. This would also include all Visitors that were queued to have Engagements with any Team.

Average wait times are grouped by media requested by the Visitor.

To download the data as CSV, see Download CSV.

Parameter Type Required Description
site_ids array Yes A list of Site IDs. Must not be empty.
team_ids array No A list of Team IDs. All Teams must belong to provided Sites.
queue_ids array No A list of Queue IDs. All Queues must belong to provided Sites.
start_date string Yes An ISO-8601 timestamp. Defines the query start date (inclusive).
end_date string Yes An ISO-8601 timestamp. Defines the query end date (exclusive).
granularity string Yes Defines the granularity to bucket query results. Can be one of month, week, day, hour

Output

Field Type Description
data array Average wait times during the period. Elements are described below.
chat integer Total average wait time for Chat Engagements during the period in seconds.
audio_video integer Total average wait time for Audio/Video Engagements during the period in seconds.
total integer Total average wait time during the period in seconds.

data

Field Type Description
start string An ISO-8601 timestamp. Start of the period (inclusive).
end string An ISO-8601 timestamp. End of the period (exclusive).
chat integer Average wait time of Visitors queued for Chat Engagements in seconds.
audio_video integer Average wait time of visitor queued for Audio/Video Engagements in seconds.

POST Queue Maximum Wait Time

curl --request POST \
    --header "Authorization: Token $token" \
    --header "Content-Type: application/json" \
    --header "Accept: application/vnd.salemove.v1+json" \
    --data-binary "{
      \"start_date\": $start_date,
      \"end_date\": $end_date,
      \"granularity\": $granularity,
      \"site_ids\": [$site_id],
      \"team_ids\": [$team_id],
      \"queue_ids\": [$queue_id]
    }" \
    "https://api.salemove.com/reporting/max_wait_time"

Generates the output

{
  "data": [
    {
      "start": "2017-06-28T00:00:00.000Z",
      "end": "2017-06-29T00:00:00.000Z",
      "chat": 120,
      "audio_video": 110
    },
    {
      "start": "2017-06-29T00:00:00.000Z",
      "end": "2017-06-30T00:00:00.000Z",
      "chat": 130,
      "audio_video": 145
    },
  ],
  "chat": 120,
  "audio_video": 145,
  "total": 145
}

Action: POST /reporting/max_wait_time

Returns an array of the maximum times a Visitor spent in Queue before being engaged with.

The endpoint requires a list of site_ids.

Optionally the parameter queue_ids can be provided, in which case only the maximum wait times of Visitors queued for Engagements in any of the specified Queues are returned. E.g. if queue_ids was ["ce06d2a0-f9cf-4e4b- 91b8-92a0543462a7"], then the request would return maximum wait times aggregated over Visitors that were queued in Queue ce06d2a0-f9cf-4e4b- 91b8-92a0543462a7.

Also, optionally the parameter team_ids can be provided, in which case only the maximum wait times of Visitors queued for Engagements in any of the specified Teams are returned. E.g. if team_ids was set to ["5db50064-8bf8-4c4a-98fc- 79cd04a089c5"], then the request would return maximum wait times aggregated over Visitors that were queued to have Engagements with Team 5db50064-8bf8-4c4a-98fc-79cd04a089c5. This would also include all Visitors that were queued to have Engagements with any Team.

Maximum wait times are grouped by media requested by the Visitor.

To download the data as CSV, see Download CSV.

Parameter Type Required Description
site_ids array Yes A list of Site IDs. Must not be empty.
team_ids array No A list of Team IDs. All Teams must belong to provided Sites.
queue_ids array No A list of Queue IDs. All Queues must belong to provided Sites.
start_date string Yes An ISO-8601 timestamp. Defines the query start date (inclusive).
end_date string Yes An ISO-8601 timestamp. Defines the query end date (exclusive).
granularity string Yes Defines the granularity to bucket query results. Can be one of month, week, day, hour

Output

Field Type Description
data array Maximum wait times during the period. Elements are described below.
chat integer Maximum wait time for Visitors queued for Chat Engagements during the period in seconds.
audio_video integer Maximum wait time for Visitors queued for Audio/Video Engagements during the period in seconds.
total integer Maximum wait time during the period in seconds.

data

Field Type Description
start string An ISO-8601 timestamp. Start of the period (inclusive).
end string An ISO-8601 timestamp. End of the period (exclusive).
chat integer Maximum wait time of Visitors queued for Chat Engagements in seconds.
audio_video integer Maximum wait time of visitor queued for Audio/Video Engagements in seconds.

POST Abandonment Rate

curl --request POST \
    --header "Authorization: Token $token" \
    --header "Content-Type: application/json" \
    --header "Accept: application/vnd.salemove.v1+json" \
    --data-binary "{
      \"start_date\": $start_date,
      \"end_date\": $end_date,
      \"granularity\": $granularity,
      \"site_ids\": [$site_id],
      \"team_ids\": [$team_id],
      \"queue_ids\": [$queue_id]
    }" \
    "https://api.salemove.com/reporting/abandonment_rate"

Generates the output

{
  "data": [
    {
      "start": "2017-06-28T00:00:00.000Z",
      "end": "2017-06-29T00:00:00.000Z",
      "chat": 10,
      "audio_video": 20
    },
    {
      "start": "2017-06-29T00:00:00.000Z",
      "end": "2017-06-30T00:00:00.000Z",
      "chat": 5,
      "audio_video": 7
    },
  ],
  "chat": 7,
  "audio_video": 10,
  "total": 8
}

Action: POST /reporting/abandonment_rate

Returns an array of abandonment rates for the period requested. Abandonment rate is the percentage of Visitors who leave the Queue before being able to establish an Engagment.

The endpoint requires a list of site_ids.

Optionally the parameter queue_ids can be provided, in which case only the abandonment rate of Visitors queued for Engagements in any of the specified Queues are returned. E.g. if queue_ids was ["ce06d2a0-f9cf-4e4b- 91b8-92a0543462a7"], then the request would return abandonment rates aggregated over Visitors that were queued in Queue ce06d2a0-f9cf-4e4b- 91b8-92a0543462a7.

Also, optionally the parameter team_ids can be provided, in which case only the abandonment rate of Visitors queued for Engagements in any of the specified Teams are returned. E.g. if team_ids was set to ["5db50064-8bf8-4c4a-98fc- 79cd04a089c5"], then the request would return abandonment rates aggregated over Visitors that were queued to have Engagements with Team 5db50064-8bf8-4c4a-98fc-79cd04a089c5. This would also include all Visitors that were queued to have Engagements with any Team.

Abandonment rates are grouped by media requested by the Visitor.

To download the data as CSV, see Download CSV.

Parameter Type Required Description
site_ids array Yes A list of Site IDs. Must not be empty.
team_ids array No A list of Team IDs. All Teams must belong to provided Sites.
queue_ids array No A list of Queue IDs. All Queues must belong to provided Sites.
start_date string Yes An ISO-8601 timestamp. Defines the query start date (inclusive).
end_date string Yes An ISO-8601 timestamp. Defines the query end date (exclusive).
granularity string Yes Defines the granularity to bucket query results. Can be one of month, week, day, hour

Output

Field Type Description
data array Abandonment rates during the period. Elements are described below.
chat integer Total abandonment rate for Visitors queued for Chat Engagements during the period, expressed as a percentage. Possible values range from 0 to 100.
audio_video integer Total abandonment rate for Visitors queued for Audio/Video Engagements during the period, expressed as a percentage. Possible values range from 0 to 100.
total integer Total abandonment rate during the period, expressed as a percentage. Possible values range from 0 to 100.

data

Field Type Description
start string An ISO-8601 timestamp. Start of the period (inclusive).
end string An ISO-8601 timestamp. End of the period (exclusive).
chat integer Abandonment rate of Visitors queued for Chat Engagements, expressed as a percentage. Possible values range from 0 to 100.
audio_video integer Abandonment rate of visitor queued for Audio/Video Engagements, expressed as a percentage. Possible values range from 0 to 100.

POST Service Level

curl --request POST \
    --header "Authorization: Token $token" \
    --header "Content-Type: application/json" \
    --header "Accept: application/vnd.salemove.v1+json" \
    --data-binary "{
      \"start_date\": $start_date,
      \"end_date\": $end_date,
      \"granularity\": $granularity,
      \"site_ids\": [$site_id],
      \"team_ids\": [$team_id],
      \"queue_ids\": [$queue_id]
    }" \
    "https://api.salemove.com/reporting/service_level"

Generates the output

{
  "data": [
    {
      "start": "2017-06-28T00:00:00.000Z",
      "end": "2017-06-29T00:00:00.000Z",
      "chat": 86,
      "audio_video": 60
    },
    {
      "start": "2017-06-29T00:00:00.000Z",
      "end": "2017-06-30T00:00:00.000Z",
      "chat": 84,
      "audio_video": 68
    },
  ],
  "chat": 85,
  "audio_video": 64,
  "total": 80
}

Action: POST /reporting/service_level

Returns an array of service levels.

Service level represents a percentage of the Engagements that were started before a certain amount of time. For example, when one Engagement is started after 5 seconds, three Engagements are started after 15 seconds and service level threshold is set to 10 seconds, the service level would be 25%.

Service level time threshold can be configured per site.

The endpoint requires a list of site_ids.

Optionally the parameter queue_ids can be provided, in which case only the service levels for Visitors that waited in any of the specified Queues are returned. E.g. if queue_ids was ["ce06d2a0-f9cf-4e4b-91b8-92a0543462a7"], then the request would return service levels aggregated over Visitors that were queued in Queue ce06d2a0-f9cf-4e4b-91b8-92a0543462a7.

Also, optionally the parameter team_ids can be provided. In this case only the service levels for Visitors queued for any of the specified Team are returned. E.g. if team_ids was set to ["5db50064-8bf8-4c4a-98fc-79cd04a089c5"], then the request would return service levels aggregated over Visitors that were queued to have Engagements with Team 5db50064-8bf8-4c4a-98fc-79cd04a089c5. This would also include all Visitors that were queued to have Engagements with any Team.

The requester must have access to the Sites. All specified Queues and Teams must belong to the Sites.

To download the data as CSV, see Download CSV.

Parameter Type Required Description
site_ids array Yes A list of Site IDs. Must not be empty.
team_ids array No A list of Team IDs. All Teams must belong to provided Sites.
queue_ids array No A list of Queue IDs. All Queues must belong to provided Sites.
start_date string Yes An ISO-8601 timestamp. Defines the query start date (inclusive).
end_date string Yes An ISO-8601 timestamp. Defines the query end date (exclusive).
granularity string Yes Defines the granularity to bucket query results. Can be one of month, week, day, hour

Output

Field Type Description
data array Service levels during the period. Elements are described below.
chat integer Chat service level during the period, expressed as a percentage. Possible values range from 0 to 100.
audio_video integer Audio/Video service level during the period, expressed as a percentage. Possible values range from 0 to 100.
total integer Total service level during the period, expressed as a percentage. Possible values range from 0 to 100.

data

Field Type Description
start string An ISO-8601 timestamp. Start of the period (inclusive).
end string An ISO-8601 timestamp. End of the period (exclusive).
chat integer Chat service level, expressed as a percentage. Possible values range from 0 to 100.
audio_video integer Audio/Video service level, expressed as a percentage. Possible values range from 0 to 100.

POST Average Handling Time

curl --request POST \
    --header "Authorization: Token $token" \
    --header "Content-Type: application/json" \
    --header "Accept: application/vnd.salemove.v1+json" \
    --data-binary "{
      \"start_date\": $start_date,
      \"end_date\": $end_date,
      \"granularity\": $granularity,
      \"site_ids\": [$site_id],
      \"team_ids\": [$team_id],
      \"queue_ids\": [$queue_id],
      \"include_without_queues\": $include_without_queues
    }" \
    "https://api.salemove.com/reporting/average_handling_time"

Generates the output

{
  "data": [
    {
      "start": "2017-06-28T00:00:00.000Z",
      "end": "2017-06-29T00:00:00.000Z",
      "chat": 120,
      "audio_video": 150
    },
    {
      "start": "2017-06-29T00:00:00.000Z",
      "end": "2017-06-30T00:00:00.000Z",
      "chat": 52,
      "audio_video": 62
    },
  ],
  "chat": 100,
  "audio_video": 120,
  "total": 110
}

Action: POST /reporting/average_handling_time

Returns an array of average Engagement durations in seconds. The endpoint requires a list of site_ids.

Optionally the parameter queue_ids can be provided. In this case the endpoint returns average Engagement durations for Engagements which resulted from any of the specified Queues.

Optionally the parameter team_ids can be provided. In this case the endpoint returns average Engagement durations only for Operators that belong to any of the specified Teams.

To download the data as CSV, see Download CSV.

Parameter Type Required Description
site_ids array Yes A list of Site IDs. Must not be empty.
team_ids array No A list of Team IDs. All Teams must belong to provided Sites.
queue_ids array No A list of Queue IDs. All Queues must belong to provided Sites.
start_date string Yes An ISO-8601 timestamp. Defines the query start date (inclusive).
end_date string Yes An ISO-8601 timestamp. Defines the query end date (exclusive).
granularity string Yes Defines the granularity to bucket query results. Can be one of month, week, day, hour
include_without_queues boolean No If true, includes results that are not associated with any Queues. If false, excludes results that are not associated with Queues. Default value is true.

Output

Field Type Description
data array Average Engagement durations during the period. Elements are described below.
chat integer Average chat Engagement duration during the period in seconds.
audio_video integer Average audio/video Engagement duration during the period in seconds.
total integer Total average Engagement duration during the period in seconds.

data

Field Type Description
start string An ISO-8601 timestamp. Start of the period (inclusive).
end string An ISO-8601 timestamp. End of the period (exclusive).
chat integer Average chat Engagement duration during the period in seconds.
audio_video integer Average audio/video Engagement duration during the period in seconds.

POST Operators

curl --request POST \
    --header "Authorization: Token $token" \
    --header "Content-Type: application/json" \
    --header "Accept: application/vnd.salemove.v1+json" \
    --data-binary "{
      \"start_date\": $start_date,
      \"end_date\": $end_date,
      \"site_ids\": [$site_id],
      \"team_ids\": [$team_id]
    }" \
    "https://api.salemove.com/reporting/operators"

Generates the output

{
  "operators": [
    {
      "id": "c8b52f0b-ad05-4c71-8c98-5056f07c4d1a",
      "name": "Operator One",
      "email": "operatorone@example.com",
      "picture_url": "https://picture.url.com/operator_one_picture.jpg",
      "teams": [
        {
          "name": "Team One"
        },
        {
          "name": "Team Two"
        }
      ],
      "stats": {
        "engagement_count": {
          "chat": 20,
          "audio_video": 10,
          "total": 30
        },
        "engagement_request_outcomes_count": {
          "reactive": {
            "accepted": 16,
            "rejected": 1,
            "timed_out": 3,
            "visitor_cancel": 2,
            "operator_left": 0,
            "visitor_left": 0,
            "total": 22
          },
          "proactive": {
            "accepted": 14,
            "rejected": 6,
            "timed_out": 4,
            "operator_cancel": 1,
            "operator_left": 0,
            "visitor_left": 0,
            "total": 25
          }
        },
        "available_while_engaged_time": 120,
        "available_time": {
          "audio_video": 125,
          "chat": 500
        },
        "unavailable_time": {
          "engaged": 900,
          "post_engagement": 100,
          "with_customer": 3452,
          "quick_break": 1300,
          "meal_break": 3045,
          "total": 8926
        }
      }
    },
    {
      "id": "f42811bc-8519-4d33-bbb1-36d4555ecb0a",
      "name": "Operator Two",
      "email": "operatortwo@example.com",
      "picture_url": "https://picture.url.com/operator_two_picture.jpg",
      "teams": [
        {
          "name": "Team Two"
        }
      ],
      "stats": {
        "engagement_count": {
          "chat": 44,
          "audio_video": 11,
          "total": 55
        },
        "engagement_request_outcomes_count": {
          "reactive": {
            "accepted": 30,
            "rejected": 1,
            "timed_out": 3,
            "visitor_cancel": 2,
            "operator_left": 0,
            "visitor_left": 0,
            "total": 36
          },
          "proactive": {
            "accepted": 25,
            "rejected": 3,
            "timed_out": 3,
            "operator_cancel": 2,
            "operator_left": 0,
            "visitor_left": 0,
            "total": 33
          }
        },
        "available_while_engaged_time": 300,
        "available_time": {
          "audio_video": 500,
          "chat": 1200
        },
        "unavailable_time": {
          "engaged": 1000,
          "post_engagement": 100,
          "quick_break": 1500,
          "meal_break": 1100,
          "training": 6000,
          "lunch": 2000,
          "other": 100,
          "total": 11800
        }
      }
    },
    {
      "id": "2e56b224-6708-4755-b6c9-35f9889e42dd",
      "name": "Operator Three",
      "email": "operatorthree@example.com",
      "picture_url": "https://picture.url.com/operator_three_picture.jpg",
      "teams": [
        {
          "name": "Team Three"
        }
      ],
      "stats": {
        "engagement_count": {
          "chat": 20,
          "audio_video": 5,
          "total": 25
        },
        "engagement_request_outcomes_count": {
          "reactive": {
            "accepted": 15,
            "rejected": 0,
            "timed_out": 2,
            "visitor_cancel": 1,
            "operator_left": 0,
            "visitor_left": 0,
            "total": 18
          },
          "proactive": {
            "accepted": 10,
            "rejected": 1,
            "timed_out": 1,
            "operator_cancel": 2,
            "operator_left": 0,
            "visitor_left": 0,
            "total": 14
          }
        },
        "available_while_engaged_time": 0,
        "available_time": {
          "audio_video": 400,
          "chat": 500
        },
        "unavailable_time": {
          "engaged": 1000,
          "quick_break": 200,
          "advanced_admin": 100,
          "statistics": 200,
          "total": 1500
        }
      }
    }
  ]
}

Action: POST /reporting/operators

Returns a list of Operators belonging to the queried Sites and Teams and their respective reporting statistics. The endpoint requires a list of site_ids. Optionally the parameter team_ids can be provided. In this case only the data for Operators belonging to the specified Teams is returned. The requester must have access to the Sites and all specified Teams must belong to the Sites.

By specifying the Accept header application/vnd.salemove.v1+csv data will be returned in CSV format.

The sub-keys in column names of CSV output are separated by / delimiter. All Team names are grouped under one column, separated by ; delimiter.

curl --request POST \
    --header "Authorization: Token $token" \
    --header "Content-Type: application/json" \
    --header "Accept: application/vnd.salemove.v1+csv" \
    --data-binary "{
      \"start_date\": $start_date,
      \"end_date\": $end_date,
      \"site_ids\": [$site_id],
      \"team_ids\": [$team_id]
    }" \
    "https://api.salemove.com/reporting/operators"

Generates the output

Operator ID,Name,Email,Picture URL,Team(s),Total Eng Count,A/V Eng Count,Chat Eng Count,Proactive Call Count,Missed Call Count,Declined Call Count,Eng (min),Post-Eng (min),Avail. A/V (min),Avail. Chat (min),Avail. While Eng (min),U/A (min),Bathroom (min),Break (min),Training (min),Lunch (min),Statistics (min)
c8b52f0b-ad05-4c71-8c98-5056f07c4d1a,Operator One,operatorone@example.com,https://picture.url.com/operator_one_picture.jpg,Team One;Team Two,30,10,20,25,3,1,15,1.67,2.08,8.33,2,38.34,0,21.67,0,0,0
f42811bc-8519-4d33-bbb1-36d4555ecb0a,Operator Two,operatortwo@example.com,https://picture.url.com/operator_two_picture.jpg,Team Two,55,11,44,33,3,2,16.67,1.67,8.33,20,5,176.74,0.07,25,100,33.33,0
2e56b224-6708-4755-b6c9-35f9889e42dd,Operator Three,operatorthree@example.com,https://picture.url.com/operator_three_picture.jpg,Team Three,25,5,20,14,2,0,16.67,0,6.67,8.33,0,20,0,0,0,0,3.33
Parameter Type Required Description
site_ids array Yes A list of Site IDs. Must not be empty.
team_ids array No A list of Team IDs. All Teams must belong to provided Sites.
start_date string Yes An ISO-8601 timestamp. Defines the query start date (inclusive).
end_date string Yes An ISO-8601 timestamp. Defines the query end date (exclusive).

Output

Field Type Description
operators array Historical data for Operators. Elements are described below.

operators

Field Type Description
id string Operator ID.
name string Full name of the Operator.
email string Email of the Operator.
picture_url string Current Operator picture. null if no picture is currently set.
teams array Array of the Teams the Operator belongs to. Elements described below.
stats object Operator’s reporting statistics for the requested time period. Elements described below.

teams

Field Type Description
name string Team name.

stats

Field Type Description
engagement_count object Object representing the count of Engagements the Operator has participated in. Elements described below.
available_while_engaged_time integer Time Operator has been in Engagements while being available for other Engagements during the requested time period (in seconds).
available_time object Object representing the time Operator has been available for Engagements. Elements described below.
unavailable_time object Object representing the time Operator has been unavailable for new Engagements. Elements described below.

engagement_count

Field Type Description
chat integer Count of Chat Engagements the Operator has participated in during the requested time period.
audio_video integer Count of Audio/Video Engagements the Operator has participated in during the requested time period.
total integer Total count of Engagements the Operator has participated in during the requested time period.

engagement_request_outcomes_count

Field Type Description
reactive object Object representing the outcome count for Engagement Requests created by the Operator.
proactive object Object representing the outcome count for Engagement Requests received by the Operator.

reactive

Field Type Description
accepted integer Count of reactive Engagement Requests accepted by the Operator.
rejected integer Count of reactive Engagement Requests rejected by the Operator.
timed_out integer Count of reactive Engagement Requests that timed out before being accepted by the Operator.
visitor_cancel integer Count of reactive Engagement Requests to the Operator cancelled by Visitor.
operator_left integer Count of reactive Engagement Requests during which the Operator left.
visitor_left integer Count of reactive Engagement Requests to the Operator during which Visitor left.

proactive

Field Type Description
accepted integer Count of proactive Engagement Requests created by the Operator accepted by a Visitor.
rejected integer Count of proactive Engagement Requests created by the Operator rejected by a Visitor.
timed_out integer Count of proactive Engagement Requests created by the Operator that timed out before being accepted by a Visitor.
operator_cancel integer Count of proactive Engagement Requests cancelled by the Operator.
operator_left integer Count of proactive Engagement Requests created by the Operator during which the Operator left.
visitor_left integer Count of proactive Engagement Requests created by the Operator during which Visitor left.

available_time

Field Type Description
audio_video integer Time Operator has been available for Audio/Video Engagements during the requested time period (in seconds).
chat integer Time Operator has been available for Chat Engagements during the requested time period (in seconds).

unavailable_time

Values in unavailable_time object indicate time the Operator has been unavailable for new Engagements. This list is not all-inclusive as each Site can be configured to have its own unavailability types. All entries valued 0 are omitted (with the exception of total, which is always present).

Field Type Description
engaged integer Time Operator has been in Engagements during the requested time period (in seconds).
post_engagement integer Time Operator has spent being in post-engagement during the requested time period (in seconds).
advanced_admin integer Time Operator has spent being in Advanced Admin during the requested time period (in seconds).
statistics integer Time Operator has spent being in Advanced Statistics during the requested time period (in seconds).
idle integer Time Operator has spent being Idle during the requested time period (in seconds). Operator is set to “Idle” after a missed engagement or transfer request if “Automatic missed call unavailability” option is enabled for the Site.
... integer Any other status the Operator has set for the reason of being unavailable for Engagements (in seconds). These statuses include (but are not limited to) meal_break, restroom, quick_break, training and with_customer.
total integer Total time Operator has spent being unavailable during the requested time period (in seconds).

POST Live Queue Maximum Wait Time

curl --request POST \
    --header "Authorization: Token $token" \
    --header "Content-Type: application/json" \
    --header "Accept: application/vnd.salemove.v1+json" \
    --data-binary '{
      "site_ids": ["$site_id"],
      "queue_ids": ["$queue_id"],
      "team_ids": ["$team_id"]
    }' \
    "https://api.salemove.com/reporting/live/queue/max_wait_time"

Generates the output

{
  "chat": 45,
  "audio": 20,
  "video": 32,
  "any": 45
}

Action: POST /reporting/live/queue/max_wait_time

Returns the longest waiting duration among currently queued Visitors. The response includes the maximum waiting time for any Visitor and separate waiting times for Visitors waiting for Engagements with a specific medium.

The endpoint requires a list of site_ids.

Optionally the parameter queue_ids can be provided, in which case only the maximum wait times of Visitors waiting in any of the specified Queues are returned. E.g. if queue_ids was ["ce06d2a0-f9cf-4e4b-91b8-92a0543462a7"], then the request would return maximum wait times aggregated over Visitors that were queued in Queue ce06d2a0-f9cf-4e4b-91b8-92a0543462a7.

Also, optionally the parameter team_ids can be provided, in which case only the maximum wait times of Visitors queued for any of the specified Teams are returned. E.g. if team_ids was set to ["5db50064-8bf8-4c4a-98fc-79cd04a089c5"], then the request would return maximum wait times aggregated over Visitors that were queued to have Engagements with Team 5db50064-8bf8-4c4a-98fc-79cd04a089c5. This would also include all Visitors that were queued to have Engagements with any Team.

The requester must have access to the Sites. All specified Queues and Teams must belong to the Sites.

Parameter Type Required Description
site_ids array Yes A list of Site IDs. Must not be empty.
queue_ids array No A list of Queue IDs. All Queues must belong to provided Sites.
team_ids array No A list of Team IDs. All Teams must belong to provided Sites.

Output

Field Type Description
chat integer Maximum wait time of Visitors queued for Chat Engagements (in seconds).
audio integer Maximum wait time of Visitors queued for Audio Engagements (in seconds).
video integer Maximum wait time of Visitors queued for Video Engagements (in seconds).
any integer Maximum wait time of Visitors queued for any kind of Engagements (in seconds).

POST Live Queue Average Wait Time

curl --request POST \
    --header "Authorization: Token $token" \
    --header "Content-Type: application/json" \
    --header "Accept: application/vnd.salemove.v1+json" \
    --data-binary '{
      "site_ids": ["$site_id"],
      "queue_ids": ["$queue_id"],
      "team_ids": ["$team_id"]
    }' \
    "https://api.salemove.com/reporting/live/queue/average_wait_time"

Generates the output

{
  "chat": 45,
  "audio": 20,
  "video": 32,
  "audio_video": 22,
  "total": 37
}

Action: POST /reporting/live/queue/average_wait_time

Returns the average waiting duration among currently queued Visitors. The response includes the total average waiting time for all Visitors and separate waiting times for Visitors waiting for Engagements with a specific medium.

The endpoint requires a list of site_ids.

Optionally the parameter queue_ids can be provided, in which case only the average wait times of Visitors waiting in any of the specified Queues are returned. E.g. if queue_ids was ["ce06d2a0-f9cf-4e4b-91b8-92a0543462a7"], then the request would return average wait times aggregated over Visitors that were queued in Queue ce06d2a0-f9cf-4e4b-91b8-92a0543462a7.

Also, optionally the parameter team_ids can be provided, in which case only the average wait times of Visitors queued for any of the specified Teams are returned. E.g. if team_ids was set to ["5db50064-8bf8-4c4a-98fc-79cd04a089c5"], then the request would return average wait times aggregated over Visitors that were queued to have Engagements with Team 5db50064-8bf8-4c4a-98fc-79cd04a089c5. This would also include all Visitors that were queued to have Engagements with any Team.

The requester must have access to the Sites. All specified Queues and Teams must belong to the Sites.

Parameter Type Required Description
site_ids array Yes A list of Site IDs. Must not be empty.
queue_ids array No A list of Queue IDs. All Queues must belong to provided Sites.
team_ids array No A list of Team IDs. All Teams must belong to provided Sites.

Output

Field Type Description
chat integer Average wait time of Visitors queued for Chat Engagements (in seconds).
audio integer Average wait time of Visitors queued for Audio Engagements (in seconds).
video integer Average wait time of Visitors queued for Video Engagements (in seconds).
audio_video integer Average wait time of Visitors queued for Audio/Video Engagements (in seconds).
total integer Total average wait time of queued Visitors (in seconds).

POST Live Queued Visitors Count

curl --request POST \
    --header "Authorization: Token $token" \
    --header "Content-Type: application/json" \
    --header "Accept: application/vnd.salemove.v1+json" \
    --data-binary '{
      "site_ids": ["$site_id"],
      "queue_ids": ["$queue_id"],
      "team_ids": ["$team_id"]
    }' \
    "https://api.salemove.com/reporting/live/queue/visitor_count"

Generates the output

{
  "chat": 10,
  "audio": 15,
  "video": 15,
  "total": 40
}

Action: POST /reporting/live/queue/visitor_count

Returns the number of Visitors who are currently waiting in a queue. The response includes a total count of all Visitors and separate counts for Visitors queued for Engagements with a specific medium.

The endpoint requires a list of site_ids.

Optionally the parameter queue_ids can be provided, in which case only the counts of Visitors waiting in any of the specified Queues are returned. E.g. if queue_ids was ["ce06d2a0-f9cf-4e4b-91b8-92a0543462a7"], then the request would return counts of Visitors that were queued in Queue ce06d2a0-f9cf-4e4b-91b8-92a0543462a7.

Also, optionally the parameter team_ids can be provided, in which case only the counts of Visitors queued for any of the specified Teams are returned. E.g. if team_ids was set to ["5db50064-8bf8-4c4a-98fc-79cd04a089c5"], then the request would return counts of Visitors that were queued to have Engagements with Team 5db50064-8bf8-4c4a-98fc-79cd04a089c5. This would also include all Visitors that were queued to have Engagements with any Team.

The requester must have access to the Sites. All specified Queues and Teams must belong to the Sites.

Parameter Type Required Description
site_ids array Yes A list of Site IDs. Must not be empty.
queue_ids array No A list of Queue IDs. All Queues must belong to provided Sites.
team_ids array No A list of Team IDs. All Teams must belong to provided Sites.

Output

Field Type Description
chat integer Count of Visitors queued for Chat Engagements.
audio integer Count of Visitors queued for Audio Engagements.
video integer Count of Visitors queued for Video Engagements.
total integer Count of queued Visitors.

POST Live Engagement Count

curl --request POST \
    --header "Authorization: Token $token" \
    --header "Content-Type: application/json" \
    --header "Accept: application/vnd.salemove.v1+json" \
    --data-binary '{
      "site_ids": ["$site_id"],
      "team_ids": ["$team_id"]
    }' \
    "https://api.salemove.com/engagements/live/count"

Generates the output

{
  "chat": 5,
  "audio": 2,
  "video": 1,
  "total": 15
}

Action: POST /engagements/live/count

Returns the count of text, audio, video and total ongoing Engagements for provided Sites and Teams. The endpoint requires a list of site_ids. Optionally the parameter team_ids can be provided. In this case only the count of Engagements for Operators belonging to the specified Teams is returned. The requester must have access to the Sites and all specified Teams must belong to the Sites.

Parameter Type Required Description
site_ids array Yes A list of Site IDs. Must not be empty.
team_ids array No A list of Team IDs. All Teams must belong to provided Sites.

Output

Field Type Description
chat integer Number of ongoing text (chat) Engagements for provided Sites and Teams.
audio integer Number of ongoing audio Engagements for provided Sites and Teams.
video integer Number of ongoing video Engagements for provided Sites and Teams.
total integer Number of all ongoing Engagements for provided Sites and Teams.

POST Live Engaged Operators Count

curl --request POST \
    --header "Authorization: Token $token" \
    --header "Content-Type: application/json" \
    --header "Accept: application/vnd.salemove.v1+json" \
    --data-binary '{
      "site_ids": ["$site_id"],
      "team_ids": ["$team_id"],
      "include_support": $include_support
    }' \
    "https://api.salemove.com/operators/engaged/count"

Generates the Output

{
  "chat": 3,
  "audio": 2,
  "video": 1,
  "total": 6
}

Action: POST /operators/engaged/count

Returns the number of Operators who are currently engaged. The response includes a total count of all Operators and separate counts for Operators engaged with a specific medium.

The requester must have access to the Sites. All specified Teams must belong to the Sites.

Parameter Type Required Description
include_support boolean No If true, includes Operators from SaleMove support staff. The default value is false.
site_ids array Yes A list of Site IDs. Must not be empty.
team_ids array No A list of Team IDs. All Teams must belong to provided Sites.

POST Live Unengaged Operators Count

curl --request POST \
    --header "Authorization: Token $token" \
    --header "Content-Type: application/json" \
    --header "Accept: application/vnd.salemove.v1+json" \
    --data-binary '{
      "site_ids": ["$site_id"],
      "team_ids": ["$team_id"],
      "include_support": $include_support
    }' \
    "https://api.salemove.com/operators/unengaged/count"

Generates the Output

{
  "chat": 3,
  "audio": 2,
  "video": 1,
  "unavailable": 1,
  "total": 7
}

Action: POST /operators/unengaged/count

Returns the number of Operators who are currently not engaged. The response includes a total count of all Operators and separate counts for Operators who are unengaged but available with a specific medium as well as Operators who are unavailable.

The requester must have access to the Sites. All specified Teams must belong to the Sites.

Parameter Type Required Description
include_support boolean No If true, includes Operators from SaleMove support staff. The default value is false.
site_ids array Yes A list of Site IDs. Must not be empty.
team_ids array No A list of Team IDs. All Teams must belong to provided Sites.

Exports

A Site can have any number of Export configurations, known as definitions. A definition is a set of attributes that describe how either Engagements or Offline Messages, known cumulatively as Leads, are exported. When SaleMove generates a Lead, it is exported to all recipients included in the definition that have access to the Site. Export definitions can be organized into folders.

Export Types

Exports have different Types, depending on how they are triggered:

Type Known as Trigger
engagement_start Engagement Start Export Start of an engagement
engagement_transfer Engagement Transfer Export Engagement transfer. The export will be triggered after a successful transfer
engagement Engagement End Export Ending of an engagement
inbox_message Generic Message Export, Inbox Message Export A message is left by a Visitor and no specific Operator has been identified for that message
operator_message Operator Message Export A message is left by a Visitor for a specific Operator
voicemail Voicemail Export A Voicemail is left by a Visitor calling an Incoming Phone Number

Definitions

An Export definition can have the following parameters:

Parameter Type Description
name string A descriptive title for the Export.
type string The type of Lead it exports. Accepted values are engagement_start, engagement_transfer, engagement, inbox_message, operator_message and voicemail. See Export Types
content_type string This specifies the content-type of the Export definition. Supported values are: text/html; charset=UTF-8, application/xml, and application/json.
email_recipient object A JSON object describing how Leads are sent via email.
crm_recipient object A JSON object describing how the Leads are sent via HTTP POST.
template string A template in XML, JSON, or HTML format that will be used as the template for the content of the export. The template must be in UTF-8 encoding.
enabled boolean Specifies whether the Export is active.
updated_by string Email of the Operator who last updated the Export template. This field is only returned in responses and cannot be sent in requests.
send_to_operator boolean Specifies whether the Export is sent to corresponding Operator(s). For Export type engagement, the Export is sent to all Operators who participated in the Engagement. For Export type inbox_message, the Export is sent to all Operators associated with the Site.
trigger string Specifies whether the Export template should be triggered automatically, or only when the Operator explicitly opts in. Possible values are, respectively, system and on_demand
created_at date The dateTime the Export was created.
updated_at date The dateTime the Export was last updated.
folder_id string Uniquely identifies the folder to which the Export belongs.
email_subject string The subject for Exports sent by email. A subject can contain field tags to dynamically include Export-specific data. (For more information, see Field Tags, below.

Note: Data returned using field tags in a JSON template are automatically enclosed in quotation marks when appropriate for their data type. For example: {visitor_name} yields "Sasha Brown".

The parameter email_recipient should include two attributes:

Attribute Type Description
enabled boolean This specifies whether the Export should be sent by email. Valid values are true and false.
emails array An array of email addresses to which the Export should be sent.

The parameter crm_recipient should include three attributes:

Attribute Type Description
enabled boolean This specifies whether the Export should be sent by HTTP POST. Valid values are true and false.
url string The URL to which the Export should be sent.
headers headers A set of headers to be sent along with the HTTP POST request. Typically, headers are used for authorization.

The template parameter may contain field tags, which are enclosed with braces {}, signaling them to be parsed and replaced with their values from the Lead when an Export occurs. For example, where {visitor_name} appears in a template, a Lead’s name will appear in each Export defined by that template. Below is a table listing the field tags that can be included in the template, and describing the data that will dynamically replace them.

Field Tags

The following field tags can be used in templates for Engagement Start Exports:

Field Type Description
custom_fields collection Visitor’s custom attributes. See custom_fields
engagement_id string Engagement ID
operator_email string Operator Email
operator_id string Operator ID
operator_name string Operator Name
platform string The platform where the Engagement was initiated. Possible values are omnicore and omnibrowse
queue_wait_time integer The time Visitor spent in Queue waiting for the Engagement. Specified in seconds.
queues collection A list of Queues that the Visitor was enqueued in before starting the Engagement. See queues
site_id string Site ID
source string Engagement source. One of Engagement sources
visitor_email string Visitor Email
visitor_id string Visitor ID
visitor_name string Visitor Name
visitor_phone string Visitor Phone

The following field tags can be used in templates for Engagement Transfer Exports:

Field Type Description
custom_fields collection Visitor’s custom attributes. See custom_fields
engagement_id string Engagement ID
operator_email string Receiving Operator Email
operator_id string Receiving Operator ID
operator_name string Receiving Operator Name
site_id string ID of the Site where the Engagement was transferred to
source string Engagement source. One of Engagement sources
visitor_email string Visitor Email
visitor_id string Visitor ID
visitor_name string Visitor Name
visitor_phone string Visitor Phone

The following field tags can be used in templates for Engagement End Exports:

Field Type Description Formatting in HTML templates
appointment_scheduled_at dateTime Scheduled appointment’s timestamp Full date with 24-hour time (in site’s timezone), e.g. September 14th, 2016 15:00
audio_used boolean Whether audio was used in the Engagement Yes/No
chat_transcript_plain_text string Chat transcript of the Engagement in plain text. For each message: *SENDER_NAME*: CONTENT concatenated in a single line. Note that there also exists a structured field, chat_transcript, which can be called via GET request. See Engagements.
chat_transcript collection The collection of Chat messages exchanged between the Visitor and the Operator, including system messages the Operator received during the Engagement. See chat_transcript
cobrowsing_used boolean Whether CoBrowsing was used in the Engagement Yes/No
crm_forwarded boolean Whether the CRM Export has already occurred Yes/No
custom_fields collection A collection of the Visitor’s custom attributes. See custom_fields
engagement_duration integer The Engagement duration in seconds Duration in seconds, e.g. 1 second or 427 seconds
engagement_ended_at dateTime The Engagement end timestamp Full date with 24-hour time (in site’s timezone), e.g. September 14th, 2016 15:00
engagement_flagged boolean Whether the Engagement has been flagged Yes/No
engagement_id string Unique identifier for the Engagement
engagement_started_at dateTime The Engagement start timestamp Full date with 24-hour time (in site’s timezone), e.g. September 14th, 2016 15:00
engagement_type string The Engagement type. Either reactive or proactive
initiator string The initiator of the Engagement. Either visitor or operator
notes string Notes by Operator(s) from the Engagement
operator_shared_screen boolean Whether the Operator shared their screen during the Engagement Yes/No
operators collection Operators who participated in the Engagement and their unique identifiers. See operators
platform string The platform where the Engagement was initiated. Possible values are omnicore and omnibrowse
queue_wait_time integer The time Visitor spent in Queue waiting for the Engagement. Specified in seconds. Duration in seconds, e.g. 1 second or 427 seconds
queues collection A list of Queues that the Visitor was enqueued in before starting the Engagement. See queues
site_name string Name of the Site where the Engagement began
site_names collection Names of Sites visited during an Engagement. See site_names
source string Engagement source. One of Engagement sources
summary_forwarded boolean Whether the summary has already been forwarded Yes/No
video_used boolean Whether video was used in the Engagement Yes/No
visitor_browser string Visitor browser
visitor_device_type string Visitor device type. Accepted values are mobile and desktop
visitor_email string Visitor email
visitor_last_name string Visitor last name
visitor_name string Visitor name
visitor_phone string Visitor phone
visitor_shared_screen boolean Whether the Visitor shared their screen during the Engagement Yes/No

The following field tags can be used in templates for Inbox Message and Operator Message Exports:

Field Type Description
custom_fields collection Visitor’s custom attributes. See custom_fields
message_id string Message ID
message_sent_at dateTime Timestamp for when the Message was sent
message string Message left by Visitor
site_name string Site name
visitor_email string Visitor Email
visitor_name string Visitor Name
visitor_phone string Visitor Phone

The following field tags can be used in templates for Voicemail Exports:

Field Type Description
incoming_phone_number string The Incoming Phone Number dialed by the Visitor
recording_duration integer Duration of the recording in seconds
site_id string Site ID
visitor_phone_number string Visitor Phone number
voice_mailbox_id string ID of the Voice Mailbox that recorded the Voicemail
voicemail_url string URL pointing to the recording of the Voicemail
last_queue_id string The ID of the Queue that the call was in last. This might be different from the Queue that the call started in when the call was transferred to a Queue. Note that this field is empty if the call was immediately rejected and never entered a Queue

Collection Tags

Some templated field tags return multiple items, such as Operators who participated in an Engagement or the custom attributes of a Visitor who left an Offline Message. These are called collection_tags, and generate XML, JSON, or HTML content, depending on the template’s content-type. Available collection_tags include:

site_names

XML Template using {site_names} tag

<?xml version='1.0' encoding='utf-8'?><export>{site_names}<export>

XML Output

<?xml version='1.0' encoding='utf-8'?>
  <export>
    <site>
      <name>Company Service Site<name>
    </site>
    <site>
      <name>Company Sales Site<name>
    </site>
  <export>

JSON Template using {site_names} tag

{"sites": {site_names}}

JSON Output

{
  "sites": [
    {
      "name": "Company Service Site"
    },
    {
      "name": "Company Sales Site"
    }
  ]
}

HTML Template using {site_names} tag

<div class="site-container">{site_names}</div>

HTML Output

<div class="sites">
  <div class="sm-site-container">
    <div class="sm-site-name-label">Name</div>
    <div class="sm-site-name">Company Service Site</div>
  </div>
  <div class="sm-site-container">
    <div class="sm-site-name-label">Name</div>
    <div class="sm-site-name">Company Sales Site</div>
  </div>
</div>

Available only for Engagement End Exports

Returns the names of Sites visited during an Engagement. Shown in the right are examples of templates and the formats of their resulting outputs.

Note: For Inbox Message and Operator Message Exports, the {site_names} collection tag is deprecated. Please refer to Field Tags, above, to include a Site’s name in your Export template for these Lead options.

operators

XML Template using {operators} tag

<?xml version='1.0' encoding='utf-8'?><export>{operators}</export>

XML OUtput

<?xml version='1.0' encoding='utf-8'?>
<export>
  <operator>
    <name>Jordan Green</name>
    <email>jordan.green@company.com</email>
    <id>c8b52f0b-ad05-4c71-8c98-5056f07c4d1a</id>
  </operator>
  <operator>
    <name>Jared Grey</name>
    <email>jared.grey@company.com</email>
    <id>f42811bc-8519-4d33-bbb1-36d4555ecb0a</id>
  </operator>
</export>

JSON Template using {operators} tag

{"operators": {operators}}

JSON Output

{
  "operators":[
    {
      "name":"Jordan Green",
      "email":"jordan.green@company.com",
      "id":"c8b52f0b-ad05-4c71-8c98-5056f07c4d1a"
    },
    {
      "name":"Jared Grey",
      "email":"jared.grey@company.com",
      "id":"f42811bc-8519-4d33-bbb1-36d4555ecb0a"
    }
  ]
}

HTML Template using {operators} tag

<div class="operators">{operators}</div>

HTML Output

<div class="operators">
  <div class="sm-operator-container">
    <div class="sm-operator-name-label">Name</div>
    <div class="sm-operator-name">Jordan Green</div>

    <div class="sm-operator-email-label">Email</div>
    <div class="sm-operator-email">jordan.green@company.com</div>

    <div class="sm-operator-id-label">id</div>
    <div class="sm-operator-id">c8b52f0b-ad05-4c71-8c98-5056f07c4d1a</div>
  </div>
  <div class="sm-operator-container">
    <div class="sm-operator-name-label">Name</div>
    <div class="sm-operator-name">Jared Grey</div>

    <div class="sm-operator-email-label">Email</div>
    <div class="sm-operator-email">jared.grey@company.com</div>

    <div class="sm-operator-id-label">id</div>
    <div class="sm-operator-id">f42811bc-8519-4d33-bbb1-36d4555ecb0a</div>
  </div>
</div>

Available only for Engagement End Exports

Returns Operators who participated in the Engagement and their unique identifiers. Shown in the right are examples of templates and the formats of their resulting outputs.

queues

XML Template using {queues} tag

<?xml version='1.0' encoding='utf-8'?><export>{queues}</export>

XML OUtput

<?xml version='1.0' encoding='utf-8'?>
<export>
  <queue>
    <name>Default Queue</name>
    <id>82af2b5d-4ea5-40c8-bab2-a87d39598a81</id>
  </queue>
  <queue>
    <name>Priority Queue</name>
    <id>d3fe1379-f113-4285-80cf-16f5b924ca24</id>
  </queue>
</export>

JSON Template using {queues} tag

{"queues": {queues}}

JSON Output

{
  "queues":[
    {
      "name":"Default Queue",
      "id":"82af2b5d-4ea5-40c8-bab2-a87d39598a81"
    },
    {
      "name":"Priority Queue",
      "id":"d3fe1379-f113-4285-80cf-16f5b924ca24"
    }
  ]
}

HTML Template using {queues} tag

<div class="queues">{queues}</div>

HTML Output

<div class="queues">
  <div class="sm-queue-container">
    <div class="sm-queue-name-label">Name</div>
    <div class="sm-queue-name">Default Queue</div>

    <div class="sm-queue-id-label">id</div>
    <div class="sm-queue-id">82af2b5d-4ea5-40c8-bab2-a87d39598a81</div>
  </div>
  <div class="sm-queue-container">
    <div class="sm-queue-name-label">Name</div>
    <div class="sm-queue-name">Priority Queue</div>

    <div class="sm-queue-id-label">id</div>
    <div class="sm-queue-id">d3fe1379-f113-4285-80cf-16f5b924ca24</div>
  </div>
</div>

Available for Engagement Start Exports and Engagement End Exports

A list of Queues that the Visitor was enqueued in before starting the Engagement. This collection tag will be populated only for reactive Engagements started started via queueing. Shown in the right are examples of templates and the formats of their resulting outputs.

custom_fields

XML Template using {custom_fields} tag

<?xml version='1.0' encoding='utf-8'?><export>{custom_fields}</export>

XML Output

<?xml version='1.0' encoding='utf-8'?>
<export>
  <field>
    <key>VIP</key>
    <value>false</value>
  </field>
  <field>
    <key>profession</key>
    <value>teacher</value>
  </field>
</export>

JSON Template using {custom_fields} tag

{"custom_fields": {custom_fields}}

JSON Output

{
  "custom_fields":
  [
    {
      "key": "VIP",
      "value": "false"
    },
    {
      "key": "profession",
      "value": "teacher"
    }
  ]
}

HTML Template using {custom_fields} tag

<div class="custom-fields">{custom_fields}</div>

HTML Output

<div class="custom-fields">
  <div class="sm-custom-attributes-container">
    <div class="sm-custom-key-label">Key</div>
    <div class="sm-custom-key">profession</div>

    <div class="sm-custom-key-value-label">Value</div>
    <div class="sm-custom-key-value">teacher</div>
  </div>
</div>

Available for Engagement Start Exports, Engagement Transfer Exports, Engagement End Exports, Inbox Messages and Operator Messages

A collection of the Visitor’s custom attributes. Shown in the right are examples of templates and the formats of their resulting outputs.

chat_transcript

XML Template using {chat_transcript} tag

<?xml version='1.0' encoding='utf-8'?><export>{chat_transcript}</export>

XML Output

<?xml version='1.0' encoding='utf-8'?><export>
  <message>
    <content>Hi, where can I add a new plan for my daughter?</content>
    <created_at>2017-07-07T13:47:28.000Z</created_at>
    <sender>
      <name>Mark White</name>
      <type>visitor</type>
    </sender>
  </message>
  <message>
    <content>Why don't I take you there?</content>
    <created_at>2017-07-07T13:47:29.000Z</created_at>
    <type>suggestion</type>
    <sender>
      <name>omniguide</name>
      <type>omniguide</type>
    </sender>
  </message>
  <message>
    <content>Why don't I take you there?</content>
    <created_at>2017-07-07T13:47:30.000Z</created_at>
    <sender>
      <name>Jared Grey</name>
      <type>operator</type>
    </sender>
  </message>
</export>

JSON Template using {chat_transcript} tag

{"chat": {chat_transcript}}

JSON Output

{
  "chat_transcript":
  [
    {
      "content": "Hi, where can I add a new plan for my daughter?",
      "created_at": "2017-07-07T13:47:28.000Z",
      "sender":
      {
        "name": "Mark White",
        "type": "visitor"
      }
    },
    {
      "content": "Why don't I take you there?",
      "created_at": "2017-07-07T13:47:29.000Z",
      "type": "suggestion",
      "sender":
      {
        "name":"omniguide",
        "type":"omniguide"
      }
    },
    {
      "content": "Why don't I take you there?",
      "created_at": "2017-07-07T13:47:30.000Z",
      "type": "user",
      "sender":
      {
        "name": "Jared Grey",
        "type": "operator"
      }
    }
  ]
}

HTML Template using {chat_transcript} tag

<div class="chat-transcript">{chat_transcript}</div>

HTML Output

<div class="chat-transcript">
  <div class="sm-message-container">
    <div class="sm-message-content-label">Content</div>
    <div class="sm-message-content">Hi, where can I add a new plan for my daughter?</div>

    <div class="sm-message-created-at-label">Date Sent</div>
    <div class="sm-message-created-at">2017-07-07T13:47:28.000Z</div>

    <div class="sm-message-sender-container sm-(visitor|operator)">
      <div class="sm-message-sender-type-label">Sender type</div>
      <div class="sm-message-sender-type">visitor</div>

      <div class="sm-message-sender-name-label">Sender Name</div>
      <div class="sm-message-sender-name">Mark White</div>
    </div>
  </div>
  <div class="sm-message-container">
    <div class="sm-message-content-label">Content</div>
    <div class="sm-message-content">Why don't I take you there?</div>

    <div class="sm-message-created-at-label">Date Sent</div>
    <div class="sm-message-created-at">2017-07-07T13:47:30.000Z</div>

    <div class="sm-message-sender-container sm-(visitor|operator)">
      <div class="sm-message-sender-type-label">Sender type</div>
      <div class="sm-message-sender-type">operator</div>

      <div class="sm-message-sender-name-label">Sender Name</div>
      <div class="sm-message-sender-name">Jared Grey</div>
    </div>
  </div>
</div>

Available only for Engagement End Exports

The collection of Chat messages exchanged between the Visitor and the Operator, including system messages the Operator received during the Engagement. Shown in the right are examples of templates and the formats of their resulting outputs.

Examples

XML Template

<?xml version='1.0' encoding='utf-8'?>
<export>
  <visitor_name>{visitor_name}</visitor_name>
  <chat>{chat_transcript}</chat>
</export>

Output

<?xml version='1.0' encoding='utf-8'?>
<export>
  <visitor_name>Jared Grey</visitor_name>
  <chat>
    <message>
      <content>Hi, where can I add a new plan for my daughter?</content>
      <created_at>2017-01-14T20:34:2200:00</created_at>
      <sender>
        <name>Mark White</name>
        <type>visitor</type>
      </sender>
    </message>
    <message>
      <content>Why don't I take you there?</content>
      <created_at>2017-01-14T20:34:2205:00</created_at>
      <sender>
        <name>Jared Grey</name>
        <type>operator</type>
      </sender>
    </message>
  </chat>
</export>

JSON Template

{
  "export":
  {
    "visitor_name": {visitor_name},
    "chat": {chat_transcript},
    "custom_fields": {custom_fields}
  }
}

Output

{
  "export":
  {
    "visitor_name": "Mark White",
    "chat":
    [
      {
        "content": "Hi, where can I add a new plan for my daughter?",
        "created_at": "2017-01-14T20:34:1807:00",
        "sender":
        {
          "name": "Mark White",
          "type": "Visitor"
        }
      },
      {
        "content": "Why don't I take you there?",
        "created_at": "2017-01-14T20:34:2205:00",
        "sender":
        {
          "name": "Jared Grey",
          "type": "Operator"
        }
      }
    ],
    "custom_fields":[
      {
        "key": "VIP",
        "value": "false"
      },
      {
        "key": "profession",
        "value": "teacher"
      }
    ]
  }
}

Template

<!doctype html>
<html lang=en>
  <head>
    <title>HTML export template</title>
  </head>
  <body>
    <p>Visitor: {visitor_name}</p>
    <h2>Chat transcript</h2>
      {chat_transcript}
    <h2>Custom attributes</h2>
      {custom_attributes}
  </body>
</html>

Generates the Output

<!doctype html>
<html lang=en>
  <head>
    <title>HTML export template</title>
  </head>
  <body>
    <p>Visitor: Markus</p>

    <h2>Chat transcript</h2>
    <div style="font-size: 12px">
      <div style="float: left; margin-right: 3px; margin-top: -3px; font-weight: bold; color: rgb(98, 140, 216); clear: left">[03:45PM]</div>
      <div style="float: left; margin-right: 3px; margin-top: -3px; font-weight: bold; color: rgb(98, 140, 216)">Stenver</div>
      <div style="float: left; margin-top: -3px">First message</div>
    </div>
    <div style="font-size: 12px">
      <div style="float: left; margin-right: 3px; margin-top: -3px; font-weight: bold; color: rgb(75, 118, 73); clear: left">[03:46PM]</div>
      <div style="float: left; margin-right: 3px; margin-top: -3px; font-weight: bold; color: rgb(75, 118, 73)">Markus</div>
      <div style="float: left; margin-top: -3px">Second message</div>
    </div>

   <h2>Custom attributes</h2>
    <div class="sm-custom-attributes-container">
      <div class="sm-custom-key-label">Key</div>
      <div class="sm-custom-key">custom key 1</div>
      <div class="sm-custom-key-value-label">Value</div>
      <div class="sm-custom-key-value">custom value 1</div>
    </div>
    <div class="sm-custom-attributes-container">
      <div class="sm-custom-key-label">Key</div>
      <div class="sm-custom-key">custom key 2</div>
      <div class="sm-custom-key-value-label">Value</div>
      <div class="sm-custom-key-value">custom value 2</div>
    </div>
  </body>
</html>

POST New Export

curl --request POST \
    --header "Authorization: Token $token" \
    --header "Content-Type: application/json" \
    --header "Accept: application/vnd.salemove.v1+json" \
    --data-binary '{
        "name": "Lead Gen",
        "type": "engagement",
        "content_type": "application/xml",
        "email_recipient": {
          "enabled": true,
          "emails": ["jared.grey@company.com"]
        },
        "crm_recipient": {
          "enabled": true,
          "url": "https://company.com/crm"
        },
        "template": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<export><visitor_name>{visitor_name}</visitor_name>\n</export>"
      }' \
    "https://api.salemove.com/sites/$site_id/crm/exports/""
require 'httparty'

ENDPOINT = 'https://api.salemove.com/sites'

token = ARGV[0].strip
site_id = ARGV[1].strip

headers = {
  :authorization => "Token #{token}",
  :content_type => "application/json",
  :accept => "application/vnd.salemove.v1+json"
}

options = {
  headers: headers,
  query: {
    "name": "Lead Gen",
    "type": "engagement",
    "content_type": "application/xml",
    "email_recipient": {
      "enabled": false,
      "emails": [
        "sales@company.com"
      ]
    },
    "crm_recipient": {
      "enabled": true,
      "url": "https://company.com/crm",
      "headers": {
        "Authorization": "CRM_Auth_Token",
        "Accept": "application/xml"
      }
    },
    "template": "<?xml version='1.0' encoding='UTF-8'?><export><visitor_name>{visitor_name}</visitor_name></export>",
    "enabled": true,
    "send_to_operator": true,
    "trigger": "system",
    "folder_id": "86313e78-a521-42c0-9477-97f5c4565fc8",
    "email_subject": "SaleMove Engagement with {visitor_name}"
  }
}

raw_response = HTTParty.post(
  "#{ENDPOINT}/#{site_id}/crm/exports",
  options
)

response = JSON.parse raw_response.body

puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('POST','https://api.salemove.com/sites/$site_id/crm/exports',false);

xhr.setRequestHeader('authorization','Token $token');
xhr.setRequestHeader('content-type','application/json');
xhr.setRequestHeader('accept','application/vnd.salemove.v1+json');

var data = {
  "name": "Lead Gen",
  "type": "engagement",
  "content_type": "application/xml",
  "email_recipient": {
    "enabled": true,
    "emails": ["sales@company.com"]
  },
  "crm_recipient": {
    "enabled": true,
    "url": "https://company.com/crm",
    "headers": {
      "Authorization": "CRM_Auth_Token",
      "Accept": "application/xml"
    }
  },
  "template": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<export><visitor_name>{visitor_name}</visitor_name>\n</export>"
};

var query = JSON.stringify(data);

xhr.send(query);

var response = JSON.parse(xhr.responseText);

console.log(response);

Generates the output

{
  "id": "efae435b-2ec5-403f-a091-46ecf1b8894b",
  "folder_id": null,
  "name": "New Lead",
  "site_id": "2e56b224-6708-4755-b6c9-35f9889e42dd",
  "type": "engagement",
  "content_type": "application/xml",
  "template": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<export><visitor_name>{visitor_name}</visitor_name>\n</export>",
  "email_subject": null,
  "created_at": "2017-07-10T19:36:40.548207Z",
  "updated_at": "2017-07-10T19:36:40.548207Z",
  "enabled": true,
  "updated_by": "manager@company.com",
  "send_to_operator": true,
  "trigger": "system",
  "crm_recipient": {
    "enabled": true,
    "url": "https://company.com/crm",
    "headers": {
      "Accept": "application/xml",
      "Authorization": "CRM_Auth_Token"
    }
  },
  "email_recipient": {
    "enabled": true,
    "emails": ["sales@company.com"]
  },
  "href":"https://api.salemove.com/sites/2e56b224-6708-4755-b6c9-35f9889e42dd/crm/exports/5681e1d2-f7ac-4473-9809-2965bfd8ef02"
}

Action: POST /sites/{site_id}/crm/exports

Creates a new Export for the {site_id}. The Operator’s API token used to make the request must have rights to access the Site’s data.

The endpoint accepts the following parameters:

Parameter Required Type Description
site_id Yes string The site_id that owns the Export.
name Yes string Look at the template definition for the description of this parameter.
type Yes string Look at the template definition for the description of this parameter.
content_type Yes string Look at the template definition for the description of this parameter.
email_recipients Yes object Look at the template definition for the description of this parameter.
crm_recipients Yes object Look at the template definition for the description of this parameter.
template Yes string Look at the template definition for the description of this parameter.

GET Export by ID

curl --request GET \
    --header "Authorization: Token $token" \
    --header "Accept: application/vnd.salemove.v1+json" \
    "https://api.salemove.com/sites/$site_id/crm/exports/$export_id"
require 'httparty'

ENDPOINT = 'https://api.salemove.com/sites'

token = ARGV[0].strip
site_id = ARGV[1].strip
export_id = ARGV[2].strip

headers = {
  :authorization => "Token #{token}",
  :accept => "application/vnd.salemove.v1+json"
}

raw_response = HTTParty.get(
  "#{ENDPOINT}/#{site_id}/crm/exports/#{export_id}",
  headers: headers
)

response = JSON.parse raw_response.body

puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('GET', 'https://api.salemove.com/sites/$site_id/crm/exports/$export_id', false);

xhr.setRequestHeader('authorization','Token $token');
xhr.setRequestHeader('accept','application/vnd.salemove.v1+json');

xhr.send();

var response = JSON.parse(xhr.responseText);

console.log(response);

Generates the output

{
  "href": "https://api.salemove.com/sites/2e56b224-6708-4755-b6c9-35f9889e42dd/crm/exports/5681e1d2-f7ac-4473-9809-2965bfd8ef02",
  "id": "5681e1d2-f7ac-4473-9809-2965bfd8ef02",
  "name": "New Lead",
  "site_id": "2e56b224-6708-4755-b6c9-35f9889e42dd",
  "type": "engagement",
  "content_type": "application/xml",
  "email_recipient": {
    "enabled": true,
    "emails": ["sales@company.com"]
  },
  "crm_recipient": {
    "enabled": true,
    "url": "http://company.com/crm",
    "headers": {
      "Accept": "application/xml",
      "Authorization": "CRM_Auth_Token"
    }
  },
  "template": "<?xml version='1.0' encoding='UTF-8'?>\n<export><visitor_name>{visitor_name}</visitor_name>\n</export>",
  "enabled": true,
  "updated_by": "manager@email.com",
  "send_to_operator": true,
  "trigger": "system",
  "created_at": "2017-07-06T09:24:22Z",
  "updated_at": "2017-07-06T09:24:22Z",
  "folder_id": null,
  "email_subject": "SaleMove Engagement with {visitor_name}"
}

Action: GET /sites/{site_id}/crm/exports/{id}

This fetches the information for the Export with the ID {id}. The Operator whose API token is used to make the request must have rights to access the Site.

Parameter Required Type Description
site_id Yes string The site_id that owns the Export definition.
id Yes string The id of the Export.

PUT Update Export

curl --request PUT \
    --header "Authorization: Token $token" \
    --header "Content-Type: application/json" \
    --header "Accept: application/vnd.salemove.v1+json" \
    --data-binary '{
      "name": "Lead Bucket",
      "type": "engagement",
      "content_type": "application/xml",
      "email_recipient": {
        "enabled": true,
        "emails": ["sales@company.com","manager@company.com"]
      },
      "crm_recipient": {
        "enabled": true,
        "url": "https://company.com/crm",
        "headers": {
          "Authorization": "Basic sAAA3tdMgcDoFOHA1WTdyMg==",
          "Accept": "application/xml"
        }
      },
      "template": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<export><visitor_name>{visitor_name}</visitor_name>\n</export>",
      "email_subject": "New SaleMove Lead",
      "send_to_operator": false,
      "trigger": "system",
      "folder_id": "86313e78-a521-42c0-9477-97f5c4565fc8"
    }' \
    "https://api.salemove.com/sites/$site_id/crm/exports/$export_id"
require 'httparty'

ENDPOINT = 'https://api.salemove.com/sites'

token = ARGV[0].strip
site_id = ARGV[1].strip
export_id = ARGV[2].strip

headers = {
  :authorization => "Token #{token}",
  :content_type => "application/json",
  :accept => "application/vnd.salemove.v1+json"
}

options = {
  headers: headers,
  query: {
    "name": "Lead Bucket",
    "type": "engagement",
    "content_type": "application/xml",
    "email_recipient": {
      "enabled": true,
      "emails": [
        "sales@company.com",
        "manager@company.com"
      ]
    },
    "crm_recipient": {
      "enabled": true,
      "url": "https://company.com/crm",
      "headers": {
        "Authorization": "Basic sAAA3tdMgcDoFOHA1WTdyMg==",
        "Accept": "application/xml"
      }
    },
    "template": "<?xml version='1.0' encoding='UTF-8'?><export><visitor_name>{visitor_name}</visitor_name></export>",
    "enabled": true,
    "updated_by": "manager@company.com",
    "send_to_operator": false,
    "trigger": "system",
    "folder_id": "86313e78-a521-42c0-9477-97f5c4565fc8",
    "email_subject": "SaleMove Engagement with {visitor_name}"
  }
}

raw_response = HTTParty.put(
  "#{ENDPOINT}/#{site_id}/crm/exports/#{export_id}",
  options
)

response = JSON.parse raw_response.body

puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('PUT','https://api.salemove.com/sites/$site_id/crm/exports/$export_id',false);

xhr.setRequestHeader('authorization','Token $token');
xhr.setRequestHeader('content-type','application/json');
xhr.setRequestHeader('accept','application/vnd.salemove.v1+json');

var data = {
  "name": "Lead Bucket",
  "type": "engagement",
  "content_type": "application/xml",
  "email_recipient": {
    "enabled": true,
    "emails": ["sales@company.com","manager@company.com"]
  },
  "crm_recipient": {
    "enabled": true,
    "url": "https://company.com/crm",
    "headers": {
      "Authorization": "Basic sAAA3tdMgcDoFOHA1WTdyMg==",
      "Accept": "application/xml"
    }
  },
  "template": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<export><visitor_name>{visitor_name}</visitor_name>\n</export>",
  "email_subject": "New SaleMove Lead",
  "send_to_operator": false,
  "trigger": "system",
  "folder_id": "86313e78-a521-42c0-9477-97f5c4565fc8"
};

var query = JSON.stringify(data);

xhr.send(query);

var response = JSON.parse(xhr.responseText);

console.log(response);

Generates the output

{
  "id": "5681e1d2-f7ac-4473-9809-2965bfd8ef02",
  "folder_id": "86313e78-a521-42c0-9477-97f5c4565fc8",
  "name": "Lead Bucket",
  "site_id": "5681e1d2-f7ac-4473-9809-2965bfd8ef02",
  "type": "engagement",
  "content_type": "application/xml",
  "template": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<export><visitor_name>{visitor_name}</visitor_name>\n</export>",
  "email_subject": "New SaleMove Lead",
  "created_at": "2017-07-10T19:03:18.492733Z",
  "updated_at":"2017-09-14T19:04:48.661271Z",
  "enabled": true,
  "updated_by": "manager@company.com",
  "send_to_operator": false,
  "trigger": "system",
  "crm_recipient": {
    "enabled":true,
    "url":"https://company.com/crm",
    "headers": {
      "Authorization": "Basic sAAA3tdMgcDoFOHA1WTdyMg==",
      "Accept": "application/xml"
    }
  },
  "email_recipient": {
    "enabled": true,
    "emails": [
      "sales@company.com",
      "manager@company.com"
    ]
  },
  "href":"https://api.salemove.com/sites/2e56b224-6708-4755-b6c9-35f9889e42dd/crm/exports/5681e1d2-f7ac-4473-9809-2965bfd8ef02"
}

Action: PUT /sites/{site_id}/crm/exports/{id}

This updates the Export with the id. The Operator whose API token is used to make the request must have the right to access the Site.

Parameter Required Type Description
site_id Yes string The site_id that owns the Export definition
id Yes string The id of the Export
name Yes string Look at the template definition for the description of this parameter
type Yes string Look at the template definition for the description of this parameter
content_type Yes string Look at the template definition for the description of this parameter
email_recipients Yes object Look at the template definition for the description of this parameter
crm_recipients Yes object Look at the template definition for the description of this parameter
template Yes string Look at the template definition for the description of this parameter

DELETE Export by ID

curl --request DELETE \
    --header "Authorization: Token $token" \
    --header "Accept: application/vnd.salemove.v1+json" \
    "https://api.salemove.com/sites/$site_id/crm/exports/$export_id"
require 'httparty'

ENDPOINT = 'https://api.salemove.com/sites'

token = ARGV[0].strip
site_id = ARGV[1].strip
export_id = ARGV[2].strip

headers = {
  :authorization => "Token #{token}",
  :accept => 'application/vnd.salemove.v1+json'
}

raw_response = HTTParty.delete(
  "#{ENDPOINT}/#{site_id}/crm/exports/#{export_id}",
  headers: headers
)

response = JSON.parse raw_response.body

puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('DELETE','https://api.salemove.com/sites/$site_id/crm/exports/$export_id',false);

xhr.setRequestHeader('authorization','Token $token');
xhr.setRequestHeader('accept','application/vnd.salemove.v1+json');

xhr.send();

var response = xhr.responseText;

console.log(response);

Genereates the Output


Action: DELETE /sites/{site_id}/crm/exports/{id}

Deletes the Export with id

Parameter Type Required Description
site_id string Yes The site_id that owns the Export definition.
id string Yes The id of the Export.

GET Exports for Site

curl --request GET \
    --header "Authorization: Token $token" \
    --header "Accept: application/vnd.salemove.v1+json" \
    "https://api.salemove.com/sites/$site_id/crm/exports"
require 'httparty'

ENDPOINT = 'https://api.salemove.com/sites'

token = ARGV[0].strip
site_id = ARGV[1].strip

headers = {
  :authorization => "Token #{token}",
  :accept => 'application/vnd.salemove.v1+json'
}

raw_response = HTTParty.get(
  "#{ENDPOINT}/#{site_id}/crm/exports",
  headers: headers
)

response = JSON.parse raw_response.body

puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('GET','https://api.salemove.com/sites/$site_id/crm/exports',false);

xhr.setRequestHeader('authorization','Token $token');
xhr.setRequestHeader('accept','application/vnd.salemove.v1+json');

xhr.send();

var response = JSON.parse(xhr.responseText);

console.log(response);

Generates the output

{
  "last_page": "https://api.salemove.com/sites/2e56b224-6708-4755-b6c9-35f9889e42dd/crm/exports?page=1",
  "exports": [
    {
      "href": "https://api.salemove.com/sites/2e56b224-6708-4755-b6c9-35f9889e42dd/crm/exports/5681e1d2-f7ac-4473-9809-2965bfd8ef02"
      "id": "5681e1d2-f7ac-4473-9809-2965bfd8ef02",
      "folder_id": "86313e78-a521-42c0-9477-97f5c4565fc8",
      "name": "Lead Bucket",
      "site_id": "5681e1d2-f7ac-4473-9809-2965bfd8ef02",
      "type": "engagement",
      "email_subject": "New SaleMove Lead",
      "content_type": "application/xml",
      "email_recipient": {
        "enabled": true,
        "emails": [
          "sales@company.com",
          "manager@company.com"
        ]
      },
      "crm_recipient": {
        "enabled":true,
        "url":"https://company.com/crm",
        "headers": {
          "Authorization": "Basic sAAA3tdMgcDoFOHA1WTdyMg==",
          "Accept": "application/xml"
        }
      },
      "template": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<export><visitor_name>{visitor_name}</visitor_name>\n</export>",
      "created_at": "2017-07-10T19:03:18.492733Z",
      "updated_at":"2017-09-14T19:04:48.661271Z",
      "enabled": true,
      "updated_by": "manager@company.com",
      "send_to_operator": false,
      "trigger": "system"
    }
  ]
}

Action: GET /sites/{site_id}/crm/exports

This fetches all of the Export definitions for the Site with site_id. The Operator whose API token is used to make the request must have rights to access the Site. The template definition is not included in this endpoint for each Export definition. Please see the endpoint for fetching a single Export definition in order to access the template definition.

Parameter Type Required Description
site_id string Yes The site_id that owns the Export definition.
page integer No The requested page if pagination is used.
per_page integer No The number of Exports included per page.
order string No Specifies if the collection should be sorted by creation time (asc or desc).

GET Folders and Exports

Action: GET /sites/{site_id}/crm/tree

It returns a list of all Exports and Folders for the site. The response places the Folders first and the Exports after, both in alphabetical order.

curl --request GET \
    --header "Authorization: Token $token" \
    --header "Accept: application/vnd.salemove.v1+json" \
    "https://api.salemove.com/sites/$site_id/crm/tree"
require 'httparty'

ENDPOINT = 'https://api.salemove.com/sites'

token = ARGV[0].strip
site_id = ARGV[1].strip

headers = {
  :authorization => "Token #{token}",
  :accept => 'application/vnd.salemove.v1+json'
}

raw_response = HTTParty.get(
  "#{ENDPOINT}/#{site_id}/crm/tree",
  headers: headers
)

response = JSON.parse raw_response.body

puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('GET', 'https://api.salemove.com/sites/$site_id/crm/tree', false);

xhr.setRequestHeader('authorization','Token $token');
xhr.setRequestHeader('accept','application/vnd.salemove.v1+json');

xhr.send();

var response = JSON.parse(xhr.responseText);

console.log(response);

Generates the Output

[
  {
    "id": "86313e78-a521-42c0-9477-97f5c4565fc8",
    "folder_id": "86313e78-a521-42c0-9477-97f5c4565fc8",
    "name": "Sales Team Exports",
    "site_id": "2e56b224-6708-4755-b6c9-35f9889e42dd",
    "created_at": "2017-07-03T12:34:56.317509Z",
    "updated_at": "2017-07-03T12:34:56.317509Z",
    "updated_by": "manager@company.com",
    "type": "folder",
    "href": "https://api.salemove.com/sites/2e56b224-6708-4755-b6c9-35f9889e42dd/crm/folders/86313e78-a521-42c0-9477-97f5c4565fc8"
  },
  {
    "href": "https://api.salemove.com/sites/2e56b224-6708-4755-b6c9-35f9889e42dd/crm/exports/5681e1d2-f7ac-4473-9809-2965bfd8ef02",
    "id": "5681e1d2-f7ac-4473-9809-2965bfd8ef02",
    "name": "New Lead",
    "site_id": "2e56b224-6708-4755-b6c9-35f9889e42dd",
    "type": "engagement",
    "content_type": "application/xml",
    "email_recipient": {
      "enabled": true,
      "emails": [
        "sales@company.com",
        "manager@company.com"
      ]
    },
    "crm_recipient": {
      "enabled": true,
      "url": "http://company.com/crm",
      "headers": {
        "Accept": "application/xml",
        "Authorization": "CRM_Auth_Token"
      }
    },
    "template": "<?xml version='1.0' encoding='UTF-8'?>\n<export><visitor_name>{visitor_name}</visitor_name>\n</export>",
    "enabled": true,
    "updated_by": "manager@company.com",
    "send_to_operator": false,
    "trigger": "system",
    "created_at": "2017-07-06T09:24:22Z",
    "updated_at": "2017-09-14T09:24:22Z",
    "folder_id": "86313e78-a521-42c0-9477-97f5c4565fc8",
    "email_subject": "SaleMove Engagement with {visitor_name}"
  }
]

Export Folders

Exports can be organized in Folders.

A Folder has the following attributes

Parameter Type Description
href string the URI for the Folder
id string Id of the Export Folder
name string Name of the Export Folder
site_id string ID of the site to which Export Folder belongs
folder_id string ID of the parent Export Folder
type string Always has value folder
created_at string Date and time, when the Export Folder was created
updated_at string Date and time, when the Export Folder was last updated
updated_by string Email of the Operator, who updated the Export Folder last.

POST Create Folder

curl --request POST \
    --header "Authorization: Token $token" \
    --header "Content-Type: application/json" \
    --header "Accept: application/vnd.salemove.v1+json" \
    --data-binary '{
      "name": "POC"
    }' \
    "https://api.salemove.com/sites/$site_id/crm/folders"
require 'httparty'

ENDPOINT = 'https://api.salemove.com/sites'

token = ARGV[0].strip
site_id = ARGV[1].strip

headers = {
  :authorization => "Token #{token}",
  :content_type => "application/json",
  :accept => "application/vnd.salemove.v1+json"
}

options = {
  headers: headers,
  query: {
    "name": "POC"
  }
}

raw_response = HTTParty.post(
  "#{ENDPOINT}/#{site_id}/crm/folders",
  options
)

response = JSON.parse raw_response.body

puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('POST','https://api.salemove.com/sites/$site_id/crm/folders',false);

xhr.setRequestHeader('authorization','Token $token');
xhr.setRequestHeader('content-type','application/json');
xhr.setRequestHeader('accept','application/vnd.salemove.v1+json');

var data = {
  "name": "POC"
};

var query = JSON.stringify(data);

xhr.send(query);

var response = JSON.parse(xhr.responseText);

console.log(response);

Generates the Output

{
  "id": "86313e78-a521-42c0-9477-97f5c4565fc8",
  "folder_id": null,
  "name": "POC",
  "site_id": "2e56b224-6708-4755-b6c9-35f9889e42dd",
  "created_at": "2017-02-15T12:34:56.317509Z",
  "updated_at": "2017-02-19T11:17:41.298641Z",
  "updated_by": "admin@company.com",
  "type": "folder",
  "href": "https://api.salemove.com/sites/2e56b224-6708-4755-b6c9-35f9889e42dd/crm/folders/86313e78-a521-42c0-9477-97f5c4565fc8"
}

Action: POST /sites/{site_id}/crm/folders

Create an Export Folder using this action. It takes a JSON object containing a folder definition. It requires management rights on the site.

GET Export Folder

curl --request GET \
    --header "Authorization: Token $token" \
    --header "Accept: application/vnd.salemove.v1+json" \
    "https://api.salemove.com/sites/$site_id/crm/folders/$folder_id"
require 'httparty'

ENDPOINT = 'https://api.salemove.com/sites'

token = ARGV[0].strip
site_id = ARGV[1].strip
folder_id = ARGV[2].strip

headers = {
  :authorization => "Token #{token}",
  :accept => "application/vnd.salemove.v1+json"
}

raw_response = HTTParty.get(
  "#{ENDPOINT}/#{site_id}/crm/folders/#{folder_id}",
  headers: headers
)

response = JSON.parse raw_response.body

puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('GET', 'https://api.salemove.com/sites/$site_id/crm/folders/folder', false);

xhr.setRequestHeader('authorization','Token $token');
xhr.setRequestHeader('accept','application/vnd.salemove.v1+json');

xhr.send();

var response = JSON.parse(xhr.responseText);

console.log(response);

Generates the Output

{
  "id":"86313e78-a521-42c0-9477-97f5c4565fc8",
  "folder_id":null,
  "name":"POC",
  "site_id":"2e56b224-6708-4755-b6c9-35f9889e42dd",
  "created_at":"2017-02-15T12:34:56.317509Z",
  "updated_at":"2017-02-19T11:17:41.298641Z",
  "updated_by":"admin@company.com",
  "type":"folder",
  "href":"https://api.salemove.com/sites/2e56b224-6708-4755-b6c9-35f9889e42dd/crm/folders/86313e78-a521-42c0-9477-97f5c4565fc8"
}

Action: GET /sites/{site_id}/crm/folders/{id}

PUT Update Export Folder

curl --request PUT \
    --header "Authorization: Token $token" \
    --header "Content-Type: application/json" \
    --header "Accept: application/vnd.salemove.v1+json" \
    --data-binary '{
      "name": "Leads"
    }' \
    "https://api.salemove.com/sites/$site_id/crm/folders/$folder_id"
require 'httparty'

ENDPOINT = 'https://api.salemove.com/sites'

token = ARGV[0].strip
site_id = ARGV[1].strip
folder_id = ARGV[2].strip

headers = {
  :authorization => "Token #{token}",
  :content_type => "application/json",
  :accept => "application/vnd.salemove.v1+json"
}

options = {
  headers: headers,
  query: {
    "name": "Leads"
  }
}

raw_response = HTTParty.put(
  "#{ENDPOINT}/#{site_id}/crm/folders/#{folder_id}",
  options
)

response = JSON.parse raw_response.body

puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('PUT','https://api.salemove.com/sites/$site_id',false);

xhr.setRequestHeader('authorization','Token $token');
xhr.setRequestHeader('content-type','application/json');
xhr.setRequestHeader('accept','application/vnd.salemove.v1+json');

var data = {
  "name": "Leads"
};

var query = JSON.stringify(data);

xhr.send(query);

var response = JSON.parse(xhr.responseText);

console.log(response);

Generates the Output

{
  "href": "https://api.salemove.com/sites/2e56b224-6708-4755-b6c9-35f9889e42dd/crm/folders/86313e78-a521-42c0-9477-97f5c4565fc8",
  "name": "Leads",
  "site_id": "2e56b224-6708-4755-b6c9-35f9889e42dd",
  "folder_id":null,
  "type": "folder",
  "created_at": "2017-07-06T09:24:22Z",
  "updated_at": "2017-09-14T11:53:42Z",
  "updated_by": "manager@company.com"
}

Action: PUT /sites/{site_id}/crm/folders/{id}

Update an existing Export Folder on the site. This action takes a JSON object containing an updated folder definition. It requires management rights on the site.

DELETE Export Folder

curl --request DELETE \
    --header "Authorization: Token $token" \
    --header "Accept: application/vnd.salemove.v1+json" \
    'https://api.salemove.com/sites/$site_id/crm/folders/$folder_id'
require 'httparty'

ENDPOINT = 'https://api.salemove.com/sites'

token = ARGV[0].strip
site_id = ARGV[1].strip
folder_id = ARGV[2].strip

headers = {
  :authorization => "Token #{token}",
  :accept => 'application/vnd.salemove.v1json'
}

raw_response = HTTParty.delete(
  "#{ENDPOINT}/#{site_id}/crm/folders/#{folder_id}",
  headers: headers
)

response = JSON.parse raw_response.body

puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('DELETE','https://api.salemove.com/sites/$site_id/crm/folders/$folder_id',false);

xhr.setRequestHeader('authorization','Token $token');
xhr.setRequestHeader('accept','application/vnd.salemove.v1+json');

xhr.send();

var response = xhr.responseText;

console.log(response);

Generates the Output


Action: DELETE /sites/{site_id}/crm/folders/{id}

Delete an existing Export Folder on the site. Requires management permissions for the given Site.

SAML

SaleMove supports clients using Single Sign-On via Security Assertion Markup Language (SAML 2.0). SAML is an XML-based, open-standard data format that allows parties to securely exchange user authentication and authorization data. SAML-Based Single Sign-On (SSO) allows clients to have full control over the authorization and authentication of user accounts that can access to the web-based Operator Application. In this model, SaleMove acts as a service provider while SaleMove’s clients act as identity providers that control usernames, passwords and other information used during the identification, authentication and authorization process of users by SaleMove web applications. In addition, all logs remain with the identity provider (SaleMove’s client) for audit purposes.

SaleMove supports two ways of SSO by means of SAML: Identity Provider (IdP) Initiated SSO (Unsolicited Web SSO) and Service Provider (SP) initiated SSO. In an IdP Initiated SSO a user is logged on to the IdP and attempts to access a resource (SaleMove) on a remote SP server. The SAML assertion is transported to the Service Provider (SaleMove) via HTTP POST.

The SAML parameters can be configured programmatically or by requesting help from your Success Manager.

POST Create SAML

Action: POST /saml

This creates a SAML provider that can be associated to a Site.

Parameters Type Required Description
idp_metadata_url string Yes A URL to the SAML Provider endpoint that returns the Provider’s configuration data
site_id string Yes The id of the Site that the SAML configuration will be associated with
name_identifier_format string Yes The name of the attribute within a SAML response where the Operator’s email is placed
subdomain string Yes The subdomain that will be used by Operators to access the Operator console. E.g. if the subdomain is set to client_name then the Operators will access SaleMove via client_name.app.salemove.com
auth_context string No The authentication context of the SAML
idp_name_attribute string No The name of the attribute within a SAML response where the Operator’s name is placed
idp_email_attribute string No The name of the attribute within a SAML response where the Opeartor’s email is placed

Later the information of the new SAML provider can be fetched at the URL subdomain.app.salemove.com/saml/metadata. Where the subdomain is the value of the parameter subdomain sent along with the POST request.

PUT Update SAML

Action: PUT /saml/{saml_id}

This updates the configuration of a SAML provider.

Parameters Type Required Description
saml_id string Yes The id of the SAML provider to be updated.
site_id string Yes The id of the Site that the SAML will be assigned to.
idp_metadata_url string Yes A URL to the SAML Provider endpoint that returns the Provider’s configuration data.
site_id string Yes The id of the Site that the SAML configuration will be associated with.
name_identifier_format string Yes The name of the attribute within a SAML response where the Operator’s email is placed.
subdomain string Yes The subdomain that will be used by Operators to access the Operator console. E.g. if the subdomain is set to client_name then the operators will access SaleMove via client_name.app.salemove.com.
auth_context string No The authentication context of the SAML
idp_name_attribute string No The name of the attribute within a SAML response where the Operator’s name is placed
idp_email_attribute string No The name of the attribute within a SAML response where the Opeartor’s email is placed

Call Your Customer Success Manager

While configuring the SAML provider via the Customer Success Manager the following parameters will be requested:

Parameters Type Required Description
certificate fingerprint string Yes The certificate fingerprint used for authentication purposes between the IDP and the SP
name_identifier_format string Yes The name of the attribute within a SAML response where the Operator’s email is placed

Surveys

Surveys enable Operators and Visitors to provide feedback and free-form comments about Engagements.

GET Visitor Survey Answers

curl --request GET \
    --header "Authorization: Token $token" \
    --header "Accept: application/vnd.salemove.v1+json" \
    "https://api.salemove.com/engagements/$engagement_id/visitor_survey"
require 'httparty'

ENDPOINT = "https://api.salemove.com/engagements"

token = ARGV[0].strip
engagement_id = ARGV[1].strip

headers = {
  :authorization => "Token #{token}",
  :accept => 'application/vnd.salemove.v1+json'
}

raw_response = HTTParty.get(
  "#{ENDPOINT}/#{engagement_id}/visitor_survey",
  headers: headers
)

response = JSON.parse raw_response.body

puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('GET','https://api.salemove.com/engagements/$engagement_id/visitor_survey',false);

xhr.setRequestHeader('authorization','Token $token');
xhr.setRequestHeader('accept','application/vnd.salemove.v1+json');

xhr.send();

var response = JSON.parse(xhr.responseText);

console.log(response);

Generates the output

{
  "questions":
  [
    {
      "id": 796,
      "type": "scale",
      "title": "How would you rate this agency?",
      "required": false
    },
    {
      "id": 797,
      "type": "scale",
      "title": "How would you rate this operator?",
      "required": false
    },
    {
      "id": 798,
      "type": "text",
      "title": "Other Thoughts",
      "required": false
    }
  ],
  "answers":
  [
    {
      "id": 796,
      "response": 5
    },
    {
      "id": 797,
      "response": 4
    },
    {
      "id": 798,
      "response": "Wonderful! From now on, when I need assistance I'll just come online to find it."
    }
  ]
}

Action: GET /engagements/:engagement_id/visitor_survey

This request fetches the Survey information provided by the Visitor following an Engagement.

GET Operator Survey Answers

curl --request GET \ 
    --header "Authorization: Token $token" \
    --header "Accept: application/vnd.salemove.v1+json" \
    "https://api.salemove.com/engagements/$engagement_id/operator_survey"
require 'httparty'

ENDPOINT = "https://api.salemove.com/engagements/"

token = ARGV[0].strip
engagement_id = ARGV[1].strip

headers = {
  :authorization => "Token #{token}",
  :accept => 'application/vnd.salemove.v1+json'
}

raw_response = HTTParty.get(
  "#{ENDPOINT}/#{engagement_id}/operator_survey",
  headers: headers
)

response = JSON.parse raw_response.body

puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('GET','https://api.salemove.com/engagements/$engagement_id/operator_survey',false);

xhr.setRequestHeader('authorization','Token $token');
xhr.setRequestHeader('accept','application/vnd.salemove.v1+json');

xhr.send();

var response = JSON.parse(xhr.responseText);

console.log(response);

Generates the output

{
  "questions":
  [
    {
      "id": 1703,
      "type": "boolean",
      "title": "Did you set an appointment?",
      "required": false
     },
    {
      "id": 1704,
      "type": "boolean",
      "title": "Did you use CoBrowsing?",
      "required": false
    },
    {
      "id": 1705,
      "type": "boolean",
      "title": "Did you use Video/Audio",
      "required": false
    },
    {
      "id": 1706,
      "type": "single_choice",
      "title": "What was the use case for this Engagement?",
      "required": true,
      "choices":
      [
        {
          "id": 479,
          "title": "Service"
        },
        {
          "id": 480,
          "title":"Sales"
        }
      ]
    }
  ],
  "answers":
  [
    {
      "id": 1703,
      "response": false
    },
    {
      "id": 1704,
      "response": true
    },
    {
      "id": 1703,
      "response": true
    },
    {
      "id": 1703,
      "response": 479
    }
  ]
}

Action: GET /engagements/:engagement_id/operator_survey

This request fetches the Survey information provided by the Operator following an Engagement.

PUT Update Survey Answers

curl --request PUT \
    --header "Authorization: Bearer $access_token" \
    --header "Content-Type: application/json" \
    --header "Accept: application/vnd.salemove.v1+json" \
    --data-binary '{
      "answers":[
        {
          "question_id":"796",
          "response":"$response"
        },
        {
          "question_id":"797",
          "response":"$response"
        },
        {
          "question_id":"798",
          "response":"$response"
        }
      ]
    }' \
"https://api.salemove.com/engagements/$engagement_id/visitor_survey/answers"
require 'httparty'

ENDPOINT = "https://api.salemove.com/engagements"

access_token = ARGV[0].strip
engagement_id = ARGV[1].strip

headers = {
  :authorization => "Bearer #{access_token}",
  :content_type => "application/json",
  :accept => "application/vnd.salemove.v1+json"
}

options = {
  headers: headers,
  query: {
    "answers": [
      {
        "question_id":"99",
        "response":"4"
      },
      {
        "question_id":"100",
        "response":"4"
      },
      {
        "question_id":"101",
        "response":"wonderful"
      }
    ]
  }
}

raw_response = HTTParty.put(
  "#{ENDPOINT}/#{engagement_id}/visitor_survey/answers",
  options
)

response = JSON.parse raw_response.body

puts response
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

var xhr = new XMLHttpRequest();

xhr.open('PUT','https://api.salemove.com/engagements/$engagement_id/visitor_survey/answers',false);

xhr.setRequestHeader('authorization','Bearer $access_token');
xhr.setRequestHeader('accept','application/vnd.salemove.v1+json');

var data = {
  "answers": [
    {
      "question_id":"99",
      "response":"4"
    },
    {
      "question_id":"100",
      "response":"4"
    },
    {
      "question_id":"101",
      "response":"wonderful"
    }
  ]
};

var query = JSON.stringify(data);

xhr.send(query);

var response = JSON.parse(xhr.responseText);

console.log(response);

Generates the output

{"success":true}

Action: PUT /engagements/:engagement_id/visitor_survey/answers

Submits Visitor survey response for the given Engagement ID.

Webhooks

SaleMove allows integrators to register webhooks which will subscribe to certain events. When an event occurs we’ll send either an Apple push notification (APN) or a HTTP request to the configured URL with the specified HTTP method and headers.

You can specify up to 10 webhooks at a time. Those webhooks can include both HTTP or APN webhooks.

HTTP webhook

Registering

The format for specifying a HTTP webhook is:

Field Required Type Description
url Yes String The URL (including protocol) to which the HTTP request will be sent to.
method Yes String The HTTP method (e.g POST, PATCH) that will be used for the HTTP request.
headers No Object An arbitrary object which will be used to set request headers for the HTTP request. The keys of the object will be used as header names and values as header values. This can be used to authenticate incoming HTTP requests in your server.
events Yes Array of Strings An array of events (at least one) upon which a HTTP request will be made.

Payload

When using a HTTP webhook, the server sends a json payload as defined in the event.

Apple push notification webhook

Registering

Compared to HTTP webhooks, the URL must be defined in the apns schema. Also, the method and header fields are not allowed.

Field Required Type Description
url Yes String The URI using the apns scheme
events Yes Array of Strings An array of events (at least one) upon which a push notification will be sent.

apns://device_token@topic?key=value&key2=value2

The apns scheme is an URI that denotes the push notification target.

Query parameters

Field Required Type Description Note
env Yes String The target environment. One of sandbox, production If sandbox, the Apple development push notification server is used.
content_available No Boolean true for silent notification false by default

Example of an APN webhook defininition

{
  "url": "apns://93af82c6cfa56172901e191d07fdcacfb7cc01c13ed06cc73c6ce8ee1fdee355@org.myapp.demo?env=sandbox",
  "events": ["engagement.start"]
}

Payload

The event payload is wrapped in the data object. The payload contains additional push notification specific fields.

Field Type Description
message String Same as event.event_type
content_available Boolean Enables silent notification
data Object The event payload as defined in events

Example of an engagement.start notification sent by the server:

{
  "message": "engagement.start",
  "content_available": false,
  "data": {
    "event_type": "engagement.start",
    "event_id": "5cfb83e9-9b29-492c-b8d9-ded81beb8121",
    "dispatched_at": "2017-01-01T00:00:00.0Z",
    "engagement": {
      "id": "584714ac-ac69-4beb-8b78-1bd7064f2356",
      "engagement_request_id": "ca0baa1f-7214-4892-b651-40abd3f429fb",
      "visitor_id": "eace7e6a-7e09-492b-84a4-150a7b894353",
      "current_sub_engagement": {
        "id": "24",
        "operator_id": "858884a0-ccbd-4188-96ff-87691d2ca2b9",
        "site_id": "375025a4-8b8f-418c-8236-593ac4098a56"
      }
    }
  }
}

Events

The available events are:

Type Trigger
engagement.request.failure When the Engagement Request ends without resulting in an Engagement (i.e canceled, timed out).
engagement.start When an Engagement starts.
engagement.end When the Engagement ends.
engagement.transfer When the Engagement is transferred to a new Operator.
engagement.chat.message When a chat message is sent.
engagement.chat.message.status When the status of chat message changes.

All events are documented as json schemas. Also, an example is given for each event.

Common fields

Each event has a specific payload which is described in the event description. All events have the following common fields:

Field Type Description
event_type String The type of the event as specified in the event description.
event_id String An ID that uniquely identifies the Event.
dispatched_at String A timestamp with the following ISO-8601 format: YYYY-MM-DDThh:mm:ss.sTZD (ISO-8601).

EngagementRequestFailureEvent

Fired when an Engagement Request ends without accepting.

{
  "$schema": "http://json-schema.org/draft-06/schema#",
  "title": "Description of engagement.request.failure event",
  "type": "object",
  "properties": {
    "event_type": {"const": "engagement.request.failure"},
    "event_id": {"type": "string"},
    "dispatched_at": {"type": "string", "format": "date-time"},
    "engagement_request": {
      "type": "object",
      "properties": {
        "id": {"type": "string"},
        "site_id": {"type": "string"},
        "visitor_id": {"type": "string"},
        "operator_id": {"type": "string"},
        "fail_reason": {
          "type": "string",
          "enum": ["rejected", "timed_out", "visitor_left", "visitor_cancel", "operator_left", "operator_cancel"]
        }
      }
    }
  }
}
{
  "event_type": "engagement.request.failure",
  "event_id": "e8bacbef-fee6-4bb7-8c02-b7b1871b98d9",
  "dispatched_at": "2017-01-01T00:00:00.0Z",
  "engagement_request": {
    "id": "5fc202a2-37a0-420f-b57f-1fbad68f4a0f",
    "site_id": "24fa79ca-ca67-45e7-a94c-b5fc98590c39",
    "visitor_id": "eace7e6a-7e09-492b-84a4-150a7b894353",
    "operator_id": "31d03cfa-e563-436c-818a-e3242138bd94",
    "fail_reason": "visitor_cancel"
}
}

EngagementStartEvent

Fired when an Engagement starts. As an Engagement can be transferred and therefore can span across multiple sites and different Operators, all Engagement events contain the field current_sub_engagement which includes the current Operator and Site ID. To end the Engagement, see End Engagement.

{
  "$schema": "http://json-schema.org/draft-06/schema#",
  "title": "Description of engagement.start event",
  "type": "object",
  "properties": {
    "event_type": {"const": "engagement.start"},
    "event_id": {"type": "string"},
    "dispatched_at": {"type": "string", "format": "date-time"},
    "engagement": {
      "type": "object",
      "properties": {
        "id": {"type": "string"},
        "engagement_request_id": {"type": "string"},
        "visitor_id": {"type": "string"},
        "current_sub_engagement": {
          "type": "object",
          "properties": {
            "id": {"type": "string"},
            "operator_id": {"type": "string"},
            "site_id": {"type": "string"}
          }
        }
      }
    }
  }
}
{
  "event_type": "engagement.start",
  "event_id": "e8bacbef-fee6-4bb7-8c02-b7b1871b98d9",
  "dispatched_at": "2017-01-01T00:00:00.0Z",
  "engagement": {
    "id": "c71379b7-4e32-4dd4-a549-04f90f959dd5",
    "engagement_request_id": "5fc202a2-37a0-420f-b57f-1fbad68f4a0f",
    "visitor_id": "eace7e6a-7e09-492b-84a4-150a7b894353",
    "current_sub_engagement": {
      "id": "fc3aa55f-e6ad-4f4f-9b6b-28541d316a4c",
      "operator_id": "31d03cfa-e563-436c-818a-e3242138bd94",
      "site_id": "4afaf91f-b2a2-4eba-b617-76c415137d7c"
    }
  }
}

EngagementEndEvent

Fired when an Engagement ends. The last Operator and Site of the Engagement are given in the current_sub_engagement field. The reason for ending is given in the end_reason field, an error reason notes that either the Visitor or Operator suffered an application failure when trying to start an Engagement in their respective applications.

{
  "$schema": "http://json-schema.org/draft-06/schema#",
  "title": "Description of engagement.end event",
  "type": "object",
  "properties": {
    "event_type": {"const": "engagement.end"},
    "event_id": {"type": "string"},
    "dispatched_at": {"type": "string", "format": "date-time"},
    "engagement": {
      "type": "object",
      "properties": {
        "id": {"type": "string"},
        "engagement_request_id": {"type": "string"},
        "visitor_id": {"type": "string"},
        "end_reason": {
          "enum": ["visitor_hung_up", "operator_hung_up", "visitor_left", "operator_left", "error"]
        },
        "current_sub_engagement": {
          "type": "object",
          "properties": {
            "id": {"type": "string"},
            "operator_id": {"type": "string"},
            "site_id": {"type": "string"}
          }
        }
      }
    }
  }
}
{
  "event_type": "engagement.end",
  "event_id": "e8bacbef-fee6-4bb7-8c02-b7b1871b98d9",
  "dispatched_at": "2017-01-01T00:00:00.0Z",
  "engagement": {
    "id": "c71379b7-4e32-4dd4-a549-04f90f959dd5",
    "engagement_request_id": "5fc202a2-37a0-420f-b57f-1fbad68f4a0f",
    "visitor_id": "eace7e6a-7e09-492b-84a4-150a7b894353",
    "current_sub_engagement": {
      "id": "fc3aa55f-e6ad-4f4f-9b6b-28541d316a4c",
      "operator_id": "31d03cfa-e563-436c-818a-e3242138bd94",
      "site_id": "4afaf91f-b2a2-4eba-b617-76c415137d7c"
    },
    "end_reason": "visitor_hung_up"
  }
}

EngagementTransferEvent

Fired when an Engagement is transferred from one Operator to another, while the Visitor of the Engagement remains the same. The previous_sub_engagement field contains the Operator and Site of the Engagement prior to the Transfer, current_sub_engagement field contains the Operator and Site after the Transfer.

{
  "$schema": "http://json-schema.org/draft-06/schema#",
  "title": "Description of engagement.transfer event",
  "type": "object",
  "properties": {
    "event_type": {"const": "engagement.transfer"},
    "event_id": {"type": "string"},
    "dispatched_at": {"type": "string", "format": "date-time"},
    "engagement": {
      "type": "object",
      "properties": {
        "id": {"type": "string"},
        "engagement_request_id": {"type": "string"},
        "transfer_request_id": {"type": "string"},
        "visitor_id": {"type": "string"},
        "previous_sub_engagement": {
          "type": "object",
          "properties": {
            "id": {"type": "string"},
            "operator_id": {"type": "string"},
            "site_id": {"type": "string"}
          }
        },
        "current_sub_engagement": {
          "type": "object",
          "properties": {
            "id": {"type": "string"},
            "operator_id": {"type": "string"},
            "site_id": {"type": "string"}
          }
        }
      }
    }
  }
}
{
  "event_type": "engagement.transfer",
  "event_id": "e8bacbef-fee6-4bb7-8c02-b7b1871b98d9",
  "dispatched_at": "2017-01-01T00:00:00.0Z",
  "engagement": {
    "id": "c71379b7-4e32-4dd4-a549-04f90f959dd5",
    "engagement_request_id": "5fc202a2-37a0-420f-b57f-1fbad68f4a0f",
    "transfer_request_id": "133f2686-41af-47af-b8bb-13172b65469b",
    "visitor_id": "eace7e6a-7e09-492b-84a4-150a7b894353",
    "current_sub_engagement": {
      "id": "fc3aa55f-e6ad-4f4f-9b6b-28541d316a4c",
      "operator_id": "31d03cfa-e563-436c-818a-e3242138bd94",
      "site_id": "4afaf91f-b2a2-4eba-b617-76c415137d7c"
    },
    "previous_sub_engagement": {
      "id": "32c383c1-a00e-491d-9463-a5bd44e004e5",
      "operator_id": "8f9582fc-8a2e-4f01-a3a1-1ffb0abee9da",
      "site_id": "4afaf91f-b2a2-4eba-b617-76c415137d7c"
    }
  }
}

ChatMessageCreatedEvent

Fired when a chat message is sent by one Engagement participant. The content field includes the message content. The sender is either the Visitor or Operator of the Engagement. Note that this event is sent to the sender of the message. The undelivered_messages field is set to true if any engagement.chat.message events prior to this one have not been successfully delivered to the recipient. The timestamp field is set to server time at the moment that the server receives the message.

{
  "$schema": "http://json-schema.org/draft-06/schema#",
  "title": "Description of engagement.chat.message event",
  "type": "object",
  "properties": {
    "event_type": {"const": "engagement.chat.message"},
    "event_id": {"type": "string"},
    "dispatched_at": {"type": "string", "format": "date-time"},
    "message": {
      "type": "object",
      "properties": {
        "timestamp": {"type": "string", "format": "date-time"},
        "id": {"type": "string"},
        "engagement_id": {"type": "string"},
        "sub_engagement_id": {"type": "string"},
        "content": {"type": "string"},
        "status": {"const": "sent"},
        "sender": {
          "type": "object",
          "properties": {
            "type": {"enum": ["visitor", "operator"]}
          }
        }
      }
    },
    "undelivered_messages": {"type": "boolean"}
  }
}
{
  "event_type": "engagement.chat.message",
  "event_id": "e8bacbef-fee6-4bb7-8c02-b7b1871b98d9",
  "dispatched_at": "2017-01-01T00:00:00.0Z",
  "message": {
    "timestamp": "2017-01-01T00:00:00.0Z",
    "id": "388c4a1f-3e08-4cf6-b8ae-d290c07dc61f",
    "engagement_id": "c71379b7-4e32-4dd4-a549-04f90f959dd5",
    "sub_engagement_id": "fc3aa55f-e6ad-4f4f-9b6b-28541d316a4c",
    "content": "message-content",
    "status": "sent",
    "sender": {
      "type": "operator"
    }
  },
  "undelivered_messages": false
}

ChatMessageStatusEvent

Fired when a chat message is successfully delivered to the recipient. Note that this event is only sent to the sender of the message.

{
  "$schema": "http://json-schema.org/draft-06/schema#",
  "title": "Description of engagement.chat.message_status event",
  "type": "object",
  "properties": {
    "event_type": {"const": "engagement.chat.message_status"},
    "event_id": {"type": "string"},
    "dispatched_at": {"type": "string", "format": "date-time"},
    "message": {
      "type": "object",
      "properties": {
        "timestamp": {"type": "string", "format": "date-time"},
        "id": {"type": "string"},
        "engagement_id": {"type": "string"},
        "sub_engagement_id": {"type": "string"},
        "content": {"type": "string"},
        "status": {"const": "delivered"},
        "sender": {
          "type": "object",
          "properties": {
            "type": {"enum": ["visitor", "operator"]}
          }
        }
      }
    }
  }
}
{
  "event_type": "engagement.chat.message_status",
  "event_id": "e8bacbef-fee6-4bb7-8c02-b7b1871b98d9",
  "dispatched_at": "2017-01-01T00:00:00.0Z",
  "message": {
    "timestamp": "2017-01-01T00:00:00.0Z",
    "id": "388c4a1f-3e08-4cf6-b8ae-d290c07dc61f",
    "engagement_id": "c71379b7-4e32-4dd4-a549-04f90f959dd5",
    "sub_engagement_id": "fc3aa55f-e6ad-4f4f-9b6b-28541d316a4c",
    "content": "message-content",
    "status": "delivered",
    "sender": {
      "type": "operator"
    }
  }
}

OmniBrowse

OmniBrowse REST API Specification

Acquire Launch Token

Action: POST /auth/token

curl --request POST \
    --data-binary "api_token=$token" \
    "https://omnibrowse.salemove.com/auth/token"
$.ajax({
  type: 'POST',
  url: 'https://omnibrowse.salemove.com/auth/token',
  data: 'api_token=AjMMVGcvSdHg8H6f_dOr6Q',
  success: function(response) {
    console.log(response);
  }
});

Generates the Output

{
  "launch_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJqdGkiOiJlZTUwMjNhMS0xM2Q3LTQzMTItYTk5YS0zOGNmODM1Yzc2NTgiLCJvcGVyYXRvcl9pZCI6ImY0MjgxMWJjLTg1MTktNGQzMy1iYmIxLTM2ZDQ1NTVlY2IwYSIsIm5hbWUiOiJTYXNoYSBCcm93biIsImVtYWlsIjoic2FzaGFicm93bkBlbWFpbC5jb20iLCJwaG9uZSI6IjEyMDI0NTYxMTExIiwiaWF0IjoxNDk5ODg5MzUwLCJleHAiOjE0OTk4OTMxODZ9.r3K_OffhPjAWEelPdsLlXo3Ewc1bMijKdiPYyhIFGLc"
}

Description

Acquire a token which can be used later to start an OmniBrowse session. The token has a very short lifespan and is intended to be used immediately. API user must provide a valid API Token to acquire a Launch Token.

Parameters

Name Located In Description Required Type
api_token request body API Token Yes string

Fetch Visitor Information by External ID

Action: GET /sites/{site_id}/visitors

curl --request GET \
    --header "Authorization: Token $token" \
    "https://omnibrowse.salemove.com/sites/$site_id/visitors?external_id=$external_id"
var siteId = '19797dfc-c035-4c92-882c-dd080007a7a5';
var externalId = '14755';
$.ajax({
  type: 'GET',
  url: 'https://omnibrowse.salemove.com/sites/' + siteId + '/visitors',
  data: {
    external_id: externalId
  },
  headers: {
    'Authorization': 'Token $token'
  },
  success: function(response) {
    console.log(response);
  }
});

Generates the Output

[
  {
    "visitor_id": "d2097185-d995-4538-94ae-2ddd77325bbe",
    "updated_at": "2017-03-21T12:18:32.598729",
    "site_id": "19797dfc-c035-4c92-882c-dd080007a7a5",
    "phone": "+19176753436",
    "note": null,
    "name": "John",
    "generated_name": "Visitor #1",
    "external_id": "14755601",
    "email": "test@email.com",
    "custom_attributes": {
      "external_id": "14755"
    },
    "created_at": "2016-07-13T14:22:56.161119"
  }
]

Description

Fetches list of Site’s Visitors with given External ID. By default, only active Visitors will be returned. The Operator whose API Token is used for making this request must have access to the Site.

Parameters

Name Located In Description Required Type
site_id path Site ID Yes string
external_id query External ID. Maximum length is 64 characters. Yes string
include_offline query Show inactive visitors. The default value is false No boolean

Fetch Visitor Information by Visitor ID

Action: GET /sites/{site_id}/visitors/{id}

curl --request GET \
     --header "Authorization: Token $token" \
     "https://omnibrowse.salemove.com/sites/$site_id/visitors/$visitor_id"
var siteId = '19797dfc-c035-4c92-882c-dd080007a7a5';
var visitorId = 'd2097185-d995-4538-94ae-2ddd77325bbe';
$.ajax({
  type: 'GET',
  url: 'https://omnibrowse.salemove.com/sites/' + siteId + '/visitors/' + visitorId,
  headers: {
    'Authorization': 'Token AjMMVGcvSdHg8H6f_dOr6Q'
  },
  success: function(response) {
    console.log(response);
  }
});

Generates the output

{
  "visitor_id": "d2097185-d995-4538-94ae-2ddd77325bbe",
  "updated_at": "2017-03-21T12:18:32.598729",
  "site_id": "19797dfc-c035-4c92-882c-dd080007a7a5",
  "phone": "+19176753436",
  "note": null,
  "name": "John",
  "generated_name": "Visitor #1",
  "external_id": "14755601",
  "email": "test@email.com",
  "custom_attributes": {
    "external_id": "14755601"
  },
  "created_at": "2016-07-13T14:22:56.161119"
}

Description

Fetches Site’s Visitor by its ID. The Operator whose API Token is used for making this request must have access to the Site.

Parameters

Name Located In Description Required Type
site_id path Site ID Yes string
id path Visitor ID Yes string

Fetch Visitor by Visitor Code

Action: GET /visitor

curl --request GET \
     --header "Authorization: Token $token" \
     "https://omnibrowse.salemove.com/visitor?visitor_code=$visitor_code"
var visitorCode = '12345';
$.ajax({
  type: 'GET',
  url: 'https://omnibrowse.salemove.com/visitor',
  data: {
    visitor_code: visitorCode
  },
  headers: {
    'Authorization': 'Token AjMMVGcvSdHg8H6f_dOr6Q'
  },
  success: function(response) {
    console.log(response);
  }
});

Generates the output

{
  "id": "c62b4a91-a0d7-4137-80e3-c281393b71c2",
  "site_id": "19797dfc-c035-4c92-882c-dd080007a7a5"
}

Description

Fetches Visitor by Visitor Code. The Operator whose API Token is used for making this request must have access to the Site that the Visitor Code was generated for.

Parameters

Name Located In Description Required Type
visitor_code query Visitor Code Yes string

Status codes

Status code Description
200 - OK The provided code is associated with the returned Visitor.
404 - Not Found Provided visitor code is not found or expired.

Update Visitor’s External ID

Action: PATCH /sites/{site_id}/visitors/{visitor_id}

curl --request PATCH \
    --header "Authorization: Token $token" \
    --data-binary "external_id=$external_id" \
    "https://omnibrowse.salemove.com/sites/$site_id/visitors/$visitor_id"
#!/usr/bin/env ruby
require 'rubygems'
require 'rest-client'
require 'json'

token = ARGV[0].strip
site_id = ARGV[1].strip
visitor_id = ARGV[2].strip
external_id = ARGV[3].strip

headers = {
  :authorization => "Token #{token}"
}

body = "external_id=#{external_id}"

response = RestClient.patch "https://omnibrowse.salemove.com/sites/#{site_id}/visitors/#{visitor_id}", body, headers
puts response.body

Generates the Output

{
  "visitor_id": "d2097185-d995-4538-94ae-2ddd77325bbe",
  "updated_at": "2017-03-21T12:18:32.598729",
  "site_id": "19797dfc-c035-4c92-882c-dd080007a7a5",
  "phone": "+19176753436",
  "note": null,
  "name": "John",
  "generated_name": "Visitor #1",
  "external_id": "14755601",
  "email": "test@email.com",
  "custom_attributes": {
    "external_id": "14755601"
  },
  "created_at": "2016-07-13T14:22:56.161119"
}

Description

Updates Visitor’s External ID. The Operator whose API Token is used for making this update must have access to the Site. The maximum length of the External ID is 64 characters.

Parameters

Name Located In Description Required Type
site_id path Site ID Yes string
id path Visitor ID Yes string
external_id request body External ID. Maximum length is 64 characters. Yes string

Showing Visitor Code

<button
  class="omnibrowse-code-button"
  onclick="document.body.appendChild(document.createElement('sm-visitor-code'))">
  Get CoBrowsing code
</button>
// The button to show Visitor Code
<button class="omnibrowse-code-button">
  Get CoBrowsing code
</button>


function showVisitorCode() {
  var code = document.createElement("sm-visitor-code");
  document.body.appendChild(code);
}

// Add a "click" event listener to the button. <sm-visitor-code />
// is added to the DOM when the button is clicked.
document.querySelector(".omnibrowse-code-button").addEventListener("click", showVisitorCode);

OmniBrowse Visitor Code is shown when the Visitor presses the CTRL + Y key combination or by a shake gesture when using a mobile device. The code can also be made to appear by adding a <sm-visitor-code /> Custom HTML Element to the DOM. SaleMove’s Visitor application detects this addition to the DOM and replaces its contents with the OmniBrowse Visitor Code modal which will then appear for the Visitor. When the Visitor clicks the ‘X’ button to close the modal the <sm-visitor-code /> element along with its contents are removed from the DOM. Only one instance of <sm-visitor-code /> can be added to the DOM at a time. When the Visitor Code modal is already visible then any new <sm-visitor-code /> elements added to the DOM will be removed. When the Operator successfully starts observing the Visitor then the OmniBrowse Visitor Code modal is closed and the <sm-visitor-code /> element is removed from the DOM.

As an example the <sm-visitor-code /> element can be used to create buttons on your site that the Visitor can interact with to show the Visitor Code. This would be an alternative method to showing Visitor Code other than the CTRL + Y key combination or the shake gesture.

Exports for OmniBrowse

What is an Engagement in OmniBrowse?

OmniBrowse is built on the same APIs as SaleMove’s more comprehensive solution, OmniCore.

While, in OmniCore, an “Engagement” begins when an Operator and Visitor initiate contact, an OmniBrowse Engagement starts when an Operator commences observation of a Visitor.

Many of our APIs are open, and you may be interested in using them to glean data about the way your Operators are using OmniBrowse.

Although the functions of OmniBrowse and OmniCore differ, you may, as an OmniBrowse customer, wish to pull engagement data from SaleMove when your Operators use the platform.

Configuring Exports

Action: POST /sites/{site_id}/crm/exports

If you implemented OmniBrowse so that your Operators are able to observe your Visitors based on their external_id, then you are already sending a custom attribute to the Visitor class. If you would like to gather other data from your Site, such as

you can do so by programmatically scraping that information from your site and submitting it to SaleMove as Visitor custom attributes when SaleMove loads or as that information becomes available.

Then, when an engagement ends, you can include that information in your Export.

Example Visitor Object

{
  "href":"https://api.salemove.com/visitors/039124e6-b4e8-4a0d-b420-5b6696c7ecb4",
  "name": "Sasha Brown",
  "email": "sasha.brown@email.com",
  "phone": null,
  "note": null,
  "custom_attributes": {},
  "id": "039124e6-b4e8-4a0d-b420-5b6696c7ecb4"
}

Export templates can be configured in three different formats: HTML, XML and JSON. Which template you use will depend on what system you are using to capture the data SaleMove sends. Example templates can be found in SaleMove’s support documentation. In order to include descriptive content about your engagements, you will want to incorporate Field Tags.

Field Tags

Field tags are placeholders for dynamic values which SaleMove will detect and replace on sending your Exports. The following values are available if they are updated before or during an OmniBrowse Engagement. Please review the Exports section of our OmniCore documentation for further information.

Collection Tags

Some templated field tags return multiple items, such as Operators who participated in an Engagement or the custom attributes of a Visitor who left an Offline Message. These are called collection_tags, and generate XML, JSON, or HTML content, depending on the template’s content-type. Please review the Exports section of our OmniCore documentation for further information.

POST New Export

With the aforementioned variables, you can configure exports programmatically. Please take a look at our OmniCore documentation for examples of how to POST an export following an engagement to your inbox, data warehouse, or CRM using SaleMove’s REST API.

OmniCall

OmniCall REST API Specification

GET Available Phone Number List

Action: GET /omnicall/available_phone_numbers

curl --request GET \
    --header "Authorization: Token $token" \
    --header "Accept: application/vnd.salemove.v1+json" \
    "https://api.salemove.com/omnicall/available_phone_numbers?iso_country=US&region=NY&contains=$number&toll_free=false"

Generates the Output

{
  "available_phone_numbers": [
    {
      "phone_number": "+14156433423"
    },
    {
      "phone_number": "+14156433424"
    }
  ]
}

Description

Lists Phone Numbers available for purchase. Query string parameters allow you to limit the list of returned numbers. See more detailed description in the parameters section.

Input Parameters

Field Type Required Description
iso_country string Yes Filters available phone numbers by country. The ISO country code format, e.g. “US”.
region string No Filters available phone numbers by region. The two-letter state or province abbreviation, e.g. “NY”. Only valid when ISO country is US or CA.
contains string No A pattern on which to match phone numbers. Valid characters are * and [0-9a-zA-Z]. The * character will match any single digit.
toll_free boolean No If true, lists available toll-free phone numbers. If false, lists available local phone numbers. Default value is false.

Output

Field Type Description
phone_number string Phone number in E.164 Format
region string The two-letter state or province abbreviation, e.g. “NY”. Only defined when the phone number is local.
postal_code string The postal (zip) code of the phone number. Only defined when the phone number is local.

POST Incoming Phone Number

Action: POST /omnicall/incoming_phone_numbers

curl --request POST \
    --header "Authorization: Token $token" \
    --header "Content-Type: application/json" \
    --header "Accept: application/vnd.salemove.v1+json" \
    --data-binary '{
      "name": "Phone Number Name",
      "description": "Phone Number Description",
      "phone_number": "+14156433423",
      "site_id": "6cd6c309-7d5c-42a0-8750-e8996a15c387"
    }' \
    "https://api.salemove.com/omnicall/incoming_phone_numbers"

Generates the Output

{
  "name": "Phone Number Name",
  "description": "Phone Number Description",
  "site_id": "6cd6c309-7d5c-42a0-8750-e8996a15c387",
  "queue_id": null,
  "phone_number": "+14156433423",
  "created_at": "2016-06-21T09:12:33.001Z",
  "created_by": "d290f1ee-6c54-4b01-90e6-d701748f0851",
  "updated_at": "2016-06-25T09:12:33.001Z",
  "updated_by": "b5cee5ac-a44b-433b-ae86-4a854fd474ab",
  "last_used_at": null,
  "forwarding_option": null,
  "visitor_context": null,
  "pre_queue_audio": null,
  "post_queue_audio": null,
  "in_queue_audio": null,
  "full_queue_audio": null,
  "bounced_queue_audio": null
}

Description

Buys Incoming Phone Number if the number is available. The endpoint returns IDs of the Site and Queue assigned to the phone number. Response also includes other phone number related information such as audio files and forwarding phone number. See more detailed description in the output section.

Input Parameters

Field Type Required Description
phone_number string Yes Incoming Phone Number
name string Yes Name of the Incoming Phone Number
description string No Short description of the Incoming Phone Number
site_id string Yes Site ID
queue_id string No ID of the Queue (in UUID v4 format) to associate with the Incoming Phone Number

Output

Field Type Description
name string Name of the Incoming Phone Number
description string Short description of the Incoming Phone Number
site_id string The ID of the Site the Incoming Phone Number is assigned to
queue_id string The ID of the Queue associated with the Site and assigned to the Incoming Phone Number
phone_number string Incoming Phone Number
created_at string An ISO-8601 timestamp. Defines the creation time of the Incoming Phone Number
created_by string The ID of the Operator who created the Incoming Phone Number
updated_at string An ISO-8601 timestamp. Defines the last time of Incoming Phone Number information update
updated_by string The ID of the Operator who updated the Incoming Phone Number
last_used_at string An ISO-8601 timestamp. Defines the time of the last usage of the Incoming Phone Number
forwarding_option object Where to forward the call when the call cannot be routed to any Operator. See Forwarding Option
visitor_context object The illustration file which is shown to the Operator during the Engagement
pre_queue_audio object The audio file which is played prior to entering the Queue
post_queue_audio object The audio file which is played right before the call is connected to the Operator
in_queue_audio object The audio file which is played while the Visitor is waiting in the Queue
full_queue_audio object The audio file which is played when the Queue is full
bounced_queue_audio object The audio file which is played when a Visitor is bounced from the Queue due to normal or abnormal system’s behavior

GET Incoming Phone Number

Action: GET /omnicall/incoming_phone_numbers/:phone_number

curl --request GET \
    --header "Authorization: Token $token" \
    --header "Accept: application/vnd.salemove.v1+json" \
    "https://api.salemove.com/omnicall/incoming_phone_numbers/$phone_number"

Generates the Output

{
  "name": "Phone Number Name",
  "description": "Phone Number Description",
  "site_id": "6cd6c309-7d5c-42a0-8750-e8996a15c387",
  "queue_id": "4fb75608-06ec-4c08-8866-447faf4b198e",
  "phone_number": "+14156433423",
  "created_at": "2016-06-21T09:12:33.001Z",
  "created_by": "d290f1ee-6c54-4b01-90e6-d701748f0851",
  "updated_at": "2016-06-25T09:12:33.001Z",
  "updated_by": "b5cee5ac-a44b-433b-ae86-4a854fd474ab",
  "last_used_at": "2016-08-29T09:12:33.001Z",
  "forwarding_option": {"type": "phone_number", "phone_number": "+19176733463"},
  "visitor_context": {
    "id": "c3753f72-fcfe-4b4d-b91e-b48f46d149f9",
    "name": "My Illustration Asset",
    "type": "illustration",
    "url": "https://api.salemove.com/omnicall/assets/c3753f72-fcfe-4b4d-b91e-b48f46d149f9",
    "content_type": "application/pdf",
    "created_at": "2016-06-21T09:12:33.001Z",
    "created_by": "d290f1ee-6c54-4b01-90e6-d701748f0851"
  },
  "pre_queue_audio": {
    "id": "6e42cf68-b802-11e7-abc4-cec278b6b50a",
    "name": "My Pre-Queue Audio Asset",
    "type": "audio",
    "url": "https://api.salemove.com/omnicall/assets/6e42cf68-b802-11e7-abc4-cec278b6b50a",
    "content_type": "audio/mpeg",
    "created_at": "2016-06-21T09:12:33.001Z",
    "created_by": "d290f1ee-6c54-4b01-90e6-d701748f0851"
  },
  "post_queue_audio": {
    "id": "097d3d9c-b803-11e7-abc4-cec278b6b50a",
    "name": "My Post-Queue Audio Asset",
    "type": "audio",
    "url": "https://api.salemove.com/omnicall/assets/097d3d9c-b803-11e7-abc4-cec278b6b50a",
    "content_type": "audio/mpeg",
    "created_at": "2016-06-21T09:12:33.001Z",
    "created_by": "d290f1ee-6c54-4b01-90e6-d701748f0851"
  },
  "in_queue_audio": {
    "id": "bb4f4c46-b802-11e7-abc4-cec278b6b50a",
    "name": "My In-Queue Audio Asset",
    "type": "audio",
    "url": "https://api.salemove.com/omnicall/assets/bb4f4c46-b802-11e7-abc4-cec278b6b50a",
    "content_type": "audio/mpeg",
    "created_at": "2016-06-21T09:12:33.001Z",
    "created_by": "d290f1ee-6c54-4b01-90e6-d701748f0851"
  },
  "full_queue_audio": {
    "id": "c39c7aae-b802-11e7-abc4-cec278b6b50a",
    "name": "My Full-Queue Audio Asset",
    "type": "audio",
    "url": "https://api.salemove.com/omnicall/assets/c39c7aae-b802-11e7-abc4-cec278b6b50a",
    "content_type": "audio/mpeg",
    "created_at": "2016-06-21T09:12:33.001Z",
    "created_by": "d290f1ee-6c54-4b01-90e6-d701748f0851"
  },
  "bounced_queue_audio": {
    "id": "171150a6-b803-11e7-abc4-cec278b6b50a",
    "name": "My Bounced-Queue Audio Asset",
    "type": "audio",
    "url": "https://api.salemove.com/omnicall/assets/171150a6-b803-11e7-abc4-cec278b6b50a",
    "content_type": "audio/mpeg",
    "created_at": "2016-06-21T09:12:33.001Z",
    "created_by": "d290f1ee-6c54-4b01-90e6-d701748f0851"
  }
}

Description

Fetches Incoming Phone Number information. The endpoint returns IDs of th