Created
September 3, 2024 14:49
-
-
Save joshtwist/ef5a8a1952e515be2583a9115691e9ca to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"openapi": "3.1.0", | |
"info": { | |
"title": "Train Travel API", | |
"description": "API for finding and booking train trips across Europe.\n\n## Run in Postman\n\nExperiment with this API in Postman, using our Postman Collection.\n\n[<img src=\"https://run.pstmn.io/button.svg\" alt=\"Run In Postman\" style=\"width: 128px; height: 32px;\">](https://app.getpostman.com/run-collection/9265903-7a75a0d0-b108-4436-ba54-c6139698dc08?action=collection%2Ffork&source=rip_markdown&collection-url=entityId%3D9265903-7a75a0d0-b108-4436-ba54-c6139698dc08%26entityType%3Dcollection%26workspaceId%3Df507f69d-9564-419c-89a2-cb8e4c8c7b8f)\n", | |
"version": "1.0.0", | |
"contact": { | |
"name": "Train Support", | |
"url": "https://example.com/support", | |
"email": "[email protected]" | |
}, | |
"license": { | |
"name": "Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International", | |
"identifier": "CC-BY-NC-SA-4.0" | |
}, | |
"x-feedbackLink": { | |
"label": "Submit Feedback", | |
"url": "https://github.com/bump-sh-examples/train-travel-api/issues/new" | |
} | |
}, | |
"servers": [ | |
{ | |
"url": "https://api.example.com", | |
"description": "Production" | |
} | |
], | |
"security": [ | |
{ | |
"OAuth2": [ | |
"read" | |
] | |
} | |
], | |
"x-topics": [ | |
{ | |
"title": "Getting started", | |
"content": { | |
"$ref": "./docs/getting-started.md" | |
} | |
} | |
], | |
"tags": [ | |
{ | |
"name": "Stations", | |
"description": "Find and filter train stations across Europe, including their location\nand local timezone.\n" | |
}, | |
{ | |
"name": "Trips", | |
"description": "Timetables and routes for train trips between stations, including pricing\nand availability.\n" | |
}, | |
{ | |
"name": "Bookings", | |
"description": "Create and manage bookings for train trips, including passenger details\nand optional extras.\n" | |
}, | |
{ | |
"name": "Payments", | |
"description": "Pay for bookings using a card or bank account, and view payment\nstatus and history.\n\n> warn\n> Bookings usually expire within 1 hour so you'll need to make your payment\n> before the expiry date \n" | |
} | |
], | |
"paths": { | |
"/stations": { | |
"get": { | |
"summary": "Get a list of train stations", | |
"description": "Returns a paginated and searchable list of all train stations.", | |
"operationId": "get-stations", | |
"tags": [ | |
"Stations" | |
], | |
"parameters": [ | |
{ | |
"name": "page", | |
"in": "query", | |
"description": "The page number to return", | |
"required": false, | |
"schema": { | |
"type": "integer", | |
"minimum": 1, | |
"default": 1 | |
}, | |
"example": 1 | |
}, | |
{ | |
"name": "coordinates", | |
"in": "query", | |
"description": "The latitude and longitude of the user's location, to narrow down the search results to sites within a proximity of this location.\n", | |
"required": false, | |
"schema": { | |
"type": "string" | |
}, | |
"example": "52.5200,13.4050" | |
}, | |
{ | |
"name": "search", | |
"in": "query", | |
"description": "A search term to filter the list of stations by name or address.\n", | |
"required": false, | |
"schema": { | |
"type": "string", | |
"examples": [ | |
"Milano Centrale", | |
"Paris" | |
] | |
} | |
} | |
], | |
"responses": { | |
"200": { | |
"description": "OK", | |
"headers": { | |
"RateLimit": { | |
"$ref": "#/components/headers/RateLimit" | |
} | |
}, | |
"content": { | |
"application/json": { | |
"schema": { | |
"properties": { | |
"data": { | |
"type": "array", | |
"items": { | |
"$ref": "#/components/schemas/Station" | |
} | |
} | |
} | |
}, | |
"example": { | |
"data": [ | |
{ | |
"id": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e", | |
"name": "Berlin Hauptbahnhof", | |
"address": "Invalidenstraße 10557 Berlin, Germany", | |
"country_code": "DE", | |
"timezone": "Europe/Berlin" | |
}, | |
{ | |
"id": "b2e783e1-c824-4d63-b37a-d8d698862f1d", | |
"name": "Paris Gare du Nord", | |
"address": "18 Rue de Dunkerque 75010 Paris, France", | |
"country_code": "FR", | |
"timezone": "Europe/Paris" | |
} | |
], | |
"links": { | |
"self": "https://api.example.com/stations&page=2", | |
"next": "https://api.example.com/stations?page=3", | |
"prev": "https://api.example.com/stations?page=1" | |
} | |
} | |
}, | |
"application/xml": { | |
"schema": { | |
"allOf": [ | |
{ | |
"$ref": "#/components/schemas/Wrapper-Collection" | |
}, | |
{ | |
"properties": { | |
"data": { | |
"type": "array", | |
"xml": { | |
"name": "stations", | |
"wrapped": true | |
}, | |
"items": { | |
"$ref": "#/components/schemas/Station" | |
} | |
} | |
} | |
}, | |
{ | |
"properties": { | |
"links": { | |
"allOf": [ | |
{ | |
"$ref": "#/components/schemas/Links-Self" | |
}, | |
{ | |
"$ref": "#/components/schemas/Links-Pagination" | |
} | |
] | |
} | |
} | |
} | |
] | |
} | |
} | |
} | |
}, | |
"400": { | |
"$ref": "#/components/responses/BadRequest" | |
}, | |
"401": { | |
"$ref": "#/components/responses/Unauthorized" | |
}, | |
"403": { | |
"$ref": "#/components/responses/Forbidden" | |
}, | |
"429": { | |
"$ref": "#/components/responses/TooManyRequests" | |
}, | |
"500": { | |
"$ref": "#/components/responses/InternalServerError" | |
} | |
} | |
} | |
}, | |
"/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.\n", | |
"operationId": "get-trips", | |
"tags": [ | |
"Trips" | |
], | |
"parameters": [ | |
{ | |
"name": "origin", | |
"in": "query", | |
"description": "The ID of the origin station", | |
"required": true, | |
"schema": { | |
"type": "string", | |
"format": "uuid" | |
}, | |
"example": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e" | |
}, | |
{ | |
"name": "destination", | |
"in": "query", | |
"description": "The ID of the destination station", | |
"required": true, | |
"schema": { | |
"type": "string", | |
"format": "uuid" | |
}, | |
"example": "b2e783e1-c824-4d63-b37a-d8d698862f1d" | |
}, | |
{ | |
"name": "date", | |
"in": "query", | |
"description": "The date and time of the trip in ISO 8601 format in origin station's timezone.", | |
"required": true, | |
"schema": { | |
"type": "string", | |
"format": "date-time" | |
}, | |
"example": "2024-02-01T09:00:00Z" | |
}, | |
{ | |
"name": "bicycles", | |
"in": "query", | |
"description": "Only return trips where bicycles are known to be allowed", | |
"required": false, | |
"schema": { | |
"type": "boolean", | |
"default": false | |
} | |
}, | |
{ | |
"name": "dogs", | |
"in": "query", | |
"description": "Only return trips where dogs are known to be allowed", | |
"required": false, | |
"schema": { | |
"type": "boolean", | |
"default": false | |
} | |
} | |
], | |
"responses": { | |
"200": { | |
"description": "A list of available train trips", | |
"headers": { | |
"RateLimit": { | |
"$ref": "#/components/headers/RateLimit" | |
} | |
}, | |
"content": { | |
"application/json": { | |
"schema": { | |
"allOf": [ | |
{ | |
"$ref": "#/components/schemas/Wrapper-Collection" | |
}, | |
{ | |
"properties": { | |
"data": { | |
"type": "array", | |
"items": { | |
"$ref": "#/components/schemas/Trip" | |
} | |
} | |
} | |
}, | |
{ | |
"properties": { | |
"links": { | |
"allOf": [ | |
{ | |
"$ref": "#/components/schemas/Links-Self" | |
}, | |
{ | |
"$ref": "#/components/schemas/Links-Pagination" | |
} | |
] | |
} | |
} | |
} | |
] | |
}, | |
"example": { | |
"data": [ | |
{ | |
"id": "ea399ba1-6d95-433f-92d1-83f67b775594", | |
"origin": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e", | |
"destination": "b2e783e1-c824-4d63-b37a-d8d698862f1d", | |
"departure_time": "2024-02-01T10:00:00Z", | |
"arrival_time": "2024-02-01T16:00:00Z", | |
"price": 50, | |
"operator": "Deutsche Bahn", | |
"bicycles_allowed": true, | |
"dogs_allowed": true | |
}, | |
{ | |
"id": "4d67459c-af07-40bb-bb12-178dbb88e09f", | |
"origin": "b2e783e1-c824-4d63-b37a-d8d698862f1d", | |
"destination": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e", | |
"departure_time": "2024-02-01T12:00:00Z", | |
"arrival_time": "2024-02-01T18:00:00Z", | |
"price": 50, | |
"operator": "SNCF", | |
"bicycles_allowed": true, | |
"dogs_allowed": true | |
} | |
], | |
"links": { | |
"self": "https://api.example.com/trips?origin=efdbb9d1-02c2-4bc3-afb7-6788d8782b1e&destination=b2e783e1-c824-4d63-b37a-d8d698862f1d&date=2024-02-01", | |
"next": "https://api.example.com/trips?origin=efdbb9d1-02c2-4bc3-afb7-6788d8782b1e&destination=b2e783e1-c824-4d63-b37a-d8d698862f1d&date=2024-02-01&page=2" | |
} | |
} | |
}, | |
"application/xml": { | |
"schema": { | |
"allOf": [ | |
{ | |
"$ref": "#/components/schemas/Wrapper-Collection" | |
}, | |
{ | |
"properties": { | |
"data": { | |
"type": "array", | |
"xml": { | |
"name": "trips", | |
"wrapped": true | |
}, | |
"items": { | |
"$ref": "#/components/schemas/Trip" | |
} | |
} | |
} | |
}, | |
{ | |
"properties": { | |
"links": { | |
"allOf": [ | |
{ | |
"$ref": "#/components/schemas/Links-Self" | |
}, | |
{ | |
"$ref": "#/components/schemas/Links-Pagination" | |
} | |
] | |
} | |
} | |
} | |
] | |
} | |
} | |
} | |
}, | |
"400": { | |
"$ref": "#/components/responses/BadRequest" | |
}, | |
"401": { | |
"$ref": "#/components/responses/Unauthorized" | |
}, | |
"403": { | |
"$ref": "#/components/responses/Forbidden" | |
}, | |
"429": { | |
"$ref": "#/components/responses/TooManyRequests" | |
}, | |
"500": { | |
"$ref": "#/components/responses/InternalServerError" | |
} | |
} | |
} | |
}, | |
"/bookings": { | |
"get": { | |
"operationId": "get-bookings", | |
"summary": "List existing bookings", | |
"description": "Returns a list of all trip bookings by the authenticated user.", | |
"tags": [ | |
"Bookings" | |
], | |
"responses": { | |
"200": { | |
"description": "A list of bookings", | |
"headers": { | |
"RateLimit": { | |
"$ref": "#/components/headers/RateLimit" | |
} | |
}, | |
"content": { | |
"application/json": { | |
"schema": { | |
"allOf": [ | |
{ | |
"$ref": "#/components/schemas/Wrapper-Collection" | |
}, | |
{ | |
"properties": { | |
"data": { | |
"type": "array", | |
"items": { | |
"$ref": "#/components/schemas/Booking" | |
} | |
} | |
} | |
}, | |
{ | |
"properties": { | |
"links": { | |
"allOf": [ | |
{ | |
"$ref": "#/components/schemas/Links-Self" | |
}, | |
{ | |
"$ref": "#/components/schemas/Links-Pagination" | |
} | |
] | |
} | |
} | |
} | |
] | |
}, | |
"example": { | |
"data": [ | |
{ | |
"id": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e", | |
"trip_id": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e", | |
"passenger_name": "John Doe", | |
"has_bicycle": true, | |
"has_dog": true | |
}, | |
{ | |
"id": "b2e783e1-c824-4d63-b37a-d8d698862f1d", | |
"trip_id": "b2e783e1-c824-4d63-b37a-d8d698862f1d", | |
"passenger_name": "Jane Smith", | |
"has_bicycle": false, | |
"has_dog": false | |
} | |
], | |
"links": { | |
"self": "https://api.example.com/bookings", | |
"next": "https://api.example.com/bookings?page=2" | |
} | |
} | |
}, | |
"application/xml": { | |
"schema": { | |
"allOf": [ | |
{ | |
"$ref": "#/components/schemas/Wrapper-Collection" | |
}, | |
{ | |
"properties": { | |
"data": { | |
"type": "array", | |
"xml": { | |
"name": "bookings", | |
"wrapped": true | |
}, | |
"items": { | |
"$ref": "#/components/schemas/Booking" | |
} | |
} | |
} | |
}, | |
{ | |
"properties": { | |
"links": { | |
"allOf": [ | |
{ | |
"$ref": "#/components/schemas/Links-Self" | |
}, | |
{ | |
"$ref": "#/components/schemas/Links-Pagination" | |
} | |
] | |
} | |
} | |
} | |
] | |
} | |
} | |
} | |
}, | |
"400": { | |
"$ref": "#/components/responses/BadRequest" | |
}, | |
"401": { | |
"$ref": "#/components/responses/Unauthorized" | |
}, | |
"403": { | |
"$ref": "#/components/responses/Forbidden" | |
}, | |
"429": { | |
"$ref": "#/components/responses/TooManyRequests" | |
}, | |
"500": { | |
"$ref": "#/components/responses/InternalServerError" | |
} | |
} | |
}, | |
"post": { | |
"operationId": "create-booking", | |
"summary": "Create a booking", | |
"description": "A booking is a temporary hold on a trip. It is not confirmed until the payment is processed.", | |
"tags": [ | |
"Bookings" | |
], | |
"security": [ | |
{ | |
"OAuth2": [ | |
"write" | |
] | |
} | |
], | |
"requestBody": { | |
"required": true, | |
"content": { | |
"application/json": { | |
"schema": { | |
"$ref": "#/components/schemas/Booking" | |
} | |
}, | |
"application/xml": { | |
"schema": { | |
"$ref": "#/components/schemas/Booking" | |
} | |
} | |
} | |
}, | |
"responses": { | |
"201": { | |
"description": "Booking successful", | |
"content": { | |
"application/json": { | |
"schema": { | |
"allOf": [ | |
{ | |
"$ref": "#/components/schemas/Booking" | |
}, | |
{ | |
"properties": { | |
"links": { | |
"$ref": "#/components/schemas/Links-Self" | |
} | |
} | |
} | |
] | |
}, | |
"example": { | |
"id": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e", | |
"trip_id": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e", | |
"passenger_name": "John Doe", | |
"has_bicycle": true, | |
"has_dog": true, | |
"links": { | |
"self": "https://api.example.com/bookings/efdbb9d1-02c2-4bc3-afb7-6788d8782b1e" | |
} | |
} | |
}, | |
"application/xml": { | |
"schema": { | |
"allOf": [ | |
{ | |
"$ref": "#/components/schemas/Booking" | |
}, | |
{ | |
"properties": { | |
"links": { | |
"$ref": "#/components/schemas/Links-Self" | |
} | |
} | |
} | |
] | |
} | |
} | |
} | |
}, | |
"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" | |
} | |
} | |
} | |
}, | |
"/bookings/{bookingId}": { | |
"parameters": [ | |
{ | |
"name": "bookingId", | |
"in": "path", | |
"required": true, | |
"description": "The ID of the booking to retrieve.", | |
"schema": { | |
"type": "string", | |
"format": "uuid" | |
}, | |
"example": "1725ff48-ab45-4bb5-9d02-88745177dedb" | |
} | |
], | |
"get": { | |
"summary": "Get a booking", | |
"description": "Returns the details of a specific booking.", | |
"operationId": "get-booking", | |
"tags": [ | |
"Bookings" | |
], | |
"responses": { | |
"200": { | |
"description": "The booking details", | |
"headers": { | |
"RateLimit": { | |
"$ref": "#/components/headers/RateLimit" | |
} | |
}, | |
"content": { | |
"application/json": { | |
"schema": { | |
"allOf": [ | |
{ | |
"$ref": "#/components/schemas/Booking" | |
}, | |
{ | |
"properties": { | |
"links": { | |
"$ref": "#/components/schemas/Links-Self" | |
} | |
} | |
} | |
] | |
}, | |
"example": { | |
"id": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e", | |
"trip_id": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e", | |
"passenger_name": "John Doe", | |
"has_bicycle": true, | |
"has_dog": true, | |
"links": { | |
"self": "https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb" | |
} | |
} | |
}, | |
"application/xml": { | |
"schema": { | |
"allOf": [ | |
{ | |
"$ref": "#/components/schemas/Booking" | |
}, | |
{ | |
"properties": { | |
"links": { | |
"$ref": "#/components/schemas/Links-Self" | |
} | |
} | |
} | |
] | |
} | |
} | |
} | |
}, | |
"400": { | |
"$ref": "#/components/responses/BadRequest" | |
}, | |
"401": { | |
"$ref": "#/components/responses/Unauthorized" | |
}, | |
"403": { | |
"$ref": "#/components/responses/Forbidden" | |
}, | |
"404": { | |
"$ref": "#/components/responses/NotFound" | |
}, | |
"429": { | |
"$ref": "#/components/responses/TooManyRequests" | |
}, | |
"500": { | |
"$ref": "#/components/responses/InternalServerError" | |
} | |
} | |
}, | |
"delete": { | |
"summary": "Delete a booking", | |
"description": "Deletes a booking, cancelling the hold on the trip.", | |
"operationId": "delete-booking", | |
"security": [ | |
{ | |
"OAuth2": [ | |
"write" | |
] | |
} | |
], | |
"tags": [ | |
"Bookings" | |
], | |
"responses": { | |
"204": { | |
"description": "Booking deleted" | |
}, | |
"400": { | |
"$ref": "#/components/responses/BadRequest" | |
}, | |
"401": { | |
"$ref": "#/components/responses/Unauthorized" | |
}, | |
"403": { | |
"$ref": "#/components/responses/Forbidden" | |
}, | |
"404": { | |
"$ref": "#/components/responses/NotFound" | |
}, | |
"429": { | |
"$ref": "#/components/responses/TooManyRequests" | |
}, | |
"500": { | |
"$ref": "#/components/responses/InternalServerError" | |
} | |
} | |
} | |
}, | |
"/bookings/{bookingId}/payment": { | |
"parameters": [ | |
{ | |
"name": "bookingId", | |
"in": "path", | |
"required": true, | |
"description": "The ID of the booking to pay for.", | |
"schema": { | |
"type": "string", | |
"format": "uuid" | |
}, | |
"example": "1725ff48-ab45-4bb5-9d02-88745177dedb" | |
} | |
], | |
"post": { | |
"summary": "Pay for a Booking", | |
"description": "A payment is an attempt to pay for the booking, which will confirm the booking for the user and enable them to get their tickets.", | |
"operationId": "create-booking-payment", | |
"tags": [ | |
"Payments" | |
], | |
"requestBody": { | |
"required": true, | |
"content": { | |
"application/json": { | |
"schema": { | |
"$ref": "#/components/schemas/BookingPayment" | |
}, | |
"examples": { | |
"Card": { | |
"summary": "Card Payment", | |
"value": { | |
"amount": 49.99, | |
"currency": "gbp", | |
"source": { | |
"object": "card", | |
"name": "J. Doe", | |
"number": "4242424242424242", | |
"cvc": 123, | |
"exp_month": 12, | |
"exp_year": 2025, | |
"address_line1": "123 Fake Street", | |
"address_line2": "4th Floor", | |
"address_city": "London", | |
"address_country": "gb", | |
"address_post_code": "N12 9XX" | |
} | |
} | |
}, | |
"Bank": { | |
"summary": "Bank Account Payment", | |
"value": { | |
"amount": 100.5, | |
"currency": "gbp", | |
"source": { | |
"object": "bank_account", | |
"name": "J. Doe", | |
"number": "00012345", | |
"sort_code": "000123", | |
"account_type": "individual", | |
"bank_name": "Starling Bank", | |
"country": "gb" | |
} | |
} | |
} | |
} | |
} | |
} | |
}, | |
"responses": { | |
"200": { | |
"description": "Payment successful", | |
"headers": { | |
"RateLimit": { | |
"$ref": "#/components/headers/RateLimit" | |
} | |
}, | |
"content": { | |
"application/json": { | |
"schema": { | |
"allOf": [ | |
{ | |
"$ref": "#/components/schemas/BookingPayment" | |
}, | |
{ | |
"properties": { | |
"links": { | |
"$ref": "#/components/schemas/Links-Booking" | |
} | |
} | |
} | |
] | |
}, | |
"examples": { | |
"Card": { | |
"summary": "Card Payment", | |
"value": { | |
"id": "2e3b4f5a-6b7c-8d9e-0f1a-2b3c4d5e6f7a", | |
"amount": 49.99, | |
"currency": "gbp", | |
"source": { | |
"object": "card", | |
"name": "J. Doe", | |
"number": "************4242", | |
"cvc": 123, | |
"exp_month": 12, | |
"exp_year": 2025, | |
"address_country": "gb", | |
"address_post_code": "N12 9XX" | |
}, | |
"status": "succeeded", | |
"links": { | |
"booking": "https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb/payment" | |
} | |
} | |
}, | |
"Bank": { | |
"summary": "Bank Account Payment", | |
"value": { | |
"id": "2e3b4f5a-6b7c-8d9e-0f1a-2b3c4d5e6f7a", | |
"amount": 100.5, | |
"currency": "gbp", | |
"source": { | |
"object": "bank_account", | |
"name": "J. Doe", | |
"account_type": "individual", | |
"number": "*********2345", | |
"sort_code": "000123", | |
"bank_name": "Starling Bank", | |
"country": "gb" | |
}, | |
"status": "succeeded", | |
"links": { | |
"booking": "https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb" | |
} | |
} | |
} | |
} | |
} | |
} | |
}, | |
"400": { | |
"$ref": "#/components/responses/BadRequest" | |
}, | |
"401": { | |
"$ref": "#/components/responses/Unauthorized" | |
}, | |
"403": { | |
"$ref": "#/components/responses/Forbidden" | |
}, | |
"429": { | |
"$ref": "#/components/responses/TooManyRequests" | |
}, | |
"500": { | |
"$ref": "#/components/responses/InternalServerError" | |
} | |
} | |
} | |
} | |
}, | |
"webhooks": { | |
"newBooking": { | |
"post": { | |
"operationId": "new-booking", | |
"summary": "New Booking", | |
"description": "Subscribe to new bookings being created, to update integrations for your users. Related data is available via the links provided in the request.\n", | |
"tags": [ | |
"Bookings" | |
], | |
"requestBody": { | |
"content": { | |
"application/json": { | |
"schema": { | |
"allOf": [ | |
{ | |
"$ref": "#/components/schemas/Booking" | |
}, | |
{ | |
"properties": { | |
"links": { | |
"allOf": [ | |
{ | |
"$ref": "#/components/schemas/Links-Self" | |
}, | |
{ | |
"$ref": "#/components/schemas/Links-Pagination" | |
} | |
] | |
} | |
} | |
} | |
] | |
}, | |
"example": { | |
"id": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e", | |
"trip_id": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e", | |
"passenger_name": "John Doe", | |
"has_bicycle": true, | |
"has_dog": true, | |
"links": { | |
"self": "https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb" | |
} | |
} | |
} | |
} | |
}, | |
"responses": { | |
"200": { | |
"description": "Return a 200 status to indicate that the data was received successfully." | |
} | |
} | |
} | |
} | |
}, | |
"components": { | |
"securitySchemes": { | |
"OAuth2": { | |
"type": "oauth2", | |
"description": "OAuth 2.0 authorization code following RFC8725 best practices.", | |
"flows": { | |
"authorizationCode": { | |
"authorizationUrl": "https://example.com/oauth/authorize", | |
"tokenUrl": "https://example.com/oauth/token", | |
"scopes": { | |
"read": "Read access", | |
"write": "Write access" | |
} | |
} | |
} | |
} | |
}, | |
"schemas": { | |
"Station": { | |
"type": "object", | |
"xml": { | |
"name": "station" | |
}, | |
"required": [ | |
"id", | |
"name", | |
"address", | |
"country_code" | |
], | |
"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" | |
] | |
}, | |
"timezone": { | |
"type": "string", | |
"description": "The timezone of the station in the [IANA Time Zone Database format](https://www.iana.org/time-zones).", | |
"examples": [ | |
"Europe/Berlin", | |
"Europe/Paris" | |
] | |
} | |
} | |
}, | |
"Links-Self": { | |
"type": "object", | |
"properties": { | |
"self": { | |
"type": "string", | |
"format": "uri" | |
} | |
} | |
}, | |
"Links-Pagination": { | |
"type": "object", | |
"properties": { | |
"next": { | |
"type": "string", | |
"format": "uri" | |
}, | |
"prev": { | |
"type": "string", | |
"format": "uri" | |
} | |
} | |
}, | |
"Problem": { | |
"xml": { | |
"name": "problem", | |
"namespace": "urn:ietf:rfc:7807" | |
}, | |
"properties": { | |
"type": { | |
"type": "string", | |
"description": "A URI reference that identifies the problem type", | |
"example": "https://example.com/probs/out-of-credit" | |
}, | |
"title": { | |
"type": "string", | |
"description": "A short, human-readable summary of the problem type", | |
"example": "You do not have enough credit." | |
}, | |
"detail": { | |
"type": "string", | |
"description": "A human-readable explanation specific to this occurrence of the problem", | |
"example": "Your current balance is 30, but that costs 50." | |
}, | |
"instance": { | |
"type": "string", | |
"description": "A URI reference that identifies the specific occurrence of the problem", | |
"example": "/account/12345/msgs/abc" | |
}, | |
"status": { | |
"type": "integer", | |
"description": "The HTTP status code", | |
"example": 400 | |
} | |
} | |
}, | |
"Trip": { | |
"type": "object", | |
"xml": { | |
"name": "trip" | |
}, | |
"properties": { | |
"id": { | |
"type": "string", | |
"format": "uuid", | |
"description": "Unique identifier for the trip", | |
"examples": [ | |
"4f4e4e1-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" | |
] | |
}, | |
"operator": { | |
"type": "string", | |
"description": "The name of the operator of the trip", | |
"examples": [ | |
"Deutsche Bahn", | |
"SNCF" | |
] | |
}, | |
"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" | |
} | |
} | |
}, | |
"Booking": { | |
"type": "object", | |
"xml": { | |
"name": "booking" | |
}, | |
"properties": { | |
"id": { | |
"type": "string", | |
"format": "uuid", | |
"description": "Unique identifier for the booking", | |
"readOnly": true, | |
"examples": [ | |
"3f3e3e1-c824-4d63-b37a-d8d698862f1d" | |
] | |
}, | |
"trip_id": { | |
"type": "string", | |
"format": "uuid", | |
"description": "Identifier of the booked trip", | |
"examples": [ | |
"4f4e4e1-c824-4d63-b37a-d8d698862f1d" | |
] | |
}, | |
"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." | |
} | |
} | |
}, | |
"Wrapper-Collection": { | |
"description": "This is a generic request/response wrapper which contains both data and links which serve as hypermedia controls (HATEOAS).", | |
"type": "object", | |
"properties": { | |
"data": { | |
"description": "The wrapper for a collection is an array of objects.", | |
"type": "array", | |
"items": { | |
"type": "object" | |
} | |
}, | |
"links": { | |
"description": "A set of hypermedia links which serve as controls for the client.", | |
"type": "object", | |
"readOnly": true | |
} | |
}, | |
"xml": { | |
"name": "data" | |
} | |
}, | |
"BookingPayment": { | |
"type": "object", | |
"properties": { | |
"id": { | |
"description": "Unique identifier for the payment. This will be a unique identifier for the payment, and is used to reference the payment in other objects.", | |
"type": "string", | |
"format": "uuid", | |
"readOnly": true | |
}, | |
"amount": { | |
"description": "Amount intended to be collected by this payment. A positive decimal figure describing the amount to be collected.", | |
"type": "number", | |
"exclusiveMinimum": 0, | |
"examples": [ | |
49.99 | |
] | |
}, | |
"currency": { | |
"description": "Three-letter [ISO currency code](https://www.iso.org/iso-4217-currency-codes.html), in lowercase.", | |
"type": "string", | |
"enum": [ | |
"bam", | |
"bgn", | |
"chf", | |
"eur", | |
"gbp", | |
"nok", | |
"sek", | |
"try" | |
] | |
}, | |
"source": { | |
"unevaluatedProperties": false, | |
"description": "The payment source to take the payment from. This can be a card or a bank account. Some of these properties will be hidden on read to protect PII leaking.", | |
"anyOf": [ | |
{ | |
"title": "Card", | |
"description": "A card (debit or credit) to take payment from.", | |
"properties": { | |
"object": { | |
"type": "string", | |
"const": "card" | |
}, | |
"name": { | |
"type": "string", | |
"description": "Cardholder's full name as it appears on the card.", | |
"examples": [ | |
"Francis Bourgeois" | |
] | |
}, | |
"number": { | |
"type": "string", | |
"description": "The card number, as a string without any separators. On read all but the last four digits will be masked for security.", | |
"examples": [ | |
"4242424242424242" | |
] | |
}, | |
"cvc": { | |
"type": "integer", | |
"description": "Card security code, 3 or 4 digits usually found on the back of the card.", | |
"minLength": 3, | |
"maxLength": 4, | |
"writeOnly": true, | |
"example": 123 | |
}, | |
"exp_month": { | |
"type": "integer", | |
"format": "int64", | |
"description": "Two-digit number representing the card's expiration month.", | |
"examples": [ | |
12 | |
] | |
}, | |
"exp_year": { | |
"type": "integer", | |
"format": "int64", | |
"description": "Four-digit number representing the card's expiration year.", | |
"examples": [ | |
2025 | |
] | |
}, | |
"address_line1": { | |
"type": "string", | |
"writeOnly": true | |
}, | |
"address_line2": { | |
"type": "string", | |
"writeOnly": true | |
}, | |
"address_city": { | |
"type": "string" | |
}, | |
"address_country": { | |
"type": "string" | |
}, | |
"address_post_code": { | |
"type": "string" | |
} | |
}, | |
"required": [ | |
"name", | |
"number", | |
"cvc", | |
"exp_month", | |
"exp_year", | |
"address_country" | |
] | |
}, | |
{ | |
"title": "Bank Account", | |
"description": "A bank account to take payment from. Must be able to make payments in the currency specified in the payment.", | |
"type": "object", | |
"properties": { | |
"object": { | |
"const": "bank_account", | |
"type": "string" | |
}, | |
"name": { | |
"type": "string" | |
}, | |
"number": { | |
"type": "string", | |
"description": "The account number for the bank account, in string form. Must be a current account." | |
}, | |
"sort_code": { | |
"type": "string", | |
"description": "The sort code for the bank account, in string form. Must be a six-digit number." | |
}, | |
"account_type": { | |
"enum": [ | |
"individual", | |
"company" | |
], | |
"type": "string", | |
"description": "The type of entity that holds the account. This can be either `individual` or `company`." | |
}, | |
"bank_name": { | |
"type": "string", | |
"description": "The name of the bank associated with the routing number.", | |
"examples": [ | |
"Starling Bank" | |
] | |
}, | |
"country": { | |
"type": "string", | |
"description": "Two-letter country code (ISO 3166-1 alpha-2)." | |
} | |
}, | |
"required": [ | |
"name", | |
"number", | |
"account_type", | |
"bank_name", | |
"country" | |
] | |
} | |
] | |
}, | |
"status": { | |
"description": "The status of the payment, one of `pending`, `succeeded`, or `failed`.", | |
"type": "string", | |
"enum": [ | |
"pending", | |
"succeeded", | |
"failed" | |
], | |
"readOnly": true | |
} | |
} | |
}, | |
"Links-Booking": { | |
"type": "object", | |
"properties": { | |
"booking": { | |
"type": "string", | |
"format": "uri", | |
"examples": [ | |
"https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb" | |
] | |
} | |
} | |
} | |
}, | |
"headers": { | |
"RateLimit": { | |
"description": "The RateLimit header communicates quota policies. It contains a `limit` to\nconvey the expiring limit, `remaining` to convey the remaining quota units,\nand `reset` to convey the time window reset time.\n", | |
"schema": { | |
"type": "string", | |
"examples": [ | |
"limit=10, remaining=0, reset=10" | |
] | |
} | |
}, | |
"Retry-After": { | |
"description": "The Retry-After header indicates how long the user agent should wait before making a follow-up request. \nThe value is in seconds and can be an integer or a date in the future. \nIf the value is an integer, it indicates the number of seconds to wait. \nIf the value is a date, it indicates the time at which the user agent should make a follow-up request. \n", | |
"schema": { | |
"type": "string" | |
}, | |
"examples": { | |
"integer": { | |
"value": "120", | |
"summary": "Retry after 120 seconds" | |
}, | |
"date": { | |
"value": "Fri, 31 Dec 2021 23:59:59 GMT", | |
"summary": "Retry after the specified date" | |
} | |
} | |
} | |
}, | |
"responses": { | |
"BadRequest": { | |
"description": "Bad Request", | |
"headers": { | |
"RateLimit": { | |
"$ref": "#/components/headers/RateLimit" | |
} | |
}, | |
"content": { | |
"application/problem+json": { | |
"schema": { | |
"$ref": "#/components/schemas/Problem" | |
}, | |
"example": { | |
"type": "https://example.com/errors/bad-request", | |
"title": "Bad Request", | |
"status": 400, | |
"detail": "The request is invalid or missing required parameters." | |
} | |
}, | |
"application/problem+xml": { | |
"schema": { | |
"$ref": "#/components/schemas/Problem" | |
}, | |
"example": { | |
"type": "https://example.com/errors/bad-request", | |
"title": "Bad Request", | |
"status": 400, | |
"detail": "The request is invalid or missing required parameters." | |
} | |
} | |
} | |
}, | |
"Conflict": { | |
"description": "Conflict", | |
"headers": { | |
"RateLimit": { | |
"$ref": "#/components/headers/RateLimit" | |
} | |
}, | |
"content": { | |
"application/problem+json": { | |
"schema": { | |
"$ref": "#/components/schemas/Problem" | |
}, | |
"example": { | |
"type": "https://example.com/errors/conflict", | |
"title": "Conflict", | |
"status": 409, | |
"detail": "There is a conflict with an existing resource." | |
} | |
}, | |
"application/problem+xml": { | |
"schema": { | |
"$ref": "#/components/schemas/Problem" | |
}, | |
"example": { | |
"type": "https://example.com/errors/conflict", | |
"title": "Conflict", | |
"status": 409, | |
"detail": "There is a conflict with an existing resource." | |
} | |
} | |
} | |
}, | |
"Forbidden": { | |
"description": "Forbidden", | |
"headers": { | |
"RateLimit": { | |
"$ref": "#/components/headers/RateLimit" | |
} | |
}, | |
"content": { | |
"application/problem+json": { | |
"schema": { | |
"$ref": "#/components/schemas/Problem" | |
}, | |
"example": { | |
"type": "https://example.com/errors/forbidden", | |
"title": "Forbidden", | |
"status": 403, | |
"detail": "Access is forbidden with the provided credentials." | |
} | |
}, | |
"application/problem+xml": { | |
"schema": { | |
"$ref": "#/components/schemas/Problem" | |
}, | |
"example": { | |
"type": "https://example.com/errors/forbidden", | |
"title": "Forbidden", | |
"status": 403, | |
"detail": "Access is forbidden with the provided credentials." | |
} | |
} | |
} | |
}, | |
"InternalServerError": { | |
"description": "Internal Server Error", | |
"headers": { | |
"RateLimit": { | |
"$ref": "#/components/headers/RateLimit" | |
} | |
}, | |
"content": { | |
"application/problem+json": { | |
"schema": { | |
"$ref": "#/components/schemas/Problem" | |
}, | |
"example": { | |
"type": "https://example.com/errors/internal-server-error", | |
"title": "Internal Server Error", | |
"status": 500, | |
"detail": "An unexpected error occurred." | |
} | |
}, | |
"application/problem+xml": { | |
"schema": { | |
"$ref": "#/components/schemas/Problem" | |
}, | |
"example": { | |
"type": "https://example.com/errors/internal-server-error", | |
"title": "Internal Server Error", | |
"status": 500, | |
"detail": "An unexpected error occurred." | |
} | |
} | |
} | |
}, | |
"NotFound": { | |
"description": "Not Found", | |
"headers": { | |
"RateLimit": { | |
"$ref": "#/components/headers/RateLimit" | |
} | |
}, | |
"content": { | |
"application/problem+json": { | |
"schema": { | |
"$ref": "#/components/schemas/Problem" | |
}, | |
"example": { | |
"type": "https://example.com/errors/not-found", | |
"title": "Not Found", | |
"status": 404, | |
"detail": "The requested resource was not found." | |
} | |
}, | |
"application/problem+xml": { | |
"schema": { | |
"$ref": "#/components/schemas/Problem" | |
}, | |
"example": { | |
"type": "https://example.com/errors/not-found", | |
"title": "Not Found", | |
"status": 404, | |
"detail": "The requested resource was not found." | |
} | |
} | |
} | |
}, | |
"TooManyRequests": { | |
"description": "Too Many Requests", | |
"headers": { | |
"RateLimit": { | |
"$ref": "#/components/headers/RateLimit" | |
}, | |
"Retry-After": { | |
"$ref": "#/components/headers/Retry-After" | |
} | |
}, | |
"content": { | |
"application/problem+json": { | |
"schema": { | |
"$ref": "#/components/schemas/Problem" | |
}, | |
"example": { | |
"type": "https://example.com/errors/too-many-requests", | |
"title": "Too Many Requests", | |
"status": 429, | |
"detail": "You have exceeded the rate limit." | |
} | |
}, | |
"application/problem+xml": { | |
"schema": { | |
"$ref": "#/components/schemas/Problem" | |
}, | |
"example": { | |
"type": "https://example.com/errors/too-many-requests", | |
"title": "Too Many Requests", | |
"status": 429, | |
"detail": "You have exceeded the rate limit." | |
} | |
} | |
} | |
}, | |
"Unauthorized": { | |
"description": "Unauthorized", | |
"headers": { | |
"RateLimit": { | |
"$ref": "#/components/headers/RateLimit" | |
} | |
}, | |
"content": { | |
"application/problem+json": { | |
"schema": { | |
"$ref": "#/components/schemas/Problem" | |
}, | |
"example": { | |
"type": "https://example.com/errors/unauthorized", | |
"title": "Unauthorized", | |
"status": 401, | |
"detail": "You do not have the necessary permissions." | |
} | |
}, | |
"application/problem+xml": { | |
"schema": { | |
"$ref": "#/components/schemas/Problem" | |
}, | |
"example": { | |
"type": "https://example.com/errors/unauthorized", | |
"title": "Unauthorized", | |
"status": 401, | |
"detail": "You do not have the necessary permissions." | |
} | |
} | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment