Skip to content

Instantly share code, notes, and snippets.

@mvexel
Created May 29, 2014 19:15
Show Gist options
  • Save mvexel/09ddfd63b4543ee9d02b to your computer and use it in GitHub Desktop.
Save mvexel/09ddfd63b4543ee9d02b to your computer and use it in GitHub Desktop.
new-api-docs

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.

Example Response

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

Create or update challenge

PUT /api/admin/challenge/<slug>

Creates or updates 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. Post 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

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

Updates the properties of a single task, or creates it if it does not exist

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

PUT /api/admin/challenge/<slug>/tasks

Updates the properties of one or more tasks, or creates them if they do not exist.

Payload

The payload is JSON representing an array of individual task dictionaries, see above for the definition of the single task dictionary.

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

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

Statistics

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

Example Response

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

Example Response

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

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

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.

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

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.

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

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

POST /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
      }
    }
  ]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment