{"openapi": "3.1.0", "info": {"title": "Mundi.ai Developer API", "summary": "Mundi.ai has a developer API for creating, editing, and sharing maps and map data.", "description": "\nMundi is a customizable, open source web GIS and can be operated via API just like it can be used as a web app. You can [programatically create maps](/developer-api/operations/create_map/), [upload geospatial data](/developer-api/operations/upload_layer_to_map/) (vectors, raster, point clouds), and share map links or embed maps in other web applications.\n\nMundi's API is both available as a [hosted cloud service](https://mundi.ai) or\n[a self-hosted set of Docker images](https://github.com/buntinglabs/mundi.ai), open source under the AGPLv3 license.\n\nTo get started, create an account at [Mundi.ai](https://app.mundi.ai) and create a new API key [here](https://app.mundi.ai/settings/api-keys).\nWhen sending requests, set the `Authorization` header to `Bearer YOUR_API_KEY`. API keys start with `sk-...`. Never share your API keys.\n\n```py\n# 1. create a new map project\ncreated_map = httpx.post(\n \"https://api.mundi.ai/api/maps/create\",\n json={\"title\": \"US political boundaries\"},\n headers={\"Authorization\": f\"Bearer {os.environ[\"MUNDI_API_KEY\"]}\"},\n).json()\nmap_id, project_id = created_map[\"id\"], created_map[\"project_id\"]\n\n# 2. upload a GeoJSON file as a layer on that map\nwith open(\"counties.geojson\", \"rb\") as f:\n upload = httpx.post(\n f\"https://api.mundi.ai/api/maps/{map_id}/layers\",\n files={\"file\": (\"counties.geojson\", f, \"application/geo+json\")},\n data={\"layer_name\": \"US Counties\", \"add_layer_to_map\": True},\n headers={\"Authorization\": f\"Bearer {os.environ[\"MUNDI_API_KEY\"]}\"},\n ).json()\n\n# 3. link to view the map with the uploaded layer\nprint(f\"https://app.mundi.ai/project/{project_id}/{map_id}\")\n```\n", "termsOfService": "https://buntinglabs.com/legal/terms", "contact": {"name": "Bunting Labs", "url": "https://buntinglabs.com/"}, "version": "0.0.1"}, "paths": {"/api/maps/create": {"post": {"tags": ["Maps"], "summary": "Create a new map", "description": "Creates a new map project. Projects contain multiple map versions (\"maps\"),\nunattached layer data, and a history of changes to the project. Each edit will\ncreate a new map version.\n\nAccepts `title` in the request body. Returns overarching project id\n`project_id` and initial map version id `id`.\n\n```py\nresult = httpx.post(\n \"https://api.mundi.ai/api/maps/create\",\n json={\"title\": \"Brazilian catchment areas\"},\n headers={\"Authorization\": f\"Bearer {os.environ['MUNDI_API_KEY']}\"}\n).json()\n\nassert result == {\n \"title\": \"Brazilian catchment areas\",\n \"created_on\": \"2025-08-29T12:34:56.789Z\",\n \"map_link\": \"https://app.mundi.ai/project/PGJSkB1zj7fT\",\n \"id\": \"Mabc123def456\",\n \"project_id\": \"PGJSkB1zj7fT\"\n}\n```", "operationId": "create_map", "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MapCreateRequest"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MapResponse"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/maps/{original_map_id}/layers": {"post": {"tags": ["Maps"], "summary": "Upload file as layer", "description": "Uploads spatial data, processes it, and adds it as a layer to the specified map.\n\nSupported formats:\n- Vector: Shapefile (as .zip), GeoJSON, GeoPackage, FlatGeobuf\n- Raster: GeoTIFF, DEM\n- [Point cloud](/guides/visualizing-point-clouds-las-laz/): LAZ, LAS\n\nOnce uploaded, Mundi transforms, reprojects, styles, and creates optimized formats for display in the browser.\nVector data is converted to [PMTiles](https://docs.protomaps.com/pmtiles/) while raster data is converted to\n[cloud-optimized GeoTIFFs](https://cogeo.org/). Point cloud data is compressed to LAZ 1.3.\n\nReturns the new layer details including its unique layer ID. The layer can optionally not be added to the map,\nbut will be faster to add to an existing map later.\n\n```py\nwith open(\"brazil_watersheds.gpkg\", \"rb\") as f:\n # project ID is PGJSkB1zj7fT, previous map ID is M4NzE8rk4FZS\n result = httpx.post(\n f\"https://api.mundi.ai/api/maps/M4NzE8rk4FZS/layers\",\n files={\"file\": (\"brazil_watersheds.gpkg\", f, \"application/octet-stream\")},\n data={\"layer_name\": \"Amazon Basin Watersheds\", \"add_layer_to_map\": True},\n headers={\"Authorization\": f\"Bearer {os.environ['MUNDI_API_KEY']}\"}\n ).json()\n\nassert result[\"name\"] == \"Amazon Basin Watersheds\"\nassert result[\"dag_child_map_id\"] == \"M4NzE8rk4FZS\"\n# use result[\"dag_child_map_id\"] as the new map id, and view this new uploaded layer\n# by navigating to https://app.mundi.ai/project/PGJSkB1zj7fT/M4NzE8rk4FZS\nsubprocess.run([\"open\", \"https://app.mundi.ai/project/PGJSkB1zj7fT/M4NzE8rk4FZS\"])\n```", "operationId": "upload_layer_to_map", "parameters": [{"name": "original_map_id", "in": "path", "required": true, "schema": {"type": "string"}}], "requestBody": {"required": true, "content": {"multipart/form-data": {"schema": {"$ref": "#/components/schemas/Body_upload_layer_to_map"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/LayerUploadResponse"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/maps/{map_id}/render.png": {"get": {"tags": ["Maps"], "summary": "Render a map as PNG", "description": "Renders a map as a static PNG image, including layers and their symbology.\n\nIf no `bbox` is provided, the extent defaults to the smallest extent that contains\nall layers with well-defined bounding boxes. `bbox` must be in the format `xmin,ymin,xmax,ymax` (EPSG:4326).\n\nWidth and height are in pixels.", "operationId": "render_map_to_png", "parameters": [{"name": "map_id", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "bbox", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}]}}, {"name": "width", "in": "query", "required": false, "schema": {"type": "integer", "default": 1024}}, {"name": "height", "in": "query", "required": false, "schema": {"type": "integer", "default": 600}}, {"name": "bgcolor", "in": "query", "required": false, "schema": {"type": "string", "default": "#ffffff"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/layers/{layer_id}/style": {"post": {"tags": ["Layers"], "summary": "Set layer style", "description": "Sets a layer's active style in the map to a MapLibre JSON layer list.\n\nThis operation will fail if the style is invalid according to the\n[style spec](https://maplibre.org/maplibre-style-spec/layers/) and the source\ndefinition.\n\nReturns the created style_id and confirmation that it has been applied.", "operationId": "set_layer_style", "parameters": [{"name": "layer_id", "in": "path", "required": true, "schema": {"type": "string"}}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SetStyleRequest"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SetStyleResponse"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/projects/{project_id}": {"delete": {"tags": ["Maps"], "summary": "Delete a map", "description": "Marks a map project as deleted (uses soft delete).", "operationId": "delete_project", "parameters": [{"name": "project_id", "in": "path", "required": true, "schema": {"type": "string"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}}, "components": {"schemas": {"Body_upload_layer_to_map": {"properties": {"file": {"type": "string", "format": "binary"}, "layer_name": {"type": "string"}, "add_layer_to_map": {"type": "boolean", "default": true}}, "type": "object", "required": ["file"], "title": "Body_upload_layer_to_map"}, "HTTPValidationError": {"properties": {"detail": {"items": {"$ref": "#/components/schemas/ValidationError"}, "type": "array"}}, "type": "object", "title": "HTTPValidationError"}, "LayerUploadResponse": {"properties": {"dag_child_map_id": {"type": "string", "description": "The ID of the new map created that contains the changes. Use this ID for further operations on the modified map."}, "dag_parent_map_id": {"type": "string", "description": "The ID of the original map which was copied to create the new map."}, "id": {"type": "string", "description": "Unique identifier for the newly uploaded layer"}, "name": {"type": "string", "description": "Display name of the layer as it appears in the map"}, "type": {"type": "string", "description": "Layer type (vector, raster, or point_cloud)"}, "url": {"type": "string", "description": "Direct URL to access the layer data (PMTiles for vector, COG for raster)"}, "message": {"type": "string", "description": "Status message confirming successful upload", "default": "Layer added successfully"}}, "type": "object", "required": ["dag_child_map_id", "dag_parent_map_id", "id", "name", "type", "url"], "title": "LayerUploadResponse"}, "MapCreateRequest": {"properties": {"title": {"type": "string", "description": "Display name for the new map", "default": "Untitled Map"}}, "type": "object", "title": "MapCreateRequest"}, "MapResponse": {"properties": {"id": {"type": "string", "description": "Unique identifier for the map"}, "project_id": {"type": "string", "description": "ID of the project containing this map. Projects can contain multiple related maps."}, "title": {"type": "string", "description": "Display name of the map"}, "created_on": {"type": "string", "description": "ISO timestamp when the map was created"}, "map_link": {"type": "string", "description": "URL to view the map project"}}, "type": "object", "required": ["id", "project_id", "title", "created_on", "map_link"], "title": "MapResponse"}, "SetStyleRequest": {"properties": {"maplibre_json_layers": {"items": {}, "type": "array", "description": "Array of MapLibre layer objects like fill, line, symbol [(style spec v8)](https://maplibre.org/maplibre-style-spec/)"}, "map_id": {"type": "string", "description": "Map ID where this new style will be applied"}}, "type": "object", "required": ["maplibre_json_layers", "map_id"], "title": "SetStyleRequest"}, "SetStyleResponse": {"properties": {"style_id": {"type": "string", "description": "ID of the created style"}, "layer_id": {"type": "string", "description": "ID of the layer the style was applied to"}}, "type": "object", "required": ["style_id", "layer_id"], "title": "SetStyleResponse"}, "ValidationError": {"properties": {"loc": {"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, "type": "array", "title": "Location"}, "msg": {"type": "string", "title": "Message"}, "type": {"type": "string", "title": "Error Type"}}, "type": "object", "required": ["loc", "msg", "type"], "title": "ValidationError"}}}}