ATLAS API Documentation
Map TIMs Dashboard

Overview

ATLAS (Advanced Tallahassee Live Automated Signals) is a V2X (Vehicle-to-Everything) signal visualization system for Tallahassee and Leon County, Florida. The external API provides real-time data from traffic signal controllers via the SAE J2735 standard.

Available Data Types

TypeNameDescription
spatSignal Phase and TimingReal-time signal states, phase timing, and countdown data for each intersection
mapMAP DataIntersection geometry including lane configurations, reference points, and approach nodes
timTraveler InformationAdvisories, work zones, hazard warnings, and road condition notices
bsmBasic Safety MessageVehicle position, speed, heading, and acceleration data

Base URL

https://<host>/api/v1/

Replace <host> with the hostname or IP address of the ATLAS server provided to you by the ATLAS administrator.

Quick Start

  1. Obtain an API key
    Contact the ATLAS administrator to request an API key. You will receive a key in the format atlas_live_ followed by 48 alphanumeric characters.
  2. Test connectivity
    Verify your key works by querying the status endpoint (public, no key needed):
    curl https://<host>/api/v1/status
    Then test with your key:
    curl -H "X-API-Key: YOUR_KEY" https://<host>/api/v1/snapshot/spat
  3. Connect to live SSE stream
    Open a persistent connection to receive real-time events:
    curl -N -H "X-API-Key: YOUR_KEY" https://<host>/api/v1/stream/spat
    The -N flag disables output buffering so events appear immediately.

Authentication

An API key is required for all data endpoints. Utility endpoints (status, intersections) are public.

Providing Your Key

MethodUsagePreferred
X-API-Key header curl -H "X-API-Key: YOUR_KEY" ... Yes (recommended)
?api_key= query parameter curl "...?api_key=YOUR_KEY" No (use for browser EventSource)
When both header and query parameter are provided, the header takes precedence.

Key Format

API keys follow the format: atlas_live_ prefix followed by 48 alphanumeric characters. Example: atlas_live_aBcDeFgHiJkLmNoPqRsTuVwXyZ012345678901234567

Scopes

Each API key is assigned scopes that control which message types it can access. Attempting to access a type outside your scopes returns a 403 error.

ScopeGrants Access To
spatSPaT streaming, snapshots, schemas, and samples
mapMAP streaming, snapshots, schemas, and samples
timTIM streaming, snapshots, schemas, and samples
bsmBSM streaming, snapshots, schemas, and samples
*All message types (wildcard)

Endpoints Reference

ATLAS provides 18 endpoints organized into 5 categories.

SSE Streaming (5 endpoints)

Server-Sent Events for real-time data. Connections remain open indefinitely.

MethodPathAuthDescription
GET /api/v1/stream Key All message types combined into one stream
GET /api/v1/stream/spat Key + scope:spat SPaT events only
GET /api/v1/stream/map Key + scope:map MAP events only
GET /api/v1/stream/tim Key + scope:tim TIM events only
GET /api/v1/stream/bsm Key + scope:bsm BSM events only

SSE Stream Format

Each event follows the W3C Server-Sent Events specification:

event: spat
data: {"intersection_id":"0_5433","timestamp":1706800000,...}
id: 42

A heartbeat comment (:ping) is sent every 15 seconds to keep the connection alive. Clients should implement auto-reconnect with exponential backoff.

Snapshots (4 endpoints)

Returns the latest cached data as a single JSON response (not streaming).

MethodPathAuthDescription
GET /api/v1/snapshot/spat Key + scope:spat Current SPaT data for all intersections
GET /api/v1/snapshot/map Key + scope:map Current MAP data for all intersections
GET /api/v1/snapshot/tim Key + scope:tim Current TIM data
GET /api/v1/snapshot/bsm Key + scope:bsm Current BSM data
JSON Schemas (4 endpoints)

Returns the JSON Schema describing the structure of each message type.

MethodPathAuthDescription
GET /api/v1/schema/spat Key SPaT event JSON Schema
GET /api/v1/schema/map Key MAP event JSON Schema
GET /api/v1/schema/tim Key TIM event JSON Schema
GET /api/v1/schema/bsm Key BSM event JSON Schema
Sample Streams (4 endpoints)

Replay recorded sample data for testing without needing a live data feed.

MethodPathAuthDescription
GET /api/v1/stream/sample/spat Key + scope:spat Replay sample SPaT data
GET /api/v1/stream/sample/map Key + scope:map Replay sample MAP data
GET /api/v1/stream/sample/tim Key + scope:tim Replay sample TIM data
GET /api/v1/stream/sample/bsm Key + scope:bsm Replay sample BSM data
Utility (2 endpoints)

Public endpoints that do not require authentication.

MethodPathAuthDescription
GET /api/v1/status Public Service health: uptime, SSE client count, data freshness
GET /api/v1/intersections Public List of active intersections with IDs and coordinates

Message Types

Below are representative JSON payloads for each message type. All data uses sanitized coordinates from Tallahassee intersections.

SPaT (Signal Phase and Timing)

Contains current signal states and timing for each phase at an intersection.

{
  "type": "SPAT",
  "data": {
    "SPAT": {
      "intersections": [
        {
          "id": {
            "region": 0,
            "id": 5433
          },
          "revision": 2,
          "status": "0000000000000000",
          "states": [
            {
              "signalGroup": 2,
              "state-time-speed": [
                {
                  "eventState": "permissive-Movement-Allowed",
                  "timing": {
                    "minEndTime": 12340,
                    "maxEndTime": 15670,
                    "likelyTime": 14200
                  }
                }
              ]
            },
            {
              "signalGroup": 6,
              "state-time-speed": [
                {
                  "eventState": "stop-And-Remain",
                  "timing": {
                    "minEndTime": 25600
                  }
                }
              ]
            }
          ],
          "moy": 346521,
          "timeStamp": 23456
        }
      ]
    }
  }
}

MAP (Intersection Geometry)

Describes intersection layout including lane configurations and reference points.

{
  "type": "MAP",
  "data": {
    "MapData": {
      "msgIssueRevision": 3,
      "layerType": "intersectionData",
      "intersections": [
        {
          "id": {
            "region": 0,
            "id": 5433
          },
          "revision": 3,
          "refPoint": {
            "lat": 304434500,
            "long": -842808300,
            "elevation": 150
          },
          "laneWidth": 366,
          "laneSet": [
            {
              "laneID": 1,
              "laneAttributes": {
                "directionalUse": "10",
                "sharedWith": "0000000000",
                "laneType": {"vehicle": "00000000"}
              },
              "maneuvers": "010000000000",
              "nodeList": {
                "nodes": [
                  {"delta": {"node-XY3": {"x": 145, "y": -1023}}},
                  {"delta": {"node-XY3": {"x": 32, "y": -845}}}
                ]
              },
              "connectsTo": [
                {"connectingLane": {"lane": 10, "maneuver": "010000000000"}}
              ]
            }
          ],
          "speedLimits": [
            {"type": "vehicleMaxSpeed", "speed": 560}
          ]
        }
      ]
    }
  }
}

TIM (Traveler Information Message)

Advisories, work zone alerts, and hazard warnings broadcast to travelers.

{
  "type": "TIM",
  "data": {
    "TravelerInformation": {
      "msgCnt": 1,
      "timeStamp": 487234,
      "packetID": "00000000001A",
      "dataFrames": [
        {
          "sspTimRights": 0,
          "frameType": "advisory",
          "msgId": {
            "roadSignID": {
              "position": {
                "lat": 304450000,
                "long": -842790000
              },
              "viewAngle": "1111111111111111",
              "mutcdCode": "warning"
            }
          },
          "startYear": 2026,
          "startTime": 346521,
          "durationTime": 1440,
          "priority": 5,
          "sspLocationRights": 3,
          "regions": [
            {
              "name": "Mahan Dr Construction Zone",
              "anchor": {
                "lat": 304450000,
                "long": -842790000
              },
              "laneWidth": 500,
              "directionality": "both",
              "description": {
                "path": {
                  "offset": {
                    "xy": {
                      "nodes": [
                        {"delta": {"node-LatLon": {"lat": 304451000, "lon": -842788000}}},
                        {"delta": {"node-LatLon": {"lat": 304452000, "lon": -842786000}}}
                      ]
                    }
                  }
                }
              }
            }
          ],
          "sspMsgRights1": 1,
          "sspMsgRights2": 1,
          "content": {
            "advisory": [
              {"item": {"itis": 7426}},
              {"item": {"text": "Road work ahead - reduce speed"}}
            ]
          }
        }
      ]
    }
  }
}

BSM (Basic Safety Message)

Vehicle position, speed, heading, and other safety-critical data.

{
  "type": "BSM",
  "data": {
    "BasicSafetyMessage": {
      "coreData": {
        "msgCnt": 42,
        "id": "a1b2c3d4",
        "secMark": 34521,
        "lat": 304440000,
        "long": -842800000,
        "elev": 152,
        "accuracy": {
          "semiMajor": 50,
          "semiMinor": 50,
          "orientation": 0
        },
        "transmission": 0,
        "speed": 1500,
        "heading": 18000,
        "angle": 0,
        "accelSet": {
          "long": 0,
          "lat": 0,
          "vert": 0,
          "yaw": 0
        },
        "brakes": {
          "wheelBrakes": 0,
          "traction": 0,
          "abs": 0,
          "scs": 0,
          "brakeBoost": 0,
          "auxBrakes": 0
        },
        "size": {
          "width": 200,
          "length": 500
        }
      }
    }
  }
}

Query Parameters

ParameterApplies ToDescription
intersections SSE streams, snapshots Comma-separated intersection IDs to filter results. Example: ?intersections=0_5433,0_5434
bbox SSE streams, snapshots Bounding box filter: ?bbox=lat1,lon1,lat2,lon2. Reserved for future use; accepted but not yet applied.
api_key All authenticated endpoints Alternative to X-API-Key header. Required for browser EventSource which cannot set custom headers.

Intersection ID Format

Intersection IDs use the format {region}_{intersection_id} where region is typically 0 and the intersection_id is assigned by the traffic signal controller. Use the /api/v1/intersections endpoint to discover available IDs.

Error Reference

All errors return a JSON body with a detail field describing the issue.

400 Bad Request

The request contains an invalid message type.

{"detail": "Invalid message type 'xyz'. Must be one of: bsm, map, spat, tim"}

401 Unauthorized

No API key was provided, or the key is invalid, revoked, or expired.

{"detail": "API key required. Provide via X-API-Key header or ?api_key= query parameter."}

403 Forbidden

The API key does not have the required scope for the requested message type.

{"detail": "Key not authorized for 'bsm'. Allowed: ['spat', 'map']"}

404 Not Found

The requested resource or endpoint does not exist.

{"detail": "Not Found"}

429 Too Many Requests

The API key has exceeded its concurrent connection limit.

{"detail": "Connection limit reached. Limit: 5 concurrent, currently using 5."}

503 Service Unavailable

SSE streaming is not available (the service may be starting up or SSE is disabled).

{"detail": "SSE streaming is not available"}

Rate Limits and Connection Limits

Key Tiers

TierScopesMax Concurrent SSE Connections
basicTypically 1-2 types (e.g., spat, map)2
standardTypically 3-4 types5
fullAll types (*)10

Limits

  • Per-key concurrent SSE connections: Varies by tier (see table above). Exceeding the limit returns HTTP 429.
  • Global maximum SSE clients: 100 simultaneous connections across all keys.
  • Snapshot and schema endpoints: No request rate limit. These are standard HTTP requests, not long-lived connections.
Connection limits apply to SSE streaming endpoints only. Snapshot and schema endpoints are not rate-limited and can be called as frequently as needed.

Network Requirements

  • HTTPS required — All API traffic must use port 443 (TLS).
  • Long-lived connections — SSE streams remain open indefinitely. Your HTTP client and any proxies must not impose a request timeout.
  • Firewall rules — Allow outbound HTTPS (TCP 443) to the ATLAS server IP.
  • Keep-alive — The server sends a :ping heartbeat comment every 15 seconds. If you do not receive data or a heartbeat for 30+ seconds, the connection may be broken.
  • Reconnection — Clients should implement auto-reconnect with exponential backoff (e.g., 1s, 2s, 4s, 8s, max 30s). The browser EventSource API handles this automatically.

Recommended Client Environments

EnvironmentNotes
Server-side (Python, Node.js, curl) Recommended for production integrations. Use X-API-Key header.
Browser (JavaScript) Use ?api_key= query parameter since EventSource cannot set custom headers. Be aware the key is visible in the URL.
Browser security note: The EventSource API does not support custom HTTP headers. When connecting from a browser, pass the API key as a query parameter (?api_key=YOUR_KEY). This exposes the key in browser history and server logs. For production systems, prefer server-side consumers.

Client Examples

curl

# Stream all SPaT events (press Ctrl+C to stop)
curl -N -H "X-API-Key: YOUR_KEY" https://<host>/api/v1/stream/spat

# Get current snapshot of all MAP data
curl -H "X-API-Key: YOUR_KEY" https://<host>/api/v1/snapshot/map

# Filter stream by specific intersections
curl -N -H "X-API-Key: YOUR_KEY" \
  "https://<host>/api/v1/stream/spat?intersections=0_5433,0_5434"

# Check service status (no key required)
curl https://<host>/api/v1/status

# Get JSON Schema for SPaT events
curl -H "X-API-Key: YOUR_KEY" https://<host>/api/v1/schema/spat

Python (with sseclient-py)

Install the client library: pip install sseclient-py requests

import sseclient
import requests
import json

# Connect to the SPaT stream
url = "https://<host>/api/v1/stream/spat"
headers = {"X-API-Key": "YOUR_KEY"}

response = requests.get(url, headers=headers, stream=True, verify=False)
client = sseclient.SSEClient(response)

for event in client.events():
    print(f"Event type: {event.event}")
    data = json.loads(event.data)
    print(f"  Intersection: {data.get('intersection_id', 'N/A')}")
    print(f"  Data: {json.dumps(data, indent=2)[:200]}...")
    print()

JavaScript (EventSource)

For browser-based consumers. Note: API key must be passed as a query parameter.

// Connect to the SPaT stream
const source = new EventSource(
  "https://<host>/api/v1/stream/spat?api_key=YOUR_KEY"
);

// Listen for SPaT events
source.addEventListener("spat", (event) => {
  const data = JSON.parse(event.data);
  console.log("SPaT update:", data);
});

// Handle connection errors
source.onerror = (error) => {
  console.error("SSE connection error:", error);
  // EventSource will automatically reconnect
};

// Listen for all event types on a combined stream
// const allSource = new EventSource(
//   "https://<host>/api/v1/stream?api_key=YOUR_KEY"
// );
// allSource.addEventListener("spat", handler);
// allSource.addEventListener("map", handler);
// allSource.addEventListener("tim", handler);
// allSource.addEventListener("bsm", handler);

Node.js (eventsource package)

Install: npm install eventsource

const EventSource = require("eventsource");

const url = "https://<host>/api/v1/stream/spat";
const source = new EventSource(url, {
  headers: { "X-API-Key": "YOUR_KEY" }
});

source.addEventListener("spat", (event) => {
  const data = JSON.parse(event.data);
  console.log("SPaT:", data);
});

source.onerror = (err) => {
  console.error("Connection error:", err);
};