//nbkelley /homelab

BlueBikes API Feeds Guide#

What Was Established#

  • Comprehensive breakdown of BlueBikes GBFS (General Bikeshare Feed Specification) endpoints.
  • JSON structure analysis for static (station_information) and real-time (station_status) feeds.
  • JavaScript patterns for fetching, joining, and displaying station data.

Key Decisions#

  • Base URL: https://gbfs.lyft.com/gbfs/1.1/bos/en/
  • Primary Feeds: station_information (static map/location data) and station_status (live availability) are the core feeds for real-time tracking.
  • Join Strategy: Match station_id fields between static and status feeds to combine location metadata with live bike/dock counts.

Current Configuration#

Core GBFS Endpoints#

Feed Purpose
station_information Static station list, names, IDs, coordinates, capacity, kiosk info
station_status Real-time bike/dock counts, station active/inactive status, last reported timestamp
system_information System metadata (operator, name, URLs)
system_regions Regional breakdowns for color-coding/mapping
system_hours Operating hours
system_calendar Start/end years, holidays
gbfs_versions Available GBFS versions
free_bike_status Free-floating bike locations
ebikes_at_stations Real-time e-bike counts per station
system_pricing_plans Membership & pricing details
system_alerts Current advisories

Data Structure Examples#

station_information

{
  "last_updated": 1742774947,
  "ttl": 60,
  "version": "1.1",
  "data": {
    "stations": [
      {
        "station_id": "1",
        "name": "MIT at Mass Ave / Amherst St",
        "short_name": "A31006",
        "lat": 42.358177,
        "lon": -71.092639,
        "region_id": "10",
        "capacity": 19,
        "rental_methods": ["KEY", "CREDITCARD"],
        "eightd_has_key_dispenser": false,
        "has_kiosk": true
      }
    ]
  }
}

station_status

{
  "last_updated": 1742775312,
  "ttl": 10,
  "version": "1.1",
  "data": {
    "stations": [
      {
        "station_id": "1",
        "num_bikes_available": 2,
        "num_ebikes_available": 0,
        "num_bikes_disabled": 0,
        "num_docks_available": 16,
        "num_docks_disabled": 1,
        "is_installed": 1,
        "is_renting": 1,
        "is_returning": 1,
        "last_reported": 1742775275,
        "eightd_has_available_keys": false
      }
    ]
  }
}

JavaScript Fetch & Join Pattern#

async function getBlueBikesStations() {
  try {
    const [infoResponse, statusResponse] = await Promise.all([
      fetch('https://gbfs.lyft.com/gbfs/1.1/bos/en/station_information.json'),
      fetch('https://gbfs.lyft.com/gbfs/1.1/bos/en/station_status.json')
    ]);

    const infoData = await infoResponse.json();
    const statusData = await statusResponse.json();

    const statusMap = new Map();
    statusData.data.stations.forEach(status => {
      statusMap.set(status.station_id, status);
    });

    const stations = infoData.data.stations.map(station => {
      const status = statusMap.get(station.station_id) || {};
      return {
        station_id: station.station_id,
        name: station.name,
        short_name: station.short_name,
        lat: station.lat,
        lon: station.lon,
        capacity: station.capacity,
        region_id: station.region_id,
        bikes_available: status.num_bikes_available || 0,
        ebikes_available: status.num_ebikes_available || 0,
        docks_available: status.num_docks_available || 0,
        disabled_bikes: status.num_bikes_disabled || 0,
        disabled_docks: status.num_docks_disabled || 0,
        is_renting: status.is_renting === 1,
        is_returning: status.is_returning === 1,
        last_reported: status.last_reported,
        last_reported_date: status.last_reported
          ? new Date(status.last_reported * 1000).toLocaleString()
          : null
      };
    });

    stations.sort((a, b) => a.name.localeCompare(b.name));
    return stations;
  } catch (error) {
    console.error('Error fetching BlueBikes data:', error);
  }
}

Historical Notes#

  • Conversation date: 2026-02-13
  • Focus was on understanding GBFS structure and building a JS fetch/join pattern for station IDs and names.
  • ttl values observed: 60s for station_information, 10s for station_status.

Open Questions#

  • How to integrate this API into the existing MBTA Dashboard or Homelab status dashboard?
  • Should station data be cached locally via n8n or Proxmox services?

Sources#

  • ingested/chats/173-BlueBikes API Feeds Guide.md
  • BlueBikes GBFS Endpoint: https://gbfs.bluebikes.com/gbfs/gbfs.json
  • DeepSeek Conversation (2026-02-13)