Skip to content

Instantly share code, notes, and snippets.

@joeycastillo
Last active December 12, 2015 06:19
Show Gist options
  • Save joeycastillo/4728811 to your computer and use it in GitHub Desktop.
Save joeycastillo/4728811 to your computer and use it in GitHub Desktop.
Notes on the ArtsFest API, which will power Bushwick Open Studios 2013.

#ArtsFest API documentation

ArtsFest is an open source framework for publishing information about multi-day arts festivals, conferences, panels and basically anything else involving events happening over time. The API allows users to consume resources at the following five endpoints:

  • /events — For an arts festival this might represent an open studio or a special event. For a music festival, this might be an showcase at a venue.
  • /venues — Each event is associated with one venue; for an arts festival this might be a gallery space or an artist's studio. For a music festival, it might be a bar or club. While an event only has one venue, a venue can be associated with multiple events.
  • /artists — Each event has zero or more artists; self-explanatory for an arts festival. For a music festival this could be the bands playing at the showcase. Note that artists can be involved with multiple events (i.e. a photographer with work in multiple exhibitions, or a band playing multiple showcases).
  • /categories — Each event has zero or more categories. Category could be a genre of music for a music festival; for an arts festival it could be an art medium (painting vs performance art) or an event feature (work for sale, handicap-accessible).
  • /sponsors — Disconnected from the graph above, this feed contains information about sponsors of the festival.

##Endpoints

All resources support the following request styles:

The form /<resource>.json returns a result set containing all <resource>s. The response takes the form of a JSON object with one member, result, an array containing zero or more results (the result set).

The form /<resource>/<id>.json returns a result set containing the resource with the specified id. If a resource with the specified id does not exist, the request will 404.

The /<resource>.json endpoint can take an optional parameter updated_since, a UNIX timestamp in UTC. If specified, the result set will only include resources whose update time is later than the specified timestamp. If no events have been modified since the specified date, the request will return an empty result set.

The updated_since parameter is useful for offline caching; you can request only resources that were changed or created since last synchronizing with the server.

##Resources

###General Notes

Within the result set, all resources will contain the following properties:

  • id — Integer. Uniquely identifies this resource among resources of the same type.
  • last_modified — Integer; speficically a UNIX timestamp in UTC. The last time this resource was modified in the database.
  • active — Boolean. If this is false, it means that the resource has been deleted.

If a resource has been deleted (active == false), no other properties will be returned. It is the client's responsibility to hide or delete the object from any on-device caches.

###Events

####Usage

/events.json
/events/1.json
/events.json?updated_since=1358299613

####Result Format

In addition to id, last_modified and active, each object in the result set will have the following properties. If a property is listed as optional, it may return either the value type listed, or null.

  • name — String. Name of the event.
  • short_desc — String, optional.
  • long_desc — String, optional.
  • section — String, optional. For more complex festivals, you may use this field to separate events into sections (i.e. official events, community events, etc.)
  • room — String, optional. For venues with multiple rooms, this can offer more detail. (i.e. "Suite 102", "Basement", "Gallery 3")
  • venue — Integer. The ID of the venue where this event takes place.
  • artists — Array of integers. The ID's of each artist taking part in the event.
  • categories — Array of integers. The ID's of each category associated with the event.
  • hours — Array of objects representing the opening and closing times each day. Each object in this array contains the following three properties:
    • opens — Integer; UNIX timestamp in UTC. The absolute time that this event opens on one day.
    • closes — Integer; UNIX timestamp in UTC. The absolute time that this event closes on one day.
    • notes — String, optional. Notes on this day's hours (i.e. "Doors open at 6:00", "Reception at 9:30")

Note that since event hours are UTC timestamps, care must be taken to display this information properly on the client side. On iOS, for example, it may make sense to initialize an NSDate with the time interval, then format the dates for display with an NSDateFormatter explicitly set to the time zone where the festival takes place.

####Sample Result Set

{
  "result": [
    {
      "id": 1, 
      "last_modified": 1358299614, 
      "active": true, 
      "name": "ArtsFest Opening Bash", 
      "short_desc": "Short description of the party.", 
      "long_desc": "Extended description with more information.", 
      "section": "official", 
      "room": "Grand Ballroom", 
      "venue": 10,
      "artists": [
        30, 
        31, 
        26
      ], 
      "categories": [
        10, 
        13, 
        14, 
        15, 
        26
      ], 
      "hours": [
        {
          "opens": 1370221200,
          "closes": 1370149200, 
          "notes": "Open bar until 10:00 PM"
        }
      ]
    }
  ]
}

###Venues

####Usage

/venues.json
/venues/1.json
/venues.json?updated_since=1358299613

####Result Format

In addition to id, last_modified and active, each object in the result set will have the following properties. If a property is listed as optional, it may return either the value type listed, or null.

  • name — String. This could be the name of the venue if it has one ("Little Skips", "The Drake Hotel"), or simply the address.
  • address — String.
  • city — String.
  • state — String.
  • country — String.
  • zip — String.
  • lat — Float. Latitude value for geocoding.
  • lon — Float. Longitude value for geocoding.
  • map_identifier — String, optional. An identifier for displaying the venue on a map.

City, state, country and zip are there for completeness; depending on the nature of the deployment, the backend can be modified to omit these values.

####Sample Result Set

{
  "result": [
    {
      "id": 11, 
      "last_modified": 1358295696, 
      "active": true, 
      "name": "East River Gallery", 
      "address": "90 Kent Avenue", 
      "city": "Brooklyn", 
      "state": "NY",
      "country": "USA", 
      "zip": "11211", 
      "lat": 40.72155, 
      "lon": -73.962067, 
      "map_identifier": "12"
    }
  ]
}

###Artists

####Usage

/artists.json
/artists/1.json
/artists.json?updated_since=1358299613

####Result Format

In addition to id, last_modified and active, each object in the result set will have only one additional property:

  • name — String. Name of the artist.

####Sample Result Set

{
  "result": [
    {
      "id": 30, 
      "last_modified": 1358295696, 
      "active": true, 
      "name": "Angela Vice"
    }
  ]
}

###Categories

####Usage

/categories.json
/categories/1.json
/categories.json?updated_since=1358299613

####Result Format

In addition to id, last_modified and active, each object in the result set will have the following properties. If a property is listed as optional, it may return either the value type listed, or null.

  • name — String, category name.
  • group — String, optional. This can be used to separate out event features, media, etc. into separate groups as needed (i.e. "Visual Arts", "Performing Arts", etc.)
  • order — Integer, optional. Purely a convenience to allow arbitrary sorting of categories on the client side.

####Sample Result Set

{
  "result": [
    {
      "id": 19, 
      "last_modified": 1358295696, 
      "active": true, 
      "name": "Music", 
      "group": "Performing Arts", 
      "order": 5
    }
  ]
}

###Sponsors

####Usage

/sponsors.json
/sponsors/1.json
/sponsors.json?updated_since=1358299613

####Result Format

In addition to id, last_modified and active, each object in the result set will have the following properties. If a property is listed as optional, it may return either the value type listed, or null.

  • name — String. Name of the sponsor.
  • short_desc — String, optional. A short (one line) description of the sponsor.
  • website — String, optional. A URL for the sponsor's website, or something chosen by the sponsor.
  • sponsor_level — String, optional. If you have sponsors on multiple levels, this can be used to group them together ("Silver", "Gold", "Platinum", etc.)

####Sample Result Set

{
  "result": [
    {
      "website": "https://www.facebook.com/pages/Cafe-El-Beit/344929228819", 
      "name": "El Beit", 
      "short_desc": "An unabashed coffee-geek bar in the heart of North Williamsburg.", 
      "last_modified": 1358295696, 
      "sponsor_level": "Friend of ArtsFest", 
      "active": true, 
      "id": 10
    }
  ]
}

##Final Notes

The API is built in Python, using the Flask microframework to handle requests, and sqlalchemy to handle the data model. The app includes middleware to handle seamless gzip compression of responses; thus while some of these response objects may look verbose, bear in mind that JSON compresses quite effectively.

The intended use case here, at least for the iPhone app, is as follows:

  1. Fetch each of the full feeds on first run, and store the full database in a cache on the user's device.
  2. Cache the last_modified date of the most recent object in each feed.
  3. Periodically poll the server using these last_modified dates, and update the local cache as needed.

In practice this means that you should never need to use /<resource>/<id>.json in your app. An alternative use case could return only summary information in /<resource>.json, and rely on calling /<resource>/<id>.json to fill in details on the fly. I don't anticipate implementing this for BOS 2013, however.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment