Map Styles Overview

One canonical styles endpoint that returns a renderer-correct style document for MapLibre / Mapbox, Leaflet, or Google Maps + deck.gl. Pick your target, list the layers you want, and mount.

Styles URL builder

Pick a renderer target and one or more layers — the URL below updates live. CDL years are expressed one per spec (e.g. cdl:2024); add multiple to stack years. Swap YOUR_API_KEY for your key when you paste this into your code.

Target

MapLibre and Mapbox return the identical MapLibre Style Spec v8 document — pick whichever name fits your codebase.

Layers

Request URL

https://api.landmapmagic.com/v1/styles?target=maplibre&layers=clu&key=YOUR_API_KEY
Open

The key param is a placeholder — the live URL needs your real API key to return a style.

GEThttps://api.landmapmagic.com/v1/styles

Why one endpoint

Every mapping library wants the same data shaped a little differently. Rather than ship a different style file per layer per target, the API answers a single question: "Given these layers and this target, hand me a ready-to-mount config." Each target gets a renderer-native document so you never have to translate paint properties yourself.

  • Duplicate-label rendering (multi-polygon features and tile-boundary repeats) is solved server-side via dedicated *_labels source layers and a canonical lmm_label_id.
  • Zoom ranges, attribution, and tile URLs come from the API's authoritative product catalog — they never drift between client and server.
  • The landmapmagic npm package consumes this endpoint, so style updates roll out without npm releases.

Parameters

Parameters

NameTypeDescription
key*stringYour API key (origin-restricted).
targetstringRenderer target. One of: maplibre (default — also serves Mapbox GL JS), leaflet, google.
layers*string (CSV)Comma-separated layer ids. Supported: clu, states, counties, townships, sections, parcels, plss, ssurgo, cdl. CDL years are expressed one per spec — cdl:YYYY (e.g. cdl:2024). Repeat to request multiple years (cdl:2024,cdl:2023). Bare `cdl` resolves to the default year.

Targets at a glance

What each target returns

AttributeTypeDescription
maplibreMapLibre Style Spec v8Full style document with sources, layers, glyphs, and metadata. Default target.
mapboxMapLibre Style Spec v8 (alias)Identical payload to maplibre. Mapbox GL JS consumes a MapLibre Style Spec v8 doc as-is — the alias exists so you can write `target=mapbox` in your code without anyone wondering whether they should switch.
leaflet{ basemap?, sources, layers }Array of declarative Leaflet descriptors (tileLayer for raster, vectorGrid for vector) with URLs, options, and label metadata. The landmapmagic/leaflet adapter mounts these directly.
google{ tileLayers, vectorOverlays, labels }deck.gl-friendly envelope with MVT / raster tile URLs and accessor descriptors (static, by-zoom, by-property). Mounted via deck.gl GoogleMapsOverlay using MVTLayer / TextLayer / TileLayer + BitmapLayer.

Label deduplication

Two distinct "duplicate label" problems are handled server-side so you don't have to think about either:

  • Multi-polygon-per-feature — one logical feature (state, parcel, CLU) often consists of many polygons; the dedicated *_labelssource layers contain a single representative point per feature so labels don't repeat per polygon.
  • Tile-boundary repeats — when a feature spans multiple tiles, every label feature carries lmm_label_id. MapLibre collision sorts on it; Leaflet and Google adapters dedupe in JS by id.
The styles API ships one good baseline label config per layer. Toggling labels off, swapping primary/secondary fields, or restyling halos is a client-side concern — see the Customizing Styles guide.

Code Examples

MapLibre — fetch + apply

JavaScript
const response = await fetch(
  "https://api.landmapmagic.com/v1/styles?" +
    new URLSearchParams({
      key: "YOUR_API_KEY",
      target: "maplibre",
      layers: "clu,counties",
    })
);
const style = await response.json();
map.setStyle(style);
cURL
curl "https://api.landmapmagic.com/v1/styles?key=YOUR_API_KEY&target=maplibre&layers=clu,counties"
Python
import requests

response = requests.get(
    "https://api.landmapmagic.com/v1/styles",
    params={
        "key": "YOUR_API_KEY",
        "target": "maplibre",
        "layers": "clu,counties",
    },
)
style = response.json()

CDL with multiple years

JavaScript
// One layer per year — repeat cdl:YYYY in the layers list
const response = await fetch(
  "https://api.landmapmagic.com/v1/styles?" +
    new URLSearchParams({
      key: "YOUR_API_KEY",
      target: "maplibre",
      layers: "clu,cdl:2024,cdl:2023",
    })
);
const style = await response.json();

Leaflet — declarative descriptors

JavaScript
const response = await fetch(
  "https://api.landmapmagic.com/v1/styles?" +
    new URLSearchParams({
      key: "YOUR_API_KEY",
      target: "leaflet",
      layers: "clu",
    })
);
const { layers } = await response.json();
// Each entry has type: 'tileLayer' | 'vectorGrid' and an
// options object with the URL template + style rules.
console.log(layers);

Google + deck.gl

JavaScript
const response = await fetch(
  "https://api.landmapmagic.com/v1/styles?" +
    new URLSearchParams({
      key: "YOUR_API_KEY",
      target: "google",
      layers: "clu",
    })
);
const { tileLayers, vectorOverlays } = await response.json();
// Pass directly to MVTLayer / TileLayer through GoogleMapsOverlay.
Looking for the one-line install? See the Master Style guide for copy-paste snippets per target.