openapi: 3.2.0
info:
  title: Redocly Cafe
  description: >
    Demo API for cafe operators (not customers) to manage menus, orders, and
    revenue.

    Create API credentials and try it yourself in a realistic OpenAPI workflow.
  version: 1.0.0
  contact:
    email: team@redocly.com
    url: https://redocly.com/contact-us/
  license:
    name: MIT
    url: https://opensource.org/licenses/MIT
  termsOfService: https://redocly.com/subscription-agreement
servers:
  - url: https://api.cafe.redocly.com
    description: Live server.
tags:
  - name: Authorization
    description: Create a client to demo the API.
  - name: Products
    description: Operations related to products.
  - name: Orders
    description: Order management operations.
  - name: Statistics
    description: Statistics operations.
paths:
  /menu:
    get:
      tags:
        - Products
      summary: List all menu items
      description: >-
        Retrieve a collection of menu items with optional filtering and
        pagination.
      operationId: listMenuItems
      security: []
      parameters:
        - $ref: '#/components/parameters/After'
        - $ref: '#/components/parameters/Before'
        - $ref: '#/components/parameters/Sort'
          description: >-
            Sorts the collection by a single field. Prefix with `-` for
            descending order

            (for example, `-price`); omit the prefix for ascending order
            (`price`).


            **Sortable fields:** `name`, `price`, `createdAt`, `updatedAt`, `id`
          example: '-price'
        - $ref: '#/components/parameters/Filter'
          description: >-
            Filters the collection items using space-separated `field:value`
            pairs.


            **Filterable fields:** `name`, `category`, `price`, `createdAt`,
            `id`


            **Format:** `field1:value1 field2:value2`


            **Supported operators:**

            - `field:value` - Exact match

            - `field:value1,value2` - Match any of the comma-separated values
            (OR)

            - Time ranges (on `createdAt`): Use `30d` (30 days), `7d` (7 days),
            `1h` (1 hour), etc.


            **Examples:**

            - `category:beverage` - Filter by a single category.

            - `category:beverage,dessert` - Filter by multiple categories.

            - `createdAt:7d` - Menu items created in the last 7 days.

            - `name:Latte` - Filter by name.

            - `category:beverage price:400` - Combine multiple filters.
          example: category:beverage
        - $ref: '#/components/parameters/Search'
          description: >-
            Performs a case-insensitive text search across the searchable
            fields, returning

            items where any of them contain the search term as a substring.


            **Searchable fields:** `name`, `photoTextDescription`
          example: Latte
        - $ref: '#/components/parameters/Limit'
      responses:
        '200':
          description: Successful operation.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MenuItemList'
        '400':
          $ref: '#/components/responses/BadRequest'
        '500':
          $ref: '#/components/responses/InternalServerError'
    post:
      tags:
        - Products
      summary: Create menu item
      description: Create a new menu item.
      operationId: createMenuItem
      security:
        - OAuth2:
            - menu:write
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/MenuItem'
            examples:
              Beverage:
                summary: Create a beverage
                value:
                  name: Cappuccino
                  price: 4500
                  category: beverage
                  volume: 250
                  containsCaffeine: true
                  photoTextDescription: A hot cappuccino in a white ceramic cup.
              Dessert:
                summary: Create a dessert
                value:
                  name: Chocolate-Brownie
                  price: 3500
                  category: dessert
                  calories: 420
                  photoTextDescription: A rich chocolate brownie square dusted with cocoa.
      responses:
        '201':
          description: Menu item created successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MenuItem'
              examples:
                MenuItemResponse:
                  value:
                    id: prd_01khr487f7qm7p44xn427m43vb
                    object: menuItem
                    name: coffee
                    price: 4000
                    category: beverage
                    createdAt: '2026-02-18T10:20:38.228Z'
                    updatedAt: '2026-02-18T10:20:38.228Z'
                    volume: 600
                    containsCaffeine: false
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '409':
          $ref: '#/components/responses/Conflict'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /menu/{menuItemId}:
    parameters:
      - $ref: '#/components/parameters/MenuItemId'
    delete:
      tags:
        - Products
      summary: Delete a menu item
      description: Delete an existing menu item.
      operationId: deleteMenuItem
      security:
        - OAuth2:
            - menu:write
      responses:
        '204':
          description: Menu item deleted successfully.
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /menu-item-images/{menuItemId}:
    parameters:
      - $ref: '#/components/parameters/MenuItemId'
    get:
      operationId: getMenuItemPhoto
      summary: Retrieve a menu item photo
      description: Retrieve the product photo image for a specific menu item.
      security: []
      tags:
        - Products
      parameters:
        - $ref: '#/components/parameters/PhotoSize'
      responses:
        '200':
          description: Menu item photo retrieved successfully.
          content:
            image/png:
              schema:
                type: string
                format: binary
            text/plain:
              schema:
                description: Alternative image text.
                type: string
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /orders:
    get:
      tags:
        - Orders
      summary: List all orders
      description: Retrieve a collection of orders with optional filtering and pagination.
      operationId: listOrders
      security:
        - OAuth2:
            - orders:read
      parameters:
        - $ref: '#/components/parameters/Filter'
          description: >-
            Filters the collection items using space-separated `field:value`
            pairs.


            **Filterable fields:** `customerName`, `status`, `totalPrice`,
            `createdAt`, `id`


            **Format:** `field1:value1 field2:value2`


            **Supported operators:**

            - `field:value` - Exact match

            - `field:value1,value2` - Match any of the comma-separated values
            (OR)

            - Time ranges (on `createdAt`): Use `30d` (30 days), `7d` (7 days),
            `1h` (1 hour), etc.


            **Examples:**

            - `status:placed` - Filter by a single status.

            - `status:placed,completed` - Filter by multiple statuses.

            - `createdAt:30d` - Orders created in the last 30 days.

            - `id:ord_01h1s5z6vf2mm1mz3hevnn9va7` - Filter by a specific order
            ID.

            - `status:placed createdAt:7d` - Combine multiple filters.
          example: status:placed
        - $ref: '#/components/parameters/Sort'
          description: >-
            Sorts the collection by a single field. Prefix with `-` for
            descending order

            (for example, `-createdAt`); omit the prefix for ascending order
            (`createdAt`).


            **Sortable fields:** `customerName`, `status`, `totalPrice`,
            `createdAt`, `updatedAt`, `id`
          example: '-createdAt'
        - $ref: '#/components/parameters/Limit'
        - $ref: '#/components/parameters/After'
        - $ref: '#/components/parameters/Before'
        - $ref: '#/components/parameters/Search'
          description: >-
            Performs a case-insensitive text search across the searchable
            fields, returning

            items where any of them contain the search term as a substring.


            **Searchable fields:** `customerName`, `id`
          example: John
      responses:
        '200':
          description: Successful operation.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OrderList'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
    post:
      tags:
        - Orders
      summary: Create order
      description: >
        Create a new order.

        Order items cannot be changed - if they need to be updated, cancel the
        order and place a new one.
      operationId: createOrder
      security:
        - OAuth2:
            - orders:write
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Order'
            examples:
              OrderRequest:
                dataValue:
                  customerName: Mary Ann
                  orderItems:
                    - menuItemId: prd_01h1s5z6vf2mm1mz3hevnn9va7
                      quantity: 2
                      comment: No sugar!
                      discount: 0
      responses:
        '201':
          description: Order placed successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Order'
              examples:
                OrderResponse:
                  dataValue:
                    id: ord_01h1s5z6vf2mm1mz3hevnn9va7
                    customerName: Mary Ann
                    orderItems:
                      - menuItemId: prd_01h1s5z6vf2mm1mz3hevnn9va7
                        quantity: 2
                        comment: No sugar!
                        discount: 0
                    object: order
                    status: placed
                    totalPrice: 200
                    createdAt: '2026-08-24T14:15:22Z'
                    updatedAt: '2026-08-24T14:15:22Z'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /orders/{orderId}:
    get:
      tags:
        - Orders
      summary: Retrieve an order
      description: Retrieve a single order by its ID.
      operationId: getOrderById
      security:
        - OAuth2:
            - orders:read
      parameters:
        - $ref: '#/components/parameters/OrderId'
      responses:
        '200':
          description: Successful operation.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Order'
              examples:
                OrderResponse:
                  dataValue:
                    id: ord_01h1s5z6vf2mm1mz3hevnn9va7
                    customerName: Mary Ann
                    orderItems:
                      - menuItemId: prd_01h1s5z6vf2mm1mz3hevnn9va7
                        quantity: 2
                        comment: No sugar!
                        discount: 0
                    object: order
                    status: placed
                    totalPrice: 200
                    createdAt: '2026-08-24T14:15:22Z'
                    updatedAt: '2026-08-24T14:15:22Z'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
    patch:
      tags:
        - Orders
      summary: Partially update an order
      description: >
        Update an existing order status.

        Order items cannot be changed - if they need to be updated, cancel the
        order and place a new one.
      operationId: updateOrder
      security:
        - OAuth2:
            - orders:write
      parameters:
        - $ref: '#/components/parameters/OrderId'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              description: >
                Partial order update using JSON Merge Patch - only include
                fields to update.
              properties:
                status:
                  $ref: '#/components/schemas/OrderStatus'
              required:
                - status
      responses:
        '200':
          description: Order updated successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Order'
              examples:
                OrderResponse:
                  dataValue:
                    id: ord_01h1s5z6vf2mm1mz3hevnn9va7
                    customerName: Mary Ann
                    orderItems:
                      - menuItemId: prd_01h1s5z6vf2mm1mz3hevnn9va7
                        quantity: 2
                        comment: No sugar!
                        discount: 0
                    object: order
                    status: completed
                    totalPrice: 200
                    createdAt: '2026-08-24T14:15:22Z'
                    updatedAt: '2026-08-24T14:15:22Z'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
    delete:
      tags:
        - Orders
      summary: Delete an order
      description: |
        Delete the order.
        To keep the order history, cancel the order instead of deleting it.
      operationId: deleteOrder
      security:
        - OAuth2:
            - orders:write
      parameters:
        - $ref: '#/components/parameters/OrderId'
      responses:
        '204':
          description: Order deleted successfully.
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /order-items:
    get:
      tags:
        - Orders
      summary: List all order items with menu item details
      description: |
        Returns an array of order items for a specific order.
        Use the `filter` parameter to filter by order ID.
      operationId: listOrderItems
      security:
        - OAuth2:
            - orders:read
      parameters:
        - $ref: '#/components/parameters/Filter'
          required: true
          description: >-
            Selects the order whose items to return, using a single
            `orderId:<value>` pair

            (for example, `orderId:ord_01h1s5z6vf2mm1mz3hevnn9va7`).


            This filter is required and only the `orderId` field is supported.
          example: orderId:ord_01h1s5z6vf2mm1mz3hevnn9va7
      responses:
        '200':
          description: Successful operation.
          content:
            application/json:
              schema:
                type: array
                description: List of menu items that are part of the order.
                items:
                  $ref: '#/components/schemas/OrderItem'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /revenue:
    get:
      tags:
        - Statistics
      summary: Get revenue statistics
      description: >
        Retrieve revenue statistics for a configurable date range.

        Returns revenue, order counts, average order amount, and other useful
        statistics.
      operationId: getRevenue
      security:
        - ApiKey: []
        - OAuth2:
            - revenue:read
      parameters:
        - name: startDate
          in: query
          required: false
          description: >
            Start date for the revenue calculation period (ISO 8601 datetime
            format).

            Defaults to 30 days ago if not provided.
          schema:
            type: string
            format: date-time
          example: '2026-01-01T00:00:00Z'
        - name: endDate
          in: query
          required: false
          description: >
            End date for the revenue calculation period (ISO 8601 datetime
            format).

            Defaults to current time if not provided.
          schema:
            type: string
            format: date-time
          example: '2026-01-31T23:59:59Z'
      responses:
        '200':
          description: Revenue statistics retrieved successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RevenueStatistics'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /oauth2/register:
    post:
      tags:
        - Authorization
      summary: Create OAuth2 client
      description: >
        Register a new OAuth2 client, implementing the Dynamic Client
        Registration Protocol (RFC 7591) with the standard snake_case metadata
        names, so off-the-shelf DCR clients work without modification.

        Responses use only the standard snake_case names (RFC 7591 Section
        3.2.1).


        All fields are optional.

        If not provided:


        - `scope` defaults to all available scopes (`menu:read menu:write
        orders:read orders:write revenue:read`)

        - `grant_types` defaults to `authorization_code`, `client_credentials`,
        and `refresh_token`

        - `token_endpoint_auth_method` defaults to `client_secret_basic` (RFC
        7591 Section 2); both supported methods are accepted at the token
        endpoint regardless of the registered value


        This server registers confidential clients only: every client is issued
        a `client_secret`, and `token_endpoint_auth_method: none` (public
        clients such as SPAs or mobile apps, RFC 7591 Section 2) is not
        supported by design.


        `redirect_uris` is required whenever the effective grant types include
        `authorization_code` (RFC 7591 Section 2), including when `grant_types`
        is omitted, since the default includes it.

        Register with `grant_types: ["client_credentials"]` for a client that
        needs no redirect URI.


        Refresh token behavior follows the registered grant types: the token
        endpoint returns a refresh token with `authorization_code` grant
        responses only when the client registered the `refresh_token` grant
        type.

        The `client_credentials` grant never returns refresh tokens (RFC 6749
        Section 4.4.3).

        Those clients request a new access token with their own credentials
        instead.


        Returns the registered client information per RFC 7591 Section 3.2.1,
        including:


        - `client_id` and `client_secret` (must be stored securely)

        - `client_id_issued_at` and `client_secret_expires_at` timestamps

        - `registration_client_uri` and `registration_access_token` for managing
        the registration (RFC 7592)

        - All registered client metadata


        Errors use the RFC 7591 Section 3.2.2 format: `400` with `error` set to
        `invalid_redirect_uri` or `invalid_client_metadata` and a human-readable
        `error_description`.
      operationId: registerOAuth2Client
      security: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RegisterClientObject'
            examples:
              RegisterClientObject:
                summary: Client credentials only
                dataValue:
                  client_name: auth
                  scope: menu:read menu:write orders:read orders:write revenue:read
                  grant_types:
                    - client_credentials
              RegisterClientForAuthorizationCode:
                summary: Authorization code with refresh tokens (RFC 7591 names)
                dataValue:
                  client_name: pos-terminal
                  redirect_uris:
                    - https://api.cafe.redocly.com/callback
                  scope: menu:read orders:read orders:write
                  grant_types:
                    - authorization_code
                    - refresh_token
      responses:
        '201':
          description: OAuth2 client registered successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OAuth2Client'
        '400':
          $ref: '#/components/responses/OAuth2BadRequest'
        '500':
          $ref: '#/components/responses/OAuth2ServerError'
  /oauth2/register/{clientId}:
    parameters:
      - $ref: '#/components/parameters/OAuth2ClientId'
    get:
      tags:
        - Authorization
      summary: Retrieve OAuth2 client
      description: >
        Read the current registration of an OAuth2 client (RFC 7592 Section
        2.1).

        Authenticate with the `registration_access_token` returned at
        registration, as a Bearer token in the `Authorization` header.

        An invalid or missing token returns `401` without revealing whether the
        client exists.
      operationId: getOAuth2Client
      security:
        - RegistrationAccessToken: []
      responses:
        '200':
          description: Current client registration.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OAuth2Client'
        '401':
          $ref: '#/components/responses/OAuth2Unauthorized'
        '500':
          $ref: '#/components/responses/OAuth2ServerError'
    put:
      tags:
        - Authorization
      summary: Update OAuth2 client
      description: >
        Replace the registration metadata of an OAuth2 client (RFC 7592 Section
        2.2).

        Authenticate with the `registration_access_token` as a Bearer token.


        This is a full replacement, not a merge: omitted metadata fields are
        reset to their registration defaults.

        The request must include `client_id` matching the client being updated
        (RFC 7592 Section 2.2).

        If `client_secret` is included it must match the current secret.

        Credentials cannot be rotated through this endpoint.
      operationId: updateOAuth2Client
      security:
        - RegistrationAccessToken: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateClientObject'
            examples:
              UpdateClient:
                dataValue:
                  client_id: client_1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d
                  client_name: pos-terminal-v2
                  redirect_uris:
                    - https://api.cafe.redocly.com/callback
                  scope: menu:read orders:read
                  grant_types:
                    - authorization_code
                    - refresh_token
      responses:
        '200':
          description: Updated client registration.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OAuth2Client'
        '400':
          $ref: '#/components/responses/OAuth2BadRequest'
        '401':
          $ref: '#/components/responses/OAuth2Unauthorized'
        '500':
          $ref: '#/components/responses/OAuth2ServerError'
    delete:
      tags:
        - Authorization
      summary: Delete OAuth2 client
      description: >
        Deprovision an OAuth2 client (RFC 7592 Section 2.3).

        Authenticate with the `registration_access_token` as a Bearer token.

        Deleting a client also invalidates all of its tokens and pending
        authorization codes.
      operationId: deleteOAuth2Client
      security:
        - RegistrationAccessToken: []
      responses:
        '204':
          description: Client registration deleted.
        '401':
          $ref: '#/components/responses/OAuth2Unauthorized'
        '500':
          $ref: '#/components/responses/OAuth2ServerError'
  /oauth2/token:
    post:
      tags:
        - Authorization
      summary: Create access token
      description: >
        OAuth2 token endpoint (RFC 6749 Section 3.2).

        Supports the `authorization_code`, `client_credentials`, and
        `refresh_token` grant types.


        **Client authentication.**

        Authenticate with HTTP Basic (`Authorization: Basic
        base64(client_id:client_secret)`) or with `client_id` and
        `client_secret` in the request body — not both at once (RFC 6749 Section
        2.3.1).


        **PKCE (RFC 7636).** 

        When the authorization request included a `code_challenge`, the matching
        `code_verifier` is required here.

        A mismatch or a `code_verifier` for a code issued without a challenge is
        rejected with `invalid_grant`.

        `S256` and `plain` challenge methods are supported.


        **Refresh tokens.**

        Rotate on every use: a successful `refresh_token` grant retires the
        presented token and returns a replacement.

        Refresh tokens expire 30 days after issuance; rotation restarts that
        window.

        The `authorization_code` grant returns a refresh token only when the
        client is registered for the `refresh_token` grant type.

        The `client_credentials` grant never returns one (RFC 6749 Section
        4.4.3).


        **Scopes.**

        `scope` is space-separated per RFC 6749 (comma-separated values are
        additionally tolerated).

        Must be a subset of the scopes previously granted (authorization code or
        refresh token) or registered (client credentials).


        Errors follow RFC 6749 Section 5.2: `400` (or `401` for
        `invalid_client`) with the standard `error` codes such as
        `invalid_grant`, `invalid_client`, `unauthorized_client`,
        `unsupported_grant_type`, and `invalid_scope`.
      operationId: createAccessToken
      security: []
      requestBody:
        required: true
        content:
          application/x-www-form-urlencoded:
            schema:
              type: object
              properties:
                grant_type:
                  type: string
                  enum:
                    - authorization_code
                    - client_credentials
                    - refresh_token
                  description: The OAuth2 grant type.
                client_id:
                  type: string
                  description: Client identifier. Omit when authenticating with HTTP Basic.
                client_secret:
                  type: string
                  description: Client secret. Omit when authenticating with HTTP Basic.
                code:
                  type: string
                  description: The authorization code (required for `authorization_code`).
                redirect_uri:
                  type: string
                  format: uri
                  description: >-
                    Must match the redirect URI used in the authorization
                    request. Required for `authorization_code`).
                code_verifier:
                  type: string
                  minLength: 43
                  maxLength: 128
                  description: >-
                    PKCE code verifier (RFC 7636) Required when the
                    authorization request included a `code_challenge`.
                refresh_token:
                  type: string
                  description: The refresh token. Required for `refresh_token`.
                scope:
                  type: string
                  description: >-
                    Space-separated scopes to request. Defaults to the
                    previously granted or registered scopes.
              required:
                - grant_type
            examples:
              ClientCredentials:
                summary: Client credentials grant
                dataValue:
                  grant_type: client_credentials
                  client_id: client_1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d
                  client_secret: YOUR_CLIENT_SECRET
                  scope: menu:read orders:read
              AuthorizationCode:
                summary: Authorization code exchange with PKCE
                dataValue:
                  grant_type: authorization_code
                  client_id: client_1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d
                  client_secret: YOUR_CLIENT_SECRET
                  code: AUTHORIZATION_CODE
                  redirect_uri: https://api.cafe.redocly.com/callback
                  code_verifier: dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk
              RefreshToken:
                summary: Refresh token grant
                dataValue:
                  grant_type: refresh_token
                  client_id: client_1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d
                  client_secret: YOUR_CLIENT_SECRET
                  refresh_token: YOUR_REFRESH_TOKEN
      responses:
        '200':
          description: >-
            Token issued successfully. The response is not cacheable (it is
            served with `Cache-Control` set to `no-store`).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TokenResponse'
        '400':
          $ref: '#/components/responses/OAuth2BadRequest'
        '401':
          $ref: '#/components/responses/OAuth2Unauthorized'
        '500':
          $ref: '#/components/responses/OAuth2ServerError'
  /oauth2/revoke:
    post:
      tags:
        - Authorization
      summary: Revoke token
      description: >
        OAuth2 token revocation endpoint (RFC 7009). Revokes an access or
        refresh

        token issued to the authenticated client. Access and refresh tokens
        issued

        together are revoked together.


        Authenticate with HTTP Basic or with `client_id` and `client_secret` in
        the

        request body, the same as the token endpoint.


        `token_type_hint` is an optional lookup optimization; both token types
        are searched regardless.

        Per RFC 7009 Section 2.2 the endpoint returns `200` even when the token
        is unknown or already revoked.

        It cannot be used to probe for valid tokens.
      operationId: revokeToken
      security: []
      requestBody:
        required: true
        content:
          application/x-www-form-urlencoded:
            schema:
              type: object
              properties:
                token:
                  type: string
                  description: The access or refresh token to revoke.
                token_type_hint:
                  type: string
                  enum:
                    - access_token
                    - refresh_token
                  description: Optional hint about the token type.
                client_id:
                  type: string
                  description: Client identifier. Omit when authenticating with HTTP Basic.
                client_secret:
                  type: string
                  description: Client secret. Omit when authenticating with HTTP Basic.
              required:
                - token
            examples:
              RevokeAccessToken:
                dataValue:
                  token: YOUR_ACCESS_TOKEN
                  token_type_hint: access_token
                  client_id: client_1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d
                  client_secret: YOUR_CLIENT_SECRET
      responses:
        '200':
          description: The token has been revoked or was already invalid.
        '400':
          $ref: '#/components/responses/OAuth2BadRequest'
        '401':
          $ref: '#/components/responses/OAuth2Unauthorized'
        '500':
          $ref: '#/components/responses/OAuth2ServerError'
  /.well-known/oauth-authorization-server:
    get:
      tags:
        - Authorization
      summary: Retrieve authorization server metadata
      description: >
        OAuth2 authorization server metadata (RFC 8414).

        Lists the authorization, token, registration, and revocation endpoints
        along with the supported scopes, grant types, client authentication
        methods, and PKCE code challenge methods.

        Clients can discover the server's capabilities instead of hard-coding
        them.
      operationId: getAuthorizationServerMetadata
      security: []
      responses:
        '200':
          description: Authorization server metadata.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthorizationServerMetadata'
              examples:
                Metadata:
                  dataValue:
                    issuer: https://api.cafe.redocly.com
                    authorization_endpoint: https://api.cafe.redocly.com/oauth2/authorize
                    token_endpoint: https://api.cafe.redocly.com/oauth2/token
                    registration_endpoint: https://api.cafe.redocly.com/oauth2/register
                    revocation_endpoint: https://api.cafe.redocly.com/oauth2/revoke
                    scopes_supported:
                      - menu:read
                      - menu:write
                      - orders:read
                      - orders:write
                      - revenue:read
                    response_types_supported:
                      - code
                    response_modes_supported:
                      - query
                    grant_types_supported:
                      - authorization_code
                      - client_credentials
                      - refresh_token
                    token_endpoint_auth_methods_supported:
                      - client_secret_basic
                      - client_secret_post
                    revocation_endpoint_auth_methods_supported:
                      - client_secret_basic
                      - client_secret_post
                    code_challenge_methods_supported:
                      - S256
                      - plain
                    authorization_response_iss_parameter_supported: true
                    service_documentation: https://cafe.redocly.com/openapi/cafe
        '500':
          $ref: '#/components/responses/OAuth2ServerError'
webhooks:
  order-notification:
    post:
      tags:
        - Orders
      operationId: orderNotificationWebhook
      security: []
      summary: Order notification webhook
      description: Webhook triggered when a new order is placed.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/OrderNotification'
      responses:
        '200':
          description: Webhook received successfully.
        '400':
          $ref: '#/components/responses/BadRequest'
        '500':
          $ref: '#/components/responses/InternalServerError'
components:
  securitySchemes:
    OAuth2:
      type: oauth2
      description: >
        OAuth2 authorization for API access. The token endpoint accepts
        `grant_type=authorization_code`, `grant_type=client_credentials`, and
        `grant_type=refresh_token`.

        Standard OAuth2 client libraries can drive these flows unmodified.

        Server capabilities are discoverable from the [RFC 8414 metadata
        endpoint](https://api.cafe.redocly.com/.well-known/oauth-authorization-server).


        ### Protocol behavior


        - **Errors follow RFC 6749 Section 5.2 and RFC 7591 Section 3.2.2.** The
        OAuth2 endpoints return `{"error": ..., "error_description": ...}` with
        the standard codes (`invalid_grant`, `invalid_client`,
        `unsupported_grant_type`, `invalid_scope`, `invalid_client_metadata`,
        ...). The rest of the API uses RFC 9457 problem+json.

        - **Client authentication.** Both `client_secret_basic` (HTTP Basic per
        RFC 6749 Section 2.3.1) and `client_secret_post` (credentials in the
        form body) are accepted at the token and revocation endpoints, but not
        both in one request.

        - **PKCE (RFC 7636) is supported** for the authorization code flow with
        the `S256` and `plain` challenge methods (`S256` recommended). When an
        authorization request carries a `code_challenge`, the token exchange
        requires the matching `code_verifier`.

        - **Refresh tokens rotate on every use.** A successful refresh retires
        the token presented and returns a replacement in `refresh_token`, as RFC
        6749 Section 6 permits and RFC 9700 recommends. Store the new value; the
        old one stops working. Refresh tokens expire 30 days after they are
        issued, and rotation restarts that window. The authorization code flow
        returns a refresh token only when the client is registered for the
        `refresh_token` grant type; the client credentials flow returns none
        (RFC 6749 Section 4.4.3).

        - **Authorization responses carry `iss`** (RFC 9207) alongside `code`
        and `state`.

        - **Tokens can be revoked** at the [revocation
        endpoint](https://api.cafe.redocly.com/oauth2/revoke) (RFC 7009), and
        client registrations managed via RFC 7592 using the
        `registration_access_token`.

        - **`scope` accepts commas.** The space-delimited form required by RFC
        6749 is always accepted and recommended; comma-separated values are
        additionally tolerated.
      oauth2MetadataUrl: https://api.cafe.redocly.com/.well-known/oauth-authorization-server
      flows:
        authorizationCode:
          authorizationUrl: https://api.cafe.redocly.com/oauth2/authorize
          tokenUrl: https://api.cafe.redocly.com/oauth2/token
          refreshUrl: https://api.cafe.redocly.com/oauth2/token
          scopes:
            menu:read: Read access to menu items and images
            menu:write: Write access to menu items (create, delete)
            orders:read: Read access to orders
            orders:write: Write access to orders (create, update, delete)
            revenue:read: Read access to revenue statistics
        clientCredentials:
          tokenUrl: https://api.cafe.redocly.com/oauth2/token
          scopes:
            menu:read: Read access to menu items and images
            menu:write: Write access to menu items (create, delete)
            orders:read: Read access to orders
            orders:write: Write access to orders (create, update, delete)
            revenue:read: Read access to revenue statistics
    ApiKey:
      type: apiKey
      name: X-API-Key
      in: header
      description: API key for internal operations.
    RegistrationAccessToken:
      type: http
      scheme: bearer
      description: >-
        Registration access token from the client registration response (RFC
        7592), sent as a Bearer token to authenticate requests to the client
        configuration endpoint (`/oauth2/register/{clientId}`).
  parameters:
    After:
      name: after
      in: query
      required: false
      description: Use the `nextPage` value as the `after` parameter to get the next page.
      schema:
        type: string
    Before:
      name: before
      in: query
      required: false
      description: >
        Use the `previousPage` value as the `before` parameter to get the
        previous page.
      schema:
        type: string
    Sort:
      name: sort
      description: |-
        To sort by id in descending order use `-id`.
        To sort by id in ascending order use `id`.
      in: query
      required: false
      schema:
        type: string
    Filter:
      name: filter
      description: >-
        Filters the collection items using space-separated `field:value` pairs.

        See each list endpoint for the specific fields it supports.


        **Format:** `field1:value1 field2:value2`


        **Supported operators:**

        - `field:value` - exact match

        - `field:value1,value2` - match any of the comma-separated values (OR)

        - Time ranges (on date fields): use `30d` (30 days), `7d` (7 days), `1h`
        (1 hour), etc.
      in: query
      required: false
      schema:
        type: string
    Search:
      name: search
      in: query
      description: >-
        Performs a case-insensitive text search across the endpoint's searchable
        fields,

        returning items where any of those fields contain the search term as a
        substring.

        See each list endpoint for the specific fields it searches.
      required: false
      schema:
        type: string
    Limit:
      name: limit
      description: >
        Specify the number of results per page.

        If there is more data, use in combination with `after` to page through
        all results.
      in: query
      required: false
      schema:
        type: integer
        minimum: 1
        maximum: 100
        default: 10
      example: 10
    MenuItemId:
      name: menuItemId
      in: path
      description: ID of the menu item to retrieve.
      required: true
      schema:
        type: string
        pattern: ^prd_[0-9abcdefghjkmnpqrstvwxyz]{26}$
    PhotoSize:
      name: photoSize
      in: query
      description: Photo size to retrieve.
      required: false
      schema:
        type: string
        enum:
          - thumbnail
          - medium
          - large
        default: medium
    OrderId:
      name: orderId
      in: path
      description: ID of the order to retrieve.
      required: true
      schema:
        type: string
        pattern: ^ord_[0-9abcdefghjkmnpqrstvwxyz]{26}$
      example: ord_01h1s5z6vf2mm1mz3hevnn9va7
    OAuth2ClientId:
      name: clientId
      in: path
      required: true
      description: The client identifier issued at registration.
      schema:
        type: string
      example: client_1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d
  schemas:
    Page:
      type: object
      properties:
        nextPage:
          type:
            - string
            - 'null'
          description: |-
            Use with the `after` query parameter to load the next page of data.
            When `null`, there is no next page.
            The cursor is opaque and internal structure is subject to change.
        previousPage:
          type:
            - string
            - 'null'
          description: >-
            Use with the `before` query parameter to load the previous page of
            data.

            When `null`, there is no previous page.

            The cursor is opaque and internal structure is subject to change.
        limit:
          type: integer
          minimum: 1
          maximum: 100
          default: 10
          description: Value showing how many items are in the page limit.
      required:
        - nextPage
        - previousPage
        - limit
    MenuBaseItem:
      type: object
      properties:
        createdAt:
          description: Created date.
          type: string
          format: date-time
          readOnly: true
        updatedAt:
          description: Updated date.
          type: string
          format: date-time
          readOnly: true
        id:
          description: Menu item ID. Unique identifier prefixed with `prd_`.
          type: string
          readOnly: true
          pattern: ^prd_[0-9abcdefghjkmnpqrstvwxyz]{26}$
          example: prd_01h1s5z6vf2mm1mz3hevnn9va7
        object:
          description: Entity name.
          type: string
          const: menuItem
          readOnly: true
        name:
          description: Menu item name.
          type: string
          minLength: 1
          maxLength: 50
        price:
          description: Price in cents.
          type: integer
          minimum: 0
        photo:
          writeOnly: true
          type:
            - string
            - 'null'
          format: binary
          description: Photo of the menu item. Must be a PNG image less than 1MB in size.
        photoUrl:
          readOnly: true
          type: string
          format: uri
          description: Photo URL of the menu item.
        photoTextDescription:
          type:
            - string
            - 'null'
      required:
        - id
        - name
        - price
        - createdAt
        - updatedAt
        - object
    Beverage:
      allOf:
        - type: object
          properties:
            category:
              description: Menu item category.
              type: string
              const: beverage
            volume:
              type: number
              description: Size of the beverage in milliliters.
              exclusiveMinimum: 0
            containsCaffeine:
              type: boolean
              description: Indicates if the beverage contains caffeine.
          required:
            - category
            - volume
            - containsCaffeine
        - $ref: '#/components/schemas/MenuBaseItem'
    Dessert:
      allOf:
        - type: object
          properties:
            category:
              description: Menu item category.
              type: string
              const: dessert
            calories:
              type: number
              exclusiveMinimum: 0
              description: Amount of calories.
          required:
            - category
            - calories
        - $ref: '#/components/schemas/MenuBaseItem'
    MenuItem:
      discriminator:
        propertyName: category
        mapping:
          beverage: '#/components/schemas/Beverage'
          dessert: '#/components/schemas/Dessert'
      oneOf:
        - $ref: '#/components/schemas/Beverage'
        - $ref: '#/components/schemas/Dessert'
      required:
        - category
    MenuItemList:
      type: object
      properties:
        object:
          type: string
          const: list
          description: Entity name.
        page:
          $ref: '#/components/schemas/Page'
        items:
          type: array
          items:
            $ref: '#/components/schemas/MenuItem'
      required:
        - object
        - page
        - items
    Error:
      type: object
      properties:
        type:
          type: string
          format: uri-reference
          description: URI reference that identifies the problem type.
          default: about:blank
        title:
          type: string
          description: Short summary of the problem type.
        status:
          type: integer
          format: int32
          description: >
            HTTP status code generated by the origin server for this occurrence
            of the problem.
          minimum: 100
          exclusiveMaximum: 600
        instance:
          type: string
          format: uri-reference
          description: >
            URI reference that identifies the specific occurrence of the
            problem, e.g. by adding a fragment identifier or sub-path to the
            problem type.

            Can be used to locate the root of this problem in the source code.
          example: /some/uri-reference#specific-occurrence-context
        details:
          description: Additional error details.
          type: object
          additionalProperties: true
      required:
        - type
        - title
        - status
    OrderStatus:
      type: string
      description: Order status.
      enum:
        - placed
        - preparing
        - completed
        - canceled
    Order:
      type: object
      title: Order
      properties:
        id:
          description: Order ID. Unique identifier prefixed with `ord_`.
          type: string
          format: ulid
          readOnly: true
          pattern: ^ord_[0-9abcdefghjkmnpqrstvwxyz]{26}$
          example: ord_01h1s5z6vf2mm1mz3hevnn9va7
        object:
          description: Entity name.
          type: string
          const: order
          readOnly: true
        customerName:
          description: >
            Name of the customer who placed the order.

            Must start and end with a letter, and can contain letters, spaces,
            hyphens, and apostrophes (e.g., "John Doe", "Mary-Jane", "O'Brien").
          type: string
          pattern: ^[A-Za-z]+(?:[\s'-][A-Za-z]+)*$
          minLength: 1
          maxLength: 100
        status:
          allOf:
            - $ref: '#/components/schemas/OrderStatus'
          readOnly: true
        totalPrice:
          description: Total order price in cents.
          type: integer
          minimum: 0
          readOnly: true
        createdAt:
          description: Created date.
          type: string
          format: date-time
          readOnly: true
        updatedAt:
          description: Updated date.
          type: string
          format: date-time
          readOnly: true
        orderItems:
          type: array
          description: List of items to include in the order.
          minItems: 1
          items:
            type: object
            properties:
              menuItemId:
                type: string
                format: ulid
                description: ID of the menu item to add to the order.
              quantity:
                type: integer
                minimum: 1
                description: Quantity of the menu item.
              discount:
                type: integer
                minimum: 0
                description: Discount amount in cents (absolute value).
                default: 0
              comment:
                type: string
                maxLength: 500
                description: Optional comment for the order item (e.g., "No sugar").
            required:
              - menuItemId
              - quantity
      required:
        - customerName
        - orderItems
    OrderList:
      type: object
      properties:
        object:
          type: string
          const: list
          description: Entity name.
        page:
          $ref: '#/components/schemas/Page'
        items:
          type: array
          items:
            $ref: '#/components/schemas/Order'
      required:
        - object
        - page
        - items
    OrderItem:
      type: object
      properties:
        menuItemId:
          type: string
          description: ID of the menu item to add to the order.
          writeOnly: true
        menuItem:
          allOf:
            - $ref: '#/components/schemas/MenuItem'
          description: Menu item that is part of the order.
          readOnly: true
        quantity:
          type: integer
          minimum: 1
          description: Quantity of the menu item.
        discount:
          type: integer
          minimum: 0
          description: Discount amount in cents (absolute value).
          default: 0
        comment:
          type: string
          maxLength: 500
          description: Optional comment for the order item (e.g., "No sugar").
      required:
        - menuItemId
        - quantity
    RevenueStatistics:
      type: object
      description: Revenue statistics for a given date range.
      properties:
        revenue:
          type: number
          format: float
          description: Total revenue in cents from completed orders.
          minimum: 0
        averageOrderAmount:
          type: number
          format: float
          description: >-
            Average order amount in cents (calculated from completed orders
            only).
          minimum: 0
        totalOrders:
          type: integer
          description: Total number of orders (all statuses) in the date range.
          minimum: 0
        placedOrders:
          type: integer
          description: Number of placed orders.
          minimum: 0
        preparingOrders:
          type: integer
          description: Number of preparing orders.
          minimum: 0
        completedOrders:
          type: integer
          description: Number of completed orders.
          minimum: 0
        canceledOrders:
          type: integer
          description: Number of canceled orders.
          minimum: 0
        startDate:
          type: string
          format: date-time
          description: Start date of the revenue calculation period.
        endDate:
          type: string
          format: date-time
          description: End date of the revenue calculation period.
      required:
        - revenue
        - averageOrderAmount
        - totalOrders
        - placedOrders
        - preparingOrders
        - completedOrders
        - canceledOrders
        - startDate
        - endDate
    RegisterClientMetadata:
      type: object
      description: >
        Client registration metadata fields per RFC 7591 Section 2, shared by
        both

        registration variants.
      properties:
        client_name:
          type: string
          description: >-
            Human-readable client name, displayed on the authorization consent
            screen.
        scope:
          type: string
          description: Space-separated list of scopes. Defaults to all available scopes.
          default: menu:read menu:write orders:read orders:write revenue:read
          pattern: >-
            ^(menu:read|menu:write|orders:read|orders:write|revenue:read)(
            (menu:read|menu:write|orders:read|orders:write|revenue:read))*$
          example: menu:read orders:read orders:write
        grant_types:
          type: array
          items:
            type: string
            enum:
              - authorization_code
              - client_credentials
              - refresh_token
          default:
            - authorization_code
            - client_credentials
            - refresh_token
          description: >
            Grant types the client may use.

            A refresh token is issued with `authorization_code` grant responses
            only when `refresh_token` is included here.

            The `client_credentials` grant never returns one (RFC 6749 Section
            4.4.3).
        token_endpoint_auth_method:
          type: string
          enum:
            - client_secret_basic
            - client_secret_post
          default: client_secret_basic
          description: >
            Requested client authentication method for the token endpoint,
            registered as client metadata and echoed in registration responses.

            Defaults to `client_secret_basic` (RFC 7591 Section 2).

            The token and revocation endpoints accept both methods for every
            client regardless.
    RegisterClientAuthorizationCode:
      title: authorization_code
      description: >-
        Effective grant types include `authorization_code` — explicitly, or by
        default when `grant_types` is omitted. A non-empty `redirect_uris` is
        required. Other grant types (`client_credentials`, `refresh_token`) can
        be registered alongside.
      allOf:
        - type: object
          required:
            - redirect_uris
          properties:
            redirect_uris:
              type: array
              minItems: 1
              items:
                type: string
                format: uri
              description: >
                Redirect URIs for the `authorization_code` grant.

                Compared with exact string matching at authorization time (RFC
                6749 Section 3.1.2.3).
        - $ref: '#/components/schemas/RegisterClientMetadata'
    RegisterClientCredentials:
      title: client_credentials
      description: >-
        `grant_types` is provided and does not include `authorization_code` —
        typically machine-to-machine clients using `client_credentials`. No
        redirect URI is needed.
      allOf:
        - $ref: '#/components/schemas/RegisterClientMetadata'
        - type: object
          required:
            - grant_types
          properties:
            grant_types:
              not:
                contains:
                  const: authorization_code
    RegisterClientObject:
      description: >
        Client registration metadata per RFC 7591 Section 2, using the standard
        snake_case field names.

        All fields are optional, with one conditional exception.

        `redirect_uris` is required whenever the effective grant types include
        `authorization_code`.

        This requirement still applies when `grant_types` is omitted:
        `authorization_code` is part of the default (RFC 7591 Section 2).
      anyOf:
        - $ref: '#/components/schemas/RegisterClientAuthorizationCode'
        - $ref: '#/components/schemas/RegisterClientCredentials'
    OAuth2Client:
      type: object
      description: >
        OAuth2 client information response per RFC 7591 Section 3.2.1, using the
        standard snake_case field names.

        Returned by the registration endpoint and the RFC 7592 client
        configuration endpoint.
      properties:
        client_id:
          type: string
          description: Client identifier issued by the authorization server.
        client_secret:
          type: string
          description: Client secret issued by the authorization server. Store it securely.
        client_id_issued_at:
          type: integer
          format: int64
          description: >-
            Time when the client_id is issued, represented as seconds since
            epoch (RFC 7591).
        client_secret_expires_at:
          type: integer
          format: int64
          description: >-
            Time at which the client_secret expires, represented as seconds
            since epoch. `0` indicates the secret does not expire (RFC 7591).
        registration_client_uri:
          type: string
          format: uri
          description: >-
            URL of the client configuration endpoint for managing this client
            registration (RFC 7592).
        registration_access_token:
          type: string
          description: >-
            Bearer token for the client configuration endpoint (RFC 7592). Store
            it securely.
        client_name:
          type: string
          description: >-
            Client name (registered metadata). Omitted for clients registered
            without a name.
        redirect_uris:
          type: array
          items:
            type: string
            format: uri
          description: Registered redirect URIs.
        grant_types:
          type: array
          items:
            type: string
            enum:
              - authorization_code
              - client_credentials
              - refresh_token
          description: Registered grant types.
        scope:
          type: string
          description: Space-separated registered scopes.
        token_endpoint_auth_method:
          type: string
          enum:
            - client_secret_basic
            - client_secret_post
          description: >
            Registered token endpoint authentication method. Defaults to
            `client_secret_basic` when not requested at registration (RFC 7591
            Section 2).

            The token and revocation endpoints accept both methods for every
            client regardless.
      required:
        - client_id
        - client_secret
        - client_id_issued_at
        - client_secret_expires_at
        - registration_client_uri
        - registration_access_token
        - redirect_uris
        - grant_types
        - scope
        - token_endpoint_auth_method
    OAuthError:
      type: object
      description: >
        OAuth2 error response, as defined by RFC 6749 Section 5.2 (token
        endpoint), RFC 7591 Section 3.2.2 (registration endpoint), and RFC 7009
        (revocation endpoint).

        The OAuth2 endpoints return this shape instead of the
        `application/problem+json` format used by the rest of the API.
      properties:
        error:
          type: string
          description: Machine-readable error code.
          enum:
            - invalid_request
            - invalid_client
            - invalid_grant
            - unauthorized_client
            - unsupported_grant_type
            - unsupported_response_type
            - invalid_scope
            - invalid_client_metadata
            - invalid_redirect_uri
            - invalid_token
            - access_denied
            - server_error
        error_description:
          type: string
          description: Human-readable explanation of the error.
      required:
        - error
    UpdateClientObject:
      description: >
        Client registration update request per RFC 7592 Section 2.2: the full
        set of registration metadata, plus the required `client_id` of the
        client being updated.

        Omitted metadata fields are reset to their registration defaults.
      allOf:
        - $ref: '#/components/schemas/RegisterClientObject'
        - type: object
          required:
            - client_id
          properties:
            client_id:
              type: string
              description: >-
                Required (RFC 7592 Section 2.2). Must match the client being
                updated. Credentials cannot be changed through this endpoint.
            client_secret:
              type: string
              description: Optional. If present, must match the client's current secret.
    TokenResponse:
      type: object
      description: Access token response per RFC 6749 Section 5.1.
      properties:
        access_token:
          type: string
          description: The issued access token (opaque string).
        token_type:
          type: string
          description: Type of the issued token.
          const: Bearer
        expires_in:
          type: integer
          description: Access token lifetime in seconds.
          example: 3600
        refresh_token:
          type: string
          description: >
            Refresh token, returned for the `authorization_code` grant when the
            client is registered for the `refresh_token` grant type, and on
            every refresh (tokens rotate on use).

            Never returned for the `client_credentials` grant (RFC 6749 Section
            4.4.3).
        scope:
          type: string
          description: Space-separated scopes granted to the token.
          example: menu:read orders:read
      required:
        - access_token
        - token_type
        - expires_in
    AuthorizationServerMetadata:
      type: object
      description: OAuth2 authorization server metadata per RFC 8414.
      properties:
        issuer:
          type: string
          format: uri
          description: The authorization server's issuer identifier.
        authorization_endpoint:
          type: string
          format: uri
        token_endpoint:
          type: string
          format: uri
        registration_endpoint:
          type: string
          format: uri
          description: Dynamic client registration endpoint (RFC 7591).
        revocation_endpoint:
          type: string
          format: uri
          description: Token revocation endpoint (RFC 7009).
        scopes_supported:
          type: array
          items:
            type: string
        response_types_supported:
          type: array
          items:
            type: string
        response_modes_supported:
          type: array
          items:
            type: string
        grant_types_supported:
          type: array
          items:
            type: string
        token_endpoint_auth_methods_supported:
          type: array
          items:
            type: string
        revocation_endpoint_auth_methods_supported:
          type: array
          items:
            type: string
        code_challenge_methods_supported:
          type: array
          description: PKCE code challenge methods supported (RFC 7636).
          items:
            type: string
        authorization_response_iss_parameter_supported:
          type: boolean
          description: >-
            Whether authorization responses carry the `iss` parameter (RFC
            9207).
        service_documentation:
          type: string
          format: uri
      required:
        - issuer
        - authorization_endpoint
        - token_endpoint
        - response_types_supported
    OrderNotification:
      type: object
      required:
        - orderId
        - orderStatus
        - timestamp
      properties:
        orderId:
          type: string
          description: Unique order identifier.
        orderStatus:
          $ref: '#/components/schemas/OrderStatus'
        timestamp:
          type: string
          format: date-time
          description: When the event occurred.
  responses:
    BadRequest:
      description: Bad request - invalid input parameters.
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Error'
    InternalServerError:
      description: Internal server error.
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Error'
    Unauthorized:
      description: Unauthorized - authorization required.
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Error'
    Forbidden:
      description: Forbidden - insufficient permissions.
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Error'
    Conflict:
      description: Conflict - entity already exists.
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Error'
    NotFound:
      description: Resource not found.
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Error'
    OAuth2BadRequest:
      description: |
        OAuth2 error (RFC 6749 Section 5.2 / RFC 7591 Section 3.2.2).
        The `error` field carries the standard OAuth2 error code.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/OAuthError'
    OAuth2ServerError:
      description: Unexpected server error, reported with the `server_error` error code.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/OAuthError'
    OAuth2Unauthorized:
      description: >
        Client authentication failed (`error: invalid_client`, RFC 6749 Section
        5.2) or the presented bearer token is invalid (`error: invalid_token`,
        RFC 6750).

        The response carries a `WWW-Authenticate` challenge naming the expected
        authentication scheme.
      headers:
        WWW-Authenticate:
          description: >-
            Authentication challenge, for example: `Basic realm="redocly-cafe"`
            or `Bearer realm="redocly-cafe", error="invalid_token"`.
          schema:
            type: string
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/OAuthError'
