Get a tile on screen in under five minutes.
itsybitsymap serves standard vector tiles over a single, simple endpoint. If you already speak MapLibre GL JS or Mapbox GL JS, you already know most of what’s below.
Overview
There’s one endpoint that matters for rendering maps: GET /v1/tiles/{z}/{x}/{y}.pbf. It returns Mapbox Vector Tile (MVT) data as application/x-protobuf bytes, which any MVT-aware client — MapLibre GL JS, Mapbox GL JS, Tangram, deck.gl — can render directly.
- • Base URL: your API base (e.g.
https://api.example.com) - • Format: standard
{z}/{x}/{y}.pbfvector tiles - • Auth: a single Bearer API key per request
- • Billing: 1 credit per successful tile request, flat
Authentication
Create an API key from the dashboard and send it as a Bearer token on every tile request:
curl "https://api.example.com/v1/tiles/6/32/22.pbf" \ -H "Authorization: Bearer mt_live_xxxxxxxxxxxxxxxx"
Keys can be rotated or revoked instantly from the dashboard — a revoked key fails closed with a 401 revoked_api_key on its very next request.
Tile endpoint
| Method | GET |
| Path | /v1/tiles/{z}/{x}/{y}.pbf |
| Headers | Authorization: Bearer <api_key> |
| Success | 200 with tile bytes, or 204 / 404 passed through from the tile source when a tile has no data at that coordinate. |
| Content-Type | application/x-protobuf |
There is also an unauthenticated GET /healthz you can use for uptime checks — it always returns a plain 200.
Error codes
Non-2xx responses from itsybitsymap itself (not proxied from the underlying tile source) use a consistent JSON envelope:
{
"error": "insufficient_credits",
"code": 402,
"message": "Credit balance exhausted. Top up at https://app.example.com/billing"
}| Status | error | When it happens |
|---|---|---|
| 401 | invalid_api_key | The Authorization header is missing, malformed, or the key doesn't exist. |
| 401 | revoked_api_key | The key was valid once but has since been rotated or revoked from the dashboard. |
| 402 | insufficient_credits | Your credit balance is exhausted. Top up or wait for the next renewal. |
| 429 | rate_limited | You're sending requests faster than your plan's rate limit allows. Back off and retry. |
None of these responses consume a credit — only successfully served tiles are billed.
MapLibre GL JS quickstart
Since the API key is a header rather than a query parameter, attach it with transformRequest so MapLibre sends it on every tile fetch:
import maplibregl from "maplibre-gl";
const ITSYBITSYMAP_API_KEY = process.env.NEXT_PUBLIC_ITSYBITSYMAP_API_KEY!;
const map = new maplibregl.Map({
container: "map",
transformRequest: (url) =>
url.includes("/v1/tiles/")
? { url, headers: { Authorization: `Bearer ${ITSYBITSYMAP_API_KEY}` } }
: { url },
style: {
version: 8,
sources: {
itsybitsymap: {
type: "vector",
tiles: ["https://api.example.com/v1/tiles/{z}/{x}/{y}.pbf"],
maxzoom: 14,
},
},
layers: [
{ id: "background", type: "background", paint: { "background-color": "#101720" } },
{
id: "water",
type: "fill",
source: "itsybitsymap",
"source-layer": "water",
paint: { "fill-color": "#1f2c3a" },
},
{
id: "roads",
type: "line",
source: "itsybitsymap",
"source-layer": "transportation",
paint: { "line-color": "#e8590c", "line-width": 1 },
},
],
},
center: [-75.6972, 45.2382],
zoom: 8,
});Layer IDs and source-layer names depend on the tile schema for your chosen style — check the dashboard’s style browser for the exact layer names available to your account.
Credit model
Every successful tile response deducts exactly 1 credit, regardless of zoom level or tile weight. The gateway decrements a Redis-cached balance optimistically on each request; a reconciliation pass in the billing service is the final source of truth, so short bursts never leave you over- or under-charged.
Failed requests (401 / 402 / 429) never consume credits. See the pricing page for plan grants and top-up packs.