Donate using PayPal

CycleStreets API (v2)

  • Details for:
  • API overview
  • Obtain API key
  • Usage policy
  • Uptime policy

Add photo

This API call is used to add locations to the Photomap. Each location can have a photo (though this is not required) and a set of metadata can be attached.

The Photomap is intended as a campaigning tool to enable citizens to geolocate and tag problems such as lack of cycle parking, or to highlight good practice, so that this data can be used by cycle campaign groups, Local Authorities and others. A variety of sites (e.g. Urban Cycle Parking) have been built using the API. Photos are used within route listings on the main site, on the Photomap for general browsing, and by any API client accessing them.

This call is ideal for use in audit-style applications.

You can add arbitrary metadata fields to a location using additionalMetadata. This could be useful for auditing and similar uses, e.g. storing results of a formal survey at the location.

You can retrieve any data added (including unpacking of any additionalMetadata) using the other Photomap calls, particularly photomap.location and photomap.locations.

Clients may wish to make an initial call to photomap.categories (and then cache the result of this) so that a list of the supported categories (e.g. 'cycleparking') and metacategories (e.g. 'bad') can be displayed as a drop-down list. This then enables the user to express good metadata on what their photo represents e.g. a cycle parking problem (category=cycleparking,metacategory=bad) at the point of uploading.


Example which adds a location representing a cycle parking problem, including a photo, and supplying some additional metadata resulting from a survey.

This call requires a POST operation, because (a) images are a binary payload, and (b) to avoid us logging user credentials in the server logs.

	[mediaupload] => [binary payload of the image file, containing embedded EXIF location and time data]
	[username] => myusername
	[password] => mypassword1978
	[category] => cycleparking
	[metacategory] => good
	[caption] => This location serves the nearby shops.
	[additionalMetadata] => {"spaces":10,"covered":"no","highway":"Red route"}


    "id": 64001,
    "url": "",
    "shortlink": "",
    "imageUrl": "",
    "thumbnailUrl": ""

You could later retrieve the data via a request to photomap.location as follows:,hasPhoto,caption,additionalMetadata

    "type": "FeatureCollection",
    "features": [
            "type": "Feature",
            "properties": {
                "id": 64001,
                "hasPhoto": true,
                "caption": "This location serves the nearby shops.",
                "additionalMetadata": {
                    "spaces": 10,
                    "covered": "no",
                    "highway": "Red route"
            "geometry": {
                "type": "Point",
                "coordinates": [

Request parameters - required or highly recommended

The following are required or highly-recommended parameters.

The mediaupload payload field can be omitted if there is no image, but, naturally, photos add interest and value when using the data.

The latitude/longitude/datetime values will be gleaned from EXIF data where they exist. The server will always try to read data from EXIF. However, explicitly-supplied values will take priority. If no data is available (from EXIF or explicitly), the location will be set as an unlocated photo. If possible, supply values explicitly, by giving the user the opportunity first to confirm/adjust the location in your GUI, to ensure a correct GPS location.

mediaupload binary (optional)
A photo file, as if posting from a standard HTML form. If there is no image to be associated with the data, you can omit this field, and the submission will be treated as a 'placeholder' location.

category string
The category (e.g. 'cycleparking') selected from the list of available tag values listed in the results of a photomap.categories call.
metacategory string
The metacategory (e.g. 'bad') selected from the list of available tag values listed in the results of a photomap.categories call.
caption text
Text for a caption describing the image.
username string
The username or e-mail address of a user (whose account has been through validation). The API call will use the username/password credentials to perform authentication. If you are creating a third-party auditing-style application, it is fine to register a single user account and all submissions be made as that user.
password string
The password for this user. See details for username.

latitude float [technically optional]
Latitude of the location of the photo (ideally not the place it was uploaded), which some devices put in the EXIF data. See note above regarding EXIF handling and priority.
longitude float [technically optional]
See details for latitude.
datetime int [technically optional]
Time (Unix timestamp) of the photo, which you can usually extract from EXIF data. See note above regarding EXIF handling and priority.

Request parameters - optional

tags string
Tags (keywords), space- or comma- separated, to provide an optional way to enable automatic matching/linking of photo themes.
license string (cc-by-sa|publicdomain|no-redistribution)
License of the image. If not specified, the default system setting in the user's profile (by default this is cc-by-sa) will be used.
bearing int (0-360) (default: 360, i.e. unknown)
Direction the camera was facing; note that 0 is north, and 360 indicates unknown.
zoom int (number between 1 and 19)
The map zoom at which the photo location was set (which helps us determine the accuracy)
additionalMetadata string (JSON-encoded string containing key-value pairs)
This is an extensible field which allows you to store pairs of arbitrary key/value strings. It is useful if you have data such as answers to a formal survey at the location.


JSON object as above, showing the unique ID of the added location, together with URLs for its public page, image file and thumbnail file.

You may wish to use these to show the successfully uploaded location to the user by way of a confirmation screen, and/or invite the user to share the link on social media.

Error response

JSON object containing an error key and a text string.

The error string from this method is suitable for passing directly on to the user.

Example errors (text string may vary):

    "error": "The username/password combination did not match any validated account."

We welcome your feedback, especially to report bugs or give us route feedback.

My comments relate to: *

Your comments: *
URL of page: *
How did you find out about CycleStreets?:
Your name:
Our ref: Please leave blank - anti-spam measure

* Items marked with an asterisk [*] are required fields and must be fully completed.