Logo
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