Skip to content

feat: expose GTFS data and add OpenAPI docs#65

Open
Felipequesada21 wants to merge 19 commits into
mainfrom
feat/api
Open

feat: expose GTFS data and add OpenAPI docs#65
Felipequesada21 wants to merge 19 commits into
mainfrom
feat/api

Conversation

@Felipequesada21

Copy link
Copy Markdown
Contributor

Summary

This branch improves the Infobús API by exposing GTFS Schedule, GTFS Realtime, and existing custom endpoints through read-only REST endpoints.

It also adds automatically generated OpenAPI documentation using drf-spectacular, while keeping the existing manual YAML documentation in parallel for now to avoid breaking historical documentation routes.

Main changes

Read-only API

  • Migrated the main ViewSets to ReadOnlyModelViewSet.
  • No write or mutation endpoints were added.
  • Cleaned up imports, serializers, and invalid filterset_fields.

GTFS Schedule endpoints

The following GTFS Schedule entities are now exposed:

  • /api/agencies/
  • /api/stops/
  • /api/geo-stops/
  • /api/routes/
  • /api/trips/
  • /api/stop-times/
  • /api/calendars/
  • /api/calendar-dates/
  • /api/shapes/
  • /api/geo-shapes/
  • /api/fare-attributes/
  • /api/fare-rules/
  • /api/feed-info/
  • /api/feed-publishers/
  • /api/feeds/
  • /api/info-services/

GTFS Realtime endpoints

The following GTFS Realtime entities are now exposed:

  • /api/feed-messages/
  • /api/trip-updates/
  • /api/stop-time-updates/
  • /api/vehicle-positions/
  • /api/service-alerts/

/api/feeds/ endpoint

Added /api/feeds/ to expose imported GTFS feed snapshots and allow the frontend to identify the active feed:

  • GET /api/feeds/
  • GET /api/feeds/?is_current=true
  • GET /api/feeds/{feed_id}/

Custom endpoints

The following custom endpoints were preserved and improved:

  • /api/next-trips/
  • /api/next-stops/
  • /api/route-stops/

Included changes:

  • Fixed outdated VehiclePosition field names in NextTripView.
  • Fixed the StopTimeUpdate.feed_message filter to use trip_update__feed_message.
  • Removed debug print() calls.
  • Added defensive handling to avoid 500 errors when data such as the active feed, realtime data, vehicle positions, shapes, or related stops are missing.

OpenAPI documentation

Configured drf-spectacular to generate automatic OpenAPI documentation:

  • /api/docs/schema-auto/
  • /api/docs/auto/

Added @extend_schema decorators to:

  • NextTripView
  • NextStopView
  • RouteStopView

For now, /api/docs/ and /api/docs/schema/ still point to the existing manual YAML documentation to avoid breaking historical routes.

Validation performed

  • python manage.py check
  • python manage.py spectacular --validate
  • Manual curl checks against main endpoints.
  • Visual validation of /api/docs/auto/.

Known pending items

  • The manual YAML file backend/api/infobus.yml still coexists with the automatic documentation. We still need to decide whether /api/docs/ should officially be replaced by /api/docs/auto/.
  • ServiceAlertSerializer still declares a feed field that does not exist directly on the Alert model; the model uses feed_message. This should be fixed before loading real alert data.
  • stop_point and position_point still generate drf-spectacular warnings because they are PostGIS geometry fields. We still need to decide whether they should be explicitly documented/serialized as GeometryField.
  • We still need to decide whether auxiliary endpoints such as Weather, Social, RouteStop, TripTime, or TripDuration should be exposed.
  • A minor duplicate enum warning remains in the generated schema.

Risk

Low. The API remains read-only, and this PR does not modify models, migrations, or ingestion pipelines.

Observable changes:

  • Custom endpoints may now return 503 Service Unavailable when there is no active GTFS feed, instead of failing with 500.
  • /api/next-stops/ now returns next_stop_sequence: [] when there is no realtime data.
  • /api/feeds/ is now available so the frontend can query the active feed.

Checklist

  • API remains read-only.
  • GTFS Schedule endpoints exposed.
  • GTFS Realtime endpoints exposed.
  • /api/feeds/ endpoint added.
  • Custom endpoints fixed and documented.
  • Defensive handling added to custom endpoints.
  • Automatic documentation available at /api/docs/auto/.
  • python manage.py check executed.
  • python manage.py spectacular --validate executed.
  • Decide whether /api/docs/ should be replaced by the automatic schema.
  • Decide final format for geographic fields.
  • Decide whether auxiliary endpoints should be exposed.

Agrega manejo defensivo mínimo en los endpoints personalizados del API para evitar errores 500 cuando faltan datos relacionados.

Cambios principales:
- En NextTripView, se valida la existencia de la parada usando filter().exists() para evitar errores por múltiples feeds.
- Se maneja el caso donde no existe un feed GTFS activo, devolviendo 503 Service Unavailable en vez de romper el endpoint.
- Se agregan validaciones para evitar errores cuando faltan trip, route, vehicle_position, position_point o geo_shape en datos realtime incompletos.
- En NextStopView, se maneja la ausencia de mensajes GTFS Realtime y se devuelve una lista vacía en lugar de provocar un error.
- En RouteStopView, se maneja la ausencia de feed activo y se evita fallar cuando una parada asociada no existe o no tiene coordenadas.

Este commit no modifica serializers, urls, modelos, paginación ni documentación OpenAPI. Solo mejora la robustez de los endpoints custom existentes.
@Felipequesada21 Felipequesada21 self-assigned this May 25, 2026
@Felipequesada21 Felipequesada21 added documentation Improvements or additions to documentation enhancement New feature or request labels May 25, 2026

@fabianabarca fabianabarca left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New feature request

  • A new api/transit-systems endpoint to show the results of the TransitSystem model inside feed/models.py
  • Implementation of filtering by request parameters for all endpoints by /?transit_system=<code> so that the results are filtered, for example: /api/routes/?transit_system=MBTA or /api/routes/?transit_system=bUCR. We will handle several transit systems and thus we need to filter appropriately.
  • Note: the field TransitSystem.code does not exist yet, it has to be created (gotta be careful with the migrations).
  • feed_publisher inside http://localhost:28000/api/feeds/ should be a hyperlink (check the serializer)
  • Check http://localhost:28000/api/feed-publishers/ because it didn't work on my machine

@Felipequesada21

Copy link
Copy Markdown
Contributor Author

Feed publishers up and working:
image

@Felipequesada21

Copy link
Copy Markdown
Contributor Author

feed_publisher inside http://localhost:28000/api/feeds/ as a hyperlink per request

image

@Felipequesada21

Copy link
Copy Markdown
Contributor Author

Working filters!
image

 Adds optional `?transit_system=<code>` filtering to the 5 GTFS
  Realtime endpoints:

    /api/feed-messages/       publisher__transit_system__code
    /api/trip-updates/        feed_message__publisher__transit_system__code
    /api/stop-time-updates/   trip_update__feed_message__publisher__transit_system__code
    /api/vehicle-positions/   feed_message__publisher__transit_system__code
    /api/service-alerts/      feed_message__publisher__transit_system__code   Existing `filterset_fields` are preserved as `Meta.fields` in the
  new FilterSet classes; behaviour without the new parameter is
  the same as before
@fabianabarca

fabianabarca commented May 29, 2026

Copy link
Copy Markdown
Member
  • Add tunnel endpoints to pass the JSON of the GTFS Realtime entities, with results just like this: https://cdn.mbta.com/realtime/VehiclePositions.json. The endpoints could be realtime/vehicle-positions, realtime/trip-updates, realtime/alerts.
  • Create a new endpoint to publish the current state of a run in particular, like realtime/runs/<run_id>/state, and would return something like:
{
    "relative_position": 0.7532,
    "congestion_level": "RUNNING_SMOOTHLY",
    "occupancy_status": "EMPTY",
    "adherence_status": "ON_TIME",
}

This will, most likely, be delivered to clients via WebSockets every time there is an update in any of the fields, but we need replication in the API.

  • Check APIs to ensure:
    • GTFS Schedule: api.infobus.ucr.ac.cr/schedule/agency, api.infobus.ucr.ac.cr/schedule/routes, etc.
    • GTFS Realtime: api.infobus.ucr.ac.cr/realtime/vehicle-positions, etc.
    • Special endpoints: api.infobus.ucr.ac.cr/realtime/next-stops, api.infobus.ucr.ac.cr/realtime/next-trips, api.infobus.ucr.ac.cr/realtime/runs (all active runs) and api.infobus.ucr.ac.cr/realtime/runs/<run_id>/state
  • Replicate the RunProgress FSM from Databús in Infobús (possibly implementing the FSM in the package gtfs-django)

Adds two new URL namespaces that reuse the existing GTFS Schedule and
  GTFS Realtime ViewSets/APIViews without touching the legacy /api/
  routes:

    /schedule/    13 Schedule endpoints (agencies, stops, routes, trips,
                  stop-times, calendars, calendar-dates, shapes,
                  geo-shapes, geo-stops, fare-attributes, fare-rules,
                  feed-info)

    /realtime/    5 Realtime endpoints + 3 custom APIViews
                  (feed-messages, trip-updates, stop-time-updates,
                  vehicle-positions, service-alerts, next-trips,
                  next-stops, route-stops)

  Each new registration uses an explicit, prefixed `basename=` so URL
  names don't collide with the legacy router. HyperlinkedRelatedField
  in serializers continues to resolve to /api/... URLs (conservative
  default); deprecation of /api/ will be handled in a later commit.

  The metadata endpoints (transit-systems, feed-publishers, feeds,
  info-services) intentionally stay only under /api/ in this commit;
  they can be exposed under the new namespaces in a follow-up.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants