diff --git a/booking.yaml b/booking.yaml new file mode 100644 index 0000000..2712666 --- /dev/null +++ b/booking.yaml @@ -0,0 +1,520 @@ +openapi: 3.0.0 +servers: [] +info: + version: 0.1.0 + title: Booking API + description: > + This is a API specification of REST endpoints that a Transport Service + Provider (TSP) should implement to receive messages from MaaS Operator(s). It is written + in machine readable [OpenAPI Specification](https://www.openapis.org/) format, so that API + endpoints, validators and test clients can be generated from the + documentation. + contact: + name: MaaS Alliance + url: 'https://maas-alliance.eu/' + license: + name: MIT + url: 'http://opensource.org/licenses/MIT' +tags: + - name: Booking + description: >- + Booking related APIs are the core of a TSP implementation. + Correspondingly, a Booking is the main object exchanged between MaaS and a + TSP. + externalDocs: + description: Booking scenarios + url: 'https://github.com/maas-alliance/apis/blob/booking-api/docs/booking.md' + - name: Listing + description: >- + Before a booking can be made via a TSP, available options at a given + location can be listed as follows +security: + - key: [] +paths: + /bookings/options/: + get: + description: >- + Returns available transport options for given coordinates. Start time + can be defined, but is optional. If startTime is not provided, but + required by the third party API, a default value of "Date.now()" is + used. + tags: + - Listing + parameters: + - name: from + description: 'User''s location in comma separated form e.g. 60.123,27.456' + in: query + required: true + schema: + type: string + pattern: >- + ^[-+]?([1-8]?\d(\.\d+)?|90(\.0+)?),\s*[-+]?(180(\.0+)?|((1[0-7]\d)|([1-9]?\d))(\.\d+)?)$ + - name: to + description: 'A desired destination e.g. 60.123,27.456' + in: query + required: false + schema: + type: string + pattern: >- + ^[-+]?([1-8]?\d(\.\d+)?|90(\.0+)?),\s*[-+]?(180(\.0+)?|((1[0-7]\d)|([1-9]?\d))(\.\d+)?)$ + - name: startTime + in: query + schema: + type: string + format: date-time + responses: + '200': + description: >- + Available transport methods matching the given query parameters. If + no transport methods are available, an empty array is returned. + content: + application/json: + schema: + type: array + description: Available transport options for the queried TSP + items: + $ref: '#/components/schemas/options' + '400': + description: >- + If coordinates given in the request are invalid the server returns + 400 Bad request as a response. + content: + application/json: + schema: + $ref: '#/components/schemas/error' + /bookings/: + get: + description: Returns the `Booking` that has been created earlier + tags: + - Booking + parameters: + - name: state + description: The state the booking to fetch + in: query + required: true + schema: + type: string + enum: + - BOOKED + - CANCELLED + - PAID + - UPDATE_REQUESTED + - UPDATED + - STARTED + - FINISHED + - name: startTime + in: query + schema: + type: string + format: date-time + responses: + '200': + description: The bookings matching the query + content: + application/json: + schema: + type: array + description: The bookings that matched the query (zero or more) + minItems: 0 + items: + $ref: '#/components/schemas/booking' + '400': + description: Bad request (invalid query parameters) + content: + application/json: + schema: + $ref: '#/components/schemas/error' + '401': + description: Authorization error (invalid API key) + content: + application/json: + schema: + $ref: '#/components/schemas/error' + default: + description: unexpected error + content: + application/json: + schema: + $ref: '#/components/schemas/error' + post: + description: >- + Creates a new `Booking` for the TSP in **booked** state. The returned + object will be a refrence that is passed back & forth throughout the + booking life cycle. + + The Booking may be modified in the response, e.g. location being + adjusted for a more suitable pick-up location. + + In addition, the service may contain a **meta** attribute for arbitrary + TSP metadata that the TSP needs later, and **token** attribute depicting + how long the current state is valid. + tags: + - Booking + responses: + '200': + description: A new booking was succesfully created + content: + application/json: + schema: + $ref: '#/components/schemas/booking' + '400': + description: Bad request (invalid body parameters) + content: + application/json: + schema: + $ref: '#/components/schemas/error' + '401': + description: Authorization error (invalid API key) + content: + application/json: + schema: + $ref: '#/components/schemas/error' + default: + description: Unexpected error + content: + application/json: + schema: + $ref: '#/components/schemas/error' + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/newBooking' + description: New `Booking` data + required: true + parameters: [] + '/bookings/{id}': + get: + description: Returns the `Bookings` that have been created through the system. + tags: + - Booking + parameters: + - name: id + in: path + description: Booking identifier + required: true + schema: + type: string + responses: + '200': + description: The booking was found + content: + application/json: + schema: + $ref: '#/components/schemas/booking' + '400': + description: Bad request (invalid query or body parameters) + content: + application/json: + schema: + $ref: '#/components/schemas/error' + '401': + description: Authorization error (invalid API key) + content: + application/json: + schema: + $ref: '#/components/schemas/error' + '404': + description: The booking was not found + content: + application/json: + schema: + $ref: '#/components/schemas/error' + default: + description: Unexpected error + content: + application/json: + schema: + $ref: '#/components/schemas/error' + put: + description: >- + Modifies the state of a `Booking`, e.g. **cancels**, **pays** or + **reschedules** it. The previous booking information is passed forward + as-is for reference. + tags: + - Booking + parameters: + - name: id + in: path + description: Booking identifier + required: true + schema: + type: string + responses: + '200': + description: The booking was modified + content: + application/json: + schema: + $ref: '#/components/schemas/booking' + default: + description: Unexpected error + content: + application/json: + schema: + $ref: '#/components/schemas/error' + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/booking' + description: New `Booking` data + required: true +components: + securitySchemes: + key: + description: > + MaaS can authenticate using an access token as part of the HTTP(S) + headers. The keys are sent as part of every request that MaaS makes to + the TSP API with a `x-api-key` custom header option. + type: apiKey + name: X-Api-Key + in: header + schemas: + error: + type: object + description: >- + An error that the service may send, e.g. in case of invalid input, + missing authorization or internal service error. + required: + - message + - code + properties: + message: + type: string + description: A human readable error message (preferrably in English) + code: + type: string + description: 'A TSP internal error code, used for reference' + newBooking: + type: object + description: 'A new booking, created by MaaS POST request in ''new'' state' + required: + - leg + - customer + properties: + state: + type: string + description: The state of the booking (always new for new bookings) + enum: + - NEW + leg: + $ref: '#/components/schemas/leg' + customer: + $ref: '#/components/schemas/customer' + booking: + type: object + description: >- + The booking information describing the state and details of the + transaction + allOf: + - $ref: '#/components/schemas/newBooking' + properties: + id: + description: The identifier MaaS will be using to referring to the booking + type: string + state: + $ref: '#/components/schemas/bookingState' + terms: + description: Any additional terms related to the booking (e.g. terms of service) + type: string + token: + $ref: '#/components/schemas/token' + meta: + description: Arbitrary metadata that a TSP can add + type: object + required: + - id + - state + - leg + - customer + - token + bookingState: + description: The life-cycle state of the booking (from NEW to FINISHED) + type: string + enum: + - NEW + - BOOKED + - CANCELLED + - PAID + - UPDATE_REQUESTED + - UPDATED + - STARTED + - FINISHED + token: + description: >- + The validity token (such as booking ID, travel ticket etc.) that MaaS + clients will display to validate the trip when starting the leg. + properties: + validityDuration: + description: >- + The rules that MaaS will interpret to schedule, re-validate or + cancel the booking. + type: object + properties: + from: + description: The starting time from which the ticket is valid + $ref: '#/components/schemas/time' + to: + description: The finishing time the ticket is valid for + $ref: '#/components/schemas/time' + meta: + description: >- + Arbitrary metadata the TSP may pass along the ticket to the client + (e.g. a booking code, base64 encoded binary) + type: object + customer: + type: object + required: + - id + - firstName + - lastName + properties: + id: + description: The identifier MaaS uses to identify the customer + type: string + firstName: + description: First name of the customer (e.g. John) + type: string + lastName: + description: Last name of the customer (e.g. Doe) + type: string + phone: + description: Phone number that the customer may be reached from + type: string + options: + type: array + description: Containing an array of available options matching the query + properties: + leg: + $ref: '#/components/schemas/options_leg' + meta: + $ref: '#/components/schemas/options_meta' + options_leg: + type: object + properties: + startTime: + $ref: '#/components/schemas/time' + endTime: + $ref: '#/components/schemas/time' + from: + $ref: '#/components/schemas/options_coordinates' + to: + $ref: '#/components/schemas/options_coordinates' + options_coordinates: + type: object + properties: + lat: + $ref: '#/components/schemas/lat' + lon: + $ref: '#/components/schemas/lon' + options_meta: + type: object + properties: + name: + type: string + description: + type: string + image: + type: string + format: url + car: + type: object + properties: + passengers: + type: integer + leg: + type: object + description: >- + A OpenTripPlanner compatible definition of a leg (see OpenTripPlanner + docs for reference) + additionalProperties: true + properties: + from: + description: The coordinates the TSP should use to resolve leg start location + $ref: '#/components/schemas/place' + to: + description: The coordinates the TSP should use to resolve leg finish location + $ref: '#/components/schemas/place' + startTime: + $ref: '#/components/schemas/time' + endTime: + $ref: '#/components/schemas/time' + mode: + $ref: '#/components/schemas/mode' + departureDelay: + $ref: '#/components/schemas/duration' + arrivalDelay: + $ref: '#/components/schemas/duration' + distance: + $ref: '#/components/schemas/distance' + fare: + $ref: '#/components/schemas/fare' + route: + type: string + routeShortName: + type: string + routeLongName: + type: string + agencyId: + type: string + legGeometry: + $ref: '#/components/schemas/legGeometry' + required: + - from + - to + - mode + - startTime + - endTime + place: + type: object + additionalProperties: true + properties: + name: + description: Human readable name of the place + type: string + stopId: + type: string + stopCode: + type: string + lat: + $ref: '#/components/schemas/lat' + lon: + $ref: '#/components/schemas/lon' + required: + - lon + - lat + lat: + type: number + minimum: -90 + maximum: 90 + lon: + type: number + minimum: -180 + maximum: 180 + legGeometry: + type: object + additionalProperties: true + properties: + points: + type: string + minLength: 1 + time: + description: >- + An ISO 8601 date/time expression (e.g. YYYY-mm-ddThh:mm:ss) + duration: + description: A duration of some time (relative to time) in milliseconds + type: integer + maximum: 2147483647 + minimum: 0 + distance: + description: The estimated distance travelled in the leg (in meters) + type: integer + minimum: 0 + fare: + description: Arbitrary fare data that MaaS will use internally + type: object + mode: + description: The type of the leg MaaS uses to identify the leg + links: {} + callbacks: {} diff --git a/docs/booking-process.svg b/docs/booking-process.svg new file mode 100644 index 0000000..18d9ad7 --- /dev/null +++ b/docs/booking-process.svg @@ -0,0 +1,4 @@ + + + +User / AppValidateTicketAbout toComplete LegTrip finishedNotify Leg Completed Give FeedbackLegCompletedAbout to Start a LegPlan a new TripQuery a RouteBook a RouteNavigationStart a LegNewBookingMaaSNotify Leg Completed Store FeedbackScheduledpaymentTicketPaidQuery a Route"Stamp the Ticket" Scheduled Stamping Automatic (re)validation Scheduled Revalidation Pay a BookingUpload Route & Schedule Data Book Route Legs RescheduleLegsTransport Service ProviderValidate a TicketReceiveFeedbackStore Leg Completed NewTransportServiceUpdate Route & Schedule Data Pay a BookingCreate a Booking Change inBookingconditionsUpdate bookingCancel a Booking Update aBookingStamp a Ticket3rd Party SystemsStore the GTFS data Query RouteGTFS DataGTFSDumpGTFSDumpUpdatedBookingValid[true/false]Booking[Paid]BookingBooking[Booked]Booking[Update requested] Booking[Cancelled]Booking[Updated]UpdateBookingUpdatedBookingNewBookingBookingBooking[Paid][manual stamping]Booking [Started]Booking[Started]Booking[Started]Booking[Started]ValidateBooking[Validated] diff --git a/docs/booking.md b/docs/booking.md new file mode 100644 index 0000000..8d15a6d --- /dev/null +++ b/docs/booking.md @@ -0,0 +1,103 @@ +# MaaS Transport Service Provider Booking API + +The following scenario explains the life-cycle of an individual trip +from a TSP viewpoint. Whenever a new concept (such as an actor or action) +is represented, it is imprinted in **bold**. + +This scenario, with a few extra details is detailed in the process diagram +below. It should be noted from the picture that MaaS more often acts as a +caller than a callee for Transport Service Provider. + +The cases of how MaaS interacts with TSP are depicted below +![Maas-TSP Business Process](https://cdn.rawgit.com/maas-alliance/apis/master/docs/booking-process.svg) +[source](https://github.com/maas-alliance/apis/blob/master/docs/booking-process.svg "MaaS-TSP Business Process"). + +## Planning a Route + +**User** **queries** for a **Route** with an address or latitude-logitude +pair from one place to another. MaaS queries the route from a third party +**Routing Engine** that contains the data for **TSP** routes. At this point +MaaS makes no queries to the TSP - it expects the Routing Engine contains +valid GTFS data for the TSP. + +**MaaS** shows several possible **Plans**, each containing a valid +**Route** with several **Legs** with a part of a route using a specific +TSP. + +## Creating a Booking + +User browses through the Plans and chooses to book a trip. For each Leg +in the Plan Route, MaaS creates a new **Booking** for a TSP. +It should be noted that the booking may be hours or days in +advance - a bit like in booking a hotel. The booking contains the +individual Leg as the detailed travel plan for the TSP, as well as +customer contact information. + +TSP receives the booking and confirms the trip. TSP may modify the details +of the Booking, such as moving the **start location** to closest known +street address or delaying the Leg **start time**, as long as the +**end time** can be guaranteed. The Booking is supplemented with +**booked** state information and additional **terms** latest such as +the latest **cancellation time**. + +MaaS checks that the booking succeeded and stores the Booking for future +reference. + +## Navigating a Route + +User starts to navigate the Route. MaaS tracks for the user location to +know if there are any changes needed in the plan. MaaS triggers the changes +for bookings by monitoring the individual Legs. + +MaaS monitors the Booking terms and Leg **start time**. +When the actual Leg starts, MaaS **starts** the Leg and notifies the TSP. +User or TSP may request changes to the Booking, e.g. in a case of a delay +or cancellation. + +Each of these scenarios are described below. + +## Updating a Booking + +A Booking may be updated by a User, MaaS or TSP when any party receives +new information that the Leg needs to be changed. Since the update may need +confirmation from User or a 3rd party system, it is an asynchronous +operation. + +Either party (MaaS or TSP) may send an updated Booking with +**UPDATE_REQUESTED** state. The recipient processes the request +asynchronously and either confirms the request with **UPDATED** state, +sends its proposal with **UPDATE_REQUESTED**, or cancels the leg with +**CANCELLED** state. + +## Cancelling a Booking + +A Booking may be cancelled by User or MaaS within **cancellation time** in +**terms** of the Booking without a specific request. MaaS sends a modified +Booking with state **CANCELLED** information. TSP confirms and updates its +own systems. + +It should be noted that cancellation is an exception case and is likely +happen only when the user chooses to cancel the whole route Plan. +Instead, MaaS and/or TSP should update the booking with new information. + +TSP can assume Booking as paid if the cancellation time has passed and no +cancellation has been received from MaaS. + +## Paying a Booking + +A Booking may be paid (e.g. confirmed) before the **cancellation time** +in **terms** has expired. MaaS sends a modified Booking with **PAID** +state wich the TSP confirms. + +TSP can assume Booking as paid if the cancellation time has passed and no +cancellation has been received from MaaS. + +## Error Cases + +It may be possible that MaaS sends an invalid request or the TSP cannot +fulfill a request. In any such case, TSP may respond with an error. If +TSP responds with an error, MaaS assumes the state was not changed (e.g. +a transaction was rolled back). MaaS may repeat the request +with the same or different data later on. + +The same principle applies when TSP is communicating with MaaS.