├── README.md ├── ch01 └── dog.yaml ├── ch06 ├── 01.yml ├── f02.yml └── openapi.yaml ├── ch07 ├── 01.yml └── openapi.yml ├── ch08 ├── 01.yml ├── 02.yml ├── markdown-cheatsheet.yml ├── openapi.yml └── site │ ├── index.html │ ├── openapi.yml │ └── site.zip ├── ch10 ├── 01.yml ├── README.md └── openapi.yml ├── ch11 ├── README.md └── openapi.yml ├── ch12 ├── 01.yml ├── 02.yml ├── 03.yml ├── README.md └── openapi.yml ├── ch13 ├── 01.yml ├── 02.yml ├── README.md └── openapi.yml ├── ch14 ├── 01.yml ├── README.md └── openapi.yml ├── ch16 ├── README.md └── openapi.yaml ├── ch17 ├── README.md └── openapi.yaml ├── ch18 ├── README.md └── openapi.yaml ├── ch19 ├── README.md └── openapi.yaml ├── ch20 ├── README.md └── openapi.yml └── core-concept └── openapi.yml /README.md: -------------------------------------------------------------------------------- 1 | # openapi 2 | The supporting OpenAPI documents for Designing APIs with Swagger and OpenAPI 3 | -------------------------------------------------------------------------------- /ch01/dog.yaml: -------------------------------------------------------------------------------- 1 | openapi: 3.0.3 2 | info: 3 | title: Dog API 4 | version: '1.0.0' 5 | servers: 6 | - url: https://dog.ceo/api 7 | paths: 8 | /breed/{breedName}/images: 9 | get: 10 | description: Get images of dog breeds 11 | parameters: 12 | - in: path 13 | name: breedName 14 | schema: 15 | type: string 16 | example: hound 17 | required: true 18 | responses: 19 | '200': 20 | description: A list of dog images 21 | content: 22 | application/json: 23 | schema: 24 | type: object 25 | properties: 26 | status: 27 | type: string 28 | example: success 29 | message: 30 | type: array 31 | items: 32 | type: string 33 | example: https://images.dog.ceo/breeds/hound-afghan/n02088094_1003.jpg 34 | -------------------------------------------------------------------------------- /ch06/01.yml: -------------------------------------------------------------------------------- 1 | openapi: 3.0.3 2 | info: 3 | version: v1 4 | title: FarmStall API 5 | servers: 6 | - url: https://farmstall.designapis.com/v1 7 | paths: 8 | /reviews: 9 | post: 10 | description: Create a new Review 11 | requestBody: 12 | description: A new Review 13 | content: 14 | application/json: 15 | schema: 16 | type: object 17 | properties: 18 | message: 19 | type: string 20 | rating: 21 | type: integer 22 | minimum: 1 23 | maximum: 5 24 | userId: 25 | type: string 26 | pattern: '^[0-9a-fA-F\-]{36}$' 27 | nullable: true 28 | responses: 29 | '201': 30 | description: Successfully created a new Review 31 | content: 32 | application/json: 33 | schema: 34 | type: object 35 | properties: 36 | message: 37 | type: string 38 | rating: 39 | type: integer 40 | minimum: 1 41 | maximum: 5 42 | userId: 43 | type: string 44 | nullable: true 45 | pattern: '^[0-9a-fA-F\-]{36}$' 46 | uuid: 47 | type: string 48 | pattern: '^[0-9a-fA-F\-]{36}$' 49 | 50 | -------------------------------------------------------------------------------- /ch06/f02.yml: -------------------------------------------------------------------------------- 1 | openapi: 3.0.3 2 | info: 3 | version: v1 4 | title: FarmStall API 5 | servers: 6 | - url: https://farmstall.designapis.com/v1 7 | paths: 8 | /reviews: 9 | # get: ... 10 | post: 11 | description: Create a new Review 12 | requestBody: 13 | description: A new Review 14 | content: 15 | application/json: 16 | schema: 17 | type: object 18 | properties: 19 | message: 20 | type: string 21 | rating: 22 | type: integer 23 | minimum: 1 24 | maximum: 5 25 | userId: 26 | type: string 27 | pattern: '^[0-9a-fA-F\-]{36}$' 28 | nullable: true 29 | responses: 30 | '201': 31 | description: Successfully created a new Review 32 | content: 33 | application/json: 34 | schema: 35 | type: object 36 | properties: 37 | message: 38 | type: string 39 | example: An awesome time for the whole family. 40 | rating: 41 | type: integer 42 | minimum: 1 43 | maximum: 5 44 | userId: 45 | type: string 46 | nullable: true 47 | pattern: '^[0-9a-fA-F\-]{36}$' 48 | uuid: 49 | type: string 50 | pattern: '^[0-9a-fA-F\-]{36}$' 51 | /reviews/{reviewId}: 52 | get: 53 | description: Get a single review 54 | parameters: 55 | - name: reviewId 56 | in: path 57 | required: true 58 | schema: 59 | type: string 60 | description: The review's ID 61 | example: 3b5b1707-b82c-4b1d-9078-157053902525 62 | minLength: 36 63 | maxLength: 36 64 | pattern: '[a-zA-Z0-9-]+' 65 | responses: 66 | '200': 67 | description: A single review 68 | content: 69 | application/json: 70 | schema: 71 | type: object 72 | properties: 73 | message: 74 | type: string 75 | rating: 76 | type: integer 77 | minimum: 1 78 | maximum: 5 79 | userId: 80 | minLength: 36 81 | maxLength: 36 82 | pattern: '^[a-zA-Z0-9-]+$' 83 | nullable: true 84 | uuid: 85 | minLength: 36 86 | maxLength: 36 87 | pattern: '^[a-zA-Z0-9-]+$' 88 | -------------------------------------------------------------------------------- /ch06/openapi.yaml: -------------------------------------------------------------------------------- 1 | openapi: 3.0.3 2 | info: 3 | version: v1 4 | title: FarmStall API 5 | servers: 6 | - url: https://farmstall.designapis.com/v1 7 | paths: 8 | /reviews: 9 | get: 10 | description: Get a list of reviews 11 | parameters: 12 | - name: maxRating 13 | in: query 14 | schema: 15 | type: number 16 | responses: 17 | '200': 18 | description: A bunch of reviews 19 | content: 20 | application/json: 21 | schema: 22 | type: array 23 | items: 24 | type: object 25 | properties: 26 | rating: 27 | type: integer 28 | minimum: 1 29 | maximum: 5 30 | message: 31 | type: string 32 | example: An awesome time for the whole family. 33 | uuid: 34 | type: string 35 | pattern: '^[0-9a-fA-F\-]{36}$' 36 | example: 3b5b1707-b82c-4b1d-9078-157053902525 37 | userId: 38 | type: string 39 | pattern: '^[0-9a-fA-F\-]{36}$' 40 | nullable: true 41 | example: 3b5b1707-b82c-4b1d-9078-157053902525 42 | post: 43 | description: Create a new Review 44 | requestBody: 45 | description: A new Review 46 | content: 47 | application/json: 48 | schema: 49 | type: object 50 | properties: 51 | message: 52 | type: string 53 | example: An awesome time for the whole family. 54 | rating: 55 | type: integer 56 | example: 5 57 | minimum: 1 58 | maximum: 5 59 | userId: 60 | type: string 61 | pattern: '^[0-9a-fA-F\-]{36}$' 62 | nullable: true 63 | example: null 64 | responses: 65 | '201': 66 | description: Successfully created a new Review 67 | content: 68 | application/json: 69 | schema: 70 | type: object 71 | properties: 72 | message: 73 | type: string 74 | example: An awesome time for the whole family. 75 | rating: 76 | type: integer 77 | example: 5 78 | minimum: 1 79 | maximum: 5 80 | userId: 81 | type: string 82 | nullable: true 83 | pattern: '^[0-9a-fA-F\-]{36}$' 84 | example: 3b5b1707-b82c-4b1d-9078-157053902525 85 | uuid: 86 | type: string 87 | pattern: '^[0-9a-fA-F\-]{36}$' 88 | example: 3b5b1707-b82c-4b1d-9078-157053902525 89 | /reviews/{reviewId}: 90 | get: 91 | description: Get a single review 92 | parameters: 93 | - name: reviewId 94 | in: path 95 | required: true 96 | schema: 97 | type: string 98 | description: The review's ID 99 | example: 3b5b1707-b82c-4b1d-9078-157053902525 100 | minLength: 36 101 | maxLength: 36 102 | pattern: '[a-zA-Z0-9-]+' 103 | responses: 104 | '200': 105 | description: A single review 106 | content: 107 | application/json: 108 | schema: 109 | type: object 110 | properties: 111 | message: 112 | type: string 113 | example: 3b5b1707-b82c-4b1d-9078-157053902525 114 | rating: 115 | type: integer 116 | example: 5 117 | minimum: 1 118 | maximum: 5 119 | userId: 120 | minLength: 36 121 | maxLength: 36 122 | pattern: '^[a-zA-Z0-9-]+$' 123 | nullable: true 124 | example: 3b5b1707-b82c-4b1d-9078-157053902525 125 | uuid: 126 | minLength: 36 127 | maxLength: 36 128 | pattern: '^[a-zA-Z0-9-]+$' 129 | example: 3b5b1707-b82c-4b1d-9078-157053902525 130 | -------------------------------------------------------------------------------- /ch07/01.yml: -------------------------------------------------------------------------------- 1 | openapi: 3.0.3 2 | info: 3 | version: v1 4 | title: FarmStall API 5 | servers: 6 | - url: https://farmstall.designapis.com/v1 7 | paths: 8 | /reviews: 9 | get: 10 | description: Get a list of reviews 11 | parameters: 12 | - name: maxRating 13 | in: query 14 | schema: 15 | type: number 16 | responses: 17 | '200': 18 | description: A bunch of reviews 19 | content: 20 | application/json: 21 | schema: 22 | type: array 23 | items: 24 | type: object 25 | properties: 26 | rating: 27 | type: integer 28 | minimum: 1 29 | maximum: 5 30 | message: 31 | type: string 32 | example: An awesome time for the whole family. 33 | uuid: 34 | type: string 35 | pattern: '^[0-9a-fA-F\-]{36}$' 36 | example: 3b5b1707-b82c-4b1d-9078-157053902525 37 | userId: 38 | type: string 39 | pattern: '^[0-9a-fA-F\-]{36}$' 40 | nullable: true 41 | example: 3b5b1707-b82c-4b1d-9078-157053902525 42 | post: 43 | description: Create a new Review 44 | requestBody: 45 | description: A new Review 46 | content: 47 | application/json: 48 | schema: 49 | type: object 50 | properties: 51 | message: 52 | type: string 53 | example: An awesome time for the whole family. 54 | rating: 55 | type: integer 56 | example: 5 57 | minimum: 1 58 | maximum: 5 59 | userId: 60 | type: string 61 | pattern: '^[0-9a-fA-F\-]{36}$' 62 | nullable: true 63 | example: null 64 | responses: 65 | '201': 66 | description: Successfully created a new Review 67 | content: 68 | application/json: 69 | schema: 70 | type: object 71 | properties: 72 | message: 73 | type: string 74 | example: An awesome time for the whole family. 75 | rating: 76 | type: integer 77 | example: 5 78 | minimum: 1 79 | maximum: 5 80 | userId: 81 | type: string 82 | nullable: true 83 | pattern: '^[0-9a-fA-F\-]{36}$' 84 | example: 3b5b1707-b82c-4b1d-9078-157053902525 85 | uuid: 86 | type: string 87 | pattern: '^[0-9a-fA-F\-]{36}$' 88 | example: 3b5b1707-b82c-4b1d-9078-157053902525 89 | /reviews/{reviewId}: 90 | get: 91 | description: Get a single review 92 | parameters: 93 | - name: reviewId 94 | in: path 95 | required: true 96 | schema: 97 | type: string 98 | description: The review's ID 99 | example: 3b5b1707-b82c-4b1d-9078-157053902525 100 | minLength: 36 101 | maxLength: 36 102 | pattern: '[a-zA-Z0-9-]+' 103 | responses: 104 | '200': 105 | description: A single review 106 | content: 107 | application/json: 108 | schema: 109 | type: object 110 | properties: 111 | message: 112 | type: string 113 | example: 3b5b1707-b82c-4b1d-9078-157053902525 114 | rating: 115 | type: integer 116 | example: 5 117 | minimum: 1 118 | maximum: 5 119 | userId: 120 | minLength: 36 121 | maxLength: 36 122 | pattern: '^[a-zA-Z0-9-]+$' 123 | nullable: true 124 | example: 3b5b1707-b82c-4b1d-9078-157053902525 125 | uuid: 126 | minLength: 36 127 | maxLength: 36 128 | pattern: '^[a-zA-Z0-9-]+$' 129 | example: 3b5b1707-b82c-4b1d-9078-157053902525 130 | -------------------------------------------------------------------------------- /ch07/openapi.yml: -------------------------------------------------------------------------------- 1 | openapi: 3.0.3 2 | info: 3 | version: v1 4 | title: FarmStall API 5 | servers: 6 | - url: https://farmstall.designapis.com/v1 7 | paths: 8 | /reviews: 9 | get: 10 | description: Get a list of reviews 11 | parameters: 12 | - name: maxRating 13 | in: query 14 | schema: 15 | type: number 16 | responses: 17 | '200': 18 | description: A bunch of reviews 19 | content: 20 | application/json: 21 | schema: 22 | type: array 23 | items: 24 | type: object 25 | properties: 26 | rating: 27 | type: integer 28 | minimum: 1 29 | maximum: 5 30 | message: 31 | type: string 32 | example: An awesome time for the whole family. 33 | uuid: 34 | type: string 35 | pattern: '^[0-9a-fA-F\-]{36}$' 36 | example: 3b5b1707-b82c-4b1d-9078-157053902525 37 | userId: 38 | type: string 39 | pattern: '^[0-9a-fA-F\-]{36}$' 40 | nullable: true 41 | example: 3b5b1707-b82c-4b1d-9078-157053902525 42 | post: 43 | description: Create a new Review 44 | security: 45 | - MyUserToken: [] 46 | requestBody: 47 | description: A new Review 48 | content: 49 | application/json: 50 | schema: 51 | type: object 52 | properties: 53 | message: 54 | type: string 55 | example: An awesome time for the whole family. 56 | rating: 57 | type: integer 58 | example: 5 59 | minimum: 1 60 | maximum: 5 61 | responses: 62 | '201': 63 | description: Successfully created a new Review 64 | content: 65 | application/json: 66 | schema: 67 | type: object 68 | properties: 69 | message: 70 | type: string 71 | example: An awesome time for the whole family. 72 | rating: 73 | type: integer 74 | example: 5 75 | minimum: 1 76 | maximum: 5 77 | userId: 78 | type: string 79 | nullable: true 80 | pattern: '^[0-9a-fA-F\-]{36}$' 81 | example: 3b5b1707-b82c-4b1d-9078-157053902525 82 | uuid: 83 | type: string 84 | pattern: '^[0-9a-fA-F\-]{36}$' 85 | example: 3b5b1707-b82c-4b1d-9078-157053902525 86 | /reviews/{reviewId}: 87 | get: 88 | description: Get a single review 89 | parameters: 90 | - name: reviewId 91 | in: path 92 | required: true 93 | schema: 94 | type: string 95 | description: The review's ID 96 | example: 3b5b1707-b82c-4b1d-9078-157053902525 97 | minLength: 36 98 | maxLength: 36 99 | pattern: '[a-zA-Z0-9-]+' 100 | responses: 101 | '200': 102 | description: A single review 103 | content: 104 | application/json: 105 | schema: 106 | type: object 107 | properties: 108 | message: 109 | type: string 110 | example: An awesome time for the whole family. 111 | rating: 112 | type: integer 113 | example: 5 114 | minimum: 1 115 | maximum: 5 116 | userId: 117 | minLength: 36 118 | maxLength: 36 119 | pattern: '^[a-zA-Z0-9-]+$' 120 | nullable: true 121 | example: 3b5b1707-b82c-4b1d-9078-157053902525 122 | uuid: 123 | minLength: 36 124 | maxLength: 36 125 | pattern: '^[a-zA-Z0-9-]+$' 126 | example: 3b5b1707-b82c-4b1d-9078-157053902525 127 | /users: 128 | post: 129 | description: Create a new user 130 | requestBody: 131 | description: User details 132 | content: 133 | application/json: 134 | schema: 135 | type: object 136 | properties: 137 | username: 138 | type: string 139 | example: ponelat 140 | password: 141 | type: string 142 | format: password 143 | fullName: 144 | type: string 145 | example: Josh Ponelat 146 | responses: 147 | '201': 148 | description: Successfully created a new user 149 | content: 150 | application/json: 151 | schema: 152 | type: object 153 | properties: 154 | username: 155 | type: string 156 | example: ponelat 157 | uuid: 158 | type: string 159 | example: f7f680a8-d111-421f-b6b3-493ebf905078 160 | /tokens: 161 | post: 162 | description: Create a new token 163 | requestBody: 164 | content: 165 | application/json: 166 | schema: 167 | type: object 168 | properties: 169 | username: 170 | type: string 171 | example: ponelat 172 | password: 173 | type: string 174 | format: password 175 | 176 | responses: 177 | '201': 178 | description: Create a new token for gaining authenticated access to resources 179 | content: 180 | application/json: 181 | schema: 182 | type: object 183 | properties: 184 | token: 185 | type: string 186 | 187 | components: 188 | securitySchemes: 189 | MyUserToken: 190 | type: apiKey 191 | in: header 192 | name: Authorization 193 | -------------------------------------------------------------------------------- /ch08/01.yml: -------------------------------------------------------------------------------- 1 | openapi: 3.0.3 2 | info: 3 | version: v1 4 | title: FarmStall API 5 | servers: 6 | - url: https://farmstall.designapis.com/v1 7 | paths: 8 | /reviews: 9 | get: 10 | description: Get a list of reviews 11 | parameters: 12 | - name: maxRating 13 | in: query 14 | schema: 15 | type: number 16 | responses: 17 | '200': 18 | description: A bunch of reviews 19 | content: 20 | application/json: 21 | schema: 22 | type: array 23 | items: 24 | type: object 25 | properties: 26 | rating: 27 | type: integer 28 | minimum: 1 29 | maximum: 5 30 | message: 31 | type: string 32 | example: An awesome time for the whole family. 33 | uuid: 34 | type: string 35 | pattern: '^[0-9a-fA-F\-]{36}$' 36 | example: 3b5b1707-b82c-4b1d-9078-157053902525 37 | userId: 38 | type: string 39 | pattern: '^[0-9a-fA-F\-]{36}$' 40 | nullable: true 41 | example: 3b5b1707-b82c-4b1d-9078-157053902525 42 | post: 43 | description: Create a new Review 44 | security: 45 | - MyUserToken: [] 46 | requestBody: 47 | description: A new Review 48 | content: 49 | application/json: 50 | schema: 51 | type: object 52 | properties: 53 | message: 54 | type: string 55 | example: An awesome time for the whole family. 56 | rating: 57 | type: integer 58 | example: 5 59 | minimum: 1 60 | maximum: 5 61 | responses: 62 | '201': 63 | description: Successfully created a new Review 64 | content: 65 | application/json: 66 | schema: 67 | type: object 68 | properties: 69 | message: 70 | type: string 71 | example: An awesome time for the whole family. 72 | rating: 73 | type: integer 74 | example: 5 75 | minimum: 1 76 | maximum: 5 77 | userId: 78 | type: string 79 | nullable: true 80 | pattern: '^[0-9a-fA-F\-]{36}$' 81 | example: 3b5b1707-b82c-4b1d-9078-157053902525 82 | uuid: 83 | type: string 84 | pattern: '^[0-9a-fA-F\-]{36}$' 85 | example: 3b5b1707-b82c-4b1d-9078-157053902525 86 | /reviews/{reviewId}: 87 | get: 88 | description: Get a single review 89 | parameters: 90 | - name: reviewId 91 | in: path 92 | required: true 93 | schema: 94 | type: string 95 | description: The review's ID 96 | example: 3b5b1707-b82c-4b1d-9078-157053902525 97 | minLength: 36 98 | maxLength: 36 99 | pattern: '[a-zA-Z0-9-]+' 100 | responses: 101 | '200': 102 | description: A single review 103 | content: 104 | application/json: 105 | schema: 106 | type: object 107 | properties: 108 | message: 109 | type: string 110 | example: An awesome time for the whole family. 111 | rating: 112 | type: integer 113 | example: 5 114 | minimum: 1 115 | maximum: 5 116 | userId: 117 | minLength: 36 118 | maxLength: 36 119 | pattern: '^[a-zA-Z0-9-]+$' 120 | nullable: true 121 | example: 3b5b1707-b82c-4b1d-9078-157053902525 122 | uuid: 123 | minLength: 36 124 | maxLength: 36 125 | pattern: '^[a-zA-Z0-9-]+$' 126 | example: 3b5b1707-b82c-4b1d-9078-157053902525 127 | /users: 128 | post: 129 | description: Create a new user 130 | requestBody: 131 | description: User details 132 | content: 133 | application/json: 134 | schema: 135 | type: object 136 | properties: 137 | username: 138 | type: string 139 | example: ponelat 140 | password: 141 | type: string 142 | format: password 143 | fullName: 144 | type: string 145 | example: Josh Ponelat 146 | responses: 147 | '201': 148 | description: Successfully created a new user 149 | content: 150 | application/json: 151 | schema: 152 | type: object 153 | properties: 154 | username: 155 | type: string 156 | example: ponelat 157 | uuid: 158 | type: string 159 | example: f7f680a8-d111-421f-b6b3-493ebf905078 160 | /tokens: 161 | post: 162 | description: Create a new token 163 | requestBody: 164 | content: 165 | application/json: 166 | schema: 167 | type: object 168 | properties: 169 | username: 170 | type: string 171 | example: ponelat 172 | password: 173 | type: string 174 | format: password 175 | 176 | responses: 177 | '201': 178 | description: Create a new token for gaining authenticated access to resources 179 | content: 180 | application/json: 181 | schema: 182 | type: object 183 | properties: 184 | token: 185 | type: string 186 | 187 | components: 188 | securitySchemes: 189 | MyUserToken: 190 | type: apiKey 191 | in: header 192 | name: Authorization 193 | -------------------------------------------------------------------------------- /ch08/02.yml: -------------------------------------------------------------------------------- 1 | openapi: 3.0.3 2 | info: 3 | version: v1 4 | title: FarmStall API 5 | description: |- 6 | 7 | An API for writing reviews about your favourite (or worst) farm stalls. 8 | 9 | ![Picture of produce](https://farmstall.designapis.com/img/produce-banner.jpg) 10 | 11 | --- 12 | 13 | # Auth 14 | 15 | To create **Reviews** without being _anonymous_. You need to add a **MyUserToken** to the `Authorization` header. 16 | 17 | To get a **MyUserToken**: 18 | 1. Create a **User** with [POST /users](#Users/post_users) 19 | 1. Get a **MyUserToken** by calling [POST /tokens](#Users/post_tokens) with your **User** credentials. 20 | 21 | # Reviews 22 | Reviews are the heart of this API.
23 | Registered **Users** and anonymous users can both write reviews based on their experience at farm stalls.
24 | 25 | Each review comes with a rating of between one and five stars inclusive. 26 | 27 | - One star being the worst experience 28 | - Five stars being the best 29 | 30 | 31 | ### Example Reviews 32 | 33 | "A wonderful time!" — Bob McNally 34 |
35 | ![5 stars](https://farmstall.designapis.com/img/rating-5.png) 36 | 37 | "An awful place" — _Anonymous_ 38 |
39 | ![1 star](https://farmstall.designapis.com/img/rating-1.png) 40 | 41 | "A totally average place." — Jane Fair 42 |
43 | ![3 stars](https://farmstall.designapis.com/img/rating-3.png) 44 | 45 | contact: 46 | name: Josh Ponelat 47 | email: jponelat+daso@gmail.com 48 | url: https://farmstall.designapis.com 49 | license: 50 | url: https://www.apache.org/licenses/LICENSE-2.0 51 | name: Apache 2.0 52 | externalDocs: 53 | url: https://farmstall.designapis.com 54 | description: Hosted docs 55 | servers: 56 | - url: https://farmstall.designapis.com/v1 57 | paths: 58 | /reviews: 59 | get: 60 | description: Get a list of reviews 61 | parameters: 62 | - name: maxRating 63 | in: query 64 | schema: 65 | type: number 66 | responses: 67 | '200': 68 | description: A bunch of reviews 69 | content: 70 | application/json: 71 | schema: 72 | type: array 73 | items: 74 | type: object 75 | properties: 76 | rating: 77 | type: integer 78 | minimum: 1 79 | maximum: 5 80 | message: 81 | type: string 82 | example: An awesome time for the whole family. 83 | uuid: 84 | type: string 85 | pattern: '^[0-9a-fA-F\-]{36}$' 86 | example: 3b5b1707-b82c-4b1d-9078-157053902525 87 | userId: 88 | type: string 89 | pattern: '^[0-9a-fA-F\-]{36}$' 90 | nullable: true 91 | example: 3b5b1707-b82c-4b1d-9078-157053902525 92 | post: 93 | description: Create a new Review 94 | security: 95 | - MyUserToken: [] 96 | requestBody: 97 | description: A new Review 98 | content: 99 | application/json: 100 | schema: 101 | type: object 102 | properties: 103 | message: 104 | type: string 105 | example: An awesome time for the whole family. 106 | rating: 107 | type: integer 108 | example: 5 109 | minimum: 1 110 | maximum: 5 111 | responses: 112 | '201': 113 | description: Successfully created a new Review 114 | content: 115 | application/json: 116 | schema: 117 | type: object 118 | properties: 119 | message: 120 | type: string 121 | example: An awesome time for the whole family. 122 | rating: 123 | type: integer 124 | example: 5 125 | minimum: 1 126 | maximum: 5 127 | userId: 128 | type: string 129 | nullable: true 130 | pattern: '^[0-9a-fA-F\-]{36}$' 131 | example: 3b5b1707-b82c-4b1d-9078-157053902525 132 | uuid: 133 | type: string 134 | pattern: '^[0-9a-fA-F\-]{36}$' 135 | example: 3b5b1707-b82c-4b1d-9078-157053902525 136 | /reviews/{reviewId}: 137 | get: 138 | description: Get a single review 139 | parameters: 140 | - name: reviewId 141 | in: path 142 | required: true 143 | schema: 144 | type: string 145 | description: The review's ID 146 | example: 3b5b1707-b82c-4b1d-9078-157053902525 147 | minLength: 36 148 | maxLength: 36 149 | pattern: '[a-zA-Z0-9-]+' 150 | responses: 151 | '200': 152 | description: A single review 153 | content: 154 | application/json: 155 | schema: 156 | type: object 157 | properties: 158 | message: 159 | type: string 160 | example: An awesome time for the whole family. 161 | rating: 162 | type: integer 163 | example: 5 164 | minimum: 1 165 | maximum: 5 166 | userId: 167 | minLength: 36 168 | maxLength: 36 169 | pattern: '^[a-zA-Z0-9-]+$' 170 | nullable: true 171 | example: 3b5b1707-b82c-4b1d-9078-157053902525 172 | uuid: 173 | minLength: 36 174 | maxLength: 36 175 | pattern: '^[a-zA-Z0-9-]+$' 176 | example: 3b5b1707-b82c-4b1d-9078-157053902525 177 | /users: 178 | post: 179 | description: Create a new user 180 | requestBody: 181 | description: User details 182 | content: 183 | application/json: 184 | schema: 185 | type: object 186 | properties: 187 | username: 188 | type: string 189 | example: ponelat 190 | password: 191 | type: string 192 | format: password 193 | fullName: 194 | type: string 195 | example: Josh Ponelat 196 | responses: 197 | '201': 198 | description: Successfully created a new user 199 | content: 200 | application/json: 201 | schema: 202 | type: object 203 | properties: 204 | username: 205 | type: string 206 | example: ponelat 207 | uuid: 208 | type: string 209 | example: f7f680a8-d111-421f-b6b3-493ebf905078 210 | /tokens: 211 | post: 212 | description: Create a new token 213 | requestBody: 214 | content: 215 | application/json: 216 | schema: 217 | type: object 218 | properties: 219 | username: 220 | type: string 221 | example: ponelat 222 | password: 223 | type: string 224 | format: password 225 | 226 | responses: 227 | '201': 228 | description: Create a new token for gaining authenticated access to resources 229 | content: 230 | application/json: 231 | schema: 232 | type: object 233 | properties: 234 | token: 235 | type: string 236 | 237 | components: 238 | securitySchemes: 239 | MyUserToken: 240 | type: apiKey 241 | in: header 242 | name: Authorization 243 | -------------------------------------------------------------------------------- /ch08/markdown-cheatsheet.yml: -------------------------------------------------------------------------------- 1 | openapi: 3.0.3 2 | info: 3 | version: v1 4 | title: FarmStall API 5 | description: |- 6 | *\*italic\** 7 | 8 | 9 | **\*\*bold\*\*** 10 | 11 | 12 | _\_Mix of italic and **\*\*bold\*\***\__ 13 | 14 | > \> Block quote 15 | 16 | # \# Heading 1 17 | 18 | 19 | ## \#\# Heading 2 20 | 21 | 22 | ### \#\#\# Heading 3 23 | 24 | [\[A link\]\(https://example.com\)]() 25 | 26 | 27 | \![An image]\(/img/rating-5.png) 28 | ![](https://farmstall.designapis.com/img/rating-5.png) 29 | 30 | \* unordered list
31 | \* two
32 | \* three
33 | 34 | 1\. numbered list
35 | 1\. two
36 | 1\. three 37 | 38 | \--- (horizontal line) 39 | 40 | --- 41 | 42 | 43 | ``` 44 | A code block 45 | ``` 46 | 47 | 48 | paths: {} 49 | -------------------------------------------------------------------------------- /ch08/openapi.yml: -------------------------------------------------------------------------------- 1 | openapi: 3.0.3 2 | info: 3 | version: v1 4 | title: FarmStall API 5 | description: |- 6 | 7 | An API for writing reviews about your favourite (or worst) farm stalls. 8 | 9 | ![Picture of produce](https://farmstall.designapis.com/img/produce-banner.jpg) 10 | 11 | --- 12 | 13 | # Auth 14 | 15 | To create **Reviews** without being _anonymous_. You need to add a **MyUserToken** to the `Authorization` header. 16 | 17 | To get a **MyUserToken**: 18 | 1. Create a **User** with [POST /users](#Users/post_users) 19 | 1. Get a **MyUserToken** by calling [POST /tokens](#Users/post_tokens) with your **User** credentials. 20 | 21 | # Reviews 22 | Reviews are the heart of this API.
23 | Registered **Users** and anonymous users can both write reviews based on their experience at farm stalls.
24 | 25 | Each review comes with a rating of between one and five stars inclusive. 26 | 27 | - One star being the worst experience 28 | - Five stars being the best 29 | 30 | 31 | ### Example Reviews 32 | 33 | "A wonderful time!" — Bob McNally 34 |
35 | ![5 stars](https://farmstall.designapis.com/img/rating-5.png) 36 | 37 | "An awful place" — _Anonymous_ 38 |
39 | ![1 star](https://farmstall.designapis.com/img/rating-1.png) 40 | 41 | "A totally average place." — Jane Fair 42 |
43 | ![3 stars](https://farmstall.designapis.com/img/rating-3.png) 44 | 45 | contact: 46 | name: Josh Ponelat 47 | email: jponelat+daso@gmail.com 48 | url: https://farmstall.designapis.com 49 | 50 | license: 51 | url: https://www.apache.org/licenses/LICENSE-2.0 52 | name: Apache 2.0 53 | 54 | externalDocs: 55 | url: https://farmstall.designapis.com 56 | description: Hosted docs 57 | 58 | tags: 59 | - name: Reviews 60 | description: Reviews of your favourite/worst farm stalls 61 | 62 | - name: Users 63 | description: Users and authentication 64 | 65 | servers: 66 | - url: 'https://farmstall.designapis.com/v1' 67 | 68 | paths: 69 | /reviews: 70 | get: 71 | tags: 72 | - Reviews 73 | description: Get a list of reviews 74 | parameters: 75 | - name: maxRating 76 | in: query 77 | schema: 78 | type: number 79 | responses: 80 | '200': 81 | description: A bunch of reviews 82 | content: 83 | application/json: 84 | schema: 85 | type: array 86 | items: 87 | type: object 88 | properties: 89 | rating: 90 | type: integer 91 | minimum: 1 92 | maximum: 5 93 | message: 94 | type: string 95 | example: An awesome time for the whole family. 96 | uuid: 97 | type: string 98 | pattern: '^[0-9a-fA-F\-]{36}$' 99 | example: 3b5b1707-b82c-4b1d-9078-157053902525 100 | userId: 101 | type: string 102 | pattern: '^[0-9a-fA-F\-]{36}$' 103 | nullable: true 104 | example: 3b5b1707-b82c-4b1d-9078-157053902525 105 | 106 | post: 107 | tags: 108 | - Reviews 109 | description: Create a new Review 110 | security: 111 | - MyUserToken: [] 112 | requestBody: 113 | description: A new Review 114 | content: 115 | application/json: 116 | schema: 117 | type: object 118 | properties: 119 | message: 120 | type: string 121 | example: An awesome time for the whole family. 122 | rating: 123 | type: integer 124 | minimum: 1 125 | maximum: 5 126 | example: 5 127 | responses: 128 | '201': 129 | description: Successfully created a new Review 130 | content: 131 | application/json: 132 | schema: 133 | type: object 134 | properties: 135 | message: 136 | type: string 137 | example: An awesome time for the whole family. 138 | rating: 139 | type: integer 140 | minimum: 1 141 | maximum: 5 142 | example: 5 143 | userId: 144 | type: string 145 | nullable: true 146 | pattern: '^[0-9a-fA-F\-]{36}$' 147 | example: 3b5b1707-b82c-4b1d-9078-157053902525 148 | uuid: 149 | type: string 150 | pattern: '^[0-9a-fA-F\-]{36}$' 151 | example: 3b5b1707-b82c-4b1d-9078-157053902525 152 | 153 | 154 | /reviews/{reviewId}: 155 | get: 156 | tags: 157 | - Reviews 158 | description: Get a single review 159 | parameters: 160 | - name: reviewId 161 | in: path 162 | required: true 163 | schema: 164 | type: string 165 | description: The review's ID 166 | example: 3b5b1707-b82c-4b1d-9078-157053902525 167 | minLength: 36 168 | maxLength: 36 169 | pattern: '[a-zA-Z0-9-]+' 170 | responses: 171 | '200': 172 | description: A single review 173 | content: 174 | application/json: 175 | schema: 176 | type: object 177 | properties: 178 | message: 179 | type: string 180 | example: An awesome time for the whole family. 181 | rating: 182 | type: integer 183 | minimum: 1 184 | maximum: 5 185 | example: 5 186 | userId: 187 | minLength: 36 188 | maxLength: 36 189 | pattern: '^[a-zA-Z0-9-]+$' 190 | nullable: true 191 | example: 3b5b1707-b82c-4b1d-9078-157053902525 192 | uuid: 193 | minLength: 36 194 | maxLength: 36 195 | pattern: '^[a-zA-Z0-9-]+$' 196 | example: 3b5b1707-b82c-4b1d-9078-157053902525 197 | '404': 198 | description: Review not found 199 | 200 | 201 | 202 | /users: 203 | post: 204 | tags: 205 | - Users 206 | description: Create a new user 207 | requestBody: 208 | description: User details 209 | content: 210 | application/json: 211 | schema: 212 | type: object 213 | properties: 214 | username: 215 | type: string 216 | example: ponelat 217 | password: 218 | type: string 219 | format: password 220 | fullName: 221 | type: string 222 | example: Josh Ponelat 223 | responses: 224 | '201': 225 | description: Successfully created a new user 226 | content: 227 | application/json: 228 | schema: 229 | type: object 230 | properties: 231 | username: 232 | type: string 233 | example: ponelat 234 | uuid: 235 | type: string 236 | example: f7f680a8-d111-421f-b6b3-493ebf905078 237 | 238 | 239 | /tokens: 240 | post: 241 | tags: 242 | - Users 243 | description: Create a new token 244 | requestBody: 245 | content: 246 | application/json: 247 | schema: 248 | type: object 249 | properties: 250 | username: 251 | type: string 252 | example: ponelat 253 | password: 254 | type: string 255 | format: password 256 | 257 | responses: 258 | '201': 259 | description: Create a new token for gaining authenticated access to resources 260 | content: 261 | application/json: 262 | schema: 263 | type: object 264 | properties: 265 | token: 266 | type: string 267 | 268 | 269 | components: 270 | securitySchemes: 271 | MyUserToken: 272 | name: Authorization 273 | type: apiKey 274 | in: header 275 | -------------------------------------------------------------------------------- /ch08/site/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | FarmStall API v1 9 | 10 | 11 | 12 |
13 | 14 | 15 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /ch08/site/openapi.yml: -------------------------------------------------------------------------------- 1 | openapi: 3.0.3 2 | info: 3 | version: v1 4 | title: FarmStall API 5 | description: |- 6 | 7 | An API for writing reviews about your favourite (or worst) farm stalls. 8 | 9 | ![Picture of produce](https://farmstall.designapis.com/img/produce-banner.jpg) 10 | 11 | --- 12 | 13 | # Auth 14 | 15 | To create **Reviews** without being _anonymous_. You need to add a **MyUserToken** to the `Authorization` header. 16 | 17 | To get a **MyUserToken**: 18 | 1. Create a **User** with [POST /users](#Users/post_users) 19 | 1. Get a **MyUserToken** by calling [POST /tokens](#Users/post_tokens) with your **User** credentials. 20 | 21 | # Reviews 22 | Reviews are the heart of this API.
23 | Registered **Users** and anonymous users can both write reviews based on their experience at farm stalls.
24 | 25 | Each review comes with a rating of between one and five stars inclusive. 26 | 27 | - One star being the worst experience 28 | - Five stars being the best 29 | 30 | 31 | ### Example Reviews 32 | 33 | "A wonderful time!" — Bob McNally 34 |
35 | ![5 stars](https://farmstall.designapis.com/img/rating-5.png) 36 | 37 | "An awful place" — _Anonymous_ 38 |
39 | ![1 star](https://farmstall.designapis.com/img/rating-1.png) 40 | 41 | "A totally average place." — Jane Fair 42 |
43 | ![3 stars](https://farmstall.designapis.com/img/rating-3.png) 44 | 45 | contact: 46 | name: Josh Ponelat 47 | email: jponelat+daso@gmail.com 48 | url: https://farmstall.designapis.com 49 | 50 | license: 51 | url: https://www.apache.org/licenses/LICENSE-2.0 52 | name: Apache 2.0 53 | 54 | externalDocs: 55 | url: https://farmstall.designapis.com 56 | description: Hosted docs 57 | 58 | tags: 59 | - name: Reviews 60 | description: Reviews of your favourite/worst farm stalls 61 | 62 | - name: Users 63 | description: Users and authentication 64 | 65 | servers: 66 | - url: 'https://farmstall.designapis.com/v1' 67 | 68 | paths: 69 | /reviews: 70 | get: 71 | tags: 72 | - Reviews 73 | description: Get a list of reviews 74 | parameters: 75 | - name: maxRating 76 | in: query 77 | schema: 78 | type: number 79 | responses: 80 | '200': 81 | description: A bunch of reviews 82 | content: 83 | application/json: 84 | schema: 85 | type: array 86 | items: 87 | type: object 88 | properties: 89 | rating: 90 | type: integer 91 | minimum: 1 92 | maximum: 5 93 | message: 94 | type: string 95 | example: An awesome time for the whole family. 96 | uuid: 97 | type: string 98 | pattern: '^[0-9a-fA-F\-]{36}$' 99 | example: 3b5b1707-b82c-4b1d-9078-157053902525 100 | userId: 101 | type: string 102 | pattern: '^[0-9a-fA-F\-]{36}$' 103 | nullable: true 104 | example: 3b5b1707-b82c-4b1d-9078-157053902525 105 | 106 | post: 107 | tags: 108 | - Reviews 109 | description: Create a new Review 110 | security: 111 | - MyUserToken: [] 112 | requestBody: 113 | description: A new Review 114 | content: 115 | application/json: 116 | schema: 117 | type: object 118 | properties: 119 | message: 120 | type: string 121 | example: An awesome time for the whole family. 122 | rating: 123 | type: integer 124 | minimum: 1 125 | maximum: 5 126 | example: 5 127 | responses: 128 | '201': 129 | description: Successfully created a new Review 130 | content: 131 | application/json: 132 | schema: 133 | type: object 134 | properties: 135 | message: 136 | type: string 137 | example: An awesome time for the whole family. 138 | rating: 139 | type: integer 140 | minimum: 1 141 | maximum: 5 142 | example: 5 143 | userId: 144 | type: string 145 | nullable: true 146 | pattern: '^[0-9a-fA-F\-]{36}$' 147 | example: 3b5b1707-b82c-4b1d-9078-157053902525 148 | uuid: 149 | type: string 150 | pattern: '^[0-9a-fA-F\-]{36}$' 151 | example: 3b5b1707-b82c-4b1d-9078-157053902525 152 | 153 | 154 | /reviews/{reviewId}: 155 | get: 156 | tags: 157 | - Reviews 158 | description: Get a single review 159 | parameters: 160 | - name: reviewId 161 | in: path 162 | required: true 163 | schema: 164 | type: string 165 | description: The review's ID 166 | example: 3b5b1707-b82c-4b1d-9078-157053902525 167 | minLength: 36 168 | maxLength: 36 169 | pattern: '[a-zA-Z0-9-]+' 170 | responses: 171 | '200': 172 | description: A single review 173 | content: 174 | application/json: 175 | schema: 176 | type: object 177 | properties: 178 | message: 179 | type: string 180 | example: An awesome time for the whole family. 181 | rating: 182 | type: integer 183 | minimum: 1 184 | maximum: 5 185 | example: 5 186 | userId: 187 | minLength: 36 188 | maxLength: 36 189 | pattern: '^[a-zA-Z0-9-]+$' 190 | nullable: true 191 | example: 3b5b1707-b82c-4b1d-9078-157053902525 192 | uuid: 193 | minLength: 36 194 | maxLength: 36 195 | pattern: '^[a-zA-Z0-9-]+$' 196 | example: 3b5b1707-b82c-4b1d-9078-157053902525 197 | '404': 198 | description: Review not found 199 | 200 | 201 | 202 | /users: 203 | post: 204 | tags: 205 | - Users 206 | description: Create a new user 207 | requestBody: 208 | description: User details 209 | content: 210 | application/json: 211 | schema: 212 | type: object 213 | properties: 214 | username: 215 | type: string 216 | example: ponelat 217 | password: 218 | type: string 219 | format: password 220 | fullName: 221 | type: string 222 | example: Josh Ponelat 223 | responses: 224 | '201': 225 | description: Successfully created a new user 226 | content: 227 | application/json: 228 | schema: 229 | type: object 230 | properties: 231 | username: 232 | type: string 233 | example: ponelat 234 | uuid: 235 | type: string 236 | example: f7f680a8-d111-421f-b6b3-493ebf905078 237 | 238 | 239 | /tokens: 240 | post: 241 | tags: 242 | - Users 243 | description: Create a new token 244 | requestBody: 245 | content: 246 | application/json: 247 | schema: 248 | type: object 249 | properties: 250 | username: 251 | type: string 252 | example: ponelat 253 | password: 254 | type: string 255 | format: password 256 | 257 | responses: 258 | '201': 259 | description: Create a new token for gaining authenticated access to resources 260 | content: 261 | application/json: 262 | schema: 263 | type: object 264 | properties: 265 | token: 266 | type: string 267 | 268 | 269 | components: 270 | securitySchemes: 271 | MyUserToken: 272 | name: Authorization 273 | type: apiKey 274 | in: header 275 | -------------------------------------------------------------------------------- /ch08/site/site.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/designapis/openapi/4b0cc3d98e9682a81bc00163f3acedd7b3cfdd3c/ch08/site/site.zip -------------------------------------------------------------------------------- /ch10/01.yml: -------------------------------------------------------------------------------- 1 | openapi: 3.0.3 2 | info: 3 | title: PetSitter API 4 | version: "0.1" 5 | paths: {} 6 | components: 7 | schemas: 8 | User: 9 | type: object 10 | properties: 11 | id: 12 | type: integer 13 | email: 14 | type: string 15 | password: 16 | type: string 17 | full_name: 18 | type: string 19 | roles: 20 | type: array 21 | items: 22 | type: string 23 | -------------------------------------------------------------------------------- /ch10/README.md: -------------------------------------------------------------------------------- 1 | # Chapter 10: Creating an API design using OpenAPI 2 | 3 | Supporting files for [chapter 10 of Designing APIs with Swagger and OpenAPI](https://livebook.manning.com/book/designing-apis-with-swagger-and-openapi/chapter-10). 4 | -------------------------------------------------------------------------------- /ch10/openapi.yml: -------------------------------------------------------------------------------- 1 | openapi: 3.0.3 2 | info: 3 | title: PetSitter API 4 | version: "0.1" 5 | paths: 6 | /users: 7 | post: 8 | summary: Register User 9 | responses: 10 | '201': 11 | description: Created 12 | headers: 13 | Location: 14 | schema: 15 | type: string 16 | requestBody: 17 | content: 18 | application/json: 19 | schema: 20 | $ref: '#/components/schemas/User' 21 | /users/{id}: 22 | parameters: 23 | - schema: 24 | type: integer 25 | name: id 26 | in: path 27 | required: true 28 | get: 29 | summary: View User 30 | responses: 31 | '200': 32 | description: OK 33 | content: 34 | application/json: 35 | schema: 36 | $ref: '#/components/schemas/User' 37 | put: 38 | summary: Modify User 39 | responses: 40 | '200': 41 | description: OK 42 | content: 43 | application/json: 44 | schema: 45 | $ref: '#/components/schemas/User' 46 | requestBody: 47 | content: 48 | application/json: 49 | schema: 50 | $ref: '#/components/schemas/User' 51 | delete: 52 | summary: Delete User 53 | responses: 54 | '204': 55 | description: No Content 56 | /jobs: 57 | post: 58 | summary: Create Job 59 | responses: 60 | '201': 61 | description: Created 62 | headers: 63 | Location: 64 | schema: 65 | type: string 66 | requestBody: 67 | content: 68 | application/json: 69 | schema: 70 | $ref: '#/components/schemas/Job' 71 | get: 72 | summary: List All Jobs 73 | responses: 74 | '200': 75 | description: OK 76 | content: 77 | application/json: 78 | schema: 79 | type: object 80 | properties: 81 | items: 82 | type: array 83 | items: 84 | $ref: '#/components/schemas/Job' 85 | /jobs/{id}: 86 | parameters: 87 | - schema: 88 | type: integer 89 | name: id 90 | in: path 91 | required: true 92 | get: 93 | summary: View Job 94 | responses: 95 | '200': 96 | description: OK 97 | content: 98 | application/json: 99 | schema: 100 | $ref: '#/components/schemas/Job' 101 | put: 102 | summary: Modify Job 103 | responses: 104 | '200': 105 | description: OK 106 | content: 107 | application/json: 108 | schema: 109 | $ref: '#/components/schemas/Job' 110 | requestBody: 111 | content: 112 | application/json: 113 | schema: 114 | $ref: '#/components/schemas/Job' 115 | /jobs/{id}/job-applications: 116 | parameters: 117 | - schema: 118 | type: integer 119 | name: id 120 | in: path 121 | required: true 122 | get: 123 | summary: List Applications For Job 124 | responses: 125 | '200': 126 | description: OK 127 | content: 128 | application/json: 129 | schema: 130 | type: object 131 | properties: 132 | items: 133 | type: array 134 | items: 135 | $ref: '#/components/schemas/JobApplication' 136 | post: 137 | summary: Create Job Application 138 | responses: 139 | '201': 140 | description: Created 141 | headers: 142 | Location: 143 | schema: 144 | type: string 145 | requestBody: 146 | content: 147 | application/json: 148 | schema: 149 | $ref: '#/components/schemas/JobApplication' 150 | /users/{id}/jobs: 151 | parameters: 152 | - schema: 153 | type: integer 154 | name: id 155 | in: path 156 | required: true 157 | get: 158 | summary: List Jobs For User 159 | responses: 160 | '200': 161 | description: OK 162 | content: 163 | application/json: 164 | schema: 165 | type: object 166 | properties: 167 | items: 168 | type: array 169 | items: 170 | $ref: '#/components/schemas/Job' 171 | /job-applications/{id}: 172 | parameters: 173 | - schema: 174 | type: integer 175 | name: id 176 | in: path 177 | required: true 178 | put: 179 | summary: Modify Job Application 180 | requestBody: 181 | description: Update the application details 182 | content: 183 | application/json: 184 | schema: 185 | $ref: '#/components/schemas/JobApplication' 186 | 187 | responses: 188 | '200': 189 | description: OK 190 | content: 191 | application/json: 192 | schema: 193 | $ref: '#/components/schemas/JobApplication' 194 | components: 195 | schemas: 196 | User: 197 | type: object 198 | properties: 199 | id: 200 | type: integer 201 | email: 202 | type: string 203 | password: 204 | type: string 205 | full_name: 206 | type: string 207 | roles: 208 | type: array 209 | items: 210 | type: string 211 | Job: 212 | type: object 213 | properties: 214 | id: 215 | type: integer 216 | creator_user_id: 217 | type: integer 218 | start_time: 219 | type: string 220 | end_time: 221 | type: string 222 | activity: 223 | type: string 224 | dog: 225 | $ref: '#/components/schemas/Dog' 226 | Dog: 227 | type: object 228 | properties: 229 | name: 230 | type: string 231 | age: 232 | type: integer 233 | breed: 234 | type: string 235 | size: 236 | type: string 237 | JobApplication: 238 | type: object 239 | properties: 240 | id: 241 | type: integer 242 | status: 243 | type: string 244 | user_id: 245 | type: integer 246 | job_id: 247 | type: integer 248 | -------------------------------------------------------------------------------- /ch11/README.md: -------------------------------------------------------------------------------- 1 | # Chapter 11: Building a change workflow around API Design First 2 | 3 | Supporting files for [chapter 11 of Designing APIs with Swagger and OpenAPI](https://livebook.manning.com/book/designing-apis-with-swagger-and-openapi/chapter-11). 4 | -------------------------------------------------------------------------------- /ch11/openapi.yml: -------------------------------------------------------------------------------- 1 | openapi: 3.0.3 2 | info: 3 | title: PetSitter API 4 | version: "0.1" 5 | paths: 6 | /users: 7 | post: 8 | summary: Register User 9 | responses: 10 | '201': 11 | description: Created 12 | headers: 13 | Location: 14 | schema: 15 | type: string 16 | requestBody: 17 | content: 18 | application/json: 19 | schema: 20 | $ref: '#/components/schemas/User' 21 | /users/{id}: 22 | parameters: 23 | - schema: 24 | type: integer 25 | name: id 26 | in: path 27 | required: true 28 | get: 29 | summary: View User 30 | responses: 31 | '200': 32 | description: OK 33 | content: 34 | application/json: 35 | schema: 36 | $ref: '#/components/schemas/User' 37 | put: 38 | summary: Modify User 39 | responses: 40 | '200': 41 | description: OK 42 | content: 43 | application/json: 44 | schema: 45 | $ref: '#/components/schemas/User' 46 | requestBody: 47 | content: 48 | application/json: 49 | schema: 50 | $ref: '#/components/schemas/User' 51 | delete: 52 | summary: Delete User 53 | responses: 54 | '204': 55 | description: No Content 56 | /jobs: 57 | post: 58 | summary: Create Job 59 | responses: 60 | '201': 61 | description: Created 62 | headers: 63 | Location: 64 | schema: 65 | type: string 66 | requestBody: 67 | content: 68 | application/json: 69 | schema: 70 | $ref: '#/components/schemas/Job' 71 | get: 72 | summary: List All Jobs 73 | responses: 74 | '200': 75 | description: OK 76 | content: 77 | application/json: 78 | schema: 79 | type: object 80 | properties: 81 | items: 82 | type: array 83 | items: 84 | $ref: '#/components/schemas/Job' 85 | /jobs/{id}: 86 | parameters: 87 | - schema: 88 | type: integer 89 | name: id 90 | in: path 91 | required: true 92 | get: 93 | summary: View Job 94 | responses: 95 | '200': 96 | description: OK 97 | content: 98 | application/json: 99 | schema: 100 | $ref: '#/components/schemas/Job' 101 | put: 102 | summary: Modify Job 103 | responses: 104 | '200': 105 | description: OK 106 | content: 107 | application/json: 108 | schema: 109 | $ref: '#/components/schemas/Job' 110 | requestBody: 111 | content: 112 | application/json: 113 | schema: 114 | $ref: '#/components/schemas/Job' 115 | delete: 116 | summary: Delete Job 117 | responses: 118 | '204': 119 | description: No Content 120 | /jobs/{id}/job-applications: 121 | parameters: 122 | - schema: 123 | type: integer 124 | name: id 125 | in: path 126 | required: true 127 | get: 128 | summary: List Applications For Job 129 | responses: 130 | '200': 131 | description: OK 132 | content: 133 | application/json: 134 | schema: 135 | type: object 136 | properties: 137 | items: 138 | type: array 139 | items: 140 | $ref: '#/components/schemas/JobApplication' 141 | post: 142 | summary: Create Job Application 143 | responses: 144 | '201': 145 | description: Created 146 | headers: 147 | Location: 148 | schema: 149 | type: string 150 | requestBody: 151 | content: 152 | application/json: 153 | schema: 154 | $ref: '#/components/schemas/JobApplication' 155 | /users/{id}/jobs: 156 | parameters: 157 | - schema: 158 | type: integer 159 | name: id 160 | in: path 161 | required: true 162 | get: 163 | summary: List Jobs For User 164 | responses: 165 | '200': 166 | description: OK 167 | content: 168 | application/json: 169 | schema: 170 | type: object 171 | properties: 172 | items: 173 | type: array 174 | items: 175 | $ref: '#/components/schemas/Job' 176 | /job-applications/{id}: 177 | parameters: 178 | - schema: 179 | type: integer 180 | name: id 181 | in: path 182 | required: true 183 | put: 184 | summary: Modify Job Application 185 | requestBody: 186 | description: Update the application details 187 | content: 188 | application/json: 189 | schema: 190 | $ref: '#/components/schemas/JobApplication' 191 | 192 | responses: 193 | '200': 194 | description: OK 195 | content: 196 | application/json: 197 | schema: 198 | $ref: '#/components/schemas/JobApplication' 199 | components: 200 | schemas: 201 | User: 202 | type: object 203 | properties: 204 | id: 205 | type: integer 206 | email: 207 | type: string 208 | password: 209 | type: string 210 | full_name: 211 | type: string 212 | roles: 213 | type: array 214 | items: 215 | type: string 216 | Job: 217 | type: object 218 | properties: 219 | id: 220 | type: integer 221 | creator_user_id: 222 | type: integer 223 | start_time: 224 | type: string 225 | end_time: 226 | type: string 227 | activity: 228 | type: string 229 | dog: 230 | $ref: '#/components/schemas/Dog' 231 | Dog: 232 | type: object 233 | properties: 234 | name: 235 | type: string 236 | age: 237 | type: integer 238 | breed: 239 | type: string 240 | size: 241 | type: string 242 | JobApplication: 243 | type: object 244 | properties: 245 | id: 246 | type: integer 247 | status: 248 | type: string 249 | user_id: 250 | type: integer 251 | job_id: 252 | type: integer 253 | -------------------------------------------------------------------------------- /ch12/01.yml: -------------------------------------------------------------------------------- 1 | openapi: 3.0.3 2 | info: 3 | title: PetSitter API 4 | version: "0.1" 5 | paths: 6 | /users: 7 | post: 8 | summary: Register User 9 | responses: 10 | '201': 11 | description: Created 12 | headers: 13 | Location: 14 | schema: 15 | type: string 16 | requestBody: 17 | content: 18 | application/json: 19 | schema: 20 | $ref: '#/components/schemas/User' 21 | /users/{id}: 22 | parameters: 23 | - schema: 24 | type: integer 25 | name: id 26 | in: path 27 | required: true 28 | get: 29 | summary: View User 30 | responses: 31 | '200': 32 | description: OK 33 | content: 34 | application/json: 35 | schema: 36 | $ref: '#/components/schemas/User' 37 | put: 38 | summary: Modify User 39 | responses: 40 | '200': 41 | description: OK 42 | content: 43 | application/json: 44 | schema: 45 | $ref: '#/components/schemas/User' 46 | requestBody: 47 | content: 48 | application/json: 49 | schema: 50 | $ref: '#/components/schemas/User' 51 | delete: 52 | summary: Delete User 53 | responses: 54 | '204': 55 | description: No Content 56 | /jobs: 57 | post: 58 | summary: Create Job 59 | responses: 60 | '201': 61 | description: Created 62 | headers: 63 | Location: 64 | schema: 65 | type: string 66 | requestBody: 67 | content: 68 | application/json: 69 | schema: 70 | $ref: '#/components/schemas/Job' 71 | get: 72 | summary: List All Jobs 73 | responses: 74 | '200': 75 | description: OK 76 | content: 77 | application/json: 78 | schema: 79 | type: object 80 | properties: 81 | items: 82 | type: array 83 | items: 84 | $ref: '#/components/schemas/Job' 85 | examples: 86 | with-some-data: 87 | summary: With some data 88 | value: 89 | items: 90 | - id: 123 91 | creator_user_id: 345 92 | start_time: 2020-06-01T00:00:00Z 93 | end_time: 2020-06-02T00:00:00Z 94 | dog: 95 | name: Fido 96 | age: 3 97 | breed: Doberman 98 | size: medium 99 | activity: walk 100 | - id: 234 101 | creator_user_id: 345 102 | start_time: 2020-06-01T00:00:00Z 103 | end_time: 2020-06-03T00:00:00Z 104 | dog: 105 | name: Rex 106 | age: 2 107 | breed: Rottweiler 108 | size: large 109 | activity: sit 110 | - id: 234 111 | creator_user_id: 345 112 | start_time: 2020-06-01T00:00:00Z 113 | end_time: 2020-06-02T00:00:00Z 114 | dog: 115 | name: Blossom 116 | age: 2 117 | breed: Rottweiler 118 | size: large 119 | activity: walk 120 | 121 | /jobs/{id}: 122 | parameters: 123 | - schema: 124 | type: integer 125 | name: id 126 | in: path 127 | required: true 128 | get: 129 | summary: View Job 130 | responses: 131 | '200': 132 | description: OK 133 | content: 134 | application/json: 135 | schema: 136 | $ref: '#/components/schemas/Job' 137 | put: 138 | summary: Modify Job 139 | responses: 140 | '200': 141 | description: OK 142 | content: 143 | application/json: 144 | schema: 145 | $ref: '#/components/schemas/Job' 146 | requestBody: 147 | content: 148 | application/json: 149 | schema: 150 | $ref: '#/components/schemas/Job' 151 | delete: 152 | summary: Delete Job 153 | responses: 154 | '204': 155 | description: No Content 156 | /jobs/{id}/job-applications: 157 | parameters: 158 | - schema: 159 | type: integer 160 | name: id 161 | in: path 162 | required: true 163 | get: 164 | summary: List Applications For Job 165 | responses: 166 | '200': 167 | description: OK 168 | content: 169 | application/json: 170 | schema: 171 | type: object 172 | properties: 173 | items: 174 | type: array 175 | items: 176 | $ref: '#/components/schemas/JobApplication' 177 | post: 178 | summary: Create Job Application 179 | responses: 180 | '201': 181 | description: Created 182 | headers: 183 | Location: 184 | schema: 185 | type: string 186 | requestBody: 187 | content: 188 | application/json: 189 | schema: 190 | $ref: '#/components/schemas/JobApplication' 191 | /users/{id}/jobs: 192 | parameters: 193 | - schema: 194 | type: integer 195 | name: id 196 | in: path 197 | required: true 198 | get: 199 | summary: List Jobs For User 200 | responses: 201 | '200': 202 | description: OK 203 | content: 204 | application/json: 205 | schema: 206 | type: object 207 | properties: 208 | items: 209 | type: array 210 | items: 211 | $ref: '#/components/schemas/Job' 212 | /job-applications/{id}: 213 | parameters: 214 | - schema: 215 | type: integer 216 | name: id 217 | in: path 218 | required: true 219 | put: 220 | summary: Modify Job Application 221 | requestBody: 222 | description: Update the application details 223 | content: 224 | application/json: 225 | schema: 226 | $ref: '#/components/schemas/JobApplication' 227 | 228 | responses: 229 | '200': 230 | description: OK 231 | content: 232 | application/json: 233 | schema: 234 | $ref: '#/components/schemas/JobApplication' 235 | components: 236 | schemas: 237 | User: 238 | type: object 239 | properties: 240 | id: 241 | type: integer 242 | email: 243 | type: string 244 | password: 245 | type: string 246 | full_name: 247 | type: string 248 | roles: 249 | type: array 250 | items: 251 | type: string 252 | Job: 253 | type: object 254 | properties: 255 | id: 256 | type: integer 257 | creator_user_id: 258 | type: integer 259 | start_time: 260 | type: string 261 | end_time: 262 | type: string 263 | activity: 264 | type: string 265 | dog: 266 | $ref: '#/components/schemas/Dog' 267 | Dog: 268 | type: object 269 | properties: 270 | name: 271 | type: string 272 | age: 273 | type: integer 274 | breed: 275 | type: string 276 | size: 277 | type: string 278 | JobApplication: 279 | type: object 280 | properties: 281 | id: 282 | type: integer 283 | status: 284 | type: string 285 | user_id: 286 | type: integer 287 | job_id: 288 | type: integer 289 | -------------------------------------------------------------------------------- /ch12/02.yml: -------------------------------------------------------------------------------- 1 | items: 2 | - id: 0 3 | user_id: 358 4 | job_id: 4012 5 | status: COMPLETE 6 | - id: 1 7 | user_id: 3089 8 | job_id: 3902 9 | status: PENDING 10 | - id: 2 11 | user_id: 4040 12 | job_id: 5269 13 | status: PENDING 14 | - id: 3 15 | user_id: 5636 16 | job_id: 8420 17 | status: PENDING 18 | - id: 4 19 | user_id: 9540 20 | job_id: 9505 21 | status: COMPLETE 22 | - id: 5 23 | user_id: 9873 24 | job_id: 3215 25 | status: PENDING 26 | - id: 6 27 | user_id: 6032 28 | job_id: 7365 29 | status: COMPLETE 30 | - id: 7 31 | user_id: 5999 32 | job_id: 1159 33 | status: COMPLETE 34 | - id: 8 35 | user_id: 2897 36 | job_id: 7982 37 | status: COMPLETE 38 | - id: 9 39 | user_id: 227 40 | job_id: 9245 41 | status: CANCELLED 42 | - id: 10 43 | user_id: 741 44 | job_id: 2752 45 | status: CANCELLED 46 | - id: 11 47 | user_id: 9059 48 | job_id: 338 49 | status: PENDING 50 | - id: 12 51 | user_id: 1379 52 | job_id: 4531 53 | status: COMPLETE 54 | - id: 13 55 | user_id: 2031 56 | job_id: 9375 57 | status: COMPLETE 58 | - id: 14 59 | user_id: 3643 60 | job_id: 5175 61 | status: CANCELLED 62 | - id: 15 63 | user_id: 5470 64 | job_id: 831 65 | status: CANCELLED 66 | - id: 16 67 | user_id: 3265 68 | job_id: 5597 69 | status: PENDING 70 | - id: 17 71 | user_id: 2815 72 | job_id: 7719 73 | status: PENDING 74 | - id: 18 75 | user_id: 8306 76 | job_id: 679 77 | status: PENDING 78 | - id: 19 79 | user_id: 9742 80 | job_id: 8239 81 | status: PENDING 82 | - id: 20 83 | user_id: 4851 84 | job_id: 940 85 | status: PENDING 86 | - id: 21 87 | user_id: 6700 88 | job_id: 4040 89 | status: PENDING 90 | - id: 22 91 | user_id: 7067 92 | job_id: 6016 93 | status: PENDING 94 | - id: 23 95 | user_id: 3265 96 | job_id: 1822 97 | status: PENDING 98 | - id: 24 99 | user_id: 8333 100 | job_id: 9988 101 | status: PENDING 102 | - id: 25 103 | user_id: 7543 104 | job_id: 9307 105 | status: PENDING 106 | - id: 26 107 | user_id: 5429 108 | job_id: 7511 109 | status: COMPLETE 110 | - id: 27 111 | user_id: 3576 112 | job_id: 1710 113 | status: PENDING 114 | - id: 28 115 | user_id: 590 116 | job_id: 2634 117 | status: COMPLETE 118 | - id: 29 119 | user_id: 2327 120 | job_id: 7205 121 | status: CANCELLED 122 | - id: 30 123 | user_id: 2193 124 | job_id: 7421 125 | status: COMPLETE 126 | - id: 31 127 | user_id: 5014 128 | job_id: 6781 129 | status: CANCELLED 130 | - id: 32 131 | user_id: 9216 132 | job_id: 8047 133 | status: COMPLETE 134 | - id: 33 135 | user_id: 3369 136 | job_id: 7438 137 | status: CANCELLED 138 | - id: 34 139 | user_id: 9825 140 | job_id: 6758 141 | status: PENDING 142 | - id: 35 143 | user_id: 3250 144 | job_id: 7760 145 | status: COMPLETE 146 | - id: 36 147 | user_id: 1552 148 | job_id: 4030 149 | status: COMPLETE 150 | - id: 37 151 | user_id: 9221 152 | job_id: 3971 153 | status: CANCELLED 154 | - id: 38 155 | user_id: 6816 156 | job_id: 7878 157 | status: PENDING 158 | - id: 39 159 | user_id: 6109 160 | job_id: 4060 161 | status: CANCELLED 162 | -------------------------------------------------------------------------------- /ch12/03.yml: -------------------------------------------------------------------------------- 1 | openapi: 3.0.3 2 | info: 3 | title: Tiny API 4 | version: "1.0.0" 5 | paths: 6 | /foo: 7 | get: 8 | description: Simple get 9 | responses: 10 | '200': 11 | description: Get Foo 12 | content: 13 | application/json: 14 | examples: 15 | one: 16 | value: 17 | foo: 1 18 | two: 19 | value: 20 | foo: 2 21 | schema: 22 | type: object 23 | '404': 24 | description: No Foo 25 | content: 26 | application/json: 27 | examples: 28 | error: 29 | value: 30 | msg: I am an error example 31 | -------------------------------------------------------------------------------- /ch12/README.md: -------------------------------------------------------------------------------- 1 | # Chapter 12: Implementing frontend code and reacting to changes 2 | 3 | The file [openapi.yaml](openapi.yaml) contains the OpenAPI file for the PetSitter project after the updates made in [chapter 12](https://livebook.manning.com/book/designing-apis-with-swagger-and-openapi/chapter-12). -------------------------------------------------------------------------------- /ch12/openapi.yml: -------------------------------------------------------------------------------- 1 | openapi: 3.0.3 2 | info: 3 | title: PetSitter API 4 | version: "0.1" 5 | paths: 6 | /users: 7 | post: 8 | summary: Register User 9 | responses: 10 | '201': 11 | description: Created 12 | headers: 13 | Location: 14 | schema: 15 | type: string 16 | requestBody: 17 | content: 18 | application/json: 19 | schema: 20 | $ref: '#/components/schemas/User' 21 | /users/{id}: 22 | parameters: 23 | - schema: 24 | type: integer 25 | name: id 26 | in: path 27 | required: true 28 | get: 29 | summary: View User 30 | responses: 31 | '200': 32 | description: OK 33 | content: 34 | application/json: 35 | schema: 36 | $ref: '#/components/schemas/User' 37 | put: 38 | summary: Modify User 39 | responses: 40 | '200': 41 | description: OK 42 | content: 43 | application/json: 44 | schema: 45 | $ref: '#/components/schemas/User' 46 | requestBody: 47 | content: 48 | application/json: 49 | schema: 50 | $ref: '#/components/schemas/User' 51 | delete: 52 | summary: Delete User 53 | responses: 54 | '204': 55 | description: No Content 56 | /jobs: 57 | post: 58 | summary: Create Job 59 | responses: 60 | '201': 61 | description: Created 62 | headers: 63 | Location: 64 | schema: 65 | type: string 66 | requestBody: 67 | content: 68 | application/json: 69 | schema: 70 | $ref: '#/components/schemas/Job' 71 | get: 72 | summary: List All Jobs 73 | responses: 74 | '200': 75 | description: OK 76 | content: 77 | application/json: 78 | schema: 79 | type: object 80 | properties: 81 | items: 82 | type: array 83 | items: 84 | $ref: '#/components/schemas/Job' 85 | examples: 86 | with-some-data: 87 | summary: With some data 88 | value: 89 | items: 90 | - id: 123 91 | creator_user_id: 345 92 | start_time: 2020-06-01T00:00:00Z 93 | end_time: 2020-06-02T00:00:00Z 94 | dog: 95 | name: Fido 96 | age: 3 97 | breed: Doberman 98 | size: medium 99 | activity: walk 100 | - id: 234 101 | creator_user_id: 345 102 | start_time: 2020-06-01T00:00:00Z 103 | end_time: 2020-06-03T00:00:00Z 104 | dog: 105 | name: Rex 106 | age: 2 107 | breed: Rottweiler 108 | size: large 109 | activity: sit 110 | - id: 234 111 | creator_user_id: 345 112 | start_time: 2020-06-01T00:00:00Z 113 | end_time: 2020-06-02T00:00:00Z 114 | dog: 115 | name: Blossom 116 | age: 2 117 | breed: Rottweiler 118 | size: large 119 | activity: walk 120 | /jobs/{id}: 121 | parameters: 122 | - schema: 123 | type: integer 124 | name: id 125 | in: path 126 | required: true 127 | get: 128 | summary: View Job 129 | responses: 130 | '200': 131 | description: OK 132 | content: 133 | application/json: 134 | schema: 135 | $ref: '#/components/schemas/Job' 136 | put: 137 | summary: Modify Job 138 | responses: 139 | '200': 140 | description: OK 141 | content: 142 | application/json: 143 | schema: 144 | $ref: '#/components/schemas/Job' 145 | requestBody: 146 | content: 147 | application/json: 148 | schema: 149 | $ref: '#/components/schemas/Job' 150 | delete: 151 | summary: Delete Job 152 | responses: 153 | '204': 154 | description: No Content 155 | /jobs/{id}/job-applications: 156 | parameters: 157 | - schema: 158 | type: integer 159 | name: id 160 | in: path 161 | required: true 162 | get: 163 | summary: List Applications For Job 164 | responses: 165 | '200': 166 | description: OK 167 | content: 168 | application/json: 169 | schema: 170 | type: object 171 | properties: 172 | items: 173 | type: array 174 | items: 175 | $ref: '#/components/schemas/JobApplication' 176 | post: 177 | summary: Create Job Application 178 | responses: 179 | '201': 180 | description: Created 181 | headers: 182 | Location: 183 | schema: 184 | type: string 185 | requestBody: 186 | content: 187 | application/json: 188 | schema: 189 | $ref: '#/components/schemas/JobApplication' 190 | /users/{id}/jobs: 191 | parameters: 192 | - schema: 193 | type: integer 194 | name: id 195 | in: path 196 | required: true 197 | get: 198 | summary: List Jobs For User 199 | responses: 200 | '200': 201 | description: OK 202 | content: 203 | application/json: 204 | schema: 205 | type: object 206 | properties: 207 | items: 208 | type: array 209 | items: 210 | $ref: '#/components/schemas/Job' 211 | /users/{id}/job-applications: 212 | parameters: 213 | - name: id 214 | in: path 215 | required: true 216 | schema: 217 | type: integer 218 | get: 219 | summary: List Applications For User 220 | responses: 221 | '200': 222 | description: OK 223 | content: 224 | application/json: 225 | examples: 226 | empty: 227 | summary: Zero Job Applications 228 | value: 229 | items: [] 230 | two-items: 231 | summary: Two Job Applications 232 | value: 233 | items: 234 | - id: 123 235 | user_id: 123 236 | job_id: 123 237 | status: PENDING 238 | - id: 123 239 | user_id: 123 240 | job_id: 123 241 | status: COMPLETE 242 | many: 243 | summary: Many Job Applications 244 | value: 245 | items: 246 | - id: 0 247 | user_id: 358 248 | job_id: 4012 249 | status: COMPLETE 250 | - id: 1 251 | user_id: 3089 252 | job_id: 3902 253 | status: PENDING 254 | - id: 2 255 | user_id: 4040 256 | job_id: 5269 257 | status: PENDING 258 | - id: 3 259 | user_id: 5636 260 | job_id: 8420 261 | status: PENDING 262 | - id: 4 263 | user_id: 9540 264 | job_id: 9505 265 | status: COMPLETE 266 | - id: 5 267 | user_id: 9873 268 | job_id: 3215 269 | status: PENDING 270 | - id: 6 271 | user_id: 6032 272 | job_id: 7365 273 | status: COMPLETE 274 | - id: 7 275 | user_id: 5999 276 | job_id: 1159 277 | status: COMPLETE 278 | - id: 8 279 | user_id: 2897 280 | job_id: 7982 281 | status: COMPLETE 282 | - id: 9 283 | user_id: 227 284 | job_id: 9245 285 | status: CANCELLED 286 | - id: 10 287 | user_id: 741 288 | job_id: 2752 289 | status: CANCELLED 290 | - id: 11 291 | user_id: 9059 292 | job_id: 338 293 | status: PENDING 294 | - id: 12 295 | user_id: 1379 296 | job_id: 4531 297 | status: COMPLETE 298 | - id: 13 299 | user_id: 2031 300 | job_id: 9375 301 | status: COMPLETE 302 | - id: 14 303 | user_id: 3643 304 | job_id: 5175 305 | status: CANCELLED 306 | - id: 15 307 | user_id: 5470 308 | job_id: 831 309 | status: CANCELLED 310 | - id: 16 311 | user_id: 3265 312 | job_id: 5597 313 | status: PENDING 314 | - id: 17 315 | user_id: 2815 316 | job_id: 7719 317 | status: PENDING 318 | - id: 18 319 | user_id: 8306 320 | job_id: 679 321 | status: PENDING 322 | - id: 19 323 | user_id: 9742 324 | job_id: 8239 325 | status: PENDING 326 | - id: 20 327 | user_id: 4851 328 | job_id: 940 329 | status: PENDING 330 | - id: 21 331 | user_id: 6700 332 | job_id: 4040 333 | status: PENDING 334 | - id: 22 335 | user_id: 7067 336 | job_id: 6016 337 | status: PENDING 338 | - id: 23 339 | user_id: 3265 340 | job_id: 1822 341 | status: PENDING 342 | - id: 24 343 | user_id: 8333 344 | job_id: 9988 345 | status: PENDING 346 | - id: 25 347 | user_id: 7543 348 | job_id: 9307 349 | status: PENDING 350 | - id: 26 351 | user_id: 5429 352 | job_id: 7511 353 | status: COMPLETE 354 | - id: 27 355 | user_id: 3576 356 | job_id: 1710 357 | status: PENDING 358 | - id: 28 359 | user_id: 590 360 | job_id: 2634 361 | status: COMPLETE 362 | - id: 29 363 | user_id: 2327 364 | job_id: 7205 365 | status: CANCELLED 366 | - id: 30 367 | user_id: 2193 368 | job_id: 7421 369 | status: COMPLETE 370 | - id: 31 371 | user_id: 5014 372 | job_id: 6781 373 | status: CANCELLED 374 | - id: 32 375 | user_id: 9216 376 | job_id: 8047 377 | status: COMPLETE 378 | - id: 33 379 | user_id: 3369 380 | job_id: 7438 381 | status: CANCELLED 382 | - id: 34 383 | user_id: 9825 384 | job_id: 6758 385 | status: PENDING 386 | - id: 35 387 | user_id: 3250 388 | job_id: 7760 389 | status: COMPLETE 390 | - id: 36 391 | user_id: 1552 392 | job_id: 4030 393 | status: COMPLETE 394 | - id: 37 395 | user_id: 9221 396 | job_id: 3971 397 | status: CANCELLED 398 | - id: 38 399 | user_id: 6816 400 | job_id: 7878 401 | status: PENDING 402 | - id: 39 403 | user_id: 6109 404 | job_id: 4060 405 | status: CANCELLED 406 | schema: 407 | type: object 408 | properties: 409 | items: 410 | type: array 411 | items: 412 | $ref: '#/components/schemas/JobApplication' 413 | /job-applications/{id}: 414 | parameters: 415 | - schema: 416 | type: integer 417 | name: id 418 | in: path 419 | required: true 420 | put: 421 | summary: Modify Job Application 422 | requestBody: 423 | description: Update the application details 424 | content: 425 | application/json: 426 | schema: 427 | $ref: '#/components/schemas/JobApplication' 428 | 429 | responses: 430 | '200': 431 | description: OK 432 | content: 433 | application/json: 434 | schema: 435 | type: array 436 | items: 437 | $ref: '#/components/schemas/JobApplication' 438 | components: 439 | schemas: 440 | User: 441 | type: object 442 | properties: 443 | id: 444 | type: integer 445 | email: 446 | type: string 447 | password: 448 | type: string 449 | full_name: 450 | type: string 451 | roles: 452 | type: array 453 | items: 454 | type: string 455 | Job: 456 | type: object 457 | properties: 458 | id: 459 | type: integer 460 | creator_user_id: 461 | type: integer 462 | start_time: 463 | type: string 464 | end_time: 465 | type: string 466 | activity: 467 | type: string 468 | dog: 469 | $ref: '#/components/schemas/Dog' 470 | Dog: 471 | type: object 472 | properties: 473 | name: 474 | type: string 475 | age: 476 | type: integer 477 | breed: 478 | type: string 479 | size: 480 | type: string 481 | JobApplication: 482 | type: object 483 | properties: 484 | id: 485 | type: integer 486 | status: 487 | type: string 488 | user_id: 489 | type: integer 490 | job_id: 491 | type: integer 492 | -------------------------------------------------------------------------------- /ch13/01.yml: -------------------------------------------------------------------------------- 1 | openapi: 3.0.3 2 | info: 3 | title: PetSitter API 4 | version: "0.1" 5 | paths: 6 | /users: 7 | post: 8 | summary: Register User 9 | responses: 10 | '201': 11 | description: Created 12 | headers: 13 | Location: 14 | schema: 15 | type: string 16 | requestBody: 17 | content: 18 | application/json: 19 | schema: 20 | $ref: '#/components/schemas/User' 21 | /users/{id}: 22 | parameters: 23 | - schema: 24 | type: integer 25 | name: id 26 | in: path 27 | required: true 28 | get: 29 | summary: View User 30 | responses: 31 | '200': 32 | description: OK 33 | content: 34 | application/json: 35 | schema: 36 | $ref: '#/components/schemas/User' 37 | put: 38 | summary: Modify User 39 | responses: 40 | '200': 41 | description: OK 42 | content: 43 | application/json: 44 | schema: 45 | $ref: '#/components/schemas/User' 46 | requestBody: 47 | content: 48 | application/json: 49 | schema: 50 | $ref: '#/components/schemas/User' 51 | delete: 52 | summary: Delete User 53 | responses: 54 | '204': 55 | description: No Content 56 | /jobs: 57 | post: 58 | summary: Create Job 59 | responses: 60 | '201': 61 | description: Created 62 | headers: 63 | Location: 64 | schema: 65 | type: string 66 | requestBody: 67 | content: 68 | application/json: 69 | schema: 70 | $ref: '#/components/schemas/Job' 71 | get: 72 | summary: List All Jobs 73 | responses: 74 | '200': 75 | description: OK 76 | content: 77 | application/json: 78 | schema: 79 | type: object 80 | properties: 81 | items: 82 | type: array 83 | items: 84 | $ref: '#/components/schemas/Job' 85 | /jobs/{id}: 86 | parameters: 87 | - schema: 88 | type: integer 89 | name: id 90 | in: path 91 | required: true 92 | get: 93 | summary: View Job 94 | responses: 95 | '200': 96 | description: OK 97 | content: 98 | application/json: 99 | schema: 100 | $ref: '#/components/schemas/Job' 101 | put: 102 | summary: Modify Job 103 | responses: 104 | '200': 105 | description: OK 106 | content: 107 | application/json: 108 | schema: 109 | $ref: '#/components/schemas/Job' 110 | requestBody: 111 | content: 112 | application/json: 113 | schema: 114 | $ref: '#/components/schemas/Job' 115 | delete: 116 | summary: Delete Job 117 | responses: 118 | '204': 119 | description: No Content 120 | /jobs/{id}/job-applications: 121 | parameters: 122 | - schema: 123 | type: integer 124 | name: id 125 | in: path 126 | required: true 127 | get: 128 | summary: List Applications For Job 129 | responses: 130 | '200': 131 | description: OK 132 | content: 133 | application/json: 134 | schema: 135 | type: object 136 | properties: 137 | items: 138 | type: array 139 | items: 140 | $ref: '#/components/schemas/JobApplication' 141 | post: 142 | summary: Create Job Application 143 | responses: 144 | '201': 145 | description: Created 146 | headers: 147 | Location: 148 | schema: 149 | type: string 150 | requestBody: 151 | content: 152 | application/json: 153 | schema: 154 | $ref: '#/components/schemas/JobApplication' 155 | /users/{id}/jobs: 156 | parameters: 157 | - schema: 158 | type: integer 159 | name: id 160 | in: path 161 | required: true 162 | get: 163 | summary: List Jobs For User 164 | responses: 165 | '200': 166 | description: OK 167 | content: 168 | application/json: 169 | schema: 170 | type: object 171 | properties: 172 | items: 173 | type: array 174 | items: 175 | $ref: '#/components/schemas/Job' 176 | /job-applications/{id}: 177 | parameters: 178 | - schema: 179 | type: integer 180 | name: id 181 | in: path 182 | required: true 183 | put: 184 | summary: Modify Job Application 185 | requestBody: 186 | description: Update the application details 187 | content: 188 | application/json: 189 | schema: 190 | $ref: '#/components/schemas/JobApplication' 191 | responses: 192 | '200': 193 | description: OK 194 | content: 195 | application/json: 196 | schema: 197 | $ref: '#/components/schemas/JobApplication' 198 | components: 199 | schemas: 200 | User: 201 | type: object 202 | properties: 203 | id: 204 | type: integer 205 | email: 206 | type: string 207 | password: 208 | type: string 209 | full_name: 210 | type: string 211 | roles: 212 | type: array 213 | items: 214 | type: string 215 | Job: 216 | type: object 217 | properties: 218 | id: 219 | type: integer 220 | creator_user_id: 221 | type: integer 222 | start_time: 223 | type: string 224 | end_time: 225 | type: string 226 | activity: 227 | type: string 228 | dog: 229 | $ref: '#/components/schemas/Dog' 230 | Dog: 231 | type: object 232 | properties: 233 | name: 234 | type: string 235 | age: 236 | type: integer 237 | breed: 238 | type: string 239 | size: 240 | type: string 241 | JobApplication: 242 | type: object 243 | properties: 244 | id: 245 | type: integer 246 | status: 247 | type: string 248 | user_id: 249 | type: integer 250 | job_id: 251 | type: integer 252 | -------------------------------------------------------------------------------- /ch13/02.yml: -------------------------------------------------------------------------------- 1 | openapi: 3.0.3 2 | info: 3 | title: PetSitter API 4 | version: "0.1" 5 | tags: 6 | - name: Users 7 | description: User-related operations 8 | - name: Jobs 9 | description: Job-related operations 10 | paths: 11 | /users: 12 | post: 13 | tags: 14 | - Users 15 | summary: Register User 16 | operationId: registerUser 17 | responses: 18 | '201': 19 | description: Created 20 | headers: 21 | Location: 22 | schema: 23 | type: string 24 | requestBody: 25 | content: 26 | application/json: 27 | schema: 28 | $ref: '#/components/schemas/User' 29 | /users/{id}: 30 | parameters: 31 | - schema: 32 | type: integer 33 | name: id 34 | in: path 35 | required: true 36 | get: 37 | tags: 38 | - Users 39 | summary: View User 40 | operationId: viewUserWithId 41 | responses: 42 | '200': 43 | description: OK 44 | content: 45 | application/json: 46 | schema: 47 | $ref: '#/components/schemas/User' 48 | put: 49 | tags: 50 | - Users 51 | summary: Modify User 52 | operationId: modifyUserWithId 53 | responses: 54 | '200': 55 | description: OK 56 | content: 57 | application/json: 58 | schema: 59 | $ref: '#/components/schemas/User' 60 | requestBody: 61 | content: 62 | application/json: 63 | schema: 64 | $ref: '#/components/schemas/User' 65 | delete: 66 | tags: 67 | - Users 68 | summary: Delete User 69 | operationId: deleteUserWithId 70 | responses: 71 | '204': 72 | description: No Content 73 | /jobs: 74 | post: 75 | tags: 76 | - Jobs 77 | summary: Create Job 78 | operationId: createJob 79 | responses: 80 | '201': 81 | description: Created 82 | headers: 83 | Location: 84 | schema: 85 | type: string 86 | requestBody: 87 | content: 88 | application/json: 89 | schema: 90 | $ref: '#/components/schemas/Job' 91 | get: 92 | tags: 93 | - Jobs 94 | summary: List All Jobs 95 | operationId: listAllJobs 96 | responses: 97 | '200': 98 | description: OK 99 | content: 100 | application/json: 101 | schema: 102 | type: object 103 | properties: 104 | items: 105 | type: array 106 | items: 107 | $ref: '#/components/schemas/Job' 108 | /jobs/{id}: 109 | parameters: 110 | - schema: 111 | type: integer 112 | name: id 113 | in: path 114 | required: true 115 | get: 116 | tags: 117 | - Jobs 118 | summary: View Job 119 | operationId: viewJobWithId 120 | responses: 121 | '200': 122 | description: OK 123 | content: 124 | application/json: 125 | schema: 126 | $ref: '#/components/schemas/Job' 127 | put: 128 | tags: 129 | - Jobs 130 | summary: Modify Job 131 | operationId: modifyJobWithId 132 | responses: 133 | '200': 134 | description: OK 135 | content: 136 | application/json: 137 | schema: 138 | $ref: '#/components/schemas/Job' 139 | requestBody: 140 | content: 141 | application/json: 142 | schema: 143 | $ref: '#/components/schemas/Job' 144 | delete: 145 | tags: 146 | - Jobs 147 | summary: Delete Job 148 | operationId: deleteJobWithId 149 | responses: 150 | '204': 151 | description: No Content 152 | /jobs/{id}/job-applications: 153 | parameters: 154 | - schema: 155 | type: integer 156 | name: id 157 | in: path 158 | required: true 159 | get: 160 | tags: 161 | - Jobs 162 | summary: List Applications For Job 163 | operationId: viewApplicationsForJob 164 | responses: 165 | '200': 166 | description: OK 167 | content: 168 | application/json: 169 | schema: 170 | type: object 171 | properties: 172 | items: 173 | type: array 174 | items: 175 | $ref: '#/components/schemas/JobApplication' 176 | post: 177 | tags: 178 | - Jobs 179 | summary: Create Job Application 180 | operationId: createJobApplication 181 | responses: 182 | '201': 183 | description: Created 184 | headers: 185 | Location: 186 | schema: 187 | type: string 188 | requestBody: 189 | content: 190 | application/json: 191 | schema: 192 | $ref: '#/components/schemas/JobApplication' 193 | /users/{id}/jobs: 194 | parameters: 195 | - schema: 196 | type: integer 197 | name: id 198 | in: path 199 | required: true 200 | get: 201 | tags: 202 | - Users 203 | summary: List Jobs For User 204 | operationId: listJobsForUser 205 | responses: 206 | '200': 207 | description: OK 208 | content: 209 | application/json: 210 | schema: 211 | type: object 212 | properties: 213 | items: 214 | type: array 215 | items: 216 | $ref: '#/components/schemas/Job' 217 | /job-applications/{id}: 218 | parameters: 219 | - schema: 220 | type: integer 221 | name: id 222 | in: path 223 | required: true 224 | put: 225 | tags: 226 | - Jobs 227 | summary: Modify Job Application 228 | operationId: modifyJobApplicationWithId 229 | requestBody: 230 | description: Update the application details 231 | content: 232 | application/json: 233 | schema: 234 | $ref: '#/components/schemas/JobApplication' 235 | responses: 236 | '200': 237 | description: OK 238 | content: 239 | application/json: 240 | schema: 241 | $ref: '#/components/schemas/JobApplication' 242 | components: 243 | schemas: 244 | User: 245 | type: object 246 | properties: 247 | id: 248 | type: integer 249 | email: 250 | type: string 251 | password: 252 | type: string 253 | full_name: 254 | type: string 255 | roles: 256 | type: array 257 | items: 258 | type: string 259 | Job: 260 | type: object 261 | properties: 262 | id: 263 | type: integer 264 | creator_user_id: 265 | type: integer 266 | start_time: 267 | type: string 268 | end_time: 269 | type: string 270 | activity: 271 | type: string 272 | dog: 273 | $ref: '#/components/schemas/Dog' 274 | Dog: 275 | type: object 276 | properties: 277 | name: 278 | type: string 279 | age: 280 | type: integer 281 | breed: 282 | type: string 283 | size: 284 | type: string 285 | JobApplication: 286 | type: object 287 | properties: 288 | id: 289 | type: integer 290 | status: 291 | type: string 292 | user_id: 293 | type: integer 294 | job_id: 295 | type: integer 296 | -------------------------------------------------------------------------------- /ch13/README.md: -------------------------------------------------------------------------------- 1 | # Chapter 13: Building a Backend with Node.js and Swagger Codegen 2 | 3 | The file [01.yml](01.yml) contains the base OpenAPI file from [chapter 11](https://livebook.manning.com/book/designing-apis-with-swagger-and-openapi/chapter-11). 4 | 5 | The file [02.yml](02.yml) contains the OpenAPI file for the PetSitter project after the operation IDs and tags were added in [chapter 13](https://livebook.manning.com/book/designing-apis-with-swagger-and-openapi/chapter-13). 6 | 7 | The file [openapi.yml](openapi.yml) contains the OpenAPI file for the PetSitter project after the additional data type changes made in [chapter 13](https://livebook.manning.com/book/designing-apis-with-swagger-and-openapi/chapter-13) and represents the state at the end of the chapter. 8 | -------------------------------------------------------------------------------- /ch13/openapi.yml: -------------------------------------------------------------------------------- 1 | openapi: 3.0.3 2 | info: 3 | title: PetSitter API 4 | version: "0.1" 5 | tags: 6 | - name: Users 7 | description: User-related operations 8 | - name: Jobs 9 | description: Job-related operations 10 | paths: 11 | /users: 12 | post: 13 | tags: 14 | - Users 15 | summary: Register User 16 | operationId: registerUser 17 | responses: 18 | '201': 19 | description: Created 20 | headers: 21 | Location: 22 | schema: 23 | type: string 24 | requestBody: 25 | content: 26 | application/json: 27 | schema: 28 | $ref: '#/components/schemas/User' 29 | /users/{id}: 30 | parameters: 31 | - schema: 32 | type: string 33 | name: id 34 | in: path 35 | required: true 36 | get: 37 | tags: 38 | - Users 39 | summary: View User 40 | operationId: viewUserWithId 41 | responses: 42 | '200': 43 | description: OK 44 | content: 45 | application/json: 46 | schema: 47 | $ref: '#/components/schemas/User' 48 | put: 49 | tags: 50 | - Users 51 | summary: Modify User 52 | operationId: modifyUserWithId 53 | responses: 54 | '200': 55 | description: OK 56 | content: 57 | application/json: 58 | schema: 59 | $ref: '#/components/schemas/User' 60 | requestBody: 61 | content: 62 | application/json: 63 | schema: 64 | $ref: '#/components/schemas/User' 65 | delete: 66 | tags: 67 | - Users 68 | summary: Delete User 69 | operationId: deleteUserWithId 70 | responses: 71 | '204': 72 | description: No Content 73 | /jobs: 74 | post: 75 | tags: 76 | - Jobs 77 | summary: Create Job 78 | operationId: createJob 79 | responses: 80 | '201': 81 | description: Created 82 | headers: 83 | Location: 84 | schema: 85 | type: string 86 | requestBody: 87 | content: 88 | application/json: 89 | schema: 90 | $ref: '#/components/schemas/Job' 91 | get: 92 | tags: 93 | - Jobs 94 | summary: List All Jobs 95 | operationId: listAllJobs 96 | responses: 97 | '200': 98 | description: OK 99 | content: 100 | application/json: 101 | schema: 102 | type: object 103 | properties: 104 | items: 105 | type: array 106 | items: 107 | $ref: '#/components/schemas/Job' 108 | /jobs/{id}: 109 | parameters: 110 | - schema: 111 | type: string 112 | name: id 113 | in: path 114 | required: true 115 | get: 116 | tags: 117 | - Jobs 118 | summary: View Job 119 | operationId: viewJobWithId 120 | responses: 121 | '200': 122 | description: OK 123 | content: 124 | application/json: 125 | schema: 126 | $ref: '#/components/schemas/Job' 127 | put: 128 | tags: 129 | - Jobs 130 | summary: Modify Job 131 | operationId: modifyJobWithId 132 | responses: 133 | '200': 134 | description: OK 135 | content: 136 | application/json: 137 | schema: 138 | $ref: '#/components/schemas/Job' 139 | requestBody: 140 | content: 141 | application/json: 142 | schema: 143 | $ref: '#/components/schemas/Job' 144 | delete: 145 | tags: 146 | - Jobs 147 | summary: Delete Job 148 | operationId: deleteJobWithId 149 | responses: 150 | '204': 151 | description: No Content 152 | /jobs/{id}/job-applications: 153 | parameters: 154 | - schema: 155 | type: string 156 | name: id 157 | in: path 158 | required: true 159 | get: 160 | tags: 161 | - Jobs 162 | summary: List Applications For Job 163 | operationId: viewApplicationsForJob 164 | responses: 165 | '200': 166 | description: OK 167 | content: 168 | application/json: 169 | schema: 170 | type: object 171 | properties: 172 | items: 173 | type: array 174 | items: 175 | $ref: '#/components/schemas/JobApplication' 176 | post: 177 | tags: 178 | - Jobs 179 | summary: Create Job Application 180 | operationId: createJobApplication 181 | responses: 182 | '201': 183 | description: Created 184 | headers: 185 | Location: 186 | schema: 187 | type: string 188 | requestBody: 189 | content: 190 | application/json: 191 | schema: 192 | $ref: '#/components/schemas/JobApplication' 193 | /users/{id}/jobs: 194 | parameters: 195 | - schema: 196 | type: string 197 | name: id 198 | in: path 199 | required: true 200 | get: 201 | tags: 202 | - Users 203 | summary: List Jobs For User 204 | operationId: listJobsForUser 205 | responses: 206 | '200': 207 | description: OK 208 | content: 209 | application/json: 210 | schema: 211 | type: object 212 | properties: 213 | items: 214 | type: array 215 | items: 216 | $ref: '#/components/schemas/Job' 217 | /job-applications/{id}: 218 | parameters: 219 | - schema: 220 | type: string 221 | name: id 222 | in: path 223 | required: true 224 | put: 225 | tags: 226 | - Jobs 227 | summary: Modify Job Application 228 | operationId: modifyJobApplicationWithId 229 | requestBody: 230 | description: Update the application details 231 | content: 232 | application/json: 233 | schema: 234 | $ref: '#/components/schemas/JobApplication' 235 | responses: 236 | '200': 237 | description: OK 238 | content: 239 | application/json: 240 | schema: 241 | $ref: '#/components/schemas/JobApplication' 242 | components: 243 | schemas: 244 | User: 245 | type: object 246 | properties: 247 | id: 248 | type: string 249 | email: 250 | type: string 251 | password: 252 | type: string 253 | full_name: 254 | type: string 255 | roles: 256 | type: array 257 | items: 258 | type: string 259 | Job: 260 | type: object 261 | properties: 262 | id: 263 | type: string 264 | creator_user_id: 265 | type: string 266 | start_time: 267 | type: string 268 | end_time: 269 | type: string 270 | activity: 271 | type: string 272 | dog: 273 | $ref: '#/components/schemas/Dog' 274 | Dog: 275 | type: object 276 | properties: 277 | name: 278 | type: string 279 | age: 280 | type: integer 281 | breed: 282 | type: string 283 | size: 284 | type: string 285 | JobApplication: 286 | type: object 287 | properties: 288 | id: 289 | type: string 290 | status: 291 | type: string 292 | user_id: 293 | type: string 294 | job_id: 295 | type: string 296 | -------------------------------------------------------------------------------- /ch14/01.yml: -------------------------------------------------------------------------------- 1 | openapi: 3.0.3 2 | info: 3 | title: PetSitter API 4 | version: "0.1" 5 | tags: 6 | - name: Users 7 | description: User-related operations 8 | - name: Jobs 9 | description: Job-related operations 10 | paths: 11 | /users: 12 | post: 13 | tags: 14 | - Users 15 | summary: Register User 16 | operationId: registerUser 17 | responses: 18 | '201': 19 | description: Created 20 | headers: 21 | Location: 22 | schema: 23 | type: string 24 | requestBody: 25 | content: 26 | application/json: 27 | schema: 28 | $ref: '#/components/schemas/User' 29 | /users/{id}: 30 | parameters: 31 | - schema: 32 | type: string 33 | name: id 34 | in: path 35 | required: true 36 | get: 37 | tags: 38 | - Users 39 | summary: View User 40 | operationId: viewUserWithId 41 | responses: 42 | '200': 43 | description: OK 44 | content: 45 | application/json: 46 | schema: 47 | $ref: '#/components/schemas/User' 48 | put: 49 | tags: 50 | - Users 51 | summary: Modify User 52 | operationId: modifyUserWithId 53 | responses: 54 | '200': 55 | description: OK 56 | content: 57 | application/json: 58 | schema: 59 | $ref: '#/components/schemas/User' 60 | requestBody: 61 | content: 62 | application/json: 63 | schema: 64 | $ref: '#/components/schemas/User' 65 | delete: 66 | tags: 67 | - Users 68 | summary: Delete User 69 | operationId: deleteUserWithId 70 | responses: 71 | '204': 72 | description: No Content 73 | /jobs: 74 | post: 75 | tags: 76 | - Jobs 77 | summary: Create Job 78 | operationId: createJob 79 | responses: 80 | '201': 81 | description: Created 82 | headers: 83 | Location: 84 | schema: 85 | type: string 86 | requestBody: 87 | content: 88 | application/json: 89 | schema: 90 | $ref: '#/components/schemas/Job' 91 | get: 92 | tags: 93 | - Jobs 94 | summary: List All Jobs 95 | operationId: listAllJobs 96 | responses: 97 | '200': 98 | description: OK 99 | content: 100 | application/json: 101 | schema: 102 | type: object 103 | properties: 104 | items: 105 | type: array 106 | items: 107 | $ref: '#/components/schemas/Job' 108 | examples: 109 | with-some-data: 110 | summary: With some data 111 | value: 112 | items: 113 | - id: 123 114 | creator_user_id: 345 115 | start_time: 2020-06-01T00:00:00Z 116 | end_time: 2020-06-02T00:00:00Z 117 | dog: 118 | name: Fido 119 | age: 3 120 | breed: Doberman 121 | size: medium 122 | activity: walk 123 | - id: 234 124 | creator_user_id: 345 125 | start_time: 2020-06-01T00:00:00Z 126 | end_time: 2020-06-03T00:00:00Z 127 | dog: 128 | name: Rex 129 | age: 2 130 | breed: Rottweiler 131 | size: large 132 | activity: sit 133 | - id: 234 134 | creator_user_id: 345 135 | start_time: 2020-06-01T00:00:00Z 136 | end_time: 2020-06-02T00:00:00Z 137 | dog: 138 | name: Blossom 139 | age: 2 140 | breed: Rottweiler 141 | size: large 142 | activity: walk 143 | /jobs/{id}: 144 | parameters: 145 | - schema: 146 | type: string 147 | name: id 148 | in: path 149 | required: true 150 | get: 151 | tags: 152 | - Jobs 153 | summary: View Job 154 | operationId: viewJobWithId 155 | responses: 156 | '200': 157 | description: OK 158 | content: 159 | application/json: 160 | schema: 161 | $ref: '#/components/schemas/Job' 162 | put: 163 | tags: 164 | - Jobs 165 | summary: Modify Job 166 | operationId: modifyJobWithId 167 | responses: 168 | '200': 169 | description: OK 170 | content: 171 | application/json: 172 | schema: 173 | $ref: '#/components/schemas/Job' 174 | requestBody: 175 | content: 176 | application/json: 177 | schema: 178 | $ref: '#/components/schemas/Job' 179 | delete: 180 | tags: 181 | - Jobs 182 | summary: Delete Job 183 | operationId: deleteJobWithId 184 | responses: 185 | '204': 186 | description: No Content 187 | /jobs/{id}/job-applications: 188 | parameters: 189 | - schema: 190 | type: string 191 | name: id 192 | in: path 193 | required: true 194 | get: 195 | tags: 196 | - Jobs 197 | summary: List Applications For Job 198 | operationId: viewApplicationsForJob 199 | responses: 200 | '200': 201 | description: OK 202 | content: 203 | application/json: 204 | examples: 205 | empty: 206 | summary: Zero Job Applications 207 | value: 208 | items: [] 209 | two-items: 210 | summary: Two Job Applications 211 | value: 212 | items: 213 | - id: 123 214 | user_id: 123 215 | job_id: 123 216 | status: PENDING 217 | - id: 123 218 | user_id: 123 219 | job_id: 123 220 | status: COMPLETE 221 | many: 222 | summary: Many Job Applications 223 | value: 224 | items: 225 | - id: 0 226 | user_id: 358 227 | job_id: 4012 228 | status: COMPLETE 229 | - id: 1 230 | user_id: 3089 231 | job_id: 3902 232 | status: PENDING 233 | - id: 2 234 | user_id: 4040 235 | job_id: 5269 236 | status: PENDING 237 | - id: 3 238 | user_id: 5636 239 | job_id: 8420 240 | status: PENDING 241 | - id: 4 242 | user_id: 9540 243 | job_id: 9505 244 | status: COMPLETE 245 | - id: 5 246 | user_id: 9873 247 | job_id: 3215 248 | status: PENDING 249 | - id: 6 250 | user_id: 6032 251 | job_id: 7365 252 | status: COMPLETE 253 | - id: 7 254 | user_id: 5999 255 | job_id: 1159 256 | status: COMPLETE 257 | - id: 8 258 | user_id: 2897 259 | job_id: 7982 260 | status: COMPLETE 261 | - id: 9 262 | user_id: 227 263 | job_id: 9245 264 | status: CANCELLED 265 | - id: 10 266 | user_id: 741 267 | job_id: 2752 268 | status: CANCELLED 269 | - id: 11 270 | user_id: 9059 271 | job_id: 338 272 | status: PENDING 273 | - id: 12 274 | user_id: 1379 275 | job_id: 4531 276 | status: COMPLETE 277 | - id: 13 278 | user_id: 2031 279 | job_id: 9375 280 | status: COMPLETE 281 | - id: 14 282 | user_id: 3643 283 | job_id: 5175 284 | status: CANCELLED 285 | - id: 15 286 | user_id: 5470 287 | job_id: 831 288 | status: CANCELLED 289 | - id: 16 290 | user_id: 3265 291 | job_id: 5597 292 | status: PENDING 293 | - id: 17 294 | user_id: 2815 295 | job_id: 7719 296 | status: PENDING 297 | - id: 18 298 | user_id: 8306 299 | job_id: 679 300 | status: PENDING 301 | - id: 19 302 | user_id: 9742 303 | job_id: 8239 304 | status: PENDING 305 | - id: 20 306 | user_id: 4851 307 | job_id: 940 308 | status: PENDING 309 | - id: 21 310 | user_id: 6700 311 | job_id: 4040 312 | status: PENDING 313 | - id: 22 314 | user_id: 7067 315 | job_id: 6016 316 | status: PENDING 317 | - id: 23 318 | user_id: 3265 319 | job_id: 1822 320 | status: PENDING 321 | - id: 24 322 | user_id: 8333 323 | job_id: 9988 324 | status: PENDING 325 | - id: 25 326 | user_id: 7543 327 | job_id: 9307 328 | status: PENDING 329 | - id: 26 330 | user_id: 5429 331 | job_id: 7511 332 | status: COMPLETE 333 | - id: 27 334 | user_id: 3576 335 | job_id: 1710 336 | status: PENDING 337 | - id: 28 338 | user_id: 590 339 | job_id: 2634 340 | status: COMPLETE 341 | - id: 29 342 | user_id: 2327 343 | job_id: 7205 344 | status: CANCELLED 345 | - id: 30 346 | user_id: 2193 347 | job_id: 7421 348 | status: COMPLETE 349 | - id: 31 350 | user_id: 5014 351 | job_id: 6781 352 | status: CANCELLED 353 | - id: 32 354 | user_id: 9216 355 | job_id: 8047 356 | status: COMPLETE 357 | - id: 33 358 | user_id: 3369 359 | job_id: 7438 360 | status: CANCELLED 361 | - id: 34 362 | user_id: 9825 363 | job_id: 6758 364 | status: PENDING 365 | - id: 35 366 | user_id: 3250 367 | job_id: 7760 368 | status: COMPLETE 369 | - id: 36 370 | user_id: 1552 371 | job_id: 4030 372 | status: COMPLETE 373 | - id: 37 374 | user_id: 9221 375 | job_id: 3971 376 | status: CANCELLED 377 | - id: 38 378 | user_id: 6816 379 | job_id: 7878 380 | status: PENDING 381 | - id: 39 382 | user_id: 6109 383 | job_id: 4060 384 | status: CANCELLED 385 | schema: 386 | type: object 387 | properties: 388 | items: 389 | type: array 390 | items: 391 | $ref: '#/components/schemas/JobApplication' 392 | post: 393 | tags: 394 | - Jobs 395 | summary: Create Job Application 396 | operationId: createJobApplication 397 | responses: 398 | '201': 399 | description: Created 400 | headers: 401 | Location: 402 | schema: 403 | type: string 404 | requestBody: 405 | content: 406 | application/json: 407 | schema: 408 | $ref: '#/components/schemas/JobApplication' 409 | /users/{id}/jobs: 410 | parameters: 411 | - schema: 412 | type: string 413 | name: id 414 | in: path 415 | required: true 416 | get: 417 | tags: 418 | - Users 419 | summary: List Jobs For User 420 | operationId: listJobsForUser 421 | responses: 422 | '200': 423 | description: OK 424 | content: 425 | application/json: 426 | schema: 427 | type: object 428 | properties: 429 | items: 430 | type: array 431 | items: 432 | $ref: '#/components/schemas/Job' 433 | /users/{id}/job-applications: 434 | parameters: 435 | - name: id 436 | in: path 437 | required: true 438 | schema: 439 | type: integer 440 | get: 441 | summary: List Applications For User 442 | responses: 443 | '200': 444 | description: OK 445 | content: 446 | application/json: 447 | examples: 448 | empty: 449 | summary: Zero Job Applications 450 | value: 451 | items: [] 452 | two-items: 453 | summary: Two Job Applications 454 | value: 455 | items: 456 | - id: 123 457 | user_id: 123 458 | job_id: 123 459 | status: PENDING 460 | - id: 123 461 | user_id: 123 462 | job_id: 123 463 | status: COMPLETE 464 | many: 465 | summary: Many Job Applications 466 | value: 467 | items: 468 | - id: 0 469 | user_id: 358 470 | job_id: 4012 471 | status: COMPLETE 472 | - id: 1 473 | user_id: 3089 474 | job_id: 3902 475 | status: PENDING 476 | - id: 2 477 | user_id: 4040 478 | job_id: 5269 479 | status: PENDING 480 | - id: 3 481 | user_id: 5636 482 | job_id: 8420 483 | status: PENDING 484 | - id: 4 485 | user_id: 9540 486 | job_id: 9505 487 | status: COMPLETE 488 | - id: 5 489 | user_id: 9873 490 | job_id: 3215 491 | status: PENDING 492 | - id: 6 493 | user_id: 6032 494 | job_id: 7365 495 | status: COMPLETE 496 | - id: 7 497 | user_id: 5999 498 | job_id: 1159 499 | status: COMPLETE 500 | - id: 8 501 | user_id: 2897 502 | job_id: 7982 503 | status: COMPLETE 504 | - id: 9 505 | user_id: 227 506 | job_id: 9245 507 | status: CANCELLED 508 | - id: 10 509 | user_id: 741 510 | job_id: 2752 511 | status: CANCELLED 512 | - id: 11 513 | user_id: 9059 514 | job_id: 338 515 | status: PENDING 516 | - id: 12 517 | user_id: 1379 518 | job_id: 4531 519 | status: COMPLETE 520 | - id: 13 521 | user_id: 2031 522 | job_id: 9375 523 | status: COMPLETE 524 | - id: 14 525 | user_id: 3643 526 | job_id: 5175 527 | status: CANCELLED 528 | - id: 15 529 | user_id: 5470 530 | job_id: 831 531 | status: CANCELLED 532 | - id: 16 533 | user_id: 3265 534 | job_id: 5597 535 | status: PENDING 536 | - id: 17 537 | user_id: 2815 538 | job_id: 7719 539 | status: PENDING 540 | - id: 18 541 | user_id: 8306 542 | job_id: 679 543 | status: PENDING 544 | - id: 19 545 | user_id: 9742 546 | job_id: 8239 547 | status: PENDING 548 | - id: 20 549 | user_id: 4851 550 | job_id: 940 551 | status: PENDING 552 | - id: 21 553 | user_id: 6700 554 | job_id: 4040 555 | status: PENDING 556 | - id: 22 557 | user_id: 7067 558 | job_id: 6016 559 | status: PENDING 560 | - id: 23 561 | user_id: 3265 562 | job_id: 1822 563 | status: PENDING 564 | - id: 24 565 | user_id: 8333 566 | job_id: 9988 567 | status: PENDING 568 | - id: 25 569 | user_id: 7543 570 | job_id: 9307 571 | status: PENDING 572 | - id: 26 573 | user_id: 5429 574 | job_id: 7511 575 | status: COMPLETE 576 | - id: 27 577 | user_id: 3576 578 | job_id: 1710 579 | status: PENDING 580 | - id: 28 581 | user_id: 590 582 | job_id: 2634 583 | status: COMPLETE 584 | - id: 29 585 | user_id: 2327 586 | job_id: 7205 587 | status: CANCELLED 588 | - id: 30 589 | user_id: 2193 590 | job_id: 7421 591 | status: COMPLETE 592 | - id: 31 593 | user_id: 5014 594 | job_id: 6781 595 | status: CANCELLED 596 | - id: 32 597 | user_id: 9216 598 | job_id: 8047 599 | status: COMPLETE 600 | - id: 33 601 | user_id: 3369 602 | job_id: 7438 603 | status: CANCELLED 604 | - id: 34 605 | user_id: 9825 606 | job_id: 6758 607 | status: PENDING 608 | - id: 35 609 | user_id: 3250 610 | job_id: 7760 611 | status: COMPLETE 612 | - id: 36 613 | user_id: 1552 614 | job_id: 4030 615 | status: COMPLETE 616 | - id: 37 617 | user_id: 9221 618 | job_id: 3971 619 | status: CANCELLED 620 | - id: 38 621 | user_id: 6816 622 | job_id: 7878 623 | status: PENDING 624 | - id: 39 625 | user_id: 6109 626 | job_id: 4060 627 | status: CANCELLED 628 | schema: 629 | type: object 630 | properties: 631 | items: 632 | type: array 633 | items: 634 | $ref: '#/components/schemas/JobApplication' 635 | /job-applications/{id}: 636 | parameters: 637 | - schema: 638 | type: string 639 | name: id 640 | in: path 641 | required: true 642 | put: 643 | tags: 644 | - Jobs 645 | summary: Modify Job Application 646 | operationId: modifyJobApplicationWithId 647 | requestBody: 648 | description: Update the application details 649 | content: 650 | application/json: 651 | schema: 652 | $ref: '#/components/schemas/JobApplication' 653 | responses: 654 | '200': 655 | description: OK 656 | content: 657 | application/json: 658 | schema: 659 | $ref: '#/components/schemas/JobApplication' 660 | components: 661 | schemas: 662 | User: 663 | type: object 664 | properties: 665 | id: 666 | type: string 667 | email: 668 | type: string 669 | password: 670 | type: string 671 | full_name: 672 | type: string 673 | roles: 674 | type: array 675 | items: 676 | type: string 677 | Job: 678 | type: object 679 | properties: 680 | id: 681 | type: string 682 | creator_user_id: 683 | type: string 684 | start_time: 685 | type: string 686 | end_time: 687 | type: string 688 | activity: 689 | type: string 690 | dog: 691 | $ref: '#/components/schemas/Dog' 692 | Dog: 693 | type: object 694 | properties: 695 | name: 696 | type: string 697 | age: 698 | type: integer 699 | breed: 700 | type: string 701 | size: 702 | type: string 703 | JobApplication: 704 | type: object 705 | properties: 706 | id: 707 | type: string 708 | status: 709 | type: string 710 | user_id: 711 | type: string 712 | job_id: 713 | type: string -------------------------------------------------------------------------------- /ch14/README.md: -------------------------------------------------------------------------------- 1 | # Chapter 14: Integrating and releasing the web application 2 | 3 | The file [openapi-merged.yaml](openapi-merged.yaml) contains the OpenAPI file for the PetSitter project in its state at the beginning of [chapter 14](https://livebook.manning.com/book/designing-apis-with-swagger-and-openapi/chapter-14) after combining the changes from chapter 12 and 13. 4 | 5 | The file [openapi.yaml](openapi.yaml) contains the OpenAPI file for the PetSitter project in its state at the end of [chapter 14](https://livebook.manning.com/book/designing-apis-with-swagger-and-openapi/chapter-14) when security was added. -------------------------------------------------------------------------------- /ch16/README.md: -------------------------------------------------------------------------------- 1 | # Chapter 16: Designing the next API iteration 2 | 3 | The file [openapi.yaml](openapi.yaml) contains the OpenAPI file for the PetSitter project after the updates made in [chapter 16](https://livebook.manning.com/book/designing-apis-with-swagger-and-openapi/chapter-16). -------------------------------------------------------------------------------- /ch16/openapi.yaml: -------------------------------------------------------------------------------- 1 | openapi: 3.0.0 2 | info: 3 | title: PetSitter API 4 | version: "0.1" 5 | tags: 6 | - name: Users 7 | description: User-related operations 8 | - name: Jobs 9 | description: Job-related operations 10 | paths: 11 | /users: 12 | post: 13 | tags: 14 | - Users 15 | summary: Register User 16 | operationId: registerUser 17 | responses: 18 | '201': 19 | description: Created 20 | headers: 21 | Location: 22 | schema: 23 | type: string 24 | requestBody: 25 | content: 26 | application/json: 27 | schema: 28 | $ref: '#/components/schemas/User' 29 | security: [] 30 | /users/{id}: 31 | parameters: 32 | - schema: 33 | type: string 34 | name: id 35 | in: path 36 | required: true 37 | get: 38 | tags: 39 | - Users 40 | summary: View User 41 | operationId: viewUserWithId 42 | responses: 43 | '200': 44 | description: OK 45 | content: 46 | application/json: 47 | schema: 48 | $ref: '#/components/schemas/User' 49 | put: 50 | tags: 51 | - Users 52 | summary: Modify User 53 | operationId: modifyUserWithId 54 | responses: 55 | '200': 56 | description: OK 57 | content: 58 | application/json: 59 | schema: 60 | $ref: '#/components/schemas/User' 61 | requestBody: 62 | content: 63 | application/json: 64 | schema: 65 | $ref: '#/components/schemas/User' 66 | delete: 67 | tags: 68 | - Users 69 | summary: Delete User 70 | operationId: deleteUserWithId 71 | responses: 72 | '204': 73 | description: No Content 74 | /jobs: 75 | post: 76 | tags: 77 | - Jobs 78 | summary: Create Job 79 | operationId: createJob 80 | responses: 81 | '201': 82 | description: Created 83 | headers: 84 | Location: 85 | schema: 86 | type: string 87 | requestBody: 88 | content: 89 | application/json: 90 | schema: 91 | $ref: '#/components/schemas/Job' 92 | get: 93 | tags: 94 | - Jobs 95 | summary: List All Jobs 96 | operationId: listAllJobs 97 | responses: 98 | '200': 99 | description: OK 100 | content: 101 | application/json: 102 | schema: 103 | type: object 104 | properties: 105 | items: 106 | type: array 107 | items: 108 | $ref: '#/components/schemas/Job' 109 | /jobs/{id}: 110 | parameters: 111 | - schema: 112 | type: string 113 | name: id 114 | in: path 115 | required: true 116 | get: 117 | tags: 118 | - Jobs 119 | summary: View Job 120 | operationId: viewJobWithId 121 | responses: 122 | '200': 123 | description: OK 124 | content: 125 | application/json: 126 | schema: 127 | $ref: '#/components/schemas/Job' 128 | put: 129 | tags: 130 | - Jobs 131 | summary: Modify Job 132 | operationId: modifyJobWithId 133 | responses: 134 | '200': 135 | description: OK 136 | content: 137 | application/json: 138 | schema: 139 | $ref: '#/components/schemas/Job' 140 | requestBody: 141 | content: 142 | application/json: 143 | schema: 144 | $ref: '#/components/schemas/Job' 145 | delete: 146 | tags: 147 | - Jobs 148 | summary: Delete Job 149 | operationId: deleteJobWithId 150 | responses: 151 | '204': 152 | description: No Content 153 | /jobs/{id}/job-applications: 154 | parameters: 155 | - schema: 156 | type: string 157 | name: id 158 | in: path 159 | required: true 160 | get: 161 | tags: 162 | - Jobs 163 | summary: List Applications For Job 164 | operationId: viewApplicationsForJob 165 | responses: 166 | '200': 167 | description: OK 168 | content: 169 | application/json: 170 | schema: 171 | type: object 172 | properties: 173 | items: 174 | type: array 175 | items: 176 | $ref: '#/components/schemas/JobApplication' 177 | post: 178 | tags: 179 | - Jobs 180 | summary: Create Job Application 181 | operationId: createJobApplication 182 | responses: 183 | '201': 184 | description: Created 185 | headers: 186 | Location: 187 | schema: 188 | type: string 189 | requestBody: 190 | content: 191 | application/json: 192 | schema: 193 | $ref: '#/components/schemas/JobApplication' 194 | /users/{id}/jobs: 195 | parameters: 196 | - schema: 197 | type: string 198 | name: id 199 | in: path 200 | required: true 201 | get: 202 | tags: 203 | - Users 204 | summary: List Jobs For User 205 | operationId: listJobsForUser 206 | responses: 207 | '200': 208 | description: OK 209 | content: 210 | application/json: 211 | schema: 212 | type: object 213 | properties: 214 | items: 215 | type: array 216 | items: 217 | $ref: '#/components/schemas/Job' 218 | /users/{id}/job-applications: 219 | parameters: 220 | - name: id 221 | in: path 222 | required: true 223 | schema: 224 | type: integer 225 | get: 226 | tags: 227 | - Users 228 | summary: List Applications For User 229 | operationId: viewApplicationsForUser 230 | responses: 231 | '200': 232 | description: OK 233 | content: 234 | application/json: 235 | schema: 236 | type: object 237 | properties: 238 | items: 239 | type: array 240 | items: 241 | $ref: '#/components/schemas/JobApplication' 242 | /job-applications/{id}: 243 | parameters: 244 | - schema: 245 | type: string 246 | name: id 247 | in: path 248 | required: true 249 | put: 250 | tags: 251 | - Jobs 252 | summary: Modify Job Application 253 | operationId: modifyJobApplicationWithId 254 | requestBody: 255 | description: Update the application details 256 | content: 257 | application/json: 258 | schema: 259 | $ref: '#/components/schemas/JobApplication' 260 | responses: 261 | '200': 262 | description: OK 263 | content: 264 | application/json: 265 | schema: 266 | type: array 267 | items: 268 | $ref: '#/components/schemas/JobApplication' 269 | /sessions: 270 | post: 271 | tags: 272 | - Users 273 | summary: Start Session (Login) 274 | operationId: startSession 275 | responses: 276 | '200': 277 | description: OK 278 | content: 279 | application/json: 280 | schema: 281 | $ref: '#/components/schemas/Session' 282 | requestBody: 283 | content: 284 | application/json: 285 | schema: 286 | type: object 287 | properties: 288 | email: 289 | type: string 290 | password: 291 | type: string 292 | security: [] 293 | components: 294 | schemas: 295 | User: 296 | type: object 297 | properties: 298 | id: 299 | type: string 300 | email: 301 | type: string 302 | password: 303 | type: string 304 | full_name: 305 | type: string 306 | roles: 307 | type: array 308 | items: 309 | type: string 310 | Job: 311 | type: object 312 | properties: 313 | id: 314 | type: string 315 | creator_user_id: 316 | type: string 317 | start_time: 318 | type: string 319 | end_time: 320 | type: string 321 | activity: 322 | type: string 323 | pets: 324 | type: array 325 | items: 326 | $ref: '#/components/schemas/Pet' 327 | Dog: 328 | type: object 329 | properties: 330 | species: 331 | type: string 332 | breed: 333 | type: string 334 | size: 335 | type: string 336 | required: 337 | - species 338 | Cat: 339 | type: object 340 | properties: 341 | species: 342 | type: string 343 | breed: 344 | type: string 345 | required: 346 | - species 347 | Pet: 348 | allOf: 349 | - type: object 350 | properties: 351 | name: 352 | type: string 353 | age: 354 | type: integer 355 | - oneOf: 356 | - $ref: '#/components/schemas/Cat' 357 | - $ref: '#/components/schemas/Dog' 358 | discriminator: 359 | propertyName: species 360 | mapping: 361 | Cat: '#/components/schemas/Cat' 362 | Dog: '#/components/schemas/Dog' 363 | JobApplication: 364 | type: object 365 | properties: 366 | id: 367 | type: string 368 | status: 369 | type: string 370 | user_id: 371 | type: string 372 | job_id: 373 | type: string 374 | Session: 375 | type: object 376 | properties: 377 | user_id: 378 | type: string 379 | auth_header: 380 | type: string 381 | securitySchemes: 382 | SessionToken: 383 | type: apiKey 384 | in: header 385 | name: Authorization 386 | security: 387 | - SessionToken: [] 388 | -------------------------------------------------------------------------------- /ch17/README.md: -------------------------------------------------------------------------------- 1 | # Chapter 17: Scaling collection endpoints with filters and pagination 2 | 3 | The file [openapi.yaml](openapi.yaml) contains the OpenAPI file for the PetSitter project after the updates made in [chapter 17](https://livebook.manning.com/book/designing-apis-with-swagger-and-openapi/chapter-17). -------------------------------------------------------------------------------- /ch17/openapi.yaml: -------------------------------------------------------------------------------- 1 | openapi: 3.0.0 2 | info: 3 | title: PetSitter API 4 | version: "0.1" 5 | tags: 6 | - name: Users 7 | description: User-related operations 8 | - name: Jobs 9 | description: Job-related operations 10 | paths: 11 | /users: 12 | post: 13 | tags: 14 | - Users 15 | summary: Register User 16 | operationId: registerUser 17 | responses: 18 | '201': 19 | description: Created 20 | headers: 21 | Location: 22 | schema: 23 | type: string 24 | requestBody: 25 | content: 26 | application/json: 27 | schema: 28 | $ref: '#/components/schemas/User' 29 | security: [] 30 | /users/{id}: 31 | parameters: 32 | - schema: 33 | type: string 34 | name: id 35 | in: path 36 | required: true 37 | get: 38 | tags: 39 | - Users 40 | summary: View User 41 | operationId: viewUserWithId 42 | responses: 43 | '200': 44 | description: OK 45 | content: 46 | application/json: 47 | schema: 48 | $ref: '#/components/schemas/User' 49 | put: 50 | tags: 51 | - Users 52 | summary: Modify User 53 | operationId: modifyUserWithId 54 | responses: 55 | '200': 56 | description: OK 57 | content: 58 | application/json: 59 | schema: 60 | $ref: '#/components/schemas/User' 61 | requestBody: 62 | content: 63 | application/json: 64 | schema: 65 | $ref: '#/components/schemas/User' 66 | delete: 67 | tags: 68 | - Users 69 | summary: Delete User 70 | operationId: deleteUserWithId 71 | responses: 72 | '204': 73 | description: No Content 74 | /jobs: 75 | post: 76 | tags: 77 | - Jobs 78 | summary: Create Job 79 | operationId: createJob 80 | responses: 81 | '201': 82 | description: Created 83 | headers: 84 | Location: 85 | schema: 86 | type: string 87 | requestBody: 88 | content: 89 | application/json: 90 | schema: 91 | $ref: '#/components/schemas/Job' 92 | get: 93 | tags: 94 | - Jobs 95 | summary: List/Search Available Jobs 96 | operationId: listOrSearchAvailableJobs 97 | parameters: 98 | - name: start_time_before 99 | in: query 100 | description: Search jobs starting before this date and time. 101 | schema: 102 | type: string 103 | format: date-time 104 | - name: start_time_after 105 | in: query 106 | description: Search jobs starting after this date and time. 107 | schema: 108 | type: string 109 | format: date-time 110 | - name: end_time_before 111 | in: query 112 | description: Search jobs ending before this date and time. 113 | schema: 114 | type: string 115 | format: date-time 116 | - name: end_time_after 117 | in: query 118 | description: Search jobs ending after this date and time. 119 | schema: 120 | type: string 121 | format: date-time 122 | - name: activity 123 | in: query 124 | description: Performs a full-text search for the phrase entered in job activities. 125 | schema: 126 | type: string 127 | - name: pets 128 | in: query 129 | description: Searches for pets matching specific criteria. 130 | style: deepObject 131 | schema: 132 | type: object 133 | properties: 134 | age_below: 135 | type: integer 136 | description: Return only pets with this age or younger. 137 | age_above: 138 | type: integer 139 | description: Return only pets with this age or older. 140 | species: 141 | type: string 142 | description: Return only pets with this species. Provide multiple species as comma-separated values. 143 | - name: limit 144 | in: query 145 | description: The maximum number of results to return. 146 | schema: 147 | type: integer 148 | default: 20 149 | maximum: 100 150 | - name: cursor 151 | in: query 152 | description: Use the cursor from the response to access more results. 153 | schema: 154 | type: string 155 | - name: sort 156 | in: query 157 | description: | 158 | Indicate the sorting key and direction for the results. 159 | Use the field name, suffixed with ":asc" for ascending 160 | or ":desc" for descending order. 161 | Valid fields: start_time, end_time 162 | schema: 163 | type: string 164 | responses: 165 | '200': 166 | description: OK 167 | content: 168 | application/json: 169 | schema: 170 | type: object 171 | properties: 172 | items: 173 | type: array 174 | items: 175 | $ref: '#/components/schemas/Job' 176 | cursor: 177 | type: string 178 | description: Cursor for the next result page. 179 | nullable: true 180 | /jobs/{id}: 181 | parameters: 182 | - schema: 183 | type: string 184 | name: id 185 | in: path 186 | required: true 187 | get: 188 | tags: 189 | - Jobs 190 | summary: View Job 191 | operationId: viewJobWithId 192 | responses: 193 | '200': 194 | description: OK 195 | content: 196 | application/json: 197 | schema: 198 | $ref: '#/components/schemas/Job' 199 | put: 200 | tags: 201 | - Jobs 202 | summary: Modify Job 203 | operationId: modifyJobWithId 204 | responses: 205 | '200': 206 | description: OK 207 | content: 208 | application/json: 209 | schema: 210 | $ref: '#/components/schemas/Job' 211 | requestBody: 212 | content: 213 | application/json: 214 | schema: 215 | $ref: '#/components/schemas/Job' 216 | delete: 217 | tags: 218 | - Jobs 219 | summary: Delete Job 220 | operationId: deleteJobWithId 221 | responses: 222 | '204': 223 | description: No Content 224 | /jobs/{id}/job-applications: 225 | parameters: 226 | - schema: 227 | type: string 228 | name: id 229 | in: path 230 | required: true 231 | get: 232 | tags: 233 | - Jobs 234 | summary: List Applications For Job 235 | operationId: viewApplicationsForJob 236 | responses: 237 | '200': 238 | description: OK 239 | content: 240 | application/json: 241 | schema: 242 | type: object 243 | properties: 244 | items: 245 | type: array 246 | items: 247 | $ref: '#/components/schemas/JobApplication' 248 | post: 249 | tags: 250 | - Jobs 251 | summary: Create Job Application 252 | operationId: createJobApplication 253 | responses: 254 | '201': 255 | description: Created 256 | headers: 257 | Location: 258 | schema: 259 | type: string 260 | requestBody: 261 | content: 262 | application/json: 263 | schema: 264 | $ref: '#/components/schemas/JobApplication' 265 | /users/{id}/jobs: 266 | parameters: 267 | - schema: 268 | type: string 269 | name: id 270 | in: path 271 | required: true 272 | get: 273 | tags: 274 | - Users 275 | summary: List Jobs For User 276 | operationId: listJobsForUser 277 | responses: 278 | '200': 279 | description: OK 280 | content: 281 | application/json: 282 | schema: 283 | type: object 284 | properties: 285 | items: 286 | type: array 287 | items: 288 | $ref: '#/components/schemas/Job' 289 | /users/{id}/job-applications: 290 | parameters: 291 | - name: id 292 | in: path 293 | required: true 294 | schema: 295 | type: integer 296 | get: 297 | tags: 298 | - Users 299 | summary: List Applications For User 300 | operationId: viewApplicationsForUser 301 | responses: 302 | '200': 303 | description: OK 304 | content: 305 | application/json: 306 | schema: 307 | type: object 308 | properties: 309 | items: 310 | type: array 311 | items: 312 | $ref: '#/components/schemas/JobApplication' 313 | /job-applications/{id}: 314 | parameters: 315 | - schema: 316 | type: string 317 | name: id 318 | in: path 319 | required: true 320 | put: 321 | tags: 322 | - Jobs 323 | summary: Modify Job Application 324 | operationId: modifyJobApplicationWithId 325 | requestBody: 326 | description: Update the application details 327 | content: 328 | application/json: 329 | schema: 330 | $ref: '#/components/schemas/JobApplication' 331 | responses: 332 | '200': 333 | description: OK 334 | content: 335 | application/json: 336 | schema: 337 | type: array 338 | items: 339 | $ref: '#/components/schemas/JobApplication' 340 | /sessions: 341 | post: 342 | tags: 343 | - Users 344 | summary: Start Session (Login) 345 | operationId: startSession 346 | responses: 347 | '200': 348 | description: OK 349 | content: 350 | application/json: 351 | schema: 352 | $ref: '#/components/schemas/Session' 353 | requestBody: 354 | content: 355 | application/json: 356 | schema: 357 | type: object 358 | properties: 359 | email: 360 | type: string 361 | password: 362 | type: string 363 | security: [] 364 | components: 365 | schemas: 366 | User: 367 | type: object 368 | properties: 369 | id: 370 | type: string 371 | email: 372 | type: string 373 | password: 374 | type: string 375 | full_name: 376 | type: string 377 | roles: 378 | type: array 379 | items: 380 | type: string 381 | Job: 382 | type: object 383 | properties: 384 | id: 385 | type: string 386 | creator_user_id: 387 | type: string 388 | start_time: 389 | type: string 390 | end_time: 391 | type: string 392 | activity: 393 | type: string 394 | pets: 395 | type: array 396 | items: 397 | $ref: '#/components/schemas/Pet' 398 | Dog: 399 | type: object 400 | properties: 401 | species: 402 | type: string 403 | breed: 404 | type: string 405 | size: 406 | type: string 407 | required: 408 | - species 409 | Cat: 410 | type: object 411 | properties: 412 | species: 413 | type: string 414 | breed: 415 | type: string 416 | required: 417 | - species 418 | Pet: 419 | allOf: 420 | - type: object 421 | properties: 422 | name: 423 | type: string 424 | age: 425 | type: integer 426 | - oneOf: 427 | - $ref: '#/components/schemas/Cat' 428 | - $ref: '#/components/schemas/Dog' 429 | discriminator: 430 | propertyName: species 431 | mapping: 432 | Cat: '#/components/schemas/Cat' 433 | Dog: '#/components/schemas/Dog' 434 | JobApplication: 435 | type: object 436 | properties: 437 | id: 438 | type: string 439 | status: 440 | type: string 441 | user_id: 442 | type: string 443 | job_id: 444 | type: string 445 | Session: 446 | type: object 447 | properties: 448 | user_id: 449 | type: string 450 | auth_header: 451 | type: string 452 | securitySchemes: 453 | SessionToken: 454 | type: apiKey 455 | in: header 456 | name: Authorization 457 | security: 458 | - SessionToken: [] 459 | -------------------------------------------------------------------------------- /ch18/README.md: -------------------------------------------------------------------------------- 1 | # Chapter 18: Supporting the unhappy path: error handling with problem+json 2 | 3 | The file [openapi.yaml](openapi.yaml) contains the OpenAPI file for the PetSitter project after the updates made in [chapter 18](https://livebook.manning.com/book/designing-apis-with-swagger-and-openapi/chapter-18). -------------------------------------------------------------------------------- /ch18/openapi.yaml: -------------------------------------------------------------------------------- 1 | openapi: 3.0.0 2 | info: 3 | title: PetSitter API 4 | version: "0.1" 5 | tags: 6 | - name: Users 7 | description: User-related operations 8 | - name: Jobs 9 | description: Job-related operations 10 | paths: 11 | /users: 12 | post: 13 | tags: 14 | - Users 15 | summary: Register User 16 | operationId: registerUser 17 | responses: 18 | '201': 19 | description: Created 20 | headers: 21 | Location: 22 | schema: 23 | type: string 24 | requestBody: 25 | content: 26 | application/json: 27 | schema: 28 | $ref: '#/components/schemas/User' 29 | security: [] 30 | /users/{id}: 31 | parameters: 32 | - schema: 33 | type: string 34 | name: id 35 | in: path 36 | required: true 37 | get: 38 | tags: 39 | - Users 40 | summary: View User 41 | operationId: viewUserWithId 42 | responses: 43 | '200': 44 | description: OK 45 | content: 46 | application/json: 47 | schema: 48 | $ref: '#/components/schemas/User' 49 | put: 50 | tags: 51 | - Users 52 | summary: Modify User 53 | operationId: modifyUserWithId 54 | responses: 55 | '200': 56 | description: OK 57 | content: 58 | application/json: 59 | schema: 60 | $ref: '#/components/schemas/User' 61 | requestBody: 62 | content: 63 | application/json: 64 | schema: 65 | $ref: '#/components/schemas/User' 66 | delete: 67 | tags: 68 | - Users 69 | summary: Delete User 70 | operationId: deleteUserWithId 71 | responses: 72 | '204': 73 | description: No Content 74 | /jobs: 75 | post: 76 | tags: 77 | - Jobs 78 | summary: Create Job 79 | operationId: createJob 80 | responses: 81 | '201': 82 | description: Created 83 | headers: 84 | Location: 85 | schema: 86 | type: string 87 | '400': 88 | description: Bad request 89 | content: 90 | application/json: 91 | schema: 92 | $ref: '#/components/schemas/OASError' 93 | '401': 94 | description: Unauthorized 95 | content: 96 | application/json: 97 | schema: 98 | $ref: '#/components/schemas/OASError' 99 | '403': 100 | description: Forbidden 101 | content: 102 | application/problem+json: 103 | schema: 104 | $ref: '#/components/schemas/Problem' 105 | get: 106 | tags: 107 | - Jobs 108 | summary: List/Search Available Jobs 109 | operationId: listOrSearchAvailableJobs 110 | parameters: 111 | - name: start_time_before 112 | in: query 113 | description: Search jobs starting before this date and time. 114 | schema: 115 | type: string 116 | format: date-time 117 | - name: start_time_after 118 | in: query 119 | description: Search jobs starting after this date and time. 120 | schema: 121 | type: string 122 | format: date-time 123 | - name: end_time_before 124 | in: query 125 | description: Search jobs ending before this date and time. 126 | schema: 127 | type: string 128 | format: date-time 129 | - name: end_time_after 130 | in: query 131 | description: Search jobs ending after this date and time. 132 | schema: 133 | type: string 134 | format: date-time 135 | - name: activity 136 | in: query 137 | description: Performs a full-text search for the phrase entered in job activities. 138 | schema: 139 | type: string 140 | - name: pets 141 | in: query 142 | description: Searches for pets matching specific criteria. 143 | style: deepObject 144 | schema: 145 | type: object 146 | properties: 147 | age_below: 148 | type: integer 149 | description: Return only pets with this age or younger. 150 | age_above: 151 | type: integer 152 | description: Return only pets with this age or older. 153 | species: 154 | type: string 155 | description: Return only pets with this species. Provide multiple species as comma-separated values. 156 | - name: limit 157 | in: query 158 | description: The maximum number of results to return. 159 | schema: 160 | type: integer 161 | default: 20 162 | maximum: 100 163 | - name: cursor 164 | in: query 165 | description: Use the cursor from the response to access more results. 166 | schema: 167 | type: string 168 | - name: sort 169 | in: query 170 | description: | 171 | Indicate the sorting key and direction for the results. 172 | Use the field name, suffixed with ":asc" for ascending 173 | or ":desc" for descending order. 174 | Valid fields: start_time, end_time 175 | schema: 176 | type: string 177 | responses: 178 | '200': 179 | description: OK 180 | content: 181 | application/json: 182 | schema: 183 | type: object 184 | properties: 185 | items: 186 | type: array 187 | items: 188 | $ref: '#/components/schemas/Job' 189 | cursor: 190 | type: string 191 | description: Cursor for the next result page. 192 | nullable: true 193 | /jobs/{id}: 194 | parameters: 195 | - schema: 196 | type: string 197 | name: id 198 | in: path 199 | required: true 200 | get: 201 | tags: 202 | - Jobs 203 | summary: View Job 204 | operationId: viewJobWithId 205 | responses: 206 | '200': 207 | description: OK 208 | content: 209 | application/json: 210 | schema: 211 | $ref: '#/components/schemas/Job' 212 | put: 213 | tags: 214 | - Jobs 215 | summary: Modify Job 216 | operationId: modifyJobWithId 217 | responses: 218 | '200': 219 | description: OK 220 | content: 221 | application/json: 222 | schema: 223 | $ref: '#/components/schemas/Job' 224 | requestBody: 225 | content: 226 | application/json: 227 | schema: 228 | $ref: '#/components/schemas/Job' 229 | delete: 230 | tags: 231 | - Jobs 232 | summary: Delete Job 233 | operationId: deleteJobWithId 234 | responses: 235 | '204': 236 | description: No Content 237 | /jobs/{id}/job-applications: 238 | parameters: 239 | - schema: 240 | type: string 241 | name: id 242 | in: path 243 | required: true 244 | get: 245 | tags: 246 | - Jobs 247 | summary: List Applications For Job 248 | operationId: viewApplicationsForJob 249 | responses: 250 | '200': 251 | description: OK 252 | content: 253 | application/json: 254 | schema: 255 | type: object 256 | properties: 257 | items: 258 | type: array 259 | items: 260 | $ref: '#/components/schemas/JobApplication' 261 | post: 262 | tags: 263 | - Jobs 264 | summary: Create Job Application 265 | operationId: createJobApplication 266 | responses: 267 | '201': 268 | description: Created 269 | headers: 270 | Location: 271 | schema: 272 | type: string 273 | requestBody: 274 | content: 275 | application/json: 276 | schema: 277 | $ref: '#/components/schemas/JobApplication' 278 | /users/{id}/jobs: 279 | parameters: 280 | - schema: 281 | type: string 282 | name: id 283 | in: path 284 | required: true 285 | get: 286 | tags: 287 | - Users 288 | summary: List Jobs For User 289 | operationId: listJobsForUser 290 | responses: 291 | '200': 292 | description: OK 293 | content: 294 | application/json: 295 | schema: 296 | type: object 297 | properties: 298 | items: 299 | type: array 300 | items: 301 | $ref: '#/components/schemas/Job' 302 | /users/{id}/job-applications: 303 | parameters: 304 | - name: id 305 | in: path 306 | required: true 307 | schema: 308 | type: integer 309 | get: 310 | tags: 311 | - Users 312 | summary: List Applications For User 313 | operationId: viewApplicationsForUser 314 | responses: 315 | '200': 316 | description: OK 317 | content: 318 | application/json: 319 | schema: 320 | type: object 321 | properties: 322 | items: 323 | type: array 324 | items: 325 | $ref: '#/components/schemas/JobApplication' 326 | /job-applications/{id}: 327 | parameters: 328 | - schema: 329 | type: string 330 | name: id 331 | in: path 332 | required: true 333 | put: 334 | tags: 335 | - Jobs 336 | summary: Modify Job Application 337 | operationId: modifyJobApplicationWithId 338 | requestBody: 339 | description: Update the application details 340 | content: 341 | application/json: 342 | schema: 343 | $ref: '#/components/schemas/JobApplication' 344 | responses: 345 | '200': 346 | description: OK 347 | content: 348 | application/json: 349 | schema: 350 | type: array 351 | items: 352 | $ref: '#/components/schemas/JobApplication' 353 | /sessions: 354 | post: 355 | tags: 356 | - Users 357 | summary: Start Session (Login) 358 | operationId: startSession 359 | responses: 360 | '200': 361 | description: OK 362 | content: 363 | application/json: 364 | schema: 365 | $ref: '#/components/schemas/Session' 366 | requestBody: 367 | content: 368 | application/json: 369 | schema: 370 | type: object 371 | properties: 372 | email: 373 | type: string 374 | password: 375 | type: string 376 | security: [] 377 | components: 378 | schemas: 379 | User: 380 | type: object 381 | properties: 382 | id: 383 | type: string 384 | email: 385 | type: string 386 | password: 387 | type: string 388 | full_name: 389 | type: string 390 | roles: 391 | type: array 392 | items: 393 | type: string 394 | Job: 395 | type: object 396 | properties: 397 | id: 398 | type: string 399 | creator_user_id: 400 | type: string 401 | start_time: 402 | type: string 403 | end_time: 404 | type: string 405 | activity: 406 | type: string 407 | pets: 408 | type: array 409 | items: 410 | $ref: '#/components/schemas/Pet' 411 | Dog: 412 | type: object 413 | properties: 414 | species: 415 | type: string 416 | breed: 417 | type: string 418 | size: 419 | type: string 420 | required: 421 | - species 422 | Cat: 423 | type: object 424 | properties: 425 | species: 426 | type: string 427 | breed: 428 | type: string 429 | required: 430 | - species 431 | Pet: 432 | allOf: 433 | - type: object 434 | properties: 435 | name: 436 | type: string 437 | age: 438 | type: integer 439 | - oneOf: 440 | - $ref: '#/components/schemas/Cat' 441 | - $ref: '#/components/schemas/Dog' 442 | discriminator: 443 | propertyName: species 444 | mapping: 445 | Cat: '#/components/schemas/Cat' 446 | Dog: '#/components/schemas/Dog' 447 | JobApplication: 448 | type: object 449 | properties: 450 | id: 451 | type: string 452 | status: 453 | type: string 454 | user_id: 455 | type: string 456 | job_id: 457 | type: string 458 | Session: 459 | type: object 460 | properties: 461 | user_id: 462 | type: string 463 | auth_header: 464 | type: string 465 | OASError: 466 | type: object 467 | properties: 468 | message: 469 | type: string 470 | description: Human-readable error message 471 | errors: 472 | type: array 473 | items: 474 | type: object 475 | properties: 476 | path: 477 | type: string 478 | description: For input validation errors, identifies where in the JSON request body the error occured 479 | message: 480 | type: string 481 | description: Human-readable error message 482 | errorCode: 483 | type: string 484 | description: Code indicating error type 485 | Problem: 486 | type: object 487 | properties: 488 | type: 489 | type: string 490 | description: URI indicating error type 491 | title: 492 | type: string 493 | description: Human-readable error title 494 | status: 495 | type: integer 496 | description: HTTP status code 497 | detail: 498 | type: string 499 | description: Human-readable error details 500 | instance: 501 | type: string 502 | description: URI indicating error instance 503 | securitySchemes: 504 | SessionToken: 505 | type: apiKey 506 | in: header 507 | name: Authorization 508 | security: 509 | - SessionToken: [] 510 | -------------------------------------------------------------------------------- /ch19/README.md: -------------------------------------------------------------------------------- 1 | # Chapter 19: Improving input validation with advanced JSON Schema 2 | 3 | The file [openapi.yaml](openapi.yaml) contains the OpenAPI file for the PetSitter project after the updates made in [chapter 19](https://livebook.manning.com/book/designing-apis-with-swagger-and-openapi/chapter-19). -------------------------------------------------------------------------------- /ch19/openapi.yaml: -------------------------------------------------------------------------------- 1 | openapi: 3.0.3 2 | info: 3 | title: PetSitter API 4 | version: "0.1" 5 | tags: 6 | - name: Users 7 | description: User-related operations 8 | - name: Jobs 9 | description: Job-related operations 10 | paths: 11 | /users: 12 | post: 13 | tags: 14 | - Users 15 | summary: Register User 16 | operationId: registerUser 17 | responses: 18 | '201': 19 | description: Created 20 | headers: 21 | Location: 22 | schema: 23 | type: string 24 | requestBody: 25 | content: 26 | application/json: 27 | schema: 28 | $ref: '#/components/schemas/User' 29 | security: [] 30 | /users/{id}: 31 | parameters: 32 | - schema: 33 | type: string 34 | name: id 35 | in: path 36 | required: true 37 | get: 38 | tags: 39 | - Users 40 | summary: View User 41 | operationId: viewUserWithId 42 | responses: 43 | '200': 44 | description: OK 45 | content: 46 | application/json: 47 | schema: 48 | $ref: '#/components/schemas/User' 49 | put: 50 | tags: 51 | - Users 52 | summary: Modify User 53 | operationId: modifyUserWithId 54 | responses: 55 | '200': 56 | description: OK 57 | content: 58 | application/json: 59 | schema: 60 | $ref: '#/components/schemas/User' 61 | requestBody: 62 | content: 63 | application/json: 64 | schema: 65 | $ref: '#/components/schemas/User' 66 | delete: 67 | tags: 68 | - Users 69 | summary: Delete User 70 | operationId: deleteUserWithId 71 | responses: 72 | '204': 73 | description: No Content 74 | /jobs: 75 | post: 76 | tags: 77 | - Jobs 78 | summary: Create Job 79 | operationId: createJob 80 | responses: 81 | '201': 82 | description: Created 83 | headers: 84 | Location: 85 | schema: 86 | type: string 87 | '400': 88 | description: Bad request 89 | content: 90 | application/json: 91 | schema: 92 | $ref: '#/components/schemas/OASError' 93 | '401': 94 | description: Unauthorized 95 | content: 96 | application/json: 97 | schema: 98 | $ref: '#/components/schemas/OASError' 99 | '403': 100 | description: Forbidden 101 | content: 102 | application/problem+json: 103 | schema: 104 | $ref: '#/components/schemas/Problem' 105 | get: 106 | tags: 107 | - Jobs 108 | summary: List/Search Available Jobs 109 | operationId: listOrSearchAvailableJobs 110 | parameters: 111 | - name: start_time_before 112 | in: query 113 | description: Search jobs starting before this date and time. 114 | schema: 115 | type: string 116 | format: date-time 117 | - name: start_time_after 118 | in: query 119 | description: Search jobs starting after this date and time. 120 | schema: 121 | type: string 122 | format: date-time 123 | - name: end_time_before 124 | in: query 125 | description: Search jobs ending before this date and time. 126 | schema: 127 | type: string 128 | format: date-time 129 | - name: end_time_after 130 | in: query 131 | description: Search jobs ending after this date and time. 132 | schema: 133 | type: string 134 | format: date-time 135 | - name: activity 136 | in: query 137 | description: Performs a full-text search for the phrase entered in job activities. 138 | schema: 139 | type: string 140 | - name: pets 141 | in: query 142 | description: Searches for pets matching specific criteria. 143 | style: deepObject 144 | schema: 145 | type: object 146 | properties: 147 | age_below: 148 | type: integer 149 | description: Return only pets with this age or younger. 150 | age_above: 151 | type: integer 152 | description: Return only pets with this age or older. 153 | species: 154 | type: string 155 | description: Return only pets with this species. Provide multiple species as comma-separated values. 156 | - name: limit 157 | in: query 158 | description: The maximum number of results to return. 159 | schema: 160 | type: integer 161 | default: 20 162 | maximum: 100 163 | - name: cursor 164 | in: query 165 | description: Use the cursor from the response to access more results. 166 | schema: 167 | type: string 168 | - name: sort 169 | in: query 170 | description: | 171 | Indicate the sorting key and direction for the results. 172 | Use the field name, suffixed with ":asc" for ascending 173 | or ":desc" for descending order. 174 | Valid fields: start_time, end_time 175 | schema: 176 | type: string 177 | responses: 178 | '200': 179 | description: OK 180 | content: 181 | application/json: 182 | schema: 183 | type: object 184 | properties: 185 | items: 186 | type: array 187 | items: 188 | $ref: '#/components/schemas/Job' 189 | cursor: 190 | type: string 191 | description: Cursor for the next result page. 192 | nullable: true 193 | /jobs/{id}: 194 | parameters: 195 | - schema: 196 | type: string 197 | name: id 198 | in: path 199 | required: true 200 | get: 201 | tags: 202 | - Jobs 203 | summary: View Job 204 | operationId: viewJobWithId 205 | responses: 206 | '200': 207 | description: OK 208 | content: 209 | application/json: 210 | schema: 211 | $ref: '#/components/schemas/Job' 212 | put: 213 | tags: 214 | - Jobs 215 | summary: Modify Job 216 | operationId: modifyJobWithId 217 | responses: 218 | '200': 219 | description: OK 220 | content: 221 | application/json: 222 | schema: 223 | $ref: '#/components/schemas/Job' 224 | requestBody: 225 | content: 226 | application/json: 227 | schema: 228 | $ref: '#/components/schemas/Job' 229 | delete: 230 | tags: 231 | - Jobs 232 | summary: Delete Job 233 | operationId: deleteJobWithId 234 | responses: 235 | '204': 236 | description: No Content 237 | /jobs/{id}/job-applications: 238 | parameters: 239 | - schema: 240 | type: string 241 | name: id 242 | in: path 243 | required: true 244 | get: 245 | tags: 246 | - Jobs 247 | summary: List Applications For Job 248 | operationId: viewApplicationsForJob 249 | responses: 250 | '200': 251 | description: OK 252 | content: 253 | application/json: 254 | schema: 255 | type: object 256 | properties: 257 | items: 258 | type: array 259 | items: 260 | $ref: '#/components/schemas/JobApplication' 261 | post: 262 | tags: 263 | - Jobs 264 | summary: Create Job Application 265 | operationId: createJobApplication 266 | responses: 267 | '201': 268 | description: Created 269 | headers: 270 | Location: 271 | schema: 272 | type: string 273 | requestBody: 274 | content: 275 | application/json: 276 | schema: 277 | $ref: '#/components/schemas/JobApplication' 278 | /users/{id}/jobs: 279 | parameters: 280 | - schema: 281 | type: string 282 | name: id 283 | in: path 284 | required: true 285 | get: 286 | tags: 287 | - Users 288 | summary: List Jobs For User 289 | operationId: listJobsForUser 290 | responses: 291 | '200': 292 | description: OK 293 | content: 294 | application/json: 295 | schema: 296 | type: object 297 | properties: 298 | items: 299 | type: array 300 | items: 301 | $ref: '#/components/schemas/Job' 302 | /users/{id}/job-applications: 303 | parameters: 304 | - name: id 305 | in: path 306 | required: true 307 | schema: 308 | type: integer 309 | get: 310 | tags: 311 | - Users 312 | summary: List Applications For User 313 | operationId: viewApplicationsForUser 314 | responses: 315 | '200': 316 | description: OK 317 | content: 318 | application/json: 319 | schema: 320 | type: object 321 | properties: 322 | items: 323 | type: array 324 | items: 325 | $ref: '#/components/schemas/JobApplication' 326 | /job-applications/{id}: 327 | parameters: 328 | - schema: 329 | type: string 330 | name: id 331 | in: path 332 | required: true 333 | put: 334 | tags: 335 | - Jobs 336 | summary: Modify Job Application 337 | operationId: modifyJobApplicationWithId 338 | requestBody: 339 | description: Update the application details 340 | content: 341 | application/json: 342 | schema: 343 | $ref: '#/components/schemas/JobApplication' 344 | responses: 345 | '200': 346 | description: OK 347 | content: 348 | application/json: 349 | schema: 350 | type: array 351 | items: 352 | $ref: '#/components/schemas/JobApplication' 353 | /sessions: 354 | post: 355 | tags: 356 | - Users 357 | summary: Start Session (Login) 358 | operationId: startSession 359 | responses: 360 | '200': 361 | description: OK 362 | content: 363 | application/json: 364 | schema: 365 | $ref: '#/components/schemas/Session' 366 | requestBody: 367 | content: 368 | application/json: 369 | schema: 370 | type: object 371 | properties: 372 | email: 373 | type: string 374 | password: 375 | type: string 376 | security: [] 377 | components: 378 | schemas: 379 | User: 380 | type: object 381 | properties: 382 | id: 383 | type: integer 384 | readOnly: true 385 | email: 386 | type: string 387 | format: email 388 | password: 389 | type: string 390 | format: password 391 | writeOnly: true 392 | minLength: 8 393 | full_name: 394 | type: string 395 | minLength: 2 396 | maxLength: 50 397 | roles: 398 | type: array 399 | minItems: 1 400 | uniqueItems: true 401 | items: 402 | type: string 403 | enum: 404 | - PetOwner 405 | - PetSitter 406 | - Admin 407 | required: 408 | - email 409 | - full_name 410 | - roles 411 | Job: 412 | type: object 413 | properties: 414 | id: 415 | type: integer 416 | readOnly: true 417 | creator_user_id: 418 | type: integer 419 | readOnly: true 420 | start_time: 421 | type: string 422 | format: date-time 423 | end_time: 424 | type: string 425 | format: date-time 426 | activity: 427 | type: string 428 | minLength: 5 429 | maxLength: 500 430 | pets: 431 | type: array 432 | minItems: 1 433 | maxItems: 10 434 | items: 435 | $ref: '#/components/schemas/Pet' 436 | required: 437 | - id 438 | - creator_user_id 439 | - start_time 440 | - end_time 441 | - pets 442 | Dog: 443 | type: object 444 | properties: 445 | species: 446 | type: string 447 | breed: 448 | type: string 449 | size: 450 | type: string 451 | required: 452 | - species 453 | Cat: 454 | type: object 455 | properties: 456 | species: 457 | type: string 458 | breed: 459 | type: string 460 | required: 461 | - species 462 | Pet: 463 | allOf: 464 | - type: object 465 | properties: 466 | name: 467 | type: string 468 | minLength: 2 469 | maxLength: 20 470 | age: 471 | type: integer 472 | minimum: 1 473 | maximum: 100 474 | - oneOf: 475 | - $ref: '#/components/schemas/Cat' 476 | - $ref: '#/components/schemas/Dog' 477 | discriminator: 478 | propertyName: species 479 | mapping: 480 | Cat: '#/components/schemas/Cat' 481 | Dog: '#/components/schemas/Dog' 482 | JobApplication: 483 | type: object 484 | properties: 485 | id: 486 | type: string 487 | readOnly: true 488 | status: 489 | type: string 490 | default: applying 491 | enum: 492 | - applying 493 | - approved 494 | - rejected 495 | user_id: 496 | type: string 497 | readOnly: true 498 | job_id: 499 | type: string 500 | readOnly: true 501 | required: 502 | - id 503 | - status 504 | - user_id 505 | - job_id 506 | Session: 507 | type: object 508 | properties: 509 | user_id: 510 | type: string 511 | auth_header: 512 | type: string 513 | OASError: 514 | type: object 515 | properties: 516 | message: 517 | type: string 518 | description: Human-readable error message 519 | errors: 520 | type: array 521 | items: 522 | type: object 523 | properties: 524 | path: 525 | type: string 526 | description: For input validation errors, identifies where in the JSON request body the error occured 527 | message: 528 | type: string 529 | description: Human-readable error message 530 | errorCode: 531 | type: string 532 | description: Code indicating error type 533 | Problem: 534 | type: object 535 | properties: 536 | type: 537 | type: string 538 | description: URI indicating error type 539 | title: 540 | type: string 541 | description: Human-readable error title 542 | status: 543 | type: integer 544 | description: HTTP status code 545 | detail: 546 | type: string 547 | description: Human-readable error details 548 | instance: 549 | type: string 550 | description: URI indicating error instance 551 | securitySchemes: 552 | SessionToken: 553 | type: apiKey 554 | in: header 555 | name: Authorization 556 | security: 557 | - SessionToken: [] 558 | -------------------------------------------------------------------------------- /ch20/README.md: -------------------------------------------------------------------------------- 1 | # Chapter 20: Versioning an API and handling breaking changes 2 | 3 | The file [openapi.yaml](openapi.yaml) contains the OpenAPI file for the PetSitter project after the updates made in [chapter 20](https://livebook.manning.com/book/designing-apis-with-swagger-and-openapi/chapter-20). -------------------------------------------------------------------------------- /ch20/openapi.yml: -------------------------------------------------------------------------------- 1 | openapi: 3.0.3 2 | info: 3 | title: PetSitter API 4 | version: "0.1" 5 | tags: 6 | - name: Users 7 | description: User-related operations 8 | - name: Jobs 9 | description: Job-related operations 10 | paths: 11 | /users: 12 | post: 13 | tags: 14 | - Users 15 | summary: Register User 16 | operationId: registerUser 17 | responses: 18 | '201': 19 | description: Created 20 | headers: 21 | Location: 22 | schema: 23 | type: string 24 | requestBody: 25 | content: 26 | application/json: 27 | schema: 28 | $ref: '#/components/schemas/User' 29 | security: [] 30 | /users/{id}: 31 | parameters: 32 | - schema: 33 | type: string 34 | name: id 35 | in: path 36 | required: true 37 | get: 38 | tags: 39 | - Users 40 | summary: View User 41 | operationId: viewUserWithId 42 | responses: 43 | '200': 44 | description: OK 45 | content: 46 | application/json: 47 | schema: 48 | $ref: '#/components/schemas/User' 49 | put: 50 | tags: 51 | - Users 52 | summary: Modify User 53 | operationId: modifyUserWithId 54 | responses: 55 | '200': 56 | description: OK 57 | content: 58 | application/json: 59 | schema: 60 | $ref: '#/components/schemas/User' 61 | requestBody: 62 | content: 63 | application/json: 64 | schema: 65 | $ref: '#/components/schemas/User' 66 | delete: 67 | tags: 68 | - Users 69 | summary: Delete User 70 | operationId: deleteUserWithId 71 | responses: 72 | '204': 73 | description: No Content 74 | /jobs: 75 | post: 76 | tags: 77 | - Jobs 78 | summary: Create Job 79 | operationId: createJob 80 | responses: 81 | '201': 82 | description: Created 83 | headers: 84 | Location: 85 | schema: 86 | type: string 87 | '400': 88 | description: Bad request 89 | content: 90 | application/json: 91 | schema: 92 | $ref: '#/components/schemas/OASError' 93 | '401': 94 | description: Unauthorized 95 | content: 96 | application/json: 97 | schema: 98 | $ref: '#/components/schemas/OASError' 99 | '403': 100 | description: Forbidden 101 | content: 102 | application/problem+json: 103 | schema: 104 | $ref: '#/components/schemas/Problem' 105 | get: 106 | tags: 107 | - Jobs 108 | summary: List/Search Available Jobs 109 | operationId: listOrSearchAvailableJobs 110 | parameters: 111 | - name: start_time_before 112 | in: query 113 | description: Search jobs starting before this date and time. 114 | schema: 115 | type: string 116 | format: date-time 117 | - name: start_time_after 118 | in: query 119 | description: Search jobs starting after this date and time. 120 | schema: 121 | type: string 122 | format: date-time 123 | - name: end_time_before 124 | in: query 125 | description: Search jobs ending before this date and time. 126 | schema: 127 | type: string 128 | format: date-time 129 | - name: end_time_after 130 | in: query 131 | description: Search jobs ending after this date and time. 132 | schema: 133 | type: string 134 | format: date-time 135 | - name: activity 136 | in: query 137 | description: Performs a full-text search for the phrase entered in job activities. 138 | schema: 139 | type: string 140 | - name: pets 141 | in: query 142 | description: Searches for pets matching specific criteria. 143 | style: deepObject 144 | schema: 145 | type: object 146 | properties: 147 | age_below: 148 | type: integer 149 | description: Return only pets with this age or younger. 150 | age_above: 151 | type: integer 152 | description: Return only pets with this age or older. 153 | species: 154 | type: string 155 | description: Return only pets with this species. Provide multiple species as comma-separated values. 156 | - name: limit 157 | in: query 158 | description: The maximum number of results to return. 159 | schema: 160 | type: integer 161 | default: 20 162 | maximum: 100 163 | - name: cursor 164 | in: query 165 | description: Use the cursor from the response to access more results. 166 | schema: 167 | type: string 168 | - name: sort 169 | in: query 170 | description: | 171 | Indicate the sorting key and direction for the results. 172 | Use the field name, suffixed with ":asc" for ascending 173 | or ":desc" for descending order. 174 | Valid fields: start_time, end_time 175 | schema: 176 | type: string 177 | responses: 178 | '200': 179 | description: OK 180 | content: 181 | application/json: 182 | schema: 183 | type: object 184 | properties: 185 | items: 186 | type: array 187 | items: 188 | $ref: '#/components/schemas/Job' 189 | cursor: 190 | type: string 191 | description: Cursor for the next result page. 192 | nullable: true 193 | /jobs/{id}: 194 | parameters: 195 | - schema: 196 | type: string 197 | name: id 198 | in: path 199 | required: true 200 | get: 201 | tags: 202 | - Jobs 203 | summary: View Job 204 | operationId: viewJobWithId 205 | responses: 206 | '200': 207 | description: OK 208 | content: 209 | application/json: 210 | schema: 211 | $ref: '#/components/schemas/Job' 212 | put: 213 | tags: 214 | - Jobs 215 | summary: Modify Job 216 | operationId: modifyJobWithId 217 | responses: 218 | '200': 219 | description: OK 220 | content: 221 | application/json: 222 | schema: 223 | $ref: '#/components/schemas/Job' 224 | requestBody: 225 | content: 226 | application/json: 227 | schema: 228 | $ref: '#/components/schemas/Job' 229 | delete: 230 | tags: 231 | - Jobs 232 | summary: Delete Job 233 | operationId: deleteJobWithId 234 | responses: 235 | '204': 236 | description: No Content 237 | /jobs/{id}/job-applications: 238 | parameters: 239 | - schema: 240 | type: string 241 | name: id 242 | in: path 243 | required: true 244 | get: 245 | tags: 246 | - Jobs 247 | summary: List Applications For Job 248 | operationId: viewApplicationsForJob 249 | responses: 250 | '200': 251 | description: OK 252 | content: 253 | application/json: 254 | schema: 255 | type: object 256 | properties: 257 | items: 258 | type: array 259 | items: 260 | $ref: '#/components/schemas/JobApplication' 261 | post: 262 | tags: 263 | - Jobs 264 | summary: Create Job Application 265 | operationId: createJobApplication 266 | responses: 267 | '201': 268 | description: Created 269 | headers: 270 | Location: 271 | schema: 272 | type: string 273 | requestBody: 274 | content: 275 | application/json: 276 | schema: 277 | $ref: '#/components/schemas/JobApplication' 278 | /users/{id}/jobs: 279 | parameters: 280 | - schema: 281 | type: string 282 | name: id 283 | in: path 284 | required: true 285 | get: 286 | tags: 287 | - Users 288 | summary: List Jobs For User 289 | operationId: listJobsForUser 290 | responses: 291 | '200': 292 | description: OK 293 | content: 294 | application/json: 295 | schema: 296 | type: object 297 | properties: 298 | items: 299 | type: array 300 | items: 301 | $ref: '#/components/schemas/Job' 302 | /users/{id}/job-applications: 303 | parameters: 304 | - name: id 305 | in: path 306 | required: true 307 | schema: 308 | type: integer 309 | get: 310 | tags: 311 | - Users 312 | summary: List Applications For User 313 | operationId: viewApplicationsForUser 314 | responses: 315 | '200': 316 | description: OK 317 | content: 318 | application/json: 319 | schema: 320 | type: object 321 | properties: 322 | items: 323 | type: array 324 | items: 325 | $ref: '#/components/schemas/JobApplication' 326 | /job-applications/{id}: 327 | parameters: 328 | - schema: 329 | type: string 330 | name: id 331 | in: path 332 | required: true 333 | put: 334 | tags: 335 | - Jobs 336 | summary: Modify Job Application 337 | operationId: modifyJobApplicationWithId 338 | requestBody: 339 | description: Update the application details 340 | content: 341 | application/json: 342 | schema: 343 | $ref: '#/components/schemas/JobApplication' 344 | responses: 345 | '200': 346 | description: OK 347 | content: 348 | application/json: 349 | schema: 350 | type: array 351 | items: 352 | $ref: '#/components/schemas/JobApplication' 353 | /sessions: 354 | post: 355 | tags: 356 | - Users 357 | summary: Start Session (Login) 358 | operationId: startSession 359 | responses: 360 | '200': 361 | description: OK 362 | content: 363 | application/json: 364 | schema: 365 | $ref: '#/components/schemas/Session' 366 | requestBody: 367 | content: 368 | application/json: 369 | schema: 370 | type: object 371 | properties: 372 | email: 373 | type: string 374 | password: 375 | type: string 376 | security: [] 377 | components: 378 | schemas: 379 | User: 380 | type: object 381 | properties: 382 | id: 383 | type: integer 384 | readOnly: true 385 | email: 386 | type: string 387 | format: email 388 | password: 389 | type: string 390 | format: password 391 | writeOnly: true 392 | minLength: 8 393 | full_name: 394 | type: string 395 | minLength: 2 396 | maxLength: 50 397 | roles: 398 | type: array 399 | minItems: 1 400 | uniqueItems: true 401 | items: 402 | type: string 403 | enum: 404 | - PetOwner 405 | - PetSitter 406 | - Admin 407 | required: 408 | - email 409 | - full_name 410 | - roles 411 | Job: 412 | type: object 413 | properties: 414 | id: 415 | type: integer 416 | readOnly: true 417 | creator_user_id: 418 | type: integer 419 | readOnly: true 420 | start_time: 421 | type: string 422 | format: date-time 423 | end_time: 424 | type: string 425 | format: date-time 426 | activity: 427 | type: string 428 | minLength: 5 429 | maxLength: 500 430 | dog: 431 | allOf: 432 | - $ref: '#/components/schemas/Dog' 433 | - description: | 434 | This is deprecated, prefer to use `pets`. 435 | If both exist, `dog` will be ignored and `pets` will be used. 436 | deprecated: true 437 | pets: 438 | type: array 439 | minItems: 1 440 | maxItems: 10 441 | items: 442 | $ref: '#/components/schemas/Pet' 443 | Dog: 444 | type: object 445 | properties: 446 | species: 447 | type: string 448 | breed: 449 | type: string 450 | size: 451 | type: string 452 | required: 453 | - species 454 | Cat: 455 | type: object 456 | properties: 457 | species: 458 | type: string 459 | breed: 460 | type: string 461 | required: 462 | - species 463 | Pet: 464 | allOf: 465 | - type: object 466 | properties: 467 | name: 468 | type: string 469 | minLength: 2 470 | maxLength: 20 471 | age: 472 | type: integer 473 | minimum: 1 474 | maximum: 100 475 | - oneOf: 476 | - $ref: '#/components/schemas/Cat' 477 | - $ref: '#/components/schemas/Dog' 478 | discriminator: 479 | propertyName: species 480 | mapping: 481 | Cat: '#/components/schemas/Cat' 482 | Dog: '#/components/schemas/Dog' 483 | JobApplication: 484 | type: object 485 | properties: 486 | id: 487 | type: string 488 | readOnly: true 489 | status: 490 | type: string 491 | default: applying 492 | enum: 493 | - applying 494 | - approved 495 | - rejected 496 | user_id: 497 | type: string 498 | readOnly: true 499 | job_id: 500 | type: string 501 | readOnly: true 502 | Session: 503 | type: object 504 | properties: 505 | user_id: 506 | type: string 507 | auth_header: 508 | type: string 509 | OASError: 510 | type: object 511 | properties: 512 | message: 513 | type: string 514 | description: Human-readable error message 515 | errors: 516 | type: array 517 | items: 518 | type: object 519 | properties: 520 | path: 521 | type: string 522 | description: For input validation errors, identifies where in the JSON request body the error occured 523 | message: 524 | type: string 525 | description: Human-readable error message 526 | errorCode: 527 | type: string 528 | description: Code indicating error type 529 | Problem: 530 | type: object 531 | properties: 532 | type: 533 | type: string 534 | description: URI indicating error type 535 | title: 536 | type: string 537 | description: Human-readable error title 538 | status: 539 | type: integer 540 | description: HTTP status code 541 | detail: 542 | type: string 543 | description: Human-readable error details 544 | instance: 545 | type: string 546 | description: URI indicating error instance 547 | securitySchemes: 548 | SessionToken: 549 | type: apiKey 550 | in: header 551 | name: Authorization 552 | security: 553 | - SessionToken: [] 554 | -------------------------------------------------------------------------------- /core-concept/openapi.yml: -------------------------------------------------------------------------------- 1 | openapi: 3.0.3 2 | info: 3 | title: UserAccount API 4 | description: For users 5 | version: 1.0.0 6 | tags: 7 | - name: User 8 | description: User related operations 9 | servers: 10 | - url: https://example.com 11 | paths: 12 | /users/{id}: 13 | put: 14 | summary: Modify user 15 | description: | 16 | Modify the user and return `updated_at`. 17 | 18 | Needs **Authentication**! 19 | operationId: modifyUser 20 | tags: 21 | - User 22 | security: 23 | - MyToken: [] 24 | parameters: 25 | - name: id 26 | in: path 27 | required: true 28 | schema: 29 | type: string 30 | - name: role 31 | in: query 32 | schema: 33 | type: string 34 | enum: 35 | - admin 36 | - member 37 | default: member 38 | 39 | requestBody: 40 | content: 41 | application/json: 42 | schema: 43 | oneOf: 44 | - $ref: '#/components/schemas/Employee' 45 | - $ref: '#/components/schemas/Customer' 46 | responses: 47 | '200': 48 | description: Updated user 49 | content: 50 | application/json: 51 | schema: 52 | $ref: '#/components/schemas/User' 53 | '403': 54 | description: Forbidden 55 | content: 56 | application/problem+json: 57 | schema: 58 | $ref: '#/components/schemas/Error' 59 | components: 60 | securitySchemes: 61 | MyToken: 62 | type: apiKey 63 | in: header 64 | name: Authorization 65 | schemas: 66 | User: 67 | type: object 68 | required: [id, name] 69 | properties: 70 | id: 71 | type: string 72 | readOnly: true 73 | name: 74 | type: string 75 | password: 76 | type: string 77 | format: password 78 | writeOnly: true 79 | Employee: 80 | allOf: 81 | - $ref: '#/components/schemas/User' 82 | - type: object 83 | required: 84 | - employee_id 85 | properties: 86 | employee_id: 87 | type: string 88 | Customer: 89 | allOf: 90 | - $ref: '#/components/schemas/User' 91 | - type: object 92 | properties: 93 | sales_rep_id: 94 | type: string 95 | Error: 96 | type: object 97 | properties: 98 | title: 99 | type: string 100 | description: Error title 101 | --------------------------------------------------------------------------------