{"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\n```py\nimport httpx\nimport os\n\n# Create a new map\nresponse = httpx.post(\n \"https://api.mundi.ai/api/maps/create\",\n json={\"title\": \"My New Map\"},\n headers={\"Authorization\": f\"Bearer {os.environ['MUNDI_API_KEY']}\"}\n)\nresult = response.json()\n```\n\nMundi.ai is below the v1.0.0 release. Backwards compatibility should be achieved by pinning Mundi to a specific\ncommit when self-hosting. In the near future, versioned API routes will guarantee backwards compatibility with\nsemver.\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.\n\nThis endpoint returns both a map id `id` and project id `project_id`. Projects\ncan contain multiple map versions (\"maps\"), unattached layer data, and details\na history of changes to the project. Each edit will create a new map version.\n\nAccepts `title` in the request body.\n\n```py\nimport httpx\nimport os\n\n# Create a new map\nresponse = httpx.post(\n \"https://api.mundi.ai/api/maps/create\",\n json={\"title\": \"My New Map\"},\n headers={\"Authorization\": f\"Bearer {os.environ['MUNDI_API_KEY']}\"}\n)\nresult = response.json()\n```\n\n# Likely JSON output:\n# {\n# \"id\": \"M_abc123def456\",\n# \"project_id\": \"P_xyz789ghi012\",\n# \"title\": \"My New Map\",\n# \"created_on\": \"2025-08-29T12:34:56.789Z\",\n# \"map_link\": \"https://app.mundi.ai/projects/P_xyz789ghi012\"\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.", "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"}}}}