openbart / docs overview openbart is an open-source REST JSON API for Bay Area Rapid Transit (BART) data. it bundles the static schedule, real-time trip updates, service alerts, and rolled-up line health into a single simple API.
all endpoints are GET , return JSON, and are served from https://openbart.com . the base path is /api/v1 .
CORS is enabled for all origins, so you can call the API directly from a browser.
authentication the API is open and works with no authentication. if you want a higher rate limit, pass an API key on every request using one of:
Authorization: Bearer <your-key>
X-API-Key: <your-key> keys look like ob_sk_... . see rate limits below for how to request one.
rate limits every response includes these headers so you can track usage:
X-RateLimit-Limit: <your limit per minute>
X-RateLimit-Remaining: <requests left in this window>
X-RateLimit-Reset: <unix timestamp when the window resets> unauthenticated — 60 requests per minute per IP
authenticated — 300 requests per minute per key (default; configurable per key)
when you exceed the limit you'll get a 429 response with a Retry-After header.
need a higher limit, or want another transit agency indexed alongside BART? reach out to @theharryet on twitter.
responses single resources are returned directly as a JSON object:
{ "id": "DBRK", "name": "Downtown Berkeley", ... } list endpoints use a consistent pagination envelope:
{
"items": [...],
"pagination": { "offset": 0, "limit": 50, "total": 234 }
} pagination params: ?offset=0&limit=50 (default 50, max 200).
errors return a standard shape with a matching HTTP status:
{ "error": { "code": "NOT_FOUND", "message": "Stop 'FAKE' not found" } } 200 — success
400 — bad request (invalid params)
401 — invalid or disabled API key
404 — resource not found
429 — rate limited
500 — internal server error
endpoints stops routes trips realtime alerts status system /stops stations and their platforms. each BART station is a parent stop with one or more platform children.
GET /api/v1/stops
list all stops
query params:
parent_only (boolean) — only return parent stations (no platforms)
offset (integer) — pagination offset (default 0)
limit (integer) — page size (default 50, max 200)
returns: { items: Stop[], pagination: { offset, limit, total } }
GET /api/v1/stops/:id
single stop with its platforms (if parent) or parent station (if platform)
path params:
id (string, required) — stop id (e.g. DBRK)
returns: Stop & { children: Stop[], parent: Stop | null }
GET /api/v1/stops/:id/arrivals
next N arrivals at a stop (sorted by arrival time), with route info and real-time delays overlaid
path params:
id (string, required) — stop id
query params:
limit (integer) — number of upcoming arrivals (default 10, max 50)
route_id (string) — filter by route id
returns: { stopId, date, arrivals: [{ tripId, routeId, route, headsign, directionId, stopId, platformCode, stopSequence, arrivalTime, departureTime, realtime: { delay, uncertainty, predictedArrivalUnix } | null }] }
GET /api/v1/stops/:id/departures
next N departures from a stop, with route info and real-time delays overlaid
path params:
id (string, required) — stop id
query params:
limit (integer) — number of upcoming departures (default 10, max 50)
route_id (string) — filter by route id
returns: { stopId, date, departures: [{ tripId, routeId, route, headsign, directionId, stopId, platformCode, stopSequence, arrivalTime, departureTime, realtime: { delay, uncertainty, predictedDepartureUnix } | null }] }
GET /api/v1/stops/:id/history
on-time performance for a station over the last N days
path params:
id (string, required) — stop id
query params:
days (integer) — window size in days (1–30, default 7)
returns: { stopId, days, totalSamples, onTimePct, avgDelaySec, worstDelaySec, majorDelayCount }
GET /api/v1/stops/:id/schedule
full scheduled day timetable for a stop
path params:
id (string, required) — stop id
query params:
date (string) — YYYYMMDD (defaults to today in America/Los_Angeles)
route_id (string) — filter by route id
returns: { stopId, date, items: StopTime[] }
/routes BART lines (Red, Blue, Yellow, Green, Orange, and others). each route has a color and direction.
GET /api/v1/routes
list all routes
returns: { items: Route[], pagination }
GET /api/v1/routes/:id
single route
path params:
id (string, required) — route id
returns: Route
GET /api/v1/routes/:id/trips
trips that run on this route
path params:
id (string, required) — route id
query params:
direction_id (0 | 1) — filter by direction
offset (integer) — pagination offset
limit (integer) — page size
returns: { items: Trip[], pagination }
GET /api/v1/routes/:id/stops
ordered list of stops along the route
path params:
id (string, required) — route id
query params:
direction_id (0 | 1) — filter by direction
returns: { routeId, directionId, stops: [{ stopId, name, lat, lon, stopSequence }] }
/trips a trip is a single train run — one vehicle going one direction on one route at a specific time.
GET /api/v1/trips/:id
single trip with its route info
path params:
id (string, required) — trip id
returns: Trip & { route: Route }
GET /api/v1/trips/:id/stop-times
all scheduled stops for a trip, with real-time delays overlaid
path params:
id (string, required) — trip id
returns: { tripId, items: [StopTime & { realtime: { arrivalDelay, departureDelay, ... } | null }] }
/realtime live trip updates from BART's GTFS-RT feed. refreshed every minute.
GET /api/v1/realtime/trip-updates
latest real-time snapshot for all trips
query params:
route_id (string) — filter by route id
trip_id (string) — filter by trip id
returns: { items: TripUpdate[], pagination }
GET /api/v1/realtime/trip-updates/:tripId
latest real-time update for a single trip, including per-stop delays
path params:
tripId (string, required) — trip id
returns: TripUpdate & { stopTimeUpdates: StopTimeUpdate[] }
GET /api/v1/realtime/stops/:stopId
latest real-time updates affecting a specific stop
path params:
stopId (string, required) — stop id
returns: { stopId, items: StopTimeUpdate[], pagination }
/alerts service disruptions, delays, and advisories published by BART.
GET /api/v1/alerts
active alerts, optionally filtered by route or stop
query params:
route_id (string) — only alerts affecting this route
stop_id (string) — only alerts affecting this stop
include_expired (boolean) — also include deleted/expired alerts
offset (integer) — pagination offset
limit (integer) — page size
returns: { items: (Alert & { informedEntities: InformedEntity[] })[], pagination }
GET /api/v1/alerts/:id
single alert with informed entities and optional version history
path params:
id (integer, required) — alert id
query params:
include_history (boolean) — include all past versions of this alert
returns: Alert & { informedEntities, history?: AlertVersion[] }
/status rolled-up service health — current line status and 90-day on-time performance.
GET /api/v1/status
overall system health and per-line status summary
returns: { overallStatus, generatedAt, lines: LineSummary[], activeAlertCount }
GET /api/v1/status/lines
per-line status in a paginated envelope
returns: { items: LineSummary[], pagination }
GET /api/v1/status/lines/:color/history
hourly history for one line
path params:
color (string, required) — line color (e.g. RED, BLUE)
query params:
days (integer) — how many days back (1–90, default 90)
returns: { color, name, displayColor, days, hourly: HourlyPoint[], summary }
GET /api/v1/status/alerts
current active alerts (with duration)
returns: { items: ActiveAlert[], pagination }
/system metadata about the transit agencies, the feed itself, and route geometry.
GET /api/v1/agencies
list all transit agencies
returns: { items: Agency[], pagination }
GET /api/v1/agencies/:id
single agency
path params:
id (string, required) — agency id
returns: Agency
GET /api/v1/feed-info
latest feed version and freshness info
returns: FeedInfo
GET /api/v1/shapes/:shapeId
GeoJSON LineString for a route shape (useful for drawing on a map)
path params:
shapeId (string, required) — shape id
returns: { shapeId, type: 'LineString', coordinates: [lon, lat][] }