NAV Navbar
Of logo
javascript

Introduction

Welcome to the Openframe JavaScript Client! You can use this lib to access Openframe REST API endpoints, which can be used to fetch and update artworks, frames, and profile information for authenticated users.

At present we only have this JavaScript client library, but you’re welcome to use any language to interact with the API directly.

All of the methods of the JS client return Promises which are resolved with the parsed response body or are rejected with an error message.

Initializing the JS Client

import OF from 'openframe-jsclient';

// use default openframe server, openframe.io
const OF = new OF();

// to use a different server, pass option to constructor
const OF = new OF({
  api_base: 'http://localhost:8888/api'
});

Import the Javascript client class and create a new instance, optionally passing configuration options.

Configuration Options

Option Default Description
api_base https://api.openframe.io/ The base URL where the API is located

Authentication / Authorization

Although some Openframe data is public and can be retrieved via unauthenticated access, the API requires an authenticated user’s access token to be supplied with requests in order to manipulate a user’s data. An access token can be obtained by hitting the login endpoint and providing a valid username (or email) and password.

Once obtained, the access token may be included in requests as a query param:

GET https://api.openframe.io/v0/user/12345/owned_frames?access_token=wtu2jsJYZTO8ZqjGokR1ejznxCw4Qd0hACFo50GXyx3eGcVNNroccDWHZHmHVXKn

or in an Authentication header:

Authentication: wtu2jsJYZTO8ZqjGokR1ejznxCw4Qd0hACFo50GXyx3eGcVNNroccDWHZHmHVXKn

As noted below, after successful login, the JS client manages storage and inclusion of the header (in browsers with localStorage available).

Log in

This assumes you’ve got an instantiated OF client.

OF.users.login({'username': 'test', 'password': 'test'})
  .then(token => {
    console.log(token);
  });

// or

OF.users.login({'email': 'test@test.com', 'password': 'test'})
  .then(token => {
    console.log(token);
  });

If valid credentials are passed, the resolved token object, looks like this, where “id” is the actual access token value:

{
  "id": "wtu2jsJYZTO8ZqjGokR1ejznxCw4Qd0hACFo50GXyx3eGcVNNroccDWHZHmHVXKn",
  "ttl": 1209600,
  "created": "2016-12-05T03:45:55.936Z",
  "userId": "56c47fba45e503657a51bebc"
}

On success, the login endpoint responds with an access token that is valid for two weeks or until explicity destroyed via logout. The token is presented as the id value of response body, and must be supplied with subsequent requests on behalf of the logged in user.

If localStorage is present (i.e. the browser), the JS client automatically saves the access token to localStorage and includes it in subsequent responses.

Log out

Calling logout will destroy the access token on the server and, if present, clear it from localStorage. Successful logout will result in a 204 no content response and resolve the Promise. If there is any problem destroying the access token on the server, the promise will be rejected with an error.

OF.users.logout()
  .then(() => {
    // success, no response body
  })
  .catch(error => {
    console.log(error);
  });

Users

Fetch a list of Users

OF.users.fetch(filter)
  .then(users => {
    // do something with users
  });

The above users array is structured like this:

[
  {
    "full_name": "Sol Lewitt",
    "username": "slewitt",
    "created": "2016-02-17T14:12:10.463Z",
    "id": "56c47fba45e503657a51bebd",
    "modified": "2016-02-17T14:12:10.463Z"
  },
  {
    "full_name": "Peter Pan",
    "username": "ppan",
    "created": "2016-02-17T14:12:10.560Z",
    "id": "56c47fba45e503657a51bebc",
    "modified": "2016-02-17T14:12:10.560Z"
  },
  {
    "full_name": "Missy Elliot",
    "username": "melliot",
    "created": "2016-02-17T14:12:10.666Z",
    "id": "56c47fba45e503657a51bebe",
    "modified": "2016-02-17T14:12:10.666Z"
  }
]

This endpoint retrieves a list of users. At present, limited information is public for all Openframe users.

Arguments

Arg Default Description
filter {} A filter config object

Fetch a User by ID

OF.users.fetchById()
  .then(user => {
    // user is currently authenticated user
  });

OF.users.fetchById("56c47fba45e503657a51bebd")
  .then(user => {
    // do something with user
  });

The above user object is structured like this:

{
  "full_name": "Sol Lewitt",
  "username": "slewitt",
  "created": "2016-02-17T14:12:10.463Z",
  "id": "56c47fba45e503657a51bebd",
  "modified": "2016-02-17T14:12:10.463Z"
}

This method retrieves a specific user by ID.

If no ID is passed, it defaults to ‘current’, which returns the currently authenticated user.

Arguments

Arg Default Description
ID 'current’ A user ID

Fetch a User by username

OF.users.fetchByUsername("slewitt")
  .then(user => {
    /* user looks like
    {
      "full_name": "Sol Lewitt",
      "username": "slewitt",
      "created": "2016-02-17T14:12:10.463Z",
      "id": "56c47fba45e503657a51bebd",
      "modified": "2016-02-17T14:12:10.463Z"
    }
    */
  });

This method retrieves a specific user by Username.

Arguments

Arg Default Description
username none A username

Frames

Fetch all current User’s frames

Artwork

Fetch a list of Artworks

OF.artwork.fetch(filter)
  .then(artworks => {
    // do something with artworks
  });

The above artworks array is structured like this:

[
  {
    "title": "unknown-1471551583623.frag",
    "is_public": true,
    "url": "https://thebookofshaders.com/log/160818203933.frag",
    "thumb_url": "https://thebookofshaders.com/log/160818203933.png",
    "author_name": "unknown",
    "required_extensions": {},
    "format": "openframe-glslviewer",
    "id": "57b61d12c0006da8310e9143",
    "ownerId": "57b61cf8c0006da8310e9141",
    "created": "2016-08-18T20:39:46.662Z",
    "modified": "2016-08-18T20:39:46.662Z"
  },
  {
    "title": "Nutrition Facts",
    "is_public": true,
    "url": "http://streetkonect.com/nutritionfacts",
    "thumb_url": "http://streetkonect.com/nutritionfacts/nf4b.jpg",
    "author_name": "Leah Valle",
    "required_extensions": {},
    "format": "openframe-website",
    "id": "57a85d5bc0006da8310e906b",
    "ownerId": "57a85cf2c0006da8310e9069",
    "created": "2016-08-08T10:22:19.405Z",
    "modified": "2016-08-08T10:22:19.405Z"
  }
]

This endpoint retrieves a list of Artworks. If called by an unauthenticated user, the list will include only public Artworks. If called by an authenticated user, private Artworks which the user has added will also be present in the response.

Fetch an Artwork by ID

Filtering queries

// an example filter for an OF.users.fetch(filter)
let filter = {
  fields: ['username', 'id', 'website'],    // fields to include
  include: 'created_artwork',               // include a relation in the result
  limit: 10,                                // limit the number of results
  skip: 10,                                 // skip a number of results
  order: 'username ASC',                    // result order direction, ASC or DESC
  where: {                                  // filter by field data
    username: {
      like: 'abc'                           // lots of operator options
    }
  },
}

All of the fetch methods can take an optional filter config object, which allows filtering of the query results. Whenever available, it takes the form shown on the right.

Errors

The Kittn API uses the following error codes:

Error Code Meaning
400 Bad Request – Your request sucks
401 Unauthorized – Your API key is wrong
403 Forbidden – The kitten requested is hidden for administrators only
404 Not Found – The specified kitten could not be found
405 Method Not Allowed – You tried to access a kitten with an invalid method
406 Not Acceptable – You requested a format that isn’t json
410 Gone – The kitten requested has been removed from our servers
418 I’m a teapot
429 Too Many Requests – You’re requesting too many kittens! Slow down!
500 Internal Server Error – We had a problem with our server. Try again later.
503 Service Unavailable – We’re temporarially offline for maintanance. Please try again later.