openapi: 3.2.0
info:
  title: Road Network API
  version: v1
  description: Public JSON API for road network health, metadata, area search, and scoped network retrieval.
servers:
  - url: http://127.0.0.1:3000
    description: Local development
tags:
  - name: Service
    description: Service health and dataset metadata
  - name: Areas
    description: Administrative-area lookup
  - name: Network
    description: BBox or area network extraction for graph and segments responses
paths:
  /health:
    get:
      tags: [Service]
      operationId: getHealth
      summary: Get service health and active dataset identity
      responses:
        '200':
          description: Service is healthy
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RoadNetworkHealthV1'
              examples:
                default:
                  value:
                    schema: road_network.health.v1
                    status: ok
                    dataset:
                      graph_hash: fde266b0f238e522191be58255c7d87119058f9c5ba699c23ddaf06d8506c648
                      projection_version: '0.1.0'
  /metadata:
    get:
      tags: [Service]
      operationId: getMetadata
      summary: Get public dataset metadata
      responses:
        '200':
          description: Dataset metadata
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RoadNetworkMetadataV1'
              examples:
                default:
                  value:
                    schema: road_network.metadata.v1
                    dataset:
                      graph_hash: fde266b0f238e522191be58255c7d87119058f9c5ba699c23ddaf06d8506c648
                      projection_version: '0.1.0'
                      source_pbf_sha256: d5e001f32c4cff2ca5b4a282362c277e4249319a53303d4c06ec746b7fad9723
                    bounds_wgs84:
                      min_lon: 11.8585256
                      min_lat: 50.1682462
                      max_lon: 15.0973503
                      max_lat: 51.7183344
                    counts:
                      nodes: 4720847
                      directed_edges: 9940782
                      transition_constraints: 11694
                      path_constraints: 120
                    profiles_supported: [car]
                    capabilities:
                      conditional_evaluation: false
  /areas/search:
    get:
      tags: [Areas]
      operationId: searchAreas
      summary: Search administrative areas by name
      description: Case-insensitive contains search over loaded OSM administrative boundaries in MVP scope (`admin_level=8`, plus `admin_level=6` names that are not county-style).
      parameters:
        - name: q
          in: query
          required: true
          description: Search string for area names (MVP scope returns `admin_level=8` areas and `admin_level=6` city-style names; county-style names like `Landkreis ...` and `...kreis` are excluded).
          schema:
            type: string
            minLength: 1
      responses:
        '200':
          description: Matching administrative areas
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RoadNetworkAreasSearchV1'
              examples:
                default:
                  value:
                    schema: road_network.areas.search.v1
                    query: dres
                    areas:
                      - area_id: a5001
                        name: Dresden
                        admin_level: '8'
                        boundary: administrative
                        bbox_wgs84:
                          min_lon: 12.95
                          min_lat: 51.95
                          max_lon: 13.15
                          max_lat: 52.1
        '400':
          description: Request validation error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RoadNetworkErrorV1'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RoadNetworkErrorV1'
  /areas/boundaries:
    get:
      tags: [Areas]
      operationId: getAreaBoundaries
      summary: Get administrative area boundary features
      description: Returns administrative area boundary features for `/areas/map`, including labels formatted as `<name> (<admin_level>)`.
      responses:
        '200':
          description: Administrative area boundaries
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RoadNetworkAreasBoundariesV1'
              examples:
                default:
                  value:
                    schema: road_network.areas.boundaries.v1
                    type: FeatureCollection
                    features:
                      - type: Feature
                        id: a5001
                        geometry:
                          type: MultiPolygon
                          coordinates:
                            - - - [12.95, 51.95]
                                - [13.15, 51.95]
                                - [13.15, 52.1]
                                - [12.95, 52.1]
                                - [12.95, 51.95]
                        properties:
                          area_id: a5001
                          name: Dresden
                          admin_level: '8'
                          boundary: administrative
                          label: Dresden (8)
                          bbox_wgs84:
                            min_lon: 12.95
                            min_lat: 51.95
                            max_lon: 13.15
                            max_lat: 52.1
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RoadNetworkErrorV1'
  /network:
    get:
      tags: [Network]
      operationId: getNetworkByBbox
      summary: Get area- or bbox-scoped network as graph or segments response
      description: Returns `RoadNetworkGraphV1` when `view=graph` and `RoadNetworkSegmentsV1` when `view=segments`; `204` means the query is valid but no matching content exists. Provide exactly one selector, `bbox` or `area_id`. Area requests use materialized area-membership artifacts for edge selection, and `view=segments` geometry is clipped to the selected area boundary. Pagination uses `limit`/`offset` over selected edges in deterministic order. Car-edge semantics such as `speed_kph`, `travel_time_seconds`, and `lane_count` are exposed on `view=graph`; `view=segments` keeps merged-geometry directionality only because a single merged segment can contain multiple directed edges with different car semantics.
      parameters:
        - name: bbox
          in: query
          required: false
          description: Comma-separated WGS84 bbox in the format `minLon,minLat,maxLon,maxLat`. Mutually exclusive with `area_id`.
          schema:
            type: string
            pattern: '^\s*-?\d+(?:\.\d+)?,-?\d+(?:\.\d+)?,-?\d+(?:\.\d+)?,-?\d+(?:\.\d+)?\s*$'
            example: 13.0,52.0,13.2,52.2
        - name: area_id
          in: query
          required: false
          description: >-
            Public administrative area identifier from `/areas/search`
            (MVP scope: `admin_level=8` plus `admin_level=6` city-style names,
            excluding county-style names). Mutually exclusive with `bbox`.
            Selection uses precomputed area memberships.
          schema:
            type: string
            example: a5001
        - name: profile
          in: query
          required: true
          description: Routing profile for network extraction.
          schema:
            type: string
            enum: [car]
        - name: view
          in: query
          required: true
          description: Response selector; `graph` returns routable graph objects and `segments` returns GeoJSON segments for map rendering.
          schema:
            type: string
            enum: [graph, segments]
        - name: limit
          in: query
          required: false
          description: Optional maximum number of selected edges to include from the deterministic edge selection order.
          schema:
            type: integer
            minimum: 1
        - name: offset
          in: query
          required: false
          description: Optional selected-edge offset for deterministic pagination.
          schema:
            type: integer
            minimum: 0
      responses:
        '200':
          description: Requested network view
          headers:
            X-Chunked-Response:
              description: "`true` when memory guard chunking was applied for this response."
              schema:
                type: string
            X-Response-Limit:
              description: Effective selected-edge limit applied by pagination/chunking.
              schema:
                type: string
            X-Response-Offset:
              description: Effective selected-edge offset used for this response page.
              schema:
                type: string
            X-Next-Offset:
              description: Next selected-edge offset for the following page.
              schema:
                type: string
            X-Has-More:
              description: "`true` if another page is available for the same deterministic selection."
              schema:
                type: string
            X-Total-Selected-Edges:
              description: Total selected edges before pagination for this request selector.
              schema:
                type: string
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: '#/components/schemas/RoadNetworkGraphV1'
                  - $ref: '#/components/schemas/RoadNetworkSegmentsV1'
              examples:
                graph:
                  value:
                    schema: road_network.network.graph.v1
                    profile: car
                    bbox_wgs84:
                      min_lon: 13.0
                      min_lat: 52.0
                      max_lon: 13.2
                      max_lat: 52.2
                    dataset:
                      graph_hash: fde266b0f238e522191be58255c7d87119058f9c5ba699c23ddaf06d8506c648
                      projection_version: '0.1.0'
                      source_pbf_sha256: d5e001f32c4cff2ca5b4a282362c277e4249319a53303d4c06ec746b7fad9723
                    nodes:
                      - node_id: n1
                        lon: 13.0
                        lat: 52.0
                        node_kind: junction
                        barrier_type: null
                    edges:
                      - edge_id: e1_s0_F
                        osm_way_id: '1'
                        from_node_id: n1
                        to_node_id: n2
                        road_class: primary
                        street_name: Main Street
                        street_ref: B170
                        direction: forward
                        oneway: forward_only
                        access_state: allowed
                        speed_kph: 80
                        travel_time_seconds: 5
                        lane_count: 2
                        length_m: 100.0
                        cost_distance_m: 100.0
                    transition_constraints:
                      - constraint_id: tc_1
                        osm_relation_id: '42'
                        kind: deny
                        from_edge_id: e1_s0_F
                        via_node_id: n2
                        to_edge_id: e2_s0_F
                        restriction: no_left_turn
                    path_constraints:
                      - constraint_id: pc_1
                        osm_relation_id: '43'
                        from_edge_id: e1_s0_F
                        via_edge_ids: [e2_s0_F]
                        to_edge_id: e3_s0_F
                        restriction: no_right_turn
                segments:
                  value:
                    schema: road_network.network.segments.v1
                    profile: car
                    bbox_wgs84:
                      min_lon: 13.0
                      min_lat: 52.0
                      max_lon: 13.2
                      max_lat: 52.2
                    dataset:
                      graph_hash: fde266b0f238e522191be58255c7d87119058f9c5ba699c23ddaf06d8506c648
                      projection_version: '0.1.0'
                      source_pbf_sha256: d5e001f32c4cff2ca5b4a282362c277e4249319a53303d4c06ec746b7fad9723
                    type: FeatureCollection
                    features:
                      - type: Feature
                        id: seg_abc
                        geometry:
                          type: LineString
                          coordinates:
                            - [13.0, 52.0]
                            - [13.1, 52.0]
                        properties:
                          segment_id: seg_abc
                          street_name: Main Street
                          street_ref: B170
                          road_class: primary
                          directionality: forward
                          length_m: 100.0
                          edge_ids: [e1_s0_F]
                          osm_way_ids: ['1']
        '204':
          description: Valid query but no content for requested bbox/profile/view
        '400':
          description: Request validation error (missing selector, invalid bbox, unsupported profile/view, or unknown area_id)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RoadNetworkErrorV1'
              examples:
                invalid_bbox:
                  value:
                    schema: road_network.error.v1
                    error:
                      code: invalid_bbox
                      message: bbox.min_lon must be smaller than bbox.max_lon
        '413':
          description: Dataset too large for the current request shape; use `limit` and `offset` pagination.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RoadNetworkErrorV1'
              examples:
                request_too_large:
                  value:
                    schema: road_network.error.v1
                    error:
                      code: request_too_large
                      message: dataset too large - use limit and offset parameters for pagination
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RoadNetworkErrorV1'
components:
  schemas:
    BBoxWgs84:
      description: Bounding box in WGS84 decimal degrees.
      type: object
      additionalProperties: false
      required: [min_lon, min_lat, max_lon, max_lat]
      properties:
        min_lon:
          type: number
          description: Minimum longitude of the bounding box.
        min_lat:
          type: number
          description: Minimum latitude of the bounding box.
        max_lon:
          type: number
          description: Maximum longitude of the bounding box.
        max_lat:
          type: number
          description: Maximum latitude of the bounding box.
    DatasetIdentity:
      description: Identity of the currently loaded dataset and source extract.
      type: object
      additionalProperties: false
      required: [graph_hash, projection_version, source_pbf_sha256]
      properties:
        graph_hash:
          type: string
          description: Stable hash of the loaded graph artifact bytes.
        projection_version:
          type: string
          description: Version of the projection pipeline used to build the dataset.
        source_pbf_sha256:
          type: string
          description: SHA-256 hash of the source OSM PBF used to build this dataset.
    Counts:
      description: Entity counts for the loaded dataset.
      type: object
      additionalProperties: false
      required: [nodes, directed_edges, transition_constraints, path_constraints]
      properties:
        nodes:
          type: integer
          minimum: 0
          description: Count of nodes in the dataset.
        directed_edges:
          type: integer
          minimum: 0
          description: Count of directed edges in the dataset.
        transition_constraints:
          type: integer
          minimum: 0
          description: Count of via-node transition constraints.
        path_constraints:
          type: integer
          minimum: 0
          description: Count of via-way path constraints.
    AreaSearchItem:
      description: Administrative area search result item.
      type: object
      additionalProperties: false
      required: [area_id, name, admin_level, boundary, bbox_wgs84]
      properties:
        area_id:
          type: string
          description: Public administrative area identifier.
        name:
          type: string
          description: Display name from OSM relation `name`.
        admin_level:
          oneOf: [{ type: string }, { type: 'null' }]
          description: OSM admin level tag value when present (`8` in current MVP scope).
        boundary:
          oneOf: [{ type: string }, { type: 'null' }]
          description: OSM boundary tag value when present.
        bbox_wgs84:
          $ref: '#/components/schemas/BBoxWgs84'
    AreaBoundaryFeature:
      description: Administrative area boundary feature.
      type: object
      additionalProperties: false
      required: [type, id, geometry, properties]
      properties:
        type:
          type: string
          const: Feature
        id:
          type: string
          description: Public administrative area identifier.
        geometry:
          $ref: '#/components/schemas/AreaBoundaryGeometry'
        properties:
          $ref: '#/components/schemas/AreaBoundaryProperties'
    AreaBoundaryGeometry:
      description: MultiPolygon geometry in WGS84 decimal-degree coordinates.
      type: object
      additionalProperties: false
      required: [type, coordinates]
      properties:
        type:
          type: string
          const: MultiPolygon
        coordinates:
          type: array
          items:
            type: array
            items:
              type: array
              items:
                type: array
                minItems: 2
                maxItems: 2
                items:
                  type: number
    AreaBoundaryProperties:
      description: Administrative area properties for boundary rendering and labels.
      type: object
      additionalProperties: false
      required: [area_id, name, admin_level, boundary, label, bbox_wgs84]
      properties:
        area_id:
          type: string
        name:
          type: string
        admin_level:
          oneOf: [{ type: string }, { type: 'null' }]
        boundary:
          oneOf: [{ type: string }, { type: 'null' }]
        label:
          type: string
          description: Display label in the exact format `<name> (<admin_level>)`.
        bbox_wgs84:
          $ref: '#/components/schemas/BBoxWgs84'
    GraphNode:
      description: Graph node returned in `view=graph`.
      type: object
      additionalProperties: false
      required: [node_id, lon, lat, node_kind, barrier_type]
      properties:
        node_id:
          type: string
          description: Public node identifier.
        lon:
          type: number
          description: Node longitude in WGS84 decimal degrees.
        lat:
          type: number
          description: Node latitude in WGS84 decimal degrees.
        node_kind:
          type: string
          enum: [barrier, junction, internal, endpoint, isolated]
          description: Structural node classification derived from graph topology.
        barrier_type:
          description: Barrier source key when the node is a barrier; otherwise null.
          oneOf:
            - type: string
            - type: 'null'
    GraphEdge:
      description: Directed graph edge returned in `view=graph`.
      type: object
      additionalProperties: false
      required:
        - edge_id
        - osm_way_id
        - from_node_id
        - to_node_id
        - road_class
        - street_name
        - street_ref
        - direction
        - oneway
        - access_state
        - speed_kph
        - travel_time_seconds
        - lane_count
        - length_m
        - cost_distance_m
      properties:
        edge_id:
          type: string
          description: Public directed edge identifier.
        osm_way_id:
          type: string
          description: Source OSM way identifier.
        from_node_id:
          type: string
          description: Start node identifier for this directed edge.
        to_node_id:
          type: string
          description: End node identifier for this directed edge.
        road_class:
          type: string
          description: Road class derived from OSM `highway` (for example `motorway`, `trunk`, `primary`, `secondary`, `tertiary`, `residential`, `service`, `unclassified`).
        street_name:
          description: Street name from OSM `name`; null when missing in source data.
          oneOf: [{ type: string }, { type: 'null' }]
        street_ref:
          description: Street reference from OSM `ref`; null when missing in source data.
          oneOf: [{ type: string }, { type: 'null' }]
        direction:
          type: string
          enum: [forward, backward]
          description: Direction of this directed edge within the source segment orientation.
        oneway:
          type: string
          enum: [forward_only, backward_only, both]
          description: Effective traversability for the underlying road segment.
        access_state:
          type: string
          enum: [allowed, denied, conditional]
          description: Car profile access state applied to this edge.
        speed_kph:
          type: integer
          minimum: 0
          description: Deterministic car speed in kilometers per hour materialized in the runtime graph for this directed edge.
        travel_time_seconds:
          type: integer
          minimum: 0
          description: Deterministic car travel time in whole seconds for this directed edge.
        lane_count:
          type: integer
          minimum: 0
          description: Deterministic lane count materialized for this directed edge.
        length_m:
          type: number
          minimum: 0
          description: Geodesic segment length in meters.
        cost_distance_m:
          type: number
          minimum: 0
          description: Distance cost in meters for this edge.
    TransitionConstraint:
      description: Via-node turn restriction returned in `view=graph`.
      type: object
      additionalProperties: false
      required:
        - constraint_id
        - osm_relation_id
        - kind
        - from_edge_id
        - via_node_id
        - to_edge_id
        - restriction
      properties:
        constraint_id:
          type: string
          description: Public transition constraint identifier.
        osm_relation_id:
          type: string
          description: Source OSM restriction relation identifier.
        kind:
          type: string
          enum: [deny, allow_only]
          description: Constraint effect on the edge transition.
        from_edge_id:
          type: string
          description: Incoming edge identifier.
        via_node_id:
          type: string
          description: Via node identifier where the transition is evaluated.
        to_edge_id:
          type: string
          description: Outgoing edge identifier.
        restriction:
          type: string
          description: Restriction tag value from the source OSM relation (for example `no_left_turn`).
    PathConstraint:
      description: Via-way restriction path returned in `view=graph`.
      type: object
      additionalProperties: false
      required:
        - constraint_id
        - osm_relation_id
        - from_edge_id
        - via_edge_ids
        - to_edge_id
        - restriction
      properties:
        constraint_id:
          type: string
          description: Public path constraint identifier.
        osm_relation_id:
          type: string
          description: Source OSM restriction relation identifier.
        from_edge_id:
          type: string
          description: Entry edge identifier.
        via_edge_ids:
          type: array
          minItems: 1
          items:
            type: string
          description: Ordered via-edge sequence that defines the constrained path.
        to_edge_id:
          type: string
          description: Exit edge identifier.
        restriction:
          type: string
          description: Restriction tag value from the source OSM relation (for example `no_right_turn`).
    SegmentFeatureProperties:
      description: Properties for a merged segment in `view=segments`. Edge-level car semantics such as `speed_kph`, `travel_time_seconds`, and `lane_count` are intentionally not exposed here because merged segments can combine multiple directed edges with different values.
      type: object
      additionalProperties: false
      required:
        - segment_id
        - street_name
        - street_ref
        - road_class
        - directionality
        - length_m
        - edge_ids
        - osm_way_ids
      properties:
        segment_id:
          type: string
          description: Public visual segment identifier; equal to `Feature.id`.
        street_name:
          description: Street name from OSM `name`; null when missing in source data.
          oneOf: [{ type: string }, { type: 'null' }]
        street_ref:
          description: Street reference from OSM `ref`; null when missing in source data.
          oneOf: [{ type: string }, { type: 'null' }]
        road_class:
          type: string
          description: Road class derived from OSM `highway` (for example `motorway`, `trunk`, `primary`, `secondary`, `tertiary`, `residential`, `service`, `unclassified`).
        directionality:
          type: string
          enum: [both, forward, backward]
          description: Effective directional availability across the merged segment.
        length_m:
          type: number
          minimum: 0
          description: Total merged geometry length in meters.
        edge_ids:
          type: array
          minItems: 1
          items:
            type: string
          description: Ordered directed edge identifiers along the merged geometry.
        osm_way_ids:
          type: array
          minItems: 1
          items:
            type: string
          description: Unique OSM way identifiers ordered by first appearance along the geometry.
    SegmentFeature:
      description: GeoJSON LineString feature for one merged visual segment.
      type: object
      additionalProperties: false
      required: [type, id, geometry, properties]
      properties:
        type:
          type: string
          const: Feature
        id:
          type: string
          description: Feature identifier equal to `properties.segment_id`.
        geometry:
          type: object
          additionalProperties: false
          required: [type, coordinates]
          properties:
            type:
              type: string
              const: LineString
            coordinates:
              type: array
              minItems: 2
              items:
                type: array
                minItems: 2
                maxItems: 2
                items: { type: number }
        properties:
          $ref: '#/components/schemas/SegmentFeatureProperties'
    SegmentFeatureCollection:
      description: GeoJSON FeatureCollection returned in `view=segments`.
      type: object
      additionalProperties: false
      required: [type, features]
      properties:
        type:
          type: string
          const: FeatureCollection
        features:
          type: array
          items:
            $ref: '#/components/schemas/SegmentFeature'
    RoadNetworkHealthV1:
      description: Health response for the currently loaded dataset.
      type: object
      additionalProperties: false
      required: [schema, status, dataset]
      properties:
        schema:
          type: string
          const: road_network.health.v1
        status:
          type: string
          const: ok
        dataset:
          type: object
          additionalProperties: false
          required: [graph_hash, projection_version]
          properties:
            graph_hash:
              type: string
              description: Stable hash of the loaded graph artifact bytes.
            projection_version:
              type: string
              description: Version of the projection pipeline used to build the dataset.
    RoadNetworkMetadataV1:
      description: Public metadata for the currently loaded dataset.
      type: object
      additionalProperties: false
      required:
        - schema
        - dataset
        - bounds_wgs84
        - counts
        - profiles_supported
        - capabilities
      properties:
        schema:
          type: string
          const: road_network.metadata.v1
        dataset:
          $ref: '#/components/schemas/DatasetIdentity'
        bounds_wgs84:
          $ref: '#/components/schemas/BBoxWgs84'
        counts:
          $ref: '#/components/schemas/Counts'
        profiles_supported:
          type: array
          items:
            type: string
            enum: [car]
          minItems: 1
          description: Public routing profiles available from this API version.
        capabilities:
          type: object
          additionalProperties: false
          required: [conditional_evaluation]
          properties:
            conditional_evaluation:
              type: boolean
              description: Whether time/condition-dependent access evaluation is applied at query time.
    RoadNetworkAreasSearchV1:
      description: Area search response over loaded administrative boundaries.
      type: object
      additionalProperties: false
      required: [schema, query, areas]
      properties:
        schema:
          type: string
          const: road_network.areas.search.v1
        query:
          type: string
          description: Normalized search query used for matching.
        areas:
          type: array
          items:
            $ref: '#/components/schemas/AreaSearchItem'
    RoadNetworkAreasBoundariesV1:
      description: Administrative area boundary response for `/areas/boundaries`.
      type: object
      additionalProperties: false
      required: [schema, type, features]
      properties:
        schema:
          type: string
          const: road_network.areas.boundaries.v1
        type:
          type: string
          const: FeatureCollection
        features:
          type: array
          items:
            $ref: '#/components/schemas/AreaBoundaryFeature'
    RoadNetworkGraphV1:
      description: Graph response for a bbox and profile.
      type: object
      additionalProperties: false
      required:
        - schema
        - profile
        - bbox_wgs84
        - dataset
        - nodes
        - edges
        - transition_constraints
        - path_constraints
      properties:
        schema:
          type: string
          const: road_network.network.graph.v1
        profile:
          type: string
          enum: [car]
        bbox_wgs84:
          $ref: '#/components/schemas/BBoxWgs84'
        dataset:
          $ref: '#/components/schemas/DatasetIdentity'
        nodes:
          type: array
          items:
            $ref: '#/components/schemas/GraphNode'
        edges:
          type: array
          items:
            $ref: '#/components/schemas/GraphEdge'
        transition_constraints:
          type: array
          items:
            $ref: '#/components/schemas/TransitionConstraint'
        path_constraints:
          type: array
          items:
            $ref: '#/components/schemas/PathConstraint'
    RoadNetworkSegmentsV1:
      description: Segments GeoJSON response for a bbox and profile.
      type: object
      additionalProperties: false
      required: [schema, profile, bbox_wgs84, dataset, type, features]
      properties:
        schema:
          type: string
          const: road_network.network.segments.v1
        profile:
          type: string
          enum: [car]
        bbox_wgs84:
          $ref: '#/components/schemas/BBoxWgs84'
        dataset:
          $ref: '#/components/schemas/DatasetIdentity'
        type:
          type: string
          const: FeatureCollection
        features:
          type: array
          items:
            $ref: '#/components/schemas/SegmentFeature'
    RoadNetworkErrorV1:
      description: Error envelope for request validation and internal failures.
      type: object
      additionalProperties: false
      required: [schema, error]
      properties:
        schema:
          type: string
          const: road_network.error.v1
        error:
          type: object
          additionalProperties: false
          required: [code, message]
          properties:
            code:
              type: string
              enum:
                - missing_parameter
                - invalid_parameter
                - invalid_bbox
                - unsupported_profile
                - unsupported_view
                - request_too_large
                - internal_error
            message:
              type: string
