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.

Step 1 — Get a token (Python)

# pip install boto3 import boto3, os def get_token(username, password): client = boto3.client('cognito-idp', region_name='us-west-2') resp = client.initiate_auth( AuthFlow='USER_PASSWORD_AUTH', AuthParameters={'USERNAME': username, 'PASSWORD': password}, ClientId='73r3fn6gi8f3qhha2m5n0197v4' ) return resp['AuthenticationResult']['AccessToken'] TOKEN = get_token( os.environ['LYNKER_USERNAME'], os.environ['LYNKER_PASSWORD'] ) print(TOKEN) # copy into LYNKER_TOKEN, or use directly below

Step 2 — Verify token + service

curl -H "Authorization: Bearer $LYNKER_TOKEN" \ https://tiles.lynker-spatial.com/catalog

Step 3 — Pull a tile

curl -H "Authorization: Bearer $LYNKER_TOKEN" \ https://tiles.lynker-spatial.com/api/tiles/lynker-spatial-modeling-fabric/5/9/11 \ -o tile.pbf

Step 4 — MapLibre source config

tiles: ['https://tiles.lynker-spatial.com/api/tiles/lynker-spatial-modeling-fabric/{z}/{x}/{y}'] 'source-layer': 'flowpath'
Token refresh: Access tokens expire after 1 day. Call get_token() again or use the RefreshToken from AuthenticationResult with AuthFlow='REFRESH_TOKEN_AUTH' to avoid re-entering credentials.

The Lynker Spatial Tile Service consists of:

Quick Start: Five Steps

Quick Setup Checklist

Verify your email (if new account)
Retrieve your token via the Python snippet above (boto3) or copy it from the portal after signing in
Export it: export LYNKER_TOKEN=<your token>
Verify access:
curl -H "Authorization: Bearer $LYNKER_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

Use the Python boto3 snippet in the Quick Start above, or sign in at the portal and copy your token from the session.

🚀 Step 4: Start Using Tiles

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

Token Management

Retrieve your token programmatically with boto3 (see Quick Start) or copy it from the portal after signing in. Tokens are user-specific — one token per user account, not shared across an organization.

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

Programmatic (recommended for scripts and pipelines):

import boto3, os def get_token(username, password): client = boto3.client('cognito-idp', region_name='us-west-2') resp = client.initiate_auth( AuthFlow='USER_PASSWORD_AUTH', AuthParameters={'USERNAME': username, 'PASSWORD': password}, ClientId='73r3fn6gi8f3qhha2m5n0197v4' ) auth = resp['AuthenticationResult'] return auth['AccessToken'], auth['RefreshToken'] token, refresh = get_token( os.environ['LYNKER_USERNAME'], os.environ['LYNKER_PASSWORD'] ) # Later, refresh without re-entering credentials: def refresh_token(refresh_tok): client = boto3.client('cognito-idp', region_name='us-west-2') resp = client.initiate_auth( AuthFlow='REFRESH_TOKEN_AUTH', AuthParameters={'REFRESH_TOKEN': refresh_tok}, ClientId='73r3fn6gi8f3qhha2m5n0197v4' ) return resp['AuthenticationResult']['AccessToken']

Tokens expire after 1 day. Store the RefreshToken securely (it lasts 30 days) and call refresh_token() before making tile requests rather than re-authenticating from scratch each time.

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: Access tokens expire after 1 day; refresh tokens expire after 30 days. Read the token's expires_in field and implement proactive refresh logic a few minutes before expiry. 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

Access Control

Access is controlled by token validity and monthly quota, not by fine-grained scopes. A valid JWT grants read access to all tile sources. Quota consumption is tracked per token by JWT ID (jti claim) and resets monthly. Enterprise API keys (X-Api-Key / X-Enterprise-Key) bypass JWT validation and quota tracking.

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', () => { map.addSource('hydrofabric', { type: 'vector', tiles: ['https://tiles.lynker-spatial.com/api/tiles/lynker-spatial-modeling-fabric/{z}/{x}/{y}'], minzoom: 0, maxzoom: 14 }); map.addLayer({ id: 'flowpaths', type: 'line', source: 'hydrofabric', 'source-layer': 'flowpath', paint: { 'line-color': '#0084ff', 'line-width': 1.5, 'line-opacity': 0.8 } }); }); </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/lynker-spatial-modeling-fabric/{z}/{x}/{y}'; map.addSource('hydrofabric', { type: 'vector', tiles: [tileUrl], minzoom: 0, maxzoom: 14 }); // Your backend proxy adds the Authorization header // Example Express.js proxy: app.get('/api/proxy/tiles/lynker-spatial-modeling-fabric/:z/:x/:y', (req, res) => { const { z, x, y } = req.params; const tileUrl = `https://tiles.lynker-spatial.com/api/tiles/lynker-spatial-modeling-fabric/${z}/${x}/${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 — for example, scaling line width by stream order:

map.addLayer({ id: 'flowpaths-styled', type: 'line', source: 'hydrofabric', 'source-layer': 'flowpath', paint: { 'line-color': '#0084ff', 'line-width': [ 'interpolate', ['linear'], ['get', 'order_'], 1, 0.5, 4, 2, 7, 5 ], 'line-opacity': [ 'case', ['boolean', ['feature-state', 'hover'], false], 1.0, 0.7 ] } }); // Highlight on hover map.on('mousemove', 'flowpaths-styled', (e) => { if (e.features.length > 0) { map.setFeatureState( { source: 'hydrofabric', id: e.features[0].id }, { hover: true } ); } });

Interactivity

// Click handler for feature information map.on('click', 'flowpaths', (e) => { const properties = e.features[0].properties; new maplibregl.Popup() .setLngLat(e.lngLat) .setHTML(` <h3>Flowpath</h3> <p>ID: ${properties.id}</p> <p>Length: ${properties.lengthkm} km</p> `) .addTo(map); }); // Change cursor on hover map.on('mouseenter', 'flowpaths', () => { map.getCanvas().style.cursor = 'pointer'; }); map.on('mouseleave', 'flowpaths', () => { 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 Hydrofabric 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, 'Modeling Hydrofabric') # 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('lynker-spatial-modeling-fabric', 'Modeling Hydrofabric') 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
Note: The tile service does not expose a WMS or WMTS endpoint. All datasets are served as vector tiles (MVT/PBF) only. ArcGIS Pro 3.x and ArcGIS Online support vector tile connections natively.

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/lynker-spatial-modeling-fabric/${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)

Configuration & Deployment

For API endpoint reference and quick-start curl commands, see QUICK_REFERENCE.md in the tiles-proxy directory.

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. No authentication required.

curl https://tiles.lynker-spatial.com/catalog Response (200 OK): { "tiles": { "lynker-spatial-modeling-fabric": { "name": "Modeling Hydrofabric", "description": "Next-generation hydrographic reference network designed for distributed hydrologic modeling and water resources analysis.", "category": "Hydrology", "attribution": "Lynker Spatial" }, "rivers": { "name": "Continental Rivers", "description": "Comprehensive national river network optimized for visualization and spatial analysis of hydrographic data.", "category": "Hydrology", "attribution": "USGS" }, "wetlands": { "name": "National Wetlands", "description": "Comprehensive mapping of wetland ecosystems and habitats across the continent for conservation planning.", "category": "Environment", "attribution": "USFWS" } // ... all 13 sources } }

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 (lynker-spatial-modeling-fabric, rivers, wetlands, 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 - 204: Authorized but no tile data at this coordinate (valid empty response) - 401: Unauthorized (missing or invalid token) - 429: Monthly quota 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. 3221225472 = 3 GB)

Rate Limiting

Enforced limits & behavior:
  • Monthly data quota: 3 GB per token (default: 3221225472 bytes). The service returns X-Quota-Remaining-Bytes and X-Quota-Total-Bytes headers on tile responses.
  • Request throttling: The application does not enforce a fixed requests-per-minute per token. Request-level throttling and global protections (CDN, API Gateway, WAF) are used in production and may vary by deployment.
  • Quota enforcement: When a token exceeds its monthly quota the service returns HTTP 429 Too Many Requests. Implement local caching and exponential backoff to avoid hitting quotas.

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?

Use the boto3 snippet in the Quick Start section — pass your portal username and password and it returns your AccessToken and RefreshToken directly. No browser required for scripts.

What URL format should I use?

Tile URLs use the pattern https://tiles.lynker-spatial.com/api/tiles/{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.