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.

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

FieldTypeRequiredDescription
refreshnumbernoPoll interval in seconds. Clamped to 2โ€“300s. Default 10s if missing. Drones might use 2, weather stations 60.
pointsarrayyesArray of point objects (see below). Empty array is valid.
idstringyesStable unique identifier. Max 60 characters.
latnumberyesLatitude in decimal degrees (-90 to 90).
lonnumberyesLongitude in decimal degrees (-180 to 180).
altnumbernoAltitude in meters (0โ€“100,000). Ground points (0 or missing) render as circles. Airborne points rise to altitude in 3D view.
headingnumbernoDirection in degrees (0โ€“360, 0 = north).
speednumbernoSpeed in meters per second (0โ€“1000). Shown in popup if present.
labelstringnoText shown in popup. Supports emoji and live data, e.g. ๐ŸŒง๏ธ | 12ยฐC Kaunas. Max 80 characters.
colorstringnoHex color, e.g. #FF6200. Default: #1DB95C.
originstringnoID of another point. Draws a line from that point to this one. Max 60 characters.

Rules

  • points must 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

  1. Enter your API URL in the Data Sources panel and click Connect.
  2. AirVeto makes a test request from your browser to validate the response.
  3. On success, the source is saved to your browser's local storage.
  4. AirVeto polls your endpoint every 10 seconds by default. Include a refresh field in your response to control the rate (2โ€“300 seconds).
  5. Ground points appear as colored circles on the map.
  6. Airborne points appear as flat circles in 2D. In 3D view, they rise to altitude with shadows below.
  7. Points with an origin field 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), vessels (AIS), 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

ProblemCauseFix
Connect stays grayCORS errorAdd Access-Control-Allow-Origin: * to your API
Points don't appearWrong schemaCheck points array with id, lat, lon
Points flickerNon-stable IDsKeep id the same between polls
Status dot turns redAPI non-200Check your API is online
URL rejectedHTTP endpointServe 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.

See it in action.

Sign in with GoogleยทNo credit card required
Custom Data Guide | AirVeto