GeoPoint REST API Guide

Introduction

Neustar's® IP Intelligence provides the geographic location, network, and contextual data for any Internet Protocol (IP) address in the public address space. This information is critical for:

  • Localizing content
  • Targeting your marketing message
  • Complying with local regulations
  • Preventing fraud

GeoPoint, the IP Intelligence data engine, enables anyone to build that IP intelligence directly into their applications for the web, desktop, and mobile devices.

The IP Intelligence API provides a simple RESTful (REST) interface that returns GeoPoint data over HTTP. The information includes:

  • Postal code, city, state, region, country, and continent
  • Area code (US and Canada only) and time zone
  • Longitude and latitude
  • DMA (Designated Market Area) and MSA (Metropolitan Statistical Area)
  • Network information, including type, speed, carrier, and registering organization

This document describes how to retrieve GeoPoint data via the REST API, whether from Neustar's hosted service or a GeoDirectory® Server (GDS) installed locally at your site.

Feedback

Neustar appreciates feedback and suggestions from customers. To submit a comment or report a documentation error, send email to support-ipintel@neustar.biz.

Developer Resources & Documentation

You can register your application and find more documentation and other resources for developers in Neustar's online community at: http://developer.neustar.biz.

Find definitions of GeoPoint data fields (provided as XML or JSON elements in the GeoPoint service) in the online Data Glossary, which includes information about possible field values and ranges, as well as notes.

Developer Badges

Developers may add the following badges to their applications: 

          

If you include a badge, link the image to: http://developer.neustar.biz.

The Request — HTTP

To access the Neustar IP Intelligence REST API, you send a standard HTTP GET request that specifies the IP address for which you want the geolocation and network data. GeoPoint then responds with the IP data in structured XML or JSON format.

This chapter describes how to make the HTTP request and includes code samples in several languages to make it easy to build requests, and the next chapter describes the response from the GeoPoint engine.

Calling the API

Neustar IP Intelligence provides two ways to retrieve IP data:

  • Neustar’s hosted service, at api.quova.com
  • Neustar GeoDirectory® Server (GDS), on a server at your site

Send API calls to one of these two platforms, depending on your Neustar license. (To learn about the benefits of each, see http://www.quova.com/what/products/.)

Make the HTTP request by appending the IP address for your query at the end of the URL:

http://<host>/v1/ipinfo/<IP address>

In the URL:

  • <host> is either:

    • <your_local_server>/GeoDirectoryServer, where <your_local_server> is the address of the server on your network and GeoDirectoryServer is the name of the service (and the default directory where GDS is installed) or

    •  api.quova.com, for the hosted service.
      NOTE: If you have a customer production class key your host value is: api.quova.com/geodirectory.

  • <IP address> is the referenced IP address, that is, the IP address for which the data is being requested.

    NOTE: IP Intelligence supports only IPv4 (32-bit) addresses, and they must be in standard IPv4 dot-decimal or decimal notation:

    • Dot-decimal notation is the 32-bit address expressed in four octets that are separated by periods, as in:

      <A-block>.<B-block>.<C-block>.<XXX>

    • Decimal notation is the 32-bit address expressed in decimal, as in:

      <XXXXXXXX>

For example, ‘4.2.2.2’ is the dot-decimal expression of the decimal IP address ‘67240450’ — both notations represent the same IP address, and both are recognized by IP Intelligence.

Using the Hosted Service

If your Neustar license is for the hosted API service, point the HTTP request at api.quova.com. For example:

http://api.quova.com/v1/ipinfo/4.2.2.2

Using the Local Service

If you call a locally installed GeoDirectory Server, send the command to the GeoDirectoryServer service on your local server. For example:

http://<your_local_server>/GeoDirectoryServer/v1/ipinfo/4.2.2.2

Signing the API Call

Requests sent to the IP Intelligence API (api.quova.com) require an API key and a digital signature. In calls to locally installed GeoDirectory Servers, API keys and digital signatures are not required.

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 IP Intelligence API key (apikey) and the shared secret that you need to build a digital signature, register your application at http://developer.neustar.biz/.

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 IP Intelligence 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.quova.com/v1/ipinfo/4.2.2.2?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: .

  • Use seconds since the UNIX Epoch, not milliseconds. (Some systems return the time in milliseconds. In these cases, the timestamp must be converted to seconds before being used.)
  • Recalculate the digital signature with each call. (There is a 5-minute window of clock skew allowed.)
  • Make sure the server calling our service is in sync with an atomic clock.  It will then be in sync with our servers.
  • Make sure the hash value is lowercase. 

The Method

Currently, there is only one method: ipinfo, which returns GeoPoint IP data. The response is in a structured data format, XML or JSON, where the fields are organized in a hierarchical format, by network information and location.

The ipinfo method includes two resources: <IP address> and schema.

  • ipinfo/<IP address> returns all data for <IP address> that the system is licensed to provide. See Sample XML Response and Sample JSON Response below.

  • ipinfo/schema returns the XML Schema Document (.xsd file) for structured XML

    NOTE: It is a good practice to request and review the XML Schema Document, as it enumerates all possible data fields that are available from IP Intelligence, not just those fields that are configured for your license. See Sample Response — ipinfo/schema below.

By default, the ipinfo method retrieves IP geolocation and network data, except when the schema resource is specifically requested.

The URL

In addition to identifying the resource (the IP address being queried) and requesting the schema document, the URL can specify parameters, and consists of several elements:

<host>/<version>/<method>/<resource>?<parameter>&<parameter>

The elements of the HTTP request are:

ElementRequiredDescription

host

Host domain for the REST API.   The host will vary with your service level:

For developer-class keys in Neustar's hosted web service, use:

  http://api.quova.com/

 

For customer production-class keys in Neustar's hosted web service, use:

  http://api.quova.com/geodirectory

 

For a locally installed GDS server, use the local server address and the GDS service name (GeoDirectoryServer, by default). For example:

http://<your_local_server>/GeoDirectoryServer/

version

The version of the API being called.

method

Currently, only one method is supported:

ipinfo: returns IP geolocation and network data in XML, or the schema.

resource

<IP address> or schema.

If an IP address is specified in the correct format, the call returns all available GeoPoint data for that IP. The IP must be a standard, 32-bit IPv4 address. The allowed IP formats are dot-decimal and decimal notation. For example:

Dot-decimal notation: 4.2.2.2

Decimal notation: 67240450

If the resource is a schema request, it returns the XML Schema Document (.xsd file).

Parameters

As illustrated above, the URL can include parameters. For calls to the IP Intelligence hosted API service, the URL must also include the following:

ParameterRequired for hosted serviceDescription
apikey

Customer application identifier. This is a string with a maximum length of 255 characters, and may not include blank spaces or special characters.

sig

The digital signature for the request, created as an MD5 hash of apikey, your shared secret, and the timestamp.

format

Specifies the data format for ipinfo responses. This parameter is optional; in its absence, the data format is determined by the HTTP Accept header. Alernatively, you can use this parameter. To specifiy responses in JSON, use format=json. For example:

http://api.quova.com/v1/ipinfo/4.2.2.2?format=json

NOTE: When the data format is specified both in the HTTP Accept header and by the format parameter, the parameter takes precedence. . If the response format cannot be determined, the format defaults to xml.

callback

IP Intelligence also supports JSON with Padding (JSONP), which allows callers to insert a dynamic script element and requires a user-specified function name. If you have specified the format as JSON, you can request that GeoPoint return the JSON data wrapped in a specified function name. To do so, use callback=<YourFunctionName>. For example:

http://api.quova.com/v1/ipinfo/4.2.2.2?format=json&callback=<YourFunctionName>

 

NOTE: Unrecognizable parameters and invalid values are ignored, and the operation reverts to defaults.

For more on authenticating your calls, see Signing the API Call above.

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, and C#). Each example retrieves the GeoPoint data for IP address 4.2.2.2, uses the hosted service at api.quova.com, and passes query parameters for an API key (apikey) and the digital signature (sig). The GeoPoint response is in XML, or JSON if specified, 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

This is an example of a call to the IP Intelligence service in PHP:

<?php

// initiate curl and set options
$ipin = '4.2.2.2';
$ch = curl_init();
$ver = 'v1/';
$method = 'ipinfo/';
$apikey = 'epuc35nesxv4bj9ww9k372rj';  
$secret = 's2Q3Cx6P';  
$timestamp = gmdate('U'); // 1200603038
// echo $timestamp;   
$sig = md5($apikey . $secret . $timestamp);
$service = 'http://api.quova.com/';
curl_setopt($ch, CURLOPT_URL, $service . $ver. $method. $ipin . '?apikey=' .
             $apikey . '&sig='.$sig . '&format=xml');
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 accessing this IP";
  return false;
} else {
   echo $data;
   return($data);
}

?>

Python

This is an example of a call to the IP Intelligence service in Python. If the credentials are valid, the call will return an XML payload into a variable named ‘xml.’ (or  ‘json’ if requested).

import urllib2
import md5
import time

service = 'http://api.quova.com/'
version = 'v1/'
method = 'ipinfo/'
ip = '4.2.2.2'

apikey = 'epuc35nesxv4bj9ww9k372rj'  
secret = 's2Q3Cx6P'

hash = md5.new()
# seconds since GMT Epoch
timestamp = str(int(time.time()))
# print timestamp
sig = md5.new(apikey + secret + timestamp).hexdigest()
url = service + version + method + ip + '?apikey=' + apikey + '&sig=' + sig + '&format=xml'
# print url
xml = urllib2.urlopen(url).read()

print xml

Java

The following Java example illustrates how to execute a web service request for GeoPoint data via an HTTP GET. It relies on the HttpComponents package from the Apache Software Foundation:

// IP Intelligence REST Web Service  
// @author www.quova.com 
//Copyright 2010 Quova, Inc. 
//This example illustrates how to execute a web service request via HTTP GET. 08 
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 service = "http://api.quova.com/";
   public static String version = "v1/";
   public static String method = "ipinfo/";
   public static String ip = "4.2.2.2";
   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 = service + version + method + ip + "?apikey=" + apikey
            + "&sig=" + sig + "&format=xml";
      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;
      try {
         response = httpclient.execute(httpget);
      } catch (ClientProtocolException e) {
         e.printStackTrace();
      } catch (IOException e) {
         e.printStackTrace();
      } 

      HttpEntity entity = response.getEntity();
      // Print the response
      System.out.println(response.getStatusLine());

      if (entity != null) {
         try {
            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();
         } catch (IOException e) {
            e.printStackTrace();
         }
      }
      // shut down the connection manager to ensure
      // immediate deallocation of all system resources.
      httpclient.getConnectionManager().shutdown();
   }
}

Ruby

The following Ruby example uses Digest::MD5 to generate the digital signature, and Net::HTTP to send the request:

require 'net/https'
require 'digest/md5'

# IP address to send to the IP Intelligence service
ip_address = '4.2.2.2'

# API location
PRODUCTION_ENDPOINT = 'api.quova.com'
PRODUCTION_PORT = 80

# Your credentials
API_KEY = 'epuc35nesxv4bj9ww9k372rj'
SHARED_SECRET = 's2Q3Cx6P'
API_VERSION = 'v1'

current_time = Time.now
timestamp = Time.now.to_i.to_s
sig = Digest::MD5.hexdigest( API_KEY+SHARED_SECRET+timestamp )

request_url = "/#{API_VERSION}/ipinfo/#{ip_address}?apikey=#{API_KEY}&sig=#{sig}&format=xml"

http = Net::HTTP.new( PRODUCTION_ENDPOINT , PRODUCTION_PORT )
http.start do |http|
  req = Net::HTTP::Get.new(request_url)

  resp, data = http.request(req)

  print data
end

Perl

The following example illustrates the same query being built in Perl:

# perl

use strict;
# use LWP::Simple;
use LWP::UserAgent;
use Digest::MD5 qw(md5 md5_hex);

my $service = 'http://api.quova.com/';
my $method = 'ipinfo/';
my $version  = 'v1/';
my $ip       = '4.2.2.2';

# 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=$service . $version . $method . $ip . '?apikey=' . $apikey . '&sig=' . $sig . '&format=xml' ;
# print $url, "\n";

my $request = new HTTP::Request('GET', $url);
my $response = $ua->request($request);
my $xml = $response->content();
print $xml,"\n";

C#

The following C# example uses HttpWebRequest and HttpWebResponse:

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Net;
using System.Security.Cryptography;

namespace IPIntelRESTSample
{
    class Program
    {
        static void Main(string[] args)
        {
            string service = "http://api.quova.com/";
            string version = "v1/";
            string method = "ipinfo/";
            string ipAddress = "4.2.2.2";
            string apikey = "epuc35nesxv4bj9ww9k372rj";
            string secret = "s2Q3Cx6P";
            string sig = MD5GenerateHash(apikey + secret + (Int32)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds);
            string fullURL = service + version + method + ipAddress + "?apikey=" + apikey + "&sig=" + sig + "&format=xml";

            // 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();
        }
    }
}



The Response — XML or JSON

Whichever language and platform you use to make the HTTP request of the IP Intelligence service, the response is the same.

GeoPoint's data fields enumerate the geolocation and network characteristics of the IP address. In the IP Intelligence service, each data field is provided as an XML or JSON element of the same name, in lower case (e.g., the ‘<ip_address></ip_address>’ element). By default, those elements are grouped into nodes that represent categories of data fields, with initial capitals (e.g., the ‘<Network></Network>’ node).

Structure of a GeoPoint Response

The response to an ipinfo query is in structured XML or JSON. The structure is reflected in the hierarchy of the nodes (categories) and elements (data fields).

Most elements are grouped into nodes of network and geographic location. The top-level node that encompasses the response is 'ipinfo' (the method called).

<ipinfo> contains:

    <ip_address> The referenced IP address
    <ip_type> The type of IP address, mapped or reserved
    premium fields For example, the <anonymizer_status/> element
    <Network> Node that contains network details about the IP address
    <Location> Node that contains geographic details about the IP address

Each node can contain both elements and sub-nodes. For example, <Location> contains the <continent> element, as well as the <CountryData> node, which in turn contains the <country> element and others.

To review the complete structure that includes all possible elements, see the sample .xsd file in Sample Response — ipinfo/schema below. (Only available in XML and not in JSON.)

For a definition of each GeoPoint data field (represented here as XML or JSON elements), see the online GeoPoint Data Glossary, which includes information about possible field values and ranges, as well as notes.

Requesting a JSON Response

By default, GeoPoint sends responses to ipinfo requests in structured XML data format. However, you can also request the response in JSON data format. To request JSON, you can either use the HTTP Accept Header to specify 'application/json' or use the format parameter in the ipinfo call. (See Parameters above.) For example:

http://api.quova.com/v1/ipinfo/4.2.2.2?format=json

NOTE: When the data format is specified both in the HTTP Accept header and by the format parameter, the parameter takes precedence.

IP Intelligence also supports JSON with Padding (JSONP), which allows callers to insert a dynamic script element and requires a user-specified function name. If you have specified the format as JSON, you can request that GeoPoint return the JSON data wrapped in the specified function name. To do so, use callback=<YourFunctionName>. For example:

http://api.quova.com/v1/ipinfo/4.2.2.2?format=json&callback=<YourFunctionName>

Sample XML Response — ipinfo/<IP address>

This example illustrates the XML elements in a typical response to ipinfo/<IP address>:

<?xml version="1.0" encoding="UTF-8"?>
<ipinfo>
   <ip_address>4.2.2.2</ip_address>
   <ip_type>Mapped</ip_type>
   <anonymizer_status/>
   <Network>
      <organization>level 3 communications  inc.</organization>
      <OrganizationData>
	 <home>false</home>
      	 <organization_type>Telecommunications</organization_type>
         <naics_code>518219</naics_code>
	 <isic_code>J6311</isic_code>
      </OrganizationData>      
      <carrier>level 3 communications</carrier>
      <asn>3356</asn>
      <connection_type>tx</connection_type>
      <line_speed>high</line_speed>
      <ip_routing_type>fixed</ip_routing_type>
      <Domain>
         <tld>net</tld>
         <sld>bbnplanet</sld>
      </Domain>
   </Network>
   <Location>
      <continent>north america</continent>
      <CountryData>
         <country>united states</country>
         <country_code>us</country_code>
         <country_cf>99</country_cf>
      </CountryData>
      <region>southwest</region>
      <StateData>
         <state>california</state>
         <state_code>ca</state_code>
         <state_cf>88</state_cf>
      </StateData>
      <dma>803</dma>
      <msa>31100</msa>
      <CityData>
         <city>san juan capistrano</city>
         <postal_code>92675</postal_code>
         <time_zone>-8</time_zone>
         <area_code>949</area_code>
         <city_cf>77</city_cf>
      </CityData>
      <latitude>33.499</latitude>
      <longitude>-117.662</longitude>
   </Location>
</ipinfo>

NOTE: If an IP address does not have data for a specific field, the value for that field is null.

NOTE: The fields in the response are based on your license key.

 

Sample JSON Response — ipinfo/<IP address>?format=json

This example illustrates the JSON elements in a typical response to ipinfo/<IP address>?format=json:

{"ipinfo": {
	"ip_address":"4.2.2.2",
 	 "ip_type":"Mapped",
	 "anonymizer_status":null,
		"Network":{
			"organization":"level 3 communications  inc.",
			"OrganizationData":{
				"home":"false",
				"organization_type":"Internet Service Provider",
				"naics_code":"517110",
				"isic_code":"J6110",
			},
			"carrier":"level 3 communications",
			"asn":3356,
			"connection_type":"tx",
			"line_speed":"high",
			"ip_routing_type":"fixed",
			"Domain":{
				"tld":"net",
				"sld":"bbnplanet"
			},
		},
		"Location":{
	            	"continent":"north america",
	                "latitude":33.499,
	                "longitude":-117.662,
			"CountryData":{
		        	"country":"united states",
		        	"country_code":"us",
		        	"country_cf":97,
			},
			"region":"southwest",
			"StateData":{
		      		"state":"california",
		       		"state_code":"ca",
		       		"state_cf":87,
			},
	       		"dma":803,
	        	"msa":31100,
			"CityData":{
		       		"city":"san juan capistrano",
		       		"postal_code":"92675",
		       		"time_zone":-8,
		       		"area_code":"949",
		       		"city_cf":77,
			},
		}
}}

NOTE: If an IP address does not have data for a specific field, the value for that field is null.

NOTE: The fields in the response are based on your license key.

 

Sample Response — ipinfo/schema

This example illustrates the XML elements in a typical response to ipinfo/schema:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
  <xs:element name="ipinfo">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="ip_address" type="xs:string" minOccurs="1" maxOccurs="1"/>
        <xs:element name="ip_type" type="xs:string" minOccurs="1" maxOccurs="1"/>
        <xs:element name="anonymizer_status" type="xs:string" minOccurs="0" maxOccurs="1"/>
        <xs:element name="Network" type="network_type" minOccurs="0" maxOccurs="1"/>
        <xs:element name="Location" type="location_type" minOccurs="0" maxOccurs="1"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  
  <!-- network type -->
  <xs:complexType name="network_type">
    <xs:sequence>
      <xs:element name="organization" type="xs:string" minOccurs="0" maxOccurs="1"/>
      <xs:element name="carrier" type="xs:string" minOccurs="0" maxOccurs="1"/>
      <xs:element name="asn" type="xs:int" minOccurs="0" maxOccurs="1"/>
      <xs:element name="connection_type" type="xs:string" minOccurs="0" maxOccurs="1"/>
      <xs:element name="line_speed" type="xs:string" minOccurs="0" maxOccurs="1"/>
      <xs:element name="ip_routing_type" type="xs:string" minOccurs="0" maxOccurs="1"/>
      <xs:element name="Domain" type="domain_type" minOccurs="0" maxOccurs="1"/>
    </xs:sequence>
  </xs:complexType>
  
  <!-- domain type -->
  <xs:complexType name="domain_type">
    <xs:sequence>
      <xs:element name="tld" type="xs:string" minOccurs="0" maxOccurs="1"/>
      <xs:element name="sld" type="xs:string" minOccurs="0" maxOccurs="1"/>      
    </xs:sequence>
  </xs:complexType>
  
  <!-- location type -->
  <xs:complexType name="location_type">
    <xs:sequence>
      <xs:element name="continent" type="xs:string" minOccurs="0" maxOccurs="1"/>
      <xs:element name="latitude" type="xs:decimal" minOccurs="0" maxOccurs="1"/>
      <xs:element name="longitude" type="xs:decimal" minOccurs="0" maxOccurs="1"/>
      <xs:element name="CountryData" type="country_data_type" minOccurs="0" maxOccurs="1"/>
      <xs:element name="region" type="xs:string" minOccurs="0" maxOccurs="1"/>
      <xs:element name="StateData" type="state_data_type" minOccurs="0" maxOccurs="1"/>
      <xs:element name="dma" type="xs:int" minOccurs="0" maxOccurs="1"/>
      <xs:element name="msa" type="xs:int" minOccurs="0" maxOccurs="1"/>
      <xs:element name="CityData" type="city_data_type" minOccurs="0" maxOccurs="1"/>
    </xs:sequence>
  </xs:complexType>
  
  <!-- country data type -->
  <xs:complexType name="country_data_type">
    <xs:sequence>
      <xs:element name="country" type="xs:string" minOccurs="0" maxOccurs="1"/>
      <xs:element name="country_code" type="xs:string" minOccurs="0" maxOccurs="1"/>
      <xs:element name="country_cf" type="xs:int" minOccurs="0" maxOccurs="1"/>
    </xs:sequence>
  </xs:complexType> 
<!-- state data type -->
  <xs:complexType name="state_data_type">
    <xs:sequence>
      <xs:element name="state" type="xs:string" minOccurs="0" maxOccurs="1"/>
      <xs:element name="state_code" type="xs:string" minOccurs="0" maxOccurs="1"/>
      <xs:element name="state_cf" type="xs:int" minOccurs="0" maxOccurs="1"/>
    </xs:sequence>
  </xs:complexType>

  <!-- city data type -->
  <xs:complexType name="city_data_type">
    <xs:sequence>
      <xs:element name="city" type="xs:string" minOccurs="0" maxOccurs="1"/>
      <xs:element name="postal_code" type="xs:string" minOccurs="0" maxOccurs="1"/>
      <xs:element name="time_zone" type="xs:int" minOccurs="0" maxOccurs="1"/>
      <xs:element name="area_code" type="xs:string" minOccurs="0" maxOccurs="1"/>
      <xs:element name="city_cf" type="xs:int" minOccurs="0" maxOccurs="1"/>
      <xs:element name="postal_code_cf" type="xs:int" minOccurs="0" maxOccurs="1"/>
    </xs:sequence>
  </xs:complexType>

</xs:schema> 

NOTE: Requests for the schema document are only supported in XML and not in JSON.

NOTE: postal_code_cf will be available in the future. To learn more, contact Neustar at support-ipintel@neustar.biz.

Response Codes

If a request to the IP Intelligence service is successful, GeoPoint returns the requested IP data in structured XML or JSON (see above). Such a response indicates success.

If a request fails, no IP data is returned, and the service returns an HTTP status code. If the failure occurred in the GeoDirectory Server, the http_status code is returned in the in the <gds_error> XML element, often with a diagnostic message:

<?xml version="1.0" encoding="UTF-8"?>
<gds_error>
	<http_status>code</http_status>
	<message>message</message>
</gds_error>  

If the ipinfo call specified a response in JSON and the failure occurred in the GeoDirectory Server, the http_status code is returned in the in the "gds_error" JSON element, often with a diagnostic "message":

{ "gds_error" : {
   "http_status" : "<code>",
   "message" : "<message>"}
}

Where code and message are:

CodeMessageMeaningNotes & Examples
200 Success!

The request for IP data or an XML schema succeeded and the service is sending the requested data.

NOTE: This code is not returned, as success is represented by the delivery of the requested IP data.

400 Bad Request

There is an error in the URI.

The referenced IP might be malformed or out of range, or the API call might contain a string for a parameter that expects an integer.

403 Forbidden

You do not have a license for the information you requested.

The API key or digital signature might be incorrect, or your IP Intelligence license has expired.

404 Not Found

The requested resource could not be located.

The URI doesn’t correspond to any known resource, or the referenced IP address is not mapped in GeoPoint's current data set.

408 Request Timeout

The client did not produce a request within the allotted time.

The client may repeat the request without modification at a later time.

500 Internal Server Error

An internal error occurred in the IP Intelligence  service. Try the request again.

If the problem persists, contact support-ipintel@neustar.biz.

503 Service Unavailable

The IP Intelligence service is down for scheduled maintenance. The server might be restarting or initializing. Try the request again later.

Rarely occurs.

If the problem persists, contact support-ipintel@neustar.biz.

API Authentication Errors

In addition to the codes above, the IP Intelligence API (api.quova.com) includes some additional 403 codes to communicate issues with permission, capacity, or authentication :

CodeMessageDescription
403 Forbidden You have not been granted permission to access the requested method or object.
403 Not Authorized The API key associated with your request was not recognized, or the digital signature was incorrect.
403 Account Inactive The API key you are using to access the IP Intelligence API has not been approved or has been disabled.
403 Account Over Queries Per Second Limit The API key you are using has attempted to access the API too many times in one second.
403 Account Over Rate Limit The API key you are using has attempted to access the API too many times in the rate limiting period.
403 Rate Limit Exceeded The service you have requested is over capacity.

NOTE: These codes do not apply to requests sent to a locally installed GeoDirectory Server.