{
  "openapi": "3.1.0",
  "info": {
    "title": "Cheese Store",
    "version": "2.0.0",
    "description": "This is a fictional API contract used to demonstrate documentation generated by [Sourcey](https://github.com/sourcey/sourcey). The Cheese Store service, accounts, keys, and endpoints are examples; there is no live cheese-ordering service behind this reference.\n\nThe Cheese Store API is organized around [REST](https://en.wikipedia.org/wiki/Representational_state_transfer). It uses resource-oriented URLs, standard HTTP methods, and returns JSON responses. All requests are authenticated using an API key or OAuth2 token.\n\n## Getting Started\n\nRead the endpoints and schemas as examples. If you adapt this contract for a real API, issue your own credentials and send them in the `X-API-Key` header.\n\n## Rate Limiting\n\n| Plan       | Requests/hour | Burst |\n|------------|---------------|-------|\n| Free       | 100           | 10    |\n| Pro        | 10,000        | 100   |\n| Enterprise | Unlimited     | 1,000 |\n\nWhen you exceed the rate limit, the API returns `429 Too Many Requests` with a `Retry-After` header.\n\n## Pagination\n\nList endpoints return paginated results. Use `cursor` and `limit` query parameters:\n\n```json\n{\n  \"items\": [...],\n  \"nextCursor\": \"eyJpZCI6NDJ9\",\n  \"hasMore\": true\n}\n```\n",
    "license": {
      "name": "Apache 2.0",
      "url": "http://www.apache.org/licenses/LICENSE-2.0.html",
      "identifier": "Apache-2.0"
    }
  },
  "servers": [
    {
      "url": "https://cheese.example.com/v2",
      "description": "Example production URL (not a live service)"
    },
    {
      "url": "https://sandbox.cheese.example.com/v2",
      "description": "Example sandbox URL (not a live service)"
    },
    {
      "url": "http://localhost:3000/v2",
      "description": "Example local development URL"
    }
  ],
  "tags": [
    {
      "name": "Cheese",
      "description": "Cheese endpoints provide access to information and operations relating to the cheeses available in the store.\n\nCheeses can be filtered by status, tags, and category. Each cheese has a unique ID, name, category, and availability status.\n",
      "externalDocs": {
        "description": "Cheese Wiki",
        "url": "http://cheese.example.com/wiki/cheese"
      }
    },
    {
      "name": "Store",
      "description": "Store endpoints provide access to cheese store orders and inventory management. Orders track the purchase lifecycle from placement through delivery."
    },
    {
      "name": "Customer",
      "description": "Customer endpoints handle account creation, authentication, and profile management.\n\nCustomer accounts support OAuth2 login and API key authentication.\n",
      "externalDocs": {
        "description": "Customer Portal",
        "url": "http://cheese.example.com/portal"
      }
    }
  ],
  "paths": {
    "/cheeses": {
      "get": {
        "tags": [
          "Cheese"
        ],
        "summary": "List all cheeses",
        "description": "Returns a paginated list of cheeses in the store. Results can be filtered by status and sorted by name or creation date.\n\nThe response includes cursor-based pagination. Use the `nextCursor` value from the response as the `cursor` parameter in subsequent requests.\n",
        "operationId": "listCheeses",
        "parameters": [
          {
            "$ref": "#/components/parameters/CursorParam"
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Maximum number of cheeses to return",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Filter by availability status",
            "schema": {
              "type": "string",
              "enum": [
                "available",
                "pending",
                "sold"
              ]
            }
          },
          {
            "name": "sort",
            "in": "query",
            "description": "Sort order for results",
            "schema": {
              "type": "string",
              "enum": [
                "name",
                "-name",
                "createdAt",
                "-createdAt"
              ],
              "default": "name"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A paginated list of cheeses",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CheeseList"
                }
              }
            },
            "headers": {
              "X-Total-Count": {
                "description": "Total number of cheeses matching the filter",
                "schema": {
                  "type": "integer"
                }
              },
              "Link": {
                "description": "Pagination links (RFC 8288)",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "security": [
          {
            "api_key": []
          },
          {
            "cheesy_oauth": [
              "read:cheeses"
            ]
          }
        ]
      },
      "post": {
        "tags": [
          "Cheese"
        ],
        "summary": "Add a new cheese",
        "description": "Add a new cheese to the store inventory. The cheese name must be unique within its category.",
        "operationId": "addCheese",
        "requestBody": {
          "description": "Cheese object to add to the store",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CheeseInput"
              },
              "example": {
                "name": "Gorgonzola",
                "category": {
                  "name": "Italian Cheese"
                },
                "status": "available",
                "photoUrls": [
                  "https://wannabechef.com/gorgonzola.jpg"
                ],
                "tags": [
                  {
                    "name": "blue"
                  },
                  {
                    "name": "italian"
                  },
                  {
                    "name": "creamy"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Cheese created successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Cheese"
                }
              }
            },
            "headers": {
              "Location": {
                "description": "URL of the newly created cheese",
                "schema": {
                  "type": "string",
                  "format": "uri"
                }
              }
            }
          },
          "409": {
            "description": "A cheese with this name already exists in the category",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          }
        },
        "security": [
          {
            "cheesy_oauth": [
              "write:cheeses"
            ]
          }
        ]
      },
      "put": {
        "tags": [
          "Cheese"
        ],
        "summary": "Update an existing cheese",
        "description": "Replace an existing cheese with updated data. The cheese ID in the body must match an existing cheese.",
        "operationId": "updateCheese",
        "requestBody": {
          "description": "Cheese object with updated fields",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Cheese"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Cheese updated successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Cheese"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          }
        },
        "security": [
          {
            "cheesy_oauth": [
              "write:cheeses"
            ]
          }
        ]
      }
    },
    "/cheeses/findByStatus": {
      "get": {
        "tags": [
          "Cheese"
        ],
        "summary": "Find cheeses by status",
        "description": "Multiple status values can be provided as comma-separated strings. Returns all cheeses matching any of the given statuses.",
        "operationId": "findCheesesByStatus",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "description": "Status values to filter by",
            "required": true,
            "explode": true,
            "schema": {
              "type": "array",
              "items": {
                "type": "string",
                "enum": [
                  "available",
                  "pending",
                  "sold"
                ],
                "default": "available"
              }
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Matching cheeses",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Cheese"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid status value provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "cheesy_oauth": [
              "read:cheeses"
            ]
          }
        ]
      }
    },
    "/cheeses/findByTags": {
      "get": {
        "tags": [
          "Cheese"
        ],
        "summary": "Find cheeses by tags",
        "description": "Multiple tags can be provided as comma-separated strings (e.g. `?tags=blue,italian,aged`).\n\n**Deprecated:** Use `GET /cheeses?tags=blue,italian` query parameter instead.\n",
        "operationId": "findCheesesByTags",
        "deprecated": true,
        "parameters": [
          {
            "name": "tags",
            "in": "query",
            "description": "Tags to filter by",
            "required": true,
            "explode": true,
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Matching cheeses",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Cheese"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid tag value",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "cheesy_oauth": [
              "read:cheeses"
            ]
          }
        ]
      }
    },
    "/cheeses/{cheeseId}": {
      "parameters": [
        {
          "name": "cheeseId",
          "in": "path",
          "description": "Unique identifier for the cheese",
          "required": true,
          "schema": {
            "type": "integer",
            "format": "int64",
            "minimum": 1
          },
          "example": 42
        }
      ],
      "get": {
        "tags": [
          "Cheese"
        ],
        "summary": "Get cheese by ID",
        "description": "Returns detailed information about a specific cheese, including its category, tags, and current availability status.",
        "operationId": "getCheeseById",
        "responses": {
          "200": {
            "description": "Cheese details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Cheese"
                },
                "example": {
                  "id": 42,
                  "name": "Gorgonzola",
                  "category": {
                    "id": 1,
                    "name": "Italian Cheese"
                  },
                  "status": "available",
                  "photoUrls": [
                    "https://wannabechef.com/gorgonzola.jpg"
                  ],
                  "tags": [
                    {
                      "id": 1,
                      "name": "blue"
                    },
                    {
                      "id": 2,
                      "name": "italian"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      },
      "post": {
        "tags": [
          "Cheese"
        ],
        "summary": "Update cheese with form data",
        "description": "Updates specific fields of a cheese using form data. Only provided fields are updated.",
        "operationId": "updateCheeseWithForm",
        "parameters": [
          {
            "name": "name",
            "in": "query",
            "description": "Updated name of the cheese",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Updated status of the cheese",
            "schema": {
              "type": "string",
              "enum": [
                "available",
                "pending",
                "sold"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Cheese updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Cheese"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          }
        },
        "security": [
          {
            "cheesy_oauth": [
              "write:cheeses"
            ]
          }
        ]
      },
      "delete": {
        "tags": [
          "Cheese"
        ],
        "summary": "Delete a cheese",
        "description": "Permanently removes a cheese from the store. This action cannot be undone. Any pending orders for this cheese will be cancelled.",
        "operationId": "deleteCheese",
        "parameters": [
          {
            "name": "X-Confirm-Delete",
            "in": "header",
            "description": "Must be set to `true` to confirm deletion",
            "required": true,
            "schema": {
              "type": "boolean",
              "const": true
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Cheese deleted successfully"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "Cheese has active orders and cannot be deleted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "cheesy_oauth": [
              "write:cheeses"
            ]
          }
        ]
      }
    },
    "/cheeses/{cheeseId}/uploadImage": {
      "post": {
        "tags": [
          "Cheese"
        ],
        "summary": "Upload a cheese image",
        "description": "Upload a photo of the cheese. Supports JPEG, PNG, and WebP formats. Maximum file size is 10MB.",
        "operationId": "uploadCheeseImage",
        "parameters": [
          {
            "name": "cheeseId",
            "in": "path",
            "description": "ID of cheese to upload image for",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "file"
                ],
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary",
                    "description": "Image file (JPEG, PNG, or WebP, max 10MB)"
                  },
                  "caption": {
                    "type": "string",
                    "maxLength": 200,
                    "description": "Optional caption for the image"
                  },
                  "isPrimary": {
                    "type": "boolean",
                    "default": false,
                    "description": "Set as the primary display image"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Image uploaded successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "imageUrl": {
                      "type": "string",
                      "format": "uri"
                    },
                    "thumbnailUrl": {
                      "type": "string",
                      "format": "uri"
                    },
                    "size": {
                      "type": "integer",
                      "description": "File size in bytes"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "File too large (max 10MB)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported media type",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "cheesy_oauth": [
              "write:cheeses"
            ]
          }
        ]
      }
    },
    "/store/inventory": {
      "get": {
        "tags": [
          "Store"
        ],
        "summary": "Get store inventory",
        "description": "Returns a map of cheese status codes to quantities, representing the current inventory levels.",
        "operationId": "getInventory",
        "responses": {
          "200": {
            "description": "Inventory counts by status",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "type": "integer",
                    "format": "int32"
                  }
                },
                "example": {
                  "available": 256,
                  "pending": 34,
                  "sold": 1089
                }
              }
            }
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/store/order": {
      "post": {
        "tags": [
          "Store"
        ],
        "summary": "Place a cheese order",
        "description": "Place an order to purchase cheese from the store. The cheese must be in `available` status.\n\nOrders are processed asynchronously. Use the returned order ID to check status via `GET /store/order/{orderId}`.\n",
        "operationId": "placeOrder",
        "requestBody": {
          "description": "Order details",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OrderInput"
              },
              "example": {
                "items": [
                  {
                    "cheeseId": 42,
                    "quantity": 3
                  },
                  {
                    "cheeseId": 17,
                    "quantity": 1
                  }
                ],
                "shippingAddress": {
                  "street": "123 Cheese Lane",
                  "city": "Cheddarville",
                  "state": "WI",
                  "zipCode": "53001",
                  "country": "US"
                },
                "notes": "Please wrap each wheel separately"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Order placed successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Order"
                }
              }
            },
            "headers": {
              "Location": {
                "description": "URL of the created order",
                "schema": {
                  "type": "string",
                  "format": "uri"
                }
              }
            }
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          }
        },
        "security": [
          {
            "cheesy_oauth": [
              "write:orders"
            ]
          }
        ]
      }
    },
    "/store/order/{orderId}": {
      "parameters": [
        {
          "name": "orderId",
          "in": "path",
          "description": "ID of the order",
          "required": true,
          "schema": {
            "type": "integer",
            "format": "int64",
            "minimum": 1
          },
          "example": 1001
        }
      ],
      "get": {
        "tags": [
          "Store"
        ],
        "summary": "Get order by ID",
        "description": "Retrieve details of a specific order. For testing, use order IDs between 1 and 10.",
        "operationId": "getOrderById",
        "responses": {
          "200": {
            "description": "Order details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Order"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      },
      "delete": {
        "tags": [
          "Store"
        ],
        "summary": "Cancel an order",
        "description": "Cancel a pending order. Orders that have already been shipped cannot be cancelled.",
        "operationId": "deleteOrder",
        "responses": {
          "204": {
            "description": "Order cancelled successfully"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "Order has already been shipped",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "cheesy_oauth": [
              "write:orders"
            ]
          }
        ]
      }
    },
    "/customer": {
      "post": {
        "tags": [
          "Customer"
        ],
        "summary": "Create a customer account",
        "description": "Register a new customer account. The username and email must be unique.",
        "operationId": "createCustomer",
        "requestBody": {
          "description": "Customer registration details",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CustomerInput"
              },
              "example": {
                "username": "gordo",
                "firstName": "Alotta",
                "lastName": "Cheese",
                "email": "love@cheese.com",
                "password": "secret123!",
                "phone": "+3344556677"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Customer account created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Customer"
                }
              }
            }
          },
          "409": {
            "description": "Username or email already exists",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          }
        }
      }
    },
    "/customer/createMultiple": {
      "post": {
        "tags": [
          "Customer"
        ],
        "summary": "Create multiple customers",
        "description": "Create a batch of customer accounts from an array. Each customer is validated independently - partial success is possible.\n\nReturns the created customers and any validation errors:\n\n```json\n{\n  \"created\": [...],\n  \"errors\": [\n    { \"index\": 2, \"message\": \"Email already exists\" }\n  ]\n}\n```\n",
        "operationId": "createMultipleCustomers",
        "requestBody": {
          "description": "Array of customer objects to create",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/CustomerInput"
                },
                "minItems": 1,
                "maxItems": 100
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Batch creation result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "created": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Customer"
                      }
                    },
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "index": {
                            "type": "integer"
                          },
                          "message": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          }
        }
      }
    },
    "/customer/login": {
      "post": {
        "tags": [
          "Customer"
        ],
        "summary": "Customer login",
        "description": "Authenticate a customer and receive a session token. The token expires after 24 hours.",
        "operationId": "loginCustomer",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "username",
                  "password"
                ],
                "properties": {
                  "username": {
                    "type": "string",
                    "description": "The customer's username"
                  },
                  "password": {
                    "type": "string",
                    "format": "password",
                    "description": "The customer's password"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Login successful",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "token": {
                      "type": "string",
                      "description": "JWT session token"
                    },
                    "expiresAt": {
                      "type": "string",
                      "format": "date-time",
                      "description": "Token expiration time (UTC)"
                    }
                  }
                }
              }
            },
            "headers": {
              "X-Rate-Limit": {
                "description": "Requests per hour allowed for this customer",
                "schema": {
                  "type": "integer",
                  "format": "int32"
                }
              },
              "X-Expires-After": {
                "description": "Token expiration date-time (UTC)",
                "schema": {
                  "type": "string",
                  "format": "date-time"
                }
              }
            }
          },
          "401": {
            "description": "Invalid username or password",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/customer/logout": {
      "get": {
        "tags": [
          "Customer"
        ],
        "summary": "Customer logout",
        "description": "End the current customer session and invalidate the session token.",
        "operationId": "logoutCustomer",
        "responses": {
          "204": {
            "description": "Logout successful"
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/customer/{username}": {
      "parameters": [
        {
          "name": "username",
          "in": "path",
          "description": "The customer's username",
          "required": true,
          "schema": {
            "type": "string",
            "minLength": 3,
            "maxLength": 30,
            "pattern": "^[a-zA-Z0-9_-]+$"
          },
          "example": "gordo"
        }
      ],
      "get": {
        "tags": [
          "Customer"
        ],
        "summary": "Get customer by username",
        "description": "Retrieve a customer's profile by their username.",
        "operationId": "getCustomerByName",
        "responses": {
          "200": {
            "description": "Customer profile",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Customer"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        },
        "security": [
          {
            "api_key": []
          },
          {
            "bearer_auth": []
          }
        ]
      },
      "put": {
        "tags": [
          "Customer"
        ],
        "summary": "Update customer profile",
        "description": "Update a customer's profile. Can only be performed by the authenticated customer.",
        "operationId": "updateCustomer",
        "requestBody": {
          "description": "Updated customer fields",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CustomerInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Customer updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Customer"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      },
      "delete": {
        "tags": [
          "Customer"
        ],
        "summary": "Delete customer account",
        "description": "Permanently delete a customer account and all associated data. This action cannot be undone.",
        "operationId": "deleteCustomer",
        "responses": {
          "204": {
            "description": "Customer deleted"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    }
  },
  "webhooks": {
    "orderStatusChanged": {
      "post": {
        "summary": "Order status changed",
        "description": "Fired when an order transitions between statuses (e.g. `placed` -> `approved` -> `shipped` -> `delivered`).\n\nConfigure your webhook URL in the developer dashboard under **Settings > Webhooks**.\n",
        "operationId": "onOrderStatusChanged",
        "tags": [
          "Store"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "event",
                  "orderId",
                  "oldStatus",
                  "newStatus",
                  "timestamp"
                ],
                "properties": {
                  "event": {
                    "type": "string",
                    "const": "order.status.changed"
                  },
                  "orderId": {
                    "type": "integer",
                    "format": "int64"
                  },
                  "oldStatus": {
                    "type": "string",
                    "enum": [
                      "placed",
                      "approved",
                      "shipped",
                      "delivered",
                      "cancelled"
                    ]
                  },
                  "newStatus": {
                    "type": "string",
                    "enum": [
                      "placed",
                      "approved",
                      "shipped",
                      "delivered",
                      "cancelled"
                    ]
                  },
                  "timestamp": {
                    "type": "string",
                    "format": "date-time"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Webhook received successfully"
          }
        }
      }
    },
    "newCheeseAdded": {
      "post": {
        "summary": "New cheese added to store",
        "description": "Fired when a new cheese is added to the store inventory. Useful for catalog sync integrations.",
        "operationId": "onNewCheeseAdded",
        "tags": [
          "Cheese"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "event",
                  "cheese"
                ],
                "properties": {
                  "event": {
                    "type": "string",
                    "const": "cheese.created"
                  },
                  "cheese": {
                    "$ref": "#/components/schemas/Cheese"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Webhook received successfully"
          }
        }
      }
    }
  },
  "components": {
    "parameters": {
      "CursorParam": {
        "name": "cursor",
        "in": "query",
        "description": "Pagination cursor from a previous response",
        "schema": {
          "type": "string"
        }
      }
    },
    "responses": {
      "NotFound": {
        "description": "The requested resource was not found",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "code": 404,
              "type": "Not found",
              "message": "Your cheese has already been eaten"
            }
          }
        }
      },
      "ValidationError": {
        "description": "The request body failed validation",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ValidationError"
            },
            "example": {
              "code": 422,
              "type": "Validation error",
              "message": "Your cheese is not mouldy enough",
              "errors": [
                {
                  "field": "name",
                  "message": "Name is required"
                },
                {
                  "field": "status",
                  "message": "Must be one of available, pending, sold"
                }
              ]
            }
          }
        }
      },
      "RateLimited": {
        "description": "Rate limit exceeded",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "code": 429,
              "type": "Rate limited",
              "message": "Too many requests, please try again later"
            }
          }
        },
        "headers": {
          "Retry-After": {
            "description": "Seconds to wait before retrying",
            "schema": {
              "type": "integer"
            }
          },
          "X-Rate-Limit": {
            "description": "Your rate limit (requests per hour)",
            "schema": {
              "type": "integer"
            }
          },
          "X-Rate-Limit-Remaining": {
            "description": "Remaining requests in the current window",
            "schema": {
              "type": "integer"
            }
          }
        }
      }
    },
    "schemas": {
      "Cheese": {
        "type": "object",
        "required": [
          "id",
          "name",
          "status"
        ],
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64",
            "description": "Unique identifier",
            "example": 42
          },
          "name": {
            "type": "string",
            "description": "Name of the cheese",
            "minLength": 1,
            "maxLength": 100,
            "example": "Gorgonzola"
          },
          "category": {
            "$ref": "#/components/schemas/Category"
          },
          "photoUrls": {
            "type": "array",
            "description": "URLs of cheese photos",
            "items": {
              "type": "string",
              "format": "uri"
            },
            "example": [
              "https://wannabechef.com/gorgonzola.jpg"
            ]
          },
          "tags": {
            "type": "array",
            "description": "Classification tags",
            "items": {
              "$ref": "#/components/schemas/Tag"
            }
          },
          "status": {
            "type": "string",
            "description": "Availability status in the store",
            "enum": [
              "available",
              "pending",
              "sold"
            ],
            "example": "available"
          },
          "origin": {
            "type": [
              "string",
              "null"
            ],
            "description": "Country of origin (null if unknown)",
            "example": "Italy"
          },
          "pricePerKg": {
            "type": "number",
            "format": "float",
            "description": "Price per kilogram in USD",
            "minimum": 0,
            "exclusiveMinimum": true,
            "example": 28.5
          },
          "ageMonths": {
            "type": "integer",
            "description": "Aging period in months",
            "minimum": 0,
            "maximum": 120,
            "example": 12
          },
          "organic": {
            "type": "boolean",
            "default": false,
            "description": "Whether the cheese is certified organic"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the cheese was added to the store"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the cheese was last updated"
          }
        }
      },
      "CheeseInput": {
        "type": "object",
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "category": {
            "type": "object",
            "properties": {
              "name": {
                "type": "string"
              }
            }
          },
          "photoUrls": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uri"
            }
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "name": {
                  "type": "string"
                }
              }
            }
          },
          "status": {
            "type": "string",
            "enum": [
              "available",
              "pending",
              "sold"
            ],
            "default": "available"
          },
          "origin": {
            "type": [
              "string",
              "null"
            ]
          },
          "pricePerKg": {
            "type": "number",
            "format": "float",
            "minimum": 0,
            "exclusiveMinimum": true
          },
          "ageMonths": {
            "type": "integer",
            "minimum": 0,
            "maximum": 120
          },
          "organic": {
            "type": "boolean",
            "default": false
          }
        }
      },
      "CheeseList": {
        "type": "object",
        "description": "Paginated list of cheeses",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Cheese"
            }
          },
          "nextCursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Cursor for the next page (null if no more results)"
          },
          "hasMore": {
            "type": "boolean",
            "description": "Whether there are more results"
          },
          "total": {
            "type": "integer",
            "description": "Total number of matching cheeses"
          }
        }
      },
      "Category": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64",
            "example": 1
          },
          "name": {
            "type": "string",
            "example": "Italian Cheese"
          }
        }
      },
      "Tag": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64",
            "example": 1
          },
          "name": {
            "type": "string",
            "example": "blue"
          }
        }
      },
      "Order": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64",
            "example": 1001
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OrderItem"
            }
          },
          "shippingAddress": {
            "$ref": "#/components/schemas/Address"
          },
          "status": {
            "type": "string",
            "description": "Order lifecycle status",
            "enum": [
              "placed",
              "approved",
              "shipped",
              "delivered",
              "cancelled"
            ],
            "example": "placed"
          },
          "notes": {
            "type": [
              "string",
              "null"
            ],
            "description": "Special instructions for the order"
          },
          "total": {
            "type": "number",
            "format": "float",
            "description": "Order total in USD",
            "example": 114.5
          },
          "shipDate": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Estimated ship date (null if not yet scheduled)"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "example": {
          "id": 1001,
          "items": [
            {
              "cheeseId": 42,
              "cheeseName": "Gorgonzola",
              "quantity": 3,
              "pricePerKg": 28.5
            },
            {
              "cheeseId": 17,
              "cheeseName": "Brie",
              "quantity": 1,
              "pricePerKg": 22
            }
          ],
          "shippingAddress": {
            "street": "123 Cheese Lane",
            "city": "Cheddarville",
            "state": "WI",
            "zipCode": "53001",
            "country": "US"
          },
          "status": "placed",
          "notes": "Please wrap each wheel separately",
          "total": 114.5,
          "shipDate": null,
          "createdAt": "2026-03-10T14:30:00Z",
          "updatedAt": "2026-03-10T14:30:00Z"
        }
      },
      "OrderInput": {
        "type": "object",
        "required": [
          "items",
          "shippingAddress"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "cheeseId",
                "quantity"
              ],
              "properties": {
                "cheeseId": {
                  "type": "integer",
                  "format": "int64"
                },
                "quantity": {
                  "type": "integer",
                  "minimum": 1,
                  "maximum": 100
                }
              }
            },
            "minItems": 1,
            "maxItems": 50
          },
          "shippingAddress": {
            "$ref": "#/components/schemas/Address"
          },
          "notes": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 500
          }
        }
      },
      "OrderItem": {
        "type": "object",
        "properties": {
          "cheeseId": {
            "type": "integer",
            "format": "int64"
          },
          "cheeseName": {
            "type": "string"
          },
          "quantity": {
            "type": "integer",
            "minimum": 1
          },
          "pricePerKg": {
            "type": "number",
            "format": "float"
          }
        }
      },
      "Address": {
        "type": "object",
        "required": [
          "street",
          "city",
          "country"
        ],
        "properties": {
          "street": {
            "type": "string",
            "example": "123 Cheese Lane"
          },
          "city": {
            "type": "string",
            "example": "Cheddarville"
          },
          "state": {
            "type": [
              "string",
              "null"
            ],
            "example": "WI"
          },
          "zipCode": {
            "type": "string",
            "pattern": "^\\d{5}(-\\d{4})?$",
            "example": "53001"
          },
          "country": {
            "type": "string",
            "minLength": 2,
            "maxLength": 2,
            "description": "ISO 3166-1 alpha-2 country code",
            "example": "US"
          }
        }
      },
      "Customer": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64",
            "example": 1
          },
          "username": {
            "type": "string",
            "example": "gordo"
          },
          "firstName": {
            "type": "string",
            "description": "Customer first name",
            "example": "Alotta"
          },
          "lastName": {
            "type": "string",
            "description": "Customer last name",
            "example": "Cheese"
          },
          "email": {
            "type": "string",
            "format": "email",
            "example": "love@cheese.com"
          },
          "phone": {
            "type": [
              "string",
              "null"
            ],
            "example": "+3344556677"
          },
          "customerStatus": {
            "type": "string",
            "description": "Customer tier based on purchase volume",
            "enum": [
              "bronze",
              "silver",
              "gold",
              "platinum"
            ],
            "example": "gold"
          },
          "favouriteCheese": {
            "description": "The customer's favourite cheese (by reference or by name)",
            "oneOf": [
              {
                "$ref": "#/components/schemas/Cheese"
              },
              {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  }
                },
                "required": [
                  "name"
                ]
              }
            ]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "CustomerInput": {
        "type": "object",
        "required": [
          "username",
          "email",
          "password"
        ],
        "properties": {
          "username": {
            "type": "string",
            "minLength": 3,
            "maxLength": 30,
            "pattern": "^[a-zA-Z0-9_-]+$"
          },
          "firstName": {
            "type": "string",
            "maxLength": 50
          },
          "lastName": {
            "type": "string",
            "maxLength": 50
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "password": {
            "type": "string",
            "format": "password",
            "minLength": 8,
            "maxLength": 128
          },
          "phone": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "Error": {
        "type": "object",
        "required": [
          "code",
          "message"
        ],
        "properties": {
          "code": {
            "type": "integer",
            "format": "int32",
            "example": 404
          },
          "type": {
            "type": "string",
            "example": "Not found"
          },
          "message": {
            "type": "string",
            "example": "Your cheese has already been eaten"
          }
        }
      },
      "ValidationError": {
        "type": "object",
        "properties": {
          "code": {
            "type": "integer",
            "format": "int32",
            "example": 422
          },
          "type": {
            "type": "string",
            "example": "Validation error"
          },
          "message": {
            "type": "string",
            "example": "Your cheese is not mouldy enough"
          },
          "errors": {
            "type": "array",
            "description": "Individual field validation errors",
            "items": {
              "type": "object",
              "properties": {
                "field": {
                  "type": "string",
                  "description": "The field that failed validation"
                },
                "message": {
                  "type": "string",
                  "description": "Human-readable error message"
                }
              }
            }
          }
        }
      }
    },
    "securitySchemes": {
      "api_key": {
        "type": "apiKey",
        "name": "X-API-Key",
        "in": "header",
        "description": "API key authentication. Include your API key in the `X-API-Key` header.\n\nThis is an example scheme. Supply credentials from your own service when adapting this contract.\n"
      },
      "cheesy_oauth": {
        "type": "oauth2",
        "description": "OAuth2 authentication for full API access",
        "flows": {
          "implicit": {
            "authorizationUrl": "https://cheese.example.com/oauth/authorize",
            "scopes": {
              "read:cheeses": "Read cheese data",
              "write:cheeses": "Create and update cheeses",
              "read:orders": "View order history",
              "write:orders": "Place and manage orders"
            }
          },
          "authorizationCode": {
            "authorizationUrl": "https://cheese.example.com/oauth/authorize",
            "tokenUrl": "https://cheese.example.com/oauth/token",
            "scopes": {
              "read:cheeses": "Read cheese data",
              "write:cheeses": "Create and update cheeses",
              "read:orders": "View order history",
              "write:orders": "Place and manage orders"
            }
          }
        }
      },
      "bearer_auth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "JWT token obtained from the `/customer/login` endpoint"
      }
    }
  }
}
