Skip to content

API Documentation (DEPRECATED)

Martijn van Exel edited this page Dec 2, 2016 · 2 revisions

This documentation is for MapRoulette 1 which is no longer active. Please see the MapRoulette 2 API documentation for up to date documentation.

Challenge Administration API

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.


Bulk List Task Statuses

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.

Responses

HTTP Status Code What happened Response Body
200 OK See example below
404 Not Found See example below

Example Response

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
}

Create or update challenge

POST /api/admin/challenge/<slug>

Creates a challenge

PUT /api/admin/challenge/<slug>

Updates a challenge.

Payload

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:

  1. POST the challenge creation, omitting "active": true
  2. Post some tasks to the challenge
  3. PUT an update to the challenge, setting active to true.

If you update, supply only the properties you want to change. For example, if you want to deactivate a challenge, do:

{
  "active": false
}

Properties

  • 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

Create or update a task

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.

Payload

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).

Examples

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"
}

Update multiple tasks at once

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.

Payload

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

Example

[
    {
        "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)"
    }
]

Statistics API

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.


Summary Statistics

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>

Example Response

{
    "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

Example Response

[
    {
        "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

Example Response

[
    {
        "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)

Example Response

[
    {
        "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
        }
    }
]

Client API

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.


List Users

GET /api/users

Example response

[
    {
        "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
    }
]

List Challenges

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.

Example response

[
  {
    "difficulty": 3,
     "slug": "test1",
     "islocal": false,
     "title": "Test Challenge 1"
  },
   {
    "difficulty": 1,
     "slug": "test2",
     "islocal": false,
     "title": "Test Challenge 2"
  },
]

Get Challenge Details

GET /api/challenge/<slug>

Metadata on a challenge identified by slug

Example Response

{
  "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 summary total / available for a Challenge

GET /api/challenge/<slug>/summary

Summary statistics about a challenge identified by slug, to display total / available counts in the main MapRoulette UI

Example Response

{
  "available": 99,
  "total": 100
}

Get Challenge Polygon

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.

Example Response

{
  "type": "Polygon",
  "coordinates": [
    [
      [
        -87.0,
         20.0
      ],
       [
        -87.0,
         21.0
      ],
       [
        -88.0,
         21.0
      ],
       [
        -88.0,
         20.0
      ],
       [
        -87.0,
         20.0
      ]
    ]
  ]
}

Get a random task for a challenge

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 as NEARBUFFER in maproulette.cfg) of the point lon|lat). Note that all 'distances' are in degrees

  • assign={0|1} To assign the task to a user or not. Defaults to 1 (True)

Example Response

{
  "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 basic information for a specific task

GET /api/challenge/<slug>/task/<task_identifier>

Get a task and its detailed information identified by task_identifier for the challenge identified by slug

Example Response

{
  "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"
}

Update a task

PUT /api/challenge/<slug>/task/<task_identifier>

Update the task identified by task_id for the challenge identified by slug.

Example

{
 'identifier': 123456,
 }

Get the geometries for a task

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.

Example Response

{
  "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
      }
    }
  ]
}