Page 1

Microsoft Pinpoint Syndication API Draft End User Guide

EDIT HISTORY DATE

WHO

EDIT

11/24/2010

sudeepku

First Draft Created -based on the Pinpoint Syndication Wiki Page


1. An introduction of the Pinpoint Read API This document is intended for developers who would like to integrate Pinpoint's catalog into their applications, on the assumption that the use does not require mass consumption of all or a large subset of Pinpoint's catalog. The documentation here includes the following topics which are covered in the subsequent sections of this document. 1. 2. 3. 4. 5.

An introduction of the Read API (this section). Authentication needed to use the API. Description of the requests for the API. Description of the results from the API. Samples and examples on the API use.

Overview The Read API is designed on top of OData. Specifically, Item

Description

REST based

The request to Pinpoint is a set of REST (REpresentational State Transfer) requests that gives you access to Pinpoint's key resources, whether as a query or as a specific request for details on a particular resource.

2 types of Results The results can be returned with the appropriate MIME type -- currently either XML-atom or JSON, both of which conforms to OData specification. Atom The XML based result set returned by Pinpoint conforms to the Atom feed Syndication Format $format=xml accept: application/atom+xml,application/atomsvc+xml,application/xml JSON data

The JSON (JavaScript Object Notation) results returned by Pinpoint echoes the data from the XML. $format=json [with support for callback as per jsonp] accept: application/json


To use the API, you need to be a registered consumer of the API. When you register, you will be given a specific key that can be used in one of several ways to connect to the API and make your request. The Pinpoint Read API operates on the following resources / entities primarily: 1. Taxonomy Data 2. Partner Data 3. Product Data Requests may have results returned as: 1. Collection / List: a list of members of these resources satisfying the request, including URIs for further navigation and attributes / properties describing these members. 2. Element: as just one of these resource member, including URIs for further navigation and attributes / properties describing this member. 3. Nested Elements: The use of "$expand" would allow nested results to be returned.

More Details and Typical Use The URL for the Read API Query for Pinpoint is: http://pinpoint.microsoft.com/<locale>/syndicate/<Resource Request> Where "locale" is one of Pinpoint's supported locales (such as "en-US", "en-GB") and the "Resource Request" is the OData conforming request for a Pinpoint collection / element. Thus, applied simply to getting the list of resources, examples are: 1. http://pinpoint.microsoft.com/en-US/syndicate/Partners 2. http://pinpoint.microsoft.com/en-GB/syndicate/Products 3. http://pinpoint.microsoft.com/de-DE/syndicate/Taxonomy Note: you will need to have a signed request for the requests above to work. A typical response would look like:


Versioning The API is versioned. This allows Pinpoint to grow / make changes to the API, both in the entities and details of the queries and results returned but allow existing developers to continue to use the API without being lock-stepped with us. However, we will remove older versions of the API with time. There may also be several versions in a single release. Pinpoint will name these versions and make that information available. In order to support versioning, versions can be included in the request, either

HTTP Header Embedded in Request

Syndication-View: v2010.05 view=v2010.05

The current version in Pinpoint's Spring release is labelled "v2010.05". Given that versions may have different constructs and data, it is important that the "view=" parameter is included in one of the 2 forms above when making a request to the API. This prevents future issues when Pinpoint updates.


Tracking of Activities The API supports tracking of activities. This includes both the requests into the API and the links provided by the API that is redirected through Pinpoint, or to Pinpoint. To enable this tracking, a specific Tracking ID needs to be used. The tracking ID is included as part of the request (as TrackID="<trackingID>"). If tracking the usage through the use of the API is relevant. Please follow this link (TBD).

2. Authentication In order to use Pinpoint, you need to be a registered consumer. This basic authentication is, at this point, 1. 2. 3.

To identify the group of applications that may connect through the API. To allow Pinpoint to revoke a group of applications from having that access in case of issues, abuse etc at Pinpoint's discretion. To provide support for the authenticity of the application making the request to Pinpoint and the integrity of the request through the use of signatures.

Becoming a Registered Consumer Note: use of the term "Registered Consumer" does not imply a "consumer" of the general public goods and services user, but in terms of some entity / applications that "consumers" the API.

To become a registered consumer, you need to provide some basic information as a request to pinpoint. [Need a form to support this here -- sending email to an alias] When you become a registered consumer, you will be given both one or more unique ID(s) and the associated unique key(s) (they will come in pairs of unique <ID, Key>).

Identification and Key Details Some basic terminology: URI / URL Query

Each request to the API is done through a HTTP URI Query structured as: http://pinpoint.microsoft.com/<locale>/syndicate/<Resource Request>

API Request

This is a convenience phrase that refers to the non-protocol / hostname portion of the API request: /<locale>/syndicate/<Resource Request>

Essentially, it includes the key elements that determines which collection / element is returned, and is the portion used in the signature. It excludes the HTTP-header portions that may contribute to the identification, version and the MIME-type that would be returned -- these do not determine which element(s) are returned as much as whether / how they are returned. ID

Often referred to as an "application ID" but may be used across multiple (instances of) applications. It is essentially the unique identifier given to you to identify that this set of applications are from you. You may have 1-n IDs as required. This ID will be either included in the API Request or as part of the HTTP-header.

Key

Often referred to as an "application key" but may be used across multiple (instances of) applications. This key is paired with an ID and may or may not be included in the API Request or


part of the HTTP-header, but is requred for creation of the signature (along with the ID). It is your responsibility in determining if including the key in plaintext is an acceptable exposure. Protection of this key is important to ensure authenticity and integrity of your request. Signature

This is the required string that signfies the authentication being used, identifies the application to Pinpoint. The specific signature components is determined by the authentication model used. The signature must be supplied in all queries to the API either as:

HTTP-Header Embedded in Request

Syndication-Sig:

S-4kwm-LNFFX5f5q/8aP2xsfFnugTgLL5g

sig=S-4kwm-LNFFX5f5q/8aP2xsfFnugTgLL5g

Every API request to the Pinpoint API needs to involve a <ID, Key> pair, and you can use the same <ID, Key> for different applications. You can therefore have 1-n <ID, Key> pairs for n applications. It affects only what happens when revocation needs to be done -- as revocation is done on an <ID, Key> pair. Pinpoint, at its discretion, will grant 1-n <ID, Key> pairs as appropriate, and also revoke the use of these pairs.

Authentication Models The format below is the currently supported format. Model

S-Format Model

Summary

Signature incorporates SHA-256/Modified Base64 hash implementation. Can be used to provide protection against replays, and an integrity check on the request.

Sig Format S-<ID>-<MB64-Hash>

S

The authentication model associated with the signature ("S"-Format)

ID

The application ID associated with this request

MB64-Hash The modifed base 64 hash of "<SHA256-Hash>"


SHA1-Hash

The SHA256 hash of "<Key>-<API Requset>"

Key

The application Key associated with the ID.

API-Request The API-request (sans signature) portion of the query (as defined above).

Note: there is a "-" between the "<Key>" and the "<API Request>". Sig Example

S-4kwm-LNFFX5f5q/8aP2xsfFnugTgLL5g

S

The model of the signature (S-Format)

4kwm

The application ID associated with this query

LNFFX5f5q/8aP2xsfFnugTgLL5g

This is the modified base 64 hash of 2cd1455f97f9abff1a3f6c6c7c59ee81380b2f 98

This is the SHA256 hash of 2cd1455f97f9abff1a3f6c6c7c59ee81380b2f 6f98d0ed-841b-48bf-9735-9b2c2b0e0a1e98 /en-US/syndicate/Partners?view=v1 6f98d0ed-841b-48bf-9735-9b2c2b0e0a1e

This is the Key associated with this ID -- the "secret".

/en-US/syndicate/Partners?view=v1

This is the API request portion of the request.

Note the "-" between the Key and the API Request. Note that the key is not shared in the clear but as part of the hash. Descriptio The "S"-format model allows the application to make the request without disclosing the key associated with the ID, thus enabling a "secret" to be shared between the application n and Pinpoint. This supports the enabling of integrity checks (query is part of hash), authentication of the application and, with the addition of a time-stamp (see below), prevention of replay. The "S" format relies on a SHA256 implementation and a Base64 implementation which


can omit trailing padding characters. Base64 trailing padding characters (‘=’) are specifically omitted because they can confuse URL parsers. The API request is subject to the URI Normalization rules (ref: http://rfc-ref.org/RFCTEXTS/3986/chapter6.html). Use Cases

1. Server side calls to Pinpoint through unprotected channels. 2. Client side applications that has the ability to encrypt (using server) the request before sending to Pinpoint. 3. Pure client side applications that can obfuscate sufficiently to protect the key from exposure to enable some amount of protection. (Remember that obfuscation does not prevent the ability to determine what the key is).

Query Expiration (Optional) The API provides for the ability to include a form of time-stamping by including in the request an "expires=datetime'<datetime>'" paramter that determines when the request is considered no longer valid. This can be used together with the hash to prevent, to a certain extent, replay. "<datetime>" is formatted as OData's dateTimeUrlLiteralOffset format, and is treated as UTC time. The application is free to select the value of the expiration, and the syndication service will simply reject any requests that has an expired "expire" <datetime> value or a <datetime> value that is invalid or empty. Pinpoint also reserves the ability / choice to reject requests with an unreasonable expiration datetime (eg >1 day). The "expire" parameter can be used and is honored regardless of the authentication model (or signature used). Example: http://pinpoint.../en-US/syndicate/Partners?view=v1&expires=datetime’2010-0403T13%3A00%3A00Z’ There is no attempt, today, for Pinpoint to provide time-synchronization between systems.

3. Request Model Pinpoint's basic requests are model as per OData's protocol. Below we describe Pinpoint specific application and use case. Note: For protection of the ID and key, the requests below do not work because the signature is fabricated. You will need to construct the URL with your given signature for this to work. All requests to Pinpoint's API needs to be signed (see section – Authentication). Therefore, an example of a full request is as below:


http://pinpoint.microsoft.com/en-US/syndicate/Partners?sig=S-1dtjCxO%2fymzVp64%2bBzSi97rf1kmqsR3Tx7NI9Ra838feda%3d

Getting to the Resources (Collection and Specific Items) In OData, each resource entity can be addressed via the URL -- whether requesting for a collection (list of) or specific entity. Thus, for Pinpoint, the following can be used (ignoring the signature & protocol portion) to access the 3 resources (partners, products and taxonomy): /en-US/syndicate/Partners

Requests the collection of Partners

/en-US/syndicate/Products

Requests the collection of Products

/en-US/syndicate/Taxonomy

Requests the collectino of Taxonomy entries.

/en-US/syndicate/Partners('4297338714') Requests a particular Partner entity -- Pinpoint ID = 4297338714 /enUS/syndicate/Products('4294968047')

Requests a particular Product entity -- Pinpoint ID = 4294968047

/en-US/syndicate/Taxonomy(200004)

Requests a particular Taxonomy entity -- Pinpoint ID = 200004 (INT)

Due to the fact that you can already get to the individual items through $expand, we currently do not support multiple levels access to the resources. To complete the requests above, they should be appended with the version and signature (either as the request header or parameter).

Query Parameters Query (system or Pinpint specific / contextual) parameters can be appended to the requests after a "?" in OData, and are "&" separated. OData's system parameters have the convention of starting with "$". For eg: http://pinpoint.microsoft.com/enUS/syndicate/Partners?$top=5&$skip=5&$expand=Links&TrackID=DemoDescription&sig=S-z2mcReB38OiTKcFHy13xx8BXyei39Fd02E%3d

The following (system) parameters are used in Pinpoint. $orderby

Defines the sort order for entities in the results. See below for the list of items that can be ordered for Partners and Products. eg. /en-US/syndicate/Products?$orderby=Name, Id

$top

Specifies the number of entities in the results. eg. /en-US/syndicate/Partners?$top=5

$skip

Specifies the number of entites to "skip" before returning the entities. eg. /en-US/syndicate/Partners?$top=5&$skip=10 -- skip the 1st 10 and show 5 -ie, entities 11-15.


$format

Specifies the format of the results desired. Currently, the value is either "xml" (implied) or "json". eg. /en-US/syndicate/Products?$format=json For JSON, inclusion of a callback is accepted to invoke a JSONP callback (using "$callback"). eg. /en-US/syndicate/Products?$format=json&$callback=MyJSONCallbackFunction

$expand

Used to "expand" out related entities that are returned embedded into the existing entities, for eg, the categories and links for the partner or product entities, or the product entities. See the "Syndication API -- Results" section for "Expanded" relationships and how they are related. eg. /en-US/syndicate/Partners?$expand=Links,Categories,Products -- returns the Partners with the list of links, categories and products for each partner "expanded". eg. /en-US/syndicate/Partners?$expand=Products,Products/Links -- returns the Partners with the list of Products expanded, but also the Links inside the Products of each partners.

$filter

This allows the construction of logical comparisons for specific "terms" defined for each entity (refer to the results or metadata definition for the set of terms for each entity), and the invocation of the "Search" query for Pinpoint. The expression language is as defined in OData, but Pinpoint only supports a limited set of the operators as of now. You will also need to use "+" to separate terms in order for the proper signature to be applied. Basic Terms eg. /en-US/syndicate/Products?$filter=Id+eq+'4294971060' -- return the list of Products whose ID (Pinpoint) match '4294971060' (similar to Products('4294971060') in this case, but this returns it as if it is a "collection"). eg. /en-US/syndicate/Partners?$filter=Name+eq+'Technology' -- return the list of Partners whose name contains "Technology". eg. /enUS/syndicate/Partners?$filter=RatingAverage+gt+4.0+and+Name+eq+'Software' -return the list of Partners whos ratings are above 4.0 and has "Software" in the name. eg. /en-US/syndicate/Partners?$filter=NativeId+eq+'2371418' -- return the list of Partners whose Native (MSPP in this case) ID matches '2371418'.

Search eg. /en-US/syndicate/Partners?$filter=Search+eq+'Dynamics+CRM' -- searches for Partners with "Dynamics CRM" in their title/descriptions. Categories eg. /enUS/syndicate/Products?$filter=Cat+eq+'Operations+Manager'&$expand=Categories -- gives products which are associated to categories which has the "Operations Manager" term, and expand out the categories for those products. [You could also use Cat+eq+'400158' for any of the taxonomy IDs]. TrackID

Sig view=

Pinpoint specific for creating a tracking ID. Maps to the "wt.MC_id" value when directed to Pinpoint. Pinpoint specific for inclusion of the required signature. Pinpoint specific for the version / view of the data being returned. This is important given that Pinpoint is expected to make adjustments and improvements to the API often. Making sure that you are explicit about which version of the data and query you are sending helps ensure that it does not have the wrong results nor structure (and break). The current version is


v2010.05. marketplace

Pinpoint specific. When specified in the query, scopes the results to a specific marketplace built on the pinpoint platform. E.g marketplace=dynamics

4. Results The following shows the organization of Pinpoint's resources (discoverable via /enUS/syndicate/$metadata).

Partners Partners resources are made up of [0..n] "Partner" with relevant data defined as: <entry>

L0 The "Partner" container (as per Atom)

<id>

L1 The "OData" ID for this partner. This takes the form of a valid OData structure to locate this particular partner. eg. /en-US/syndicate/Partners('4295678162')

<view>

L1 The version of the data returned.

<title>

L1 Partner Name -- as is common practice in Atom Pub.

<summary>

L1 Partner Description -- as is common practice in Atom Pub.

<published>

L1 Last published date of the profile.

<updated>

L1 Last modified date of the profile.

<link title="Partner">

L1 Reference to the "Partner" resource (similar to ID above), without the path. eg. Partners('4295678162')

<link title="Links">

L1 Reference to the expandable list of links relevant to this partner, without the path. eg. Partners('4295678162')/Links

<link title="Locations"> L1 Reference to the expandable list of locations for this partner, without the path. eg. Partners('4295678162')/Locations <link title="Products"> L1 Reference to the expandable list of products for this partner, without the path. eg. Partners('4295678162')/Products <link title="Categories">

L1 Reference to the expandable list of categories for this partner, without the path. eg. Partners('4295678162')/Categories

<content / m:properties>

L1 Container for the set of items particular to a partner. L2

<d:Id>

L3 The Pinpoint ID for this partner.

<d:NativeId>

L3 The MSPP ID for this partner.

<d:Name>

L3 The Partner Name (similar <Title>).

<d:Description>

L3 The Partner Description (similar <Summary>).

<d:RatingAverage>

L3 Average Rating for this partner as a decimal (eg. 4.775).

<d:RatingCount>

L3 Number of ratings / reviews for this partner as an integer (eg. 97).

<d:Certification>

L3 String result of the type of certification for this partner (currently, Gold or


Certified partners). (eg. Gold Certified Partner) [Note: do not use, will be deprecated]

Products Products resources are made up of [0..n] "Product" with relevant data defined as: <entry>

L0 The "Product" container (as per Atom)

<id>

L1 The "OData" ID for this product. This takes the form of a valid OData structure to locate this particular product. eg. /en-US/syndicate/Products('4294972121')

<view>

L1 The version of the data returned.

<title>

L1 Product Name -- as is common practice in Atom Pub.

<summary>

L1 Product Description -- as is common practice in Atom Pub.

<published>

L1 Last published date of the profile.

<updated>

L1 Last modified date of the profile.

<link title="Product">

L1 Reference to the "Product" resource (similar to ID above), without the path. eg. Products('4294972121')

<link title="Partner">

L1 Reference to the expandable "Partner" of this Product, without the path. eg. Products('4294972121')/Partner

<link title="Links">

L1 Reference to the expandable list of links relevant to this product, without the path. eg. Products('4294972121')/Links

<link title="Locations"> L1 Reference to the expandable list of locations for this product, without the path. eg. Products('4294972121')/Locations <link title="Categories">

L1 Reference to the expandable list of categories for this product, without the path. eg. Products('4294972121')/Categories

<content / m:properties>

L1 Container for the set of items particular to a product. L2

<d:Id>

L3 The Pinpoint ID for this product.

<d:NativeId>

L3 The MSPP ID for this product.

<d:Name>

L3 The Product Name (similar <Title>).

<d:Description>

L3 The Product Description (similar <Summary>).

<d:RatingAverage>

L3 Average Rating for this product as a decimal (eg. 4.775).

<d:RatingCount>

L3 Number of ratings / reviews for this product as an integer (eg. 97).

<d:Pricing>

L3 String of the pricing model this product is offered under. ("For Purchase" or "Free").

<d:Version>

L3 The version for this product (no particular format -- as String).

<d:ReleaseDate>

L3 The date that this product is described as being released.

Taxonomy Taxonomy resources are made up of [0..n] "Taxonomy" entry with relevant data defined as: <entry>

L0 The "Taxonomy" container (as per Atom)

<id>

L1 The "OData" ID for this taxonomy entry. This takes the form of a valid OData structure to locate this particular taxonomy entry. eg. /en-US/syndicate/Taxonomy(100001)

<view>

L1 The version of the data returned.


<title>

L1 Taxonomy Entry Name -- as is common practice in Atom Pub.

<updated>

L1 Last modified date of this taxonomy entry.

<link title="Taxonomy" L1 Reference to the "Taxonomy" resource (similar to ID above), without the path. eg. Taxonomy(100001) <link title="Parent"

L1 Refence to the expandable parent of this taxonomy entry, without the path. eg. Taxonomy(100001)/Parent

<link title="Children"

L1 Reference to the expandable list of children of this taxonomy entry, without the path. eg. Taxonomy(100001)/Children

<content / m:properties>

L1 Container for the set of items particular to taxonomy entries L2

<d:Id>

L3 Integer ID value of the taxonomy entry

<d:Name>

L3 The name of this taxonomy entry.

<d:Description>

L3 Description of this taxonomy entry.

"Expandable" Relationships As per OData's structure, each entity may have relationships with other entities (whether 1:1 or 1:n), and these are expressed as "<link>" entities that can be expanded ($expand=). All expanded items start with an "<m:inline>" inside the "<link>" entity. An empty "<m:inline>" could occur indicating no results.

The two 1:1 relationships are Parent under Taxonomy and Partner under Product. Each of these are expanded as "<entry>" inside the "<m:inline>" entity. The entities are similar to the specific definition above (Parent as Taxonomy Entry and Partner as Partner Entry). The other links are all 1:n relationships. These are Children, Products, Links, Locations and Categories (see above for where the links appear). These are expanded as a "<feed>" entity inside the "<m:inline>" entity. This may be an empty entity, or there may be 0 or more "<entry>" of the specific entry types.


Specifically, 1. 2. 3. 4.

Each "child" in Children is a Taxonomy Entry (defined above). Each Product is a Product Entry (defined above). Each Category of Categories is also a Taxonomy Entry (defined above). Each Link Entry for Links is defined, under "<content / m:properties>": 1. Type -- describing the type of the link, 2. Description -- description of the link, 3. URL -- the specific link to use 5. Each Location Entry for Locations is defined, under "<content / m:properties>": 1. The location (address, city, state, country, postal code), 2. The contact (name, phone + extension, fax).

The types of links supported today are, For Partners: pinpointpartnerpage

A link to the Partner's details page on Pinpoint.

pinpointpartnerproductlist

A link to the Partner's list of products page on Pinpoint.

pinpointpartnerreviewpage

A link to the Partner's review page on Pinpoint.

pinpointpartnerlocationpage

A link to the Partner's location page on Pinpoint.

pinpointpartnerrfipage

A link to the Partner's RFI page on Pinpoint.

partnerwebsite

A relay link that redirects to the Partner's website.

partnerlogo

A image reference to the partner's logo graphics.

For Products: pinpointproductpage

A link to the Product's details page on Pinpoint.


pinpointproductreviewpage

A link to the Product's review page on Pinpoint.

pinpointpartnerrfipage

A link to the Partner's RFI page for this Product on Pinpoint.

generalsolution, whitepaper, A relay link that redirects to the various collateral for the Product. supportandtraining, referencematerial, ... solutiondemo, trial, purchase

A relay link that redirects to the try, buy, demo links for the Product.

screenshot

Between 0...3 "screenshots" image references for the Product.

5. Samples and Examples Here are some generic examples to get started: 1. Get different entity definitions and Meta data for each of the entities: http://pinintin01.redmond.corp.microsoft.com:8083/en-US/syndicate/$metadata 2. Get Details of a specific partner: http://pinintin01.redmond.corp.microsoft.com:8083/enUS/syndicate/Partners('4295684099') 3. Get Details of a specific product: http://pinintin01.redmond.corp.microsoft.com:8083/enUS/syndicate/Products('4294967445') 4. Get Partners, where partner name equals software: http://pinintin01.redmond.corp.microsoft.com:8083/enUS/syndicate/Partners/?$filter=Name+eq+'Software

6. Sample Code Generating Signatures The basic C# code fragment for creation of a signature is as follows (thanks to Paris Chavez for providing):

class Hasher { public static string Hash(string app_KEY, string uri, string encodeFunction) { byte[] uri_bytes = Encoding.Unicode.GetBytes(uri); byte[] key_bytes = Encoding.Unicode.GetBytes(app_KEY);


HMACSHA256 hmac = new HMACSHA256(key_bytes); byte[] hash = hmac.ComputeHash(uri_bytes);

string hash_b64 = Convert.ToBase64String(hash); string hash_b64_pe = null; if (encodeFunction.Length == 0 || encodeFunction.Contains('1')) { hash_b64_pe = HttpUtility.UrlEncode(hash_b64); } else if (encodeFunction.Contains('2')) { hash_b64_pe = Uri.EscapeDataString(hash_b64); } else if (encodeFunction.Contains('3')) { hash_b64_pe = Uri.EscapeUriString(hash_b64); }

return hash_b64_pe; } }

Additional sample codes TBA

Microsoft Pinpoin Syndication API  

DATE WHO EDIT EDIT HISTORY Draft End User Guide 11/24/2010 sudeepku First Draft Created -based on the Pinpoint Syndication Wiki Page