-
Notifications
You must be signed in to change notification settings - Fork 27
API Documentation (DEPRECATED)
This documentation is for MapRoulette 1 which is no longer active. Please see the MapRoulette 2 API documentation for up to date documentation.
This API is used by Challenge providers to update their challenges and their task queue. On MapRoulette.org, this API is accessible from localhost only, so you need an SSH tunnel into the MapRoulette server to access it. Contact the authors at maproulette@maproulette.org to learn more.
GET /api/admin/challenge/<slug>/tasks
Gets the current status for all Tasks in the Challenge identified by slug
Common statuses are:
- created - The task is created. This is set by default when a new task is created, no need to set it explicitly. This status can only be set from within MapRoulette
- fixed - The task has been fixed by a MapRoulette user. This status can only be set from within MapRoulette
- falsepositive - The task has been marked as a false positive by a MapRoulette user. This status can only be set from within MapRoulette
- skipped - The task has been skipped (looked at, but not fixed) by a MapRoulette user. This status can only be set from within MapRoulette
- deleted - The task is deleted because the problem disappeared outside of MapRoulette.
HTTP Status Code | What happened | Response Body |
---|---|---|
200 | OK | See example below |
404 | Not Found | See example below |
This is a typical response for a valid slug
that has tasks:
[
{
"status":"created",
"identifier":"fc295c3e-c717-4f3f-9bed-478f3ca91822"
},
{
"status":"created",
"identifier":"abd15516-3067-48e0-b250-aedbbd864a84"
},
{
"status":"created",
"identifier":"a1fe42a1-4d34-4577-a163-3f44e6041087"
},
{
"status":"created",
"identifier":"e8e9615d-7e28-4241-bab0-4383beca423e"
}
]
This is a typical response for a slug
that does not exist:
{
"message": "Not Found. You have requested this URI [/api/challenge/martijntest] but did you mean /api/challenge/<slug>/task/<identifier>/geometries or /api/challenge/<slug>/task or /api/challenge/<string:challenge_slug>/summary ?",
"status": 404
}
POST /api/admin/challenge/<slug>
Creates a challenge
PUT /api/admin/challenge/<slug>
Updates a challenge.
Here is an example:
{
"title": "Repair Motorways",
"description": "Repair all motorways",
"blurb": "For this challenge, the idea is to repair all motorways",
"help": "Repair the motorway where it is broken as indicated on the map",
"instruction": "Look at the map for broken pieces of way. Go into you editor and repair them as needed",
"active": true,
"difficulty": 2
}
It is usually a bad idea to make a challenge active upon creating it, because it will not yet have any tasks. A typical challenge creation cycle would be:
- POST the challenge creation, omitting
"active": true
- Post some tasks to the challenge
- PUT an update to the challenge, setting
active
totrue
.
If you update, supply only the properties you want to change. For example, if you want to deactivate a challenge, do:
{
"active": false
}
- title - the Challenge title in plain text required
- geometry - the task geometry (NOT YET IMPLEMENTED) optional
- description - longer challenge description in plain text optional
- blurb - a short blurb about this challenge in plain text optional
- help - a brief help text in plain text optional
- instruction - longer challenge instruction, can be HTML optional
- active - Is the challenge active or not? (true or false, defaults to false on creation) optional
- difficulty - Difficulty level (1: easy, 2: normal, 3: expert) optional
POST /api/admin/challenge/<slug>/task/<task_identifier>
Creates a single task.
PUT /api/admin/challenge/<slug>/task/<task_identifier>
Updates the properties of a single task.
The payload for this endpoint is a JSON representation of the new or updated task with its (updated) properties.
The properties that can be set on a task are:
-
geometries - the task geometries as GeoJSON. If the task geometries represent OSM objects, the OSM id should be in the geometry's
osmid
property. MapRoulette will then attempt to pre-select the appropriate ways and nodes in iD or JOSM. We will assume that a line feature maps to an OSM way, and a point feature to an OSM node. - instruction - The instruction text that is displayed when the task is loaded. Usually, this is set at Challenge level, but it can be overridden for individual tasks.
- status - The task status.
For an existing task, there are no required properties, so in theory you could supply {} and the task would just be touched.
For a new task, task geometries must be supplied, the rest is optional. The task geometries consist of the geometry itself, and optionally the OpenStreetMap ID of the object, if it corresponds to an OSM object. The geometry must be supplied as a nested GeoJSON serialization.
If you want to update a large number of tasks at once, please consider using the bulk task upload endpoint (see below).
This would be a typical payload for a new task being created, including a custom instruction:
{
"instruction" : "This is a hard task!",
"geometries" : {
"type": "FeatureCollection",
"features": [
{ "type": "Feature",
"geometry":
{ "type": "Point",
"coordinates": [-41.4710170873565, 31.235521774136]
},
"properties": {"osmid": 12345}
},
{ "type": "Feature",
"geometry":
{ "type": "LineString",
"coordinates": [[-88.72199, 30.39396], [-88.72135, 30.39395], [-88.72125, 30.3939]]
},
"properties": {"osmid": 23456}
}
]
}
}
This would be the payload for closing a task because the problem no longer exists:
{
"status" : "deleted"
}
POST /api/admin/challenge/<slug>/tasks
Creates one or more tasks.
PUT /api/admin/challenge/<slug>/tasks
Updates the properties of one or more tasks.
The API will accept at most 5000 task updates for a single request.
The payload is an array of JSON objects. Each JSON object represents a task that you want to upload. The JSON object is comprised of three keys: 'geometries', 'identifier', and 'instruction'.
The 'geometries' key contains a GeoJSON Feature Collection object that is comprised of various geometries (points, linestrings, polygons). Each geometry of the GeoJSON Feature Collection contains properties that are associated with the specific task. The 'identifier' key contains a unique string that MapRoulette can use to identify the uploaded task. The 'instruction' key contains the instruction you want included with your uploaded task.
If you want to update tasks that have been already fixed outside of MapRoulette, you can create a JSON object with the 'identifier' and 'status' set to "deleted".
Below is an example of a JSON payload that is acceptable by MapRoulette
[
{
"geometries": {
"features": [
{
"geometry": {
"coordinates": [
[
-82.46102,
27.94211
],
[
-82.46191,
27.94032
],
[
-82.46102,
27.94173
],
[
-82.46102,
27.94164
]
],
"type": "LineString"
},
"id": null,
"properties": {
"osmid": 10982458
},
"type": "Feature"
},
{
"geometry": {
"coordinates": [
-82.461465,
27.941024
],
"type": "Point"
},
"id": null,
"properties": {},
"type": "Feature"
}
],
"type": "FeatureCollection"
},
"identifier": "-245422134830019020515072624911431000923134125997",
"instruction": "1. [Zorro first = 5.4 degrees, second = 29.1 degrees]: 109824580003:109824580004:109824580005 (10982458,10982458,10982458)"
},
{
"geometries": {
"features": [
{
"geometry": {
"coordinates": [
[
-82.15821,
36.59216
],
[
-82.15896,
36.59273
],
[
-82.15876,
36.59271
],
[
-82.15911,
36.59294
]
],
"type": "LineString"
},
"id": null,
"properties": {
"osmid": 19628476
},
"type": "Feature"
},
{
"geometry": {
"coordinates": [
-82.15886,
36.59272
],
"type": "Point"
},
"id": null,
"properties": {},
"type": "Feature"
}
],
"type": "FeatureCollection"
},
"identifier": "-417552606960620657971358843856641634245254110348",
"instruction": "2. [Zorro first = 36.3 degrees, second = 32.2 degrees]: 196284740002:196111360001:196284760001 (19628474,19611136,19628476)"
}
]
The various statistics endpoints are used by a yet-to-be-published Maproulette Statistics page or set of pages.
All statistics endpoint can be parametrized with a time slice in the form ?start=YYYYMMDDHHMM&end=YYYYMMDDHHMM
, where the end timestamp is optional (if omitted, the currrent UTC time will be used) and the hours and minutes are optional (if omitted, 00:00 will be used.) Note that everything is stored as UTC times, so that is what you should input.
This gives a breakdown of task statuses overall, per challenge, or per user.
GET /api/stats
GET /api/stats/user/<user_id>
GET /api/stats/challenge/<challenge_id>
{
"alreadyfixed": 6,
"assigned": 377,
"available": 106,
"created": 157983,
"deleted": 4684,
"editing": 176,
"falsepositive": 73,
"fixed": 80,
"skipped": 170
}
You can also get a breakdown of these for all users:
GET /api/stats/users
GET /api/stats/challenge/<challenge_slug>/users
[
{
"User 1": {
"assigned": 33,
"editing": 11,
"falsepositive": 13,
"skipped": 24
}
},
{
"User 4": {
"alreadyfixed": 1,
"assigned": 21,
"editing": 5,
"falsepositive": 2,
"fixed": 1,
"skipped": 9
}
},
{
"User 9": {
"assigned": 1,
"editing": 1
}
},
{
"User 10": {
"assigned": 1,
"editing": 3,
"fixed": 3
}
}
]
Or by challenge:
GET /api/stats/challenges
GET /api/stats/user/<user_id>/challenges
[
{
"null": {
"assigned": 6,
"editing": 4
}
},
{
"badrampangles": {
"falsepositive": 2
}
},
{
"conn": {
"assigned": 3,
"editing": 4,
"skipped": 6
}
},
{
"missingroundabout": {
"assigned": 1,
"editing": 1,
"fixed": 1
}
},
{
"missingroundabouttest": {
"alreadyfixed": 1,
"assigned": 2,
"editing": 1,
"skipped": 3
}
}
]
This can be further broken down by day, as follows:
GET /api/stats/history
GET /api/stats/user/<user_id>/history
GET /api/stats/challenge/<challenge_slug>/history
GET /api/stats/challenge/<challenge_slug>/user/<user_id>/history
GET /api/stats/user/<user_id>/challenge/<challenge_slug>/history
(The last two requests are equivalent)
[
{
"2014-04-08T00:00:00": {
"alreadyfixed": 17,
"assigned": 322,
"created": 46112,
"editing": 146,
"falsepositive": 155,
"fixed": 47,
"skipped": 47
}
},
{
"2014-04-09T00:00:00": {
"alreadyfixed": 4,
"assigned": 430,
"available": 76,
"created": 1038,
"deleted": 1085,
"editing": 76,
"falsepositive": 27,
"fixed": 14,
"skipped": 362
}
},
{
"2014-04-10T00:00:00": {
"alreadyfixed": 9,
"assigned": 509,
"available": 35,
"created": 39234,
"deleted": 896,
"editing": 253,
"falsepositive": 47,
"fixed": 145,
"skipped": 280
}
}
]
This API is used by the web front end. It is not accessible or useful for anything beyond the MapRoulette client. You need to be authenticated against the OSM OAuth interface for all API calls.
All GET calls return JSON, or GeoJSON if the response is geo.
GET /api/users
[
{
"display_name": "Test User 0",
"id": 0
},
{
"display_name": "Test User 1",
"id": 1
},
{
"display_name": "Test User 2",
"id": 2
},
{
"display_name": "Test User 3",
"id": 3
},
{
"display_name": "Test User 4",
"id": 4
}
]
GET /api/challenges
Get a list of available challenges.
Note that by default, this only returns challenges that are local to the user. Local challenges are challenges whose polygons cover less than the threshold set in the MAX_SQ_DEGREES_FOR_LOCAL
configuration parameter, and the user's home location (as set in the OpenStreetMap user settings) lies within the challenge's polygon. See below for how to override this.
Parameters (all are optional):
-
contains=lon|lat
Return only challenges whose bounding polygon contains the point(lon, lat)
. This will not return any 'global' challenges (that do not have bounding polygons defined). -
difficulty=[1|2|3]
Return only challenges that are of a certain difficulty level, where 1 = easy, 2 = medium and 3 = hard. -
all=true
Force return all challenges, regardless whether they are local or not.
[
{
"difficulty": 3,
"slug": "test1",
"islocal": false,
"title": "Test Challenge 1"
},
{
"difficulty": 1,
"slug": "test2",
"islocal": false,
"title": "Test Challenge 2"
},
]
GET /api/challenge/<slug>
Metadata on a challenge identified by slug
{
"description": "This describes the fifth test challenge in more detail",
"done_dlg": {
"buttons": "",
"text": "This area is being loaded in your editor. Did you fix it?"
},
"instruction": "Five score years ago, a great American, in whose....",
"difficulty": 1,
"active": true,
"blurb": "This is the fifth test challenge",
"help": "Four score and seven years ago our fathers..."
}
GET /api/challenge/<slug>/summary
Summary statistics about a challenge identified by slug
, to display total / available counts in the main MapRoulette UI
{
"available": 99,
"total": 100
}
GET /api/challenge/<slug>/polygon
Get the polygon for the challenge identified by slug
. The polygon identifies the spatial extent of the challenge. Returns the entire world unless the challenge provider supplied a different extent.
{
"type": "Polygon",
"coordinates": [
[
[
-87.0,
20.0
],
[
-87.0,
21.0
],
[
-88.0,
21.0
],
[
-88.0,
20.0
],
[
-87.0,
20.0
]
]
]
}
GET /api/challenge/<slug>/task
Return a (random) task and its basic information for the challenge identified by slug
Parameters (all are optional):
-
near=lon|lat
Get challenges within a certain buffer (defined asNEARBUFFER
inmaproulette.cfg
) of the pointlon|lat
). Note that all 'distances' are in degrees -
assign={0|1}
To assign the task to a user or not. Defaults to 1 (True)
{
"text": "never forget that can be have devotion shall portion the of that which It as",
"id": "23d3c477-4918-47f3-b298-bea84ce55844",
"location": "-87.1990711924|20.2659097328"
}
GET /api/challenge/<slug>/task/<task_identifier>
Get a task and its detailed information identified by task_identifier
for the challenge
identified by slug
{
"text": "never forget that can be have devotion shall portion the of that which It as",
"id": "23d3c477-4918-47f3-b298-bea84ce55844",
"location": "-87.1990711924|20.2659097328"
}
PUT /api/challenge/<slug>/task/<task_identifier>
Update the task identified by task_id
for the challenge identified by slug
.
{
'identifier': 123456,
}
GET /api/challenge/<slug>/task/<task_identifier>/geometries
Get the geometries and their properties involved with the task identified by task_identifier
for the challenge identified by slug
.
{
"type": "FeatureCollection",
"features": [
{
"geometry": {
"type": "Point",
"coordinates": [
-87.199071192396,
20.26590973278159
]
},
"type": "Feature",
"id": null,
"properties": {
"selected": true,
"osmid": 326623386
}
},
{
"geometry": {
"type": "LineString",
"coordinates": [
[
-87.199071192396,
20.26590973278159
],
[
-87.19496891502735,
20.272784574293198
]
]
},
"type": "Feature",
"id": null,
"properties": {
"selected": true,
"osmid": 761469003
}
}
]
}