To search for stops around a point, send its latitude, longitude and a radius to a proximity API. Then check the response status, returned entities and coverage information before displaying a list or a map.
In the ROOTE contract roote-1.0.0, the GET /v1/transit/nearby route discovers nearby transport places. It does not retrieve departures or real-time alerts. Searching for a place and searching for its next departure are two distinct operations.
Define the parameters
The request uses lat for latitude and lng for longitude. The alias lon is also described in the contract. The radius parameter expresses the radius in meters; limit bounds the number of requested results. The modes filter can specify transport modes.
| Parameter | Example | Meaning |
|---|---|---|
| lat | 44.8378 | Search point latitude |
| lng | -0.5792 | Search point longitude |
| radius | 600 | Requested radius in meters |
| limit | 10 | Requested result limit |
| modes | bus,tram | Searched modes |
These coordinates are an example for a search in Bordeaux; they do not guarantee a specific stop. See the ROOTE OpenAPI contract for current bounds, fields and conditions.
Find transport stops nearby.
Explore stops listed around a city or your location. Check the details for transport modes and available information.
Send a first request from the server side
Here is a JavaScript example for a Node.js environment with fetch. The token, if your access uses one, stays in a server-side environment variable. The example does not require placing a secret in the browser.
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
};
}
The consulted contract allows anonymous or token access, depending on applicable policies. Verify your rights and access limits. A successful HTTP response does not exempt you from validating its content; in production, also validate objects against the schema.
Read entities and their relations
The stations collection contains the returned places. For each, check id, name, entity_kind, location and distance_meters. The line_ids and operator_ids references allow associating the lines and operators collections when they are provided.
Display a geographic distance as such. Do not convert it to walking time without routing calculation. The guide finding a nearby stop explains why access conditions can change actual travel.
Also handle explicitly unknown information. In the contract, accessibility.wheelchair can be unknown: this value is neither yes nor no. A declared departure capacity is not a list of departures.
Show a list or a map
Use the identifier to stabilize interface elements, the name for their label and location for their position. Associate lines using references, rather than by matching their names.
If you display line colors or labels coming from the data, treat them as external inputs to validate. For names, use text rather than injected HTML.
Keep source attributions and display those the contract indicates as required.
Handle empty result, partial response and error
An empty result describes a search with no results returned within the known perimeter. It does not prove the physical absence of transport. A partial response may contain useful places while indicating limits: present the results and the appropriate warning.
Read coverage, warnings and applied limits in meta. A truncated list does not describe exhaustive coverage. In case of network or HTTP error, show an unavailability state, without replacing the result with "no stops".
For a 429 code, consult retry guidance and any service headers. Avoid retry loops.
Distinguish stations, areas and platforms
The entity_kind field distinguishes several place levels. Two nearby results may correspond to distinct platforms; two similar names may come from different sources.
Do not automatically merge places based on proximity alone. Use relations and identities documented by the service. Our guide GTFS, GTFS-RT and GBFS explains the data context.
Prepare the production integration
Trigger searches when position or filters change meaningfully. Group identical calls, set a timeout and adapt caching to the data type and service conditions.
A list of places and a real-time availability feed do not have the same freshness requirements. Test the flow with complete, empty, partial and error responses before presenting the search to users.
Extend the search to urban services
Stops and urban services use separate endpoints. To search for toilets around the same point, the GET route /v1/services/nearby expects lat and lon, with types=toilets. Do not send modes=toilets to this route: this vocabulary belongs to the map URL, not to the Services filter.
The following JavaScript example builds a Services URL for a 600-meter radius. It does not trigger the request; reuse the HTTP and contract controls described above. The expected collection becomes services, instead of stations. Keep service_type, location, distance_meters, and the attributes actually present.
The REST contract documents notably toilets, drinking_water, fountain, wifi, parking, charging, aed, and locker. The types exposed by the MCP may differ. For accepted parameters, their bounds, and the limits of your access, consult the schema of the interface used.
The attributes of a service do not guarantee its availability at the time of the search. Unknown accessibility does not equal an inaccessible service; an empty list resulting from an error does not prove the absence of toilets. Keep data specific to each family rather than reducing them to a name and a point.
For a combined map, associate results with their family and their identifiers. Display a Services error without clearing the stops returned by Transit. The search remains centered on the same point, but statuses and coverages may differ.
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());
Diagnosing an empty or error search
Directly integrate a filtered map into a website
Build an assistant around these searches
Frequently asked questions
Does Nearby provide upcoming departures?
Not in the contract shown here. This route discovers transport places; departures require a separate capability.
Can I show an empty list after an error?
Show an unavailability state. An error does not demonstrate the absence of stops.
Can I put the API token in the browser?
A secret must remain server-side. Use the access model provided for your application and account.