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
Hydrofabric Nexus: Watershed divides, flowlines, and routing networks
PADUS: Protected Areas Database of the United States
Wetlands: National Wetland Inventory data
Flowline Features: Stream classification and geometry
Reservoirs: Dam and reservoir locations and characteristics
Earth Observation: Flooding, land cover, and hazard analysis
Key Features
Vector tiles in PMTiles/MVT format for efficient delivery
Zoom level support from 0 to 28 for detailed mapping
JWT Bearer token authentication for secure access
Monthly data quota per token (5 GB) with production request throttling handled by CDN/API layer
RESTful API with catalog discovery
Support for all major Web GIS platforms
Low-latency delivery via AWS CloudFront CDN
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:
Base URL: https://tiles.lynker-spatial.com
Tile Format: PBF (Protocol Buffers) / PMTiles
Authentication: JWT Bearer Token (expires per Cognito app client; this deployment uses 1 day)
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
Internet Connection: HTTPS connections required
HTTP/2 Support: Recommended for efficient tile streaming
TLS 1.2+: For secure authentication
Standard GIS Software: Works with MapLibre, QGIS, ArcGIS, Leaflet, etc.
Sign Up & Account Setup
📧 Step 1: Create or Sign In
Visit the Lynker Spatial authentication portal to create an account or sign in.
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:
View your current access token
Token expiry varies by Cognito app client. This deployment uses 1 day access/ID tokens and 30 day refresh tokens; clients should read the token's `expires_in` and refresh a few minutes before expiry.
Use in Authorization header: Bearer <token>
Refresh tokens automatically when they expire
Tokens are user-specific, not organization-wide
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:
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
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' />
# 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>
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.
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?
User-Friendly: Sign in once via browser OAuth flow
Secure: Tokens stored in HttpOnly cookies (not accessible to JavaScript)
Automatic Refresh: Tokens refresh automatically before expiration
No Manual Headers: Authentication handled server-side by the proxy
PKCE Protected: RFC 7636 compliant protection against authorization code interception
CSRF Protection: State and nonce validation prevents cross-site attacks
HttpOnly Cookies: Tokens never accessible to JavaScript (prevents XSS)
Automatic Token Refresh: Refreshes tokens before expiration with backoff retry
Token Redaction: Tokens automatically redacted in logs
Secure Session Storage: Redis-ready abstraction for scaling
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:
Monthly data quota: 5 GB per token (default: 5368709120 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
Implement connection pooling to reuse HTTP connections
Use HTTP/2 for multiplexing multiple tile requests
Enable gzip compression in Accept-Encoding
Cache tiles locally to reduce API calls
Implement exponential backoff for rate limit retries
Monitor X-Quota-Remaining-Bytes header to avoid hitting quota limits
Set appropriate timeout values (30 seconds recommended)
Include meaningful User-Agent for analytics
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.