{
  "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[![Run In Postman](https://run.pstmn.io/button.svg =128pxx32px)](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.2.0",
    "contact": {
      "name": "Train Support",
      "url": "https://example.com/support",
      "email": "support@example.com"
    },
    "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://try.microcks.io/rest/Train+Travel+API/1.0.0",
      "description": "Mock Server",
      "x-internal": false
    },
    {
      "url": "https://api.example.com",
      "description": "Production",
      "x-internal": false
    }
  ],
  "x-speakeasy-retries": {
    "strategy": "backoff",
    "backoff": {
      "initialInterval": 500,
      "maxInterval": 60000,
      "maxElapsedTime": 3600000,
      "exponent": 1.5
    },
    "statusCodes": [
      "5XX"
    ],
    "retryConnectionErrors": true
  },
  "security": [
    {
      "OAuth2": [
        "read"
      ]
    }
  ],
  "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": [
          {
            "$ref": "#/components/parameters/page"
          },
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "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"
              ]
            },
            "examples": {
              "berlin_station": {
                "value": "Berlin"
              },
              "milano_station": {
                "value": "Milano"
              },
              "paris_station": {
                "value": "Paris"
              }
            }
          },
          {
            "name": "country",
            "in": "query",
            "description": "Filter stations by country code",
            "required": false,
            "schema": {
              "type": "string",
              "format": "iso-country-code"
            },
            "example": "DE"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/Cache-Control"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Wrapper-Collection"
                    },
                    {
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Station"
                          }
                        }
                      }
                    },
                    {
                      "properties": {
                        "links": {
                          "allOf": [
                            {
                              "$ref": "#/components/schemas/Links-Self"
                            },
                            {
                              "$ref": "#/components/schemas/Links-Pagination"
                            }
                          ]
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "stations": {
                    "summary": "A list of train stations",
                    "value": {
                      "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"
                      }
                    }
                  },
                  "berlin_station": {
                    "value": {
                      "data": [
                        {
                          "id": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e",
                          "name": "Berlin Hauptbahnhof",
                          "address": "Invalidenstraße 10557 Berlin, Germany",
                          "country_code": "DE",
                          "timezone": "Europe/Berlin"
                        }
                      ]
                    }
                  },
                  "paris_station": {
                    "value": {
                      "data": [
                        {
                          "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"
                        }
                      ]
                    }
                  }
                }
              },
              "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": [
          {
            "$ref": "#/components/parameters/page"
          },
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "name": "origin",
            "in": "query",
            "description": "The ID of the origin station",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "examples": {
              "trips": {
                "value": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e"
              }
            }
          },
          {
            "name": "destination",
            "in": "query",
            "description": "The ID of the destination station",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "examples": {
              "trips": {
                "value": "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"
            },
            "examples": {
              "trips": {
                "value": "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": {
              "Cache-Control": {
                "$ref": "#/components/headers/Cache-Control"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Wrapper-Collection"
                    },
                    {
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "allOf": [
                              {
                                "$ref": "#/components/schemas/Trip"
                              },
                              {
                                "$ref": "#/components/schemas/Links-Origin"
                              },
                              {
                                "$ref": "#/components/schemas/Links-Destination"
                              }
                            ]
                          }
                        }
                      }
                    },
                    {
                      "properties": {
                        "links": {
                          "allOf": [
                            {
                              "$ref": "#/components/schemas/Links-Self"
                            },
                            {
                              "$ref": "#/components/schemas/Links-Pagination"
                            }
                          ]
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "trips": {
                    "summary": "A list of available train trips",
                    "value": {
                      "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"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/page"
          },
          {
            "$ref": "#/components/parameters/limit"
          }
        ],
        "responses": {
          "200": {
            "description": "A list of bookings",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/Cache-Control"
              },
              "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"
                            }
                          ]
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "bookings": {
                    "summary": "A list of bookings",
                    "value": {
                      "data": [
                        {
                          "id": "bfc5af2c-f477-43c4-8bdf-a00bdb939d65",
                          "trip_id": "4d67459c-af07-40bb-bb12-178dbb88e09f",
                          "passenger_name": "John Doe",
                          "has_bicycle": true,
                          "has_dog": true
                        },
                        {
                          "id": "1725ff48-ab45-4bb5-9d02-88745177dedb",
                          "trip_id": "4d67459c-af07-40bb-bb12-178dbb88e09f",
                          "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"
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "new_booking": {
                    "summary": "New Booking",
                    "value": "{\n  \"id\": \"{{ uuid() > put(bookingId) }}\",\n  \"trip_id\": \"{{ request.body/trip_id }}\",\n  \"passenger_name\": \"{{ request.body/passenger_name }}\",\n  \"has_bicycle\": {{ request.body/has_bicycle }},\n  \"has_dog\": {{ request.body/has_dog }},\n  \"links\": {\n    \"self\": \"https://api.example.com/bookings/{{ bookingId }}\"\n  }\n}"
                  }
                }
              },
              "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"
          },
          "examples": {
            "booking_1725ff48-ab45-4bb5-9d02-88745177dedb": {
              "value": "1725ff48-ab45-4bb5-9d02-88745177dedb"
            },
            "booking_bfc5af2c-f477-43c4-8bdf-a00bdb939d65": {
              "value": "bfc5af2c-f477-43c4-8bdf-a00bdb939d65"
            }
          }
        }
      ],
      "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": {
              "Cache-Control": {
                "$ref": "#/components/headers/Cache-Control"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Booking"
                    },
                    {
                      "properties": {
                        "links": {
                          "$ref": "#/components/schemas/Links-Self"
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "booking_1725ff48-ab45-4bb5-9d02-88745177dedb": {
                    "summary": "John Doe",
                    "value": {
                      "id": "1725ff48-ab45-4bb5-9d02-88745177dedb",
                      "trip_id": "ea399ba1-6d95-433f-92d1-83f67b775594",
                      "passenger_name": "John Doe",
                      "has_bicycle": true,
                      "has_dog": true,
                      "links": {
                        "self": "https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb"
                      }
                    }
                  },
                  "booking_bfc5af2c-f477-43c4-8bdf-a00bdb939d65": {
                    "summary": "Billy Bikeless",
                    "value": {
                      "id": "bfc5af2c-f477-43c4-8bdf-a00bdb939d65",
                      "trip_id": "ea399ba1-6d95-433f-92d1-83f67b775594",
                      "passenger_name": "Billy Bikeless",
                      "has_bicycle": false,
                      "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"
          },
          "examples": {
            "booking_1725ff48-ab45-4bb5-9d02-88745177dedb": {
              "summary": "Payment by Card",
              "value": "1725ff48-ab45-4bb5-9d02-88745177dedb"
            },
            "booking_bfc5af2c-f477-43c4-8bdf-a00bdb939d65": {
              "summary": "Payment by Bank Transfer",
              "value": "bfc5af2c-f477-43c4-8bdf-a00bdb939d65"
            }
          }
        }
      ],
      "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": {
                "booking_1725ff48-ab45-4bb5-9d02-88745177dedb": {
                  "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"
                    }
                  }
                },
                "booking_bfc5af2c-f477-43c4-8bdf-a00bdb939d65": {
                  "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": {
              "Cache-Control": {
                "$ref": "#/components/headers/Cache-Control"
              },
              "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": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Booking"
                  },
                  {
                    "properties": {
                      "links": {
                        "allOf": [
                          {
                            "$ref": "#/components/schemas/Links-Self"
                          },
                          {
                            "$ref": "#/components/schemas/Links-Pagination"
                          }
                        ]
                      }
                    }
                  }
                ]
              },
              "examples": {
                "new_booking": {
                  "summary": "New Booking",
                  "value": {
                    "id": "1725ff48-ab45-4bb5-9d02-88745177dedb",
                    "trip_id": "ea399ba1-6d95-433f-92d1-83f67b775594",
                    "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": {
    "parameters": {
      "page": {
        "name": "page",
        "in": "query",
        "description": "The page number to return",
        "required": false,
        "schema": {
          "type": "integer",
          "minimum": 1,
          "default": 1
        },
        "example": 1
      },
      "limit": {
        "name": "limit",
        "in": "query",
        "description": "The number of items to return per page",
        "required": false,
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100,
          "default": 10
        },
        "example": 10
      }
    },
    "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-Destination": {
        "type": "object",
        "description": "The link to the destination station resource.",
        "properties": {
          "self": {
            "type": "string",
            "format": "uri"
          }
        }
      },
      "Links-Origin": {
        "type": "object",
        "description": "The link to the origin station resource.",
        "properties": {
          "self": {
            "type": "string",
            "format": "uri"
          }
        }
      },
      "Links-Pagination": {
        "type": "object",
        "properties": {
          "next": {
            "type": "string",
            "format": "uri"
          },
          "prev": {
            "type": "string",
            "format": "uri"
          }
        }
      },
      "Problem": {
        "type": "object",
        "xml": {
          "name": "problem",
          "namespace": "urn:ietf:rfc:7807"
        },
        "properties": {
          "type": {
            "type": "string",
            "description": "A URI reference that identifies the problem type",
            "examples": [
              "https://example.com/probs/out-of-credit"
            ]
          },
          "title": {
            "type": "string",
            "description": "A short, human-readable summary of the problem type",
            "examples": [
              "You do not have enough credit."
            ]
          },
          "detail": {
            "type": "string",
            "description": "A human-readable explanation specific to this occurrence of the problem",
            "examples": [
              "Your current balance is 30, but that costs 50."
            ]
          },
          "instance": {
            "type": "string",
            "description": "A URI reference that identifies the specific occurrence of the problem",
            "examples": [
              "/account/12345/msgs/abc"
            ]
          },
          "status": {
            "type": "integer",
            "description": "The HTTP status code",
            "examples": [
              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": [
              "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e",
              "b2e783e1-c824-4d63-b37a-d8d698862f1d"
            ]
          },
          "destination": {
            "type": "string",
            "description": "The destination station of the trip",
            "examples": [
              "b2e783e1-c824-4d63-b37a-d8d698862f1d",
              "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e"
            ]
          },
          "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.",
            "oneOf": [
              {
                "title": "Card",
                "description": "A card (debit or credit) to take payment from.",
                "type": "object",
                "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": "string",
                    "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": {
      "Cache-Control": {
        "description": "The Cache-Control header communicates directives for caching mechanisms in both requests and responses. \nIt is used to specify the caching directives in responses to prevent caches from storing sensitive information.\n",
        "schema": {
          "type": "string",
          "description": "A comma-separated list of directives as defined in [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111.html).",
          "examples": [
            "max-age=3600",
            "max-age=604800, public",
            "no-store",
            "no-cache",
            "private"
          ]
        }
      },
      "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."
            }
          }
        }
      }
    }
  }
}