{"id":13558469,"url":"https://github.com/maproulette/maproulette-backend","last_synced_at":"2026-04-01T18:45:54.899Z","repository":{"id":5673231,"uuid":"53699564","full_name":"maproulette/maproulette-backend","owner":"maproulette","description":"MapRoulette back-end / API","archived":false,"fork":false,"pushed_at":"2026-03-19T01:58:43.000Z","size":5973,"stargazers_count":52,"open_issues_count":127,"forks_count":40,"subscribers_count":8,"default_branch":"main","last_synced_at":"2026-03-19T05:37:51.403Z","etag":null,"topics":["maproulette","openstreetmap","osm"],"latest_commit_sha":null,"homepage":"","language":"Scala","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/maproulette.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2016-03-11T22:07:54.000Z","updated_at":"2026-03-18T15:33:41.000Z","dependencies_parsed_at":"2023-11-30T07:29:03.381Z","dependency_job_id":"f272e6a6-0aa3-4a5a-ab93-ca5ac99547c4","html_url":"https://github.com/maproulette/maproulette-backend","commit_stats":{"total_commits":965,"total_committers":32,"mean_commits":30.15625,"dds":0.7005181347150259,"last_synced_commit":"d9239b7369f8ce9ece433bfef89167174a29b460"},"previous_names":["maproulette/maproulette2"],"tags_count":231,"template":false,"template_full_name":null,"purl":"pkg:github/maproulette/maproulette-backend","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maproulette%2Fmaproulette-backend","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maproulette%2Fmaproulette-backend/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maproulette%2Fmaproulette-backend/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maproulette%2Fmaproulette-backend/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/maproulette","download_url":"https://codeload.github.com/maproulette/maproulette-backend/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maproulette%2Fmaproulette-backend/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31290947,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-01T13:12:26.723Z","status":"ssl_error","status_checked_at":"2026-04-01T13:12:25.102Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["maproulette","openstreetmap","osm"],"created_at":"2024-08-01T12:04:58.352Z","updated_at":"2026-04-01T18:45:54.888Z","avatar_url":"https://github.com/maproulette.png","language":"Scala","funding_links":[],"categories":["Scala","others"],"sub_categories":[],"readme":"# MapRoulette API\n[![Build Status](https://github.com/maproulette/maproulette-backend/actions/workflows/scala.yml/badge.svg)](https://github.com/maproulette/maproulette-backend/actions?query=branch%3Amain)\n[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=maproulette_maproulette2\u0026metric=alert_status)](https://sonarcloud.io/dashboard?id=maproulette_maproulette2)\n![GitHub release (latest by date)](https://img.shields.io/github/v/release/maproulette/maproulette-backend)\n\nWelcome to the repository for the MapRoulette back-end server code. The MapRoulette back-end exposes the MapRoulette API, which the MapRoulette front-end web application depends on. The source code for the web application is in [a separate repository](https://github.com/maproulette/maproulette3).\n\n**If you just want to deploy the MapRoulette back-end, [we have a 🚢 Docker image 🚢 for that](https://github.com/maproulette/maproulette2-docker)**. This is especially useful if you want to contribute to the MapRoulette front-end and don't intend to touch the back-end.\n\n## Requirements\n\nMapRoulette depends on several technologies for building and running the project:\n\n* Java 17 JDK\n* PostgreSQL with PostGIS\n* [Scala Build Tool](https://www.scala-sbt.org/download.html)\n\n## Setup\n\nMapRoulette is a complex tool and depends on several other tools\n([Mapillary](https://www.mapillary.com/),\n[Overpass API](https://overpass-api.de/),\n[OpenStreetMap](https://www.openstreetmap.org/),\nPostgreSQL, and others) that need to be correctly configured within the application's\n[HOCON configuration](https://github.com/lightbend/config/blob/main/HOCON.md) files.\n\nThe initial setup is not trivial, so the documentation is split to specific steps where each step can be easily validated.\nThe validation at each step is a helpful sanity check so please, regardless of your experience, **take the time to verify along the way**.\n\n---\n\n### Step 1: Installing Tools\n\nTo get started you'll need to install Docker, JDK 17, and sbt.\n\n#### Docker\n\nDocker is a virtualization tool and feel free to use\n[Docker Desktop](https://docs.docker.com/get-docker/),\nor [Podman](https://podman.io/),\nor even [Rancher Desktop](https://rancherdesktop.io/).\n\n#### JDK 17 and sbt\n\n[sdkman](https://sdkman.io/install) is a great tool to install a specific build of the JDK to keep your environment\nas similar to production as possible. It also handles fetching x8664 and aarch64 builds automatically.\nFollow the installation steps and install the JDK and sbt using a command similar to:\n\n* `sdk install java 17.0.15-tem`\n* `sdk install sbt 1.11.2`\n\n#### Validation\n\nWithin a terminal check that docker, javac, and sbt are working.\n\n* `docker run hello-world`\n  * Verify docker works\n* `javac -version`\n  * Verify javac is JDK 17\n  * Apple Silicon: Verify that the JDK is an aarch64 build and not x8664.\n* `sbt -version`\n\n---\n\n### Step 2: Setup PostGIS and MapRoulette DB Configuration\n\n#### PostGIS Container\n\nMapRoulette development assumes a database is running on the local system within a docker container.\n\nBelow is a sample command to run a PostGIS database within a container and sets necessary ports/credentials.\n\n* **NOTE: Apple Silicon:** Use `ghcr.io/baosystems/postgis:17-3.5` docker image since postGIS does not yet publish aarch64 images.\n* NOTE: No volume mount is used so the database's data will be deleted when the container is deleted.\n  If you'd like to keep the data external of the container, be sure to add `--volume \"/some/path/here/postgres-data\":/var/lib/postgresql/data` to the docker call.\n\n```sh\ndocker run \\\n    -d \\\n    -p 5432:5432 \\\n    --name maproulette-postgis \\\n    --restart unless-stopped \\\n    --shm-size=512MB \\\n    -e POSTGRES_DB=maproulette-db \\\n    -e POSTGRES_USER=maproulette-db-user \\\n    -e POSTGRES_PASSWORD=maproulette-db-pass \\\n    postgis/postgis:17-3.5\n```\n\n* NOTE: If there's a port conflict, you probably have another pg instance running. Check with `docker ps`.\n* NOTE: It is helpful to see logs with `docker logs -f maproulette-postgis`\n* NOTE: To stop the container, that'd be `docker stop maproulette-postgis`. Then you can start it again using `docker start maproulette-postgis`.\n\n#### Configuration\n\nClone the maproulette-backend repository and `cd` to that directory, and create `conf/dev.conf` using the example file:\n\n```sh\n    cp conf/dev.conf.example conf/dev.conf\n```\n\nEdit `conf/dev.conf` and set db.default based on the previous step's POSTGRES_DB, POSTGRES_USER,\nand POSTGRES_PASSWORD values:\n\n```text\ndb.default {\n  url=\"jdbc:postgresql://localhost:5432/maproulette-db\"\n  username=\"maproulette-db-user\"\n  password=\"maproulette-db-pass\"\n}\n```\n\nAlternatively, you can configure the backend using environment variables. The\nvariables `MR_DATABASE_URL`, `MR_DATABASE_USERNAME` and `MR_DATABASE_PASSWORD`\ncontrol the same values as the config parameters shown above. Look in `conf/\napplication.conf` for what else can be overridden via environment variables.\nAny pattern like `${?FOO}` in that file will be replaced with the value of the\nenvironment variable `FOO` at runtime.\n\nNow start the MapRoulette server! Run this command in a terminal, **not within Intellij/vscode**:\n\n`sbt -J-Xms4G -J-Xmx4G -J-Dconfig.file=./conf/dev.conf -J-Dlogger.resource=logback-dev.xml run`\n\nThere should be some output that looks like this:\n\n    --- (Running the application, auto-reloading is enabled) ---\n    [info] p.c.s.AkkaHttpServer - Listening for HTTP on /0:0:0:0:0:0:0:0:9000\n    (Server started, use Enter to stop and go back to the console...)\n\nThat's the expected output. And when you need, like it says, use Enter to stop the server.\n\n#### Step 2 - Validation\n\nOpen a new terminal so that the MapRoulette server is not stopped. Verify:\n\n* Check that the database is running, `docker inspect -f '{{.State.Running}}' maproulette-postgis`\n* Start the MapRoulette server if it's not already running (see the previous section for the `sbt` command)\n* Verify that the local [Swagger docs load in a web browser](http://127.0.0.1:9000/docs/)\n* Do this GET call to get the list of challenges: `curl http://127.0.0.1:9000/api/v2/challenges`\n  * The result may be an empty array or some data, as long as it's not a failed call\n  * Tip: the response can be formatted by piping to `jq`\n* Open the terminal that has `sbt` running the server. Verify that there are log messages printed.\n\nIf there's a failure at this point _READ THE LOG MESSAGES_, checking for simple setup issues.\n\nA few known setup misconfigurations could be:\n\n* Does the server log that it can't communicate with the database? \"HikariPool Connection is not available, request timed out after 30000ms\"\n  * Check the `conf/dev.conf` MapRoulette server configuration file for typos, accidental setting overrides, etc\n  * Check that the MapRoulette server conf and postgis are using the same database, user, password.\n* Recursive loading of Guice injected object: 'java.lang.IllegalStateException: Recursive load of: org.maproulette.framework.service.ServiceManager.\u003cinit\u003e()'\n  * We've seen this with Apple Silicon aarch64 systems. Possibly related to mixing aarch64 and x8664 JDKs. Intellij 2022.3 pre-release seems to work fine\n* Having some other issue?\n  * Please file a GitHub issue with a detailed description on what was tried and include the error message.\n\n---\n\n### Step 3: Setup OAuth 2.0 Login and Run the front-end GUI\n\nWith the database and MapRoulette server working together, it's now time to get the front-end login workflow working!\n\nHigh level the user visits to MapRoulette, clicks 'login' and is sent to OpenStreepMap to login then, after authentication, MapRoulette is able to make OSM changes of behalf\nof the user. This is done by registering the local dev instance of MapRoulette as an OSM OAuth 2.0 Application to create keys, and then\nthe those keys are pasted into the MapRoulette server configuration. More details on how OSM uses OAuth is on\nthe [OpenStreetMap OAuth documentation](https://wiki.openstreetmap.org/wiki/OAuth).\n\n#### Register localhost as an OpenStreetMap OAuth 2.0 Application\n\nWithin OpenStreetMap, MapRoulette needs to be setup as an \"OAuth 2 Application\" so that changes in MapRoulette are associated\nwith a user's OSM account.\n\n1. Login to the [development OpenStreetMap server](https://master.apis.dev.openstreetmap.org) (make an account if needed)\n1. In the top right, click the user and go to `My Settings`\n1. Then click `OAuth 2 applications` tab\n1. At the bottom of the OAuth2 settings page, click `Register new application`\n1. Register using these settings:\n   * `Name`: maprouletteDevLocalhost (any name is fine)\n   * `Redirect URIs`: \u003chttp://127.0.0.1:9000\u003e\n   * `Confidential application`: Keep this checked\n   * `Permissions`: Select\n     * `Read user preferences`\n     * `Modify user preferences` (MapRoulette saves the user's MR API key in OSM)\n     * `Modify the map` (MapRoulette tasks edit the map)\n\nClick `Register` and note the displayed Client ID and the Client Secret. Copy and paste those keys into the MapRoulette\n`conf/dev.conf` file's osm section where it has \"CHANGE_ME\":\n\n```text\nosm {\n  # The OSM OAuth 2.0 Client ID and Client Secret, respectively\n  consumerKey=\"CHANGE_ME\"\n  consumerSecret=\"CHANGE_ME\"\n}\n```\n\nStop and start the MapRoulette server to load the updated configuration.\n\n#### Run the MapRoulette front-end\n\nClone the maproulette3 repository and follow the steps in the [DEVELOPMENT.md \"Run the UI from Docker\" section](https://github.com/maproulette/maproulette3/blob/master/DEVELOPMENT.md#run-the-ui-from-docker).\nBe sure to execute the `docker run` step that starts the UI.\n\n#### Step 3 - Validation\n\n* Open \u003chttp://127.0.0.1::3000/\u003e and attempt to log in\n  * This should redirect to the development OpenStreetMap server and redirect back to MapRoulette\n  * The username should show in the top-right corner\n* Create a new Project (this is the easiest way to verify), or a new challenge, or update a project/challenge/task,\n  or do some other work that causes various request types to the MapRoulette server\n\nKnown setup issues:\n\n* Exceptions with 'java.lang.NumberFormatException: For input string: \"CHANGE_ME\"'. Edit the `conf/dev.conf` and verify that these are not \"CHANGE_ME\":\n  * `osm.consumerKey`\n  * `osm.consumerSecret`\n  * `maproulette.super.key`\n  * `maproulette.super.accounts`\n\n---\n\n### Step 4: Intelllij Configuration\n\nThe server is working end-to-end on command line! Time to import into IntelliJ. Stop the running MapRoulette server from the previous step, if it's still running.\n\n* Open IntelliJ\n* Click `Plugins` and verify that the Scala plugin is installed\n* Click `Open` and navigate to the MapRoulette source directory and `Open as Project`\n  * The project will load\n* Create a new `sbt Task` runtime configuration\n  * Name it `MapRoulette Server` or similar\n  * Set Tasks to  `run`\n  * Uncheck 'Use sbt shell`\n  * Use these `VM parameters`\n\n    ```text\n    -Xms4G\n    -Xmx4G\n    -Dconfig.file=./conf/dev.conf\n    -Dlogger.resource=logback-dev.xml\n    ```\n\n#### Step 4 - Validation\n\nOpen the front-end UI \u003chttp://localhost:3000/\u003e and attempt to log in. It should function.\n\n---\n\n---\n\n### Additional (Optional) Server Configuration\n\n* Open `dev.conf` in a text editor and change at least the following entries:\n    * `super.key`: a randomly chosen API key for superuser access\n    * `super.accounts`: a comma-separated list of OSM accound IDs whose corresponding MapRoulette users will have superuser access. Can be an empty string.\n    * `mapillary.clientId`: a [Mapillary Client ID](https://www.mapillary.com/dashboard/developers), needed if you want to use any of the Mapillary integrations.\n\n## Notes\n\n### Logging Levels\n\nDuring development, please set `-Dlogger.resource=logback-dev.xml` to have the best experience. The logback dev file sets\nmany items to the devel level and logs all HTTP request paths and response times.\n\nAny changes to the `conf/logback-dev.xml` will be loaded within about 5 seconds and a service restart is not needed.\n\nTo have all request _headers_ sent by the client logged, update the `conf/logback-dev.xml` \"org.maproulette.filters\" entry to TRACE.\n\n### Deploying on Windows\n\nWindows is not officially supported. However, there is an unofficial [setup guide](https://gist.github.com/3710d7f15534ec747423a3117cd7cc9c).\n\n### SMTP (email) configuration\n\nMapRoulette now supports transmission of emails, for example to inform users\nwhen they receive new in-app notifications. You will need access to an SMTP\nserver to send emails, and will also need to add SMTP configuration settings to\nyour configuration file (or whatever configuration mechanism you're using).\n`play.mailer.host` is the only required SMTP setting, but most SMTP servers\nwill also want a username and password.\n\n```\nplay.mailer.host = \"smtp.server.com\"\nplay.mailer.user = \"smtpusername\"\nplay.mailer.password = \"secret\"\n```\n\nMany additional SMTP configuration options are available -- see\n[play-mailer](https://github.com/playframework/play-mailer/blob/master/README.md)\nfor a full list.\n\n\u003e Note: If you're doing development, you can set `play.mailer.mock = yes` to\n\u003e simply log emails instead of transmitting them\n\nIt's also important that you set the `emailFrom` setting to the email address\nyou wish emails to come from, and that you ensure `publicOrigin` is set so that\nlinks in emails will properly point to your server.\n\n```\nemailFrom = \"maproulette@yourserver.com\"\npublicOrigin = \"https://www.yourserver.com\"\n```\n\nBy default, notification emails that are to be sent immediately are processed\nby a background job every 1 minute. Both the frequency and max number of emails\nto process in a single run can be controlled.\n\n```\nnotifications.immediateEmail.interval = \"1 minute\"\nnotifications.immediateEmail.batchSize = 10         # max emails per run\n```\n\nNotification emails that are to be sent as a digest are initially processed at\n8pm local server time by default, and then every 24 hours thereafter (i.e.\ndaily digests). Both of these settings can be customized. There is not\ncurrently a maximum limit to the number of emails for digest emails.\n\n```\nnotifications.digestEmail.startTime = \"20:00:00\"    # 8pm local server time\nnotifications.digestEmail.interval = \"24 hours\"     # once daily\n```\n\n## Creating new Challenges\n\n[The wiki for this repo](https://github.com/maproulette/maproulette-backend/wiki) has some information on creating challenges.\n\n[Challenge API](docs/challenge_api.md) has further information about creating challenges through the API.\n\nSee also the Swagger API documentation. You can view the documentation by going to the URL ```/docs/swagger-ui/index.html``` on any MapRoulette instance.\n\n## Dev Docs\n\n- [Creating Challenges](docs/challenge_api.md)\n- [Deployment](docs/deployment.md)\n- [Github Example](docs/github_example.md)\n- [GraphQL](docs/graphql.md)\n- [Tag Changes](docs/tag_changes.md)\n- [Testing](docs/testing.md)\n- [Routes](conf/v2_route/readme.md)\n\n## Contributing\n\nPlease fork the project and submit a pull request. See [Postman Docs](postman/README.md) for information on API Testing. The project is integrated with Travis-CI, so PR's will only be accepted once the build compiles successfully. MapRoulette also uses Scalafmt as it's code formatter. This is too keep the code style consistent across all developers. The check will be run first in Travis for the build, so if there are any code style issues it will fail the build immediately. IntelliJ should pick up the formatter and use Scalafmt automatically, however you can also use `sbt scalafmt` to format any and all code for you.\n\n## Contact\n\nBug and feature requests are best left as an issue right here on Github. For other things, contact maproulette@maproulette.org\n\nMapRoulette now also has a channel #maproulette on the [OSM US Slack community](https://osmus.slack.com).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaproulette%2Fmaproulette-backend","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmaproulette%2Fmaproulette-backend","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaproulette%2Fmaproulette-backend/lists"}