Lynker Spatial Tiles

Complete Documentation - Sign Up Through Production Deployment

← Home Quick Start (5 min)

Welcome to Lynker Spatial Tiles

Access geospatial tile data for watershed analysis, flood modeling, land cover classification, and more.

Get Started Now

Service Overview

The Lynker Spatial Tile Service provides cloud-hosted vector and raster tile datasets optimized for web and desktop applications. All data is served in Protocol Buffer (PBF) format with JWT Bearer token authentication.

Service Base URL: https://tiles.lynker-spatial.com

Available Datasets

Key Features

Getting Started

Start in 5 Minutes (Recommended)

Use this exact endpoint and layer as your default first integration target.

# 1) Verify token + service curl -H "Authorization: Bearer YOUR_TOKEN" \ https://tiles.lynker-spatial.com/catalog # 2) Pull one known tile from modeling fabric curl -H "Authorization: Bearer YOUR_TOKEN" \ https://tiles.lynker-spatial.com/api/tiles/lynker-spatial-modeling-fabric/5/9/11 \ -o tile.pbf # 3) MapLibre defaults tiles: ['https://tiles.lynker-spatial.com/api/tiles/lynker-spatial-modeling-fabric/{z}/{x}/{y}'] 'source-layer': 'flowpath'

The Lynker Spatial Tile Service consists of:

Quick Start: Five Steps

Quick Setup Checklist

Go to https://proxy.lynker-spatial.com/ to sign up or sign in
Verify your email (if new account)
Visit https://proxy.lynker-spatial.com/token to see your JWT token
Copy your token for authentication
Test access (catalog is public):
curl -i https://tiles.lynker-spatial.com/catalog # Optional: you may include Authorization but it's not required for catalog discovery curl -i -H "Authorization: Bearer TOKEN" https://tiles.lynker-spatial.com/catalog

System Requirements

Sign Up & Account Setup

📧 Step 1: Create or Sign In

Visit the Lynker Spatial authentication portal to create an account or sign in.

Go to Portal

✓ Step 2: Verify Email

Check your email inbox for a verification link and confirm your account (if new).

🔑 Step 3: Get Your Token

Visit https://proxy.lynker-spatial.com/token to view your access token.

🚀 Step 4: Start Using Tiles

Use your token in the Authorization header to access all tile endpoints.

Token Management

Your JWT token is available at https://proxy.lynker-spatial.com/token after signing in:

Authentication & Authorization

All requests to the Lynker Spatial Tile Service require JWT Bearer token authentication. Tokens are issued through AWS Cognito; token lifetimes vary by Cognito app client. This deployment uses 1 day access/ID tokens and 30 day refresh tokens — configure your client to refresh tokens proactively based on the returned `expires_in`.

Getting Your Token

Recommended: Visit the web portal to view and copy your token:

https://proxy.lynker-spatial.com/token

Your token is a JWT that expires according to your Cognito app client's configuration. In this deployment the app client issues 1 day access/ID tokens; for production applications, read the token's `expires_in` and implement refresh logic a few minutes before expiry.

Using Your Token

Include the token in the Authorization header for all tile service requests:

curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ https://tiles.lynker-spatial.com/api/tiles/lynker-spatial-modeling-fabric/5/9/11
Security Note: Tokens expire every hour. Implement token refresh logic in production applications. Never commit tokens to version control.

Token Refresh Pattern

Implement automatic token refresh to handle expiration:

// Example: Node.js token refresh async function getValidToken() { const cached = getCachedToken(); if (cached && !isExpired(cached)) { return cached; } const newToken = await requestNewToken(); cacheToken(newToken); return newToken; } // Use in requests const token = await getValidToken(); // For catalog discovery the Authorization header is optional; include it when available fetch('https://tiles.lynker-spatial.com/catalog', { headers: token ? { 'Authorization': `Bearer ${token}` } : {} });

Testing Authentication

Verify your setup works:

# Test 1: Get service catalog (requires valid token) curl -H "Authorization: Bearer YOUR_TOKEN" \ https://tiles.lynker-spatial.com/catalog # Test 2: Request a specific tile (note: no .pbf extension in URL) curl -H "Authorization: Bearer YOUR_TOKEN" \ https://tiles.lynker-spatial.com/api/tiles/lynker-spatial-modeling-fabric/5/9/11 \ -o tile.pbf # Verify the file is valid file tile.pbf # Should output: tile.pbf: Protocol Buffer data

Authorization Scopes

Token permissions are controlled through scopes:

MapLibre GL JS Integration

MapLibre GL JS is a free, open-source JavaScript library for interactive maps. It provides excellent support for vector tiles and is ideal for web applications.

Installation

# Via npm npm install maplibre-gl # Via CDN (for simple projects) <script src='https://unpkg.com/maplibre-gl@latest/dist/maplibre-gl.js'></script> <link href='https://unpkg.com/maplibre-gl@latest/dist/maplibre-gl.css' rel='stylesheet' />

Basic Map with Tiles

<!DOCTYPE html> <html> <head> <meta charset='utf-8' /> <title>Lynker Tiles with MapLibre</title> <meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' /> <script src='https://unpkg.com/maplibre-gl@latest/dist/maplibre-gl.js'></script> <link href='https://unpkg.com/maplibre-gl@latest/dist/maplibre-gl.css' rel='stylesheet' /> <style> body { margin: 0; padding: 0; } #map { position: absolute; top: 0; bottom: 0; width: 100%; } </style> </head> <body> <div id='map'></div> <script> const map = new maplibregl.Map({ container: 'map', style: 'https://demotiles.maplibre.org/style.json', center: [-100, 40], zoom: 6 }); map.on('load', () => { // Add modeling fabric flowpaths layer map.addSource('padus', { type: 'vector', tiles: ['https://tiles.lynker-spatial.com/api/tiles/lynker-spatial-modeling-fabric/{z}/{x}/{y}'], // omit .pbf extension minzoom: 0, maxzoom: 14 }); map.addLayer({ id: 'padus-fill', type: 'fill', source: 'padus', 'source-layer': 'flowpath', paint: { 'fill-color': '#088', 'fill-opacity': 0.3 } }); map.addLayer({ id: 'padus-outline', type: 'line', source: 'padus', 'source-layer': 'flowpath', paint: { 'line-color': '#088', 'line-width': 2 } }); }); </script> </body> </html>

Authentication in MapLibre

Since MapLibre runs in the browser, handle authentication through a proxy server:

// Option 1: Proxy tile requests through your backend const tileUrl = '/api/proxy/tiles/{z}/{x}/{y}'; map.addSource('padus', { type: 'vector', tiles: [tileUrl], minzoom: 0, maxzoom: 14 }); // Your backend proxy adds the Authorization header // Example Express.js proxy: app.get('/api/proxy/tiles/:z/:x/:y', (req, res) => { const tileUrl = `https://tiles.lynker-spatial.com/api/tiles/lynker-spatial-modeling-fabric/${req.params.z}/${req.params.x}/${req.params.y}`; fetch(tileUrl, { headers: { 'Authorization': `Bearer ${process.env.LYNKER_TOKEN}` } }) .then(r => r.buffer()) .then(buffer => { res.set('Content-Type', 'application/octet-stream'); res.send(buffer); }) .catch(err => res.status(500).json({ error: err.message })); });

Advanced Styling

Use data-driven styling to create thematic maps:

map.addLayer({ id: 'padus-styled', type: 'fill', source: 'padus', 'source-layer': 'flowpath', paint: { 'fill-color': [ 'interpolate', ['linear'], ['get', 'protection_level'], 0, '#fee5d9', 1, '#fcae91', 2, '#fb6a4a', 3, '#cb181d' ], 'fill-opacity': [ 'case', ['boolean', ['feature-state', 'hover'], false], 0.7, 0.3 ] } }); // Add hover effects map.on('mousemove', 'padus-styled', (e) => { if (e.features.length > 0) { map.setFeatureState( { source: 'padus', id: e.features[0].id }, { hover: true } ); } });

Interactivity

// Click handler for feature information map.on('click', 'padus-fill', (e) => { const properties = e.features[0].properties; new maplibregl.Popup() .setLngLat(e.lngLat) .setHTML(` <h3>${properties.name}</h3> <p>Type: ${properties.type}</p> <p>Area: ${properties.area_sqmi} sq mi</p> `) .addTo(map); }); // Change cursor on hover map.on('mouseenter', 'padus-fill', () => { map.getCanvas().style.cursor = 'pointer'; }); map.on('mouseleave', 'padus-fill', () => { map.getCanvas().style.cursor = ''; });

QGIS Integration

QGIS 3.x has native support for vector tiles. Here are three methods to add Lynker Spatial tiles to your QGIS projects.

Method 1: Vector Tile Layer (GUI)

Step-by-Step Instructions

Open QGIS and go to Layer → Add Layer → Add Vector Tile Layer
Click the New button to create a new connection
Enter connection details:
Name: Lynker PADUS URL: https://tiles.lynker-spatial.com/api/tiles/lynker-spatial-modeling-fabric/{z}/{x}/{y} (omit .pbf extension)
Go to the HTTP Headers tab
Add custom header:
Header Name: Authorization Header Value: Bearer YOUR_ACCESS_TOKEN
Click OK and save the connection
Select the connection from the list and add the layer
Configure symbology by right-clicking the layer → Properties → Symbology

Method 2: Python Console

from qgis.core import QgsVectorTileLayer, QgsProject from qgis.utils import iface # Create vector tile layer (note: no .pbf extension in URL) url = 'https://tiles.lynker-spatial.com/api/tiles/lynker-spatial-modeling-fabric/{z}/{x}/{y}' layer = QgsVectorTileLayer(url, 'PADUS Protected Areas') # Add to project QgsProject.instance().addMapLayer(layer) print(f"Layer added: {layer.name()}")

Method 3: Custom Python Plugin

For more control, create a custom plugin:

import requests from qgis.core import QgsVectorTileLayer, QgsProject class LynkerTileManager: def __init__(self, token=None): self.token = token self.base_url = 'https://tiles.lynker-spatial.com' def get_catalog(self): """Fetch available tile sources (catalog is public; Authorization optional)""" headers = {'Authorization': f'Bearer {self.token}'} if self.token else {} response = requests.get(f'{self.base_url}/catalog', headers=headers) return response.json() def add_tile_layer(self, source_name, display_name=None): """Add a tile layer to QGIS""" if display_name is None: display_name = source_name url = f'{self.base_url}/api/tiles/{source_name}/{{z}}/{{x}}/{{y}}' # no .pbf extension layer = QgsVectorTileLayer(url, display_name) QgsProject.instance().addMapLayer(layer) return layer # Usage manager = LynkerTileManager('YOUR_TOKEN') manager.add_tile_layer('padus', 'Protected Areas') manager.add_tile_layer('wetlands', 'Wetlands')

Styling Vector Tiles in QGIS

  1. Right-click the layer → Properties
  2. Go to the Symbology tab
  3. Select Vector Tile Rendering style
  4. Configure colors, opacity, and outlines for each feature type
  5. Use Rule-based rendering for conditional styling

Troubleshooting

ArcGIS Integration

Add Lynker Spatial tiles to ArcGIS Pro, ArcGIS Online, and ArcMap using multiple connection methods.

ArcGIS Pro Setup

Adding a Vector Tile Service

In ArcGIS Pro, go to Insert → Connections → New Vector Tile Service Connection
Enter the service URL and configure authentication
Add the connection to your project
Drag the connection into your map to add layers

ArcGIS Online

In ArcGIS Online Map Viewer:

  1. Click "Add" → "Add Layer from Web"
  2. Select "Vector Tile Service"
  3. URL: https://tiles.lynker-spatial.com/api/tiles/lynker-spatial-modeling-fabric/{z}/{x}/{y}
  4. Add Authorization header: Bearer YOUR_TOKEN
layer = mapping.Layer(layer_file) mapping.AddLayerToGroup(df, df.listLayers()[0].longName, layer) mapping.RefreshActiveView()

WMS/WMTS Alternative

If vector tiles don't work, use the WMS endpoint:

# In ArcGIS Pro or Online Add WMS Layer Service URL: https://tiles.lynker-spatial.com/wms Authentication Header: Authorization: Bearer YOUR_ACCESS_TOKEN Available Layers: - padus (Protected Areas) - wetlands (Wetlands) - hydrofabric (Hydrofabric)

Configuring Proxy for Enterprise

For enterprise deployments, configure a proxy server:

# proxy.ashx or similar proxy configuration # Note: Use Bearer token in Authorization header instead of ClientId/Secret QueryableLayerIds: 0,1,2,3,4,5 LogFile: C:\logs\proxy.log LogLevel: All ServerUrl: https://tiles.lynker-spatial.com AllowedReferrers: yourdomain.com AllowedPorts: 443 HasToken: true # Get this token from https://proxy.lynker-spatial.com/token BearerToken: YOUR_JWT_TOKEN_FROM_PORTAL

Leaflet.js Integration

Leaflet is a lightweight, open-source JavaScript library perfect for simple to moderately complex maps.

Installation

# Via npm npm install leaflet # Via CDN (easiest for simple projects) <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" /> <script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>

Basic Map with Tiles

<!DOCTYPE html> <html> <head> <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" /> <style> #map { height: 600px; } </style> </head> <body> <div id="map"></div> <script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script> <script> const map = L.map('map').setView([40, -100], 6); // Base layer L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { attribution: '© OpenStreetMap contributors', maxZoom: 19 }).addTo(map); // Lynker tile overlay through proxy const tileLayer = L.tileLayer('/api/tiles/{z}/{x}/{y}', { // proxy handles auth attribution: '© Lynker Spatial', minZoom: 0, maxZoom: 14, opacity: 0.7 }).addTo(map); </script> </body> </html>

Proxy Setup for Leaflet

Implement a backend proxy to handle authentication:

const token = process.env.LYNKER_TOKEN; app.get('/api/tiles/:z/:x/:y', async (req, res) => { const { z, x, y } = req.params; const url = `https://tiles.lynker-spatial.com/api/tiles/padus/${z}/${x}/${y}`; const response = await fetch(url, { headers: { 'Authorization': `Bearer ${token}` } }); res.set('Content-Type', 'application/octet-stream'); res.send(Buffer.from(await response.arrayBuffer())); });

Leaflet vs MapLibre Comparison

Aspect Leaflet MapLibre GL JS
Bundle Size ~39 KB gzipped ~70 KB gzipped
Learning Curve Easy Moderate
3D Support No Yes
Vector Tile Support Basic (via proxy) Native & Advanced
Best Use Case Simple web maps Complex styling & effects

Folium & Python Jupyter

Folium bridges Python and Leaflet.js, making it easy to create interactive maps in Jupyter notebooks.

Installation

pip install folium # Optional: for enhanced functionality pip install folium geopandas shapely

Basic Map with Tiles

import folium # Create base map m = folium.Map(location=[40, -100], zoom_start=6) # Add tile layer via proxy (backend handles token) folium.TileLayer( tiles='/api/tiles/{z}/{x}/{y}', attr='© Lynker Spatial', name='Protected Areas' ).add_to(m) folium.LayerControl().add_to(m) m.save('map.html')

Working with GeoPandas

import folium import geopandas as gpd from shapely.geometry import Point, box # Load vector data gdf = gpd.read_file('protected_areas.geojson') # Create map centered on data bounds = gdf.total_bounds center = [(bounds[1] + bounds[3])/2, (bounds[0] + bounds[2])/2] m = folium.Map(location=center, zoom_start=6) # Add GeoDataFrame as GeoJson layer folium.GeoJson( data=gdf, style_function=lambda x: { 'fillColor': '#088', 'color': '000', 'weight': 1, 'fillOpacity': 0.3 } ).add_to(m) # Add Lynker tiles as base layer # (via proxy endpoint) m.save('geopandas_map.html')

Spatial Data Analysis

import folium import geopandas as gpd # Load and analyze spatial data gdf = gpd.read_file('data.geojson') center = [gdf.total_bounds[1], gdf.total_bounds[0]] m = folium.Map(location=center, zoom_start=6) folium.GeoJson(data=gdf).add_to(m) m.save('map.html')

OpenLayers Integration

OpenLayers is a powerful, enterprise-grade mapping library suitable for complex GIS web applications.

Installation

# Via npm npm install ol # Via CDN <script src="https://cdn.jsdelivr.net/npm/ol@latest/dist/ol.js"></script> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/ol@latest/ol.css" />

Basic Map Setup

import Map from 'ol/Map'; import OSM from 'ol/source/OSM'; import TileLayer from 'ol/layer/Tile'; import VectorTileLayer from 'ol/layer/VectorTile'; import MVTFormat from 'ol/format/MVT'; import View from 'ol/View'; import { fromLonLat } from 'ol/proj'; // Create a map instance const map = new Map({ target: 'map', layers: [ new TileLayer({ source: new OSM() }) ], view: new View({ center: fromLonLat([-100, 40]), zoom: 6 }) }); // Add vector tile layer const vectorTileLayer = new VectorTileLayer({ source: new VectorTile({ format: new MVTFormat(), // Canonical tile URL: /{source}/{z}/{x}/{y} (omit .pbf extension) url: 'https://tiles.lynker-spatial.com/api/tiles/lynker-spatial-modeling-fabric/{z}/{x}/{y}', minZoom: 0, maxZoom: 14 }), style: { 'fill-color': '#088', 'stroke-color': '#000', 'stroke-width': 1, 'fill-opacity': 0.3 } }); map.addLayer(vectorTileLayer);

Advanced Styling

import { Style, Fill, Stroke, Icon } from 'ol/style'; const styleFunction = (feature) => { const protectionLevel = feature.get('protection_level'); let fillColor; switch(protectionLevel) { case 3: fillColor = '#cb181d'; break; case 2: fillColor = '#fb6a4a'; break; case 1: fillColor = '#fcae91'; break; default: fillColor = '#fee5d9'; } return new Style({ fill: new Fill({ color: fillColor }), stroke: new Stroke({ color: '#000', width: 1 }) }); }; vectorTileLayer.setStyle(styleFunction);

R Language Integration

R users can access Lynker Spatial tiles through several packages for geospatial analysis.

Installation

# Install required packages install.packages('leaflet') install.packages('sf') install.packages('ggplot2')

Basic Map with Leaflet

library(leaflet) m <- leaflet() %>% setView(lng = -100, lat = 40, zoom = 6) %>% addTiles() %>% addTiles( # Canonical direct tile URL (omit .pbf). For browser use, prefer a proxy # that injects the Authorization header. Example proxy URL shown elsewhere. urlTemplate = 'https://tiles.lynker-spatial.com/api/tiles/lynker-spatial-modeling-fabric/{z}/{x}/{y}', attribution = '© Lynker Spatial' ) m

Working with Spatial Data

library(sf) library(leaflet) # Load and display spatial data counties <- st_read('counties.geojson') leaflet(counties) %>% addTiles() %>% addPolygons(fillColor = ~colorQuantile("viridis", POPULATION)(POPULATION))

Static Maps

library(ggplot2) library(sf) states <- st_as_sf(maps::map('state', fill=TRUE, plot=FALSE)) ggplot(states) + geom_sf(aes(fill = NAME), alpha = 0.7) + theme_minimal()

Working with Raster Data

library(leaflet) # Display raster tiles with Leaflet leaflet() %>% addTiles() %>% addRasterImage(rasterData, opacity = 0.7)

OAuth2 Authentication Setup

For production tile access with secure authentication, Lynker Spatial provides an OAuth2-enabled tile proxy. This allows browsers and desktop applications to authenticate once and access tiles without manual token handling.

Why OAuth2?

Architecture Overview

Browser Application ↓ OAuth2 Tile Proxy (https://tiles.lynker-spatial.com) • Handles OAuth2 login/logout • Manages secure token storage • Enforces PKCE authentication • Injects tokens into tile requests ↓ Upstream Token Service (Cognito, Azure AD, or OIDC provider) • Issues & validates JWT tokens ↓ Lynker Spatial Tile CDN • Serves tiles with verified tokens

Quick Start: Browser-Based OAuth2 Flow

1. Check Status: GET /auth/session
2. Login: GET /auth/login?redirectTo=/home (in browser)
3. OAuth Provider: User signs in at OAuth provider
4. Redirect Back: Returns to /home with session cookie
5. Fetch Tiles: Browser now has authentication
6. Logout: POST /auth/logout to clear session

Client-Side Implementation (JavaScript/MapLibre)

const PROXY_URL = 'https://tiles.lynker-spatial.com'; // Check auth status async function checkAuth() { const response = await fetch(`${PROXY_URL}/auth/session`, { credentials: 'include' // Include cookies }); return await response.json(); } // Login function login() { // Redirect to OAuth provider window.location.href = `${PROXY_URL}/auth/login?redirectTo=${encodeURIComponent(window.location.pathname)}`; } // Logout async function logout() { await fetch(`${PROXY_URL}/auth/logout`, { method: 'POST', credentials: 'include' }); // Refresh auth status window.location.reload(); } // Add tiles after authentication async function initMap() { const session = await checkAuth(); if (!session.authenticated) { showLoginButton(); return; } // User is authenticated - add tile layers const map = new maplibregl.Map({ container: 'map', style: 'https://demotiles.maplibre.org/style.json', center: [-100, 40], zoom: 4 }); map.on('load', () => { map.addSource('lynker-tiles', { type: 'vector', tiles: [`${PROXY_URL}/api/tiles/lynker-spatial-modeling-fabric/{z}/{x}/{y}`], minzoom: 0, maxzoom: 14 }); map.addLayer({ id: 'flowpaths', type: 'line', source: 'lynker-tiles', 'source-layer': 'flowpath', paint: { 'line-color': '#0084ff', 'line-width': 1.5 } }); }); } initMap();

API Endpoints

Method Endpoint Auth Required Description
GET /health ❌ No Service health check
GET /catalog ❌ No List all available datasets with metadata
GET /:dataset ❌ No Get TileJSON metadata for specific dataset (e.g., /padus, /wetlands)
GET /auth/session ❌ No Check authentication status and session info
GET /auth/login?redirectTo=<path> ❌ No Start OAuth2 authentication flow (browser)
GET /auth/callback?code=<code>&state=<state> ❌ No OAuth provider redirect callback (automatic)
POST /auth/logout ✅ Yes Clear session and logout user
GET /api/tiles/:dataset/:z/:x/:y ✅ Yes Fetch tile (requires session authentication)

Interactive Example

Try the OAuth2 example in your browser: Open Interactive OAuth2 Example

This example demonstrates:

Configuration & Deployment

For detailed setup, configuration, and production deployment instructions, see:

Security Features

Advanced Usage Patterns

Direct HTTP Access

Access tiles with curl for testing:

# Download a single tile curl -H "Authorization: Bearer YOUR_TOKEN" \ https://tiles.lynker-spatial.com/api/tiles/lynker-spatial-modeling-fabric/5/9/11 \ -o tile.pbf

Simple Python Tile Request

import requests token = 'YOUR_TOKEN' url = 'https://tiles.lynker-spatial.com/api/tiles/lynker-spatial-modeling-fabric/5/9/11' response = requests.get(url, headers={'Authorization': f'Bearer {token}'}) if response.status_code == 200: with open('tile.pbf', 'wb') as f: f.write(response.content)

API Reference

Base URL

https://tiles.lynker-spatial.com

Core Endpoints

GET /catalog

List all available tile sources and metadata

curl -H "Authorization: Bearer YOUR_TOKEN" \ https://tiles.lynker-spatial.com/catalog Response (200 OK): { "tiles": { "padus": { "name": "Protected Areas Database of the US", "description": "Federal and state protected lands", "minzoom": 0, "maxzoom": 14, "bounds": [-180, -85.051129, 180, 85.051129], "center": [0, 0, 4], "attribution": "USDA, USGS, The Nature Conservancy" }, "wetlands": { "name": "National Wetland Inventory", "description": "Wetlands across the United States", "minzoom": 0, "maxzoom": 14 } } }

GET /api/tiles/{source}/{z}/{x}/{y}

Retrieve a vector tile

curl -H "Authorization: Bearer YOUR_TOKEN" \ https://tiles.lynker-spatial.com/api/tiles/lynker-spatial-modeling-fabric/5/9/11 \ -o tile.pbf Parameters: - source: Tile dataset identifier (padus, wetlands, hydrofabric, etc.) - z: Zoom level (0-14 depending on source) - x: Tile column index - y: Tile row index Response: Binary PBF/MVT data Status Codes: - 200: Tile found and returned - 401: Unauthorized (missing/invalid token) - 404: Tile not found - 429: Rate limit exceeded

HTTP Headers

Header Direction Required Description
Authorization Request Yes Bearer token: Bearer YOUR_TOKEN
User-Agent Request Recommended Identify your application
Accept-Encoding Request Recommended Use gzip for compression
Content-Type Response Yes application/octet-stream
X-Quota-Remaining-Bytes Response Yes Remaining bytes in the current monthly token quota
X-Quota-Total-Bytes Response Yes Total monthly quota in bytes for the token (e.g. 5368709120 = 5GB)

Rate Limiting

Enforced limits & behavior:

Error Responses

# 401 Unauthorized { "error": "Unauthorized", "message": "Invalid or expired token", "status": 401 } # 404 Not Found { "error": "Not Found", "message": "Tile not found at coordinates z/x/y", "status": 404 } # 429 Too Many Requests { "error": "Rate Limited", "message": "Too many requests. Retry after 60 seconds.", "status": 429, "retry_after": 60 }

Best Practices for API Calls

FAQs

How do I get a token?

Sign in at https://proxy.lynker-spatial.com and visit the /token page to copy your JWT.

What URL format should I use?

Tile URLs use the pattern https://tiles.lynker-spatial.com/{source}/{z}/{x}/{y}. Do not include the .pbf extension in MapLibre or client configs.

What happens when I hit quota limits?

API responses will return 429 Too Many Requests and include X-Quota-Remaining-Bytes and X-Quota-Total-Bytes headers. Implement exponential backoff and caching to avoid exhausting your monthly quota.