ITSYBITSYMAP
Documentation

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}.pbf vector 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:

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

MethodGET
Path/v1/tiles/{z}/{x}/{y}.pbf
HeadersAuthorization: Bearer <api_key>
Success200 with tile bytes, or 204 / 404 passed through from the tile source when a tile has no data at that coordinate.
Content-Typeapplication/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:

402 response
{
  "error": "insufficient_credits",
  "code": 402,
  "message": "Credit balance exhausted. Top up at https://app.example.com/billing"
}
StatuserrorWhen it happens
401invalid_api_keyThe Authorization header is missing, malformed, or the key doesn't exist.
401revoked_api_keyThe key was valid once but has since been rotated or revoked from the dashboard.
402insufficient_creditsYour credit balance is exhausted. Top up or wait for the next renewal.
429rate_limitedYou'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:

map.ts
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.