openapi: 3.1.0
info:
  title: Order Service — Past Ordered Items
  version: 1.0.0
  description: |
    Returns the items an authenticated user has previously ordered from a vendor,
    or from a specific branch of that vendor, including the modifiers they selected.
    Results are grouped by product ID.
servers:
  - url: https://prod.hubz.nyotek.com
    description: Production
  - url: https://dev.hubz.nyotek.com
    description: Development
security:
  - bearerAuth: []
tags:
  - name: Past Orders
    description: Previously ordered items for the current user
paths:
  /order/{vendor_id}/items:
    get:
      operationId: getPastOrderedItemsByVendor
      summary: List past ordered items from a vendor
      description: Returns the authenticated user's previously ordered items across all branches of the vendor, grouped by product ID.
      x-assumed-method: true
      tags: [Past Orders]
      parameters:
        - $ref: '#/components/parameters/VendorId'
        - $ref: '#/components/parameters/XServiceId'
        - $ref: '#/components/parameters/XClientTz'
        - $ref: '#/components/parameters/XLocale'
        - $ref: '#/components/parameters/XSelectedLang'
        - $ref: '#/components/parameters/XServices'
      responses:
        '200':
          $ref: '#/components/responses/PastOrderedItems'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /order/{vendor_id}/{branch_id}/items:
    get:
      operationId: getPastOrderedItemsByBranch
      summary: List past ordered items from a branch
      description: Returns the authenticated user's previously ordered items from one branch of the vendor, grouped by product ID.
      x-assumed-method: true
      tags: [Past Orders]
      parameters:
        - $ref: '#/components/parameters/VendorId'
        - $ref: '#/components/parameters/BranchId'
        - $ref: '#/components/parameters/XServiceId'
        - $ref: '#/components/parameters/XClientTz'
        - $ref: '#/components/parameters/XLocale'
        - $ref: '#/components/parameters/XSelectedLang'
        - $ref: '#/components/parameters/XServices'
      responses:
        '200':
          $ref: '#/components/responses/PastOrderedItems'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
  parameters:
    VendorId:
      name: vendor_id
      in: path
      required: true
      description: Vendor ID.
      schema:
        $ref: '#/components/schemas/Ulid'
    BranchId:
      name: branch_id
      in: path
      required: true
      description: Branch ID (must belong to the vendor).
      schema:
        $ref: '#/components/schemas/Ulid'
    XServiceId:
      name: X-Service-Id
      in: header
      required: true
      description: ID of the Nyotek service (tenant/app) the request is made for.
      schema:
        $ref: '#/components/schemas/Ulid'
    XClientTz:
      name: X-Client-Tz
      in: header
      required: false
      description: Client's IANA time zone, used for date/time handling.
      schema:
        type: string
        examples: [Asia/Dubai]
    XLocale:
      name: X-Locale
      in: header
      required: false
      description: Client locale for formatting.
      schema:
        type: string
        examples: [en-us]
    XSelectedLang:
      name: X-Selected-Lang
      in: header
      required: false
      description: Language the user selected for content/translations.
      schema:
        type: string
        examples: [en-us]
    XServices:
      name: X-Services
      in: header
      required: false
      description: Services the request applies to / is scoped to.
      schema:
        type: string
  responses:
    PastOrderedItems:
      description: Past ordered items, grouped by product ID.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/PastOrderedItemsResponse'
          example:
            data:
              01HMBSQSRG0000000000000000:
                - product_id: 01HMBSQSRG0000000000000000
                  selected_mods:
                    - parent_id: 01HMBSQSRG9G6XZ7XQ50P1W6WE
                      parent_name: { en-us: Sizes }
                      parent_type: select_mod
                      selected_child:
                        - selected_id: 01HMBSQSRGQ4PQRDTW5K540726
                          selected_name: { en-us: 6 Inch }
                          selected_type: size_mod
                          selected_media_url:
                            '0': https://storage.googleapis.com/nyofiles/01HMBSF8XJCMVQP9YP7W85D0JA.png
                          selected_price: 1650
                          selected_vat_price: 0
                          selected_add_on_price: false
                          selected_quantity: 1
                    - parent_id: 01HMBSSAVY8PH5WS5PYM1H42YR
                      parent_name: { en-us: Ingredients }
                      parent_type: multi_mod
                      selected_child:
                        - selected_id: 01HMBSSAVYH30XKMXSDE0N58WB
                          selected_name: { en-us: Bread }
                          selected_type: child_mod
                          selected_media_url:
                            '0': https://storage.googleapis.com/nyofiles/01HKPNMEQE8T417CDX0XM6R0WT.png
                          selected_price: 0
                          selected_vat_price: 0
                          selected_add_on_price: false
                          selected_quantity: 1
                  last_ordered_at: '2026-10-15T10:30:00Z'
    BadRequest:
      description: Invalid path parameter or missing required header.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Unauthorized:
      description: Missing or invalid bearer token.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    NotFound:
      description: Vendor or branch not found.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  schemas:
    Ulid:
      type: string
      pattern: '^[0-9A-HJKMNP-TV-Z]{26}$'
      examples: [01HMBSQSRG9G6XZ7XQ50P1W6WE]
    LocalizedString:
      type: object
      description: Map of locale code to text.
      additionalProperties:
        type: string
      examples:
        - en-us: Sizes
    MediaUrlMap:
      type: object
      description: Map of index ("0", "1", …) to image URL.
      additionalProperties:
        type: string
        format: uri
    PastOrderedItemsResponse:
      type: object
      required: [data]
      properties:
        data:
          type: object
          description: Keyed by product ID; each value lists the distinct configurations of that product the user has ordered.
          propertyNames:
            $ref: '#/components/schemas/Ulid'
          additionalProperties:
            type: array
            items:
              $ref: '#/components/schemas/PastOrderedItem'
    PastOrderedItem:
      type: object
      required: [product_id, selected_mods, last_ordered_at]
      properties:
        product_id:
          $ref: '#/components/schemas/Ulid'
        selected_mods:
          type: array
          items:
            $ref: '#/components/schemas/SelectedModGroup'
        last_ordered_at:
          type: string
          format: date-time
          x-assumed: true
          description: When this configuration was last ordered.
    SelectedModGroup:
      type: object
      required: [parent_id, parent_name, parent_type, selected_child]
      properties:
        parent_id:
          $ref: '#/components/schemas/Ulid'
        parent_name:
          $ref: '#/components/schemas/LocalizedString'
        parent_type:
          type: string
          description: Modifier group type. Seen values select_mod (pick one) and multi_mod (pick many).
          examples: [select_mod, multi_mod]
        selected_child:
          type: array
          items:
            $ref: '#/components/schemas/SelectedModOption'
    SelectedModOption:
      type: object
      required: [selected_id, selected_name, selected_type, selected_price, selected_vat_price, selected_add_on_price, selected_quantity]
      properties:
        selected_id:
          $ref: '#/components/schemas/Ulid'
        selected_name:
          $ref: '#/components/schemas/LocalizedString'
        selected_type:
          type: string
          description: Option type. Seen values size_mod and child_mod.
          examples: [size_mod, child_mod]
        selected_media_url:
          $ref: '#/components/schemas/MediaUrlMap'
        selected_price:
          type: integer
          description: Option price, in minor currency units.
          x-assumed: true
          examples: [1650]
        selected_vat_price:
          type: integer
          description: VAT amount for the option, in minor currency units.
          x-assumed: true
          examples: [0]
        selected_add_on_price:
          type: boolean
          description: Whether selected_price is added on top of the base product price.
          x-assumed: true
        selected_quantity:
          type: integer
          minimum: 1
          examples: [1]
    Error:
      type: object
      x-assumed: true
      properties:
        message:
          type: string