Neustar Web Performance Management

API Documentation

Available APIs



How to use this Interactive Documentation

This API documentation guide is interactive. On the api details page, simple enter your api and shared secret keys and you can make test api calls right from the documentation page. You can find your api keys by going to the "My Account" area when clicking on your username in the top right corner of the web portal, and then clicking on 'Manage' for your username. The documentation page constructs a valid sig for you, and automatically adds the apikey parameter to each call. You may then tweak the other parameters as desired. Required parameters are bolded, and any defaults will be pre-populated for you.

How to use the APIs

The Neustar Web Performance Management (WPM) APIs are provided as a simple RESTful web service interface so that you can obtain information from and modify your account.

To perform an action using the Neustar WPM APIs, you need to send an HTTP GET, POST, PUT or DELETE request to the API URL specifying your api key, a valid signature and some arguments. You will receive a json formatted response, along with a HTTP response code.

The base Neustar WPM API URL is: http://api.sec.neustar.biz/performance/ The path to the particular api endpoint that you wish to call is appended next (includes the API version number).

A Python library is available as an example at https://github.com/web-performance/wpm_api_client

Making the Request

Signing the API Call

Requests sent to the Neustar WPM API require an API key and a digital signature.

A valid call is determined by validating the sig parameter at the time the request is made against the service. The value of sig is calculated by generating an MD5 hash made up of the API key (apikey), the API user’s shared secret, and a UNIX timestamp reflecting the number of seconds since the Unix epoch (January 1 1970 00:00:00 GMT) at the time the request is made. The system accepts timestamps up to five minutes on either side of the server timestamp, to accommodate reasonable clock drift.

NOTE: To obtain your Neustar WPM API key (apikey) and the shared secret that you need to build a digital signature, register online at https://home.wpm.neustar.biz/, then click on your username on the top right and go to 'My Account'. Then click on Manage beside your username and your keys will be displayed.

Creating a Digital Signature in Code


Most programming languages provide some version of an md5() function, which should be used to generate the signature. The following example illustrates how to generate a valid signature with PHP:


$apikey = 'epuc35nesxv4bj9ww9k372rj'; $secret = 's2Q3Cx6P'; $timestamp = gmdate('U'); // 1200603038 $sig = md5($apikey . $secret . $timestamp);


The following example URL illustrates a request to the Neustar WPM API, based on an API key of ‘epuc35nesxv4bj9ww9k372rj,’ a timestamp of ‘1200603038’ (Thu, 17 Jan 2008 20:50:38 +0000), and a shared secret of ‘s2Q3Cx6P’:


http://api.sec.neustar.biz/performance/monitor/1.0?apikey=epuc35nesxv4bj9ww9k372rj&sig=65a08176826fa4621116997e1dd775fa


NOTE: Errors during the creation of the digital signature are often the reason when requests fail to authenticate and yield 403 errors. When creating the signature, be sure to:


Code Samples

You can send REST requests in any programming language. The following are samples of the code for several popular languages (PHP, Python, Java, Ruby, Perl, C#, and node.js). Each example retrieves the list of all monitoring locations available for an account, uses the hosted service at api.sec.neustar.biz, and passes query parameters for an API key (apikey) and the digital signature (sig). The response is in JSON, and does not change from language to language of the request.


NOTE: This is sample code to illustrate the syntax and is not suitable for production environments. Best practices dictate that using these samples in a production environment requires error handling to catch situations where the request fails at the HTTP level.


PHP


// initiate curl and set options $ch = curl_init(); $apikey = 'epuc35nesxv4bj9ww9k372rj'; $secret = 's2Q3Cx6P'; $timestamp = gmdate('U'); // 1200603038 // echo $timestamp; $sig = md5($apikey . $secret . $timestamp); $base_url = 'http://api.sec.neustar.biz/performance'; $service = '/monitor'; $ver = '/1.0'; $method = '/locations'; curl_setopt($ch, CURLOPT_URL, $base_url . $service . $ver. $method. '?apikey=' . $apikey . '&sig='.$sig); curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $data = curl_exec($ch); $headers = curl_getinfo($ch); // close curl curl_close($ch); // return XML data if ($headers['http_code'] != '200') { echo "An error has occurred"; return false; } else { echo $data; return($data); }


Python


import urllib2 import hashlib import time
base_url = 'http://api.sec.neustar.biz/performance' service = '/monitor' version = '/1.0' method = '/locations'
apikey = 'epuc35nesxv4bj9ww9k372rj' secret = 's2Q3Cx6P'
# seconds since GMT Epoch timestamp = str(int(time.time())) # print timestamp sig_unencoded = apikey + secret + timestamp sig = hashlib.md5(sig_unencoded.encode()).hexdigest() url = base_url + service + version + method + '?apikey=' + apikey + '&sig=' + sig # print url json = urllib2.urlopen(url).read()
print json


Java


import java.io.*; import java.math.BigInteger; import java.security.MessageDigest;
import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient;
public class RestfulCallExample {
public static String baseUrl = "http://api.sec.neustar.biz/performance"; public static String service = "/monitor"; public static String version = "/1.0"; public static String method = "/locations"; public static String apikey = "epuc35nesxv4bj9ww9k372rj"; public static String secret = "s2Q3Cx6P";
public static void main(String[] args) throws Exception {
MessageDigest md = MessageDigest.getInstance("MD5"); long timeInSeconds = (long)(System.currentTimeMillis()/1000); String input = apikey + secret + timeInSeconds; md.update(input.getBytes()); String sig = String.format("%032x", new BigInteger(1, md.digest()));
String url = baseUrl + service + version + method + "?apikey=" + apikey + "&sig=" + sig; System.out.println("URL=" + url); DefaultHttpClient httpclient = new DefaultHttpClient();
// Create an HTTP GET request HttpGet httpget = new HttpGet(url);
// Execute the request httpget.getRequestLine(); HttpResponse response = null; response = httpclient.execute(httpget);
HttpEntity entity = response.getEntity(); // Print the response System.out.println(response.getStatusLine());
if (entity != null) { InputStream inputStream = entity.getContent(); // Process the response BufferedReader bufferedReader = new BufferedReader( new InputStreamReader(inputStream)); String line; while ((line = bufferedReader.readLine()) != null) { System.out.println(line); } bufferedReader.close(); } // shut down the connection manager to ensure // immediate deallocation of all system resources. httpclient.getConnectionManager().shutdown(); } }


Ruby


require 'net/http' require 'digest/md5'
# API location PRODUCTION_ENDPOINT = 'http://api.sec.neustar.biz/performance' SERVICE = '/monitor' API_VERSION = '/1.0' METHOD = '/locations'
# Your credentials API_KEY = 'epuc35nesxv4bj9ww9k372rj' SHARED_SECRET = 's2Q3Cx6P'
current_time = Time.now timestamp = Time.now.to_i.to_s sig = Digest::MD5.hexdigest( API_KEY+SHARED_SECRET+timestamp )
request_url = URI.parse("#{PRODUCTION_ENDPOINT}#{SERVICE}#{API_VERSION}#{METHOD}?apikey=#{API_KEY}&sig=#{sig}")
req = Net::HTTP::Get.new(request_url.to_s) res = Net::HTTP.start(request_url.host, request_url.port) do |http| http.request(req) end print res.body


Perl


# perl
use strict; use LWP::UserAgent; use Digest::MD5 qw(md5 md5_hex);
my $baseUrl = 'http://api.sec.neustar.biz/performance'; my $service = '/monitor'; my $version = '/1.0'; my $method = '/locations';
# key and shared secret obtained from registering application my $apikey = 'epuc35nesxv4bj9ww9k372rj'; my $secret = 's2Q3Cx6P';
my $timestamp = time; # above timestamp needs to be created in PERL !!! Placeholder my $sig = md5_hex($apikey . $secret . $timestamp);
# print $timestamp," ", $sig, "\n";
my $ua = new LWP::UserAgent; $ua->timeout(120);
my $url = $baseUrl . $service . $version . $method . '?apikey=' . $apikey . '&sig=' . $sig ; # print $url, "\n";
my $request = new HTTP::Request('GET', $url); my $response = $ua->request($request); my $json = $response->content(); print $json,"\n";


C#


using System; using System.Collections.Generic; using System.Text; using System.IO; using System.Net; using System.Security.Cryptography;
namespace WPMAPIRESTSample { class Program { static void Main(string[] args) { string baseUrl = "http://api.sec.neustar.biz/performance"; string service = "/monitor"; string version = "/1.0"; string method = "/locations"; string apikey = "epuc35nesxv4bj9ww9k372rj"; string secret = "s2Q3Cx6P"; string sig = MD5GenerateHash(apikey + secret + (Int32)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds); string fullURL = baseUrl + service + version + method + "?apikey=" + apikey + "&sig=" + sig;
// Create the web request HttpWebRequest request = WebRequest.Create(fullURL) as HttpWebRequest;
// Get response using (HttpWebResponse response = request.GetResponse() as HttpWebResponse) { // Get the response stream StreamReader reader = new StreamReader(response.GetResponseStream()); | // Write response to the console Console.WriteLine(reader.ReadToEnd()); }
}
private static string MD5GenerateHash(string strInput) { // Create a new instance of the MD5CryptoServiceProvider object. MD5 md5Hasher = MD5.Create();
// Convert the input string to a byte array and compute the hash. byte[] data = md5Hasher.ComputeHash(Encoding.Default.GetBytes(strInput));
// Create a new Stringbuilder to collect the bytes and create a string. StringBuilder sBuilder = new StringBuilder();
// Loop through each byte of the hashed data and format each one as a hexadecimal string. for (int nIndex = 0; nIndex < data.Length; ++nIndex) { sBuilder.Append(data[nIndex].ToString("x2")); }
// Return the hexadecimal string. return sBuilder.ToString(); } } }


node.js


var http = require('http'), crypto = require('crypto');
var options = { host: 'api.sec.neustar.biz', path: '/performance', port: 80, };
var service = '/monitor'; var version = '/1.0'; var method = '/locations';
var apikey = 'epuc35nesxv4bj9ww9k372rj'; var secret = 's2Q3Cx6P';
var currTimeStamp = Math.round((new Date().getTime()) / 1000); var sig = crypto.createHash('md5').update(apikey + secret + currTimeStamp).digest("hex");
options.path += service + version + method +'?apikey=' + apikey + '&sig=' + sig;
var response = ''; var req = http.get(options, function(res) { res.on('data', function (chunk) { response += chunk; }); res.on('end', function () { if (res.statusCode !== 200) { console.log('Request failed: HTTP status response = ' + res.statusCode); } console.log(response); }); });


Response Format

The response will return two things: If the success response could be paginated, it should always return a data object with items, more, total (the total number of records available), count (the number returned in this call) and offset.

{ "data": { "items": [{"status": 'SUCCESS', "bytesReceived": 594936, "errorLineNumber": 0, "location": 'portland', "startTime": '2012-05-31T15:27:05', "duration": 6765, "id": 'bf5565f0ab6f11e1afe1984be166ac54' }, {...}, ... {...} ], "count": 2000, "more": true, "total": 2268, "offset": 0 } }


If the success response isn't paginated, then just the items.

{ "data": { "items": [{"alertPolicy": null, "locations": ["sanfranciscoca", "washingtondc", "portlandor"], "script": {"version": "mPHIo4TJ5nAonnZhz_16wyB5lTLC7.MX", "id": "69cc4faaac5a4bb7b880380926b08998", "name": "Grid" }, "description": "My Monitor Description", "interval": 5, "name": "API Name", "lastSampleAt", null "inMaintenanceWindow": false, "active": false, "type": "full", "id": "8725440e931711e1b459000c299f6329", "browser": "chrome" }, {...}, ... {...} ] } }


The error response should always contain the message, code and param keys, but additional are optional.

{ "errors": [{ "message": "The item could not be found", //A string providing details on what the error was. "code": "NAMESPACE-40", //Identifies which error occurred. "param": "FAILED_PARAMETER" //Optional - A string indicating which field(s) had the failure, if it was a field error. // other optional }] }


Error Codes


If a request fails, then both an HTTP status coding indicating the general failure condition as well as a detailed error message are produced. The error code is a machine readable status which will never change, where the text of the error message might change due to changing inputs or other factors. A list of these codes and messages is shown below.


Monitoring API Error Codes


Error CodeDescription
MON_0000Resource :resource not available
MON_0001Item with Id :itemid not found
MON_0002Duplicate name :name found.
MON_0003:missingfield is/are required fields
MON_0004:value is an invalid value.
MON_0005:value is an invalid value type. Type :valuetype expected
MON_0006:field is an invalid field
MON_0007Valid :field id not supplied
MON_0008Empty body received in POST
MON_0009Empty body received in PUT
MON_0010System cannot complete the request
MON_0011User does not have permission to perform the action
MON_9999An internal error has occured


Real User Measurements API Error Codes


Error CodeDescription
RUM_000Request has been throttled
RUM_001Database internal error
RUM_002Generic internal error
RUM_003Database found data inconsistencies
RUM_004Generic Forbidden error
RUM_005Mandatory parameter is missing
RUM_006Parameter is not valid



© 2017 Neustar Inc. All Rights Reserved.Privacy Policy Sales: 1.888.367.4812 Support: 1.888.367.4820