The Eric Wroolie Blog

Overpass Experiences

  • Blog
  • Videos
  • Overpass Apps

Powered by Overpass Apps

Connecting to the Nike+ API with C#

May 5, 2008 by wroolie 14 Comments

A few months ago, I started writing some small personal apps which take information from the Nike+ service. Nike+ is the gadget I attach to my IPod and my running shoes which tracks details about my runs. It tracks things like distance, time, what I’m listening to, etc. When I sync the ipod, this information gets uploaded to the Nike+ website where I can see a couple of flash-heavy graphs of my running progress. Ideally, I would like to use this data myself–so I looked for an API.

I only found one example of an API referrence. This is a WordPress plugin written in PHP (http://www.ear-fung.us/apps/nikeplus/). There is very little documentation on the API out there. What I’ve been able to do involved a lot of trial and error to figure out how to get it working.

API Overview

Basically, the API (like most web-based APIs) includes a list of URLs which return an XML string. The first url will return an authentication cookie which all of the other urls use.

Here are the URLs:

URL Description
https://secure-nikeplus.nike.com/nikeplus/v1/services/widget/generate_pin.jhtml?
login=<Username>&password=<Password>
Authenticates the user. Once this information is passed in, a cookie is put on the client and used for the other calls. I’ll outline how to get around this later.
http://secure-nikeplus.nike.com/nikeplus/v1/services/app/get_user_data.jhtml Gets all of the data about the user (Name, Gender, Country, etc)
https://secure-nikeplus.nike.com/nikeplus/v1/services/app/goal_list.jhtml List of goals for the user.
https://secure-nikeplus.nike.com/nikeplus/v1/services/app/run_list.jhtml A list of all runs with basic summary information. This can get pretty long.
https://secure-nikeplus.nike.com/nikeplus/v1/services/app/get_run.jhtml?id=<RunNumber> A more detailed view of a specific run using the run number from the run list.
https://secure-nikeplus.nike.com/nikeplus/v1/services/widget/get_challenges_for_user.jhtml List of the Challenges the user has.
https://secure-nikeplus.nike.com/nikeplus/v1/services/app/personal_records.jhtml Lists all personal records for the user.

Authenticating

The biggest problem I had when using these urls was how to deal with the cookie information. Since I wanted something that would sit outside the browser (like a sidebar gadget or a web component), I didn’t want to worry about only hosting one session at a time. So I captured the cookie information and fed it back to the server for each additional call.

        public  bool Authenticate()
        {

            //get the login URL (which I include app.config)
            string authURI = String.Format(ConfigurationSettings.AppSettings["CreateSession"].ToString()+"?login={0}&password={1}",
                    _userName, _passWord);

            //Make the call to initiate the connection
            WebRequest objRequest = System.Net.HttpWebRequest.Create(authURI);

            //Read the response
            WebResponse objResponse = objRequest.GetResponse();

            //a cookie will be returned for authentication-- catch it here
            _authenticationCookie = objResponse.Headers["SET-COOKIE"].ToString();

            StreamReader webResponse = new StreamReader(objResponse.GetResponseStream());

            XmlDocument dataDoc = new XmlDocument();
            dataDoc.LoadXml(webResponse.ReadToEnd());

            if (dataDoc.SelectSingleNode("//status").InnerText == "success")
            {
                return true;
            }
            else
            {
                return false;
            }

        }


 

The xml that’s returned is pretty simple, it returns a status node. The important thing it returns is the cookie.

I basically capture the cookie information in the “SET-COOKIE” information which gets passed in with the http header. I store this in a class variable so I can send it in with later calls.

Retrieving Data

Now that I’ve authenticated, all I need to do is pass the cookie details back to the api with each subsequent request.

        private XmlDocument getAdditionalDetails(string uri)
        {
            WebRequest objRequest = System.Net.HttpWebRequest.Create(uri);

            //return the authorization cookie
            objRequest.Headers.Add("Cookie", _authenticationCookie);

            WebResponse objResponse = objRequest.GetResponse();

            StreamReader webResponse = new StreamReader(objResponse.GetResponseStream());

            XmlDocument dataDoc = new XmlDocument();
            dataDoc.LoadXml(webResponse.ReadToEnd());

            return dataDoc;
        }

 

I do this by using the Headers.Add() function. I pass back the same information I retrieved on the initial request. I am no longer dependent on cookies at all. Now, I can read the xml in the application.

Reading the Data

The API does not have any published schemas. However, these are very easy to decipher once you read them. I’ve actually written an entire API wrapper which assigns these xml values to an object model. This is probably overkill, however. An example of the run list xml is below:

<?xml version="1.0" encoding="UTF-8"?>
<plusService>
  <status>success</status>
  <runList>
    <run id="888888">
      <startTime>2006-10-07T10:03:31+01:00</startTime>
      <distance>6.8276</distance>
      <duration>2035266</duration>
      <syncTime>2006-10-07T09:51:46+00:00</syncTime>
      <calories>631</calories>
      <name><![CDATA[]]></name>
      <description><![CDATA[]]></description>
    </run>
    <run id="99999999">
      <startTime>2006-10-10T08:26:10+01:00</startTime>
      <distance>4.51</distance>
      <duration>1331531</duration>
      <syncTime>2006-10-10T07:54:38+00:00</syncTime>
      <calories>417</calories>
      <name><![CDATA[]]></name>
      <description><![CDATA[]]></description>
    </run>
. . .

Summary

I will admit that I should have used all of the time I spent playing with this api to actually be out running. Still it was fun to get it working. I only used the data for small projects. I hope that someone creates some decent gadgets for the Vista or Google Desktop sidebars from this.

If you would like my actual API wrapper code, drop me an email and I can send you what I’ve done. I’ve written the proper object oriented classes along with unit tests, etc. However, once you can get the xml data, you have all you need.

I hope this helps someone out there. Like I said, this is not documented anywhere else, so it could possibly change in the future (so keep your apps flexible).

Filed Under: C# Coding, Software Dev & Productivity

Loading Facebook Comments ...

Comments

  1. Mark says

    May 5, 2008 at 11:14 am

    Wow! Great! Thanks for putting this out there.

    It took me quite a while to figure out how the Nike+ api worked to make my wordpress plugin. It was basically hit-or-miss since Nike doesn’t provide any documentation and have not explicitly approved non-nike applications.

    Great job explaining it here.

    Reply
  2. Eric says

    May 13, 2008 at 4:25 am

    Thanks Mark. None of this would have been possible if you hadn’t created the wordpress plugin first.

    Reply
  3. pbarthelemy says

    June 17, 2008 at 9:49 pm

    hello,

    do you have any information on how to submit the XML files stored in an iPod to nikeplus.com ?
    the point is to bypass iTunes…

    TIA

    Reply
  4. Eric says

    June 21, 2008 at 2:13 pm

    TIA,

    I know that the workout information is stored on the ipod under the Ipod_Control/Device/Trainer/Workouts/Empeds// folder. There are two files–synced and latest. Latests haven’t been synced yet and synced have.

    However, I haven’t investigated how it gets uploaded to Nike+. If you’re lucky, you can use a tool like fiddler to sniff this out. Otherwise, if it is uploaded to iTunes and then synced from there, this would be difficult to find out.

    Eric

    Reply
  5. Paul Dowman says

    August 22, 2008 at 4:08 pm

    Hi Eric,
    I decided a week or two ago that I’d prefer my own implementation of the run data to that on the Nike+ website. I’m looking to code it in c# and came across this blog. Great stuff – can I take you up on your offer of the code you’ve created so far?

    Reply
  6. Erick Rivas says

    January 8, 2009 at 12:32 am

    Good stuff. Is the C# API wrapper you’ve written available, open source?

    Reply
  7. Eric Wroolie says

    January 8, 2009 at 7:15 am

    I’ve put the code at https://nikepluscsharp.googlecode.com/svn/trunk

    The unit tests are working quite the way I would like them to, but there is a client app you can use.

    Reply
  8. Richard Back says

    January 27, 2009 at 8:41 pm

    @Eric Wroolie
    Hi there, How can I get hold of this? It is asking me for a username and password. It looks really interesting!

    Reply
  9. Eric Wroolie says

    January 28, 2009 at 7:22 am

    Okay, I get it. Google Code sucks.

    I’ve put a link to the code on a more recent post:
    http://wroolie.co.uk/?p=296

    Take it as is. It could still use some work.

    Reply
  10. Eric says

    February 9, 2009 at 6:05 am

    One more change. I’ve added it to an anonymous repository:
    http://wroolie.co.uk/?p=314

    Reply
  11. Jeff says

    April 10, 2009 at 8:52 pm

    I just jail-broke my iPod Touch 2g. I’m trying to find a way to pull the data off of iPod as some of nmy older runs won’t sync with Nike+. Does anyone know where the runs are stored on this device? Thanks!

    Reply
  12. Jeff says

    April 10, 2009 at 8:59 pm

    @Jeff
    /private/var/mobile/Media/iTunes_Control/Device/Trainer/Workouts/Empeds

    My linux-searching-foo was pretty weak. Booya.

    Reply

Leave a Reply to Mark Cancel reply

Your email address will not be published. Required fields are marked *

Recent Posts

  • My Gig and the Imposter Syndrome
  • Getting Picked Last for Teams in PE
  • One Little Growth Opportunity at a Time
  • I’m sorry if I look like I know what I’m doing
  • New Years Reclamations