Skip to content

Instantly share code, notes, and snippets.

@joshtwist
Created September 3, 2024 14:49
Show Gist options
  • Save joshtwist/ef5a8a1952e515be2583a9115691e9ca to your computer and use it in GitHub Desktop.
Save joshtwist/ef5a8a1952e515be2583a9115691e9ca to your computer and use it in GitHub Desktop.
{
"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": "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://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