Integrations API Production

About the Integrations API

Our Integrations API allows merchants using various eCommerce, booking or payment platforms to instantly access Ve Self Service. Ve Self Service is an integrated platform that plays host to our award winning technology, designed to enhance conversions in addition to driving traffic and incremental revenue growth. The API creates a programmatic way of doing the integration, therefore it can be used by individuals as well as platforms or agencies who want to easily integrate with Ve.


The Customer Tier

The Customer Tier includes the following limits:

  • Working against our production DBs.
  • Request size limits: 0.5kb (double than the average request).
  • Requests per minute: unlimited.
  • Timeout limit: 400ms (based on usual peaks, even though the average is 172ms of server response time).


API Implementation

The implementation of the Generic Integrations API is based on the Client Credentials Grant flow of the OAuth 2 specification.


The auth flow includes the following steps:

  • Step 1: Obtain credentials – direct communication between the your platform and Ve Interactive is used to obtain username and password
  • Step 2: Obtain a bearer token – based on the credentials, an access token is obtained and will be used for the following request.
  • Step 3: Request to authenticate API based on bearer token


Step 1: Obtaining credentials

The username and password will be provided by Ve Interactive upon request.


Step 2: Obtaining a bearer token

In order to make calls to the API, you will have to add in the Request Header the following key: “Ocp-Apim-Subscription-Key” and as value, the API Key found under your profile in Azure API Management Portal account.


Step 3: Authenticate API requests

The token obtained at step 2 can be used in order to issue requests to our API endpoints. There are 2 endpoints which an application should try to access:

  • Install
  • Uninstall

Install


This method should be applied when a merchant wants to install the Ve Self Service. Request requirements:

  • The request must be a HTTPS POST request
  • The request must include an Accept header with the value of application/json
  • The request must include an Content-Type header with the value of application/json
  • The request must include an Ocp-Apim-Subscription-Key header key with the value of <API Key obtained at step 2 from your profile>
  • The body of the request must contain the following parameters (the required ones will have an * next to them, the others are optional)

Parameters:

  • Domain*: complete URL of the shop, not only the domain
  • Email*: email of the merchant
  • Country*: country ISO code (two letters) of the merchant
  • Currency: currency ISO code (three letters) of the merchant
  • Language: language ISO code (two letters) of the merchant
  • Phone: phone number of the merchant
  • ECommerce: the agency used by the merchant
  • ECommercePlatform: the platform used by the merchant (e.g. Magento, Prestashop, etc.)
  • Version: version number of the platform used by the merchant
  • Merchant: contact name


Try it

Request URL

Request headers

(optional)
string
Media type of the body sent to the API.
string
Subscription key which provides access to this API. Found in your Profile.

Request body

{
 "Domain":"string",
 "Email":"string",
 "Country":"string",
 "Currency":"string",,
 "Language":"string",
 "Phone":"string",
 "ECommerce":"string",
 "ECommercePlatform":"string",
 "Version":"string",
 "Merchant":"string"
}
{
  "type": "object",
  "properties": {
    "EcommercePlatform": {
      "type": "string"
    },
    "TaskId": {
      "type": "string"
    },
    "AppCodes": {
      "type": "string"
    },
    "Ecommerce": {
      "type": "string"
    },
    "domain": {
      "type": "string"
    },
    "email": {
      "type": "string"
    },
    "language": {
      "type": "string"
    },
    "merchant": {
      "type": "string"
    },
    "phone": {
      "type": "string"
    },
    "country": {
      "type": "string"
    },
    "currency": {
      "type": "string"
    },
    "contactname": {
      "type": "string"
    },
    "city": {
      "type": "string"
    },
    "province": {
      "type": "string"
    },
    "isInstallFlow": {
      "type": "string"
    },
    "version": {
      "type": "string"
    },
    "extra": {
      "type": "string"
    },
    "token": {
      "type": "string"
    },
    "requestcode": {
      "type": "string"
    },
    "encrypteddate": {
      "type": "string"
    }
  }
}
{
 "Domain":"string",
 "Email":"string",
 "Country":"string",
 "Currency":"string",,
 "Language":"string",
 "Phone":"string",
 "ECommerce":"string",
 "ECommercePlatform":"string",
 "Version":"string",
 "Merchant":"string"
}
{
  "type": "object",
  "properties": {
    "EcommercePlatform": {
      "type": "string"
    },
    "TaskId": {
      "type": "string"
    },
    "AppCodes": {
      "type": "string"
    },
    "Ecommerce": {
      "type": "string"
    },
    "domain": {
      "type": "string"
    },
    "email": {
      "type": "string"
    },
    "language": {
      "type": "string"
    },
    "merchant": {
      "type": "string"
    },
    "phone": {
      "type": "string"
    },
    "country": {
      "type": "string"
    },
    "currency": {
      "type": "string"
    },
    "contactname": {
      "type": "string"
    },
    "city": {
      "type": "string"
    },
    "province": {
      "type": "string"
    },
    "isInstallFlow": {
      "type": "string"
    },
    "version": {
      "type": "string"
    },
    "extra": {
      "type": "string"
    },
    "token": {
      "type": "string"
    },
    "requestcode": {
      "type": "string"
    },
    "encrypteddate": {
      "type": "string"
    }
  }
}

Response 200

Once the method was invoked it will return a JSON object if the installation was successful or a “FALSE” flag in case the installation was unsuccessful.

The JSON object contains the following properties:

  • Errors: a message describing the error (in case an error occurred)
  • Status: a message suggesting if a request was successful or not
  • Token: unique identifier of the merchant
  • URLPixel: the URL of the pixel () that the merchant has to embed in the body of the “Thank You” page
  • URLTag: the URL of the tag that the merchant has to embed in the footer section of all its HTML pages
  • Timestamp: response cached date

{
  "Errors": "",
  "Status": "Success",
  "Token": "94e77dd31b1189aa2cb169880a0d9fc3",
  "URLPixel": "//cds.ve.com/DataReceiverService.asmx/Pixel?journeycode=DC4CC18D-4321-9061-FLWF-2128DAD6DBA6",
  "URLTag": //config.ve.com/tags/DC4CC18D/4321/9061/FLWF/2128DAD6DBA6/tag.js",
  "Timestamp": "2016-11-17,11:42:07-522"
}
{
  "type": "object",
  "properties": {
    "Token": {
      "type": "string"
    },
    "JourneyCode": {
      "type": "string"
    },
    "URLTag": {
      "type": "string"
    },
    "URLPixel": {
      "type": "string"
    },
    "DataCenterName": {
      "type": "string"
    },
    "Status": {
      "enum": [
        "Success",
        "InvalidRequest",
        "Unauthorized",
        "Forbidden",
        "NotFound",
        "TooManyRequests",
        "Error"
      ],
      "type": "string"
    },
    "Errors": {
      "type": "string"
    }
  }
}
{
  "Errors": "",
  "Status": "Success",
  "Token": "94e77dd31b1189aa2cb169880a0d9fc3",
  "URLPixel": "//cds.ve.com/DataReceiverService.asmx/Pixel?journeycode=DC4CC18D-4321-9061-FLWF-2128DAD6DBA6",
  "URLTag": //config.ve.com/tags/DC4CC18D/4321/9061/FLWF/2128DAD6DBA6/tag.js",
  "Timestamp": "2016-11-17,11:42:07-522"
}
{
  "type": "object",
  "properties": {
    "Token": {
      "type": "string"
    },
    "JourneyCode": {
      "type": "string"
    },
    "URLTag": {
      "type": "string"
    },
    "URLPixel": {
      "type": "string"
    },
    "DataCenterName": {
      "type": "string"
    },
    "Status": {
      "enum": [
        "Success",
        "InvalidRequest",
        "Unauthorized",
        "Forbidden",
        "NotFound",
        "TooManyRequests",
        "Error"
      ],
      "type": "string"
    },
    "Errors": {
      "type": "string"
    }
  }
}

Response 400

Invalid request to obtain bearer token

  • Invalid request data (missing required parameters)

{
  "Message": "The request is invalid.",
  "ModelState": {
    "webshopInstallRequest.Domain": [
      "The Domain field is required."
    ]
  }
}
{
  "type": "object",
  "properties": {
    "Status": {
      "enum": [
        "Success",
        "InvalidRequest",
        "Unauthorized",
        "Forbidden",
        "NotFound",
        "TooManyRequests",
        "Error"
      ],
      "type": "string"
    },
    "Errors": {
      "type": "string"
    }
  }
}
{
  "Message": "The request is invalid.",
  "ModelState": {
    "webshopInstallRequest.Domain": [
      "The Domain field is required."
    ]
  }
}
{
  "type": "object",
  "properties": {
    "Status": {
      "enum": [
        "Success",
        "InvalidRequest",
        "Unauthorized",
        "Forbidden",
        "NotFound",
        "TooManyRequests",
        "Error"
      ],
      "type": "string"
    },
    "Errors": {
      "type": "string"
    }
  }
}

Response 401

Page can not be loaded until log on with a valid user ID and password.

{
  "StatusCode": 401,
  "Message": "Access denied due to missing subscription key. Make sure to include subscription key when making requests to an API."
}
{
  "type": "string"
}
{
  "StatusCode": 401,
  "Message": "Access denied due to missing subscription key. Make sure to include subscription key when making requests to an API."
}
{
  "type": "string"
}

Response 429

Too many requests from the same IP

Our API allows a limited number of requests from the same IP as following: 20 requests/second, 100 requests/minute, 400 requests/hour, 1500 requests/day

If this limit is passed, the API will send an error response with the status 429: Too Many Requests


{
  "StatusCode": 429,
  "Message": "Rate limit is exceeded. Try again in 46 seconds."
}
{
  "type": "string"
}
{
  "StatusCode": 429,
  "Message": "Rate limit is exceeded. Try again in 46 seconds."
}
{
  "type": "string"
}

Code samples

@ECHO OFF

curl -v -X POST "https://api.veinteractive.com/IntegrationsApi/Install"
-H "Content-Type: application/json"
-H "Ocp-Apim-Subscription-Key: {subscription key}"

--data-ascii "{body}" 
using System;
using System.Net.Http.Headers;
using System.Text;
using System.Net.Http;
using System.Web;

namespace CSHttpClientSample
{
    static class Program
    {
        static void Main()
        {
            MakeRequest();
            Console.WriteLine("Hit ENTER to exit...");
            Console.ReadLine();
        }
        
        static async void MakeRequest()
        {
            var client = new HttpClient();
            var queryString = HttpUtility.ParseQueryString(string.Empty);

            // Request headers
            client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "{subscription key}");

            var uri = "https://api.veinteractive.com/IntegrationsApi/Install?" + queryString;

            HttpResponseMessage response;

            // Request body
            byte[] byteData = Encoding.UTF8.GetBytes("{body}");

            using (var content = new ByteArrayContent(byteData))
            {
               content.Headers.ContentType = new MediaTypeHeaderValue("< your content type, i.e. application/json >");
               response = await client.PostAsync(uri, content);
            }

        }
    }
}	
// // This sample uses the Apache HTTP client from HTTP Components (http://hc.apache.org/httpcomponents-client-ga/)
import java.net.URI;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

public class JavaSample 
{
    public static void main(String[] args) 
    {
        HttpClient httpclient = HttpClients.createDefault();

        try
        {
            URIBuilder builder = new URIBuilder("https://api.veinteractive.com/IntegrationsApi/Install");


            URI uri = builder.build();
            HttpPost request = new HttpPost(uri);
            request.setHeader("Content-Type", "application/json");
            request.setHeader("Ocp-Apim-Subscription-Key", "{subscription key}");


            // Request body
            StringEntity reqEntity = new StringEntity("{body}");
            request.setEntity(reqEntity);

            HttpResponse response = httpclient.execute(request);
            HttpEntity entity = response.getEntity();

            if (entity != null) 
            {
                System.out.println(EntityUtils.toString(entity));
            }
        }
        catch (Exception e)
        {
            System.out.println(e.getMessage());
        }
    }
}

<!DOCTYPE html>
<html>
<head>
    <title>JSSample</title>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
</head>
<body>

<script type="text/javascript">
    $(function() {
        var params = {
            // Request parameters
        };
      
        $.ajax({
            url: "https://api.veinteractive.com/IntegrationsApi/Install?" + $.param(params),
            beforeSend: function(xhrObj){
                // Request headers
                xhrObj.setRequestHeader("Content-Type","application/json");
                xhrObj.setRequestHeader("Ocp-Apim-Subscription-Key","{subscription key}");
            },
            type: "POST",
            // Request body
            data: "{body}",
        })
        .done(function(data) {
            alert("success");
        })
        .fail(function() {
            alert("error");
        });
    });
</script>
</body>
</html>
#import <Foundation/Foundation.h>

int main(int argc, const char * argv[])
{
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    
    NSString* path = @"https://api.veinteractive.com/IntegrationsApi/Install";
    NSArray* array = @[
                         // Request parameters
                         @"entities=true",
                      ];
    
    NSString* string = [array componentsJoinedByString:@"&"];
    path = [path stringByAppendingFormat:@"?%@", string];

    NSLog(@"%@", path);

    NSMutableURLRequest* _request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:path]];
    [_request setHTTPMethod:@"POST"];
    // Request headers
    [_request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
    [_request setValue:@"{subscription key}" forHTTPHeaderField:@"Ocp-Apim-Subscription-Key"];
    // Request body
    [_request setHTTPBody:[@"{body}" dataUsingEncoding:NSUTF8StringEncoding]];
    
    NSURLResponse *response = nil;
    NSError *error = nil;
    NSData* _connectionData = [NSURLConnection sendSynchronousRequest:_request returningResponse:&response error:&error];

    if (nil != error)
    {
        NSLog(@"Error: %@", error);
    }
    else
    {
        NSError* error = nil;
        NSMutableDictionary* json = nil;
        NSString* dataString = [[NSString alloc] initWithData:_connectionData encoding:NSUTF8StringEncoding];
        NSLog(@"%@", dataString);
        
        if (nil != _connectionData)
        {
            json = [NSJSONSerialization JSONObjectWithData:_connectionData options:NSJSONReadingMutableContainers error:&error];
        }
        
        if (error || !json)
        {
            NSLog(@"Could not parse loaded json with error:%@", error);
        }
        
        NSLog(@"%@", json);
        _connectionData = nil;
    }
    
    [pool drain];

    return 0;
}
<?php
// This sample uses the Apache HTTP client from HTTP Components (http://hc.apache.org/httpcomponents-client-ga/)
require_once 'HTTP/Request2.php';

$request = new Http_Request2('https://api.veinteractive.com/IntegrationsApi/Install');
$url = $request->getUrl();

$headers = array(
    // Request headers
    'Content-Type' => 'application/json',
    'Ocp-Apim-Subscription-Key' => '{subscription key}',
);

$request->setHeader($headers);

$parameters = array(
    // Request parameters
);

$url->setQueryVariables($parameters);

$request->setMethod(HTTP_Request2::METHOD_POST);

// Request body
$request->setBody("{body}");

try
{
    $response = $request->send();
    echo $response->getBody();
}
catch (HttpException $ex)
{
    echo $ex;
}

?>
########### Python 2.7 #############
import httplib, urllib, base64

headers = {
    # Request headers
    'Content-Type': 'application/json',
    'Ocp-Apim-Subscription-Key': '{subscription key}',
}

params = urllib.urlencode({
})

try:
    conn = httplib.HTTPSConnection('api.veinteractive.com')
    conn.request("POST", "/IntegrationsApi/Install?%s" % params, "{body}", headers)
    response = conn.getresponse()
    data = response.read()
    print(data)
    conn.close()
except Exception as e:
    print("[Errno {0}] {1}".format(e.errno, e.strerror))

####################################

########### Python 3.2 #############
import http.client, urllib.request, urllib.parse, urllib.error, base64

headers = {
    # Request headers
    'Content-Type': 'application/json',
    'Ocp-Apim-Subscription-Key': '{subscription key}',
}

params = urllib.parse.urlencode({
})

try:
    conn = http.client.HTTPSConnection('api.veinteractive.com')
    conn.request("POST", "/IntegrationsApi/Install?%s" % params, "{body}", headers)
    response = conn.getresponse()
    data = response.read()
    print(data)
    conn.close()
except Exception as e:
    print("[Errno {0}] {1}".format(e.errno, e.strerror))

####################################
require 'net/http'

uri = URI('https://api.veinteractive.com/IntegrationsApi/Install')

request = Net::HTTP::Post.new(uri.request_uri)
# Request headers
request['Content-Type'] = 'application/json'
# Request headers
request['Ocp-Apim-Subscription-Key'] = '{subscription key}'
# Request body
request.body = "{body}"

response = Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https') do |http|
    http.request(request)
end

puts response.body