Summary: Microsoft PFE, Chris Wu talks about using the Live REST API with Windows PowerShell.

Microsoft Scripting Guy, Ed Wilson, is here. Once again we have Chris Wu with us. For previous posts from Chris, see the Hey, Scripting Guy! Blog. Take it away Chris…

In this post, we will show off some miscellaneous tasks that are enabled by the Live REST API. Again, the following code snippets assume that a valid $AccessToken with appropriate scope has been returned. For information about how to create a valid access token, read my post, Use PowerShell 3.0 to Get More Out of Windows Live.

In this post, I’ll discuss how to:

  • Enumerate and search for contacts
  • Interact with calendars and calendar events
  • Create a new contact

Enumerate and search for contacts

Note   This task requires the wl.basic scope.

To enumerate contacts of currently signed-in user, send a request to me/contacts:

$ApiUri = "https://apis.live.net/v5.0"

Invoke-RestMethod -Uri "$ApiUri/me/contacts?access_token=$AccessToken"

Image of command output

Note that the listed contact objects have a property called email_hashes, which is an array that contains a hash for each email address that user possesses. The purpose of using this hash is apparently to protect confidential information from being transmitted in clear text.

Searching for a contact by first and last name can be easily done with our old friend Where-Object:

(Invoke-RestMethod -Uri "$ApiUri/me/contacts?access_token=$AccessToken").data | Where-Object { $_.first_name -eq 'Chris' -and $_.last_name -eq 'Wu' }

If you are running Windows PowerShell 3.0, the following new syntax will come in handy:

(Invoke-RestMethod -Uri "$ApiUri/me/contacts?access_token=$AccessToken").data | ? name -like 'Chris Wu'

To search for a contact by email address, however, involves a little more work. We need the hash, which technically is a SHA256 hash of UTF8 encoding of the email address concatenated with the script’s client ID. So here is the script:

$Email = "chris@contoso.com".Trim()

$hash = -join ((new-object System.Security.Cryptography.SHA256CryptoServiceProvider).ComputeHash( `

  (new-object System.Text.UTF8Encoding).GetBytes("$Email$ClientID".ToLower())) | `

    %{ $_.ToString("x2") })

(Invoke-RestMethod -Uri "$ApiUri/me/contacts?access_token=$AccessToken").data | ? email_hashes -Contains $hash

The user_id property of the object (if present) in the previous examples identifies the Microsoft account for that contact. An application can request the corresponding user object to retrieve more details. However, sensitive information such as birthday, work profile, email addresses, postal address, and phone numbers are granularly controlled through additional scopes: wl.birthday, wl.work_profile, wl.emails, wl.postal_addresses, wl.phone_numbers.

This model works great for commercial applications to gather user information per a user’s consent. But for a Windows PowerShell script that’s not used by a large user base (usually run by a single user like me), this means difficulty in getting those additional fields.

Anyway, the following snippet returns the user object of a contact with a valid user ID:

$UserID = ((Invoke-RestMethod -Uri "$ApiUri/me/contacts?access_token=$AccessToken").data | ? name -like 'Chris Wu').user_id

Invoke-RestMethod -Uri "$ApiUri/$UserID`?access_token=$AccessToken"

Create a new contact

Note   This task requires the wl.calendars scope.

A Post request like this will create a new contact:

$contact = @{

  first_name="Jack";

  last_name="Smith";

  emails=@{preferred="jsmith@contoso.com";business="Jack.Smith@contoso.com"}

} | ConvertTo-Json

Invoke-RestMethod -Uri "$ApiUri/me/contacts?access_token=$AccessToken" -Method Post -ContentType "application/json" -Body $contact

Image of command output

In this example, we piped a hash table to the ConvertTo-Json cmdlet to get the JSON representation, which can be passed as the body of the Post request.

Interact with calendars and calendar events

Note  This task requires the wl.contacts_create scope.

Interacting with calendars by using the Rest method is pretty straightforward. Most tasks can easily be accomplished through the Windows PowerShell Invoke-RestMethod cmdlet. The tasks are also well documented at Interacting with calendars (Live Connect API).

Let’s say that I have added Canadian public holidays to my calendar by following these instructions: Add holiday or lunar calendars to Outlook.com. The following snippet will enumerate all the calendars I have in my account:

(Invoke-RestMethod -Uri "$ApiUri/me/calendars?access_token=$AccessToken").data

Image of command output

To unsubscribe to the Canadian holiday calendar, I simply send a Delete request:

$CalendarID = ((Invoke-RestMethod -Uri "$ApiUri/me/calendars?access_token=$AccessToken").data | ? {$_.name -eq "Canada Holidays"}).id

Invoke-RestMethod -Uri "$ApiUri/$CalendarID`?access_token=$AccessToken" -Method Delete

Similarly, sending a request to me/events will return a list of calendar events (seemingly for the next 30 days):

Invoke-RestMethod -Uri "$ApiUri/me/events?access_token=$AccessToken"

Unfortunately, even though the documentation states that the REST API supports subscribing to and creating calendars, I can’t seem to make it work. (Yes, I double checked that the required scopes are enabled.) If any reader finds a solution and comments to this post, it will be very much appreciated.

After playing with the Live SDK, I personally find the Live REST API strong in supporting SkyDrive, but lacking in other areas. Understandably, this is probably due to the transition from Hotmail to Outlook.com, and Live Messenger to Skype. Hopefully after all the transitions are complete, Microsoft will release a new version of Live SDK to fill the gaps.

One last piece of information before I conclude this series of blog posts: All applications that use Windows Live services and have requested user permissions are listed on the User’s Apps and Services setting page. As a user, it may be a good idea to regularly visit this page to revoke access or remove obsolete applications.

~Chris

That’s it this week for Chris Wu. Thanks again, Chris, for sharing your time and knowledge.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy