Download OpenAPI specification:
The ZeeMaps REST API allows enterprise customers to programmatically create and manage maps and markers, and perform geographic searches.
Internal naming note for implementers: a user-facing "map" is the ZeeMaps
Groupdomain object (com.zeesource.maps.Group), and a "marker" is ancom.zeesource.maps.entries.Entry(tableNewEntries). The public API uses the terms "map" and "marker" throughout; do not expose "group"/"entry".
All requests must include an API key in the Authorization header:
Authorization: Bearer <api_key>
Keys are minted by ZeeMaps on request (any account may request one), stored
only as a SHA-256 hash, and returned in full once at mint time. Multiple
keys per account are supported (e.g. "Production", "Staging"), each with a
read_only or read_write scope. A read_only key is rejected with 403
on any write (POST/PATCH/DELETE) endpoint.
API access requires the enterprise plan. A valid key whose account is not on
the enterprise plan is rejected with 402 PLAN_REQUIRED on every endpoint.
map_id and marker_id are positive integers — the underlying
ZeeMaps record IDs — and are returned as JSON numbers, not strings. Because IDs
are sequential and enumerable, every endpoint strictly enforces ownership (see
below); a valid key may only reach maps the account owns. Maps merely shared to
the account are not accessible through the API.
Rate limits are enforced per API key. Limit details are returned in response headers on every response:
X-RateLimit-Limit: requests allowed per minuteX-RateLimit-Remaining: requests remaining in current windowX-RateLimit-Reset: Unix timestamp when the window resetsWhen the limit is exceeded the API returns 429 with a Retry-After header.
List endpoints return cursor-based pages:
page_token from next_page_token in the previous responsepage_sizeAll errors follow a consistent structure:
{ "error": { "code": "NOT_FOUND", "message": "Map not found" } }
Codes: UNAUTHORIZED (401), PLAN_REQUIRED (402), FORBIDDEN (403),
NOT_FOUND (404), BAD_REQUEST (400), RATE_LIMITED (429),
INTERNAL_ERROR (500). PLAN_REQUIRED means the account must upgrade to the
enterprise plan to use the API. On 401 and 402 the error may include a
help_url deep-linking the user to the request-a-key or upgrade page.
Returns the account, scope, plan, and rate limit behind the current API key. Lets a client self-configure and detect plan/scope before making other calls.
{- "account_email": "ops@acme.example",
- "scope": "read_write",
- "plan": "enterprise",
- "rate_limit": 30
}Lists maps owned by the authenticated account. Defaults to active maps; use status=archived for the archived view. Maps shared to the account are not listed (owned-only API).
| page_size | integer <= 1000 Default: 100 Maximum number of items to return per page. Defaults to 100; values above the maximum of 1000 are capped. |
| page_token | string Cursor token from a previous list response |
| q | string Filter maps by name (partial match) |
| status | string Default: "active" Enum: "active" "archived" Lifecycle filter (archived = Groups.status 2). |
{- "data": [
- {
- "id": 4321179,
- "name": "US Sales Territories Q3 2026",
- "description": "string",
- "owner_email": "string",
- "status": "active",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z",
- "private": true,
- "extended_colors": true,
- "marker_count": 0,
- "region_count": 0
}
], - "page_info": {
- "total_count": 0,
- "next_page_token": "string"
}
}Creates a new map owned by the authenticated account. New maps are private by default. Returns the created map.
| name required | string Title for the new map. |
| description | string Optional "About" text for the map (stored as MapProps.about). |
{- "name": "string",
- "description": "string"
}{- "id": 4321179,
- "name": "US Sales Territories Q3 2026",
- "description": "string",
- "owner_email": "string",
- "status": "active",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z",
- "private": true,
- "extended_colors": true,
- "marker_count": 0,
- "region_count": 0
}Fetches a single owned map by id, including marker and region counts. Returns 404 if the map doesn't exist, is deleted, or isn't owned by the account.
| map_id required | integer <int64> Example: 4321179 Numeric identifier of the map (ZeeMaps Group ID) |
{- "id": 4321179,
- "name": "US Sales Territories Q3 2026",
- "description": "string",
- "owner_email": "string",
- "status": "active",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z",
- "private": true,
- "extended_colors": true,
- "marker_count": 0,
- "region_count": 0
}Applies a partial update (name, description, and/or private) to an owned map. Only the supplied fields are changed.
| map_id required | integer <int64> Example: 4321179 Numeric identifier of the map (ZeeMaps Group ID) |
| name | string New map title. |
| description | string New "About" text for the map (MapProps.about). |
| private | boolean Make the map private (true) or public (false). |
{- "name": "string",
- "description": "string",
- "private": true
}{- "id": 4321179,
- "name": "US Sales Territories Q3 2026",
- "description": "string",
- "owner_email": "string",
- "status": "active",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z",
- "private": true,
- "extended_colors": true,
- "marker_count": 0,
- "region_count": 0
}Soft-deletes the map (sets Groups.status = 1), matching the web app's own delete behavior. The map stops appearing in list/get responses but the row is retained and is recoverable. Returns 204.
| map_id required | integer <int64> Example: 4321179 Numeric identifier of the map (ZeeMaps Group ID) |
{- "error": {
- "code": "UNAUTHORIZED",
- "message": "Missing or invalid API key."
}
}Clones an owned map into a new copy owned by the caller, optionally including its markers and/or regions. Returns the new map.
| map_id required | integer <int64> Example: 4321179 Numeric identifier of the map (ZeeMaps Group ID) |
| name required | string Name for the cloned map |
| include_markers | boolean Default: true Copy the source map's markers into the clone (default true). |
| include_regions | boolean Default: true Copy the source map's regions into the clone (default true). |
{- "name": "string",
- "include_markers": true,
- "include_regions": true
}{- "id": 4321179,
- "name": "US Sales Territories Q3 2026",
- "description": "string",
- "owner_email": "string",
- "status": "active",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z",
- "private": true,
- "extended_colors": true,
- "marker_count": 0,
- "region_count": 0
}Moves the map to the archived state (Groups.status = 2).
| map_id required | integer <int64> Example: 4321179 Numeric identifier of the map (ZeeMaps Group ID) |
{- "id": 4321179,
- "name": "US Sales Territories Q3 2026",
- "description": "string",
- "owner_email": "string",
- "status": "active",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z",
- "private": true,
- "extended_colors": true,
- "marker_count": 0,
- "region_count": 0
}Restores an archived or soft-deleted map to the active state (Groups.status = 0). Paid feature — non-paid accounts get 402/403.
| map_id required | integer <int64> Example: 4321179 Numeric identifier of the map (ZeeMaps Group ID) |
{- "id": 4321179,
- "name": "US Sales Territories Q3 2026",
- "description": "string",
- "owner_email": "string",
- "status": "active",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z",
- "private": true,
- "extended_colors": true,
- "marker_count": 0,
- "region_count": 0
}Reassigns ownership of the map to another account. Owner or superuser only.
| map_id required | integer <int64> Example: 4321179 Numeric identifier of the map (ZeeMaps Group ID) |
| new_owner_email required | string Email of the new owner. A pending account is created if it doesn't exist. |
{- "new_owner_email": "string"
}{- "error": {
- "code": "BAD_REQUEST",
- "message": "Invalid request."
}
}Switches the map to the extended color palette (MapProps.extendedColors, via the SetExtendedColors DB function). One-way — there is no way to revert to the standard palette. Idempotent if already enabled. Returns the updated map.
| map_id required | integer <int64> Example: 4321179 Numeric identifier of the map (ZeeMaps Group ID) |
{- "id": 4321179,
- "name": "US Sales Territories Q3 2026",
- "description": "string",
- "owner_email": "string",
- "status": "active",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z",
- "private": true,
- "extended_colors": true,
- "marker_count": 0,
- "region_count": 0
}Lists the map's custom field definitions (Attributes). Useful for clients (e.g. the MCP server) to discover which custom_fields keys a map uses before reading/writing markers. Read-only — fields are created implicitly when markers are written with new custom_fields keys.
| map_id required | integer <int64> Example: 4321179 Numeric identifier of the map (ZeeMaps Group ID) |
{- "fields": [
- {
- "id": 8801,
- "name": "Account Owner",
- "type": "text",
- "ordering": 0
}, - {
- "id": 8802,
- "name": "Annual Revenue",
- "type": "currency",
- "ordering": 1
}
]
}Lists the color names available for this map's active palette (standard or extended, per extended_colors). Use the returned name values as a marker color. Read-only.
| map_id required | integer <int64> Example: 4321179 Numeric identifier of the map (ZeeMaps Group ID) |
{- "extended": false,
- "colors": [
- {
- "name": "blue",
- "fill_color": "#2244cc",
- "text_color": "#ffffff"
}, - {
- "name": "red",
- "fill_color": "#cc2222",
- "text_color": "#ffffff"
}
]
}Lists the map's categories and their legend colors (from MapProps.legends). Categories are created implicitly when markers are written with a new category value (color auto-assigned); to rename, recolor, or reorder them, use PUT /maps/{map_id}/categories.
| map_id required | integer <int64> Example: 4321179 Numeric identifier of the map (ZeeMaps Group ID) |
{- "categories": [
- {
- "name": "Gold",
- "color": "yellow",
- "ordering": 0
}, - {
- "name": "Silver",
- "color": "gray",
- "ordering": 1
}
]
}Full replace of the map's legend (same model as the web app's legend editor): the submitted category list becomes the legend, in the given order. Use it to rename a category (markers keep their color), reassign a color, or re-order legend entries. Markers are never modified. When the map has exactly one layer the default layer's legend is kept in sync.
| map_id required | integer <int64> Example: 4321179 Numeric identifier of the map (ZeeMaps Group ID) |
required | Array of objects The new legend, in display order. |
{- "categories": [
- {
- "name": "Gold",
- "color": "yellow",
- "ordering": 0
}, - {
- "name": "Silver",
- "color": "gray",
- "ordering": 1
}
]
}{- "categories": [
- {
- "name": "Gold",
- "color": "yellow",
- "ordering": 0
}, - {
- "name": "Silver",
- "color": "gray",
- "ordering": 1
}
]
}Clears the map's legend/category mappings (maps to /legends/clear?all=true). Does NOT delete markers — they keep their assigned color; only the legend labels/mappings are reset. Returns 204.
| map_id required | integer <int64> Example: 4321179 Numeric identifier of the map (ZeeMaps Group ID) |
{- "error": {
- "code": "UNAUTHORIZED",
- "message": "Missing or invalid API key."
}
}Lists markers on the map's default layer, cursor-paginated. To filter by category, geographic bounds, or proximity, use GET .../markers/search.
| map_id required | integer <int64> Example: 4321179 Numeric identifier of the map (ZeeMaps Group ID) |
| page_size | integer <= 1000 Default: 100 Maximum number of items to return per page. Defaults to 100; values above the maximum of 1000 are capped. |
| page_token | string Cursor token from a previous list response |
{- "data": [
- {
- "id": 88341027,
- "map_id": 0,
- "name": "Acme Corp HQ",
- "type": "pin",
- "address": {
- "street": "string",
- "street2": "string",
- "city": "string",
- "state": "string",
- "country": "string",
- "zip": "string"
}, - "lat": 37.7879,
- "lng": -122.3983,
- "radius": 0,
- "radius_unit": "miles",
- "category": "string",
- "color": "string",
- "custom_fields": {
- "property1": "string",
- "property2": "string"
}, - "region_source": "string",
- "created_at": "2019-08-24T14:15:22Z"
}
], - "page_info": {
- "total_count": 0,
- "next_page_token": "string"
}
}Adds a single marker to the map's default layer. Supply lat+lng, or an address to be geocoded server-side (there is no standalone geocode endpoint). Returns the created marker.
| map_id required | integer <int64> Example: 4321179 Numeric identifier of the map (ZeeMaps Group ID) |
| name required | string Marker label/name. |
| type | string Enum: "pin" "us_zip" "us_county" "country" "au_state" "us_state" "circle" "ca_fsa" "uk_postcode" "pinned_circle" "au_postcode" "de_postcode" Defaults to |
object (Address) Structured address (NewEntries street/city/state/country/zipcode + AddressLine2). There is no single free-text address column; supply the parts. For postal region types (us_zip, ca_fsa, uk_postcode, au_postcode, de_postcode) the | |
| lat | number <double> Provide |
| lng | number <double> Longitude. Provide with |
| radius | number <double> Required for |
| radius_unit | string Default: "miles" Enum: "miles" "km" Unit for |
| category | string Legend category for the marker; drives its color (auto-assigned from the category). |
| color | string Palette color name; normally omitted (derived from category). |
object Map-defined custom field values, as a key→string map. New keys create new field definitions on the map. |
{- "name": "string",
- "type": "pin",
- "address": {
- "street": "string",
- "street2": "string",
- "city": "string",
- "state": "string",
- "country": "string",
- "zip": "string"
}, - "lat": 0.1,
- "lng": 0.1,
- "radius": 0.1,
- "radius_unit": "miles",
- "category": "string",
- "color": "string",
- "custom_fields": {
- "property1": "string",
- "property2": "string"
}
}{- "id": 88341027,
- "map_id": 0,
- "name": "Acme Corp HQ",
- "type": "pin",
- "address": {
- "street": "string",
- "street2": "string",
- "city": "string",
- "state": "string",
- "country": "string",
- "zip": "string"
}, - "lat": 37.7879,
- "lng": -122.3983,
- "radius": 0,
- "radius_unit": "miles",
- "category": "string",
- "color": "string",
- "custom_fields": {
- "property1": "string",
- "property2": "string"
}, - "region_source": "string",
- "created_at": "2019-08-24T14:15:22Z"
}Add many markers in a single request. Bulk add is always asynchronous:
the upload is handed to the shared ZeeMaps import service (Bin/import) —
which owns encoding detection, hybrid geocoding + cache, and dedup/overwrite
— and the endpoint returns 202 Accepted + a BulkJob. Poll
GET /v1/jobs/{job_id} for progress. All imports are scoped to the map's
default layer.
Three request content types are accepted:
text/csv — a raw CSV. Columns are recognized per column, in
order: exact ZeeMaps field names (name, lat, lng, street,
street2, city, state, zip, country, county, category,
photo_url, photo_width, photo_height, youtube_id,
video_width, video_height, …) and the display names ZeeMaps
itself exports ("Photo URL", "Photo Width", "Zipcode", "Color", …);
then a header row previously confirmed in the web upload UI (header
memory); then AI classification with a regex fallback — the same
pipeline as the web upload. Anything still unrecognized becomes a
custom field named after its header. Set auto_map=false to skip
the memory/AI steps (strict exact-name matching only). The AI step
runs synchronously before the 202 and typically adds ~0.5–2 s; it
is skipped when every column already resolves exactly, and an AI
failure is fail-open (the import still runs).application/json — a JSON array of marker objects (the same
shape as MarkerCreateRequest: name, lat/lng or address {},
category, custom_fields). Per-marker type/color/radius are
not supported — the importer applies one marker_type and default
per batch. auto_map defaults to false for this shape:
custom_fields keys stay custom fields verbatim and no AI call is
made. Pass auto_map=true to have unrecognized keys classified into
special columns like the CSV shapes.multipart/form-data — a file part (the spreadsheet; CSV in v1)
plus a meta JSON part (BulkImportMeta) carrying a column_mapping
({apiField: columnRef}, the column by header name or 0-based index),
an optional ignore list of column names, and options (marker_type,
on_duplicate, default_country, auto_map). An explicit mapping
always wins; unmapped columns go through the same recognition steps
as text/csv. Use this when the spreadsheet's columns don't match
ZeeMaps field names.For text/csv and application/json, batch options are passed as
the query parameters on_duplicate, default_country, marker_type,
and auto_map (the multipart form carries them inside meta instead).
Row limit: bounded by the map's subscription/plan limit
(uploadexceedslimit), not a fixed constant. Over-limit requests are
rejected with 400.
# text/csv shape (ZeeMaps-named headers)
name,street,city,state,zip,category
Acme Corp,350 Mission St,San Francisco,CA,94105,Gold
| map_id required | integer <int64> Example: 4321179 Numeric identifier of the map (ZeeMaps Group ID) |
| on_duplicate | string Default: "skip" Enum: "skip" "overwrite" "error" (text/csv and application/json only) How to handle a row that matches an existing marker. Only |
| default_country | string (text/csv and application/json only) Country code applied to rows that have no country of their own (importer |
| marker_type | string (MarkerType) Enum: "pin" "us_zip" "us_county" "country" "au_state" "us_state" "circle" "ca_fsa" "uk_postcode" "pinned_circle" "au_postcode" "de_postcode" (text/csv and application/json only) Marker type applied to every imported row (the importer applies one type per import); defaults to |
| auto_map | boolean (text/csv and application/json only) Automatically recognize columns the way the web upload does (header memory, then AI classification with a regex fallback) after exact field names/aliases are applied. Set |
object (DemographicsConfig) (text/csv and application/json only) Demographic-enrichment config as a URL-encoded JSON object. For multipart uploads set this inside the | |
object (ChoroplethConfig) (text/csv and application/json only) Choropleth config as a URL-encoded JSON object (use |
A CSV whose header row uses ZeeMaps field names. Unmapped columns become custom fields.
{- "job_id": "918273",
- "kind": "bulk_import",
- "status": "completed",
- "status_url": "/v1/jobs/918273",
- "added": 1450,
- "skipped": null,
- "errors": [
- {
- "index": 37,
- "message": "Row could not be imported (geocoding or validation failed)."
}
], - "created_at": "2026-06-30T17:10:00Z"
}Delete markers by all (clear the map), marker_ids, or a color-based selection (categories and/or colors). Requires confirm: true.
| map_id required | integer <int64> Example: 4321179 Numeric identifier of the map (ZeeMaps Group ID) |
| all | boolean Default: false Delete every marker on the map (clears the map). Maps to the efficient cascading |
| marker_ids | Array of integers <int64> [ items <int64 > ] Explicit list of marker IDs to delete. |
| categories | Array of strings Delete all markers in these categories. Each category label is resolved to its color id via the map legend (MapProps.legends), then deleted via |
| colors | Array of strings Delete all markers of these palette color names (e.g. "blue", "Hot Pink"). Each name is resolved to a color id against the map's active palette — standard (Colors/StdColors) or extended (ExtColors) per the map's extended-colors setting. May be combined with |
| confirm | boolean Default: false Must be true to execute bulk delete. |
{- "all": false,
- "marker_ids": [
- 0
], - "categories": [
- "string"
], - "colors": [
- "string"
], - "confirm": false
}{- "deleted": 0
}Fetches a single marker from the map's default layer by id. Returns 404 if no such marker exists on the map.
| map_id required | integer <int64> Example: 4321179 Numeric identifier of the map (ZeeMaps Group ID) |
| marker_id required | integer <int64> Example: 88341027 Numeric identifier of the marker |
{- "id": 88341027,
- "map_id": 0,
- "name": "Acme Corp HQ",
- "type": "pin",
- "address": {
- "street": "string",
- "street2": "string",
- "city": "string",
- "state": "string",
- "country": "string",
- "zip": "string"
}, - "lat": 37.7879,
- "lng": -122.3983,
- "radius": 0,
- "radius_unit": "miles",
- "category": "string",
- "color": "string",
- "custom_fields": {
- "property1": "string",
- "property2": "string"
}, - "region_source": "string",
- "created_at": "2019-08-24T14:15:22Z"
}Applies a partial update to a marker on the map's default layer; only supplied fields change. Changing the address or lat/lng re-geocodes the marker.
| map_id required | integer <int64> Example: 4321179 Numeric identifier of the map (ZeeMaps Group ID) |
| marker_id required | integer <int64> Example: 88341027 Numeric identifier of the marker |
| name | string New marker label/name. |
| type | string (MarkerType) Enum: "pin" "us_zip" "us_county" "country" "au_state" "us_state" "circle" "ca_fsa" "uk_postcode" "pinned_circle" "au_postcode" "de_postcode" ZeeMaps marker type (internally "marktype"). Type is per-marker — a single map may contain a mix. Region types render as a filled area rather than a pin; the polygon is resolved server-side from the marker's location/postcode by SetMarkType and recorded in EntryState (see |
object (Address) Structured address (NewEntries street/city/state/country/zipcode + AddressLine2). There is no single free-text address column; supply the parts. For postal region types (us_zip, ca_fsa, uk_postcode, au_postcode, de_postcode) the | |
| lat | number <double> New latitude (provide with |
| lng | number <double> New longitude (provide with |
| radius | number <double> New radius for circle/pinned_circle markers, in |
| radius_unit | string Enum: "miles" "km" Unit for |
| category | string New legend category (reassigns the marker's color). |
| color | string Palette color name to set explicitly (overrides the category-derived color). |
object Custom field values to set, as a key→string map. |
{- "name": "string",
- "type": "pin",
- "address": {
- "street": "string",
- "street2": "string",
- "city": "string",
- "state": "string",
- "country": "string",
- "zip": "string"
}, - "lat": 0.1,
- "lng": 0.1,
- "radius": 0.1,
- "radius_unit": "miles",
- "category": "string",
- "color": "string",
- "custom_fields": {
- "property1": "string",
- "property2": "string"
}
}{- "id": 88341027,
- "map_id": 0,
- "name": "Acme Corp HQ",
- "type": "pin",
- "address": {
- "street": "string",
- "street2": "string",
- "city": "string",
- "state": "string",
- "country": "string",
- "zip": "string"
}, - "lat": 37.7879,
- "lng": -122.3983,
- "radius": 0,
- "radius_unit": "miles",
- "category": "string",
- "color": "string",
- "custom_fields": {
- "property1": "string",
- "property2": "string"
}, - "region_source": "string",
- "created_at": "2019-08-24T14:15:22Z"
}Deletes a marker from the map's default layer. Returns 204 on success, or 404 if no such marker exists on the map.
| map_id required | integer <int64> Example: 4321179 Numeric identifier of the map (ZeeMaps Group ID) |
| marker_id required | integer <int64> Example: 88341027 Numeric identifier of the marker |
{- "error": {
- "code": "UNAUTHORIZED",
- "message": "Missing or invalid API key."
}
}The global catalog of demographic fields selectable in a bulk import's demographics config — reference each by id or key. Auth-gated but not map-scoped.
{- "demographic_fields": [
- {
- "id": 1,
- "key": "total_population",
- "label": "Population",
- "type": "number"
}, - {
- "id": 3,
- "key": "median_income",
- "label": "Income (Median)",
- "type": "currency"
}
]
}Full-text and geo search across markers on a map.
| map_id required | integer <int64> Example: 4321179 Numeric identifier of the map (ZeeMaps Group ID) |
| q | string Text search across name, description, address, and custom fields. MVP uses ILIKE substring matching (markers have no tsvector index today). |
| category | string |
| bounds | string Bounding box: sw_lat,sw_lng,ne_lat,ne_lng (PostGIS ST_Within on NewEntries.location) |
| near | string Center point + radius: lat,lng,radius_km — e.g. 37.77,-122.41,50 (PostGIS ST_DWithin) |
| page_size | integer <= 1000 Default: 100 Maximum number of items to return per page. Defaults to 100; values above the maximum of 1000 are capped. |
| page_token | string Cursor token from a previous list response |
{- "data": [
- {
- "id": 88341027,
- "map_id": 0,
- "name": "Acme Corp HQ",
- "type": "pin",
- "address": {
- "street": "string",
- "street2": "string",
- "city": "string",
- "state": "string",
- "country": "string",
- "zip": "string"
}, - "lat": 37.7879,
- "lng": -122.3983,
- "radius": 0,
- "radius_unit": "miles",
- "category": "string",
- "color": "string",
- "custom_fields": {
- "property1": "string",
- "property2": "string"
}, - "region_source": "string",
- "created_at": "2019-08-24T14:15:22Z"
}
], - "page_info": {
- "total_count": 0,
- "next_page_token": "string"
}
}Render a standard image of the map (PNG or PDF) — the API equivalent of the web app's Print / Share → PDF/PNG. v1 exposes a fixed set of layouts via preset (pin coverage, US, world, regions) rather than arbitrary bounds or dimensions, so output stays small. Rendering is heavyweight (Mapnik), so it always runs asynchronously: returns 202 + an ImageJob; poll GET /v1/jobs/{job_id} and download image_url once complete. Images are un-watermarked and covered by the enterprise plan at no extra charge. Owned-only.
| map_id required | integer <int64> Example: 4321179 Numeric identifier of the map (ZeeMaps Group ID) |
| preset required | string Enum: "pin_coverage" "us" "world" "regions" Which standard layout to render — |
| format | string Default: "png" Enum: "png" "pdf" Output file format. |
| map_type | string Default: "map" Enum: "map" "satellite" Base layer — street map or satellite imagery. |
| paper_size | string Default: "letter" Enum: "letter" "a4" Page size for the render. Bounded to standard sizes only — no Poster or custom dimensions; large renders are intentionally not offered in v1. |
| orientation | string Default: "landscape" Enum: "landscape" "portrait" Page orientation. Landscape by default, matching the web map export. |
| legend | boolean Default: false Draw the category legend on the image (off by default, matching the web export). |
| title | boolean Default: true Draw the map title (the map name) on the image. |
| labels | boolean Default: false Draw marker labels on the image. |
{- "preset": "us",
- "format": "png",
- "map_type": "map",
- "paper_size": "letter",
- "legend": true
}{- "job_id": "img_9f3a2c",
- "kind": "image",
- "status": "completed",
- "format": "png",
- "error": null,
- "created_at": "2026-06-25T18:04:00Z",
- "completed_at": "2026-06-25T18:04:12Z"
}Poll the status of an async operation — a bulk marker import (BulkJob) or a standard image render (ImageJob); the kind field discriminates them. Owned-only — returns the job only if its map is owned by the calling account; otherwise 404.
| job_id required | string^[A-Za-z0-9_]+$ Identifier of an async job — a bulk-import csvid (e.g. |
{- "job_id": "918273",
- "kind": "bulk_import",
- "status": "completed",
- "status_url": "/v1/jobs/918273",
- "added": 1450,
- "skipped": null,
- "errors": [
- {
- "index": 37,
- "message": "Row could not be imported (geocoding or validation failed)."
}
], - "created_at": "2026-06-30T17:10:00Z"
}