{"openapi":"3.1.0","info":{"title":"ROOTE API","version":"1.1.0","description":"Worldwide live mobility near a coordinate."},"servers":[{"url":"/","description":"Standalone ROOTE API"}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"rt_live_..."}}},"paths":{"/health":{"get":{"operationId":"health","summary":"API health","responses":{"200":{"description":"Running","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"ok"},"service":{"type":"string"},"version":{"type":"string"},"time":{"type":"string"}}}}}}}}},"/openapi.json":{"get":{"operationId":"openApi","summary":"OpenAPI document","responses":{"200":{"description":"OpenAPI 3.1 document","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/v1/geocode":{"get":{"operationId":"geocodeAddress","security":[{},{"bearerAuth":[]}],"summary":"Geocode an address","description":"Resolves address-like queries into up to five candidates in Google ranking order. The API does not choose a conversational answer.","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string","minLength":1,"maxLength":200}},{"name":"language","in":"query","schema":{"type":"string"}},{"name":"country","in":"query","schema":{"type":"string","minLength":2,"maxLength":2}},{"name":"token","in":"query","deprecated":true,"schema":{"type":"string"},"description":"Compatibility API token; prefer Authorization Bearer."}],"responses":{"200":{"description":"Up to five ordered geographic candidates. The first result is the provider's highest-ranked candidate, not a guaranteed unique match. No results returns HTTP 200 and an empty array.","content":{"application/json":{"schema":{"type":"object","required":["results","meta"],"properties":{"results":{"type":"array","maxItems":5,"description":"Geographic candidates in provider relevance order.","items":{"type":"object","required":["roote_id","name","label","type","location","address","source_id","source_place_id"],"properties":{"roote_id":{"type":"null"},"name":{"type":"string"},"label":{"type":"string"},"type":{"type":"string","enum":["address","street","locality","city","neighborhood","region","country","poi","station","airport","railway_station","transit_station","establishment","unknown"]},"location":{"type":"object","required":["lat","lon"],"properties":{"lat":{"type":"number"},"lon":{"type":"number"}}},"address":{"type":"object","properties":{"formatted":{"type":["string","null"]},"street":{"type":["string","null"]},"street_number":{"type":["string","null"]},"city":{"type":["string","null"]},"postal_code":{"type":["string","null"]},"region":{"type":["string","null"]},"country":{"type":["string","null"]}}},"source_id":{"type":"string","const":"google"},"source_place_id":{"type":["string","null"]},"match_quality":{"type":"string","enum":["rooftop","range_interpolated","geometric_center","approximate"],"description":"Provider-reported geocoding precision when available; not a ROOTE confidence score."}}}},"meta":{"type":"object","required":["source","cache","total"],"properties":{"source":{"type":"string"},"cache":{"type":"string","enum":["hit","miss"]},"total":{"type":"integer"},"query":{"type":"string"},"origin":{"type":"object","required":["lat","lon"],"properties":{"lat":{"type":"number"},"lon":{"type":"number"}}}}}}}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"429":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"502":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"503":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"504":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/v1/place-search":{"get":{"operationId":"searchPlaces","security":[{},{"bearerAuth":[]}],"summary":"Search places and POIs","description":"Resolves cities, POIs and named places into up to five candidates in Google ranking order. Position is optional and used only as location bias. The API does not choose a conversational answer.","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string","minLength":1,"maxLength":200}},{"name":"lat","in":"query","schema":{"type":"number","minimum":-90,"maximum":90}},{"name":"lon","in":"query","schema":{"type":"number","minimum":-180,"maximum":180}},{"name":"language","in":"query","schema":{"type":"string"}},{"name":"token","in":"query","deprecated":true,"schema":{"type":"string"},"description":"Compatibility API token; prefer Authorization Bearer."}],"responses":{"200":{"description":"Up to five ordered geographic candidates. The first result is the provider's highest-ranked candidate, not a guaranteed unique match. No results returns HTTP 200 and an empty array.","content":{"application/json":{"schema":{"type":"object","required":["results","meta"],"properties":{"results":{"type":"array","maxItems":5,"description":"Geographic candidates in provider relevance order.","items":{"type":"object","required":["roote_id","name","label","type","location","address","source_id","source_place_id"],"properties":{"roote_id":{"type":"null"},"name":{"type":"string"},"label":{"type":"string"},"type":{"type":"string","enum":["address","street","locality","city","neighborhood","region","country","poi","station","airport","railway_station","transit_station","establishment","unknown"]},"location":{"type":"object","required":["lat","lon"],"properties":{"lat":{"type":"number"},"lon":{"type":"number"}}},"address":{"type":"object","properties":{"formatted":{"type":["string","null"]},"street":{"type":["string","null"]},"street_number":{"type":["string","null"]},"city":{"type":["string","null"]},"postal_code":{"type":["string","null"]},"region":{"type":["string","null"]},"country":{"type":["string","null"]}}},"source_id":{"type":"string","const":"google"},"source_place_id":{"type":["string","null"]},"match_quality":{"type":"string","enum":["rooftop","range_interpolated","geometric_center","approximate"],"description":"Provider-reported geocoding precision when available; not a ROOTE confidence score."}}}},"meta":{"type":"object","required":["source","cache","total"],"properties":{"source":{"type":"string"},"cache":{"type":"string","enum":["hit","miss"]},"total":{"type":"integer"},"query":{"type":"string"},"origin":{"type":"object","required":["lat","lon"],"properties":{"lat":{"type":"number"},"lon":{"type":"number"}}}}}}}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"429":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"502":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"503":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"504":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/v1/reverse-geocode":{"get":{"operationId":"reverseGeocode","security":[{},{"bearerAuth":[]}],"summary":"Reverse geocode coordinates","description":"Anonymous calls remain available; authenticated calls require geography:read.","parameters":[{"name":"lat","in":"query","required":true,"schema":{"type":"number","minimum":-90,"maximum":90}},{"name":"lon","in":"query","required":true,"schema":{"type":"number","minimum":-180,"maximum":180}},{"name":"language","in":"query","schema":{"type":"string"}},{"name":"token","in":"query","deprecated":true,"schema":{"type":"string"},"description":"Compatibility API token; prefer Authorization Bearer."}],"responses":{"200":{"description":"Up to five ordered geographic candidates. The first result is the provider's highest-ranked candidate, not a guaranteed unique match. No results returns HTTP 200 and an empty array.","content":{"application/json":{"schema":{"type":"object","required":["results","meta"],"properties":{"results":{"type":"array","maxItems":5,"description":"Geographic candidates in provider relevance order.","items":{"type":"object","required":["roote_id","name","label","type","location","address","source_id","source_place_id"],"properties":{"roote_id":{"type":"null"},"name":{"type":"string"},"label":{"type":"string"},"type":{"type":"string","enum":["address","street","locality","city","neighborhood","region","country","poi","station","airport","railway_station","transit_station","establishment","unknown"]},"location":{"type":"object","required":["lat","lon"],"properties":{"lat":{"type":"number"},"lon":{"type":"number"}}},"address":{"type":"object","properties":{"formatted":{"type":["string","null"]},"street":{"type":["string","null"]},"street_number":{"type":["string","null"]},"city":{"type":["string","null"]},"postal_code":{"type":["string","null"]},"region":{"type":["string","null"]},"country":{"type":["string","null"]}}},"source_id":{"type":"string","const":"google"},"source_place_id":{"type":["string","null"]},"match_quality":{"type":"string","enum":["rooftop","range_interpolated","geometric_center","approximate"],"description":"Provider-reported geocoding precision when available; not a ROOTE confidence score."}}}},"meta":{"type":"object","required":["source","cache","total"],"properties":{"source":{"type":"string"},"cache":{"type":"string","enum":["hit","miss"]},"total":{"type":"integer"},"query":{"type":"string"},"origin":{"type":"object","required":["lat","lon"],"properties":{"lat":{"type":"number"},"lon":{"type":"number"}}}}}}}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"429":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"502":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"503":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"504":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/v1/services/nearby":{"get":{"operationId":"getNearbyServices","security":[{},{"bearerAuth":[]}],"summary":"Find nearby urban services","description":"Returns a compact service result with per-type counts. Parking and charging reuse the same Google adapter as their specialized endpoints; lockers use the public, non-guaranteed InPost Geowidget source behind a defensive adapter. Provider failures produce partial coverage; provider orchestration and counters are returned only when debug=true.","parameters":[{"name":"lat","in":"query","required":true,"schema":{"type":"number","minimum":-90,"maximum":90},"description":"Latitude of query_origin"},{"name":"lon","in":"query","required":true,"schema":{"type":"number","minimum":-180,"maximum":180},"description":"Longitude of query_origin"},{"name":"types","in":"query","required":true,"schema":{"type":"string"},"description":"Comma-separated types: aed, toilets, wifi, fountain, parking, charging, locker. drinking_water remains a compatibility alias."},{"name":"country","in":"query","required":false,"schema":{"type":"string","minLength":2,"maxLength":2,"pattern":"^[A-Za-z]{2}$"},"description":"Optional ISO 3166-1 alpha-2 country hint passed to providers that support it, including InPost."},{"name":"radius","in":"query","required":false,"schema":{"type":"number","exclusiveMinimum":0,"maximum":10000,"default":1500},"description":"Requested metres; values above 10000 are clamped to 10000"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200,"default":50},"description":"Requested aggregate count; values above 200 are clamped to 200. Google returns at most 20 items for each Google-backed category; InPost returns at most 100."},{"name":"debug","in":"query","required":false,"schema":{"type":"boolean","default":false},"description":"Include internal provider, cache and requested/applied diagnostics"},{"name":"token","in":"query","deprecated":true,"schema":{"type":"string"},"description":"Compatibility API token; prefer Authorization Bearer."}],"responses":{"200":{"description":"Compact nearby urban services result","content":{"application/json":{"schema":{"type":"object","required":["status","query_origin","radius","total","summary","results"],"properties":{"status":{"type":"string","enum":["success","empty","partial"]},"message":{"type":"string","description":"Deterministic convenience message for empty or incomplete coverage."},"query_origin":{"type":"object","required":["lat","lon"],"properties":{"lat":{"type":"number"},"lon":{"type":"number"}},"description":"Exact canonical coordinates used for the services search and distance calculation."},"radius":{"type":"number","maximum":10000,"description":"Effective search radius in metres."},"total":{"type":"integer","minimum":0},"summary":{"type":"object","description":"Returned result count for every requested service type, including zero counts.","additionalProperties":{"type":"integer","minimum":0}},"results":{"type":"array","maxItems":200,"items":{"type":"object","required":["id","type","service_type","name","location","distance_meters","attributes","source_id","source_type"],"properties":{"id":{"type":"string"},"type":{"type":"string","const":"service"},"service_type":{"type":"string","enum":["aed","toilets","drinking_water","fountain","wifi","parking","charging","locker"]},"provider":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}}},"external_id":{"type":"string"},"name":{"type":"string"},"location":{"type":"object","required":["lat","lon"],"properties":{"lat":{"type":"number"},"lon":{"type":"number"}}},"distance_meters":{"type":"integer","minimum":0},"attributes":{"type":"object"},"source_id":{"type":"string","enum":["aedmap","refuge","openstreetmap","google","inpost"]},"source_type":{"type":"string","enum":["partner_api","community"]}}}},"attributions":{"type":"array","description":"Attributions required when Google-backed parking or charging types are requested.","items":{"type":"object","required":["provider","display_name","required"],"properties":{"provider":{"type":"string","const":"Google"},"display_name":{"type":"string","const":"Google"},"required":{"type":"boolean","const":true}}}},"debug":{"type":"object","description":"Internal provider diagnostics returned only when debug=true.","properties":{"providers":{"type":"object","additionalProperties":{"type":"object","required":["status","raw_count","returned_count"],"properties":{"status":{"type":"string","enum":["ok","timeout","error","unauthorized","unavailable"]},"raw_count":{"type":"integer","minimum":0},"returned_count":{"type":"integer","minimum":0}}}},"provider_calls":{"type":"integer"},"cache":{"type":"string","enum":["hit","miss","partial"]},"requested_radius":{"type":"number"},"applied_radius":{"type":"number"},"requested_limit":{"type":"integer"},"applied_limit":{"type":"integer"}}}}}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"401":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"402":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"403":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"429":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"503":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/v1/parking/nearby":{"get":{"operationId":"getNearbyParking","security":[{},{"bearerAuth":[]}],"summary":"Find nearby parking","description":"Returns Google Places parking POIs normalized by ROOTE. Google attribution is mandatory for consumers.","parameters":[{"name":"lat","in":"query","required":true,"schema":{"type":"number","minimum":-90,"maximum":90},"description":"Latitude of query_origin"},{"name":"lon","in":"query","required":true,"schema":{"type":"number","minimum":-180,"maximum":180},"description":"Longitude of query_origin"},{"name":"language","in":"query","schema":{"type":"string"},"description":"Preferred Google result language"},{"name":"radius","in":"query","required":false,"schema":{"type":"number","exclusiveMinimum":0,"default":1500},"description":"Requested metres; values above 10000 are clamped to 10000"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":20},"description":"Requested count; values above the Google Nearby Search maximum of 20 are clamped to 20"},{"name":"debug","in":"query","required":false,"schema":{"type":"boolean","default":false},"description":"Include safe provider, cache and applied-limit diagnostics"},{"name":"token","in":"query","deprecated":true,"schema":{"type":"string"},"description":"Compatibility API token; prefer Authorization Bearer."}],"responses":{"200":{"description":"Nearby parking results","content":{"application/json":{"schema":{"type":"object","required":["status","query_origin","radius","total","results","attribution"],"properties":{"status":{"type":"string","enum":["success","empty","partial"]},"message":{"type":"string"},"query_origin":{"type":"object","required":["lat","lon"],"properties":{"lat":{"type":"number"},"lon":{"type":"number"}}},"radius":{"type":"number","maximum":10000},"total":{"type":"integer","minimum":0},"results":{"type":"array","maxItems":20,"items":{"type":"object","required":["id","type","service_type","name","location","distance_meters","attributes","source_id","source_type"],"properties":{"id":{"type":"string"},"type":{"type":"string","const":"service"},"service_type":{"type":"string","const":"parking"},"provider":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}}},"external_id":{"type":"string"},"name":{"type":"string"},"location":{"type":"object","required":["lat","lon"],"properties":{"lat":{"type":"number"},"lon":{"type":"number"}}},"distance_meters":{"type":"integer","minimum":0},"attributes":{"type":"object","required":["google_place_id","types","open_status","parking"],"properties":{"google_place_id":{"type":"string"},"address":{"type":"string"},"primary_type":{"type":"string","enum":["parking","parking_garage","parking_lot"]},"types":{"type":"array","items":{"type":"string"}},"open_status":{"type":"string","enum":["open","closed","unknown"]},"opening_hours":{"type":"array","items":{"type":"string"}},"google_maps_uri":{"type":"string"},"parking":{"type":"object","required":["kind","features"],"properties":{"kind":{"type":"string","enum":["parking","garage","lot"]},"features":{"type":"array","items":{"type":"string","enum":["free_parking","paid_parking","free_street_parking","paid_street_parking","valet_parking","free_garage_parking","paid_garage_parking"]}}}}}},"source_id":{"type":"string","const":"google"},"source_type":{"type":"string","const":"partner_api"}}}},"attribution":{"type":"object","required":["provider","display_name","required"],"properties":{"provider":{"type":"string","const":"Google"},"display_name":{"type":"string","const":"Google"},"required":{"type":"boolean","const":true}}},"debug":{"type":"object","description":"Internal provider diagnostics returned only when debug=true.","properties":{"providers":{"type":"object","additionalProperties":{"type":"object","required":["status","raw_count","returned_count"],"properties":{"status":{"type":"string","enum":["ok","timeout","error","unauthorized","unavailable"]},"raw_count":{"type":"integer","minimum":0},"returned_count":{"type":"integer","minimum":0}}}},"provider_calls":{"type":"integer"},"cache":{"type":"string","enum":["hit","miss","partial"]},"requested_radius":{"type":"number"},"applied_radius":{"type":"number"},"requested_limit":{"type":"integer"},"applied_limit":{"type":"integer"}}}}}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"401":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"402":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"403":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"429":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"503":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/v1/charging/nearby":{"get":{"operationId":"getNearbyEvCharging","security":[{},{"bearerAuth":[]}],"summary":"Find nearby EV charging stations","description":"Returns Google Places EV charging stations and connector availability when supplied. Missing availability is never represented as zero. Google attribution is mandatory for consumers.","parameters":[{"name":"lat","in":"query","required":true,"schema":{"type":"number","minimum":-90,"maximum":90},"description":"Latitude of query_origin"},{"name":"lon","in":"query","required":true,"schema":{"type":"number","minimum":-180,"maximum":180},"description":"Longitude of query_origin"},{"name":"language","in":"query","schema":{"type":"string"},"description":"Preferred Google result language"},{"name":"radius","in":"query","required":false,"schema":{"type":"number","exclusiveMinimum":0,"default":1500},"description":"Requested metres; values above 10000 are clamped to 10000"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":20},"description":"Requested count; values above the Google Nearby Search maximum of 20 are clamped to 20"},{"name":"debug","in":"query","required":false,"schema":{"type":"boolean","default":false},"description":"Include safe provider, cache and applied-limit diagnostics"},{"name":"token","in":"query","deprecated":true,"schema":{"type":"string"},"description":"Compatibility API token; prefer Authorization Bearer."}],"responses":{"200":{"description":"Nearby EV charging results","content":{"application/json":{"schema":{"type":"object","required":["status","query_origin","radius","total","results","attribution"],"properties":{"status":{"type":"string","enum":["success","empty","partial"]},"message":{"type":"string"},"query_origin":{"type":"object","required":["lat","lon"],"properties":{"lat":{"type":"number"},"lon":{"type":"number"}}},"radius":{"type":"number","maximum":10000},"total":{"type":"integer","minimum":0},"results":{"type":"array","maxItems":20,"items":{"type":"object","required":["id","type","service_type","name","location","distance_meters","attributes","source_id","source_type"],"properties":{"id":{"type":"string"},"type":{"type":"string","const":"service"},"service_type":{"type":"string","const":"charging"},"provider":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}}},"external_id":{"type":"string"},"name":{"type":"string"},"location":{"type":"object","required":["lat","lon"],"properties":{"lat":{"type":"number"},"lon":{"type":"number"}}},"distance_meters":{"type":"integer","minimum":0},"attributes":{"type":"object","required":["google_place_id","types","open_status","charging"],"properties":{"google_place_id":{"type":"string"},"address":{"type":"string"},"primary_type":{"type":"string","const":"electric_vehicle_charging_station"},"types":{"type":"array","items":{"type":"string"}},"open_status":{"type":"string","enum":["open","closed","unknown"]},"opening_hours":{"type":"array","items":{"type":"string"}},"google_maps_uri":{"type":"string"},"charging":{"type":"object","required":["connectors"],"properties":{"connector_count":{"type":"integer","minimum":0},"available_count":{"type":"integer","minimum":0},"out_of_service_count":{"type":"integer","minimum":0},"availability_updated_at":{"type":"string","format":"date-time"},"connectors":{"type":"array","items":{"type":"object","required":["type"],"properties":{"type":{"type":"string","enum":["J1772","Type 2","CHAdeMO","CCS1","CCS2","NACS","Tesla","GB/T","Other"]},"max_kw":{"type":"number","minimum":0},"count":{"type":"integer","minimum":0},"available_count":{"type":"integer","minimum":0},"out_of_service_count":{"type":"integer","minimum":0},"availability_updated_at":{"type":"string","format":"date-time"}}}}}}}},"source_id":{"type":"string","const":"google"},"source_type":{"type":"string","const":"partner_api"}}}},"attribution":{"type":"object","required":["provider","display_name","required"],"properties":{"provider":{"type":"string","const":"Google"},"display_name":{"type":"string","const":"Google"},"required":{"type":"boolean","const":true}}},"debug":{"type":"object","description":"Internal provider diagnostics returned only when debug=true.","properties":{"providers":{"type":"object","additionalProperties":{"type":"object","required":["status","raw_count","returned_count"],"properties":{"status":{"type":"string","enum":["ok","timeout","error","unauthorized","unavailable"]},"raw_count":{"type":"integer","minimum":0},"returned_count":{"type":"integer","minimum":0}}}},"provider_calls":{"type":"integer"},"cache":{"type":"string","enum":["hit","miss","partial"]},"requested_radius":{"type":"number"},"applied_radius":{"type":"number"},"requested_limit":{"type":"integer"},"applied_limit":{"type":"integer"}}}}}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"401":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"402":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"403":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"429":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"503":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/v1/transport/nearby":{"get":{"operationId":"getNearbyTransport","security":[{},{"bearerAuth":[]}],"summary":"Find nearby public transport stations","description":"Multi-provider transport discovery. TripGo is the first provider; realtime departures and alerts are intentionally not fetched by this endpoint.","parameters":[{"name":"lat","in":"query","required":true,"schema":{"type":"number","minimum":-90,"maximum":90},"description":"Latitude of query_origin"},{"name":"lng","in":"query","required":false,"schema":{"type":"number","minimum":-180,"maximum":180},"description":"Longitude; supply lng or lon."},{"name":"lon","in":"query","required":false,"schema":{"type":"number","minimum":-180,"maximum":180},"description":"ROOTE compatibility alias for lng."},{"name":"radius","in":"query","required":false,"schema":{"type":"number","exclusiveMinimum":0,"maximum":5000,"default":1000},"description":"Requested metres; values above 5000 are clamped to 5000"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200,"default":50},"description":"Maximum returned stations; capability policy can apply a lower limit"},{"name":"modes","in":"query","schema":{"type":"string","default":"bus,tram,metro,rail,rapid_transit,ferry,coach"},"description":"Comma-separated normalized ROOTE transport modes"},{"name":"providers","in":"query","schema":{"type":"string","default":"tripgo"},"description":"Comma-separated providers: tripgo, navitia, gtfs, gbfs"},{"name":"realtime","in":"query","schema":{"type":"boolean","default":false},"description":"Reserved preference; Nearby reports capabilities without fetching departures or alerts."},{"name":"language","in":"query","schema":{"type":"string"},"description":"Preferred response language for providers that support it."},{"name":"debug","in":"query","required":false,"schema":{"type":"boolean","default":false},"description":"Include provider and cache diagnostics"},{"name":"token","in":"query","deprecated":true,"schema":{"type":"string"},"description":"Compatibility API token; prefer Authorization Bearer."}],"responses":{"200":{"description":"Normalized nearby transport stations","content":{"application/json":{"schema":{"type":"object","required":["status","query_origin","radius","total","results"],"properties":{"status":{"type":"string","enum":["success","empty","partial"]},"message":{"type":"string"},"query_origin":{"type":"object","required":["lat","lon"],"properties":{"lat":{"type":"number"},"lon":{"type":"number"}}},"radius":{"type":"number","maximum":5000},"total":{"type":"integer","minimum":0},"results":{"type":"object","required":["stations"],"properties":{"stations":{"type":"array","maxItems":200,"items":{"type":"object","required":["id","type","name","location","distance_meters","modes","operators","routes","realtime","alerts","accessibility","freshness","sources"],"properties":{"id":{"type":"string","pattern":"^roote_transport_station_"},"type":{"type":"string","const":"transport_station"},"name":{"type":"string"},"location":{"type":"object","required":["lat","lon"],"properties":{"lat":{"type":"number"},"lon":{"type":"number"}}},"distance_meters":{"type":"integer","minimum":0},"modes":{"type":"array","items":{"type":"string","enum":["bus","tram","metro","rail","rapid_transit","ferry","coach","cable_transport","bicycle","scooter","car_share","carpool","taxi","rideshare","demand_responsive","shared_mobility","other"]}},"operators":{"type":"array","items":{"type":"object"}},"routes":{"type":"array","items":{"type":"object"}},"realtime":{"type":"object","required":["available","queried"],"properties":{"available":{"type":["boolean","null"]},"queried":{"type":"boolean","const":false}}},"alerts":{"type":"object","required":["available","queried"],"properties":{"available":{"type":["boolean","null"]},"queried":{"type":"boolean","const":false}}},"accessibility":{"type":"object","required":["wheelchair"],"properties":{"wheelchair":{"type":"string","enum":["yes","no","unknown"]}}},"freshness":{"type":"object","required":["data_class","fetched_at"],"properties":{"data_class":{"type":"string","const":"static"},"fetched_at":{"type":"string","format":"date-time"}}},"sources":{"type":"array","items":{"type":"object","required":["provider","region","source_id","operator_id","feed_id"],"properties":{"provider":{"type":"string","enum":["tripgo","navitia","gtfs","gbfs"]},"region":{"type":["string","null"]},"source_id":{"type":"string"},"operator_id":{"type":["string","null"]},"feed_id":{"type":["string","null"]}}}}}}}}},"debug":{"type":"object","description":"Provider and cache diagnostics returned only when debug=true."}}}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"401":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"402":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"403":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"429":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"503":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/v1/capabilities":{"post":{"operationId":"runCapability","security":[{},{"bearerAuth":[]}],"summary":"Execute a ROOTE Contract 1.0.0 capability","description":"Strict Contract 1.0.0 boundary. search_mobility uses the existing provider orchestration; read_dataset returns the exact stored id/version without provider calls.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["contract_version","correlation","request","freshness_policy"],"properties":{"contract_version":{"type":"string","const":"1.0.0"},"correlation":{"type":"object","additionalProperties":false,"required":["conversation_id","interaction_id","request_id","parent_request_id","turn_id"]},"request":{"oneOf":[{"type":"object","additionalProperties":false,"required":["capability","args"],"properties":{"capability":{"type":"string","const":"search_mobility"},"args":{"type":"object"}}},{"type":"object","additionalProperties":false,"required":["capability","args"],"properties":{"capability":{"type":"string","const":"read_dataset"},"args":{"type":"object","required":["id","version"],"properties":{"id":{"type":"string"},"version":{"type":"string"}}}}}]},"freshness_policy":{"type":["string","null"],"enum":["accept_valid_cache","revalidate",null]}}}}}},"responses":{"200":{"description":"Canonical CapabilityResult","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["contract_version","correlation","observation"],"properties":{"contract_version":{"type":"string","const":"1.0.0"},"correlation":{"type":"object"},"observation":{"oneOf":[{"type":"object","required":["dataset_id","scope","query_parameters","received_at","provenance","freshness"],"properties":{"dataset_id":{"type":"string","pattern":"^nearby_"},"scope":{"type":"string","const":"mobility.nearby"},"query_parameters":{"type":"object"},"received_at":{"type":["string","null"],"format":"date-time"},"provenance":{"type":"array","items":{"type":"object"}},"freshness":{"type":"object","required":["fresh","stale","unknown","realtime_reliable"],"properties":{"fresh":{"type":"integer"},"stale":{"type":"integer"},"unknown":{"type":"integer"},"realtime_reliable":{"type":"boolean"}}}}},{"type":"object","required":["contract_version","status","query","delivered_at","errors"],"properties":{"contract_version":{"type":"string","const":"1.0.0"},"status":{"type":"string","const":"error"},"query":{"type":["object","null"]},"delivered_at":{"type":"string","format":"date-time"},"errors":{"type":"array"}}}]}}}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"404":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"410":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"429":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"503":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/v1/nearby":{"get":{"operationId":"getGlobalNearby","security":[{},{"bearerAuth":[]}],"summary":"What is around me now?","description":"Returns canonical ROOTE mobility entities. High-confidence observations of the same physical station are resolved and merged before counts, pagination and billing. Provider identity, provenance, cache, usage, protection and orchestration diagnostics are included only when debug=true. Anonymous calls use the Free usage policy. Radius is capped at 400 metres.","parameters":[{"name":"lat","in":"query","required":true,"schema":{"type":"number","minimum":-90,"maximum":90},"description":"Latitude of query_origin"},{"name":"lon","in":"query","required":false,"schema":{"type":"number","minimum":-180,"maximum":180},"description":"Longitude of query_origin; supply lon or lng"},{"name":"lng","in":"query","required":false,"schema":{"type":"number","minimum":-180,"maximum":180},"description":"Alias of lon"},{"name":"radius","in":"query","required":false,"schema":{"type":"number","minimum":1,"default":400},"description":"Requested metres; maximum applied is 400"},{"name":"modes","in":"query","required":false,"schema":{"type":"string","default":"bicycle,scooter,moped,car"},"description":"Comma-separated ROOTE modes"},{"name":"include","in":"query","required":false,"schema":{"type":"string","default":"stations,vehicles"},"description":"Comma-separated result families"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":100},"description":"Requested count; plan limits apply"},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0},"description":"Pagination offset"},{"name":"format","in":"query","required":false,"schema":{"type":"string","enum":["json","geojson"],"default":"json"},"description":"Response format"},{"name":"debug","in":"query","required":false,"schema":{"type":"boolean","default":false},"description":"Include provider provenance and internal execution diagnostics"},{"name":"token","in":"query","deprecated":true,"schema":{"type":"string"},"description":"Compatibility API token; prefer Authorization Bearer."}],"responses":{"200":{"description":"Compact nearby mobility result","content":{"application/json":{"schema":{"type":"object","required":["status","query_origin","radius","total","results","available_actions"],"properties":{"status":{"type":"string","enum":["success","empty","partial"]},"message":{"type":"string","description":"Deterministic human-readable convenience text generated by api.roote.ai; machine consumers must use status, total, results and warnings."},"query_origin":{"type":"object","required":["lat","lon"],"properties":{"lat":{"type":"number"},"lon":{"type":"number"}},"description":"Exact point used to execute the nearby search and calculate distance_meters."},"radius":{"type":"number","maximum":400},"total":{"type":"integer","minimum":0,"description":"Number of normalized public objects after identity resolution and deduplication, before pagination and plan limits."},"results":{"type":"object","required":["places","lines","stations","vehicles","alerts"],"properties":{"places":{"type":"array","items":{"type":"object"}},"lines":{"type":"array","items":{"type":"object"}},"stations":{"type":"array","items":{"type":"object","required":["id","type","name","network","location","availability","distance_meters"],"properties":{"id":{"type":"string","pattern":"^roote_station_"},"type":{"type":"string","const":"station"},"name":{"type":"string"},"network":{"type":"object","required":["id","name"],"properties":{"id":{"type":"string"},"name":{"type":"string"}}},"location":{"type":"object","required":["lat","lon"],"properties":{"lat":{"type":"number"},"lon":{"type":"number"}}},"capacity":{"type":["integer","null"]},"availability":{"type":"object"},"distance_meters":{"type":"number"},"entity_type":{"type":["string","null"],"enum":["bicycle_vehicle","bicycle_station","scooter_vehicle","motorscooter_vehicle","car_vehicle","parking","transit_stop","transit_station",null]},"mode":{"type":["string","null"]},"data_class":{"type":"string","enum":["realtime","semi_static","static"]},"service_status":{"type":"object","required":["state"],"properties":{"state":{"type":"string","enum":["operational","degraded","unavailable","maintenance","unknown"]}}},"capabilities":{"type":"object","required":["pickup","return","park","charge","reserve","navigate"],"properties":{"pickup":{"type":"boolean"},"return":{"type":"boolean"},"park":{"type":"boolean"},"charge":{"type":"boolean"},"reserve":{"type":"boolean"},"navigate":{"type":"boolean"}}},"action_state":{"type":"object","additionalProperties":{"type":"string","enum":["available_now","unavailable_now","unknown"]}},"context_actions":{"type":"array","items":{"type":"object","required":["id","intent","mode"],"properties":{"id":{"type":"string"},"intent":{"type":"string","enum":["explore","pickup","return","depart","arrive","park","charge","reserve"]},"mode":{"type":"string","enum":["bicycle","scooter","moped","car","other"]}}}}}}},"vehicles":{"type":"array","items":{"type":"object","required":["source","source_id","network_id"],"properties":{"source":{"type":"object","required":["entity_type","mode","data_class","service_status","capabilities","action_state","context_actions"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"location":{"type":"object","required":["lat","lon"],"properties":{"lat":{"type":"number"},"lon":{"type":"number"}}},"source_kind":{"type":"string","enum":["provider","gbfs"]},"distance_meters":{"type":"number","description":"Straight-line distance in meters from query_origin to the entity location."},"entity_type":{"type":["string","null"],"enum":["bicycle_vehicle","bicycle_station","scooter_vehicle","motorscooter_vehicle","car_vehicle","parking","transit_stop","transit_station",null]},"mode":{"type":["string","null"]},"data_class":{"type":"string","enum":["realtime","semi_static","static"]},"service_status":{"type":"object","required":["state"],"properties":{"state":{"type":"string","enum":["operational","degraded","unavailable","maintenance","unknown"]}}},"capabilities":{"type":"object","required":["pickup","return","park","charge","reserve","navigate"],"properties":{"pickup":{"type":"boolean"},"return":{"type":"boolean"},"park":{"type":"boolean"},"charge":{"type":"boolean"},"reserve":{"type":"boolean"},"navigate":{"type":"boolean"}}},"action_state":{"type":"object","additionalProperties":{"type":"string","enum":["available_now","unavailable_now","unknown"]}},"context_actions":{"type":"array","items":{"type":"object","required":["id","intent","mode"],"properties":{"id":{"type":"string"},"intent":{"type":"string","enum":["explore","pickup","return","depart","arrive","park","charge","reserve"]},"mode":{"type":"string","enum":["bicycle","scooter","moped","car","other"]}}}}}},"source_id":{"type":"string"},"network_id":{"type":"string"},"canonical_id":{"type":"null"},"resolution_status":{"type":"string","enum":["unresolved","merged","possible_match"]},"roote_id":{"type":"string"},"entity_source":{"type":"string","const":"roote"},"resolution_confidence":{"type":"number","minimum":0,"maximum":1},"provenance":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["provider","roote_internal"]},"source":{"type":"string"},"provider":{"type":"string"},"entity_id":{"type":"string"},"source_id":{"type":"string"},"network_id":{"type":"string"},"fields":{"type":"array","items":{"type":"string"}}}}},"conflicts":{"type":"array","items":{"type":"object"}}}}},"alerts":{"type":"array","items":{"type":"object"}}}},"available_actions":{"type":"array","items":{"type":"object","required":["id","intent","mode"],"properties":{"id":{"type":"string"},"intent":{"type":"string","enum":["explore","pickup","return","depart","arrive","park","charge","reserve"]},"mode":{"type":"string","enum":["bicycle","scooter","moped","car","other"]}}}},"requested_radius":{"type":"number"},"requested_limit":{"type":"integer"},"limit":{"type":"integer"},"warnings":{"type":"array","items":{"type":"object","required":["code","message","requested","applied"],"properties":{"code":{"type":"string","enum":["radius_capped","limit_capped"]},"message":{"type":"string"},"requested":{"type":"number"},"applied":{"type":"number"}}}},"debug":{"type":"object","properties":{"sources":{"type":"array","items":{"type":"object","properties":{"source_id":{"type":"string"},"status":{"type":"string"},"raw_count":{"type":"integer"},"matched_count":{"type":"integer"},"reason":{"type":["string","null"]}}}},"resolution":{"type":"object"},"entities":{"type":"array","description":"Canonical station provenance and entity-resolution diagnostics.","items":{"type":"object"}},"realtime":{"type":"object"},"warnings":{"type":"array","items":{"type":"string"}},"usage":{"type":"object"},"protection":{"type":"object"},"orchestration":{"type":"object"},"requested_radius":{"type":"number"},"applied_radius":{"type":"number"},"requested_limit":{"type":"integer"},"applied_limit":{"type":"integer"},"limit":{"type":"integer"},"offset":{"type":"integer"},"coverage":{"type":"string"}},"description":"Safe internal diagnostics returned only when debug=true."}}}},"application/geo+json":{"schema":{"type":"object","required":["query_origin","type","features","available_actions"],"properties":{"query_origin":{"type":"object","required":["lat","lon"],"properties":{"lat":{"type":"number"},"lon":{"type":"number"}},"description":"Coordinates used as the spatial origin for this GeoJSON query."},"type":{"type":"string","const":"FeatureCollection"},"features":{"type":"array","items":{"type":"object"}},"available_actions":{"type":"array","items":{"type":"object","required":["id","intent","mode"],"properties":{"id":{"type":"string"},"intent":{"type":"string","enum":["explore","pickup","return","depart","arrive","park","charge","reserve"]},"mode":{"type":"string","enum":["bicycle","scooter","moped","car","other"]}}}},"meta":{"type":"object"}}}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"401":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"402":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"403":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"429":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}}}}