diff --git a/components/responses/BadRequest.yaml b/components/responses/BadRequest.yaml new file mode 100644 index 0000000..2169713 --- /dev/null +++ b/components/responses/BadRequest.yaml @@ -0,0 +1,8 @@ +description: Bad Request +content: + application/problem+json: + example: + type: https://example.com/errors/bad-request + title: Bad Request + status: 400 + detail: The request is invalid or missing required parameters. diff --git a/components/responses/Conflict.yaml b/components/responses/Conflict.yaml new file mode 100644 index 0000000..9929321 --- /dev/null +++ b/components/responses/Conflict.yaml @@ -0,0 +1,8 @@ +description: Conflict +content: + application/problem+json: + example: + type: https://example.com/errors/conflict + title: Conflict + status: 409 + detail: There is a conflict with an existing resource. diff --git a/components/responses/Forbidden.yaml b/components/responses/Forbidden.yaml new file mode 100644 index 0000000..f65e5be --- /dev/null +++ b/components/responses/Forbidden.yaml @@ -0,0 +1,8 @@ +description: Forbidden +content: + application/problem+json: + example: + type: https://example.com/errors/forbidden + title: Forbidden + status: 403 + detail: Access is forbidden for the provided credentials. diff --git a/components/responses/InternalServerError.yaml b/components/responses/InternalServerError.yaml new file mode 100644 index 0000000..c7423ab --- /dev/null +++ b/components/responses/InternalServerError.yaml @@ -0,0 +1,8 @@ +description: Internal Server Error +content: + application/problem+json: + example: + type: https://example.com/errors/internal-server-error + title: Internal Server Error + status: 500 + detail: An unexpected error occurred. diff --git a/components/responses/NotFound.yaml b/components/responses/NotFound.yaml new file mode 100644 index 0000000..7de987b --- /dev/null +++ b/components/responses/NotFound.yaml @@ -0,0 +1,8 @@ +description: Not Found +content: + application/problem+json: + example: + type: https://example.com/errors/not-found + title: Not Found + status: 404 + detail: The requested resource was not found. diff --git a/components/responses/TooManyRequests.yaml b/components/responses/TooManyRequests.yaml new file mode 100644 index 0000000..d4e7092 --- /dev/null +++ b/components/responses/TooManyRequests.yaml @@ -0,0 +1,8 @@ +description: Too Many Requests +content: + application/problem+json: + example: + type: https://example.com/errors/too-many-requests + title: Too Many Requests + status: 429 + detail: You have exceeded the rate limit. diff --git a/components/responses/Unauthorized.yaml b/components/responses/Unauthorized.yaml new file mode 100644 index 0000000..5bf6df3 --- /dev/null +++ b/components/responses/Unauthorized.yaml @@ -0,0 +1,8 @@ +description: Unauthorized +content: + application/problem+json: + example: + type: https://example.com/errors/unauthorized + title: Unauthorized + status: 401 + detail: You do not have the necessary permissions. diff --git a/components/schemas/Booking.yaml b/components/schemas/Booking.yaml new file mode 100644 index 0000000..a11f244 --- /dev/null +++ b/components/schemas/Booking.yaml @@ -0,0 +1,26 @@ +type: object +properties: + booking_id: + type: string + format: uuid + description: Unique identifier for the booking + readOnly: true + examples: + - efdbb9d1-02c2-4bc3-afb7-6788d8782b1e + trip_id: + type: string + format: uuid + description: Identifier of the booked trip + examples: + - efdbb9d1-02c2-4bc3-afb7-6788d8782b1e + passenger_name: + type: string + description: Name of the passenger + examples: + - John Doe + has_bicycle: + type: boolean + description: Indicates whether the passenger has a bicycle + has_dog: + type: boolean + description: Indicates whether the passenger has a dog diff --git a/components/schemas/Station.yaml b/components/schemas/Station.yaml new file mode 100644 index 0000000..24f8488 --- /dev/null +++ b/components/schemas/Station.yaml @@ -0,0 +1,28 @@ +type: object +properties: + id: + type: string + format: uuid + description: Unique identifier for the station + examples: + - efdbb9d1-02c2-4bc3-afb7-6788d8782b1e + - b2e783e1-c824-4d63-b37a-d8d698862f1d + name: + type: string + description: The name of the station + examples: + - Berlin Hauptbahnhof + - Paris Gare du Nord + address: + type: string + description: The address of the station + examples: + - Invalidenstraße 10557 Berlin, Germany + - 18 Rue de Dunkerque 75010 Paris, France + country_code: + type: string + description: The country code of the station + format: iso-country-code + examples: + - DE + - FR diff --git a/components/schemas/Trip.yaml b/components/schemas/Trip.yaml new file mode 100644 index 0000000..dcaf3f9 --- /dev/null +++ b/components/schemas/Trip.yaml @@ -0,0 +1,44 @@ +type: object +properties: + id: + type: string + format: uuid + description: Unique identifier for the trip + examples: + - efdbb9d1-02c2-4bc3-afb7-6788d8782b1e + - b2e783e1-c824-4d63-b37a-d8d698862f1d + origin: + type: string + description: The starting station of the trip + examples: + - Berlin Hauptbahnhof + - Paris Gare du Nord + destination: + type: string + description: The destination station of the trip + examples: + - Paris Gare du Nord + - Berlin Hauptbahnhof + departure_time: + type: string + format: date-time + description: The date and time when the trip departs + examples: + - '2024-02-01T10:00:00Z' + arrival_time: + type: string + format: date-time + description: The date and time when the trip arrives + examples: + - '2024-02-01T16:00:00Z' + price: + type: number + description: The cost of the trip + examples: + - 50 + bicycles_allowed: + type: boolean + description: Indicates whether bicycles are allowed on the trip + dogs_allowed: + type: boolean + description: Indicates whether dogs are allowed on the trip diff --git a/openapi.yaml b/openapi.yaml index 1200047..74255bc 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -3,157 +3,23 @@ info: title: Train Travel API description: API for finding and booking train trips across Europe. version: 1.0.0 - contact: + contact: name: Train Support url: https://example.com/support email: support@example.com servers: - url: https://api.example.com/v1 - paths: /stations: - get: - summary: Get a list of train stations - description: Returns a list of all train stations in the system. - operationId: get-stations - responses: - '200': - description: A list of train stations - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/Station' - example: - - id: "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e" - name: Berlin Hauptbahnhof - address: "Invalidenstraße 10557 Berlin, Germany" - country_code: DE - - id: "b2e783e1-c824-4d63-b37a-d8d698862f1d" - name: Paris Gare du Nord - address: "18 Rue de Dunkerque 75010 Paris, France" - country_code: FR - '401': - $ref: '#/components/responses/Unauthorized' - '403': - $ref: '#/components/responses/Forbidden' - '429': - $ref: '#/components/responses/TooManyRequests' - '500': - $ref: '#/components/responses/InternalServerError' - + $ref: paths/stations.yaml /trips: - get: - summary: Get available train trips - description: Returns a list of available train trips between the specified origin and destination stations on the given date, and allows for filtering by bicycle and dog allowances. - operationId: get-trips - parameters: - - name: origin - in: query - description: The ID of the origin station - required: true - schema: - type: string - format: uuid - - name: destination - in: query - description: The ID of the destination station - required: true - schema: - type: string - format: uuid - - name: date - in: query - description: The date of the trip (YYYY-MM-DD) - required: true - schema: - type: string - format: date - - name: bicycles - in: query - description: Indicates whether bicycles are allowed on the trip - required: false - schema: - type: boolean - - name: dogs - in: query - description: Indicates whether dogs are allowed on the trip - required: false - schema: - type: boolean - responses: - '200': - description: A list of available train trips - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/Trip' - example: - - id: "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e" - origin: Berlin Hauptbahnhof - destination: Paris Gare du Nord - departure_time: "2024-02-01T10:00:00Z" - arrival_time: "2024-02-01T16:00:00Z" - price: 50.00 - bicycles_allowed: true - dogs_allowed: true - - '401': - $ref: '#/components/responses/Unauthorized' - '403': - $ref: '#/components/responses/Forbidden' - '429': - $ref: '#/components/responses/TooManyRequests' - '500': - $ref: '#/components/responses/InternalServerError' - + $ref: paths/trips.yaml /bookings: - post: - summary: Book a train trip - operationId: create-booking - description: Books a train trip for a passenger. - security: - - OAuth2: ['write'] - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/Booking' - example: - trip_id: "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e" - passenger_name: John Doe - has_bicycle: true - has_dog: true - responses: - '201': - description: Booking successful - content: - application/json: - schema: - $ref: '#/components/schemas/Booking' - - '400': - $ref: '#/components/responses/BadRequest' - '401': - $ref: '#/components/responses/Unauthorized' - '404': - $ref: '#/components/responses/NotFound' - '409': - $ref: '#/components/responses/Conflict' - '429': - $ref: '#/components/responses/TooManyRequests' - '500': - $ref: '#/components/responses/InternalServerError' - -security: - - OAuth2: ['read'] - + $ref: paths/bookings.yaml +security: + - OAuth2: + - read components: - securitySchemes: OAuth2: type: oauth2 @@ -164,144 +30,3 @@ components: scopes: read: Read access write: Write access - schemas: - Station: - type: object - properties: - id: - type: string - format: uuid - description: Unique identifier for the station - name: - type: string - description: The name of the station - address: - type: string - description: The address of the station - country_code: - type: string - description: The country code of the station - format: iso-country-code - Trip: - type: object - properties: - id: - type: string - format: uuid - description: Unique identifier for the trip - origin: - type: string - description: The starting station of the trip - destination: - type: string - description: The destination station of the trip - departure_time: - type: string - format: date-time - description: The date and time when the trip departs - arrival_time: - type: string - format: date-time - description: The date and time when the trip arrives - price: - type: number - description: The cost of the trip - bicycles_allowed: - type: boolean - description: Indicates whether bicycles are allowed on the trip - dogs_allowed: - type: boolean - description: Indicates whether dogs are allowed on the trip - - Booking: - type: object - properties: - booking_id: - type: string - format: uuid - description: Unique identifier for the booking - readOnly: true - trip_id: - type: string - format: uuid - description: Identifier of the booked trip - passenger_name: - type: string - description: Name of the passenger - has_bicycle: - type: boolean - description: Indicates whether the passenger has a bicycle - has_dog: - type: boolean - description: Indicates whether the passenger has a dog - - responses: - Unauthorized: - description: Unauthorized - content: - application/problem+json: - example: - type: https://example.com/errors/unauthorized - title: Unauthorized - status: 401 - detail: You do not have the necessary permissions. - - Forbidden: - description: Forbidden - content: - application/problem+json: - example: - type: https://example.com/errors/forbidden - title: Forbidden - status: 403 - detail: Access is forbidden for the provided credentials. - - BadRequest: - description: Bad Request - content: - application/problem+json: - example: - type: https://example.com/errors/bad-request - title: Bad Request - status: 400 - detail: The request is invalid or missing required parameters. - - NotFound: - description: Not Found - content: - application/problem+json: - example: - type: https://example.com/errors/not-found - title: Not Found - status: 404 - detail: The requested resource was not found. - - Conflict: - description: Conflict - content: - application/problem+json: - example: - type: https://example.com/errors/conflict - title: Conflict - status: 409 - detail: There is a conflict with an existing resource. - - TooManyRequests: - description: Too Many Requests - content: - application/problem+json: - example: - type: https://example.com/errors/too-many-requests - title: Too Many Requests - status: 429 - detail: You have exceeded the rate limit. - - InternalServerError: - description: Internal Server Error - content: - application/problem+json: - example: - type: https://example.com/errors/internal-server-error - title: Internal Server Error - status: 500 - detail: An unexpected error occurred. diff --git a/paths/bookings.yaml b/paths/bookings.yaml new file mode 100644 index 0000000..e1cbd87 --- /dev/null +++ b/paths/bookings.yaml @@ -0,0 +1,95 @@ +get: + operationId: get-bookings + summary: List existing bookings + description: Returns a list of all trips booking by the authenticated user. + responses: + '200': + description: A list of bookings + content: + application/json: + schema: + type: object + properties: + data: + type: array + items: + $ref: ../components/schemas/Booking.yaml + links: + type: object + properties: + self: + type: string + format: uri + next: + type: string + format: uri + prev: + type: string + format: uri + example: + data: + - booking_id: efdbb9d1-02c2-4bc3-afb7-6788d8782b1e + trip_id: efdbb9d1-02c2-4bc3-afb7-6788d8782b1e + passenger_name: John Doe + has_bicycle: true + has_dog: true + - booking_id: b2e783e1-c824-4d63-b37a-d8d698862f1d + trip_id: b2e783e1-c824-4d63-b37a-d8d698862f1d + passenger_name: Jane Smith + has_bicycle: false + has_dog: false + '401': + $ref: ../components/responses/Unauthorized.yaml + '403': + $ref: ../components/responses/Forbidden.yaml + '429': + $ref: ../components/responses/TooManyRequests.yaml + '500': + $ref: ../components/responses/InternalServerError.yaml +post: + operationId: create-booking + summary: Create a booking + description: Attempts to book a trip for the authenticated user. + security: + - OAuth2: + - write + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + data: + $ref: ../components/schemas/Booking.yaml + links: + type: object + properties: + self: + type: string + format: uri + example: + data: + trip_id: efdbb9d1-02c2-4bc3-afb7-6788d8782b1e + passenger_name: John Doe + has_bicycle: true + has_dog: true + responses: + '201': + description: Booking successful + content: + application/json: + schema: + $ref: ../components/schemas/Booking.yaml + '400': + $ref: ../components/responses/BadRequest.yaml + '401': + $ref: ../components/responses/Unauthorized.yaml + '404': + $ref: ../components/responses/NotFound.yaml + '409': + $ref: ../components/responses/Conflict.yaml + '429': + $ref: ../components/responses/TooManyRequests.yaml + '500': + $ref: ../components/responses/InternalServerError.yaml diff --git a/paths/stations.yaml b/paths/stations.yaml new file mode 100644 index 0000000..a1e9afe --- /dev/null +++ b/paths/stations.yaml @@ -0,0 +1,46 @@ +get: + summary: Get a list of train stations + description: Returns a list of all train stations in the system. + operationId: get-stations + responses: + '200': + description: A list of train stations + content: + application/json: + schema: + type: object + properties: + data: + type: array + items: + $ref: ../components/schemas/Station.yaml + links: + type: object + properties: + self: + type: string + format: uri + next: + type: string + format: uri + prev: + type: string + format: uri + example: + data: + - id: efdbb9d1-02c2-4bc3-afb7-6788d8782b1e + name: Berlin Hauptbahnhof + address: Invalidenstraße 10557 Berlin, Germany + country_code: DE + - id: b2e783e1-c824-4d63-b37a-d8d698862f1d + name: Paris Gare du Nord + address: 18 Rue de Dunkerque 75010 Paris, France + country_code: FR + '401': + $ref: ../components/responses/Unauthorized.yaml + '403': + $ref: ../components/responses/Forbidden.yaml + '429': + $ref: ../components/responses/TooManyRequests.yaml + '500': + $ref: ../components/responses/InternalServerError.yaml diff --git a/paths/trips.yaml b/paths/trips.yaml new file mode 100644 index 0000000..de4d928 --- /dev/null +++ b/paths/trips.yaml @@ -0,0 +1,83 @@ +get: + summary: Get available train trips + description: >- + Returns a list of available train trips between the specified origin and + destination stations on the given date, and allows for filtering by bicycle + and dog allowances. + operationId: get-trips + parameters: + - name: origin + in: query + description: The ID of the origin station + required: true + schema: + type: string + format: uuid + - name: destination + in: query + description: The ID of the destination station + required: true + schema: + type: string + format: uuid + - name: date + in: query + description: The date of the trip (YYYY-MM-DD) + required: true + schema: + type: string + format: date + - name: bicycles + in: query + description: Indicates whether bicycles are allowed on the trip + required: false + schema: + type: boolean + - name: dogs + in: query + description: Indicates whether dogs are allowed on the trip + required: false + schema: + type: boolean + responses: + '200': + description: A list of available train trips + content: + application/json: + schema: + type: object + properties: + data: + type: array + items: + $ref: ../components/schemas/Trip.yaml + links: + type: object + properties: + self: + type: string + format: uri + next: + type: string + format: uri + prev: + type: string + format: uri + example: + data: + - id: efdbb9d1-02c2-4bc3-afb7-6788d8782b1e + origin: Berlin Hauptbahnhof + destination: Paris Gare du Nord + departure_time: '2024-02-01T10:00:00Z' + arrival_time: '2024-02-01T16:00:00Z' + price: 50 + bicycles_allowed: true + dogs_allowed: true + '401': + $ref: ../components/responses/Unauthorized.yaml + '403': + $ref: ../components/responses/Forbidden.yaml + '429': + $ref: ../components/responses/TooManyRequests.yaml + '500': + $ref: ../components/responses/InternalServerError.yaml