50,000 free calls a month, card-free. Get an API key →

news / maps-for-ai · raw .md
Agents9 min readMapMap engineering
Route geometry and contour lines dissolving at one edge into an ordered grid of uniform data cells and bracket glyphs.

Maps for AI agents, with no human in the loop

Note, updated 3 August 2026. The MCP server exposed twelve tools when this was written. It exposes 32 today, and geocode is live on the hosted gateway. The tools named below are all still live; the list has grown since. See /docs/mcp for the current set.

MapMap's signup is an API call. POST /v1/keys with an email address and "accept_tos": true returns 201 and a live snk_ key worth 1,000 calls over 72 hours, with no card, no CAPTCHA and no sales call. Prices sit at /pricing.json in machine-readable form, orientation sits at /llms.txt on every deployment, errors carry stable type URIs an agent can branch on, and the hosted MCP server at https://mcp.mapmap.ai/mcp needs no key to connect. An agent can find us, price us, get a key and route, with no human in the loop. That is not a demo. It is the signup flow.

Why can't an agent buy a normal mapping API?

Because every step of the purchase assumes a human with a credit card and a calendar. Look at what the incumbents actually require before the first route comes back:

  • The price is on a marketing page, rendered by JavaScript, or it is "contact us" for the tier that has the capability you need.
  • The key comes from a dashboard behind a card form, a CAPTCHA and sometimes a phone number.
  • The premium capability, in our case truck dimensions and ADR dangerous-goods tunnel codes, is quoted rather than published.
  • The errors are English prose in a JSON body, with no stable identifier to dispatch on.

An agent has none of the things those steps demand. It has no card, no phone, no patience for a demo booking form, and no reliable way to read a price out of a rendered pricing table. So it does what models do when the facts are not available: it guesses, or it picks the provider whose documentation it could actually parse.

We took the opposite position. Every step a human takes to become a customer has a machine equivalent, published at a fixed path, and served by every deployment including your own self-hosted one.

How does an agent get from cold start to a route?

Six steps, all plain HTTP, and no human at our end in any of them.

StepCallWhat comes back
1. OrientGET /llms.txtWhat the platform does, endpoint names, the instructions-for-agents block. Every gateway deployment serves its own, alongside /openapi.json.
2. PriceGET /pricing.jsonCurrent prices, bands, quotas and unit rules. Do not scrape the marketing pages.
3. KeyPOST /v1/keys201 with a provisional snk_ key: 1,000 calls, 72 hours, card-free
4. CallAuthorization: Bearer snk_…Routing, matrix, isochrone, map-matching and ADR checks; geocoding on deployments that enable it
5. CheckGET /v1/keys/selfKey state, quota, remaining calls, prepaid balance. Consumes no quota, no credit, no rate limit
6. Handle402 and 429On 402, read the x402 body. On 429, honour Retry-After

Step 3 is the one people do not believe until they run it:

sh
curl -fsS -X POST "https://api.mapmap.ai/v1/keys" \
  -H "Content-Type: application/json" \
  -d '{"email": "you@example.co.uk", "accept_tos": true}'
json
{
  "key": "snk_…",
  "key_id": "3f1c…-uuid",
  "state": "provisional",
  "calls": 1000,
  "expires_in_h": 72,
  "verify": "link sent to email; clicking upgrades this key to the free tier",
  "tos": "https://mapmap.ai/terms"
}

The key is shown once, so store it on receipt. It works immediately, rate-limited to 60 requests a minute, and it expires after 72 hours if nothing verifies it. A magic link goes to the email address separately, and clicking it upgrades that same key to the free tier: 50,000 calls a month, commercial use allowed, still no card. Re-issuing with the same address is safe, because the verification link upgrades every provisional key issued to that email. It is not unlimited: an identity holds at most five active keys, and a single IP can issue three a day. The sixth key is a 409 (urn:sn-gateway:problem:key-cap) and the fourth issuance in a day is a 429 (urn:sn-gateway:problem:issuance-velocity), so an agent should key once and store it rather than loop.

That verification step is the one place a mailbox is still assumed. An agent with mail access clears it alone. An agent without one gets 1,000 calls and 72 hours to prove the integration works, which is enough to decide.

Step 5 is how an agent knows where it stands without spending anything:

sh
curl -fsS "https://api.mapmap.ai/v1/keys/self" \
  -H "Authorization: Bearer $API_KEY"
json
{
  "key_id": "3f1c…-uuid",
  "state": "provisional",
  "monthly_quota": 1000,
  "used_this_month": 1,
  "remaining": 999,
  "credits_pence": 0,
  "credits_millipence": 0,
  "expires_at": "2026-07-18T09:00:00Z",
  "identity_keys": 1
}

Trimmed above: the live response also carries the offline-download allowance and the monthly-active-user counters. expires_at appears on provisional keys only, so its absence is how an agent tells a verified key from an unverified one without parsing state.

Polling this endpoint costs nothing against quota, credit or the rate limit. That is deliberate: an agent watching for its own verification to land, or watching a prepaid balance before a large job, should not have to spend calls to do it. credits_millipence is the full-precision balance, because 1p is 1,000 millipence and per-call prices are fractional.

What does it cost, and what happens when the free tier runs out?

Prices are published per call, both classes, no quote required. These reconcile with /pricing.json, which wins if this page ever drifts.

ClassApplies to50k to 1M/month1M to 10MBeyond 10M
StandardCar, van, bus, two-wheeler and pedestrian routing, geocoding, matrix, isochrone, map-matching0.05p0.03p0.02p
PremiumTruck routing and ADR compliance1p0.7p0.4p

The class is detected per request, so an agent never picks a plan. The free tier is 50,000 included calls a month after verification, and a premium call draws 20 included calls, which makes all-premium free usage 2,500 calls a month. Size-metered requests are explicit: a matrix bills one call per started block of 25 elements and caps at 10,000 elements per request, an isochrone bills one call per contour with a maximum of 10, an optimisation bills a flat 10 calls.

Past the free tier, the answer depends on the key's history, and the distinction matters more than it looks:

json
{
  "x402Version": 1,
  "error": "free tier of 50000 calls/month exhausted and prepaid balance is below the request price of 1p",
  "accepts": [],
  "instructions": "x402 payment is not enabled on this deployment yet; top up prepaid credits at https://api.mapmap.ai/account to continue"
}

That 402 is the x402 wire format, not our usual problem+json, so x402 clients parse it directly. A verified key that has never bought credit gets something different: a 429 with problem type urn:sn-gateway:problem:quota-exceeded, carrying quota and used. So an agent should not sit waiting for a 402 to discover payment exists. On a quota-exceeded 429, top up. After the first top-up, an insufficient balance produces 402s. There is no post-paid overage on any path, which is the point: no credit means the calls stop, never a surprise invoice. The full 402-versus-429 matrix is in the machine payments guide.

MCP tools are what an agent can do; skills are what an agent knows

MCP tools let an agent act on the platform; agent skills teach it how to build against one. Conflating the two is why agent integrations produce code that compiles and is still wrong.

The MCP server is the action layer. Twelve tools: route, check_adr_tunnel, geocode, matrix, optimise_routes, order_stops, list_style_layers, get_style, create_style, set_palette, set_layer_paint, check_style_contrast. All carry full JSON Schemas and structured outputs, so a model calls them correctly first try, and tool errors name the exact problem so it can self-correct. The hosted endpoint speaks streamable HTTP, takes no key to connect and runs under fair use:

sh
claude mcp add --transport http mapmap https://mcp.mapmap.ai/mcp

Cursor, Claude Desktop, Codex, VS Code, Windsurf and the Claude API MCP connector each take the same URL, with no command and no environment variables. Configs for all of them are on the agents page, and the build story is in our MCP server release note.

The agent skills are the knowledge layer, installed separately:

sh
npx skills add Mapmapai/mapmap-agent-skills

Ten Markdown modules, MIT licensed, carrying no credentials and making no network calls, from mapmap-mcp-setup and mapmap-truck-adr-routing through mapmap-fleet-optimisation, mapmap-x402-payments and mapmap-self-host-ops. A tool lets an agent execute a route. A skill is what stops it burning three attempts finding out that truck parameters 400 on any profile other than truck, that bare coordinates on the compatible endpoint are lon,lat, that setting tunnel_code: "D" already implies hazmat, and that slashed codes like B/D must be URL-encoded. Install the tools so the agent can act, install the skills so it acts well.

Why do errors carry stable type URIs?

So an agent branches on an identifier instead of parsing English that we reserve the right to reword. Every gateway error is RFC 9457 application/problem+json with a type of urn:sn-gateway:problem:<slug>.

typeStatusAn agent should
urn:sn-gateway:problem:unauthorized401Reissue at POST /v1/keys
urn:sn-gateway:problem:quota-exceeded429Verify email or top up credit, do not retry
urn:sn-gateway:problem:rate-limited429Back off for retry_after seconds, also sent as Retry-After
urn:sn-gateway:problem:optimisation-too-large422Split the problem, using max_locations and locations from the body
urn:sn-gateway:problem:costing-conflict400Drop the fields named in conflicting_fields

Two 429s that mean opposite things (wait a second, versus stop and pay) are distinguishable by URN rather than by reading the detail string. There are exactly two exceptions to the envelope and we name them rather than hide them: the OSRM-compatible URL endpoint uses its own {"code": …, "message": …} shape because OSRM clients dispatch on code, and the 402 uses the x402 format above.

What is not live yet, and what it does not do

Four things fall short of the pitch above, and they are the ones a sales page would leave out.

  • x402 inline payment is not switched on for the hosted gateway. The gateway implements the standard server-side (protocol version 1, HTTP transport), but accepting payments is configuration-gated on SN_X402_*. Without it a deployment is x402-ready: identical wire shape, accepts empty, and an X-PAYMENT header ignored entirely, so do not retry with payment. Prepaid Stripe credit is the settlement rail that works on every deployment today. Dynamic per-request quoting and the POST /v1/x402/topup bridge need a further variable, SN_X402_MICROUSD_PER_PENCE, on top of that base configuration. Check the machine payments guide rather than trusting this paragraph, because it changes the day we flip it.
  • The hosted MCP endpoint is for evaluation, not production traffic. route, matrix, check_adr_tunnel, list_style_layers and get_style work today. geocode, optimise_routes and order_stops answer with tool errors until their upstreams, the geocoder and the optimisation solver, are enabled on that deployment, and style publishes are metered and may be unavailable. For production, call the REST API with your own key or run the server against your own deployment.
  • The sn-mcp binary is not on a package registry. You build it from source or run it from the self-host distro's Docker image.
  • Provisional keys are limited on purpose. They cannot draw prepaid credit and cannot download offline territory layers. Verify the email and both open up.

Try it

Issue a key with the curl above, then read /llms.txt and /pricing.json on whichever deployment you are pointed at, because both are per-deployment rather than global. Connect the MCP server with one command, add the skills with one more, and if you would rather not depend on our uptime at all, run the same gateway, engine and MCP server yourself from the Docker distro. Every distributable is permissive-licence only.

Routing derives from OpenStreetMap, so credit "© OpenStreetMap contributors" when you render or republish it.