About

Review Stream

Query for all the latest reviews of a given property to use in offline analysis. Filter these reviews by different criteria. Content provided by this API cannot be used for display purposes due to content restrictions.

Widget Review Stream

Query for all the latest reviews of a given property to use for display purposes, such as in a widget. Due to content licensing agreements with our partners, TripAdvisor and Yelp, we are unable to provide TripAdvisor and Yelp content through this endpoint.

Review Summary

The review summary provides you with critical data about your hotel. Key metrics can be analyzed over custom time periods and include:

  • New reviews volume

  • Average review rating

  • TripAdvisor rank

Additionally, see your volume breakdown by review site.

Sentiment Summary

Sentiment Analysis is a core Revinate feature that will help you quickly and easily assess the guest sentiment attributed to your hotels, as well as provide incredibly detailed insight into your operation. Sentiment Analysis goes beyond the review rating by looking at the detail of the reviews and identifying sentiment about various aspects of your operations.

We've tailored our Sentiment Analysis feature specifically for the hospitality industry. Collaborating closely with our customers, we've identified hundreds of the most important topics for hotels, and categorized them based on traditional operations and guest feedback categories.

Introduction

This document describes Revinate's REST API, available resources, supported methods, and expected behavior for requests, responses, and security.

Base URL

All Resources share the same base url: https://porter.revinate.com

Authentication and Access Control

Resources requiring authentication require the use of an API key and API secret (provided by Revinate), which are used to pass the following Authentication headers (sample values below):

                                X-Revinate-Porter-Username: test_user@revinate.com
                                X-Revinate-Porter-Timestamp: 1420765002
                                X-Revinate-Porter-Key: d87b88ceefbcf9d2b2adfb2bbbde1234
                                X-Revinate-Porter-Encoded: 753b2b64fc91ab26484d67b67eeae4f5588ce4d5b107346308a7421246c8fff8
                            
  • The X-Revinate-Porter-Username must be a username that has access to the resources requested and to the API key used.
  • The X-Revinate-Porter-Timestamp is an epoch seconds timestamp that must be within 5 minutes (before or after) of when the request was sent.
  • The X-Revinate-Porter-Key is the API key provided by Revinate.
  • The X-Revinate-Porter-Encoded header is is a keyed-hash message authentication code using a SHA-256 crypto hash function (HMAC SHA256) encryption of the concatenated string: username + timestamp using the API secret. The header is thus HMAC_SHA256(apiSecret, username + timestamp) as per the specifications here HMAC

Below are some sample snippets for how to calculate the HMAC SHA256 using the API secret, username and timestamp

#!/bin/sh

USERNAME=test_user@revinate.com
SECRET=b7536617fa4a1a9e3c7a707abcde866771570cb8c9a28401abcde755b48be6cb
TIMESTAMP=`date +%s`

# Take hexdump of API Secret
kSecret=$(printf "$SECRET" | xxd -p -c 256)

# Use openssl to key-hash the username and timestamp using the secret as key
# Make sure openssl is at least 1.0.0
ENCODED=$(printf "$USERNAME$TIMESTAMP" | openssl dgst -binary -hex -sha256 -mac HMAC -macopt hexkey:$kSecret | sed 's/^.* //')
                                    
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.security.GeneralSecurityException;

public class EncryptionUtil {

    public static String calculateHMAC(String secret, String username, int timestamp) {
        // Concatenate the username and timestamp (epoch seconds)
        String data = username + timestamp;

        try {
            // Encrypt data using the secret
            SecretKeySpec signingKey = new SecretKeySpec(secret.getBytes(), "HmacSHA256");
            Mac mac = Mac.getInstance("HmacSHA256");
            mac.init(signingKey);
            byte[] rawHmac = mac.doFinal(data.getBytes());

            // encrypted data is a byte array convert back to string
            String encoded = "";
            for (final byte element : rawHmac) {
                encoded += Integer.toString((element & 0xff) + 0x100, 16).substring(1);
            }
            return encoded;
        } catch (GeneralSecurityException e) {
            throw new IllegalArgumentException();
        }
    }
}
                                    
require "openssl"

digest = OpenSSL::Digest::SHA256.new

secret = "b7536617fa4a1a9e3c7a707abcde866771570cb8c9a28401abcde755b48be6cb"
username = "test_user@revinate.com"
timestamp = Time.now.to_i
data = "#{username}#{timestamp}"

encoded = OpenSSL::HMAC.hexdigest(digest, secret, data)
                                    
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Security.Cryptography;
namespace Revinate.Tools
{
    class EncryptionUtil
    {
        public static String calculateHMAC(String secret, String username, int timestamp)
        {
            //Concatenate the username and timestamp (epoch seconds)
            String data = username + timestamp;
            try
            { return CreateEncodedToken(data, secret); }
            catch
            { return null; }
        }

        private static string CreateEncodedToken(string message, string secret)
        {
            secret = secret ?? "";
            var encoding = new System.Text.UTF8Encoding();
            byte[] keyByte = encoding.GetBytes(secret);
            byte[] messageBytes = encoding.GetBytes(message);
            using (var hmacsha256 = new HMACSHA256(keyByte))
            {
                byte[] hashmessage = hmacsha256.ComputeHash(messageBytes);
                return ByteToString(hashmessage);
            }
        }

        private static string ByteToString(byte[] buff)
        {
            string sbinary = "";
            for (int i = 0; i < buff.Length; i++)
            { sbinary += buff[i].ToString("x2"); }
            return (sbinary);
        }
    }
}
                                    

Using the snippets above for the following inputs:

                                Username: test_user@revinate.com
                                Timestamp: 1420765002
                                API Key: d87b88ceefbcf9d2b2adfb2bbbde1234
                                API Secret: b7536617fa4a1a9e3c7a707abcde866771570cb8c9a28401abcde755b48be6cb
                            

should result in the following request headers:

                                X-Revinate-Porter-Username: test_user@revinate.com
                                X-Revinate-Porter-Timestamp: 1420765002
                                X-Revinate-Porter-Key: d87b88ceefbcf9d2b2adfb2bbbde1234
                                X-Revinate-Porter-Encoded: 753b2b64fc91ab26484d67b67eeae4f5588ce4d5b107346308a7421246c8fff8
                            

Please contact your sales representative or account manager for your API key and API secret and appropriate access permissions.

Pagination

Some resources support pagination. Typically, these resources contain large lists for which it is impractical to return the entire result set. When pagination is supported, the query parameters used to control the page size and page number are consistent across the API and will be page and size, respectively. It is possible to specify a combination of page and size, which extends beyond the actual result set – in this case, an error is not returned, however the paginated result set will be empty. Additionally, the Revinate API returns a page field in the response body of the form:

                                "page": {
                                    "totalElements": 0,
                                    "totalPages": 0,
                                    "size": 0,
                                    "number": 0
                                }
                            

Where totalElements is the total number of objects and totalPages is the number of pages available based on the value of query param size (default of 10 except reviews which defaults to 5. Max size is 1000). number is the page number of the current page.

Sorting

Some resources support sorting by fields. When sorting is supported, the query parameter used to control the sorting is consistent across the API and will be sort. The sort filter is of the form {field}(,ASC|DESC) where field is a valid field of the resource being requested and ASC|DESC are the available sort directions. Default sort direction is ascending (ASC). Example: ?sort=name,DESC.

Date Filter

Some resources support filtering by a date range. When date filtering is supported, the query parameter used to control the filtering is consistent across the API and will be date. The date filter is of the form {startDate}..{endDate} where startDate and endDate are epoch seconds date endpoints. Example: 1389402398..1420938399.

Resources