openapi: 3.0.3
info:
  title: BEEP! API
  version: "1.7.0"
  description: |
    Official API specification for the BEEP! Developer Platform.

    All endpoints use POST with JSON body and require Bearer authentication
    with your Secret Key (bk_test_sk_... or bk_live_sk_...).

    Base URL: `https://europe-west6-beep-c6786.cloudfunctions.net/apiGateway/api/v1`
  contact:
    name: BEEP! Developer Support
    email: developer@beep-technologies.de
    url: https://www.beep-technologies.de/developer/
  license:
    name: Proprietary
    url: https://www.beep-technologies.de/developer/docs/quickstart.html

servers:
  - url: https://europe-west6-beep-c6786.cloudfunctions.net/apiGateway/api/v1
    description: Production (europe-west6)

security:
  - BearerAuth: []

components:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      description: "Your BEEP! secret key (bk_test_sk_... or bk_live_sk_...)"

  schemas:
    Store:
      type: object
      properties:
        storeId: { type: string, example: "sandbox_store_001" }
        companyName: { type: string, example: "Sandbox Lebensmittel GmbH" }
        tradingName: { type: string, example: "BioMarkt Berlin" }
        address:
          type: object
          properties:
            street: { type: string }
            city: { type: string }
            zip: { type: string }
            country: { type: string, example: "DE" }
        coordinates:
          type: object
          properties:
            lat: { type: number, example: 52.5200 }
            lng: { type: number, example: 13.4050 }
        hasScanAndGo: { type: boolean }
        package: { type: string, enum: [DISCOVER, ASSIST, GO, GROW, PRIME] }
        securityTagMode: { type: string, enum: [none, manual, station, rfid], default: none, description: "Security tag deactivation mode for Scan & Go" }
        securityTagHint: { type: string, description: "Custom hint text shown to customers about security tag handling (optional)" }

    Product:
      type: object
      properties:
        productId: { type: string }
        ean: { type: string, example: "4000000000001" }
        name: { type: string, example: "Bio-Vollmilch 3,5%" }
        brand: { type: string, example: "BioHof" }
        price: { type: number, example: 1.49 }
        oldPrice: { type: number, description: "Previous price (optional, for sale display)" }
        vat: { type: number, example: 7, description: "VAT percentage" }
        category: { type: string }
        imageUrl: { type: string }
        nutrition:
          type: object
          description: "Optional nutrition data per 100g/100ml (EU Regulation 1169/2011)"
          properties:
            calories: { type: number, description: "Energy in kcal" }
            fat: { type: number, description: "Total fat in grams" }
            saturatedFat: { type: number, description: "Saturated fat in grams" }
            carbohydrates: { type: number, description: "Total carbohydrates in grams" }
            sugar: { type: number, description: "Sugar in grams" }
            protein: { type: number, description: "Protein in grams" }
            fiber: { type: number, description: "Dietary fiber in grams" }
            salt: { type: number, description: "Salt in grams" }
            nutriScore: { type: string, enum: [A, B, C, D, E], description: "Nutri-Score grade" }
            per: { type: string, enum: ["100g", "100ml"], default: "100g" }
            source: { type: string, enum: [merchant, reference, community], description: "Origin of nutrition data: merchant (manually entered), reference (official database e.g. BLS 4.0), community (Open Food Facts)" }
            confidence: { type: number, minimum: 0, maximum: 1, description: "Trust score (0-1) for consolidated nutrition data. Higher values indicate more reliable sources." }

    Offer:
      type: object
      properties:
        offerId: { type: string }
        groupId: { type: string }
        storeIds: { type: array, items: { type: string } }
        title: { type: string }
        description: { type: string }
        products: { type: array, items: { $ref: '#/components/schemas/Product' } }
        validFrom: { type: string, format: date-time }
        validUntil: { type: string, format: date-time }
        storeCount: { type: integer }

    Purchase:
      type: object
      properties:
        transactionId: { type: string }
        storeId: { type: string }
        items:
          type: array
          items:
            type: object
            properties:
              productId: { type: string }
              name: { type: string }
              price: { type: number }
              quantity: { type: integer }
        total: { type: number }
        currency: { type: string, example: "EUR" }
        timestamp: { type: string, format: date-time }
        status: { type: string }
        securityTagMode: { type: string, enum: [none, manual, station, rfid], description: "Security tag mode (only present if configured)" }
        securityTagStatus: { type: string, enum: [pending, deactivated], description: "Security tag deactivation status (only present if securityTagMode != none)" }
        securityTagHint: { type: string, description: "Merchant hint text for security tags (only present if configured)" }

    LoyaltyProgram:
      type: object
      properties:
        programId: { type: string }
        storeId: { type: string }
        name: { type: string }
        type: { type: string, enum: [stamps, points, cashback, tier] }
        earningMethods: { type: array, items: { type: string, enum: [qr_checkin, store_checkin, scan_and_go, click_collect] } }
        isActive: { type: boolean }

    Error:
      type: object
      properties:
        error: { type: string }
        code: { type: string }
        requiredUpgrade: { type: string }
        currentPackage: { type: string }

  responses:
    Unauthorized:
      description: Invalid or missing API key
      content:
        application/json:
          schema: { $ref: '#/components/schemas/Error' }
    Forbidden:
      description: Insufficient package permissions
      content:
        application/json:
          schema: { $ref: '#/components/schemas/Error' }
    RateLimited:
      description: Rate limit exceeded
      content:
        application/json:
          schema: { $ref: '#/components/schemas/Error' }

paths:
  # STORES (DISCOVER+)
  /fetchStores:
    post:
      tags: [Stores]
      summary: List all stores
      description: Returns all stores linked to your developer account.
      operationId: fetchStores
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                city: { type: string, description: "Filter by city" }
                radius: { type: number, description: "Radius in km" }
      responses:
        '200':
          description: Store list
          content:
            application/json:
              schema:
                type: object
                properties:
                  success: { type: boolean }
                  stores: { type: array, items: { $ref: '#/components/schemas/Store' } }
        '401': { $ref: '#/components/responses/Unauthorized' }
        '403': { $ref: '#/components/responses/Forbidden' }

  /fetchStore:
    post:
      tags: [Stores]
      summary: Get a single store
      operationId: fetchStore
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [storeId]
              properties:
                storeId: { type: string }
      responses:
        '200':
          description: Store details
          content:
            application/json:
              schema: { $ref: '#/components/schemas/Store' }
        '401': { $ref: '#/components/responses/Unauthorized' }
        '404': { description: Store not found }

  /submitStoreRegistration:
    post:
      tags: [Stores]
      summary: Register a new store
      operationId: submitStoreRegistration
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [companyName, tradingName, address]
              properties:
                companyName: { type: string }
                tradingName: { type: string }
                address: { type: object }
      responses:
        '200': { description: Registration submitted }
        '401': { $ref: '#/components/responses/Unauthorized' }

  # CATALOG (DISCOVER+)
  /insertProduct:
    post:
      tags: [Catalog]
      summary: Insert a product
      operationId: insertProduct
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [storeId, ean, name, price, vat]
              properties:
                storeId: { type: string }
                ean: { type: string }
                name: { type: string }
                brand: { type: string }
                price: { type: number }
                oldPrice: { type: number }
                vat: { type: number }
                category: { type: string }
      responses:
        '200':
          description: Product created
          content:
            application/json:
              schema: { $ref: '#/components/schemas/Product' }
        '401': { $ref: '#/components/responses/Unauthorized' }

  /fetchProducts:
    post:
      tags: [Catalog]
      summary: List products for a store
      operationId: fetchProducts
      requestBody:
        content:
          application/json:
            schema:
              type: object
              required: [storeId]
              properties:
                storeId: { type: string }
                limit: { type: integer, default: 50 }
                offset: { type: integer, default: 0 }
      responses:
        '200':
          description: Product list
          content:
            application/json:
              schema:
                type: object
                properties:
                  products: { type: array, items: { $ref: '#/components/schemas/Product' } }

  /fetchProduct:
    post:
      tags: [Catalog]
      summary: Get a single product
      operationId: fetchProduct
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [productId]
              properties:
                productId: { type: string }
                storeId: { type: string }
      responses:
        '200':
          description: Product details
          content:
            application/json:
              schema: { $ref: '#/components/schemas/Product' }

  /registerProductToStore:
    post:
      tags: [Catalog]
      summary: Register an existing product to a store
      operationId: registerProductToStore
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [productId, storeId]
              properties:
                productId: { type: string }
                storeId: { type: string }
                price: { type: number }
      responses:
        '200': { description: Product registered to store }

  /uploadImageToProduct:
    post:
      tags: [Catalog]
      summary: Upload an image to a product
      operationId: uploadImageToProduct
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [productId, imageBase64]
              properties:
                productId: { type: string }
                imageBase64: { type: string, description: "Base64-encoded image" }
      responses:
        '200': { description: Image uploaded }

  /bulkImportProducts:
    post:
      tags: [Catalog]
      summary: Bulk import products
      operationId: bulkImportProducts
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [storeId, products]
              properties:
                storeId: { type: string }
                products: { type: array, items: { $ref: '#/components/schemas/Product' } }
      responses:
        '200':
          description: Import result
          content:
            application/json:
              schema:
                type: object
                properties:
                  imported: { type: integer }
                  errors: { type: array, items: { type: object } }

  # OFFERS (GO+)
  /createOffer:
    post:
      tags: [Offers]
      summary: Create a multi-store offer
      operationId: createOffer
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [storeIds, title, products]
              properties:
                storeIds: { type: array, items: { type: string } }
                title: { type: string }
                description: { type: string }
                products: { type: array, items: { type: object } }
                validFrom: { type: string, format: date-time }
                validUntil: { type: string, format: date-time }
      responses:
        '200':
          description: Offer created
          content:
            application/json:
              schema: { $ref: '#/components/schemas/Offer' }
        '403': { $ref: '#/components/responses/Forbidden' }

  /updateOffer:
    post:
      tags: [Offers]
      summary: Update an offer (propagates to all stores in group)
      operationId: updateOffer
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [offerId]
              properties:
                offerId: { type: string }
                title: { type: string }
                products: { type: array, items: { type: object } }
                storeIds: { type: array, items: { type: string } }
      responses:
        '200': { description: Offer updated }

  /deleteOffer:
    post:
      tags: [Offers]
      summary: Delete an offer (deletes all branch copies)
      operationId: deleteOffer
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [offerId]
              properties:
                offerId: { type: string }
      responses:
        '200': { description: Offer deleted }

  /getManagerOffers:
    post:
      tags: [Offers]
      summary: List offers for a merchant (deduplicated by groupId)
      operationId: getManagerOffers
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                status: { type: string, enum: [active, expired, draft] }
      responses:
        '200':
          description: Offer list
          content:
            application/json:
              schema:
                type: object
                properties:
                  offers: { type: array, items: { $ref: '#/components/schemas/Offer' } }

  /cloneOffer:
    post:
      tags: [Offers]
      summary: Clone an offer to additional stores
      operationId: cloneOffer
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [offerId, targetStoreIds]
              properties:
                offerId: { type: string }
                targetStoreIds: { type: array, items: { type: string } }
                priceAdjustments: { type: object, description: "Per-store price overrides" }
      responses:
        '200': { description: Offer cloned }

  # CLICK & COLLECT (GO+)
  /submitClickCollectOrder:
    post:
      tags: [Click & Collect]
      summary: Submit a C&C order
      operationId: submitClickCollectOrder
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [storeId, items]
              properties:
                storeId: { type: string }
                items: { type: array, items: { type: object } }
                pickupTime: { type: string }
      responses:
        '200': { description: Order submitted }

  /updateClickCollectStatus:
    post:
      tags: [Click & Collect]
      summary: Update order status
      operationId: updateClickCollectStatus
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [orderId, status]
              properties:
                orderId: { type: string }
                status: { type: string, enum: [accepted, preparing, ready, picked_up, cancelled] }
      responses:
        '200': { description: Status updated }

  # SCAN & GO (GROW+)
  /checkIn:
    post:
      tags: [Scan & Go]
      summary: Check in a customer at a store
      operationId: checkIn
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [storeId]
              properties:
                storeId: { type: string }
                userId: { type: string }
      responses:
        '200':
          description: Session created
          content:
            application/json:
              schema:
                type: object
                properties:
                  sessionId: { type: string }
        '403': { $ref: '#/components/responses/Forbidden' }

  /startCheckout:
    post:
      tags: [Scan & Go]
      summary: Start a checkout session
      operationId: startCheckout
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [sessionId, items]
              properties:
                sessionId: { type: string }
                items: { type: array, items: { type: object } }
                currency: { type: string, default: "EUR" }
                destination: { type: string, description: "Optional destination" }
      responses:
        '200':
          description: Checkout started
          content:
            application/json:
              schema: { $ref: '#/components/schemas/Purchase' }

  /fetchPurchase:
    post:
      tags: [Scan & Go]
      summary: Get purchase details
      operationId: fetchPurchase
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [transactionId]
              properties:
                transactionId: { type: string }
      responses:
        '200':
          description: Purchase details
          content:
            application/json:
              schema: { $ref: '#/components/schemas/Purchase' }

  /fetchPurchaseHistory:
    post:
      tags: [Scan & Go]
      summary: Get purchase history for a store
      operationId: fetchPurchaseHistory
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [storeId]
              properties:
                storeId: { type: string }
                limit: { type: integer, default: 20 }
                offset: { type: integer, default: 0 }
      responses:
        '200':
          description: Purchase list
          content:
            application/json:
              schema:
                type: object
                properties:
                  purchases: { type: array, items: { $ref: '#/components/schemas/Purchase' } }
                  total: { type: integer }

  /verifySecurityTagDeactivation:
    post:
      tags: [Scan & Go]
      summary: Verify security tag deactivation for a purchase
      description: |
        Checks whether a purchase has been paid and authorizes security tag
        deactivation. Used by deactivation stations (station mode) or RFID
        gates. Returns item list and deactivation authorization.
      operationId: verifySecurityTagDeactivation
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                purchaseId: { type: string, description: "Firestore purchase document ID" }
                receiptToken: { type: string, description: "Session/receipt token (alternative to purchaseId)" }
      responses:
        '200':
          description: Deactivation verification result
          content:
            application/json:
              schema:
                type: object
                properties:
                  success: { type: boolean }
                  status: { type: string, enum: [paid, CREATED, PENDING_PAYMENT, CANCELLED] }
                  items: { type: array, items: { type: object } }
                  securityTagMode: { type: string, enum: [none, manual, station, rfid] }
                  deactivationAuthorized: { type: boolean, description: "true if purchase is paid and security tags are configured" }
                  storeData: { type: object }
        '400': { description: "purchaseId or receiptToken is required" }
        '404': { description: "Purchase not found" }
        '403': { $ref: '#/components/responses/Forbidden' }

  # LOYALTY (GO+)
  /createLoyaltyProgram:
    post:
      tags: [Loyalty]
      summary: Create a loyalty program
      operationId: createLoyaltyProgram
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [storeId, name, type]
              properties:
                storeId: { type: string }
                name: { type: string }
                type: { type: string, enum: [stamps, points, cashback, tier] }
                earningMethods: { type: array, items: { type: string, enum: [qr_checkin, store_checkin, scan_and_go, click_collect] } }
      responses:
        '200':
          description: Program created
          content:
            application/json:
              schema: { $ref: '#/components/schemas/LoyaltyProgram' }
        '403': { $ref: '#/components/responses/Forbidden' }

  /updateLoyaltyProgram:
    post:
      tags: [Loyalty]
      summary: Update a loyalty program
      operationId: updateLoyaltyProgram
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [programId]
              properties:
                programId: { type: string }
                name: { type: string }
                earningMethods: { type: array, items: { type: string } }
      responses:
        '200': { description: Program updated }

  /getLoyaltyProgram:
    post:
      tags: [Loyalty]
      summary: Get a loyalty program
      operationId: getLoyaltyProgram
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [programId]
              properties:
                programId: { type: string }
      responses:
        '200':
          description: Program details
          content:
            application/json:
              schema: { $ref: '#/components/schemas/LoyaltyProgram' }

  /getStoreLoyaltyPrograms:
    post:
      tags: [Loyalty]
      summary: List loyalty programs for a store
      operationId: getStoreLoyaltyPrograms
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [storeId]
              properties:
                storeId: { type: string }
      responses:
        '200':
          description: Program list
          content:
            application/json:
              schema:
                type: object
                properties:
                  programs: { type: array, items: { $ref: '#/components/schemas/LoyaltyProgram' } }

  /getLoyaltyPrograms:
    get:
      tags: [Loyalty]
      summary: List loyalty programs for a store (GET variant)
      operationId: getLoyaltyPrograms
      parameters:
        - name: storeId
          in: query
          required: true
          schema: { type: string }
      responses:
        '200':
          description: Program list
          content:
            application/json:
              schema:
                type: object
                properties:
                  status: { type: string }
                  data: { type: array, items: { $ref: '#/components/schemas/LoyaltyProgram' } }

  /enrollInLoyaltyProgram:
    post:
      tags: [Loyalty]
      summary: Enroll a user in a loyalty program
      operationId: enrollInLoyaltyProgram
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [programId, userId]
              properties:
                programId: { type: string }
                userId: { type: string }
      responses:
        '200': { description: User enrolled }

  /addLoyaltyPoints:
    post:
      tags: [Loyalty]
      summary: Add points or stamps to a user
      operationId: addLoyaltyPoints
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [programId, userId, points]
              properties:
                programId: { type: string }
                userId: { type: string }
                points: { type: number }
                source: { type: string, enum: [qr_checkin, store_checkin, scan_and_go, click_collect] }
      responses:
        '200': { description: Points added }

  /redeemLoyaltyPoints:
    post:
      tags: [Loyalty]
      summary: Redeem points or stamps
      operationId: redeemLoyaltyPoints
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [programId, userId, points]
              properties:
                programId: { type: string }
                userId: { type: string }
                points: { type: number }
      responses:
        '200': { description: Points redeemed }

  /getCustomerBalance:
    post:
      tags: [Loyalty]
      summary: Get a customer's loyalty balance and tier
      operationId: getCustomerBalance
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [programId, userId]
              properties:
                programId: { type: string }
                userId: { type: string }
      responses:
        '200':
          description: Balance info
          content:
            application/json:
              schema:
                type: object
                properties:
                  balance: { type: number }
                  tier: { type: string }

  /getLoyaltyAnalytics:
    post:
      tags: [Loyalty]
      summary: Get analytics for a loyalty program
      operationId: getLoyaltyAnalytics
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [programId]
              properties:
                programId: { type: string }
      responses:
        '200': { description: Loyalty analytics data }

  /syncExternalLoyalty:
    post:
      tags: [Loyalty]
      summary: Sync points from an external system (PRIME)
      operationId: syncExternalLoyalty
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [programId, externalSystemId, data]
              properties:
                programId: { type: string }
                externalSystemId: { type: string }
                data: { type: object }
      responses:
        '200': { description: Sync complete }
        '403': { $ref: '#/components/responses/Forbidden' }

  /getLoyaltyWebhookEvents:
    post:
      tags: [Loyalty]
      summary: Register or list loyalty webhook configurations
      operationId: getLoyaltyWebhookEvents
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [storeId, url, events]
              properties:
                storeId: { type: string }
                url: { type: string, format: uri }
                events:
                  type: array
                  items:
                    type: string
                    enum: [loyalty.points_earned, loyalty.points_redeemed, loyalty.tier_changed, loyalty.enrollment, loyalty.reward_unlocked, loyalty.checkin_earned, loyalty.qr_earned, loyalty.external_synced]
                secret: { type: string }
      responses:
        '200':
          description: Webhook registered or listed
          content:
            application/json:
              schema:
                type: object
                properties:
                  status: { type: string }
                  id: { type: string }
                  message: { type: string }

  # INTEGRATIONS (GROW+)
  /syncPOS:
    post:
      tags: [Integrations]
      summary: Sync catalog from POS to BEEP!
      operationId: syncPOS
      requestBody:
        content:
          application/json:
            schema:
              type: object
              required: [storeId, data]
              properties:
                storeId: { type: string }
                provider: { type: string }
                data: { type: object }
      responses:
        '200': { description: Sync complete }
        '403': { $ref: '#/components/responses/Forbidden' }

  /pushToPOS:
    post:
      tags: [Integrations]
      summary: Push data from BEEP! to POS
      operationId: pushToPOS
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [storeId, data]
              properties:
                storeId: { type: string }
                data: { type: object }
      responses:
        '200': { description: Push complete }

  /syncERP:
    post:
      tags: [Integrations]
      summary: Sync data from ERP to BEEP!
      operationId: syncERP
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [storeId, data]
              properties:
                storeId: { type: string }
                provider: { type: string }
                data: { type: object }
      responses:
        '200': { description: Sync complete }

  /pushToERP:
    post:
      tags: [Integrations]
      summary: Push data from BEEP! to ERP
      operationId: pushToERP
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [storeId, data]
              properties:
                storeId: { type: string }
                data: { type: object }
      responses:
        '200': { description: Push complete }

  /configurePSP:
    post:
      tags: [Integrations]
      summary: Configure a Payment Service Provider
      operationId: configurePSP
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [storeId, provider, credentials]
              properties:
                storeId: { type: string }
                provider: { type: string, example: "stripe" }
                credentials: { type: object }
      responses:
        '200': { description: PSP configured }

  /processPayment:
    post:
      tags: [Integrations]
      summary: Process a payment
      operationId: processPayment
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [storeId, amount, currency]
              properties:
                storeId: { type: string }
                amount: { type: number }
                currency: { type: string, default: "EUR" }
      responses:
        '200': { description: Payment processed }

  /refundPayment:
    post:
      tags: [Integrations]
      summary: Initiate a refund
      operationId: refundPayment
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [storeId, transactionId]
              properties:
                storeId: { type: string }
                transactionId: { type: string }
                amount: { type: number, description: "Partial refund amount (omit for full refund)" }
      responses:
        '200': { description: Refund initiated }

  # ANALYTICS (GO+ / GROW+)
  /getAnalytics:
    post:
      tags: [Analytics]
      summary: Get store KPIs
      operationId: getAnalytics
      requestBody:
        content:
          application/json:
            schema:
              type: object
              required: [storeId]
              properties:
                storeId: { type: string }
                from: { type: string, format: date }
                to: { type: string, format: date }
      responses:
        '200':
          description: Analytics data
          content:
            application/json:
              schema:
                type: object
                properties:
                  revenue: { type: number }
                  transactions: { type: integer }
                  avgBasketSize: { type: number }
                  peakHour: { type: integer }

  /exportSalesData:
    post:
      tags: [Analytics]
      summary: Export sales data (revenue, transactions, top products)
      operationId: exportSalesData
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [storeId]
              properties:
                storeId: { type: string }
                from: { type: string, format: date }
                to: { type: string, format: date }
      responses:
        '200': { description: Sales export data }
        '403': { $ref: '#/components/responses/Forbidden' }

  /exportReceiptData:
    post:
      tags: [Analytics]
      summary: Export receipt and TSE data
      operationId: exportReceiptData
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [storeId]
              properties:
                storeId: { type: string }
                from: { type: string, format: date }
                to: { type: string, format: date }
      responses:
        '200': { description: Receipt export data }
        '403': { $ref: '#/components/responses/Forbidden' }
