{
  "agency_count": 32,
  "average_score": 65.5,
  "common_fixes": [
    {
      "agencies": 27,
      "code": "scorecard_wheelchair_accessible_unknown",
      "fix": "Set wheelchair_accessible on every trip. If every vehicle is accessible, this may be one default; otherwise use the value for each trip."
    },
    {
      "agencies": 24,
      "code": "scorecard_wheelchair_boarding_unknown",
      "fix": "Set wheelchair_boarding to 1 (accessible) or 2 (not accessible) for every stop. A field survey can start with the busiest stops."
    },
    {
      "agencies": 10,
      "code": "scorecard_missing_feed_info_dates",
      "fix": "Add feed_info.txt with feed_start_date and feed_end_date to your export."
    },
    {
      "agencies": 6,
      "code": "scorecard_no_fare_data",
      "fix": "Add fare_attributes.txt (or Fares v2 files) with your fare structure. If your service is fare-free, ask to have it marked fare-free instead."
    },
    {
      "agencies": 4,
      "code": "scorecard_missing_headsigns",
      "fix": "Add the destination, direction, or 'via' label riders actually see to trip_headsign. Do not copy the route name. If the label changes during the trip, use stop_headsign."
    },
    {
      "agencies": 3,
      "code": "mixed_case_recommended_field",
      "fix": "Use mixed case for stop names and headsigns (e.g. 'Main St & 2nd Ave', not 'MAIN ST & 2ND AVE')."
    },
    {
      "agencies": 3,
      "code": "scorecard_feed_expiring_soon",
      "fix": "Re-export with a validity window that reaches at least 60 days out."
    },
    {
      "agencies": 2,
      "code": "stop_too_far_from_shape_using_user_distance",
      "fix": "Check the flagged stops' shape_dist_traveled against the route shape, and re-generate it on export if they disagree."
    },
    {
      "agencies": 2,
      "code": "foreign_key_violation",
      "fix": "Review the rule documentation for 'foreign_key_violation' at https://gtfs-validator.mobilitydata.org/rules.html and check the flagged rows in your feed."
    },
    {
      "agencies": 2,
      "code": "trip_distance_exceeds_shape_distance_below_threshold",
      "fix": "Re-generate shape_dist_traveled on export so stop and shape distances use the same units."
    },
    {
      "agencies": 2,
      "code": "stop_time_with_arrival_before_previous_departure_time",
      "fix": "Review the rule documentation for 'stop_time_with_arrival_before_previous_departure_time' at https://gtfs-validator.mobilitydata.org/rules.html and check the flagged rows in your feed."
    },
    {
      "agencies": 2,
      "code": "equal_shape_distance_diff_coordinates",
      "fix": "Review the rule documentation for 'equal_shape_distance_diff_coordinates' at https://gtfs-validator.mobilitydata.org/rules.html and check the flagged rows in your feed."
    },
    {
      "agencies": 2,
      "code": "expired_calendar",
      "fix": "Remove past service periods the next time you export the feed."
    }
  ],
  "comparison": {
    "absolute_rankings_published": false,
    "eligible_count": 31,
    "excluded_count": 1,
    "exclusion_counts": {
      "measured_category_set_mismatch": 1
    },
    "individual_percentiles_published": false,
    "measured_category_cohorts": {
      "correctness+freshness+completeness": 31,
      "correctness+freshness+completeness+realtime": 1
    },
    "note": "Score aggregates and named changes use one current producer contract, raw reader archive profile, and measured-category set across canonical feed records, with unresolved duplicate identities removed. Absolute rankings and individual percentiles are not published.",
    "required_measured_categories": [
      "correctness",
      "freshness",
      "completeness"
    ],
    "required_reader_archive_profile": "raw-v1",
    "required_rubric_version": "1.4",
    "required_scoring_profile_id": "gtfs-scorecard-1.4",
    "required_validator_version": "8.0.1"
  },
  "expired": {
    "lapsed": 0,
    "stale": 0,
    "total": 0
  },
  "generated_at": "2026-10-16T01:21:49+00:00",
  "grade_distribution": {
    "B": 6,
    "C": 8,
    "D": 8,
    "F": 9
  },
  "members": [
    {
      "annual_trips": null,
      "attention_reason": "Service data expires in 60 day(s)",
      "days_until_expiry": 60,
      "expiry_status": "current",
      "grade": "C",
      "id": "bizkaibus",
      "name": "Bizkaibus",
      "needs_attention": true,
      "score": 73.3,
      "shapes_status": null,
      "snapshot_date": "2026-10-15",
      "top_fix": "Set wheelchair_boarding to 1 (accessible) or 2 (not accessible) for every stop. A field survey can start with the busiest stops.",
      "top_fix_code": "scorecard_wheelchair_boarding_unknown"
    },
    {
      "annual_trips": null,
      "attention_reason": "Service data expires in 46 day(s)",
      "days_until_expiry": 46,
      "expiry_status": "current",
      "grade": "D",
      "id": "emt-malaga",
      "name": "Empresa Malague\u00f1a de Transportes (EMT M\u00e1laga)",
      "needs_attention": true,
      "score": 67.4,
      "shapes_status": null,
      "snapshot_date": "2026-10-15",
      "top_fix": "Set wheelchair_boarding to 1 (accessible) or 2 (not accessible) for every stop. A field survey can start with the busiest stops.",
      "top_fix_code": "scorecard_wheelchair_boarding_unknown"
    },
    {
      "annual_trips": null,
      "attention_reason": "Service data expires in 14 day(s)",
      "days_until_expiry": 14,
      "expiry_status": "expiring_soon",
      "grade": "F",
      "id": "emt-fuenlabrada",
      "name": "EMT Fuenlabrada (EMTF)",
      "needs_attention": true,
      "score": 58.3,
      "shapes_status": null,
      "snapshot_date": "2026-10-15",
      "top_fix": "Re-export with a validity window that reaches at least 60 days out.",
      "top_fix_code": "scorecard_feed_expiring_soon"
    },
    {
      "annual_trips": null,
      "attention_reason": "The export's structure changed",
      "days_until_expiry": 30,
      "expiry_status": "expiring_soon",
      "grade": "F",
      "id": "emt-valencia",
      "name": "EMT Val\u00e8ncia",
      "needs_attention": true,
      "score": 49.3,
      "shapes_status": null,
      "snapshot_date": "2026-10-15",
      "top_fix": "Set wheelchair_boarding to 1 (accessible) or 2 (not accessible) for every stop. A field survey can start with the busiest stops.",
      "top_fix_code": "scorecard_wheelchair_boarding_unknown"
    },
    {
      "annual_trips": null,
      "attention_reason": "Service data expires in 30 day(s)",
      "days_until_expiry": 30,
      "expiry_status": "expiring_soon",
      "grade": "D",
      "id": "metro-bilbao",
      "name": "Metro Bilbao",
      "needs_attention": true,
      "score": 63.2,
      "shapes_status": null,
      "snapshot_date": "2026-10-15",
      "top_fix": "Set wheelchair_boarding to 1 (accessible) or 2 (not accessible) for every stop. A field survey can start with the busiest stops.",
      "top_fix_code": "scorecard_wheelchair_boarding_unknown"
    },
    {
      "annual_trips": null,
      "attention_reason": "Score changed sharply on 2026-10-07",
      "days_until_expiry": 35,
      "expiry_status": "current",
      "grade": "D",
      "id": "metro-malaga",
      "name": "Metro de M\u00e1laga",
      "needs_attention": true,
      "score": 68.3,
      "shapes_status": null,
      "snapshot_date": "2026-10-15",
      "top_fix": "Set wheelchair_boarding to 1 (accessible) or 2 (not accessible) for every stop. A field survey can start with the busiest stops.",
      "top_fix_code": "scorecard_wheelchair_boarding_unknown"
    },
    {
      "annual_trips": null,
      "attention_reason": "Service data expires in 15 day(s)",
      "days_until_expiry": 15,
      "expiry_status": "expiring_soon",
      "grade": "D",
      "id": "puente-bizkaia",
      "name": "Puente Bizkaia (El Transbordador de Vizcaya)",
      "needs_attention": true,
      "score": 68.8,
      "shapes_status": null,
      "snapshot_date": "2026-10-15",
      "top_fix": "Re-export with a validity window that reaches at least 60 days out.",
      "top_fix_code": "scorecard_feed_expiring_soon"
    },
    {
      "annual_trips": null,
      "attention_reason": "Service data expires in 30 day(s)",
      "days_until_expiry": 30,
      "expiry_status": "expiring_soon",
      "grade": "F",
      "id": "tram-barcelona-tbx",
      "name": "TRAM Barcelona (Trambaix)",
      "needs_attention": true,
      "score": 52.5,
      "shapes_status": null,
      "snapshot_date": "2026-10-15",
      "top_fix": "Set wheelchair_boarding to 1 (accessible) or 2 (not accessible) for every stop. A field survey can start with the busiest stops.",
      "top_fix_code": "scorecard_wheelchair_boarding_unknown"
    },
    {
      "annual_trips": null,
      "attention_reason": "Service data expires in 30 day(s)",
      "days_until_expiry": 30,
      "expiry_status": "expiring_soon",
      "grade": "F",
      "id": "tram-barcelona-tbs",
      "name": "TRAM Barcelona (Trambes\u00f2s)",
      "needs_attention": true,
      "score": 54.3,
      "shapes_status": null,
      "snapshot_date": "2026-10-15",
      "top_fix": "Set wheelchair_boarding to 1 (accessible) or 2 (not accessible) for every stop. A field survey can start with the busiest stops.",
      "top_fix_code": "scorecard_wheelchair_boarding_unknown"
    },
    {
      "annual_trips": null,
      "attention_reason": "Service data expires in 29 day(s)",
      "days_until_expiry": 29,
      "expiry_status": "expiring_soon",
      "grade": "D",
      "id": "tuvisa-vitoria",
      "name": "TUVISA (Vitoria-Gasteiz)",
      "needs_attention": true,
      "score": 63.2,
      "shapes_status": null,
      "snapshot_date": "2026-10-15",
      "top_fix": "Re-export with a validity window that reaches at least 60 days out.",
      "top_fix_code": "scorecard_feed_expiring_soon"
    },
    {
      "annual_trips": null,
      "attention_reason": null,
      "days_until_expiry": 442,
      "expiry_status": "current",
      "grade": "F",
      "id": "gencat-interurban-bus",
      "name": "Autobusos interurbans de la Generalitat de Catalunya",
      "needs_attention": false,
      "score": 44.1,
      "shapes_status": null,
      "snapshot_date": "2026-10-15",
      "top_fix": "Set wheelchair_boarding to 1 (accessible) or 2 (not accessible) for every stop. A field survey can start with the busiest stops.",
      "top_fix_code": "scorecard_wheelchair_boarding_unknown"
    },
    {
      "annual_trips": null,
      "attention_reason": null,
      "days_until_expiry": 77,
      "expiry_status": "current",
      "grade": "B",
      "id": "bermibusa",
      "name": "Bermibusa (Bermeo)",
      "needs_attention": false,
      "score": 87.2,
      "shapes_status": null,
      "snapshot_date": "2026-10-15",
      "top_fix": "Set wheelchair_boarding to 1 (accessible) or 2 (not accessible) for every stop. A field survey can start with the busiest stops.",
      "top_fix_code": "scorecard_wheelchair_boarding_unknown"
    },
    {
      "annual_trips": null,
      "attention_reason": null,
      "days_until_expiry": 258,
      "expiry_status": "current",
      "grade": "B",
      "id": "bilbobus",
      "name": "Bilbobus",
      "needs_attention": false,
      "score": 81.2,
      "shapes_status": null,
      "snapshot_date": "2026-10-15",
      "top_fix": "Use mixed case for stop names and headsigns (e.g. 'Main St & 2nd Ave', not 'MAIN ST & 2ND AVE').",
      "top_fix_code": "mixed_case_recommended_field"
    },
    {
      "annual_trips": null,
      "attention_reason": null,
      "days_until_expiry": 182,
      "expiry_status": "current",
      "grade": "C",
      "id": "tib-mallorca",
      "name": "Consorci de Transports de Mallorca (TIB)",
      "needs_attention": false,
      "score": 76.9,
      "shapes_status": null,
      "snapshot_date": "2026-10-15",
      "top_fix": "Set wheelchair_boarding to 1 (accessible) or 2 (not accessible) for every stop. A field survey can start with the busiest stops.",
      "top_fix_code": "scorecard_wheelchair_boarding_unknown"
    },
    {
      "annual_trips": null,
      "attention_reason": null,
      "days_until_expiry": 360,
      "expiry_status": "current",
      "grade": "F",
      "id": "crtm-red-de-urbanos",
      "name": "CRTM \u2014 Red de Autobuses Urbanos (Madrid regional urban bus)",
      "needs_attention": false,
      "score": 33.8,
      "shapes_status": null,
      "snapshot_date": "2026-10-15",
      "top_fix": "Review the rule documentation for 'stop_time_with_arrival_before_previous_departure_time' at https://gtfs-validator.mobilitydata.org/rules.html and check the flagged rows in your feed.",
      "top_fix_code": "stop_time_with_arrival_before_previous_departure_time"
    },
    {
      "annual_trips": null,
      "attention_reason": null,
      "days_until_expiry": 77,
      "expiry_status": "current",
      "grade": "C",
      "id": "crtm-red-de-emt",
      "name": "CRTM \u2014 Red de EMT (Madrid city bus)",
      "needs_attention": false,
      "score": 71.0,
      "shapes_status": null,
      "snapshot_date": "2026-10-15",
      "top_fix": "Set wheelchair_boarding to 1 (accessible) or 2 (not accessible) for every stop. A field survey can start with the busiest stops.",
      "top_fix_code": "scorecard_wheelchair_boarding_unknown"
    },
    {
      "annual_trips": null,
      "attention_reason": null,
      "days_until_expiry": 360,
      "expiry_status": "current",
      "grade": "F",
      "id": "crtm-red-de-interurbanos",
      "name": "CRTM \u2014 Red de Interurbanos (Madrid regional bus)",
      "needs_attention": false,
      "score": 33.8,
      "shapes_status": null,
      "snapshot_date": "2026-10-15",
      "top_fix": "Review the rule documentation for 'stop_time_with_arrival_before_previous_departure_time' at https://gtfs-validator.mobilitydata.org/rules.html and check the flagged rows in your feed.",
      "top_fix_code": "stop_time_with_arrival_before_previous_departure_time"
    },
    {
      "annual_trips": null,
      "attention_reason": null,
      "days_until_expiry": 280,
      "expiry_status": "current",
      "grade": "C",
      "id": "crtm-metro-ligero",
      "name": "CRTM \u2014 Red de Metro Ligero (Madrid light rail)",
      "needs_attention": false,
      "score": 70.9,
      "shapes_status": null,
      "snapshot_date": "2026-10-15",
      "top_fix": "Add feed_info.txt with feed_start_date and feed_end_date to your export.",
      "top_fix_code": "scorecard_missing_feed_info_dates"
    },
    {
      "annual_trips": null,
      "attention_reason": null,
      "days_until_expiry": 77,
      "expiry_status": "current",
      "grade": "C",
      "id": "emt-madrid",
      "name": "EMT Madrid",
      "needs_attention": false,
      "score": 72.8,
      "shapes_status": null,
      "snapshot_date": "2026-10-15",
      "top_fix": "Set wheelchair_boarding to 1 (accessible) or 2 (not accessible) for every stop. A field survey can start with the busiest stops.",
      "top_fix_code": "scorecard_wheelchair_boarding_unknown"
    },
    {
      "annual_trips": null,
      "attention_reason": null,
      "days_until_expiry": 77,
      "expiry_status": "current",
      "grade": "C",
      "id": "erandiobusa",
      "name": "ErandioBus (Erandiobusa)",
      "needs_attention": false,
      "score": 79.3,
      "shapes_status": null,
      "snapshot_date": "2026-10-15",
      "top_fix": "Review the rule documentation for 'foreign_key_violation' at https://gtfs-validator.mobilitydata.org/rules.html and check the flagged rows in your feed.",
      "top_fix_code": "foreign_key_violation"
    },
    {
      "annual_trips": null,
      "attention_reason": null,
      "days_until_expiry": 77,
      "expiry_status": "current",
      "grade": "B",
      "id": "etxebarribus",
      "name": "EtxebarriBus",
      "needs_attention": false,
      "score": 82.2,
      "shapes_status": null,
      "snapshot_date": "2026-10-15",
      "top_fix": "Set wheelchair_boarding to 1 (accessible) or 2 (not accessible) for every stop. A field survey can start with the busiest stops.",
      "top_fix_code": "scorecard_wheelchair_boarding_unknown"
    },
    {
      "annual_trips": null,
      "attention_reason": null,
      "days_until_expiry": 77,
      "expiry_status": "current",
      "grade": "C",
      "id": "fgc-catalunya",
      "name": "Ferrocarrils de la Generalitat de Catalunya (FGC)",
      "needs_attention": false,
      "score": 75.2,
      "shapes_status": null,
      "snapshot_date": "2026-10-15",
      "top_fix": "Set wheelchair_boarding to 1 (accessible) or 2 (not accessible) for every stop. A field survey can start with the busiest stops.",
      "top_fix_code": "scorecard_wheelchair_boarding_unknown"
    },
    {
      "annual_trips": null,
      "attention_reason": null,
      "days_until_expiry": 228,
      "expiry_status": "current",
      "grade": "B",
      "id": "funicular-artxanda",
      "name": "Funicular de Artxanda (Artxandako Funikularra)",
      "needs_attention": false,
      "score": 89.4,
      "shapes_status": null,
      "snapshot_date": "2026-10-15",
      "top_fix": "Set wheelchair_accessible on every trip. If every vehicle is accessible, this may be one default; otherwise use the value for each trip.",
      "top_fix_code": "scorecard_wheelchair_accessible_unknown"
    },
    {
      "annual_trips": null,
      "attention_reason": null,
      "days_until_expiry": 3029,
      "expiry_status": "current",
      "grade": "D",
      "id": "guaguas-municipales",
      "name": "Guaguas Municipales",
      "needs_attention": false,
      "score": 65.9,
      "shapes_status": null,
      "snapshot_date": "2026-10-15",
      "top_fix": "Set wheelchair_boarding to 1 (accessible) or 2 (not accessible) for every stop. A field survey can start with the busiest stops.",
      "top_fix_code": "scorecard_wheelchair_boarding_unknown"
    },
    {
      "annual_trips": null,
      "attention_reason": null,
      "days_until_expiry": 77,
      "expiry_status": "current",
      "grade": "B",
      "id": "kbus-barakaldo",
      "name": "Kbus (Barakaldo)",
      "needs_attention": false,
      "score": 83.0,
      "shapes_status": null,
      "snapshot_date": "2026-10-15",
      "top_fix": "Set wheelchair_boarding to 1 (accessible) or 2 (not accessible) for every stop. A field survey can start with the busiest stops.",
      "top_fix_code": "scorecard_wheelchair_boarding_unknown"
    },
    {
      "annual_trips": null,
      "attention_reason": null,
      "days_until_expiry": 77,
      "expiry_status": "current",
      "grade": "B",
      "id": "leioabus",
      "name": "LeioaBus (Lejoan Busa)",
      "needs_attention": false,
      "score": 86.5,
      "shapes_status": null,
      "snapshot_date": "2026-10-15",
      "top_fix": "Set wheelchair_boarding to 1 (accessible) or 2 (not accessible) for every stop. A field survey can start with the busiest stops.",
      "top_fix_code": "scorecard_wheelchair_boarding_unknown"
    },
    {
      "annual_trips": null,
      "attention_reason": null,
      "days_until_expiry": 7017,
      "expiry_status": "current",
      "grade": "F",
      "id": "ctan-andalucia",
      "name": "Red de Consorcios de Transporte de Andaluc\u00eda",
      "needs_attention": false,
      "score": 42.0,
      "shapes_status": null,
      "snapshot_date": "2026-10-15",
      "top_fix": "Review the rule documentation for 'foreign_key_violation' at https://gtfs-validator.mobilitydata.org/rules.html and check the flagged rows in your feed.",
      "top_fix_code": "foreign_key_violation"
    },
    {
      "annual_trips": null,
      "attention_reason": null,
      "days_until_expiry": null,
      "expiry_status": "unknown",
      "grade": "F",
      "id": "renfe-alta-larga-media",
      "name": "Renfe (Alta Velocidad, Larga y Media Distancia)",
      "needs_attention": false,
      "score": 36.8,
      "shapes_status": null,
      "snapshot_date": "2026-10-15",
      "top_fix": "Add feed_start_date and feed_end_date to feed_info.txt and include calendar end dates in your export.",
      "top_fix_code": "scorecard_no_expiry_date"
    },
    {
      "annual_trips": null,
      "attention_reason": null,
      "days_until_expiry": null,
      "expiry_status": "unknown",
      "grade": "F",
      "id": "renfe-cercanias-rodalies",
      "name": "Renfe Cercan\u00edas y Rodalies",
      "needs_attention": false,
      "score": 33.6,
      "shapes_status": null,
      "snapshot_date": "2026-10-15",
      "top_fix": "Add feed_start_date and feed_end_date to feed_info.txt and include calendar end dates in your export.",
      "top_fix_code": "scorecard_no_expiry_date"
    },
    {
      "annual_trips": null,
      "attention_reason": null,
      "days_until_expiry": 442,
      "expiry_status": "current",
      "grade": "C",
      "id": "reus-transport",
      "name": "Reus Transport",
      "needs_attention": false,
      "score": 74.3,
      "shapes_status": null,
      "snapshot_date": "2026-10-15",
      "top_fix": "Set wheelchair_accessible on every trip. If every vehicle is accessible, this may be one default; otherwise use the value for each trip.",
      "top_fix_code": "scorecard_wheelchair_accessible_unknown"
    },
    {
      "annual_trips": null,
      "attention_reason": null,
      "days_until_expiry": 178,
      "expiry_status": "current",
      "grade": "D",
      "id": "titsa-tenerife",
      "name": "TITSA (Tenerife)",
      "needs_attention": false,
      "score": 63.3,
      "shapes_status": null,
      "snapshot_date": "2026-10-15",
      "top_fix": "Set wheelchair_boarding to 1 (accessible) or 2 (not accessible) for every stop. A field survey can start with the busiest stops.",
      "top_fix_code": "scorecard_wheelchair_boarding_unknown"
    },
    {
      "annual_trips": null,
      "attention_reason": null,
      "days_until_expiry": 374,
      "expiry_status": "current",
      "grade": "D",
      "id": "transprober-granada",
      "name": "TranspRober (Granada)",
      "needs_attention": false,
      "score": 62.4,
      "shapes_status": null,
      "snapshot_date": "2026-10-15",
      "top_fix": "Set wheelchair_accessible on every trip. If every vehicle is accessible, this may be one default; otherwise use the value for each trip.",
      "top_fix_code": "scorecard_wheelchair_accessible_unknown"
    }
  ],
  "needs_attention": 10,
  "realtime": {
    "bands": {
      "mostly": 0,
      "reliable": 1,
      "spotty": 0
    },
    "configured_feed_records": 1,
    "median_coverage_pct": null,
    "median_lag_seconds": 15,
    "median_uptime_pct": 100.0,
    "members": [
      {
        "band": "reliable",
        "configured_kinds": [
          "service_alerts",
          "trip_updates",
          "vehicle_positions"
        ],
        "first_ts": 1789936240,
        "id": "renfe-cercanias-rodalies",
        "last_ts": 1792106944,
        "median_coverage_pct": null,
        "median_lag_seconds": 15,
        "name": "Renfe Cercan\u00edas y Rodalies",
        "observations": 200,
        "uptime_pct": 100.0
      }
    ],
    "monitored_feed_records": 1
  },
  "rollup": {
    "country_code": "ES",
    "country_name": "Spain",
    "id": "country-es",
    "name": "Spain"
  },
  "schema_version": "1.19",
  "shapes_readiness": {
    "at_risk": 0,
    "not_measured": 32,
    "not_ready": 0,
    "ready": 0,
    "total": 32
  },
  "state_percentile": null
}
