From 5ce13ac3e8fcfdd03b053fb8e8d5a36a7686f71e Mon Sep 17 00:00:00 2001
From: Phil Sturgeon <67381+philsturgeon@users.noreply.github.com>
Date: Wed, 26 Jun 2024 13:04:59 +0100
Subject: [PATCH 01/13] getting examples working with microcks
---
openapi.yaml | 182 +++++++++++++++++++++++++++++----------------------
1 file changed, 104 insertions(+), 78 deletions(-)
diff --git a/openapi.yaml b/openapi.yaml
index 95bacc6..f3653b7 100644
--- a/openapi.yaml
+++ b/openapi.yaml
@@ -122,22 +122,25 @@ paths:
allOf:
- $ref: '#/components/schemas/Links-Self'
- $ref: '#/components/schemas/Links-Pagination'
- 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
+ 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
application/xml:
schema:
allOf:
@@ -239,29 +242,32 @@ paths:
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
+ 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:
@@ -322,21 +328,24 @@ paths:
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
+ examples:
+ Bookings:
+ summary: A list of bookings
+ value:
+ 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:
@@ -395,14 +404,21 @@ paths:
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
+ examples:
+ new_booking:
+ summary: New Booking
+ value: |-
+ {
+ "id": "{{ uuid() }}",
+ "trip_id": "{{ request.body/trip_id }}",
+ "passenger_name": "{{ request.body/passenger_name }}",
+ "has_bicycle": {{ request.body/has_bicycle }},
+ "has_dog": {{ request.body/has_dog }},
+ "links": {
+ "self": "https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb"
+ }
+ }
+
application/xml:
schema:
allOf:
@@ -455,14 +471,17 @@ paths:
- 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
+ examples:
+ booking_efdbb9d1-02c2-4bc3-afb7-6788d8782b1e:
+ summary: Booking
+ value:
+ 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:
@@ -494,6 +513,10 @@ paths:
responses:
'204':
description: Booking deleted
+ examples:
+ BookingDeleted:
+ summary: Booking Deleted
+ value: ''
'400':
$ref: '#/components/responses/BadRequest'
'401':
@@ -642,14 +665,17 @@ webhooks:
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
+ examples:
+ new_booking:
+ summary: New Booking
+ value:
+ 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.
From 5ae670f24fc95c93cebea5bacd661bef581fa17e Mon Sep 17 00:00:00 2001
From: Phil Sturgeon <67381+philsturgeon@users.noreply.github.com>
Date: Sun, 30 Jun 2024 13:47:33 +0100
Subject: [PATCH 02/13] chore: add microcks spectral rulset
This will help make sure the OpenAPI is working well within Microcks.
---
.spectral.yaml | 15 ++++-----------
1 file changed, 4 insertions(+), 11 deletions(-)
diff --git a/.spectral.yaml b/.spectral.yaml
index f3ab72e..423215e 100644
--- a/.spectral.yaml
+++ b/.spectral.yaml
@@ -1,12 +1,5 @@
extends:
-# - "spectral:oas"
-- "spectral:arazzo"
-# - "@stoplight/spectral-owasp-ruleset"
-# - "@apisyouwonthate/style-guide""
-
-# rules:
-# owasp:api4:2019-array-limit: false
-# owasp:api4:2019-string-limit: false
-# owasp:api4:2019-string-restricted: false
-# owasp:api4:2019-integer-limit: false
-# owasp:api4:2019-integer-format: false
+- "spectral:oas"
+- "@stoplight/spectral-owasp-ruleset"
+# - "@apisyouwonthate/style-guide"
+- "@microcks/spectral-ruleset"
From 74a18cfaf06fb0883b4099b097d4bb843fa5dddb Mon Sep 17 00:00:00 2001
From: Phil Sturgeon <67381+philsturgeon@users.noreply.github.com>
Date: Sun, 30 Jun 2024 13:47:56 +0100
Subject: [PATCH 03/13] feat: mark production as not internal
---
openapi.yaml | 1 -
1 file changed, 1 deletion(-)
diff --git a/openapi.yaml b/openapi.yaml
index f3653b7..282f3fe 100644
--- a/openapi.yaml
+++ b/openapi.yaml
@@ -25,7 +25,6 @@ servers:
- url: https://api.example.com
description: Production
x-internal: false
-
- url: https://mocks.example.com/rest
description: Mock Server
x-internal: false
From 2836d9e292c42bebab68d6bcdc313b903f555485 Mon Sep 17 00:00:00 2001
From: Phil Sturgeon <67381+philsturgeon@users.noreply.github.com>
Date: Sun, 30 Jun 2024 13:48:49 +0100
Subject: [PATCH 04/13] feat: name more examples in pairs for microcks
---
openapi.yaml | 46 ++++++++++++++++++++++++++++++----------------
1 file changed, 30 insertions(+), 16 deletions(-)
diff --git a/openapi.yaml b/openapi.yaml
index 282f3fe..415d05c 100644
--- a/openapi.yaml
+++ b/openapi.yaml
@@ -122,7 +122,7 @@ paths:
- $ref: '#/components/schemas/Links-Self'
- $ref: '#/components/schemas/Links-Pagination'
examples:
- Stations:
+ stations:
summary: A list of train stations
value:
data:
@@ -195,7 +195,9 @@ paths:
schema:
type: string
format: uuid
- example: b2e783e1-c824-4d63-b37a-d8d698862f1d
+ 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.
@@ -203,7 +205,9 @@ paths:
schema:
type: string
format: date-time
- example: '2024-02-01T09:00:00Z'
+ examples:
+ trips:
+ value: '2024-02-01T09:00:00Z'
- name: bicycles
in: query
description: Only return trips where bicycles are known to be allowed
@@ -242,7 +246,7 @@ paths:
- $ref: '#/components/schemas/Links-Self'
- $ref: '#/components/schemas/Links-Pagination'
examples:
- Trips:
+ trips:
summary: A list of available train trips
value:
data:
@@ -332,12 +336,12 @@ paths:
summary: A list of bookings
value:
data:
- - id: efdbb9d1-02c2-4bc3-afb7-6788d8782b1e
+ - id: bfc5af2c-f477-43c4-8bdf-a00bdb939d65
trip_id: efdbb9d1-02c2-4bc3-afb7-6788d8782b1e
passenger_name: John Doe
has_bicycle: true
has_dog: true
- - id: b2e783e1-c824-4d63-b37a-d8d698862f1d
+ - id: 1725ff48-ab45-4bb5-9d02-88745177dedb
trip_id: b2e783e1-c824-4d63-b37a-d8d698862f1d
passenger_name: Jane Smith
has_bicycle: false
@@ -408,13 +412,13 @@ paths:
summary: New Booking
value: |-
{
- "id": "{{ uuid() }}",
+ "id": "{{ uuid() > put(bookingId) }}",
"trip_id": "{{ request.body/trip_id }}",
"passenger_name": "{{ request.body/passenger_name }}",
"has_bicycle": {{ request.body/has_bicycle }},
"has_dog": {{ request.body/has_dog }},
"links": {
- "self": "https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb"
+ "self": "https://api.example.com/bookings/{{ bookingId }}"
}
}
@@ -447,7 +451,11 @@ paths:
schema:
type: string
format: uuid
- example: 1725ff48-ab45-4bb5-9d02-88745177dedb
+ 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.
@@ -471,16 +479,26 @@ paths:
links:
$ref: '#/components/schemas/Links-Self'
examples:
- booking_efdbb9d1-02c2-4bc3-afb7-6788d8782b1e:
- summary: Booking
+ booking_1725ff48-ab45-4bb5-9d02-88745177dedb:
+ summary: John Doe
value:
- id: efdbb9d1-02c2-4bc3-afb7-6788d8782b1e
+ id: 1725ff48-ab45-4bb5-9d02-88745177dedb
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
+ booking_bfc5af2c-f477-43c4-8bdf-a00bdb939d65:
+ summary: Billy Bikeless
+ value:
+ id: bfc5af2c-f477-43c4-8bdf-a00bdb939d65
+ trip_id: efdbb9d1-02c2-4bc3-afb7-6788d8782b1e
+ 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:
@@ -512,10 +530,6 @@ paths:
responses:
'204':
description: Booking deleted
- examples:
- BookingDeleted:
- summary: Booking Deleted
- value: ''
'400':
$ref: '#/components/responses/BadRequest'
'401':
From 45d3e6581052c38959e5ed0beae165840dafce02 Mon Sep 17 00:00:00 2001
From: Phil Sturgeon <67381+philsturgeon@users.noreply.github.com>
Date: Tue, 16 Jul 2024 10:22:30 +0100
Subject: [PATCH 05/13] added mock server to servers
---
openapi.yaml | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/openapi.yaml b/openapi.yaml
index 415d05c..e47d4eb 100644
--- a/openapi.yaml
+++ b/openapi.yaml
@@ -98,6 +98,13 @@ paths:
type: string
format: iso-country-code
example: DE
+ - in: header
+ name: If-Modified-Since
+ description: Request only stations modified since this date
+ schema:
+ type: string
+ format: date-time
+ example: '2024-01-01T00:00:00Z'
responses:
'200':
description: OK
@@ -157,6 +164,8 @@ paths:
allOf:
- $ref: '#/components/schemas/Links-Self'
- $ref: '#/components/schemas/Links-Pagination'
+ '304':
+ description: Not Modified
'400':
$ref: '#/components/responses/BadRequest'
'401':
@@ -893,6 +902,10 @@ components:
description: Name of the passenger
examples:
- John Doe
+ seat_preference:
+ type: string
+ enum: [window, aisle, any]
+ example: "window"
has_bicycle:
type: boolean
description: Indicates whether the passenger has a bicycle.
From c81ed10c7b85b418924c37ea0014bc55015933f3 Mon Sep 17 00:00:00 2001
From: Phil Sturgeon <67381+philsturgeon@users.noreply.github.com>
Date: Tue, 16 Jul 2024 10:32:05 +0100
Subject: [PATCH 06/13] remove caching stuff for now
---
openapi.yaml | 9 ---------
1 file changed, 9 deletions(-)
diff --git a/openapi.yaml b/openapi.yaml
index e47d4eb..93671b8 100644
--- a/openapi.yaml
+++ b/openapi.yaml
@@ -98,13 +98,6 @@ paths:
type: string
format: iso-country-code
example: DE
- - in: header
- name: If-Modified-Since
- description: Request only stations modified since this date
- schema:
- type: string
- format: date-time
- example: '2024-01-01T00:00:00Z'
responses:
'200':
description: OK
@@ -164,8 +157,6 @@ paths:
allOf:
- $ref: '#/components/schemas/Links-Self'
- $ref: '#/components/schemas/Links-Pagination'
- '304':
- description: Not Modified
'400':
$ref: '#/components/responses/BadRequest'
'401':
From 3030f1adc86d92b49c9dadc2433ff50dd74795bb Mon Sep 17 00:00:00 2001
From: Phil Sturgeon <67381+philsturgeon@users.noreply.github.com>
Date: Thu, 25 Jul 2024 13:04:15 +0100
Subject: [PATCH 07/13] Silence failing rules for microcks
---
.spectral.yaml | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/.spectral.yaml b/.spectral.yaml
index 423215e..11cf878 100644
--- a/.spectral.yaml
+++ b/.spectral.yaml
@@ -1,5 +1,14 @@
extends:
- "spectral:oas"
-- "@stoplight/spectral-owasp-ruleset"
-# - "@apisyouwonthate/style-guide"
-- "@microcks/spectral-ruleset"
+# - "@stoplight/spectral-owasp-ruleset"
+- "@apisyouwonthate/style-guide"
+# - "@microcks/spectral-ruleset"
+
+
+rules:
+ # The API doesn't have these (yet?)
+ api-home: off
+ api-health: off
+
+ # Microcks mocking with dynamic examples causes this rule to fail
+ oas3-valid-media-example: off
From 67526de0d80f7c00b8969f677ebb9fbc2667021b Mon Sep 17 00:00:00 2001
From: Phil Sturgeon <67381+philsturgeon@users.noreply.github.com>
Date: Thu, 25 Jul 2024 13:04:24 +0100
Subject: [PATCH 08/13] bring back seat preferences later
---
openapi.yaml | 4 ----
1 file changed, 4 deletions(-)
diff --git a/openapi.yaml b/openapi.yaml
index 93671b8..415d05c 100644
--- a/openapi.yaml
+++ b/openapi.yaml
@@ -893,10 +893,6 @@ components:
description: Name of the passenger
examples:
- John Doe
- seat_preference:
- type: string
- enum: [window, aisle, any]
- example: "window"
has_bicycle:
type: boolean
description: Indicates whether the passenger has a bicycle.
From 42652257bf29fa9d53a9d662e1fa8a7293b7b404 Mon Sep 17 00:00:00 2001
From: Phil Sturgeon <67381+philsturgeon@users.noreply.github.com>
Date: Tue, 5 Nov 2024 14:06:33 +0000
Subject: [PATCH 09/13] allow microcks back in for linting
---
.spectral.yaml | 2 +-
package.json | 3 ++-
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/.spectral.yaml b/.spectral.yaml
index 11cf878..274c9ef 100644
--- a/.spectral.yaml
+++ b/.spectral.yaml
@@ -2,7 +2,7 @@ extends:
- "spectral:oas"
# - "@stoplight/spectral-owasp-ruleset"
- "@apisyouwonthate/style-guide"
-# - "@microcks/spectral-ruleset"
+- "@microcks/spectral-ruleset"
rules:
diff --git a/package.json b/package.json
index 6a1ee9f..0e1c146 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,7 @@
{
"devDependencies": {
"@apisyouwonthate/style-guide": "^1.5.0",
- "@stoplight/spectral-owasp-ruleset": "^1.4.3"
+ "@stoplight/spectral-owasp-ruleset": "^1.4.3",
+ "@microcks/spectral-ruleset": "^0.0.5"
}
}
From 765262b5c4e7b3ea577af3e2eb60bbf1806090b8 Mon Sep 17 00:00:00 2001
From: Phil Sturgeon <67381+philsturgeon@users.noreply.github.com>
Date: Thu, 21 Nov 2024 21:50:28 +0000
Subject: [PATCH 10/13] revert main openapi.yaml and make a overlay / generated
openapi.mock.yaml
---
.microcks/openapi.mock.yaml | 1216 +++++++++++++++++++++++++++++++++++
.microcks/overlays.yaml | 204 ++++++
openapi.yaml | 203 +++---
3 files changed, 1502 insertions(+), 121 deletions(-)
create mode 100644 .microcks/openapi.mock.yaml
create mode 100644 .microcks/overlays.yaml
diff --git a/.microcks/openapi.mock.yaml b/.microcks/openapi.mock.yaml
new file mode 100644
index 0000000..fdeb438
--- /dev/null
+++ b/.microcks/openapi.mock.yaml
@@ -0,0 +1,1216 @@
+openapi: 3.1.0
+info:
+ title: Train Travel API
+ description: |
+ API for finding and booking train trips across Europe.
+
+ ## Run in Postman
+
+ Experiment with this API in Postman, using our Postman Collection.
+
+ [](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)
+ 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
+ x-internal: false
+ - url: https://mocks.example.com/rest
+ description: Mock Server
+ x-internal: false
+security:
+ - OAuth2:
+ - read
+tags:
+ - name: Stations
+ description: |
+ Find and filter train stations across Europe, including their location
+ and local timezone.
+ - name: Trips
+ description: |
+ Timetables and routes for train trips between stations, including pricing
+ and availability.
+ - name: Bookings
+ description: |
+ Create and manage bookings for train trips, including passenger details
+ and optional extras.
+ - 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.
+
+ 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.
+
+ required: false
+ schema:
+ type: string
+ examples:
+ - Milano Centrale
+ - 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:
+ type: object
+ properties:
+ data:
+ type: array
+ items:
+ $ref: '#/components/schemas/Station'
+ 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
+ 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.
+
+ 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: b2e783e1-c824-4d63-b37a-d8d698862f1d
+ - name: destination
+ in: query
+ description: The ID of the destination station
+ required: true
+ schema:
+ type: string
+ format: uuid
+ examples:
+ trips:
+ value: '2024-02-01T09:00:00Z'
+ - 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:
+ 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/Trip'
+ - 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: efdbb9d1-02c2-4bc3-afb7-6788d8782b1e
+ passenger_name: John Doe
+ has_bicycle: true
+ has_dog: true
+ - id: 1725ff48-ab45-4bb5-9d02-88745177dedb
+ 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'
+ examples:
+ new_booking:
+ summary: New Booking
+ value: |-
+ {
+ "id": "{{ uuid() > put(bookingId) }}",
+ "trip_id": "{{ request.body/trip_id }}",
+ "passenger_name": "{{ request.body/passenger_name }}",
+ "has_bicycle": {{ request.body/has_bicycle }},
+ "has_dog": {{ request.body/has_dog }},
+ "links": {
+ "self": "https://api.example.com/bookings/{{ bookingId }}"
+ }
+ }
+ 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: 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
+ booking_bfc5af2c-f477-43c4-8bdf-a00bdb939d65:
+ summary: Billy Bikeless
+ value:
+ id: bfc5af2c-f477-43c4-8bdf-a00bdb939d65
+ trip_id: efdbb9d1-02c2-4bc3-afb7-6788d8782b1e
+ 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:
+ Card:
+ value: 1725ff48-ab45-4bb5-9d02-88745177dedb
+ Bank:
+ value: 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:
+ 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.
+ 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'
+ examples:
+ new_booking:
+ summary: New Booking
+ value:
+ 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:
+ 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-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:
+ - 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.
+ 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: 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:
+ 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
+ convey the expiring limit, `remaining` to convey the remaining quota units,
+ and `reset` to convey the time window reset time.
+ 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.
diff --git a/.microcks/overlays.yaml b/.microcks/overlays.yaml
new file mode 100644
index 0000000..07e9878
--- /dev/null
+++ b/.microcks/overlays.yaml
@@ -0,0 +1,204 @@
+overlay: 1.0.0
+info:
+ title: Train Travel API - Microcks
+ description: |
+ This API is a mock server for the Train Travel API, which provides a way to
+ find and book train trips across Europe. It includes endpoints for finding
+ stations, getting timetables, and managing bookings.
+ version: 1.0.0
+
+actions:
+
+ - target: $["x-topics"]
+ description: Remove x-topics, not needed for mock server.
+ remove: true
+
+ - target: $.paths["/stations"].get.responses["200"].content["application/json"]["example"]
+ description: Remove the example from get /stations.
+ remove: true
+
+ - target: $.paths["/stations"].get.responses["200"].content["application/json"]
+ description: Add Microcks examples for get /stations.
+ update:
+ 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
+
+ - target: $.paths["/trips"].get.parameters[?(@.name=="origin")].example
+ description: Remove the example from get /trips - origin parameter.
+ remove: true
+
+ - target: $.paths["/trips"].get.parameters[?(@.name=="origin")]
+ description: Add Microcks examples for get /trips - origin parameter
+ update:
+ examples:
+ trips:
+ value: b2e783e1-c824-4d63-b37a-d8d698862f1d
+
+ - target: $.paths["/trips"].get.parameters[?(@.name=="destination")].example
+ remove: true
+
+ - target: $.paths["/trips"].get.parameters[?(@.name=="destination")]
+ update:
+ examples:
+ trips:
+ value: '2024-02-01T09:00:00Z'
+
+ - target: $.paths["/trips"].get.responses["200"].content["application/json"]["example"]
+ remove: true
+
+ - target: $.paths["/trips"].get.responses["200"].content["application/json"]
+ update:
+ 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
+
+ - target: $.paths["/bookings"].get.responses["200"].content["application/json"]["example"]
+ remove: true
+
+ - target: $.paths["/bookings"].get.responses["200"].content["application/json"]
+ update:
+ examples:
+ bookings:
+ summary: A list of bookings
+ value:
+ data:
+ - id: bfc5af2c-f477-43c4-8bdf-a00bdb939d65
+ trip_id: efdbb9d1-02c2-4bc3-afb7-6788d8782b1e
+ passenger_name: John Doe
+ has_bicycle: true
+ has_dog: true
+ - id: 1725ff48-ab45-4bb5-9d02-88745177dedb
+ 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
+
+ - target: $.paths["/bookings"]["post"].responses["201"].content["application/json"]["example"]
+ remove: true
+
+ - target: $.paths["/bookings"]["post"].responses["201"].content["application/json"]
+ update:
+ examples:
+ new_booking:
+ summary: New Booking
+ value: |-
+ {
+ "id": "{{ uuid() > put(bookingId) }}",
+ "trip_id": "{{ request.body/trip_id }}",
+ "passenger_name": "{{ request.body/passenger_name }}",
+ "has_bicycle": {{ request.body/has_bicycle }},
+ "has_dog": {{ request.body/has_dog }},
+ "links": {
+ "self": "https://api.example.com/bookings/{{ bookingId }}"
+ }
+ }
+
+ - target: $.paths["/bookings/{bookingId}"].parameters[?(@.name=="bookingId")].example
+ remove: true
+
+ - target: $.paths["/bookings/{bookingId}"].parameters[?(@.name=="bookingId")]
+ update:
+ 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
+
+ - target: $.paths["/bookings/{bookingId}"].get.responses["200"].content["application/json"]["example"]
+ remove: true
+
+ - target: $.paths["/bookings/{bookingId}"].get.responses["200"].content["application/json"]
+ update:
+ examples:
+ booking_1725ff48-ab45-4bb5-9d02-88745177dedb:
+ summary: John Doe
+ value:
+ id: 1725ff48-ab45-4bb5-9d02-88745177dedb
+ 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
+ booking_bfc5af2c-f477-43c4-8bdf-a00bdb939d65:
+ summary: Billy Bikeless
+ value:
+ id: bfc5af2c-f477-43c4-8bdf-a00bdb939d65
+ trip_id: efdbb9d1-02c2-4bc3-afb7-6788d8782b1e
+ passenger_name: Billy Bikeless
+ has_bicycle: false
+ has_dog: true
+ links:
+ self: https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb
+
+
+ - target: $.paths["/bookings/{bookingId}/payment"].parameters[?(@.name=="bookingId")].example
+ remove: true
+
+ - target: $.paths["/bookings/{bookingId}/payment"].parameters[?(@.name=="bookingId")]
+ update:
+ examples:
+ Card:
+ value: 1725ff48-ab45-4bb5-9d02-88745177dedb
+ Bank:
+ value: 1725ff48-ab45-4bb5-9d02-88745177dedb
+
+ - target: $.webhooks["newBooking"]["post"]["requestBody"].content["application/json"]["example"]
+ remove: true
+
+ - target: $.webhooks["newBooking"]["post"]["requestBody"].content["application/json"]
+ update:
+ examples:
+ new_booking:
+ summary: New Booking
+ value:
+ 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
diff --git a/openapi.yaml b/openapi.yaml
index 415d05c..95bacc6 100644
--- a/openapi.yaml
+++ b/openapi.yaml
@@ -25,6 +25,7 @@ servers:
- url: https://api.example.com
description: Production
x-internal: false
+
- url: https://mocks.example.com/rest
description: Mock Server
x-internal: false
@@ -121,25 +122,22 @@ paths:
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
+ 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:
@@ -195,9 +193,7 @@ paths:
schema:
type: string
format: uuid
- examples:
- trips:
- value: b2e783e1-c824-4d63-b37a-d8d698862f1d
+ 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.
@@ -205,9 +201,7 @@ paths:
schema:
type: string
format: date-time
- examples:
- trips:
- value: '2024-02-01T09:00:00Z'
+ example: '2024-02-01T09:00:00Z'
- name: bicycles
in: query
description: Only return trips where bicycles are known to be allowed
@@ -245,32 +239,29 @@ paths:
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
+ 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:
@@ -331,24 +322,21 @@ paths:
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: efdbb9d1-02c2-4bc3-afb7-6788d8782b1e
- passenger_name: John Doe
- has_bicycle: true
- has_dog: true
- - id: 1725ff48-ab45-4bb5-9d02-88745177dedb
- 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
+ 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:
@@ -407,21 +395,14 @@ paths:
links:
$ref: '#/components/schemas/Links-Self'
- examples:
- new_booking:
- summary: New Booking
- value: |-
- {
- "id": "{{ uuid() > put(bookingId) }}",
- "trip_id": "{{ request.body/trip_id }}",
- "passenger_name": "{{ request.body/passenger_name }}",
- "has_bicycle": {{ request.body/has_bicycle }},
- "has_dog": {{ request.body/has_dog }},
- "links": {
- "self": "https://api.example.com/bookings/{{ bookingId }}"
- }
- }
-
+ 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:
@@ -451,11 +432,7 @@ paths:
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
+ example: 1725ff48-ab45-4bb5-9d02-88745177dedb
get:
summary: Get a booking
description: Returns the details of a specific booking.
@@ -478,27 +455,14 @@ paths:
- 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: 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
- booking_bfc5af2c-f477-43c4-8bdf-a00bdb939d65:
- summary: Billy Bikeless
- value:
- id: bfc5af2c-f477-43c4-8bdf-a00bdb939d65
- trip_id: efdbb9d1-02c2-4bc3-afb7-6788d8782b1e
- passenger_name: Billy Bikeless
- has_bicycle: false
- has_dog: true
- links:
- self: https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb
+ 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:
@@ -678,17 +642,14 @@ webhooks:
allOf:
- $ref: '#/components/schemas/Links-Self'
- $ref: '#/components/schemas/Links-Pagination'
- examples:
- new_booking:
- summary: New Booking
- value:
- 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
+ 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.
From 25e1c7848c60d4d925ec01e11bf24fddbaeb5807 Mon Sep 17 00:00:00 2001
From: Phil Sturgeon <67381+philsturgeon@users.noreply.github.com>
Date: Thu, 21 Nov 2024 22:02:09 +0000
Subject: [PATCH 11/13] add a script to remind me how to do this
---
.microcks/{openapi.mock.yaml => openapi.yaml} | 270 ++++++++++++------
package.json | 6 +
2 files changed, 187 insertions(+), 89 deletions(-)
rename .microcks/{openapi.mock.yaml => openapi.yaml} (80%)
diff --git a/.microcks/openapi.mock.yaml b/.microcks/openapi.yaml
similarity index 80%
rename from .microcks/openapi.mock.yaml
rename to .microcks/openapi.yaml
index fdeb438..5f5fbf6 100644
--- a/.microcks/openapi.mock.yaml
+++ b/.microcks/openapi.yaml
@@ -1,30 +1,35 @@
openapi: 3.1.0
info:
title: Train Travel API
- description: |
+ description: >
API for finding and booking train trips across Europe.
+
## Run in Postman
+
Experiment with this API in Postman, using our Postman Collection.
- [](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)
+
+ [](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)
version: 1.0.0
contact:
name: Train Support
- url: https://example.com/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
+ url: 'https://github.com/bump-sh-examples/train-travel-api/issues/new'
servers:
- - url: https://api.example.com
+ - url: 'https://api.example.com'
description: Production
x-internal: false
- - url: https://mocks.example.com/rest
+ - url: 'https://mocks.example.com/rest'
description: Mock Server
x-internal: false
security:
@@ -44,7 +49,18 @@ tags:
Create and manage bookings for train trips, including passenger details
and optional extras.
- 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"
+ description: >
+ Pay for bookings using a card or bank account, and view payment
+
+ status and history.
+
+
+ > warn
+
+ > Bookings usually expire within 1 hour so you'll need to make your
+ payment
+
+ > before the expiry date
paths:
/stations:
get:
@@ -59,17 +75,16 @@ paths:
- 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.
-
+ The latitude and longitude of the user's location, to narrow down
+ the search results to sites within a proximity of this location.
required: false
schema:
type: string
- example: 52.5200,13.4050
+ example: '52.5200,13.4050'
- name: search
in: query
- description: >
+ description: |
A search term to filter the list of stations by name or address.
-
required: false
schema:
type: string
@@ -95,12 +110,18 @@ paths:
content:
application/json:
schema:
- type: object
- properties:
- data:
- type: array
- items:
- $ref: '#/components/schemas/Station'
+ 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
@@ -108,18 +129,18 @@ paths:
data:
- id: efdbb9d1-02c2-4bc3-afb7-6788d8782b1e
name: Berlin Hauptbahnhof
- address: Invalidenstraße 10557 Berlin, Germany
+ 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
+ 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
+ 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:
@@ -151,8 +172,9 @@ paths:
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.
-
+ Returns a list of available train trips between the specified origin and
+ destination stations on the given date, and allows for filtering by
+ bicycle and dog allowances.
operationId: get-trips
tags:
- Trips
@@ -181,7 +203,9 @@ paths:
value: '2024-02-01T09:00:00Z'
- name: date
in: query
- description: The date and time of the trip in ISO 8601 format in origin station's timezone.
+ description: >-
+ The date and time of the trip in ISO 8601 format in origin station's
+ timezone.
required: true
schema:
type: string
@@ -248,8 +272,10 @@ paths:
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
+ 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:
@@ -326,8 +352,8 @@ paths:
has_bicycle: false
has_dog: false
links:
- self: https://api.example.com/bookings
- next: https://api.example.com/bookings?page=2
+ self: 'https://api.example.com/bookings'
+ next: 'https://api.example.com/bookings?page=2'
application/xml:
schema:
allOf:
@@ -358,7 +384,9 @@ paths:
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.
+ description: >-
+ A booking is a temporary hold on a trip. It is not confirmed until the
+ payment is processed.
tags:
- Bookings
security:
@@ -417,7 +445,7 @@ paths:
$ref: '#/components/responses/TooManyRequests'
'500':
$ref: '#/components/responses/InternalServerError'
- /bookings/{bookingId}:
+ '/bookings/{bookingId}':
parameters:
- name: bookingId
in: path
@@ -463,7 +491,8 @@ paths:
has_bicycle: true
has_dog: true
links:
- self: https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb
+ self: >-
+ https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb
booking_bfc5af2c-f477-43c4-8bdf-a00bdb939d65:
summary: Billy Bikeless
value:
@@ -473,7 +502,8 @@ paths:
has_bicycle: false
has_dog: true
links:
- self: https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb
+ self: >-
+ https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb
application/xml:
schema:
allOf:
@@ -495,7 +525,7 @@ paths:
$ref: '#/components/responses/InternalServerError'
delete:
summary: Delete a booking
- description: Deletes a booking, cancelling the hold on the trip.
+ description: 'Deletes a booking, cancelling the hold on the trip.'
operationId: delete-booking
security:
- OAuth2:
@@ -517,7 +547,7 @@ paths:
$ref: '#/components/responses/TooManyRequests'
'500':
$ref: '#/components/responses/InternalServerError'
- /bookings/{bookingId}/payment:
+ '/bookings/{bookingId}/payment':
parameters:
- name: bookingId
in: path
@@ -533,7 +563,9 @@ paths:
value: 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.
+ 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
@@ -608,7 +640,8 @@ paths:
address_post_code: N12 9XX
status: succeeded
links:
- booking: https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb/payment
+ booking: >-
+ https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb/payment
Bank:
summary: Bank Account Payment
value:
@@ -625,7 +658,8 @@ paths:
country: gb
status: succeeded
links:
- booking: https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb
+ booking: >-
+ https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb
'400':
$ref: '#/components/responses/BadRequest'
'401':
@@ -641,8 +675,9 @@ webhooks:
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.
+ description: >
+ Subscribe to new bookings being created, to update integrations for your
+ users. Related data is available via the links provided in the request.
tags:
- Bookings
requestBody:
@@ -666,10 +701,13 @@ webhooks:
has_bicycle: true
has_dog: true
links:
- self: https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb
+ 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.
+ description: >-
+ Return a 200 status to indicate that the data was received
+ successfully.
components:
parameters:
page:
@@ -699,8 +737,8 @@ components:
description: OAuth 2.0 authorization code following RFC8725 best practices.
flows:
authorizationCode:
- authorizationUrl: https://example.com/oauth/authorize
- tokenUrl: https://example.com/oauth/token
+ authorizationUrl: 'https://example.com/oauth/authorize'
+ tokenUrl: 'https://example.com/oauth/token'
scopes:
read: Read access
write: Write access
@@ -732,8 +770,8 @@ components:
type: string
description: The address of the station.
examples:
- - Invalidenstraße 10557 Berlin, Germany
- - 18 Rue de Dunkerque 75010 Paris, France
+ - 'Invalidenstraße 10557 Berlin, Germany'
+ - '18 Rue de Dunkerque 75010 Paris, France'
country_code:
type: string
description: The country code of the station.
@@ -743,7 +781,9 @@ components:
- FR
timezone:
type: string
- description: The timezone of the station in the [IANA Time Zone Database format](https://www.iana.org/time-zones).
+ description: >-
+ The timezone of the station in the [IANA Time Zone Database
+ format](https://www.iana.org/time-zones).
examples:
- Europe/Berlin
- Europe/Paris
@@ -766,26 +806,30 @@ components:
type: object
xml:
name: problem
- namespace: urn:ietf:rfc:7807
+ 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
+ - 'https://example.com/probs/out-of-credit'
title:
type: string
- description: A short, human-readable summary of the problem type
+ 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
+ description: >-
+ A human-readable explanation specific to this occurrence of the
+ problem
examples:
- - Your current balance is 30, but that costs 50.
+ - 'Your current balance is 30, but that costs 50.'
instance:
type: string
- description: A URI reference that identifies the specific occurrence of the problem
+ description: >-
+ A URI reference that identifies the specific occurrence of the
+ problem
examples:
- /account/12345/msgs/abc
status:
@@ -875,7 +919,9 @@ components:
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).
+ description: >-
+ This is a generic request/response wrapper which contains both data and
+ links which serve as hypermedia controls (HATEOAS).
type: object
properties:
data:
@@ -893,18 +939,26 @@ components:
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.
+ 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.
+ 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.
+ description: >-
+ Three-letter [ISO currency
+ code](https://www.iso.org/iso-4217-currency-codes.html), in
+ lowercase.
type: string
enum:
- bam
@@ -917,7 +971,10 @@ components:
- 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.
+ 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.
@@ -933,12 +990,16 @@ components:
- 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.
+ 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.
+ description: >-
+ Card security code, 3 or 4 digits usually found on the back
+ of the card.
minLength: 3
maxLength: 4
writeOnly: true
@@ -975,7 +1036,9 @@ components:
- 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.
+ 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:
@@ -985,16 +1048,22 @@ components:
type: string
number:
type: string
- description: The account number for the bank account, in string form. Must be a current account.
+ 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.
+ 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`.
+ 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.
@@ -1010,7 +1079,9 @@ components:
- bank_name
- country
status:
- description: The status of the payment, one of `pending`, `succeeded`, or `failed`.
+ description: >-
+ The status of the payment, one of `pending`, `succeeded`, or
+ `failed`.
type: string
enum:
- pending
@@ -1024,30 +1095,51 @@ components:
type: string
format: uri
examples:
- - https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb
+ - >-
+ 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"
+ description: >
+ The Cache-Control header communicates directives for caching mechanisms
+ in both requests and responses.
+
+ It is used to specify the caching directives in responses to prevent
+ caches from storing sensitive information.
schema:
type: string
- description: A comma-separated list of directives as defined in [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111.html).
+ 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
+ - 'max-age=604800, public'
- no-store
- no-cache
- private
RateLimit:
- description: |
- The RateLimit header communicates quota policies. It contains a `limit` to
- convey the expiring limit, `remaining` to convey the remaining quota units,
+ description: >
+ The RateLimit header communicates quota policies. It contains a `limit`
+ to
+
+ convey the expiring limit, `remaining` to convey the remaining quota
+ units,
+
and `reset` to convey the time window reset time.
schema:
type: string
examples:
- - limit=10, remaining=0, reset=10
+ - '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"
+ description: >
+ The Retry-After header indicates how long the user agent should wait
+ before making a follow-up request.
+
+ The value is in seconds and can be an integer or a date in the future.
+
+ If the value is an integer, it indicates the number of seconds to wait.
+
+ If the value is a date, it indicates the time at which the user agent
+ should make a follow-up request.
schema:
type: string
examples:
@@ -1068,7 +1160,7 @@ components:
schema:
$ref: '#/components/schemas/Problem'
example:
- type: https://example.com/errors/bad-request
+ type: 'https://example.com/errors/bad-request'
title: Bad Request
status: 400
detail: The request is invalid or missing required parameters.
@@ -1076,7 +1168,7 @@ components:
schema:
$ref: '#/components/schemas/Problem'
example:
- type: https://example.com/errors/bad-request
+ type: 'https://example.com/errors/bad-request'
title: Bad Request
status: 400
detail: The request is invalid or missing required parameters.
@@ -1090,7 +1182,7 @@ components:
schema:
$ref: '#/components/schemas/Problem'
example:
- type: https://example.com/errors/conflict
+ type: 'https://example.com/errors/conflict'
title: Conflict
status: 409
detail: There is a conflict with an existing resource.
@@ -1098,7 +1190,7 @@ components:
schema:
$ref: '#/components/schemas/Problem'
example:
- type: https://example.com/errors/conflict
+ type: 'https://example.com/errors/conflict'
title: Conflict
status: 409
detail: There is a conflict with an existing resource.
@@ -1112,7 +1204,7 @@ components:
schema:
$ref: '#/components/schemas/Problem'
example:
- type: https://example.com/errors/forbidden
+ type: 'https://example.com/errors/forbidden'
title: Forbidden
status: 403
detail: Access is forbidden with the provided credentials.
@@ -1120,7 +1212,7 @@ components:
schema:
$ref: '#/components/schemas/Problem'
example:
- type: https://example.com/errors/forbidden
+ type: 'https://example.com/errors/forbidden'
title: Forbidden
status: 403
detail: Access is forbidden with the provided credentials.
@@ -1134,7 +1226,7 @@ components:
schema:
$ref: '#/components/schemas/Problem'
example:
- type: https://example.com/errors/internal-server-error
+ type: 'https://example.com/errors/internal-server-error'
title: Internal Server Error
status: 500
detail: An unexpected error occurred.
@@ -1142,7 +1234,7 @@ components:
schema:
$ref: '#/components/schemas/Problem'
example:
- type: https://example.com/errors/internal-server-error
+ type: 'https://example.com/errors/internal-server-error'
title: Internal Server Error
status: 500
detail: An unexpected error occurred.
@@ -1156,7 +1248,7 @@ components:
schema:
$ref: '#/components/schemas/Problem'
example:
- type: https://example.com/errors/not-found
+ type: 'https://example.com/errors/not-found'
title: Not Found
status: 404
detail: The requested resource was not found.
@@ -1164,7 +1256,7 @@ components:
schema:
$ref: '#/components/schemas/Problem'
example:
- type: https://example.com/errors/not-found
+ type: 'https://example.com/errors/not-found'
title: Not Found
status: 404
detail: The requested resource was not found.
@@ -1180,7 +1272,7 @@ components:
schema:
$ref: '#/components/schemas/Problem'
example:
- type: https://example.com/errors/too-many-requests
+ type: 'https://example.com/errors/too-many-requests'
title: Too Many Requests
status: 429
detail: You have exceeded the rate limit.
@@ -1188,7 +1280,7 @@ components:
schema:
$ref: '#/components/schemas/Problem'
example:
- type: https://example.com/errors/too-many-requests
+ type: 'https://example.com/errors/too-many-requests'
title: Too Many Requests
status: 429
detail: You have exceeded the rate limit.
@@ -1202,7 +1294,7 @@ components:
schema:
$ref: '#/components/schemas/Problem'
example:
- type: https://example.com/errors/unauthorized
+ type: 'https://example.com/errors/unauthorized'
title: Unauthorized
status: 401
detail: You do not have the necessary permissions.
@@ -1210,7 +1302,7 @@ components:
schema:
$ref: '#/components/schemas/Problem'
example:
- type: https://example.com/errors/unauthorized
+ type: 'https://example.com/errors/unauthorized'
title: Unauthorized
status: 401
detail: You do not have the necessary permissions.
diff --git a/package.json b/package.json
index 0e1c146..4e6e65a 100644
--- a/package.json
+++ b/package.json
@@ -1,4 +1,10 @@
{
+ "dependencies": {
+ "bump-cli": "^2.8.4"
+ },
+ "scripts": {
+ "microcks": "bump overlay openapi.yaml .microcks/overlays.yaml > .microcks/openapi.yaml"
+ },
"devDependencies": {
"@apisyouwonthate/style-guide": "^1.5.0",
"@stoplight/spectral-owasp-ruleset": "^1.4.3",
From 795048a63e46b02ec6b527f8f251826547eb91c9 Mon Sep 17 00:00:00 2001
From: Phil Sturgeon <67381+philsturgeon@users.noreply.github.com>
Date: Fri, 22 Nov 2024 18:06:21 +0000
Subject: [PATCH 12/13] disable linting on microcks openapi.yaml as it uses
string examples
---
.github/workflows/lint.yml | 5 +++--
.microcks/openapi.yaml | 1 +
.microcks/overlays.yaml | 10 +++++-----
.spectral.yaml | 5 -----
4 files changed, 9 insertions(+), 12 deletions(-)
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index 0635da6..0fc436c 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -27,8 +27,9 @@ jobs:
fetch-depth: 0
- name: Super-linter
- uses: super-linter/super-linter@v6.0.0
+ uses: super-linter/super-linter/slim@v7.2.0
env:
DEFAULT_BRANCH: main
- VALIDATE_OPENAPI: true
+ FILTER_REGEX_EXCLUDE: ^.microcks/
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ VALIDATE_OPENAPI: true
diff --git a/.microcks/openapi.yaml b/.microcks/openapi.yaml
index 5f5fbf6..9f21f9d 100644
--- a/.microcks/openapi.yaml
+++ b/.microcks/openapi.yaml
@@ -1306,3 +1306,4 @@ components:
title: Unauthorized
status: 401
detail: You do not have the necessary permissions.
+
diff --git a/.microcks/overlays.yaml b/.microcks/overlays.yaml
index 07e9878..a22d114 100644
--- a/.microcks/overlays.yaml
+++ b/.microcks/overlays.yaml
@@ -49,7 +49,7 @@ actions:
update:
examples:
trips:
- value: b2e783e1-c824-4d63-b37a-d8d698862f1d
+ value: 'b2e783e1-c824-4d63-b37a-d8d698862f1d'
- target: $.paths["/trips"].get.parameters[?(@.name=="destination")].example
remove: true
@@ -143,9 +143,9 @@ actions:
update:
examples:
booking_1725ff48-ab45-4bb5-9d02-88745177dedb:
- value: 1725ff48-ab45-4bb5-9d02-88745177dedb
+ value: '1725ff48-ab45-4bb5-9d02-88745177dedb'
booking_bfc5af2c-f477-43c4-8bdf-a00bdb939d65:
- value: bfc5af2c-f477-43c4-8bdf-a00bdb939d65
+ value: 'bfc5af2c-f477-43c4-8bdf-a00bdb939d65'
- target: $.paths["/bookings/{bookingId}"].get.responses["200"].content["application/json"]["example"]
remove: true
@@ -182,9 +182,9 @@ actions:
update:
examples:
Card:
- value: 1725ff48-ab45-4bb5-9d02-88745177dedb
+ value: '1725ff48-ab45-4bb5-9d02-88745177dedb'
Bank:
- value: 1725ff48-ab45-4bb5-9d02-88745177dedb
+ value: '1725ff48-ab45-4bb5-9d02-88745177dedb'
- target: $.webhooks["newBooking"]["post"]["requestBody"].content["application/json"]["example"]
remove: true
diff --git a/.spectral.yaml b/.spectral.yaml
index 274c9ef..719461d 100644
--- a/.spectral.yaml
+++ b/.spectral.yaml
@@ -2,13 +2,8 @@ extends:
- "spectral:oas"
# - "@stoplight/spectral-owasp-ruleset"
- "@apisyouwonthate/style-guide"
-- "@microcks/spectral-ruleset"
-
rules:
# The API doesn't have these (yet?)
api-home: off
api-health: off
-
- # Microcks mocking with dynamic examples causes this rule to fail
- oas3-valid-media-example: off
From ea7e90b401413fbb0dda95583328486c24c67697 Mon Sep 17 00:00:00 2001
From: Phil Sturgeon <67381+philsturgeon@users.noreply.github.com>
Date: Fri, 22 Nov 2024 18:19:13 +0000
Subject: [PATCH 13/13] Regex...
---
.github/workflows/lint.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index 0fc436c..ad89126 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -30,6 +30,6 @@ jobs:
uses: super-linter/super-linter/slim@v7.2.0
env:
DEFAULT_BRANCH: main
- FILTER_REGEX_EXCLUDE: ^.microcks/
+ FILTER_REGEX_INCLUDE: ^openapi.yaml
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
VALIDATE_OPENAPI: true