openapi: 3.0.0

info:
  title: Transport Operator MaaS Provider API
  description: >
    This API defines a minimal subset of the v1.6.1 TOMP API.
    In a nutshell, we have stripped away everything optional that isn't strictly necessary for our specific use case.
    See https://github.com/TOMP-WG/TOMP-API for the original specification.

security:
  - ApiKeyAuth: []

servers:
  - url: https://api.stage.voiapp.io/edge/tomp
  - url: https://api.voiapp.io/edge/tomp

paths:
  /bookings/one-stop:
    post:
      operationId: PostOneStop
      description:
        Returns a booking for the given travel plan. This endpoint executes POST /planning/offers and POST /booking in one blow, the information provided should lead
        to only one possible offer, that is booked directly. The returned booking is still in `PENDING` state, you have to commit it. Unless 'AUTO_COMMIT' process identifier
        is applied. In that case the booking is in state 'CONFIRMED'.
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/oneStopBookingRequest"
      responses:
        "201":
          description: A single booking, or when it's not possible, return a 406.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/booking"
          headers:
            Content-Language:
              $ref: "#/components/headers/language"
            Expires:
              $ref: "#/components/headers/expires"
        "400":
          $ref: "#/components/responses/400BadRequest"
        "401":
          $ref: "#/components/responses/401Unauthorized"
        "403":
          $ref: "#/components/responses/403Forbidden"
        "406":
          description: this booking cannot be done.

  /bookings/{id}:
    parameters:
      - name: id
        in: path
        description: Booking identifier
        required: true
        schema:
          type: string
    get:
      operationId: GetBooking
      description: Returns the booking. See (3.5.2) in the process flow - booking. In the 'meta'-field the digital tickes can be returned (see (3.3) in the process flow - booking)
      responses:
        "200":
          description: The booking was found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/booking"
          headers:
            Content-Language:
              $ref: "#/components/headers/language"
        "401":
          $ref: "#/components/responses/401Unauthorized"
        "404":
          $ref: "#/components/responses/404NotFound"

  /legs/{id}:
    parameters:
      - name: id
        in: path
        description: Leg identifier
        required: true
        schema:
          type: string
    get:
      operationId: GetLeg
      description: Retrieves the latest summary of the leg, being the execution of a portion of a journey travelled using one asset (vehicle). Every leg belongs to one booking, every booking has at least one leg. Where the booking describes the agreement between user/MP and TO, the leg describes the journey as it occured. See (4.3) in the flow chart - trip execution
      responses:
        "200":
          description: operation successful
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/leg"

  /legs/{id}/events:
    parameters:
      - name: id
        in: path
        description: Leg identifier
        required: true
        schema:
          type: string
    post:
      operationId: PostLegsEvents
      description: This endpoint must be used to alter the state of a leg.<br>
        `FINISH` will end this leg (see (4.6) in process flow) [TO and MP]
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/legEvent"
      responses:
        "200":
          description: operation successful
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/leg"
        "204":
          $ref: "#/components/responses/204NoContent"
        "400":
          $ref: "#/components/responses/400BadRequest"
        "401":
          $ref: "#/components/responses/401Unauthorized"
        "403":
          $ref: "#/components/responses/403Forbidden"
        "404":
          $ref: "#/components/responses/404NotFound"
        "503":
          description: In case of temporary malfunctioning, this response can be send (e.g. bluetooth lock jammed). See also https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After
          headers:
            Retry-After:
              description: seconds after response
              example: 120
              schema:
                type: integer

  /operator/meta:
    get:
      operationId: GetMeta
      summary: describes the running implementations
      description:
        all versions that are implemented on this url, are described in the result of this endpoint. In contains all versions and per version the endpoints, their status
        and the supported scenarios.
      responses:
        "200":
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/endpointImplementation"
          headers:
            Content-Language:
              $ref: "#/components/headers/language"

  /operator/pricing-plans:
    get:
      operationId: GetPricingPlans
      summary: gives pricing information
      description: Describes pricing of systems or assets [from GBFS]
      responses:
        "200":
          description: returns standard pricing plans for an operator
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/systemPricingPlan"
          headers:
            Content-Language:
              $ref: "#/components/headers/language"
        "400":
          $ref: "#/components/responses/400BadRequest"
        "401":
          $ref: "#/components/responses/401Unauthorized"
        "403":
          $ref: "#/components/responses/403Forbidden"

  /operator/regions:
    get:
      operationId: GetRegions
      summary: describes regions for a system that is broken up by geographic or political region. It is defined as a separate feed to allow for additional region metadata (such as shape definitions). [from GBFS]
      responses:
        "200":
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/systemRegion"
        "400":
          $ref: "#/components/responses/400BadRequest"
        "401":
          $ref: "#/components/responses/401Unauthorized"

  /support:
    post:
      operationId: CreateSupportTicket
      description: creates a request for support from end user via MP
      tags:
        - support
        - TO
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/supportRequest"
      responses:
        "200":
          description: support request acknowledged
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/supportStatus"
        "400":
          $ref: "#/components/responses/400BadRequest"
        "401":
          $ref: "#/components/responses/401Unauthorized"
        "403":
          $ref: "#/components/responses/403Forbidden"
        "404":
          $ref: "#/components/responses/404NotFound"

components:
  schemas:
    supportRequest:
      description: request for support
      type: object
      required:
        - id
        - supportType
        - time
        - comment
        - contactInformationEndUser
      properties:
        id:
          type: string
          description: the booking id
        supportType:
          type: string
          enum:
            [
              BROKEN_DOWN,
              NOT_AT_LOCATION,
              MISSING_AFTER_PAUSE,
              NOT_CLEAN,
              NOT_AVAILABLE,
              UNABLE_TO_OPEN,
              UNABLE_TO_CLOSE,
              API_TECHNICAL,
              API_FUNCTIONAL,
              ACCIDENT,
              OTHER,
            ]
        time:
          type: string
          format: date-time
        contactInformationEndUser:
          description: contact information of the end user in case of direct response requests, like phone number
          type: string
        comment:
          type: string

    supportStatus:
      description: the current status of support
      type: object
      allOf:
        - $ref: "#/components/schemas/supportRequest"
        - type: object
          properties:
            status:
              type: string
              enum: [PROCESSING, UPDATE_REQUESTED, RESOLVED, CANCELLED]
              example: PROCESSING

    asset:
      type: object
      required:
        - id
      properties:
        id:
          type: string
          description: Identifier of an asset. Whenever used in Operator Information changed after every trip (GDPR).
        stateOfCharge:
          type: integer
          minimum: 0
          maximum: 100
          description: percentage of charge available
        maxRange:
          type: integer
          minimum: 0
          description: maximum range of the asset, in meters

    assetClass:
      type: string
      x-go-type-skip-optional-pointer: true
      description: These classes are taken from the NeTeX standard, but ALL and UNKNOWN are removed. On the other hand OTHER and PARKING are added.
      enum: [
          BICYCLE,
          OTHER, # then add the scooter to the subClass
        ]

    assetType:
      type: object
      required:
        - id
      properties:
        id:
          type: string
          description: Unique identifier of an asset type,
        assets:
          type: array
          x-go-type-skip-optional-pointer: true
          description: use this field only in the map-oriented scenario or in the committed bookings. Don't use it in public data (to prevent GDPR issues).
          items:
            $ref: "#/components/schemas/asset"
        assetClass:
          $ref: "#/components/schemas/assetClass"
          x-go-type-skip-optional-pointer: true
        assetSubClass:
          # always scooter
          type: string
          description: a more precise classification of the asset, like 'cargo bike', 'public bus', 'coach bus', 'office bus', 'water taxi',  'segway'. This is mandatory when using 'OTHER' as class.
          x-go-type-skip-optional-pointer: true

    booking:
      description: The booking information describing the state and details of an agreed upon trip
      type: object
      allOf:
        - $ref: "#/components/schemas/bookingRequest"
        - type: object
          required:
            - id
          properties:
            state:
              $ref: "#/components/schemas/bookingState"
            legs:
              description:
                The legs of this booking, generally just one for simple legs, in order of how they will be travelled.
                If this part is not present, it means that there is only one leg. This leg can be constructed
                * leg[0].id = booking.id
                * leg[0].departureTime = booking.departureTime
                * leg[0].arrivalTime = booking.arrivalTime
                * leg[0].assetType = booking.mainAssetType
                * leg[0].pricing = booking.pricing
                This approach is not allowed in the trip execution part
              type: array
              items:
                $ref: "#/components/schemas/leg"
            pricing:
              description: The pricing information of the overall booking, in addition to any leg pricing, if not all legs have pricing the booking should have the fare
              $ref: "#/components/schemas/fare"
            departureTime:
              description: The initial departure time (over all legs)
              type: string
              format: date-time
            arrivalTime:
              description: The intended arrival time at the destination of the booking (over all legs)
              type: string
              format: date-time

    bookingRequest:
      description: A booking requested by the MP
      type: object
      properties:
        id:
          description: A unique identifier for the TO to know this booking by
          type: string
        from:
          description: information about the origin, only to supply when requested in the conditionRequireBookingData
          $ref: "#/components/schemas/place"
        customer:
          description: The user that wants to make this booking, only to supply when requested in the conditionRequireBookingData
          $ref: "#/components/schemas/customer"
        extraInfo:
          description: dictionary for extra fields (bilatural agreements)
          type: object
          additionalProperties: true

    bookingState:
      description: The life-cycle state of the booking (from NEW to FINISHED)
      type: string
      enum:
        [
          NEW,
          PENDING,
          REJECTED,
          RELEASED,
          EXPIRED,
          CONDITIONAL_CONFIRMED,
          CONFIRMED,
          CANCELLED,
          STARTED,
          FINISHED,
        ]
      example: CONFIRMED

    cardType:
      description: A generic description of a card, asset class and acceptors is only allowed for DISCOUNT/TRAVEL/OTHER cards
      type: object
      required:
        - type
      properties:
        type:
          description: The broad category of card
          type: string
          enum: [ID, DISCOUNT, TRAVEL, BANK, CREDIT, PASSPORT, OTHER]
        subType:
          description: For use in case of OTHER. Can be used in bilateral agreements.
          type: string
        assetClass:
          $ref: "#/components/schemas/assetClass"
        acceptors:
          description: references to accepting parties, only if applicable
          type: array
          items:
            type: string
            format: maas-id

    condition:
      required:
        - conditionType
      properties:
        conditionType:
          description: The specific subclass of condition, should match the schema name exactly
          type: string
        id:
          description: An identifier for this condition that can be used to refer to this condition
          type: string
          example: deposit50eu

    coordinates:
      type: object
      description: a lon, lat (WGS84, EPSG:4326)
      required:
        - lat
        - lng
      properties:
        lng:
          type: number
          example: 6.169639
          format: double
          minimum: 0
        lat:
          type: number
          example: 52.253279
          format: double
          minimum: 0

    country:
      type: string
      description: two-letter country codes according to ISO 3166-1
      maxLength: 2
      minLength: 2
      example: NL

    customer:
      description: A MaaS user that wishes to make a booking, only use the fields required by booking conditions
      allOf:
        - $ref: "#/components/schemas/traveler"
        - type: object
          properties:
            externalId:
              description:
                The identifier that the MP uses to identify this customer. It is not mandatory to store it at the TOs side,
                since the communication between TO and MP always uses the identifier on TO side.
              type: string
              example: "A0-123456"
            extraInfo:
              description: dictionary for extra fields (bilatural agreements)
              type: object
              additionalProperties: true

    createCustomerAccountParameters:
      description: A CUSTOMER ACCOUNT request, resulting in a new or linked TO CUSTOMER ACCOUNT
      $ref: "#/components/schemas/customer"

    customerAccount:
      description: A registration of the TRANSPORT CUSTOMER with an ACCOUNT PROVIDER to obtain travel services.
      allOf:
        - $ref: "#/components/schemas/customer"
        - type: object
          required:
            - id
          properties:
            creationDate:
              type: string
              format: date-time
              example: "2019-10-12T07:20:50.52Z"
              pattern: "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z$"
              description: The date in which the CUSTOMER ACCOUNT has been created
            modificationDate:
              type: string
              format: date-time
              pattern: "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z$"
              description: Last modification date of CUSTOMER ACCOUNT.
            status:
              $ref: "#/components/schemas/customerAccountStatus"
              description: The status of the CUSTOMER ACCOUNT

    customerAccountStatus:
      type: string
      description: status of a CUSTOMER ACCOUNT<br>
        _CREATED_ the customer account has been created but is not ready to create a purchase yet<br>
        _TO_PENDING_VALIDATION_ the customer account is pending a verification of identity and properties by the TO. No purchases can be made in this step<br>
        _OTP_REQUIRED_ the TO has sent an OTP to the customer's phone or email address and is expecting it to activate the account. No purchases can be made in this step<br>
        _ACTIVE_ the customer account is active and can continue to purchase offers<br>
        _BLOCKED_ the customer account has been blocked by the TO and can no longer use this TO<br>
      enum: [CREATED, TO_PENDING_VALIDATION, ACTIVE, BLOCKED]

    damage:
      description: A damage of the vehicle.
      type: object
      required:
        - vehicleComponent
        - description
      properties:
        vehicleComponent:
          description: Part/Component of the vehicle affected. If OTHER is specified the description needs to provide more detail as to what part/component is affected.
          type: string
          enum:
            [
              FRONT,
              REAR,
              LEFT,
              RIGHT,
              TOP,
              BOTTOM,
              INTERIOR,
              TIRE,
              ANCILLARY,
              OTHER,
            ]
        vehicleComponentName:
          description: a short term to describe the damaged part
          type: string
          x-examples: wheel, ring, light, brake, gear, saddle, pedal, window, rack, ...
        description:
          description: Description of the damage.
          type: string
        pictures:
          type: array
          description: URL where pictures of the damage can be accessed. Any special characters in the URL must be correctly escaped.
          items:
            type: string
            format: url

    distance:
      description: The estimated distance travelled in the leg (in meters)
      type: integer
      minimum: 0
      example: 7250

    duration:
      description: A duration of some time (relative to a time) in milliseconds
      type: integer
      maximum: 2147483647
      minimum: 0
      example: 11112

    endpoint:
      type: object
      description: a formal description of an endpoint.
      required:
        - method
        - path
        - status
      properties:
        method:
          type: string
          enum: [POST, PUT, GET, DELETE, PATCH]
        path:
          description: the exact path of the endpoint, starting after the base URL
          type: string
          example: /plannings/
        eventType:
          description: in case the path is ending in /events, the event type/operator enum should be added here.
          type: string
          enum:
            [
              PREPARE,
              ASSIGN_ASSET,
              SET_IN_USE,
              PAUSE,
              OPEN_TRUNK,
              START_FINISHING,
              FINISH,
              ISSUE,
              CANCEL,
              EXPIRE,
              DENY,
              COMMIT,
            ]
        status:
          type: string
          enum: [NOT_IMPLEMENTED, DIALECT, IMPLEMENTED]

    endpointImplementation:
      type: object
      description: a complete endpoint description, containing all endpoints, their status, but also the served scenarios and implemented process flows. The identifiers for the process flows can be found at https://github.com/TOMP-WG/TOMP-API/wiki/ProcessIdentifiers<br>
      required:
        - version
        - baseUrl
        - endpoints
        - scenarios
        - processIdentifiers
      properties:
        version:
          type: string
        baseUrl:
          type: string
        endpoints:
          type: array
          items:
            $ref: "#/components/schemas/endpoint"
        scenarios:
          type: array
          items:
            $ref: "#/components/schemas/scenario"
        processIdentifiers:
          $ref: "#/components/schemas/processIdentifiers"

    scenario:
      type: string
      enum:
        [
          POSTPONED_COMMIT,
          DEPOSIT,
          PAY_WHEN_FINISHED,
          REQUIRE_BOOKING_DATA,
          RETURN_AREA,
          UPFRONT_PAYMENT,
        ]

    processIdentifiers:
      type: object
      description:
        Process Identifiers deliberately not included in the specification, since new ones pop up regularly. <br>
        Known identifiers can be found at https://github.com/TOMP-WG/TOMP-API/wiki/ProcessIdentifiers.<br>
      required:
        - operatorInformation
        - planning
        - booking
        - tripExecution
        - support
        - payment
        - general
      properties:
        operatorInformation:
          type: array
          items:
            type: string
        planning:
          type: array
          items:
            type: string
        booking:
          type: array
          items:
            type: string
        tripExecution:
          type: array
          items:
            type: string
        support:
          type: array
          items:
            type: string
        payment:
          type: array
          items:
            type: string
        general:
          type: array
          items:
            type: string
    error:
      type: object
      description:
        An error that the service may send, e.g. in case of invalid input,
        missing authorization or internal service error. See https://github.com/TOMP-WG/TOMP-API/wiki/Error-handling-in-TOMP for further explanation of error code.
      properties:
        status:
          type: integer
          description: The HTTP status code ([RFC7231], Section 6) generated by the origin server for this occurrence of the problem.
          x-go-type-skip-optional-pointer: true
        detail:
          type: string
          description: A human-readable explanation specific to this occurrence of the problem, could match Content-Language
          x-go-type-skip-optional-pointer: true

    geojsonLine:
      type: object
      description: An array of WGS84 coordinate pairs
      allOf:
        - $ref: "#/components/schemas/geojsonGeometry"
        - type: object
          properties:
            coordinates:
              description: Geojson Coordinate
              type: array
              example: [[6.169639, 52.253279], [6.05623, 52.63473]]
              items:
                $ref: "#/components/schemas/basePoint"

    basePoint:
      type: array
      minItems: 2
      maxItems: 2
      items:
        type: number
        format: double
        minimum: 0.0
      example: [4.53432, 55.324523]

    geojsonPoint:
      type: object
      description: Geojson Coordinate
      allOf:
        - $ref: "#/components/schemas/geojsonGeometry"
        - type: object
          properties:
            coordinates:
              $ref: "#/components/schemas/basePoint"

    geojsonPolygon:
      type: object
      description: geojson representation of a polygon. First and last point must be equal. See also https://geojson.org/geojson-spec.html#polygon and example https://geojson.org/geojson-spec.html#id4. The order should be lon, lat [[[lon1, lat1], [lon2,lat2], [lon3,lat3], [lon1,lat1]]], the first point should match the last point.
      allOf:
        - $ref: "#/components/schemas/geojsonGeometry"
        - type: object
          properties:
            coordinates:
              type: array
              example:
                [[[1.0, 1.0], [0.0, 1.0], [0.0, 0.0], [1.0, 0.0], [1.0, 1.0]]]
              items:
                type: array
                items:
                  $ref: "#/components/schemas/basePoint"

    geojsonMultiPolygon:
      type: object
      description: geojson representation of a multi polygon. See also https://geojson.org/geojson-spec.html#multipolygon
      allOf:
        - $ref: "#/components/schemas/geojsonGeometry"
        - type: object
          properties:
            coordinates:
              type: array
              example:
                [[[[1.0, 1.0], [0.0, 1.0], [0.0, 0.0], [1.0, 0.0], [1.0, 1.0]]]]
              items:
                type: array
                items:
                  type: array
                  items:
                    $ref: "#/components/schemas/basePoint"

    geojsonGeometry:
      type: object
      description: geoJSON geometry
      required:
        - type
      properties:
        type:
          type: string
          enum:
            - Point
            - LineString
            - Polygon
            - MultiPolygon
      discriminator:
        propertyName: type
        mapping:
          Point: "#/components/schemas/geojsonPoint"
          LineString: "#/components/schemas/geojsonLine"
          Polygon: "#/components/schemas/geojsonPolygon"
          MultiPolygon: "#/components/schemas/geojsonMultiPolygon"

    leg:
      description: A planned (segment of) a booked trip using one asset type
      type: object
      properties:
        id:
          description: The unique identifier (TO) of this leg
          type: string
        from:
          description: The departure location of this leg, using this asset type
          $ref: "#/components/schemas/place"
        departureTime:
          description: The departure time of this leg. Or, in case of a parking, the start of the usage.
          type: string
          format: date-time
        arrivalTime:
          description: The intended arrival time at the to place. Or, in case of a parking, the end of the usage.
          type: string
          format: date-time
        assetType:
          description: The asset type used in this leg as determined during booking
          $ref: "#/components/schemas/assetType"
        asset:
          description: The concrete asset used for the execution of the leg
          $ref: "#/components/schemas/asset"
        state:
          $ref: "#/components/schemas/legState"
        pricing:
          description: The leg-specific pricing information, all fares are additive, if the booking does not have pricing set all legs should
          $ref: "#/components/schemas/fare"

    legEvent:
      type: object
      description: event for the execution
      required:
        - event
      properties:
        event:
          type: string
          enum: [FINISH, START_FINISHING]
        userLocation:
          description: This field might lead to GDPR issues. Be aware, use it with caution.
          $ref: "#/components/schemas/place"
        asset:
          $ref: "#/components/schemas/asset"
        url:
          type: array
          x-go-type-skip-optional-pointer: true
          description: urls to support the event e.g. pictures justifying the exit conditions
          items:
            type: string
            format: url

    legState:
      type: string
      description: status of a leg
      enum:
        [
          NOT_STARTED,
          PREPARING,
          IN_USE,
          PAUSED,
          FINISHING,
          FINISHED,
          ISSUE_REPORTED,
          CANCELLED,
        ]

    oneStopBookingRequest:
      type: object
      anyOf:
        - required: ["useAssets"]
      allOf:
        - $ref: "#/components/schemas/planningRequest"
        - type: object
          properties:
            customer:
              description: The user that wants to make this booking, only to supply when requested in the conditionRequireBookingData
              $ref: "#/components/schemas/customer"

    place:
      type: object
      description: a origin or destination of a leg, 3D. lon/lat in WGS84.
      required:
        - coordinates
      properties:
        coordinates:
          $ref: "#/components/schemas/coordinates"

    planningRequest:
      description: A travel planning for which bookable options are requested
      type: object
      required:
        - from
      properties:
        from:
          $ref: "#/components/schemas/place"
        useAssets:
          description: The specific asset(s) the user wishes to receive leg options for
          x-go-type-skip-optional-pointer: true
          type: array
          items:
            type: string
            format: an asset id for this operator, this might be an asset id from gbfs, but can also be another identification for this asset (e.g. bluetooth id)
        extraInfo:
          description: dictionary for extra fields (bilatural agreements)
          type: object
          additionalProperties: true

    planning:
      description: A travel planning with bookable options that fulfil the constraints of the planning
      type: object
      required:
        - validUntil
        - options
      properties:
        validUntil:
          description: The time until which the presented options are (likely) available
          type: string
          format: date-time
        options:
          type: array
          items:
            $ref: "#/components/schemas/booking"

    requirement:
      type: object
      description: describes an (dis)ability or ancillary.
      required:
        - category
        - number
      properties:
        source:
          type: string
          description: if obsolete, it is referencing the travelers' dictionary (https://github.com/TOMP-WG/TOMP-API/blob/master/documents/CROW%20passenger%20characteristics.xlsx)
        category:
          type: string
          description: references to the first column of the specification
            initial values [ HR, AV, HV, AB, AER, K, ZR, RR ]
        number:
          type: string
          description: references to the second column of the specification
          minLength: 2
          maxLength: 2
        type:
          description: conditionally extra information, referencing to the 3th column
          type: string
        memo:
          description: extra field for detailed information, not standardized
          type: string
        variable-number:
          description: in some requirements there is references to '[variable number]' e.g. of meters (like ZR06)
          type: integer
          minimum: 0
        applicable-days:
          description: days of week that are applicable
          type: array
          items:
            type: string
            enum: [MO, TU, WE, TH, FR, SA, SU]

    systemPricingPlan:
      type: object
      required:
        - planId
        - name
        - isTaxable
        - description
        - fare
        - regionId
      properties:
        regionId:
          type: string
          description: The region that this pricing plan applies to.
        planId:
          type: string
          description: a unique identifier for this plan in the system
          example: freeplan1
        name:
          type: string
          description: name of this pricing scheme, could match Content-Language
          example: Free Plan
        fare:
          $ref: "#/components/schemas/fare"
        isTaxable:
          type: boolean
          description: false indicates that no additional tax will be added (either because tax is not charged, or because it is included) true indicates that tax will be added to the base price

    fare:
      description: the total fare is the sum of all parts, except for the 'MAX' farePart. This one describes the maximum price for the complete leg.
      required:
        - estimated
        - parts
      properties:
        estimated:
          description: is this fare an estimation?
          type: boolean
        parts:
          type: array
          items:
            $ref: "#/components/schemas/farePart"

    farePart:
      description:
        this describes a part of the fare (or discount). It contains a for instance the startup costs (fixed)
        or the flex part (e.g. 1.25 EUR per 2.0 MILES). The amount is tax included. In case of discounts, the values are
        negative. With 'MAX' you can specify e.g. a maximum of 15 euro per day. Percentage is mainly added for discounts.
        The `scale` properties create the ability to communicate scales (e.g. the first 4 kilometers you've to pay
        EUR 0.35 per kilometer, the kilometers 4 until 8 EUR 0.50 and above it EUR 0.80 per kilometer).
      allOf:
        - $ref: "#/components/schemas/amountOfMoney"
        - type: object
          required:
            - amount
          properties:
            type:
              description:
                type of fare part. If there is only one farepart and this field is missing, it should
                be assumed it is 'FIXED'. In all other situations this field is mandatory.
              type: string
              enum: [FIXED, FLEX, MAX]
            kind:
              description:
                is this the default price or is this an additional part (discount, price surge). In case of a DISCOUNT, the amount
                must always be negative and in case of SURGE it must be positive. This also means, that when you're working with discounts or surges,
                you have to deliver 2 fareparts, one for the default price and one for the discount/surge. This can be used in combination with as
                well the fixed price parts as with the flex price parts.
              type: string
              enum: [DEFAULT, DISCOUNT, SURGE]
            unitType:
              type: string
              description: in case of 'FLEX' mandatory, otherwise not allowed. E.g. 0.5 EUR per HOUR
              enum: [KM, SECOND, MINUTE, HOUR, MILE, PERCENTAGE]
            units:
              type: number
              description:
                the number of km, seconds etc. Mandatory when the type is 'FLEX', otherwise
                not allowed. In case of 0.5 EUR per 15 MINUTES, `units` should contain 15 and `unitType` MINUTES.
              format: double
              minimum: 0
            name:
              description: an optional description of this fare part.
              type: string
            class:
              description: class of this fare part. Could be FARE or ANCILLARY
              default: "FARE"
              type: string
              enum: ["FARE", "ANCILLARY"]

    amountOfMoney:
      type: object
      properties:
        amount:
          description: This should be in the base unit as defined by the ISO 4217 currency code with the appropriate number of decimal places and omitting the currency symbol. e.g. if the price is in US Dollars the price would be 9.95. This is inclusive VAT
          type: number
          example: 9.95
          format: double
          minimum: 0
        currencyCode:
          description: ISO 4217 currency code
          type: string
          minLength: 3
          maxLength: 3
        vatRate:
          type: number
          description: value added tax rate (percentage of amount)
          example: 21.0
          format: double
          minimum: 0
        amountExVat:
          type: number
          example: 8.95
          format: double
          minimum: 0

    systemRegion:
      type: object
      required:
        - regionId
        - name
      properties:
        regionId:
          type: string
          description: Unique identifier for this region
          example: BikeRegion
        name:
          type: string
          description: Public name for this region, could match Content-Language
          example: BikeTown
        type:
          type: string
          description:
            the type of area. Default this is 'OPERATING', but other area's can be published here as well
            (since 1.3.0). Before 1.3.0, it was only allowed to communicate OPERATING area's.
          enum:
            [OPERATING, NO_ACCESS, NO_PARKING, PARKING, DISCOUNT, SPEEDLIMIT]
          default: OPERATING
        typeUnit:
          type: string
          description: in case the type needs a value (f.x. speed limit), this is the unit type.
          enum: [KMPH, MPH]
        typeValue:
          type: number
          format: double
          description: the value that belongs to the type (e.g. 8 MPH)
        serviceArea:
          description: The area served by the region (i.e. where one may travel using the service's assets) as GeoJSON Polygon coordinates
          $ref: "#/components/schemas/geojsonPolygon"

    traveler:
      description: A generic description of a traveler, not including any identifying information
      type: object
      properties:
        isValidated:
          description: Whether this traveler's identity and properties have been verified by the MaaS provider
          type: boolean

  headers:
    language:
      required: true
      schema:
        type: string
        format: A comma-separated list of BCP 47 (RFC 5646) language tags and optional weights as described in IETF RFC7231 section 5.3.5
      description: A list of the languages/localizations the user would like to see the results in. For user privacy and ease of use on the TO side, this list should be kept as short as possible, ideally just one language tag from the list in operator/information
      example: nl, de;q=0.7
    expires:
      description: The result is valid until this timestamp. The pending booking is expired after this timestamp.
      schema:
        description: A HTTP date string, see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Expires
        type: string
        format: http-date
      required: true

  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-Access-Token

  responses:
    202Accepted:
      description: Request was successfully accepted for processing but has not yet completed.
      headers:
        Location:
          schema:
            type: string
          description: The URI where the created or updated resource will eventually be found.
          example: "/bookings/1234"
    204NoContent:
      description: Request was successful, no content to return.
    400BadRequest:
      description: Bad request. See https://github.com/TOMP-WG/TOMP-API/wiki/Error-handling-in-TOMP for further explanation of error code.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/error"
    401Unauthorized:
      description: Although the HTTP standard specifies "unauthorized", semantically this response means "unauthenticated". That is, the client must authenticate itself to get the requested response.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/error"
    403Forbidden:
      description: The client does not have access rights to the content, i.e. they are unauthorized, so server is rejecting to give proper response. Unlike 401, the client's identity is known to the server.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/error"
    404NotFound:
      description: The requested resources does not exist or the requester is not authorized to see it or know it exists.
    409Conflict:
      description: The request will not be fulfilled. The request itself is legal, but the content conflicts with the server and might be stale. The user might try again after looking up the current state of the resource.
    410Gone:
      description: The requested resource is no longer available. This is permanent.
    428PreconditionRequired:
      description: Preconditions are not met in order to access the requested resource. This might happen e.g. if a booking is made but the user has been blocked by the TO. See https://github.com/TOMP-WG/TOMP-API/wiki/Error-handling-in-TOMP for further explanation of error code.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/error"

    errorResponse:
      description: Bad request. See https://github.com/TOMP-WG/TOMP-API/wiki/Error-handling-in-TOMP for further explanation of error code.
      headers:
        Content-Language:
          $ref: "#/components/headers/language"
      content:
        application/json:
          schema:
            type: object
            properties:
              errors:
                type: array
                maxItems: 10
                items:
                  $ref: "#/components/schemas/error"
