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 [email protected] 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.
[
{
"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"
}
]
PUT /api/admin/challenge/<slug>
Creates or updates 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
- Post 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
PUT /api/admin/challenge/<slug>/task/<task_identifier>
Updates the properties of a single task, or creates it if it does not exist
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. - 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"
}
PUT /api/admin/challenge/<slug>/tasks
Updates the properties of one or more tasks, or creates them if they do not exist.
The payload is JSON representing an array of individual task dictionaries, see above for the definition of the single task dictionary.
[
{
"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)"
}
]
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/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..."
}
The various statistics endpoints are used by the User / Challenge / Overall statistics views, as well as on the main interface to provide a quick total / unfixed count for challenges.
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.
GET /api/stats/challenge/<slug>/summary
Summary statistics about a challenge identified by slug
{
"available": 99,
"total": 100
}
GET /api/stats
Overall breakdown of task statuses.
GET /api/stats/user/<user_id>
Breakdown of task statuses for one user.
GET /api/stats/challenge/<challenge_id>
Breakdown of task statuses for one challenge.
{
"alreadyfixed": 6,
"assigned": 377,
"available": 106,
"created": 157983,
"deleted": 4684,
"editing": 176,
"falsepositive": 73,
"fixed": 80,
"skipped": 170
}
GET /api/stats/users
Overall breakdown of task statuses by user.
GET /api/stats/challenge/<challenge_slug>/users
Breakdown of task statuses by user for one challenge.
[
{
"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
}
}
]
GET /api/stats/history
Overall breakdown of task statuses by day.
GET /api/stats/user/<user_id>/history
Breakdown of task statuses by day for one user.
GET /api/stats/challenge/<challenge_slug>/history
Breakdown of task statuses by day for one challenge.
[
{
"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
}
}
]
GET /api/stats/challenges
Breakdown of task statuses by challenge.
GET /api/stats/user/<user_id>/challenges
Breakdown of task statuses by user and challenge.
[
{
"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
}
}
]
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"
}
POST /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
}
}
]
}