Philadelphia Public Art @philart.net
API
Welcome to the documentation page for the Philadelphia Public Art API @philart.net, a read-only, RESTful JSON API which exists to enable application developers and data miners to retrieve and use the same data that drives the main website.
Disclaimers
This API is offered as-is. It is a part-time hobby project of the webmaster, and as such offers no guarantees of up-time, bug-free operation, or data accuracy. The data returned may be in a partial state during updates, which are both frequent and unscheduled. This API is not intended, nor should it be used, as the basis of any commercial application. The webmaster is not responsible for your use or misuse of the API or for any financial or other harm that may come from your use of it.
Backwards Compatibility and Versioning
There will only ever be one supported version of the API active at any time. However, the webmaster does endavor to make the current version as accurate and bug-free as possible, and does promise that as changes are made or new features added, the API will stay as backwards compatible as possible, with every attempt made to avoid changes to structure or data meaning that would likely break existing applications.
Copyright
The copyright notice in the fine print of the footer of this page applies to all data supplied through, and images referenced by, the API on this site. The format of the positive JSON responses on this site is Copyright 2015, Christopher William Purdom. Permission is granted to use the JSON format in any way you choose, so long as you do not claim ownership for yourself.
Introduction
- The bottom of this page is a consumer of the API. It can be used to test and view responses, and through the view source function of your browser you have acces to sample JavaScript code.
- The core function of the API is to return descriptions of pieces of public art in Philadelphia
- There are two primary types of data returned by this API: those that exist purely for navigation and those that return descriptions of art.
- The JSON format for the artworks is consistent in all responses.
- Some responses describe collections of art. Some collection types include extra information specific to the collection itself.
- This API mostly subscribes to a HATEOAS model of navigation and the use of the "links":{"rel":"X","href":"Y"} structure.
- With two exceptions, navigation is top down, with the highest level being philart.net/api.json, followed by phiart.net/api/x.json and philart.net/api/x/y.json, where x is an alphabetic plural type, and y is a numeric id code for the specific piece of art or collection.
- The first exception is philart.net/api/geo.json, which returns a collection that is defined by bb and ll URL arguments
- The second exception is philart.net/api/sizes.json, which has two children, philart.net/api/sizes/big.json and philart.net/api/sizes/small.json.
- With the exception of the geo.json URL, it is highly recommended that you use the navigation to drive through the results.
- JSON-formatted Error messages and codes will be returned in case of API failures, partial data, or attempts to access non-existent identifiers.
- However, any request that is not recognized as a valid API reference may get the standard website 404 page as a response.
- The api defines three possible elements to all good responses: A links section, with HATEOAS style links, a head, which includes a title and a type, and a body, the format of which depends on the type in the head.
- Some of the responses include external HTML links in the body section. These links are outside the webmaster's control and may or may not be useful to any application
Head Types
The following types are currently supported in the head:
- topnav: returned by philart.net/api.json. It has no body, just a head and links. See the tester for format and current values
- listnav: returned by all philart.net/api/x.json (except for geo) and lists all of the valid children of the current request in the body. See the tester for format and current values
- art: returned by philart.net/api/art/x.json, the body contains a description of a single piece of art
- artist: returned by philart.net/api/artists/x.json, the body contains information about the artist, and an array of related art descriptions
- person: returned by philart.net/api/people/x.json, the body contains information about a person referenced in one or more pieces of art, and an array of descriptions of those pieces
- landmark: returned by philart.net/api/landmarks/x.json, the body contains information about a landmark which has physically associated art, and an array of descriptions of that art
- content: all pieces of art in the database are associated with content types which are arbitrary inventions of the webmaster, such as "People Standing" or "Fish, Dolphins, and Whales". This type is returned by philart.net/api/content/x.json. The body contains an array of descriptions of art associated with one content type, and in some cases, additional explanatory text.
- tour: returned by philart.net/api/tours/x.json. Tours are collections of reasonably geographically contiguous pieces of art, presented in an order that makes sense to the webmaster. The body of the response includes a description of the tour, additional information, and a sequenced array of art descriptions.
- exhibit: returned by philart.net/api/exhibits/x.json. Exhibits are collections of art curated by the webmaster. The body contains a description and a sequenced array of art descriptions. Some exhibits, such as "War" are further divided into named sections.
- year: returned by philart.net/api/years/x.json. The body contains an array of descriptions of all the art associated with that year.
- architecture: returned by philart.net/api/architecture/x,json. All pieces of art that are attached to buildings or have some practical architectural function have been classified into various arbitrary architectural categories by the webmaster, such as "Bike Racks" and "Stairs". The body of this response includes an array of descriptions of all pieces in one such category
- size: returned by philart.net/api/sizes/x.json, where x is "big" or "small". The body of this response includes an array of descriptions of art that have been arbitrarily classified into one of those two categories by the webmaster.
- geo: returned by philart.net/api/geo.json. The body contains an array of art descriptions as described in detail further below.
HATEOAS links
All HATEOAS links are in the form "links":[ {"rel":"x","href":"y"}] where the first element always has a rel of "self" and the href is a fully qualified URL. For all the head types listed below (art, artist, person, etc.) as well as listnav, the links element includes self and parent elements. The topnav includes a longer list which you can see in the tester. HATEOAS links in the body only contain self. HATEOAS links are required when mentioned below.
External Links
All external links are of the form of an array: "externallink":[{"url":"x","label":"y"}]. As noted these are typically html links, and may or may not be of any use to a json application. The externallinks element is always optional, and will not be included if there are no associated external links. The label may contain an HTML "i" tag.
Detailed JSON Documentation by head.type
art
API responses with head.type == 'art' include the following elements in the body. These same elements are found in the "art" array in the body of the other listed responses. Objects in an art array also include a top level HATEOAS links element (e.g. body.art[1].links).
- title: a required object with two string members: display, and list.
- artists: an optional array of objects with three members: name (a required string), external links, and HATEOAS links.
- years: an optional array of one or two objects with two members: year (a required string), and HATEOAS links. If there is one element in the array, then the date is definitive. If there are two elements in the array, then the dates are a range.
- yearmodifier: an optional string that provides some textual context for the years.
- location: an object with three members: latitude (a required string), longitude (a required string), and description (an optional string). If the art has been physically removed, then the description will be blank, and the latitude and longitude will refer to the last known location. If the art description is part of an array in a response with head type "tour", the optional member tourmapoverride may be added to this object. See "tour" below.
- comments: an optional string. This string may contain the HTML tags "b", "i", and "br". Double quotes are escaped in the JSON, ASCII line breaks are converted to spaces.
- related: an optional array of objects with three members: title (a required string), prefix (a required string describing the relationship) and HATEOAS links. This field exists where two pieces of art have a relationship beyond subject matter or artist, such as one being a copy of the other, or one having replaced the other in a specific location.
- inscription: an optional string. This string may contain the HTML tags "b", "i", and "br". Double quotes are escaped in the JSON, ASCII line breaks are converted to spaces.
- architecture: an optional object with two members: description (a required string) and HATEOAS links.
- landmark: an optional object with four members: name (a required string), prefix (an optional string), external links, and HATEOAS links.
- people: an optional array of objects with three members: name (a string), external links, and HATEOAS links.
- peopleprefix: an optional string describing how the people in the people field are referenced by the art, such as "statue of" or "quotes from".
- externallinks: external links for the art itself, such as articles or pictures on other sites.
- sizes: an array of objects with two members: size (a required string set to "big" or "small"), and HATEOAS links. An entry that has both big and small typically describes a piece that is very large but contains small detailed elements.
- content: an array of objects with three members: description (a required string), separator (an optional string), and HATEOAS links. The array is sequenced both in terms of imporance of the content and to make it possible to construct a reasonably syntactic English list of content elements. If the elements are to be listed in the form of a sentence, the seperator should be displayed after the description. Currently the only supported value of the separator is a comma, but that is subject to change without warning.
- pictures: an array of objects with two members: small, and large, which are required objects with two members: url (a required string) and mimetype (a required string). The small is a thumbnail of the large. Currently for all entries the small members are gifs and the large members are jpegs, though this could conceivably change in the future.
- tours: an optional array of objects with two members: name, and HATEOAS links.
- exhibits: an optional array of objects with two members: name, and HATEOAS links.
artist
In addition to the required "self" and "parent", the HATEOAS links for artist can include "ref":"asperson" where the database contains both art that is by the artist (listed in this response) and art that refers to the artist (listed in the asperson link). In addition to the art array, the body member of a response with head type "artist" includes:
- comments: an optional string. This string may contain the HTML tags "b", "i", and "br". Double quotes are escaped in the JSON, ASCII line breaks are converted to spaces.
- externallinks
person
In addition to the required "self" and "parent", the HATEOAS links for person can include "ref":"asartist" where the database contains both art that is by the artist (listed in the asartist link) and art that refers to the artist (listed in this response). In addition to the art array, the body member of a response with head type "person" includes the following members:
- comments: an optional string. This string may contain the HTML tags "b", "i", and "br". Double quotes are escaped in the JSON, ASCII line breaks are converted to spaces.
- landmarks: an otional array of objects with two members: name (a required string) and HATEOAS links. This member is included when there are landmarks named for the person that also have attached public art
- externallinks
landmark
In addition to the art array, the body member of a response with head type "landmark" includes the following members:
- comments: an optional string. This string may contain the HTML tags "b", "i", and "br". Double quotes are escaped in the JSON, ASCII line breaks are converted to spaces.
- person: an optional object with two members: name (a required string) and HATEOAS links. This member is included when the landmark is named for a person who is otherwise referred to in public art.
- externallinks
content
in addition to the art array, the body member of a response with head type "content" includes the optional string comments, which may contain the HTML tags "b", "i", and "br". Double quotes are escaped in the JSON, ASCII line breaks are converted to spaces.
tour
The location member of the art array in the body of a response with head type "tour" can include the additional member tourmapoverride, an object with the required strings "latitude" and longitude" (e.g.. body.art[x].location.tourmapoverride.latitude). This member is present when the art in question is best viewed from a distance, and it can be used to position a different numbered point on a map of the tour. In addition to the art array, the body includes the following members:
- description: a required string. This string may contain the HTML tags "b", "i", "p", "ul", "li", and "br". Double quotes are escaped in the JSON, ASCII line breaks are converted to spaces.
- map: a required object with three members: latitude, longitude, and zoom, all required strings. These are the recommended values for initiating a google map that will cover the area of the tour.
- extensions: an optional array of objects with three members: name (a requird string), directions (a required string) and HATEOAS links. These are tours that can easily be reached from the end of the current tour.
- externallinks
exhibit
The body member of a response with a head type "exhibit" can include either an art array or sections, which is an array of objects with two members: name (an optional string) and an art array. The web site and the tester display these exhibit results with the name of each section over the associated art list. See for example the "War" exhibit.
In addition to the art or sections array, the body member includes the following members:
- description: an optional string. This string may contain the HTML tags "b", "i", "p", and "br". Double quotes are escaped in the JSON, ASCII line breaks are converted to spaces.
- externallinks
Using geo.json
The philart.net/api/geo.json request takes two required URL arguments, ll and bb. The topnav entry for geo includes the sample arguments ll=39.952400,-75.165700&bb=39.951400,-75.166700,39.953400,-75.164700. ll stands for "latitude, longitude," and is used to sequence the array of returned art descriptions. bb stands for "bounding box" and is used to determine which pieces of art will be returned, where the first two values are the minimum latitude and longitude, and the last two values are the maximum latitude and longitude. All three latitude values and all three longitude values in the two arguments must conform to the following restrictions, or the API will return a 400 error:
- latitudes cannot be more than 9 characters long (inclusive of the decimal point), must be numbers, and cannot be < 39 or > 41
- longitudes cannot be more than 10 characters long (inclusive of a minus sign and decimal point), must be numbers, and cannot be < -76 or > -74
All art returned will have a latitude and longitude within the range specified by the bb argument. If no art is found within the specified range, the API will return a 404.
All art returned will be sequenced by distance from the ll argument, where distance is defined as the delta of latitude plus the delta of longitude. While this is not mathematically correct, it requires a minimum of calculation and is close enough in an environment where an approximately NSEW street grid confines most travel.
If your application is driven by a map api that specifies a bounding box, you should use the bounding box coordinates supplied by the map api. However, you should not call this API if the bounding box is completely outside the valid range. If the source bounding box overlaps the valid bounding box values you should adjust the bounding box arguments to match the overlapping portion. If the bounding box is within range, but you are getting the ll based on current geolocation of the device, you should adjust the ll to the nearest valid point.
If your application is driving a map api that accepts a bounding box argument, you should use the same bounding box for both, though as in the previous case you may need to adjust the arguments or skip calling the API altogether.
If your application is driving a map api that does not accept a bounding box argument then you will need to guess a bounding box based on the zoom size you are requesting, which will probably vary across map APIs and devices.
If you are building an application that is going to show information about the very nearest art, without using a map, you should try using a very small bounding box, for example +- .0001 from both parts of the ll.
Error Returns
If your request is not recognized as an API request you will receive a normal philart.net web site response, probably the standard 404 page.
The following JSON objects may be attached to a status 500, 400 or 404 by the API. Anything other than 200 should be considered an error. The format was copied from the Twitter specification, though this API never returns more than one error in the array.
- {"errors":[{"message":"Database connection error","code":1}]}
- {"errors":[{"message":"Sorry, that identifier does not exist","code":2}]}
- {"errors":[{"message":"Error retrieving known data","code":3}]}
- {"errors":[{"message":"bb and ll are required arguments","code":4}]}
- {"errors":[{"message":"arguments are outside the documented ranges","code":5}]}
- {"errors":[{"message":"Sorry, no results were found inside the bounding box [bb]","code":6}]}
- {"errors":[{"message":"Sorry, no art has been attached yet to artist [id]","code":7}]}
- {"errors":[{"message":"Sorry, no art was found for year [year]","code":8}]}
- {"errors":[{"message":"Sorry, no art has been attached yet to person [id]","code":9}]}
- {"errors":[{"message":"Sorry, no art has been attached yet to landmark [id]","code":10}]}
- {"errors":[{"message":"Sorry, no art has been attached yet to architecture id [id]","code":11}]}
- {"errors":[{"message":"Sorry, no art has been attached yet to content id [id]","code":12}]}
- {"errors":[{"message":"Sorry, no art has been attached yet to tour [id]","code":13}]}
- {"errors":[{"message":"Sorry, no sections has been attached yet to exhibit [id]","code":14}]}
- {"errors":[{"message":"Sorry, no art has been attached yet to the first section of exhibit [id]","code":15}]}
The API Tester
Everything between this paragraph and the footer tag in "view source" constitutes the API tester, which functions as follows:
- clickable list elements are displayed underlined on most browsers
- The tester has three lists of clickable elements at the top: navigation URLs, specific numeric ID URLs which may be adjusted using the input box at the top of the list, and the Geolocation URL, which may be modified using the bb and ll boxes. These are listed under the headings "Test Navigation Requests", "Test Numeric ID Requests", and "Test the Geolocation Request" respectively.
- All clickable list elements call the testUrl() script function which calls the standard XMLHttpRequest()
- Responses with readyState == 4 are sent to the showResponseText() script function, which calls JSON.parse() with the response text.
- Depending on the status code, showResponseText() calls either createGoodResponseOutput() or createBadResponseOutput() to convert the parsed response text into HTML
- createGoodResponseOutput() calls createTypeSpecificBodyString() to create a response based on head.type.
- showResponseText() sets the innerHTML of the apiresult div to the resulting HTML
- The resulting HTML includes the title from the head element, the raw response (which may include HTML tags and therefore some formatting), an ordered list of clickable HATEOAS links, an ordered list of elements from the body other than the art, some of which may be clickable, and art data, formatted as an ordered list (with clickable elements) followed by image thumbnails and an empty div for holding large versions of the clicked thumbnails. Where the art data is a list, the "Art Data" header includes a count (e.g. "Art Data (6)") and the pieces of art are separated by an hr tag.
- The tester results will appear at the bottom of this page. You may have to scroll down to see them.
Test Navigation Requests
- https://www.philart.net/api.json
- https://www.philart.net/api/art.json
- https://www.philart.net/api/artists.json
- https://www.philart.net/api/years.json
- https://www.philart.net/api/people.json
- https://www.philart.net/api/landmarks.json
- https://www.philart.net/api/architecture.json
- https://www.philart.net/api/sizes.json
- https://www.philart.net/api/content.json
- https://www.philart.net/api/tours.json
- https://www.philart.net/api/exhibits.json
Test Numeric ID Requests
- id:
- https://www.philart.net/api/art/[id].json
- https://www.philart.net/api/artists/[id].json
- https://www.philart.net/api/years/[year].json
- https://www.philart.net/api/people/[id].json
- https://www.philart.net/api/landmarks/[id].json
- https://www.philart.net/api/architecture/[id].json
- https://www.philart.net/api/content/[id].json
- https://www.philart.net/api/tours/[id].json
- https://www.philart.net/api/exhibits/[id].json
Test the Geolocation Request
- ll: bb:
- https://www.philart.net/geo.json?ll=[ll]&bb=[bb]