# Cómo buscar paradas de transporte cercanas con una API

> Aprende a buscar paradas cercanas con la API de ROOTE: coordenadas, radio, ejemplo en JavaScript, lectura de resultados y manejo de errores.

Source: https://www.roote.ai/es/guias/api-paradas-transporte-proximidad/
Language: es
Author: ROOTE

Para buscar paradas alrededor de un punto, envía su latitud, longitud y un radio a una API de proximidad. Luego verifica el estado de la respuesta, las entidades devueltas y la información de cobertura antes de mostrar la lista o el mapa.

En el contrato ROOTE roote-1.0.0, la ruta GET /v1/transit/nearby descubre los lugares de transporte cercanos. No recupera salidas ni alertas en tiempo real. La búsqueda de un lugar y la búsqueda de su próxima salida son dos operaciones distintas.

## Definir los parámetros

La petición usa lat para la latitud y lng para la longitud. El alias lon también se describe en el contrato. El parámetro radius expresa el radio en metros; limit limita el número de resultados solicitados. El filtro modes puede especificar los modos de transporte.

| Parámetro | Ejemplo | Significado |
| --- | --- | --- |
| lat | 44.8378 | Latitud del punto de búsqueda |
| lng | -0.5792 | Longitud del punto de búsqueda |
| radius | 600 | Radio solicitado en metros |
| limit | 10 | Límite solicitado de resultados |
| modes | bus,tram | Modos buscados |

Estas coordenadas sirven como ejemplo de búsqueda en Burdeos; no garantizan una parada. Consulte el [contrato OpenAPI ROOTE](https://api.roote.ai/openapi.json) para los límites, campos y condiciones vigentes.

## Enviar una primera petición desde el servidor

Aquí hay un ejemplo en JavaScript para un entorno Node.js con fetch. El token, si tu acceso usa uno, permanece en una variable de entorno en el servidor. El ejemplo no requiere colocar un secreto en el navegador.

```
async function rechercherArrets(token = process.env.ROOTE_API_TOKEN) {
  const url = new URL('https://api.roote.ai/v1/transit/nearby');
  url.search = new URLSearchParams({
    lat: '44.8378',
    lng: '-0.5792',
    radius: '600',
    limit: '10',
    modes: 'bus,tram'
  }).toString();

  const headers = { Accept: 'application/json' };
  if (token) headers.Authorization = `Bearer ${token}`;

  const response = await fetch(url, {
    headers,
    signal: AbortSignal.timeout(10000)
  });
  if (!response.ok) {
    throw new Error(`Erreur HTTP ${response.status}`);
  }

  const data = await response.json();
  if (data.contract_version !== 'roote-1.0.0') {
    throw new Error('Version du contrat non reconnue');
  }
  if (!['success', 'empty', 'partial'].includes(data.status)) {
    throw new Error('Recherche indisponible');
  }
  if (!Array.isArray(data.stations)) {
    throw new Error('Réponse sans collection stations valide');
  }

  return {
    status: data.status,
    stations: data.stations,
    lines: data.lines,
    operators: data.operators,
    coverage: data.coverage,
    warnings: data.warnings,
    attributions: data.attributions,
    meta: data.meta
  };
}
```

El contrato consultado prevé acceso anónimo o mediante token, según las políticas aplicables. Verifica tus derechos y los límites de acceso. Una respuesta HTTP correcta no exime de validar su contenido; en producción, usa también una validación de objetos contra el esquema.

## Leer las entidades y sus relaciones

La colección stations contiene los lugares devueltos. Para cada uno, consulta especialmente id, name, entity_kind, location y distance_meters. Las referencias line_ids y operator_ids permiten asociar las colecciones lines y operators cuando están presentes.

Muestra una distancia geográfica tal cual. No la transformes en tiempo de caminata sin un cálculo de ruta. La guía [encontrar una parada cercana](https://www.roote.ai/es/guias/trouver-arret-bus-tram/) explica por qué los accesos pueden modificar el desplazamiento real.

Trata también la información desconocida de forma explícita. En el contrato, accessibility.wheelchair puede valer unknown: ese valor no equivale ni a yes ni a no. Una capacidad de salidas anunciada no constituye una lista de salidas.

## Mostrar una lista o un mapa

Usa el identificador para estabilizar los elementos de la interfaz, el nombre para su etiqueta y location para su posición. Asocia las líneas mediante las referencias, en lugar de emparejar por nombre.

Si muestras colores de líneas o etiquetas provenientes de los datos, trátalos como entradas externas a validar. Para los nombres, usa texto en lugar de HTML inyectado.

Conserva las atribuciones de las fuentes y muestra las que el contrato indique como requeridas.

## Gestionar resultado vacío, respuesta parcial y error

Un resultado empty describe una búsqueda sin resultados devueltos en el perímetro conocido. No prueba la ausencia física de transportes. Una respuesta partial puede contener lugares útiles mientras indica límites: presenta los resultados y la advertencia adecuada.

Lee coverage, warnings y los límites aplicados en meta. Una lista recortada no describe una cobertura exhaustiva. En caso de error de red o HTTP, muestra una indisponibilidad, sin sustituir el resultado por «ninguna parada».

Para un código 429, consulta las indicaciones de reintento y los posibles encabezados del servicio. Evita relanzamientos en bucle.

## Distinguir stations, zonas y andenes

El campo entity_kind distingue varios niveles de lugares. Dos resultados cercanos pueden corresponder a andenes distintos; dos nombres similares pueden pertenecer a fuentes diferentes.

No fusiones automáticamente lugares solo por proximidad. Usa las relaciones e identidades documentadas por el servicio. Nuestra guía [GTFS, GTFS-RT y GBFS](https://www.roote.ai/es/guias/gtfs-gtfs-rt-gbfs-differences/) explica el contexto de los datos.

## Preparar la integración en producción

Dispara las búsquedas cuando la posición o los filtros cambien de forma útil. Agrupa las llamadas idénticas, define un tiempo de espera y adapta la caché al tipo de dato y a las condiciones del servicio.

Una lista de lugares y una disponibilidad en tiempo real no tienen las mismas exigencias de frescura. Valida el flujo con respuestas completas, vacías, parciales y en error antes de presentar la búsqueda a los usuarios.

## Extender la búsqueda a los servicios urbanos

Las paradas y los servicios urbanos utilizan rutas distintas. Para buscar baños cerca del mismo punto, la ruta GET /v1/services/nearby espera lat y lon, con types=toilets. No envíes modes=toilets a esta ruta: este vocabulario pertenece a la URL del mapa, no al filtro Servicios.

El siguiente ejemplo en JavaScript construye una URL para Servicios con un radio de 600 metros. No ejecuta la consulta; reutiliza los controles HTTP y de contrato descritos arriba. La colección esperada cambia a services, en lugar de stations. Conserva service_type, location, distance_meters y los atributos realmente presentes.

El contrato REST documenta, entre otros, toilets, drinking_water, fountain, wifi, parking, charging, aed y locker. Los tipos expuestos por el MCP pueden variar. Para conocer los parámetros aceptados, sus límites y las restricciones de tu acceso, consulta el esquema de la interfaz utilizada.

Los atributos de un servicio no garantizan que esté abierto en el momento de la búsqueda. Una accesibilidad desconocida no equivale a un servicio inaccesible; una lista vacía por un error no prueba la ausencia de baños. Mantén los datos específicos de cada familia en lugar de reducirlos a un nombre y un punto.

Para un mapa combinado, asocia los resultados a su familia y sus identificadores. Muestra un error de Servicios sin borrar las paradas retornadas por Transit. La búsqueda sigue centrada en el mismo punto, pero los estados y coberturas pueden ser distintos.

```
const url = new URL('https://api.roote.ai/v1/services/nearby');
url.search = new URLSearchParams({
  lat: '44.8416106', lon: '-0.5810938',
  radius: '600', limit: '10', types: 'toilets'
}).toString();
console.log(url.toString());
```

[Diagnosticar una búsqueda vacía o con error](https://www.roote.ai/es/guias/resultado-vacio-o-error-api-como-diferenciar/)

[Integrar directamente un mapa filtrado en un sitio](https://www.roote.ai/es/guias/como-integrar-un-mapa-de-movilidad-en-tu-sitio/)

[Construir un asistente alrededor de estas búsquedas](https://www.roote.ai/es/guias/como-crear-un-asistente-que-encuentre-movilidad-cerca-de-una-direccion/)

## Preguntas frecuentes

### ¿Nearby proporciona las próximas salidas?

No en el contrato presentado aquí. Esta ruta descubre los lugares de transporte; las salidas requieren una capacidad distinta.

### ¿Se puede mostrar una lista vacía tras un error?

Muestra una indisponibilidad. Un error no demuestra la ausencia de paradas.

### ¿Se puede poner el token API en el navegador?

Un secreto debe permanecer en el servidor. Usa el modelo de acceso previsto para tu aplicación y tu cuenta.
