Back to Documentation

Public REST API

Use the Mapiry REST API to programmatically create and manage maps, locations, categories, tags, and layers from your own apps and automations

Last updated: March 1, 2026

Public REST API

The Mapiry REST API lets Pro users create and manage maps, locations, categories, tags, and layers programmatically — perfect for AI workflows, automations, and integrations with your own tooling.

Prerequisites

  • A Pro subscription (API access is a Pro feature)
  • An API key created in Account Settings

Interactive API Reference

Full API reference with live try-it-out: /docs/api


Authentication

All API requests require a Bearer token in the Authorization header:

Authorization: Bearer mk_live_your_key_here

API keys are scoped:

ScopeAllowed Methods
READ_ONLYGET
READ_WRITEGET, POST, PUT, DELETE

Creating an API Key

  1. Go to Account Settings → API Keys
  2. Click Create API Key
  3. Choose a name, scope, and optional expiration
  4. Copy the key immediately — it is shown only once

You can have up to 10 active API keys per account.

Base URL

https://mapiry.com/api/v1

Rate Limits

Rate limits are per account (shared across all your keys):

BucketLimit
General1,000 requests / hour
Map creation (POST /maps)50 requests / hour
Bulk location creation20 requests / hour

Every response includes rate limit headers:

X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 997
X-RateLimit-Reset: 1740000000

When a limit is exceeded you receive 429 Too Many Requests with a Retry-After header.


Endpoints Overview

Maps

MethodPathDescription
POST/mapsCreate a map
GET/maps/:mapIdGet a map
PUT/maps/:mapIdUpdate a map
DELETE/maps/:mapIdDelete a map

Locations

MethodPathDescription
GET/maps/:mapId/locationsList locations
POST/maps/:mapId/locationsCreate a location
POST/maps/:mapId/locations/bulkBulk create (up to 100)
GET/maps/:mapId/locations/:locIdGet a location
PUT/maps/:mapId/locations/:locIdUpdate a location
DELETE/maps/:mapId/locations/:locIdDelete a location

Categories

MethodPathDescription
GET/maps/:mapId/categoriesList categories
POST/maps/:mapId/categoriesCreate a category
PUT/maps/:mapId/categories/:catIdUpdate a category
DELETE/maps/:mapId/categories/:catIdDelete a category

Tags

MethodPathDescription
GET/maps/:mapId/tagsList tags
POST/maps/:mapId/tagsCreate a tag
PUT/maps/:mapId/tags/:tagIdUpdate a tag
DELETE/maps/:mapId/tags/:tagIdDelete a tag

Layers

MethodPathDescription
GET/maps/:mapId/layersList layers
POST/maps/:mapId/layersCreate a layer
PUT/maps/:mapId/layers/:layerIdUpdate a layer
DELETE/maps/:mapId/layers/:layerIdDelete a layer
PUT/maps/:mapId/locations/:locId/layersReplace a location's layer memberships

API Keys

MethodPathDescription
GET/keysList your API keys
POST/keysCreate an API key
DELETE/keys/:keyIdRevoke an API key

Quick Examples

Create a map

curl -X POST https://mapiry.com/api/v1/maps \
  -H "Authorization: Bearer mk_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"title": "Best Coffee in Tokyo", "description": "My favourite spots"}'

Response (201 Created):

{
  "data": {
    "id": "clxyz...",
    "title": "Best Coffee in Tokyo",
    "slug": "best-coffee-in-tokyo",
    "description": "My favourite spots",
    "country": "",
    "city": "",
    "public": false,
    "allowCloning": true,
    "style": "streets-v12",
    "centerLat": null,
    "centerLng": null,
    "zoom": null,
    "userId": "user_xyz",
    "createdAt": "2026-03-01T00:00:00.000Z"
  }
}

Bulk create locations

curl -X POST https://mapiry.com/api/v1/maps/clxyz.../locations/bulk \
  -H "Authorization: Bearer mk_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "locations": [
      {"name": "Fuglen Tokyo", "lat": 35.6654, "lng": 139.7006},
      {"name": "Bear Pond Espresso", "lat": 35.6585, "lng": 139.6968}
    ]
  }'

Response (201 Created):

{
  "data": {
    "created": [
      {
        "id": "loc1",
        "name": "Fuglen Tokyo",
        "lat": 35.6654,
        "lng": 139.7006,
        "layers": []
      },
      {
        "id": "loc2",
        "name": "Bear Pond Espresso",
        "lat": 35.6585,
        "lng": 139.6968,
        "layers": []
      }
    ],
    "count": 2
  }
}

List locations with pagination

curl "https://mapiry.com/api/v1/maps/clxyz.../locations?page=1&pageSize=20" \
  -H "Authorization: Bearer mk_live_your_key_here"

Response:

{
  "data": {
    "locations": [
      {
        "id": "loc1",
        "name": "Fuglen Tokyo",
        "lat": 35.6654,
        "lng": 139.7006,
        "layers": [
          {
            "id": "layer_day1",
            "name": "Day 1",
            "color": "#6366F1",
            "order": 0,
            "routeEnabled": false,
            "routeShowByDefault": false,
            "mapId": "clxyz...",
            "createdAt": "2026-03-01T00:00:00.000Z",
            "updatedAt": "2026-03-01T00:00:00.000Z"
          }
        ]
      }
    ],
    "pagination": {
      "total": 47,
      "page": 1,
      "pageSize": 20,
      "totalPages": 3
    }
  }
}

Error Responses

All errors follow this shape:

{
  "error": {
    "code": "INVALID_API_KEY",
    "message": "The API key is invalid or has been revoked."
  }
}
CodeStatusMeaning
MISSING_API_KEY401No Authorization header provided
INVALID_API_KEY401Key not found or revoked
API_KEY_EXPIRED401Key has passed its expiration date
PRO_SUBSCRIPTION_REQUIRED403Account does not have an active Pro subscription
INSUFFICIENT_SCOPE403Key scope doesn't allow this method (e.g. READ_ONLY used with POST)
NOT_FOUND404Resource not found or not owned by you
CONFLICT409Duplicate resource (e.g. tag name already exists on this map)
VALIDATION_ERROR400Request body failed validation
RATE_LIMIT_EXCEEDED429Rate limit hit — check Retry-After header

Notes

  • The API is write-only scoped for v1 — you can read your own data but there is no public read access for other users' maps
  • No geocoding endpoint — coordinates must be provided directly
  • Bulk location creation is atomic: if any location fails validation, none are created
  • Bulk create accepts a maximum of 100 locations per request
  • Layer memberships are managed separately from location CRUD via PUT /maps/:mapId/locations/:locId/layers
  • Location read responses include embedded layers summaries so clients can render layer names/colors without extra lookups
  • All timestamps are ISO 8601 in UTC

What's Next

Related Articles