OSM Protocol Version 0.5 is an old version of the API, released on 2007-10-07 and replaced by API v0.6 in April 2009. Much of the API structure has remained the same in terms of XML responses etc, so some of this document still applies.
See an overview of changes...
v0.5 requires JOSM version 345 or higher
v0.6 requires JOSM version requires v1529 or higher
This protocol is based on the ideas of the RESTful API. For more information on RESTful APIs see wikipedia's Representational State Transfer page.
The API is the server component to which REST requests are addressed. The REST requests take the form of HTTP GET, PUT, POST, and DELETE messages. Any payload is in XML form, using the MIME type "text/xml" and UTF-8 character enconding, and may be compressed on the HTTP layer if the client indicates through the HTTP "Accept" header that it can handle compressed messages.
Requests to modify the database are authorized using HTTP Basic Authorization. Read requests do not require authorization.
The status of rails routing file OSM Protocol Version 0.5/Command Overview can be found here.
Basic Objects Types
The API supports the creation, modification, and deletion of three major object types: Nodes, Ways, and Relations.
Nodes have fixed coordinates and are used to express points of interest, as well as specifying the shape of ways. A typical XML representation of a node looks like this:
<node id="156804" lat="61.8083953857422" lon="10.8497076034546" visible="true" timestamp="2005-07-30T14:27:12+01:00"/>
Nodes may have tags:
<node id="156804" lat="61.8083953857422" lon="10.8497076034546" visible="true" timestamp="2005-07-30T14:27:12+01:00"> <tag k="tourism" v="hotel" /> <tag k="name" v="Cockroach Inn" /> </node>
This is the DTD for nodes (see also Full DTD):
Ways represent an ordered list of nodes. They must have at least two nodes, and typically have tags to specify the meaning of the way - a road, a river, a forest. Closed ways with certain tags are treated as areas by the rendering software; there is no explicit way of specifying an area. A typical XML representation of a way looks like this:
<way id="35" visible="true" timestamp="2006-03-14T10:07:23+00:00" user="johnz"> <nd ref="156804"/> <nd ref="156805"/> <nd ref="156806"/> <tag k="highway" v="secondary"/> </way>
This is the DTD for ways (see also Full DTD):
<!ELEMENT way (tag*,nd,tag*,nd,(tag|nd)*)> <!ATTLIST way id CDATA #REQUIRED> <!ATTLIST way visible CDATA #IMPLIED> <!ATTLIST way user CDATA #IMPLIED> <!ATTLIST way timestamp CDATA #IMPLIED> <!ELEMENT nd EMPTY> <!ATTLIST nd ref CDATA #REQUIRED>
<!ELEMENT tag EMPTY> <!ATTLIST tag k CDATA #REQUIRED> <!ATTLIST tag v CDATA #REQUIRED>
Relations are used to model any kind of relationship between objects, and can also represent an object themselves. Relations typically have one or more members (where members may be nodes, ways, or other relations), and a number of tags of which one is a "type" tag specifying the kind of relation. But relations without members or tags are permitted. The list of members is unordered, but membership may be qualified by a "role" attribute.
This is an example of a relation:
There may be any number of members (order is insignificant). The
type attribute is one of "way", "node", or "relation". The
ref attribute specifies the id of the object referenced. Only
ref together identify the object referenced. The
role attribute is optionally used to specify which role the object plays in the relationship. For simple groupings,
role is expected to remain empty or be left out?, but for turn restrictions etc. it will have an arbitrary string value.
An object can only be referenced in a particular relation once only, since the 20th May 2008, the API will return a 412 error if an object is referenced twice (before then, a 500 error was returned). Unfortunately there may still be bad data in the database, which means that you cannot simply upload a minor change to the data. It is recommended to use a more recent version of JOSM, as it no longer allows duplicate entities in the relation.
This is the DTD for relations (see also Full DTD):
<!ELEMENT relation ((tag|member)*)> <!ATTLIST relation id CDATA #REQUIRED> <!ATTLIST relation visible CDATA #IMPLIED> <!ATTLIST relation user CDATA #IMPLIED> <!ATTLIST relation timestamp CDATA #IMPLIED> <!ELEMENT member EMPTY> <!ATTLIST member type (way|node|relation) #REQUIRED> <!ATTLIST member ref CDATA #REQUIRED> <!ATTLIST member role CDATA #IMPLIED>
<!ELEMENT tag EMPTY> <!ATTLIST tag k CDATA #REQUIRED> <!ATTLIST tag v CDATA #REQUIRED>
Returned XML data
Several of the request types returned below return XML data. These essentially return one or more objects to the client. All the objects are always returned in a single <osm> tag.
|Purpose||HTTP Method and URL||Payload|
|Creation||PUT /api/0.5/<objtype>/create||XML per DTD||id|
|Retrieval||GET /api/0.5/<objtype>/<id>||n/a||XML per DTD|
|Update||PUT /api/0.5/<objtype>/<id>||XML per DTD||empty|
Note: When creating an object, the object id is assigned by the server and returned. There is no way to know or define the id beforehand. Thus, if you are uploading a data structure with references, for example a new way that uses two new nodes, you have to upload the nodes first, then put the node ids that the server has assigned into your way, and then upload the way.
Note: Some platforms do not support HTTP PUT AND DELETE method,such as J2ME. It can be done by using specify _method as an URL parameter (given that you send a POST request): eg./api/0.5/<objtype>/create?_method=put
These methods will return a HTTP 200 OK message if successful, or one of the following HTTP error codes:
|400 Bad Request||The payload did not match the request. This happens for example when an "update" request is made and the obejct id given in the XML does not match the object id in the URL.|
|401 Unauthorized||A write request was attempted without (valid) HTTP Basic Authorization.|
|404 Not Found||The object requested to be retrieved/modified/deleted does not exist, and did never.|
|405 Method Not Allowed||The keyword "create" was passed on the URL but the request was not a PUT request.|
|410 Gone||The object requested to be retrieved/modified/deleted existed once but has been deleted meanwhile.|
|412 Precondition Failed||The operation requested would break referential integrity (e.g. when requesting to delete a node that is used in a way, or when modifying a way to refer to a non-existing node). This error code is also used when the XML payload contains an object id in the context of a "create" request (where the server is expected to assign a fresh id).|
|417||The API no longer returns a 417 error code, however if you are using curl you might come across it when curl sends an Expect header and lighttpd rejects it. See the curl page for more information|
|500 Internal Server Error||An internal error occurred. This is usually an uncaught Ruby exception and should be reported as a bug. There have been cases where such errors were caused by timeouts, i.e. a retry after a short waiting period could succeed.|
|503 Service Unavailable||The database has been taken offline for maintenance.|
In some cases the server also includes an additional HTTP header, Error, to provide details about the problem. Example:
HTTP/1.1 400 Bad Request Cache-Control: no-cache Connection: Keep-Alive Error: The maximum bbox size is 0.25, and your request was too large. Either request a smaller area, or use planet.osm Date: Sun, 29 Apr 2007 09:31:51 GMT Content-Type: text/xml; charset=utf-8 Server: WEBrick/1.3.1 (Ruby/1.8.5/2006-08-25) Content-Length: 1
Retrieving all objects in a bounding box
There are two commands that take an area, called a bounding box, as input and return the objects that are in or otherwise associated with it.
About bounding boxes
A bounding box is an area defined by two longitudes and two latitudes, where:
- Latitude is a decimal number between -90.0 and 90.0.
- Longitude is a decimal number between -180.0 and 180.0.
There are two restrictions on the size of bounding boxes:
- They cannot enclose more than 0.25 degrees of latitude or longitude. The area covered by the largest possible bounding box (of 0.25 square degrees) varies from about 900 square miles at the equator to about 400 square miles on Iceland.
- They cannot enclose more than 50,000 nodes.
The commands that take bounding boxes return errors if either of these restrictions are violated. To work with bounding boxes that are larger than permitted by these restrictions, use Osmxapi or an offline solution such as the planet file.
Retrieving nodes, ways, and relations
The following command returns:
- All nodes that are inside a given bounding box and any relations that reference them.
- All ways that reference at least one node that is inside a given bounding box, any relations that reference them [the ways], and any nodes outside the bounding box that the ways may reference.
- All relations that reference one of the relations included due to the above rules. (Does not apply recursively.)
GET /api/0.5/map?bbox=, , ,
is the longitude of the left (westernmost) side of the bounding box.
is the latitude of the bottom (southernmost) side of the bounding box.
is the longitude of the right (easternmost) side of the bounding box.
is the latitude of the top (northernmost) side of the bounding box.
Note that, while this command returns those relations that reference the aforementioned nodes and ways, the reverse is not true: it does not (necessarily) return all of the nodes and ways that are referenced by these relations. This prevents unreasonably-large result sets. For example, imagine the case where:
- There is a relationship named "England" that references every node in England.
- The nodes, ways, and relations are retrieved for a bounding box that covers a small portion of England.
While the result would include the nodes, ways, and relations as specified by the rules for the command, including the "England" relation, it would (fortuitously) not include every node and way in England. If desired, the nodes and ways referenced by the "England" relation could be retrieved by their respective IDs.
Retrieving GPS tracks
The following command returns, in GPX format, the GPS track points that are inside a given bounding box.
GET /api/0.5/trackpoints?bbox=, , , &page=
are used the same way as they are in the command to retrieve nodes, ways, and relations.
specifies which group of 5,000 points, or page, to return. Since the command does not return more than 5,000 points at a time, this parameter must be incremented—and the command sent again (using the same bounding box)—in order to retrieve all of the points for a bounding box that contains more than 5,000 points. When this parameter is 0 (zero), the command returns the first 5,000 points; when it is 1, the command returns points 5,001–10,000, etc.
Retrieve the first 5,000 points for a bounding box:
Retrieve the next 5,000 points (points 5,001–10,000) for the same bounding box:
Other Advanced Object Access Methods
The following additional methods are available to retrieve (possibly) more than one object. They are all GET methods, and the return payload is an XML document containing any number of elements per above DTDs. Some of these requests do not purely follow the REST schema because they take URL parameters.
Retrieving Object History
You can access the full history of any object.
Returns the current version of the object specified along with all known older versions. The
<objtype> may be one of node, way, or relation. This also works for deleted objects where the standard GET request would return a "Gone" error code.
Retrieving Multiple Objects
You can retrieve more than one object of the same type in one single call.
(Note the plural form in this call!) Takes one URL parameter named after the object type (which may be node, way, or relation) and containing a comma-separated list of object ids, e.g.
GET /api/0.5/ways?ways=35,99,123. Returns the objects found. Return code is 200 OK if at least one object matched, 401 Bad Request otherwise.
Finding Back References
You can find out which other objects reference a given object.
GET /api/0.5/node/<id>/ways GET /api/0.5/<objtype>/<id>/relations
The first call returns all ways containing the specified node. The second call returns all relations containing the specified object, where <objtype> is one of node, way, or relation.
Resolving Forward References
You can retrieve an object and all objects referenced by it.
This call is available for an <objtype> of way or relation. For a way, it will return the way specified plus the full XML of all nodes referenced by the way. For a relation, it will return the following:
- the relation itself
- all nodes, ways, and relations that are members of the relation
- plus all nodes used by ways from the previous step.
The same recursive logic is not applied to relations. This means: If relation r1 contains way w1 and relation r2, and w1 contains nodes n1 and n2, and r2 contains node n3, then a "full" request for r1 will give you r1, r2, w1, n1, and n2. Not n3.
Getting list of changed tiles
You can retrieve information about all the map tiles changed in a specified time period
This will fetch the list of tiles at zoom-16 changed in the last hour.
Parameters to this method include:
|zoom||12||The zoom level of the tiles to return information about|
|hours||1||Number of hours prior to the current time to report on|
|start||none||Start time of period to report on|
|end||none||End time of period to report on|
The maximum time span that can be chosen for reporting on is 24 hours.
Due to current limitations in the database schema this method will currently only notice changes made to nodes, so adding an existing node to a way or changing the tags on a way will not cause a change to be reported.
Searching for Objects by Tag
You can search for objects based on their tags.
GET /api/0.5/ways/search?type=<type>&value=<value> GET /api/0.5/relations/search?type=<type>&value=<value> GET /api/0.5/search?type=<type>&value=<value>
The first two calls search for ways, and relations specifically while the last one searches for any kind of object. The searching of nodes (ie GET /api/0.5/nodes/search?type=<type>&value=<value>) is currently deactivated as it impacts badly on API performance when the search query is poor or too encompassing.
Use a tag name for <type> and the desired tag value for <value>. (Instead of the URL parameters "type" and "value", you can also use the shorthand "name=<name>" which is equivalent to "type=name&value=<name>").
This call searches for, and returns, objects using the following conditions:
- If type and value are given: Returns only objects that have the tag <type> with the value <value>.
- If type is given, but value is not: Returns only objects that have a <type> tag with any value.
- If value is given, but type is not: Returns only objects that have a (any) tag with the value <value>.
- If neither type nor value is given: Returns arbitrary objects.
Comparison of keys and values is case insensitive, and you have to use UTF-8 encoding if your search values contain special characters.
Note that you cannot combine search requests with "and" or "or" - you can only use one condition at a time. Nor is it possible to limit a search to a certain bounding box.
The call returns a maximum of 100 matching ways, and 100 matching relations. For each way returned, all nodes referenced by the way are also returned (even if that pushes the total number of nodes beyond 2000). Relation members are not automatically returned.
If nothing is found, an empty document is returned.
The return code is always 200 OK.
- This operation is very slow. If you do not require current data, use the OsmXAPI instead which specializes in these kinds of operation and also permits the searching of nodes which is currently disabled in the OSM API. If you are interested in named objects, also check out the NameFinder as an alternative.
Methods for GPX Traces
See #Retrieving GPS tracks above, for retrieving all traces within a bounding box.
You can upload a GPX file through the API:
This is the only API call using the POST method. It expects the following POST parameters in a multipart/form-data HTTP message:
|file||The GPX file containing the track points. Note that for successful processing, the file must contain trackpoints (<trkpt>), not only waypoints, and the trackpoints must have a valid timestamp. Since the file is processed asynchronously, the call will complete successfully even if the file cannot be processed. The file may also be a .tar, .tar.gz or .zip containing multiple gpx files, although it will appear as a single entry in the upload log.|
|description||The trace description.|
|tags||A string containing tags for the trace.|
|public||1 if the trace is public, 0 if not.|
HTTP basic authentication is required.
You access a GPX file's details and download the full file:
GET /api/0.5/gpx/<id>/details GET /api/0.5/gpx/<id>/data
HTTP basic authentication is required, although theoretically these calls should be allowed without authentication if the trace is marked public. If the trace is not public, only the owner may access the data.
Example "details" response:
<?xml version="1.0" encoding="UTF-8"?> <osm version="0.5" generator="OpenStreetMap server"> <gpx_file id="38698" name="rathfarnham_churchtown_nutgrove.gpx" lat="53.285644054" lon="-6.238367558" user="robfitz" public="true" pending="false" timestamp="2007-09-13T23:28:41+01:00"/> </osm>
The "data" response will be the exact file uploaded.
Methods for User Data
Unless noted otherwise, all user-specific API calls require authentication and operate on the currently authenticated user account. That's why they don't normally have an explicit "username" parameter.
The OSM server supports storing arbitrary user preferences. This can be used by editors, for example, to offer the same configuration wherever the user logs in, instead of a locally-stored configuration.
You can retrieve the list of current preferences using
this returns an XML document of the form
<osm version="0.5" generator="OpenStreetMap server"> <preferences> <preference k="somekey" v="somevalue" /> ... </preferences> </osm>
The same structure can be used to upload preferences (using the PUT method instead of GET). All existing preferences are replaced by the newly uploaded set.
Also possible is to PUT a single preference using
PUT /api/0.5/user/preferences/[your_key] (without the brackets)
in this instance, the payload of the request should only contain the value of the preference, i.e. not XML formatted.
The PUT call returns HTTP response code 406 (not acceptable) if the same key occurs more than once, and code 413 (request entity too large) if you try to upload more than 150 preferences at once. The sizes of the key and value are limited to 255 characters.
|id, <id>, ref||64-Bit||Unsigned Integer||Unique within the database for the object type.|
|bllon||-180 to +180 degrees||Float||Longitude of the bottom left corner of the bounding box (minimum longitude)|
|bllat||-90 to +90||Float||Latitude of the bottom left corner of the bounding box (minimum latitude)|
|trlon||-180 to +180 degrees||Float||Longitude of the top right corner of the bounding box (maximum longitude)|
|trlat||-90 to +90 degrees||Float||Latitude of the top right corner of the bounding box (maximum latitude)|