NAV
javascript shell

ayvri V2 REST API

The ayvri API let’s you create new ayvri Activities and Scenes to use in your application.
It is a REST based API with predictable, resource-oriented URLs, and uses HTTP response codes to indicate API errors. We use built-in HTTP features, like HTTP authentication and HTTP verbs, which are understood by off-the-shelf HTTP clients. JSON is returned by all API responses, including errors.

Authentication

Getting an access token

var request = require('request');
var base64_credentials = new Buffer(CLIENT_ID + ":" + PASSWORD).toString('base64')
request.post({
url: 'https://api.ayvri.com/2.0/auth',
headers: { Authorization: 'Basic ' + base64_credentials },
form: {grant_type: 'client_credentials'} },
function(err, res, body) {
grant = JSON.parse(body);
console.log(grant);
}
);
curl -X POST https://api.ayvri.com/2.0/auth \
-u $CLIENT_ID:$PASSWORD \
-d 'grant_type=client_credentials'
Example Response
{
access_token: '80a0jacec98f0ace0acacca.098f89cjca09ec0aca0j.0accejcs'
refresh_token: '08aecjaca0aec0jacejiecjac.09ec8acjce0a0ecjaaciajc.0acjc0'
}

Getting a new access token using a refresh token

var request = require('request');
var base64_credentials = new Buffer(CLIENT_ID + ":" + PASSWORD).toString('base64')
request.post({
url: 'https://api.ayvri.com/2.0/auth',
headers: { Authorization: 'Basic ' + base64_credentials },
form: {grant_type: 'refresh_token', refresh_token: grant.refresh_token} },
function(err, res, body) {
grant = JSON.parse(body);
console.log(grant);
});
curl -X POST https://api.ayvri.com/2.0/auth \
-u $CLIENT_ID:$PASSWORD \
-d "grant_type=refresh_token&refresh_token=$REFRESH_TOKEN"

ayvri v2 api uses JWT authentication. In order to get a valid auth token, you will need to pass your api account details to the authentication endpoint. This will return a grant which includes an access_token and a refresh_token. Tokens expire after 1 week. When your token expires,you can retrieve a new access_token by passing the refresh_token from your original grant to the

The auth endpoint will return a json object which contains the access_token and refresh_token.

Getting Started : 101

With an access token, create a simple activity & scene

var request = require('request');
request.post({
url: 'https://api.ayvri.com/2.0/activity',
headers: { Authorization: YOUR_ACCESS_TOKEN },
body: JSON.stringify({activityType: ADD_ACTIVITY_TYPE}) },
function(err, res, body) {
var resBody = JSON.parse(body);
var uploadUrl = resBody.uploadUrl;
var activityId = resBody.activityId;
request.post({
url: uploadUrl,
body: YOUR_GPX_OR_IGC_DATA
}, function(err, res, body) {
request.post({
url: 'https://api.ayvri.com/2.0/scene',
headers: { Authorization: YOUR_ACCESS_TOKEN },
body: JSON.stringify({activities: [activityId]})
}, function(err, res, body) {
console.log(JSON.parse(body));
var embedUrl = JSON.parse(body).embedUrl;
});
});
});

Once you have an authentication token, you can get started uploading activities and creating scenes.
Creating a scene is a 3 step process

The example here shows how to create a simple scene using the javascript request library, and is used as a simple example to get you started.
Once you can create an activity and a scene, see below for more details and capabilities to customize your scene.

Create Activity

Creating a new activity

var request = require('request');

var activityDetails = {
activityId: 'UTMB_2017',
title: 'UTMB 2017',
activityType: 'Run',
avatar: {
name: 'Brook Martin'
},
color: 'rgb(40,15,110)'
}

request.post({
url: 'https://api.ayvri.com/2.0/activity',
headers: { Authorization: grant.access_token },
body: JSON.stringify(activityDetails) },
function(err, res, body) {
var uploadUrl = JSON.parse(body).uploadUrl
console.log( body );
});
curl -X POST https://api.ayvri.com/2.0/activity \
-H "Authorization: accesss_token" \
-H "Accept: application\json"
-d "{\"activityType\": \"Run\"}"
Example Response

Creating an activity will save the activity details to your api account and return an upload URL to use to push a GPS or IGC file up to the server to be processed.

Activity has the following attributes

Upload Activity

Upload a gps or igc file

var require('fs');
fs.readFile(file, function(err, data) {
request.put({
url: uploadUrl,
body: data
},(err, res, body) => {
//should return a 200 response
});
})
curl -X PUT -T file uploadUrl \

Use the upload url in the response of the created activity to push the activity gps to ayvri. The upload url is valid for 3 minutes.

When the url is uploaded, ayvri will process the tracks to prepare them to be displayed in the viewer. This processing takes only a few seconds.

When a file has been uploaded, ayvri will process the track to get it ready to be displayed in a Scene.

Delete Activity

Delete an activity from ayvri and all scenes

request.delete({
url: 'https://api.ayvri.com/2.0/activity/{accountId}/{activityId}',
headers: { Authorization: grant.access_token },
function(err, res, body) {
console.log( body );
});

curl -X DELETE https://api.ayvri.com/2.0/activity/{accountId}/{activityId} \
-H "Authorization: accesss_token" \

Deleting an activity via the api will delete the activity from ayvri and will remove the activity from any scenes it is included in. The scenes will not be deleted directly as a result of this action.

Create Scene

Create a Scene containing activities

var request = require('request');
var sceneDetails = {
title: 'choose a unique title',
activities: [{activityId: activityId_1}, {activityId: activityId_2}...]
}
request.post({
url: 'https://api.ayvri.com/2.0/scene',
headers: { Authorization: access_token },
body: JSON.stringify(sceneDetails)
},
function(err, res, body) {
var embedUrl = JSON.parse(body).embedUrl
});
curl -X POST https://api.ayvri.com/2.0/scene \
-H "Authorization: access_token"
-d '{"activities":[{activityId: activityId_1}, {activityId: activityId_2}...]}'

When the activities have been uploaded and processed, create a Scene to display the activity or activities.

A Scene has the following root attributes, see below for child object details

Activities

A Scene’s activities array is a subset of the activity details

Adding an Activity to a Scene

var request = require('request');
var addActivity = {
sceneId: scene_id,
activityId: activityId_1
}
request.post({
url: 'https://api.ayvri.com/2.0/addActivityToScene',
headers: { Authorization: access_token },
body: JSON.stringify(addActivity)
},
function(err, res, body) {
// should return 200 response
});
curl -X POST https://api.ayvri.com/2.0/addActivityToScene \
-H "Authorization: access_token"
-d '{"sceneId": scene_id, "activity": activityId_1}'

Under most circumstances, you will create a scene with activities defined in the scene object. However, you can add an activity to a scene using the addActivityToScene path in the api.

Custom Loading Screen

var request = require('request');
var sceneDetails = {
title: 'choose a unique title',
activities: [...],
loading: {
background: "https://url.to/background-image",
startImg: "https://url.to/image-to-replace-play-button"
}
}
request.post({
url: 'https://api.ayvri.com/2.0/scene',
headers: { Authorization: access_token },
body: JSON.stringify(sceneDetails)
},
function(err, res, body) {
var embedUrl = JSON.parse(body).embedUrl
});
curl -X POST https://api.ayvri.com/2.0/scene \
-H "Authorization: access_token"
-d '{"activities":[...], "loading":{"background":"https://url.to/background-image"}}'

You can set a custom loading screen on your Scene. ayvri does not provide a background image for your loading screen (yet). The loading screen will not be used if the Scene is set to autoplay.

Sharing Image

Set an image to be used by social networks when your Scene is shared.

Default Speed & Distance

For fine control over player speed and the follow distance of an activity, use the Segments, however you can set a simple default which will override the built in defaults

Autoplay

The Scene can be set to autoplay when loaded, so the loading page which not be seen.

Stats

var request = require('request');
var sceneDetails = {
title: 'choose a unique title',
activities: [...],
stats: ["speed","altitude","gradient","localTime"],
defaultStatsVisible: 3
}
request.post({
url: 'https://api.ayvri.com/2.0/scene',
headers: { Authorization: access_token },
body: JSON.stringify(sceneDetails)
},
function(err, res, body) {
var embedUrl = JSON.parse(body).embedUrl
});
curl -X POST https://api.ayvri.com/2.0/scene \
-H "Authorization: access_token"
-d '{"activities":[...], "stats": ["speed","altitude","gradient","localTime"], "defaultStatsVisible": 3 }'

The Scene can display stats specific to the target activity such as speed, altitude, local time and more.
valid stats are
"speed","airSpeed","boatSpeed","distance","altitude","gradient","climbrate","glideRatio","elevation","altitude","altitudeFromStart","localTime","gmtTime"

By default only the first stat in the array is displayed and other stats can be viewed by the user by click a tab which opens the other stats to view.

The number of stats visible by default can be set with defaultStatsVisible

Media

var request = require('request');
var sceneDetails = {
title: 'choose a unique title',
activities: [...],
media: [
{
mediaType: "image",
content: "https://url.to/image-file",
points: [
{
latitude: 40.7128,
longitude: 74.0060,
height: 300
}
]
}
height: 200
]
}
request.post({
url: 'https://api.ayvri.com/2.0/scene',
headers: { Authorization: access_token },
body: JSON.stringify(sceneDetails)
},
function(err, res, body) {
var embedUrl = JSON.parse(body).embedUrl
});
curl -X POST https://api.ayvri.com/2.0/scene \
-H "Authorization: access_token"
-d '{"activities":[...], "media": [{"mediaType":"image", "content":"https://url.to/media-image", "points": [{"latitude": 40.7128, "longitude": 73.0060, "height": 300}],"height": 200}] }'

Images and labels can be added into the scene by defining them in the Scene’s media array.

Media items have the following common properties:

Image

An image is a media item and has all the properties listed above, the content is defined as

Caption

A caption is a text label in the scene, it has the same properties as other media items. The content of a caption is defined as

Segments

var request = require('request');
var sceneDetails = {
title: 'choose a unique title',
activities: [...],
segments: [
{
time: "2017-11-03T12:11:00Z",
target: "activity",
targetId: "uniqueTargetId",
speed: 300,
targetDistance: 2000
},
{
time: "2017-11-03T12:18:00Z",
target: "activity",
targetId: "uniqueTargetId",
speed: 100,
targetDistance: 1200
}
]
}
request.post({
url: 'https://api.ayvri.com/2.0/scene',
headers: { Authorization: access_token },
body: JSON.stringify(sceneDetails)
},
function(err, res, body) {
var embedUrl = JSON.parse(body).embedUrl
});
curl -X POST https://api.ayvri.com/2.0/scene \
-H "Authorization: access_token"
-d '{"activities":[...], "segments": [{"time":"2017-11-03T12:11:00Z", "target": "activity":, "targetId":"uniqueTargetId", "speed": 300, "targetDistance": 2000}, {"time":"2017-11-03T12:18:00Z", "target": "activity":, "targetId":"uniqueTargetId", "speed": 100, "targetDistance": 1200}] }'

Segments define the activity of the camera in the scene including which activity is followed, how closely the camera follows the activity, and how quickly time passes.

There are multiple uses for segments, for instance if there is a less interesting portion of a track, a larger followDistance and higher speed automatically gives the user a quick view of this area. Over a more interesting portion of the track, a closer followDistance and slower speed will bring a larger focus on that segment.

Additionally, for scenes with multiple tracks or activities, like a triathlon, adventure race or other multi-track scenes, a segment lets the scene creator define when to switch from viewing one activity to move to view another. For instance, viewing the swim portion of a triathlon, and then at a specified time, switching to follow the bike portion.

If setting segments, it is required that the first segment be defined at the beginning of the scene. If no segments are defined, the player will use follow the first activity at the pre-defined default speed and target distance.

Exit Screen

var request = require('request');
var sceneDetails = {
title: 'choose a unique title',
activities: [...],
exitScreen: [
{
"image": "https://url.to/image",
"link": "https://url.to/your-page"
}
]
}
request.post({
url: 'https://api.ayvri.com/2.0/scene',
headers: { Authorization: access_token },
body: JSON.stringify(sceneDetails)
},
function(err, res, body) {
var embedUrl = JSON.parse(body).embedUrl
});
curl -X POST https://api.ayvri.com/2.0/scene \
-H "Authorization: access_token"
-d '{"activities":[...], "exitScreen":[{"image": "https"://url.to/image", "link":"https://url.to/your-page"}] }'

When the scene is finished playing, you can add an optional 3 links with images to the exit screen. These images and links will be displayed above the sharing icons. The images will be evenly spaced across the screen and are fit into a 1:1 aspect ratio taking up 20% of the screeen width.

Distance Markers

var request = require('request');
var sceneDetails = {
title: 'choose a unique title',
activities: [{activityId: 'someActivity'}],
distanceMarkers: {
frequency: 5,
color: '#4286f4',
height: 200
}
}
request.post({
url: 'https://api.ayvri.com/2.0/scene',
headers: { Authorization: access_token },
body: JSON.stringify(sceneDetails)
},
function(err, res, body) {
var embedUrl = JSON.parse(body).embedUrl
});
curl -X POST https://api.ayvri.com/2.0/scene \
-H "Authorization: access_token"
-d '{"activities":[{"activityId": "someActivityId"}], "distanceMarkers": {"frequency": 5, "color": "#4286f4"}}'

A scene can have distance markers evenly distributed across the length of a scene.

If the frequency is 5 and the users is viewing in metric, the markers will display at each 5 kilometer. If the user is viewing in imperial, the markers will be displayed at each 5 miles.

Delete Scene

Deleting a Scene from ayvri

request.delete({
url: 'https://api.ayvri.com/2.0/scene/{accountId}/{sceneId}',
headers: { Authorization: grant.access_token },
function(err, res, body) {
console.log( body );
});
curl -X DELETE https://api.ayvri.com/2.0/scene/{accountId}/{sceneId} \
-H "Authorization: accesss_token" \

Deleting a Scene from ayvri will remove the scene from ayvri services. Activities and media contained in the scene are not automatically deleted.

ayvri V2 Client-Side API

In order to use the Client API, you will need:

Getting Started

Include the script tag in the head of your file

Then create a reference to the AyvriClientAPI class.

Setup the ayvri API:

<script type="text/javascript" src="https://static.ayvri.com/clientAPI.js"></script>
<script>
var ayvriAPI = new AyvriClientAPI();
</script>

Authentication & Initialization

Authenticate and Initialize the API:

ayvriAPI.init('API-KEY', 'IFRAME-REFERENCE').then(res => {
if (res.error) console.log('the api returned with an error: ', res.error);
return console.log('the api is initialized');
});

Make sure to replace API-KEY with your API key.

Make sure to replace IFRAME-REFERENCE with a DOM selector for your iframe.

The ClientAPI is specific to your API key. You must initialize the API with your key.

The Scene you want to interact with will need to be included in your webpage via an iFrame. The API will also need a reference to this iframe.
This is done via a document.querySelector in initializing the api.

You can pass in any valid querySelector syntax to get the DOM element for the iframe embedded in your page.

It is best the iframe already loaded and ready in the page, but it is not necessary, as the API will not resolve until the iframe is ready.

Player Ready

Is the player ready?

ayvriAPI.playerReady().then(res => {
var ready = res.playerReady;
})

Once the api has connected to the iFrame, the player must be ‘ready’ before you can start pushing data to it. The player is only ready once the user has hit play, or if the scene is autoplaying, once the player has fully loaded up and is bootstrapped.

Time

Getting the current time in the player

ayvriApi.getTime().then(res => {
if (res.error) return console.log('this should never happen ', res.error);
return console.log('current time is ', res.time);
})

Setting the time in the player

ayvriApi.setTime(milliseconds).then(res => {
if (res.error) return console.log('could not set time');
return console.log('time updated to ', res.time);
})

ayvri scene plays over time. In order for the tracks and the camera following to work properly, it is important that all elements work with the same timestamp range.

In ayvri, time is always in milliseconds.

Activities

Adding an Activity

var activity = {
activityId: uniqueId,
avatar: {
name: 'text to display with user',
image: urlToAvatarImg
},
color: 'rgb(230,120,4)'
}

ayvriApi.addActivity(activity).then(res => {
if (res.error) console.log('an error occurred adding the activity: ', res.error);
return console.log('activity has been added and is ready for points');

});

Activities in ayvri refer to the track, user, and path within a ayvri Scene.
Before you can push GPS points to an activity, the activity must be added to ayvri so ayvri knows which activity to add points to.

An activity has the following attributes

Toggling Activity Visibility

ayvriApi.toggleActivityVisibility(activityId).then(res => {
console.log('the activity visibility has been toggled');
}, err => {
console.log('an error occured toggling the activity visibility')
});

You can toggle the visibility of an activity in the scene by calling ayvriApi.toggleActivityVisibility and pass in the activityId of an activity in the scene. If the activity does not exist, an error will be returned.

Delete Activity

ayvriApi.deleteActivity(activityId).then(res => {
console.log('activity has been successfully removed');
}, err => {
console.log('an error occurred deleting the activity', err);
});

To remove an activity from the scene call ayvriApi.deleteActivity and pass in the activityId. The activity and all references to it’s points will be removed from the scene. If the activity cannot be found, an error will be returned.

Adding GPS Points

var points = [...array_Of_GPS_Points];
ayvriAPI.addPoints({activityId: activity.id, points: points}).then(res => {
if (res.error) console.log('an error occured adding points: ', res.error);
return console.log('points have been added to activity: ', res.activityId);
})

Once an activity has been added to the player, you can send GPS points to the activity which will be displayed in relation to the clock time in the player.

Each gps points must include:

Camera Follow Path

In ayvri, the camera follows the path of an activity.

The path of the camera is set in a segment or can be set using setTargetActivity.

In a segment, the camera will follow a path from a specified start time.
When using setTargetActivity the camera will begin following the specified activity at the time the command is set

Adding a Segment

var segment = {
time: Date.now(),
target: 'activity',
targetId: activity.ativityId
targetDistance: 1400
speed: 20
}

ayvriAPI.addSegment(segment).then(res => {
if (res.error) return console.log('an error occured adding a segment: ' res.error);
return console.log('segment added');
});

A segment has the following controls:

Setting Target Activity


ayvriAPI.setTargetActivity(activityId).then(res => {
if (res.error) return console.log('an error occured setting the target activity: 'res.error);
return console.log('new target activity set');
});

To set a new target activity, pass the activityId to the setTargetActivity the terrain profile will be updated within the segment, to display the current target activity profile. If no segments have been set, the entire terrain profile will display the points for the target activity.

Media

Adding Media

media = {
mediaId: 'mediaId',
mediaType: 'label',
labelType: 'caption',
content: {
text: 'added media'
},
points:[{
"latitude":47.8095,
"longitude":13.0550,
"height":475.78557142344965
}]
};
ayvriAPI.addMedia(media).then(data => {
console.log('media item added', data);
}, err => {
console.log('error adding media', err);
});

Media can be added dynamically into the scene via the front-end url. Valid media objects are the same as those used when creating a Scene on the server. Details of valid Media can be found here. Only the front-end requests change.

Toggle Media Visibility

ayvriApi.toggleMediaVisibility('mediaId').then(res => {
console.log('media visiblity toggled');
}, err => {
console.log('error toggling media visibility', err);
});

To toggle the visibility of a media item, call ayvriApi.toggleMediaVisibility and pass in the mediaId. If the mediaId does not exist, an error will be returned.

Delete Media

ayvriApi.deleteMedia('mediaId').then(res => {
console.log('media item has been deleted');
}, err => {
console.log('error deleting media', err);
});

To delete a media item from the scene, call ayvriApi.deleteMedia and pass in the mediaId. If the mediaId does not exist, an error will be returned.