Custom data guide.
Connect your own data sources to AirVeto and see them rendered on the map in real time. Your browser fetches directly from your API โ nothing passes through AirVeto servers.
Who uses custom data overlays
Border-security teams and OSINT analysts use custom data overlays to combine AirVeto's wind-field and cross-border inflow detection with their own sensors and intelligence feeds. Defence researchers overlay drone telemetry and radar detections to track airspace activity. News organisations and think tanks integrate fleet GPS and sensor networks for situational awareness reporting on EU eastern-border security.
Requirements
- HTTPS only โ your API must be served over HTTPS. Browsers block mixed content from HTTPS pages.
- CORS headers โ your API must return
Access-Control-Allow-Origin: *or the browser will block the response. - JSON response โ must conform to the schema below.
- Pro subscription โ custom data sources require an active AirVeto Pro plan.
Response Schema
Your API endpoint must return this JSON shape:
{
"refresh": 5,
"points": [
{
"id": "station-001",
"lat": 54.6872,
"lon": 25.2797,
"alt": 150,
"label": "๐ก | Active Vilnius",
"origin": "radar-01"
}
]
}Fields
| Field | Type | Required | Description |
|---|---|---|---|
refresh | number | no | Poll interval in seconds. Clamped to 2โ300s. Default 10s if missing. Drones might use 2, weather stations 60. |
points | array | yes | Array of point objects (see below). Empty array is valid. |
id | string | yes | Stable unique identifier. Max 60 characters. |
lat | number | yes | Latitude in decimal degrees (-90 to 90). |
lon | number | yes | Longitude in decimal degrees (-180 to 180). |
alt | number | no | Altitude in meters (0โ100,000). Ground points (0 or missing) render as circles. Airborne points rise to altitude in 3D view. |
heading | number | no | Direction in degrees (0โ360, 0 = north). |
speed | number | no | Speed in meters per second (0โ1000). Shown in popup if present. |
label | string | no | Text shown in popup. Supports emoji and live data, e.g. ๐ง๏ธ | 12ยฐC Kaunas. Max 80 characters. |
color | string | no | Hex color, e.g. #FF6200. Default: #1DB95C. |
origin | string | no | ID of another point. Draws a line from that point to this one. Max 60 characters. |
Rules
pointsmust be an array. Empty array is valid.- Maximum 50 points per response. Extra points are truncated.
- All string fields are sanitized โ HTML tags are stripped, length capped.
- Colors must be valid hex (
#RGB,#RRGGBB, or#RRGGBBAA). Invalid colors are ignored. - Numeric fields are clamped: altitude 0โ100,000m, heading 0โ360ยฐ, speed 0โ1,000 m/s.
- Points outside valid lat/lon ranges are dropped.
- Your API must respond within 8 seconds or the request is aborted.
How It Works
- Enter your API URL in the Data Sources panel and click Connect.
- AirVeto makes a test request from your browser to validate the response.
- On success, the source is saved to your browser's local storage.
- AirVeto polls your endpoint every 10 seconds by default. Include a
refreshfield in your response to control the rate (2โ300 seconds). - Ground points appear as colored circles on the map.
- Airborne points appear as flat circles in 2D. In 3D view, they rise to altitude with shadows below.
- Points with an
originfield draw connection lines to their source.
Authentication
AirVeto does not manage API keys. Two options:
- IP whitelist โ configure your API to allow requests from your IP. The browser makes requests directly.
- Query parameter โ embed credentials in the URL:
https://api.example.com/data?key=YOUR_KEY. Stored in your browser only.
CORS Setup
Your API must include CORS headers or the browser will block the response entirely. This is the most common issue.
Node.js / Express:
app.use((req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', '*');
next();
});Python / Flask:
from flask_cors import CORS
CORS(app)Python / FastAPI:
from fastapi.middleware.cors import CORSMiddleware
app.add_middleware(CORSMiddleware, allow_origins=["*"], allow_methods=["GET"])Nginx:
add_header Access-Control-Allow-Origin *;Examples
Custom APIs are for your own data sources. Aircraft (ADS-B) and satellites (TLE) are already built-in โ toggle them in the Data Sources panel.
Drone telemetry
Track a drone's live position. The label field supports any text โ include live data, status, or emoji for quick identification.
{
"points": [
{
"id": "drone-01",
"lat": 54.2341,
"lon": 25.0128,
"alt": 120,
"heading": 315,
"speed": 8.5,
"color": "#FF6200",
"label": "๐ธ | 120m Survey Drone"
}
]
}Radar network with detections
Radar stations on the ground, detected targets in the air. The origin field draws connection lines from origin to target.
{
"points": [
{
"id": "radar-vilnius",
"lat": 54.6339,
"lon": 24.9106,
"color": "#1DB95C",
"label": "๐ก | 12 targets Vilnius"
},
{
"id": "uav-001",
"lat": 54.58,
"lon": 25.02,
"alt": 450,
"speed": 12,
"color": "#f87171",
"label": "โ ๏ธ Unknown UAV",
"origin": "radar-vilnius"
}
]
}Weather stations
Ground-based sensors with live readings in the label. No altitude needed โ points render as circles on the map.
{
"refresh": 60,
"points": [
{
"id": "wx-kaunas",
"lat": 54.8985,
"lon": 23.9036,
"color": "#fbbf24",
"label": "๐ง๏ธ | 12ยฐC Kaunas"
},
{
"id": "wx-vilnius",
"lat": 54.6872,
"lon": 25.2797,
"color": "#60a5fa",
"label": "โ๏ธ | 15ยฐC Vilnius"
}
]
}Vehicle / fleet GPS
Track patrol units or research vehicles. Each vehicle has a stable ID.
{
"points": [
{
"id": "unit-alpha",
"lat": 54.3521,
"lon": 25.7843,
"heading": 90,
"speed": 16.7,
"label": "๐ | 60 km/h Alpha"
},
{
"id": "unit-bravo",
"lat": 54.1892,
"lon": 25.3017,
"speed": 0,
"label": "๐ | Stationary Bravo"
}
]
}Create Your API with AI
Not a developer? Paste this prompt into Claude, ChatGPT, or any AI assistant to generate a working API:
Build me a simple API server that returns JSON for AirVeto custom data sources.
Requirements:
- Single GET endpoint at /api/data
- Returns JSON matching this exact schema:
{
"points": [
{
"id": "unique-stable-id",
"lat": 54.6872,
"lon": 25.2797,
"alt": 150,
"label": "Description text"
}
]
}
- "id", "lat", "lon" are required. "alt" (meters), "label" are optional.
- Maximum 50 points.
- Must include CORS header: Access-Control-Allow-Origin: *
- Must serve over HTTPS.
- Each point's "id" must stay the same between requests.
My data: [DESCRIBE YOUR DATA HERE]
Give me the complete code and instructions to deploy for free on Vercel or Railway.Limitations
- Browser-only โ requests come from your browser. Your API sees your IP address.
- Polling only โ every 10 seconds. No WebSocket support yet.
- No field mapping โ your API must return the exact schema above.
- Local storage โ clearing browser data removes custom sources.
- 50 point cap โ per source, per response.
Troubleshooting
| Problem | Cause | Fix |
|---|---|---|
| Connect stays gray | CORS error | Add Access-Control-Allow-Origin: * to your API |
| Points don't appear | Wrong schema | Check points array with id, lat, lon |
| Points flicker | Non-stable IDs | Keep id the same between polls |
| Status dot turns red | API non-200 | Check your API is online |
| URL rejected | HTTP endpoint | Serve over HTTPS (Cloudflare, Vercel, Railway) |
Privacy
- Your API URL is stored only in your browser's local storage.
- AirVeto servers never see or proxy your custom data requests.
- Data is held in browser memory and discarded when you close the tab.
- Other users cannot see your custom data sources.