Documentation
Overview
Register for a key
In order to get started, you need to register for a key. The type of key you require depends on what data you wish to access and what your application is for.
Authentication
An access key is required for all requests to the API and can be obtained by registration. This key, combined with the signature explained below, is required to get any access to the API. If you do not provide an access key, or provide an invalid key or signature, the server will return an HTTP 403 error.
Your secret token is used to calculate the correct signature for each API request and must never be disclosed. Once issued, it is never transmitted back or forward. The API server holds a copy of your secret token, which it uses to check that you have signed each request correctly.
You calculate the signature using the HMAC-SHA1 algorithm:
-
Build the full API request URL, including your access key but excluding the server domain - eg
/events?festival=book&key=12345
. See the note below on URL encoding. - Calculate the hmac hash of the url using the sha1 algorithm and your secret token as the key.
- Append the hex-encoded hash to your url as the signature parameter
URL encoding in queries
You should calculate the signature after URL-encoding any parameters - for example, to search for the
title
"Mrs Brown" you would first build the URL /events?title=Mrs%20Brown&key=12345
and then sign
this string and append the signature.
Signature encoding
Some languages - notably C# - default to encoding hashes in UTF-16. Ensure your signature is encoded in plain ASCII hex or it will not be valid.
Signature examples
$api_key = '12345678'; $secret_key = '135fa25acs33'; $query = '/events?filter=that&key='.$api_key; $signature = hash_hmac('sha1', $query, $secret_key); $url = 'https://api.edinburghfestivalcity.com'.$query.'&signature='.$signature;
import hmac import hashlib api_key = '12345678' secret_key = '135fa25acs33' query = '/events?filter=that&key=' + api_key signature = hmac.new(secret_key, query, hashlib.sha1).hexdigest() url = 'https://api.edinburghfestivalcity.com' + query + '&signature=' + signature
Valid request URL:
https://api.edinburghfestivalcity.com/events?festival=jazz&key=12345678&signature=e471178c45d33d7a37f99f74f8ff59d97749e7bf
Access to Fringe listings
To access live Edinburgh Festival Fringe data you will need to
apply for approval. All users can access a set
of randomised Fringe data for testing, which you can request by including the
festival=demofringe
parameter in your search terms. All users have access to
live listings data for events from the other participating festivals.
Querying the API
URL endpoints
The API service currently exposes 2 resources at:
https://api.edinburghfestivalcity.com
/events |
filterable list of events |
/events/{UUID} |
specific event by `UUID` (unique event identifier) |
Available query parameters
You can filter the list of events with any or all of the following optional parameters.
Basic search | |
---|---|
festival |
Festival ID, possible values are fringe, demofringe, jazz, book, international, tattoo, art, hogmanay, science, imaginate, film, mela, storytelling |
genre |
Available genres vary by festival and year - explore the data to see the range of values. |
country |
Country of origin of the company/artist/production - not populated for all events. |
code |
Festival-specific event code - useful for matching against other systems. |
year |
Festival year, for example 2015, or * for all years. The default is the current festival year - which rolls over on the 15th January each year to accommodate the Edinburgh's Hogmanay programme. |
Full text search on titles, descriptions and performers | |
title |
Strict matching against the event title |
description |
Matches event description - query types as above |
artist |
Matches artist name - query types as above. Not populated for all events. |
Date search | |
date_from |
Events with performances after the specified Europe/London time. |
date_to |
Events with performances before the specified Europe/London time. |
Price search | |
price_from |
Events with at least one performance where full price is more than £10.10 |
price_to |
Events with at least one performance where full price is less than £9.99 |
Venue search | |
venue_name |
Any venue matching query |
venue_code |
Number (123, 456) is venue ID from Fringe list. Not relevant for non-Fringe venues |
post_code |
Venue postcode, exact string match |
Geographic location by distance from latitude / longitude | |
lat |
Latitude |
lon |
Longitude |
distance |
Circle around Lat/Lon point. Specified as Xmiles or Xkilometers (note no space, eg. 10miles or 1kilometers) |
Last modified search | |
modified_from |
Events where any of the data fields have changed since the specified Europe/London time. There may be a delay of a few minutes between an event being marked as modified and it being returned in an API query. Therefore, if you are using this query to synchronise a local copy of the data you should add a ten minute window to ensure you receive all changes. For example, if you sent your last query at 10:00:00 you should pass a modified_from of 09:50:00 with your next query. This may result in a few events being received in both updates and you should handle this appropriately in your application. Including this parameter will trigger the API to include deleted and cancelled events. See the section on event status for further details. |
Paging | |
size |
25 results per response, default is 25, max value is 100 |
from |
Index of the first result to return - for example, with size=25 you would query with from=0, from=25, from=50, etc. |
Other options | |
pretty |
Adding &pretty=1 to your search query will make any format human readable |
Synchronising with a local database
If you're using the API to feed a high-traffic site, or to merge with data from other sources, you may want to keep a local copy of our data. All the festival listings change over time, so you'll need to regularly synchronise this to keep it up to date. You're required to do this at least once every 24 hours, but we recommend more often if you can.
Each event has a url
field that is guaranteed to be unique and constant even if the event's
title
/
date / etc changes. This field is the event's ID in the API : we strongly recommend storing this and using
it
to
match up data between each import.
To fetch just the updated events, use the modified_from
query parameter with a time ten minutes
before
your last request. For example: ?modified_from=2017-02-13+09:50:00
. Note that this query will
also
return cancelled and deleted events : see the event status documentation.
Event Status
Events should only be matched or changes tracked based on the unique url
key in the response.
It
is
essential that you do not attempt to match similar looking events on their titles, venues
etc
as
these are likely or known to change.
By default, API responses do not include events that have been removed from the original festival's listings or where they are explicitly marked as cancelled in the data we receive. For most API queries, you should consider all events received as being active and display them accordingly.
However, if you include a modified_from parameter in your search
query, the API may also return inactive events. This is to ensure you can consistently update any
local cached or stored versions of the data when events are deleted or cancelled. The JSON
formats include a status
field for each event which should be interpreted as follows:
status |
Expected action |
---|---|
empty/missing | Event is active - display as normal |
active |
Event is active - display as normal |
cancelled |
Event has been cancelled. You may continue to display the event, or remove it, as appropriate to your application. |
deleted |
Event has been removed from the API database. This may be because it was cancelled and the festival source data does not provide an explicit cancelled event status. Or it may have been added to the API in error and subsequently deleted. You must remove this event from any local database and stop displaying it in your application. |
As a fallback for backwards compatibility with clients that do not properly handle the status field, the API also amends the title, description and performances list for events that have been deleted or cancelled.
Response formats
You must pass an Accept
header with your request specifying the response format you require.
The only supported response format for new applications is application/json;ver=2.0.
Heads up! Future improvements to the API will be backwards compatible with these response formats, but may add additional fields. You should only process API responses with a suitable parser library - attempting to use regular expressions or text libraries may cause your application to break in future.
The schema of the returned data is consistent across all festivals, but there are significant variations in
the
level of data completeness between events and festivals. Where no value is available, the API will return
null
values - you should ensure your application treats and displays these values as "Unknown"
rather
than for example as equivalent to a boolean false
or numerical zero
. Before
building
any
application reliant on a particular field, we strongly recommend exploring the range and availability of
values
across the festivals you wish to include.
{ "age_category": "12+", "artist": "Dream The Idle", "artist_type": "Professional", "categories": { "strand_titles": [ "Epic Journeys" ], "subjects": [ "Travel", "Exploration" ], "keywords": [ { "category": "Countries", "keywords": [ "America", "England" ] }, { "category": "Artforms", "keywords": [ "Physical Theatre", "Storytelling" ] } ] }, "code": "DREAMIDLE", "country": "ENGLAND", "description": "beautiful; attempting doomed connect to willed mini-epic man searching in this a is one Al with Ridiculous He's fail Grandad to tropical Northumberland. rainforest... and adventure he is to never for a yet triumph. knew. an", "description_teaser": "One man's beautiful attempt to connect", "disabled": { "audio": false, "audio_dates": "", "captioning": false, "captioning_dates": "", "other_services": false, "other_services_dates": "", "other_services_information": "", "signed": false, "signed_dates": "" }, "discounts": { "friends": true, "group": true, "passport": true, "schools": true, "two_for_one": true }, "festival": "Fringe", "festival_id": "fringe", "fringe_first": false, "genre": "Theatre", "genre_tags": "physical theatre, storytelling", "images": { }, "latitude": -3.1871529999999999, "longitude": 55.948039000000001, "non_english": false, "performance_space": { "age_limit": "", "age_limited": false, "capacity": 50, "name": "The Aviary", "wheelchair_access": "" }, "performances": [ { type:"in-person", "price_type: "paid", "is_at_fixed_time": true, "price": 12, "concession": 10, "concession_additional": null, "concession_family": null, "price_string": "£12 (£10)", "start": "2011-06-29 11:15:00", "end": "2011-06-29 11:45:00", "duration_minutes": 30, "title": null } ], "performers_number": 1, "status": "active", "sub_venue": null, "title": "The Station: Fourstones", "twitter": "theidledream", "updated": "2011-07-01 02:20:20", "url": "https://api.edinburghfestivalcity.com/events/124ae5df40eb3f455460a1c5a8c3f16c0ffcf024", "venue": { "address": "The Pleasance 140", "box_office_fringe": false, "box_office_opening": "From Aug 5 10:00-22:00", "cafe_description": "Cold drinks available.", "code": "124", "description": "classic Courtyard. Just new the a world. rising the theatres drama, breathtaking from studio theatre award-winning, around intimate writing, companies, from comedy the and best of road dance down feast physical talent Zoo's the emerging host Pleasance", "disabled_description": "assistance welcome, equalities access people, impaired for visually dogs trained.\r\n\r\n Improved staff", "email": null, "fax": null, "has_bar": false, "has_booking_over_card": false, "has_booking_over_phone": false, "has_booking_over_web": false, "has_cafe": false, "name": "Zoo", "phone": "0131 662 6892", "position": { "lat": 55.945683000000002, "lon": -3.1811180000000001 }, "post_code": "EH8 9RR", "web_address": "www.zoofestival.co.uk" }, "warnings": "", "website": "http://www.edfringe.com/whats-on/theatre/abbi-patrix-and-linda-edsjoe-a-concert-of-stories" }
Event Images
The API provides a consistent interface for accessing listings images for events across all participating festivals, subject to availability.
Usage rights, hosting, linking and protocols
Most of the images are only approved for distribution as part of the participating festivals' marketing and promotion activity. You are welcome to use and display the provided images alongside both historical and active listings content, generally accompanied by at least the name of and link to the festival website. Use of the images independently may be a breach of copyright. We are working on more specific guidance, but in the meantime if you are not sure whether your proposed image usage meets these requirements please contact us to discuss.
Images are hosted on Amazon S3 and are available over both HTTP and HTTPS connections. The API response
returns a scheme-relative URL - eg
//images.api.edinburghfestivalcity.com/ab/cd/ef/9948272323-original.jpg
.
This URL format will trigger browsers to automatically use either HTTP or HTTPS depending on whether the
connection to your own server was over a secure connection. Some parsing libraries (including PHP) do not
properly recognise scheme-relative URLs so you may find you need to add the appropriate http: or https:
prefix for machine usage.
For low and medium traffic applications, you are welcome to serve the provided URLs directly in your application or website, subject to the normal API terms and conditions. If you are operating a high traffic site we ask that you contact us to discuss fair usage and any bandwidth limitations before launching your site.
Image types
The shape and size of source images varies by festival, depending on what the image was originally intended
for. The type
property of each image provides a hint as to intended use. You may also wish to
check the orientation
property as well as the width and height of the original image in order
to
filter out images that may not be in a suitable format for your use case.
You may only resize images in their original aspect ratio, and you must not crop images (automatically or manually) without advance permission.
Type | Description |
---|---|
hero | A large-format, generally landscape, image originally designed for display as the major feature element of a page. May be suitable as a thumbnail but requires careful handling in this case. See for example the Edinburgh International Festival's category pages and event listing pages. |
thumb | A smaller, generally approximately square or portait, image designed for display alongside other content on a page or as a thumbnail within listings results. See for example the Edinburgh International Book Festival's category pages and event listing pages. |
Image versions
In addition to the original format, we provide resized versions of each image. Small images will not be scaled up, so only the original, square-75 and square-150 versions are guaranteed to be present.
Version Key | Width | Height | Description |
---|---|---|---|
original | {varies} | {varies} | The original size and format of the image |
square-75 | 75px | 75px | Scaled down to fit a transparent 75 pixel square box. |
square-150 | 150px | 150px | Scaled down to fit a transparent 150 pixel square box. |
thumb-100 | One side 100px | Scaled down in original aspect ratio to 100 pixels on the longest side. | |
small-320 | One side 320px | Scaled down in original aspect ratio to 320 pixels on the longest side. | |
medium-640 | One side 640px | Scaled down in original aspect ratio to 640 pixels on the longest side. | |
large-1024 | One side 1024px | Scaled down in original aspect ratio to 1024 pixels on the longest side. |
Libraries & Examples
-
PHP
We provide a PHP client https://github.com/festivalslab/api-client-php which is also available through composer with
composer require festivalslab/api-client-php
-
Rubygem
Gareth Adams has contributed the open-source (MIT licence) festivals_lab rubygem for accessing the API. It's in alpha, and not officially supported, but covers the whole of the current JSON API. For documentation and installation instructions see the festivals_lab gem on github.
Implementations in other languages should be relatively straightforward. If there's a particular language you think we should provide official packages for, or if you have developed a library you'd like to share with the community, please do contact us.