Fitness API support for Runkeeper, Strava, MapMyFitness, UnderArmour, Fitbit.
Fitness API is currently compatible with Meteor 1.2.0.1 and above.
meteor add selaias:fit-api
Optional packages to use for authentication:
meteor add selaias:accounts-runkeeper
meteor add selaias:accounts-fitbit
meteor add selaias:accounts-strava
meteor add selaias:accounts-mapmyfitness
meteor add selaias:accounts-underarmour
In order to be able to use the API, you should initialize a fitness service by passing (at least)
the access_token
of an authenticated user (You can use the Authentication APIs to connect a user
and then read the access_token
stored in Meteor.users collection)
var token = Meteor.users.findOne({_id: userId}).services.runkeeper.access_token;
Now you are ready to initialize the Runkeeper API.
server/main.js
const Runkeeper = FitAPI.runkeeper;
var options = {
config: {
access_token: "XXXXXXXXXXX"
}
};
Runkeeper.init(options);
Currenty the FitAPI is provided with a few basic endpoints for Runkeeper with their editable fields.
var endPoints = {
"user": {
"content_type": "application/vnd.com.runkeeper.User+json",
"uri": "/user"
},
"profile": {
"content_type": "application/vnd.com.runkeeper.Profile+json",
"uri": "/profile",
"pat": {
"athlete_type": Match.OneOf(
'Athlete', 'Runner',
'Marathoner', 'Ultra Marathoner',
'Cyclist', 'Tri-Athlete', 'Walker',
'Hiker', 'Skier', 'Snowboarder',
'Skater', 'Swimmer', 'Rower'
)
}
},
"settings": {
"content_type": "application/vnd.com.runkeeper.Settings+json",
"uri": "/settings",
"pat": {
"share_fitness_activities": Match.OneOf("Just Me", "Street Team", "Everyone"),
"share_map": Match.OneOf("Just Me", "Street Team", "Everyone"),
"post_fitness_activity_facebook": Match.Optional(Boolean),
"post_fitness_activity_twitter": Match.Optional(Boolean),
"post_live_fitness_activity_facebook": Match.Optional(Boolean),
"post_live_fitness_activity_twitter": Match.Optional(Boolean),
"share_background_activities": Match.Optional(Boolean),
"post_background_activity_facebook": Match.Optional(Boolean),
"post_background_activity_twitter": Match.Optional(Boolean),
"share_sleep": Match.OneOf("Just Me", "Street Team", "Everyone"),
"post_sleep_facebook": Match.Optional(Boolean),
"post_sleep_twitter": Match.Optional(Boolean),
"share_nutrition": Match.OneOf("Just Me", "Street Team", "Everyone"),
"post_nutrition_facebook": Match.Optional(Boolean),
"post_nutrition_twitter": Match.Optional(Boolean),
"share_weight": Match.OneOf("Just Me", "Street Team", "Everyone"),
"post_weight_facebook": Match.Optional(Boolean),
"post_weight_twitter": Match.Optional(Boolean),
"share_general_measurements":Match.OneOf("Just Me", "Street Team", "Everyone"),
"post_general_measurements_facebook": Match.Optional(Boolean),
"post_general_measurements_twitter": Match.Optional(Boolean),
"share_diabetes": Match.OneOf("Just Me", "Street Team", "Everyone"),
"post_diabetes_facebook": Match.Optional(Boolean),
"post_diabetes_twitter": Match.Optional(Boolean),
"distance_units": Match.OneOf("mi", "km"),
"weight_units": Match.OneOf("lbs", "kg"),
"first_day_of_week": Match.OneOf("Sunday", "Monday")
}
},
"fitnessActivityFeed": {
"content_type": "application/vnd.com.runkeeper.FitnessActivityFeed+json",
"uri": "/fitnessActivities"
},
"fitnessActivities": {
"content_type": "application/vnd.com.runkeeper.FitnessActivity+json",
"uri": "/fitnessActivities",
"pat": {
"type": Match.Optional(
Match.OneOf(
'Running', 'Cycling', 'Mountain Biking',
'Walking', 'Hiking', 'Downhill Skiing ',
'Cross-Country Skiing', 'Snowboarding',
'Skating', 'Swimming', 'Wheelchair',
'Rowing', 'Elliptical', 'Other', 'Yoga',
'Pilates', 'CrossFit', 'Spinning', 'Zumba',
'Barre', 'Group Workout', 'Dance', 'Bootcamp',
'Boxing / MMA', 'Meditation', 'Strength Training',
'Circuit Training', 'Core Strengthening',
'Arc Trainer', 'Stairmaster / Stepwell',
'Sports', 'Nordic Walking'
)
),
"secondary_type": Match.Optional(String),
"equipment": Match.Optional(
Match.OneOf(
'None', 'Treadmill', 'Stationary Bike',
'Elliptical', 'Row Machine')
),
"start_time": Match.Optional(String), //Sat, 1 Jan 2011 00:00:00
"total_distance": Match.Optional(Number),
"distance": Match.Optional(Object), // {timestamp: Number, distance: Number}
"duration": Match.Optional(Number),
"average_heart_rate": Match.Optional(Number),
"heart_rate": Match.Optional(Object), // {timestamp: Number, heart_rate: Number}
"notes": Match.Optional(String),
"path": Match.Optional(Object),
// {timestamp: Number, latitude: Number, longitude: Number,
// altitude: Number, type: Match.OneOf('start', 'end', 'gps', 'pause', 'resume', 'manual')}
}
}
};
but you can extend those endpoints and pass it as options in the init function.
server/main.js
const Runkeeper = FitAPI.runkeeper;
var options = {
config: {
access_token: "XXXXXXXXXXX"
},
endPoints: {
// ..... //
}
};
Runkeeper.init(options);
Currently on the client only one agnostic method is provided FitAPIRequest
and you can use it
for all API methods and extra endPoints you have set.
client/runkeeper_user.js
Simple user request [https://runkeeper.com/developer/healthgraph/example-api-calls#example-get-retrieving-user-info]
var options = {
service: "runkeeper", // currently One Of ('runkeeper', 'strava') more to follow
method: "GET", // One Of ('GET', 'POST', 'PUT', 'DELETE')
endPoint: "user" // One of endpoints set on init
}
Meteor.call('FitAPIRequest', options, function(err, result){
if(err) {
console.log(err)
} else {
console.log(result)
}
});
or a request to update an Activity type
var options = {
service: "runkeeper", // currently One Of ('runkeeper', 'strava') more to follow
method: "PUT", // One Of ('GET', 'POST', 'PUT', 'DELETE')
endPoint: "fitnessActivities", // One of endpoints set on init
params: {
id: 'yourActivityId', // Optional for GET / POST, required for PUT / DELETE
data: {
type: 'Running' // request_body data based on endpoint editable fields.
}
}
}
Meteor.call('FitAPIRequest', options, function(err, result){
if(err) {
console.log(err)
} else {
console.log(result)
}
});
Include more APIs, like Nike+, Polar etc, complete all endpoints for each service and more...
Ideas, Issues, PRs are more than welcome.
MIT