Documentation menu
self-serve
POST/v1/keys
Public. No key, and no quota deducted.
Call it
bash
curl -fsS -X POST "https://api.mapmap.ai/v1/keys" \
-H "Content-Type: application/json" \
-d @request.jsonRequest body
application/json · IssueKeyRequest
| Field | Type | Required | Description |
|---|---|---|---|
| accept_tos | not stated | no | Must be literally true, anything else is a 400 echoing the
terms-of-service URL. |
| allowed_origins | string[] | no | Origins this key may be called from, e.g.
["https://app.example.com", "https://*.staging.example.com"].
At most 20; each is scheme://host[:port] with no path, and a
wildcard may only stand for a single subdomain label. Omit for an
unrestricted key, the default, and what a server-to-server
integration wants. |
| device_id | string | no | Email-less issuance only: an opaque, stable id for the app install (the apps' install id). Never stored as sent; only its hash is used, as a per-install daily issuance budget beside the per-IP one. At most 128 characters. Optional, and ignored when an email is given. |
| string | no | Email address; becomes the (lowercased) identity of the key.
Optional ONLY for the MapMap apps' own labels
([identity::EMAIL_OPTIONAL_LABELS]), which then get an email-less
anonymous key; every other caller must send one. | |
| label | string | no | Optional human-readable label for this key (shown on the account
page, e.g. "nightly-dispatch-agent"). Defaults to the email. |
| scope | string | no | "full" (the default) or "maps". A maps key may draw tiles,
read styles/fonts/sprites, geocode and read its own status, and
nothing else. |
| source | string | no | Optional channel tag naming where this signup came from
("chatgpt", "agent-recipe", "cursor" …). Lowercased and
restricted to [a-z0-9._-], at most 40 characters; anything else
is dropped, never rejected, attribution must not break signups. |
Responses
201Provisional key issued; the
key field is shown once only| Field | Type | Required | Description |
|---|---|---|---|
| allowed_origins | string[] | no | The canonical origin allow-list stored for this key, echoed back so the caller can see exactly what was accepted (ports and case are normalised, duplicates dropped). Absent on unrestricted keys. |
| calls | integer | yes | Call allowance: in total until verified for a provisional key, per
calendar month for anonymous and verified keys. |
| claim_url | string | no | Zero-authority claim pointer for the HUMAN behind this agent: the
page shows a masked email and offers to send a sign-in link. Safe
to print in chat or logs; it grants nothing by itself. Present only
when the deployment has a console (SN_CONSOLE_URL). |
| display_to_user | string | no | Sentence for the agent to show its human verbatim (contains the
claim URL, never the key). Present only alongside claim_url. |
| expires_in_h | integer | yes | Hours until the provisional key expires unverified; 0 for keys that do not expire. |
| key | string | yes | The full API key (snk_…). Shown once, never again. |
| key_id | string | yes | Key id (UUID), for /v1/keys/self correlation and admin ops. |
| scope | string | no | "maps" when the key was minted map-scoped; absent for the full
surface. |
| state | string | yes | provisional at an ordinary issuance; anonymous for an email-less
app key; verified for the store-review identity. |
| tos | string | yes | Terms-of-service URL that was accepted. |
| verify | string | yes | What happens next. |
400ToS not accepted (body echoes the
tos URL), invalid/disposable email, or rejected allowed_origins/scope (body carries problems[])429Issuance velocity exceeded: per IP or per install (
limit_per_day), per address per hour for a key without an email (limit_per_hour), or the global hourly ceilingError bodies follow the shared problem model documented on API conventions.
Also under self-serve
Generated from https://api.mapmap.ai/openapi.json on 2026-11-01 · operationId issue_key