{"openapi":"3.1.2","jsonSchemaDialect":"https://json-schema.org/draft/2020-12/schema","info":{"title":"Unified Transit Interface local API","version":"0.1.0","description":"Synthetic Bengaluru reference implementation. AIS-140-style input is an adapter output contract, not a device wire format. The local ingress is unauthenticated and must not be exposed publicly. Bridge schemas are generated from the runtime Zod contracts. Web response schemas describe the current facade."},"servers":[{"url":"http://localhost:4100","description":"Local bridge"}],"paths":{"/health":{"get":{"summary":"Bridge health","responses":{"200":{"description":"Healthy","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Health"}}}}}}},"/v1/observations":{"post":{"summary":"Ingest a normalized observation","description":"Idempotency key: providerId + vehicleId + observedAt. Duplicate packets return 202 with duplicate=true. Older packets do not replace a newer snapshot. Unknown assignments are accepted but unassigned. Explicit tripHint requires serviceDate for assignment. Extra JSON properties are stripped by the runtime parser.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Observation"}}}},"responses":{"202":{"description":"Accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IngestionReceipt"}}}},"400":{"description":"Invalid JSON or observation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Request body too large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Unsupported content type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Local request limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/vehicles":{"get":{"summary":"Latest observations with assignment and freshness","responses":{"200":{"description":"Snapshots","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/VehicleSnapshot"}}},"required":["data"]}}}}}}},"/v1/observations/batch":{"post":{"summary":"Ingest a simulated fleet snapshot","description":"Same validation and deduplication as single ingress. The whole array is validated before ingestion. Maximum 5000 observations and 4 MiB per request.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Observation"},"minItems":1,"maxItems":5000}}}},"responses":{"202":{"description":"Accepted","content":{"application/json":{"schema":{"type":"object","properties":{"accepted":{"const":true},"count":{"type":"number"},"duplicates":{"type":"number"}},"required":["accepted","count","duplicates"]}}}},"400":{"description":"Invalid observations","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Request too large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/vehicles/{vehicleId}":{"get":{"summary":"One vehicle snapshot","parameters":[{"name":"vehicleId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Snapshot","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/VehicleSnapshot"}},"required":["data"]}}}},"404":{"description":"Unknown vehicle","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/gtfs/schedule.zip":{"get":{"summary":"Download the paired synthetic GTFS Schedule","responses":{"200":{"description":"The same archive loaded by OTP. Generate with pnpm gtfs:demo.","content":{"application/zip":{"schema":{"type":"string","format":"binary"}}}},"503":{"description":"Schedule has not been generated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/gtfs-rt/vehicle-positions.pb":{"get":{"summary":"VehiclePositions Protocol Buffer","description":"Synthetic GTFS-Realtime 2.0 FULL_DATASET. No authentication in this local prototype.","responses":{"200":{"description":"Current full snapshot. An empty entity list is valid when no usable observations exist.","headers":{"X-Data-Origin":{"schema":{"const":"synthetic"}},"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/x-protobuf":{"schema":{"type":"string","format":"binary"}}}},"429":{"description":"Local request limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/gtfs-rt/vehicle-positions.json":{"get":{"summary":"VehiclePositions debug JSON","description":"Synthetic GTFS-Realtime 2.0 FULL_DATASET. No authentication in this local prototype.","responses":{"200":{"description":"Current full snapshot. An empty entity list is valid when no usable observations exist.","headers":{"X-Data-Origin":{"schema":{"const":"synthetic"}},"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GtfsRealtimeJson"}}}},"429":{"description":"Local request limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/gtfs-rt/trip-updates.pb":{"get":{"summary":"TripUpdates Protocol Buffer","description":"Synthetic GTFS-Realtime 2.0 FULL_DATASET. No authentication in this local prototype.","responses":{"200":{"description":"Current full snapshot. An empty entity list is valid when no usable observations exist.","headers":{"X-Data-Origin":{"schema":{"const":"synthetic"}},"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/x-protobuf":{"schema":{"type":"string","format":"binary"}}}},"429":{"description":"Local request limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/gtfs-rt/trip-updates.json":{"get":{"summary":"TripUpdates debug JSON","description":"Synthetic GTFS-Realtime 2.0 FULL_DATASET. No authentication in this local prototype.","responses":{"200":{"description":"Current full snapshot. An empty entity list is valid when no usable observations exist.","headers":{"X-Data-Origin":{"schema":{"const":"synthetic"}},"Cache-Control":{"schema":{"const":"no-store"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GtfsRealtimeJson"}}}},"429":{"description":"Local request limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/openapi.json":{"get":{"summary":"This OpenAPI document","responses":{"200":{"description":"OpenAPI 3.1.2","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/schemas/observation.schema.json":{"get":{"summary":"Runtime-derived ingress schema","responses":{"200":{"description":"JSON Schema 2020-12","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/journeys":{"servers":[{"url":"http://localhost:3000","description":"Local Next.js server"}],"get":{"summary":"Plan a door-to-door journey between two demo places using OTP","parameters":[{"name":"from","in":"query","required":true,"schema":{"type":"string","description":"Place ID from packages/network/data/catalogue.json","example":"koramangala-home"}},{"name":"to","in":"query","required":true,"schema":{"type":"string","description":"Place ID from packages/network/data/catalogue.json","example":"ecospace"}},{"name":"departure","in":"query","required":false,"schema":{"type":"string","format":"date-time"},"description":"Defaults to now. Must be within 24 hours of now. All display times use Asia/Kolkata."}],"responses":{"200":{"description":"Up to five journeys; empty list when no journey is found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JourneyResponse"}}}},"400":{"description":"Invalid places or departure","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"OTP unavailable or invalid response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/vehicles":{"servers":[{"url":"http://localhost:3000","description":"Local Next.js server"}],"get":{"summary":"Track exact dated trips without replanning a journey","parameters":[{"name":"trips","in":"query","required":true,"schema":{"type":"string"},"description":"One to four comma-separated tripId:YYYYMMDD values"}],"responses":{"200":{"description":"Matching vehicle signals; available=false when bridge is unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrackingResponse"}}}},"400":{"description":"Invalid dated trip identifiers","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/stops/{stopId}/arrivals":{"servers":[{"url":"http://localhost:3000","description":"Local Next.js server"}],"get":{"summary":"Stop board with realtime arrivals and timetable fallback","parameters":[{"name":"stopId","in":"path","required":true,"schema":{"type":"string","description":"A stop ID from the demo network catalogue","example":"UTI-S-2509433159"}}],"responses":{"200":{"description":"Next six arrivals, across demo routes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StopArrivals"}}}},"404":{"description":"Unknown stop","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/standards":{"servers":[{"url":"http://localhost:3000","description":"Local Next.js server"}],"get":{"summary":"One observation through assignment and both feed entities","responses":{"200":{"description":"Inspectable pipeline","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardsSnapshot"}}}},"502":{"description":"Bridge unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"No observations","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/feed/demo/{feed}":{"servers":[{"url":"http://localhost:3000","description":"Local Next.js server"}],"get":{"summary":"Same-origin read-only proxy for feeds and contract documents","parameters":[{"name":"feed","in":"path","required":true,"schema":{"type":"string","enum":["VehiclePositions.pb","VehiclePositions.json","TripUpdates.pb","TripUpdates.json","schedule.zip","openapi.json","observation.schema.json"]}}],"responses":{"200":{"description":"Selected document or feed; content type is forwarded from the bridge","content":{"application/json":{"schema":{"type":"object"}},"application/zip":{"schema":{"type":"string","format":"binary"}},"application/x-protobuf":{"schema":{"type":"string","format":"binary"}}}},"404":{"description":"Unknown feed name","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Bridge feed unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"schemas":{"Observation":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"schemaVersion":{"type":"string","const":"1.0"},"sourceProtocol":{"type":"string","const":"AIS-140"},"providerId":{"type":"string","minLength":1},"vehicleId":{"type":"string","minLength":1},"observedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},"receivedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},"position":{"type":"object","properties":{"latitude":{"type":"number","minimum":-90,"maximum":90},"longitude":{"type":"number","minimum":-180,"maximum":180}},"required":["latitude","longitude"]},"speedKph":{"type":"number","minimum":0,"maximum":180},"headingDegrees":{"type":"number","minimum":0,"exclusiveMaximum":360},"routeHint":{"type":"string","minLength":1},"tripHint":{"type":"string","minLength":1},"serviceDate":{"type":"string","pattern":"^\\d{8}$"}},"required":["schemaVersion","sourceProtocol","providerId","vehicleId","observedAt","position","speedKph","headingDegrees"]},"VehicleSnapshot":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"observation":{"type":"object","properties":{"schemaVersion":{"type":"string","const":"1.0"},"sourceProtocol":{"type":"string","const":"AIS-140"},"providerId":{"type":"string","minLength":1},"vehicleId":{"type":"string","minLength":1},"observedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},"receivedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},"position":{"type":"object","properties":{"latitude":{"type":"number","minimum":-90,"maximum":90},"longitude":{"type":"number","minimum":-180,"maximum":180}},"required":["latitude","longitude"],"additionalProperties":false},"speedKph":{"type":"number","minimum":0,"maximum":180},"headingDegrees":{"type":"number","minimum":0,"exclusiveMaximum":360},"routeHint":{"type":"string","minLength":1},"tripHint":{"type":"string","minLength":1},"serviceDate":{"type":"string","pattern":"^\\d{8}$"}},"required":["schemaVersion","sourceProtocol","providerId","vehicleId","observedAt","position","speedKph","headingDegrees"],"additionalProperties":false},"assignment":{"anyOf":[{"type":"object","properties":{"vehicleId":{"type":"string"},"routeId":{"type":"string"},"tripId":{"type":"string"},"startDate":{"type":"string","pattern":"^\\d{8}$"},"startTime":{"type":"string","pattern":"^\\d{2}:\\d{2}:\\d{2}$"},"stopId":{"type":"string"},"confidence":{"type":"number","minimum":0,"maximum":1},"method":{"type":"string","enum":["direct_hint","route_geometry","schedule_window","unassigned"]},"assignedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"}},"required":["vehicleId","routeId","tripId","confidence","method","assignedAt"],"additionalProperties":false},{"type":"null"}]},"freshness":{"type":"string","enum":["live","recent","stale","scheduled"]},"ageSeconds":{"type":"number","minimum":0}},"required":["observation","assignment","freshness","ageSeconds"],"additionalProperties":false},"IngestionReceipt":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"accepted":{"type":"boolean","const":true},"vehicleId":{"type":"string"},"observedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},"duplicate":{"type":"boolean"}},"required":["accepted","vehicleId","observedAt","duplicate"],"additionalProperties":false},"Health":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"status":{"type":"string","const":"ok"},"service":{"type":"string"},"version":{"type":"string"},"now":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"}},"required":["status","service","version","now"],"additionalProperties":false},"Error":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"},"statusCode":{"type":"number"},"issues":{"type":"array","items":{"type":"object"}}},"required":["error"]},"GtfsRealtimeJson":{"type":"object","properties":{"header":{"type":"object","properties":{"gtfsRealtimeVersion":{"const":"2.0"},"timestamp":{"type":"number"},"incrementality":{"const":"FULL_DATASET"}},"required":["gtfsRealtimeVersion","timestamp","incrementality"]},"entity":{"type":"array","items":{"type":"object"}}},"required":["header"],"description":"Debug projection from gtfs-realtime-bindings: camelCase fields, enum strings and numeric int64 values. Entity contents follow the authoritative GTFS-Realtime protobuf schema, not a UTI-specific replacement.","externalDocs":{"url":"https://gtfs.org/documentation/realtime/reference/"}},"Place":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"area":{"type":"string"},"kind":{"type":"string"},"lat":{"type":"number"},"lng":{"type":"number"},"nearbyStopId":{"type":"string"},"fictional":{"type":"boolean"}},"required":["id","name","area","kind","lat","lng","nearbyStopId"]},"JourneyPoint":{"type":"object","properties":{"name":{"type":"string"},"lat":{"type":"number"},"lng":{"type":"number"},"stopId":{"type":"string"}},"required":["name","lat","lng"]},"JourneyLeg":{"type":"object","properties":{"mode":{"enum":["WALK","BUS"]},"start":{"type":"string","format":"date-time"},"end":{"type":"string","format":"date-time"},"scheduledStart":{"type":"string","format":"date-time"},"scheduledEnd":{"type":"string","format":"date-time"},"durationSeconds":{"type":"number"},"distanceMeters":{"type":"number"},"from":{"$ref":"#/components/schemas/JourneyPoint"},"to":{"$ref":"#/components/schemas/JourneyPoint"},"geometry":{"type":"array","items":{"type":"array","prefixItems":[{"type":"number"},{"type":"number"}],"minItems":2,"maxItems":2}},"routeId":{"type":"string"},"routeName":{"type":"string"},"headsign":{"type":"string"},"tripId":{"type":"string"},"serviceDate":{"type":"string","pattern":"^\\d{8}$"},"realtime":{"type":"boolean"}},"required":["mode","start","end","scheduledStart","scheduledEnd","durationSeconds","distanceMeters","from","to","geometry","realtime"]},"Journey":{"type":"object","properties":{"id":{"type":"string"},"start":{"type":"string","format":"date-time"},"end":{"type":"string","format":"date-time"},"durationSeconds":{"type":"number"},"walkingSeconds":{"type":"number"},"waitingSeconds":{"type":"number"},"transfers":{"type":"number"},"legs":{"type":"array","items":{"$ref":"#/components/schemas/JourneyLeg"}}},"required":["id","start","end","durationSeconds","walkingSeconds","waitingSeconds","transfers","legs"]},"JourneyResponse":{"type":"object","properties":{"generatedAt":{"type":"string","format":"date-time"},"requestedDeparture":{"type":"string","format":"date-time"},"from":{"$ref":"#/components/schemas/Place"},"to":{"$ref":"#/components/schemas/Place"},"journeys":{"type":"array","items":{"$ref":"#/components/schemas/Journey"}},"dataOrigin":{"const":"synthetic"}},"required":["generatedAt","requestedDeparture","from","to","journeys","dataOrigin"]},"TrackedBus":{"type":"object","properties":{"vehicleId":{"type":"string"},"tripId":{"type":"string"},"serviceDate":{"type":"string"},"routeName":{"type":"string"},"headsign":{"type":"string"},"observedAt":{"type":"string","format":"date-time"},"latitude":{"type":"number"},"longitude":{"type":"number"},"ageSeconds":{"type":"number"},"freshness":{"enum":["live","recent","stale","scheduled"]},"speedKph":{"type":"number"},"progressMeters":{"type":"number"},"nextStopDistanceMeters":{"type":"number"},"nextStopName":{"type":"string"},"shape":{"type":"array","items":{"type":"array","prefixItems":[{"type":"number"},{"type":"number"}],"minItems":2,"maxItems":2}},"distances":{"type":"array","items":{"type":"number"}}},"required":["vehicleId","tripId","serviceDate","routeName","headsign","observedAt","latitude","longitude","ageSeconds","freshness","speedKph","progressMeters","nextStopDistanceMeters","nextStopName","shape","distances"]},"TrackingResponse":{"type":"object","properties":{"generatedAt":{"type":"string","format":"date-time"},"available":{"type":"boolean"},"vehicles":{"type":"array","items":{"$ref":"#/components/schemas/TrackedBus"}},"trips":{"type":"array","items":{"$ref":"#/components/schemas/TrackedTrip"}}},"required":["generatedAt","available","vehicles","trips"]},"TripStopCall":{"type":"object","properties":{"stopId":{"type":"string"},"name":{"type":"string"},"lat":{"type":"number"},"lng":{"type":"number"},"sequence":{"type":"number"},"distanceMeters":{"type":"number"},"scheduledAt":{"type":"string","format":"date-time"},"arrival":{"type":"string","format":"date-time"},"departure":{"type":"string","format":"date-time"},"realtime":{"type":"boolean"},"passed":{"type":"boolean"}},"required":["stopId","name","lat","lng","sequence","distanceMeters","scheduledAt","arrival","departure","realtime","passed"]},"TrackedTrip":{"type":"object","properties":{"tripId":{"type":"string"},"serviceDate":{"type":"string"},"routeName":{"type":"string"},"headsign":{"type":"string"},"stops":{"type":"array","items":{"$ref":"#/components/schemas/TripStopCall"}}},"required":["tripId","serviceDate","routeName","headsign","stops"]},"StopArrival":{"allOf":[{"type":"object","properties":{"tripId":{"type":"string"},"serviceDate":{"type":"string","pattern":"^\\d{8}$"},"routeId":{"type":"string"},"routeShortName":{"type":"string"},"headsign":{"type":"string"},"directionId":{"enum":[0,1]},"stopSequence":{"type":"number"},"effectiveAt":{"type":"number"},"scheduledAt":{"anyOf":[{"type":"number"},{"type":"null"}]},"state":{"enum":["live","recent","stale","scheduled"]}},"required":["tripId","routeId","routeShortName","headsign","directionId","stopSequence","effectiveAt","scheduledAt","state"]},{"oneOf":[{"type":"object","properties":{"source":{"const":"scheduled"}},"required":["source"]},{"type":"object","properties":{"source":{"const":"realtime"},"predictedAt":{"type":"number"},"delaySeconds":{"anyOf":[{"type":"number"},{"type":"null"}]},"uncertaintySeconds":{"anyOf":[{"type":"number"},{"type":"null"}]},"ageSeconds":{"type":"number"},"vehicleId":{"anyOf":[{"type":"string"},{"type":"null"}]},"lastObservedAt":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["source","predictedAt","delaySeconds","uncertaintySeconds","ageSeconds","vehicleId","lastObservedAt"]}]}]},"StopArrivals":{"type":"object","properties":{"generatedAt":{"type":"string"},"stop":{"type":"object","properties":{"id":{"type":"string","description":"A stop ID from the demo network catalogue","example":"UTI-S-2509433159"},"name":{"type":"string"}},"required":["id","name"]},"realtimeAvailable":{"type":"boolean"},"arrivals":{"type":"array","items":{"$ref":"#/components/schemas/StopArrival"}}},"required":["generatedAt","stop","realtimeAvailable","arrivals"]},"StandardsSnapshot":{"type":"object","properties":{"generatedAt":{"type":"string"},"observation":{"$ref":"#/components/schemas/Observation"},"assignment":{"anyOf":[{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"vehicleId":{"type":"string"},"routeId":{"type":"string"},"tripId":{"type":"string"},"startDate":{"type":"string","pattern":"^\\d{8}$"},"startTime":{"type":"string","pattern":"^\\d{2}:\\d{2}:\\d{2}$"},"stopId":{"type":"string"},"confidence":{"type":"number","minimum":0,"maximum":1},"method":{"type":"string","enum":["direct_hint","route_geometry","schedule_window","unassigned"]},"assignedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"}},"required":["vehicleId","routeId","tripId","confidence","method","assignedAt"],"additionalProperties":false},{"type":"null"}]},"freshness":{"enum":["live","recent","stale","scheduled"]},"ageSeconds":{"type":"number"},"vehiclePosition":{"anyOf":[{"type":"object"},{"type":"null"}]},"tripUpdate":{"anyOf":[{"type":"object"},{"type":"null"}]}},"required":["generatedAt","observation","assignment","freshness","ageSeconds","vehiclePosition","tripUpdate"]}}}}