openapi: 3.0.3
info:
  title: Prediction Market API
  description: |
    Operator integration API for the Prediction Market Engine.

    All authenticated endpoints require the `X-Api-Key` header.
    The API uses a consistent response envelope with `success` and `data` (or `error`) fields.
  version: 1.0.0
  contact:
    name: Prediction Market Platform

servers:
  - url: https://polymarket.sandbox.playbatman.com
    description: Sandbox environment
  - url: https://polymarket.sandbox.playbatman.com
    description: Local development

security:
  - ApiKeyAuth: []

components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-Api-Key
      description: Operator API key

  schemas:
    # ── Common ────────────────────────────────────────────────
    ErrorResponse:
      type: object
      properties:
        success:
          type: boolean
          example: false
        error:
          type: object
          properties:
            code:
              type: string
              example: MARKET_NOT_FOUND
            message:
              type: string
              example: "Market with id abc-123 not found"
            details:
              type: object

    # ── Market ────────────────────────────────────────────────
    MarketOutcomeInput:
      type: object
      required: [name]
      properties:
        name:
          type: string
          example: "Yes"
        description:
          type: string
          example: "The event occurs"

    MarketOutcome:
      type: object
      properties:
        id:
          type: string
          format: uuid
        name:
          type: string
        description:
          type: string
        index:
          type: integer
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time

    CategoryInfo:
      type: object
      properties:
        id:
          type: string
          format: uuid
        name:
          type: string
        slug:
          type: string

    Market:
      type: object
      properties:
        id:
          type: string
          format: uuid
        operatorId:
          type: string
          format: uuid
        categoryId:
          type: string
          format: uuid
          nullable: true
        title:
          type: string
        description:
          type: string
          nullable: true
        imageUrl:
          type: string
          nullable: true
        status:
          type: string
          enum: [DRAFT, UPCOMING, OPEN, SUSPENDED, CLOSED, RESOLVED, SETTLED, CANCELLED]
        currency:
          type: string
          example: "USD"
        tradingStartsAt:
          type: string
          format: date-time
          nullable: true
        tradingEndsAt:
          type: string
          format: date-time
          nullable: true
        resolvedAt:
          type: string
          format: date-time
          nullable: true
        winningOutcomeId:
          type: string
          format: uuid
          nullable: true
        resolutionSource:
          type: string
          nullable: true
        resolutionNotes:
          type: string
          nullable: true
        totalVolume:
          type: string
          example: "0"
        totalTrades:
          type: integer
          example: 0
        metadata:
          type: object
          nullable: true
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
        outcomes:
          type: array
          items:
            $ref: '#/components/schemas/MarketOutcome'
        category:
          $ref: '#/components/schemas/CategoryInfo'

    # ── Category ──────────────────────────────────────────────
    Category:
      type: object
      properties:
        id:
          type: string
          format: uuid
        operatorId:
          type: string
          format: uuid
          nullable: true
        name:
          type: string
        slug:
          type: string
        description:
          type: string
          nullable: true
        iconUrl:
          type: string
          nullable: true
        isActive:
          type: boolean
        sortOrder:
          type: integer
        createdAt:
          type: string
          format: date-time

    # ── Order ─────────────────────────────────────────────────
    Order:
      type: object
      properties:
        id:
          type: string
          format: uuid
        marketId:
          type: string
          format: uuid
        outcomeId:
          type: string
          format: uuid
        operatorId:
          type: string
          format: uuid
        playerId:
          type: string
        side:
          type: string
          enum: [BUY, SELL]
        type:
          type: string
          enum: [MARKET, LIMIT]
        shares:
          type: string
          example: "100"
        price:
          type: string
          nullable: true
          example: "0.65"
        filledShares:
          type: string
          example: "50"
        avgFillPrice:
          type: string
          nullable: true
          example: "0.63"
        remainingShares:
          type: string
          example: "50"
        status:
          type: string
          enum: [PENDING, PARTIAL, FILLED, CANCELLED, EXPIRED, REJECTED]
        transactionId:
          type: string
          nullable: true
        expiresAt:
          type: string
          format: date-time
          nullable: true
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time

    # ── Trade ─────────────────────────────────────────────────
    Trade:
      type: object
      properties:
        id:
          type: string
          format: uuid
        marketId:
          type: string
          format: uuid
        outcomeId:
          type: string
          format: uuid
        buyOrderId:
          type: string
          format: uuid
        sellOrderId:
          type: string
          format: uuid
        buyerOperatorId:
          type: string
          format: uuid
        sellerOperatorId:
          type: string
          format: uuid
        price:
          type: string
          example: "0.65"
        shares:
          type: string
          example: "30"
        buyerFee:
          type: string
          example: "0.39"
        sellerFee:
          type: string
          example: "0.39"
        createdAt:
          type: string
          format: date-time

    # ── Position ──────────────────────────────────────────────
    Position:
      type: object
      properties:
        id:
          type: string
          format: uuid
        marketId:
          type: string
          format: uuid
        outcomeId:
          type: string
          format: uuid
        operatorId:
          type: string
          format: uuid
        playerId:
          type: string
          description: Player identifier
          example: "player-123"
        shares:
          type: string
          example: "150"
        avgPrice:
          type: string
          example: "0.62"
        totalCost:
          type: string
          example: "93"
        realizedPnl:
          type: string
          example: "0"
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time

    # ── Settlement ────────────────────────────────────────────
    Settlement:
      type: object
      properties:
        id:
          type: string
          format: uuid
        positionId:
          type: string
          format: uuid
        marketId:
          type: string
          format: uuid
        outcomeId:
          type: string
          format: uuid
        operatorId:
          type: string
          format: uuid
        playerId:
          type: string
          description: Player identifier
          example: "player-123"
        shares:
          type: string
          example: "100"
        payoutPerShare:
          type: string
          example: "1"
        totalPayout:
          type: string
          example: "100"
        transactionId:
          type: string
          nullable: true
        status:
          type: string
          enum: [PENDING, PROCESSING, COMPLETED, FAILED]
        errorMessage:
          type: string
          nullable: true
        settledAt:
          type: string
          format: date-time
          nullable: true
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time

    # ── Market Data ───────────────────────────────────────────
    PriceLevel:
      type: object
      properties:
        price:
          type: number
          example: 0.65
        shares:
          type: number
          example: 150
        orderCount:
          type: integer
          example: 3

    OrderBookSnapshot:
      type: object
      properties:
        marketId:
          type: string
          format: uuid
        outcomeId:
          type: string
          format: uuid
        bids:
          type: array
          items:
            $ref: '#/components/schemas/PriceLevel'
        asks:
          type: array
          items:
            $ref: '#/components/schemas/PriceLevel'
        bestBid:
          type: number
          nullable: true
          example: 0.65
        bestAsk:
          type: number
          nullable: true
          example: 0.68
        spread:
          type: number
          nullable: true
          example: 0.03
        timestamp:
          type: integer
          format: int64

    MarketPrice:
      type: object
      properties:
        marketId:
          type: string
          format: uuid
        outcomeId:
          type: string
          format: uuid
        outcomeName:
          type: string
        bestBid:
          type: number
          example: 0.65
        bestAsk:
          type: number
          example: 0.68
        lastPrice:
          type: number
          example: 0.66
        midPrice:
          type: number
          example: 0.665
        spread:
          type: number
          example: 0.03
        volume24h:
          type: number
          example: 5000

    Webhook:
      type: object
      properties:
        id:
          type: string
          format: uuid
        operatorId:
          type: string
          format: uuid
        url:
          type: string
          format: uri
          example: https://example.com/webhooks/prediction
        secret:
          type: string
          description: HMAC-SHA256 signing secret (only shown in full at creation time)
          example: "a1b2c3...truncated"
        events:
          type: array
          items:
            $ref: '#/components/schemas/EventType'
          description: Event types this webhook receives (empty = all)
        isActive:
          type: boolean
          example: true
        description:
          type: string
          example: Production webhook
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time

    OperatorEvent:
      type: object
      properties:
        id:
          type: string
          format: uuid
        sequence:
          type: integer
          description: Monotonically increasing sequence number
          example: 42
        operatorId:
          type: string
          format: uuid
        eventType:
          $ref: '#/components/schemas/EventType'
        marketId:
          type: string
          format: uuid
          nullable: true
        payload:
          type: object
          description: Event-specific data
        createdAt:
          type: string
          format: date-time
        expiresAt:
          type: string
          format: date-time

    EventType:
      type: string
      enum:
        - MARKET_CREATED
        - MARKET_STATUS_CHANGED
        - MARKET_RESOLVED
        - ORDER_BOOK_UPDATE
        - PRICE_UPDATED
        - ORDER_PLACED
        - ORDER_MATCHED
        - ORDER_CANCELLED
        - POSITION_UPDATED
        - SETTLEMENT_COMPLETED

    WebhookDeliveryPayload:
      type: object
      description: Payload delivered to webhook URLs via HTTP POST
      properties:
        id:
          type: string
          format: uuid
          description: Unique delivery ID
        event:
          $ref: '#/components/schemas/EventType'
        timestamp:
          type: integer
          description: Unix timestamp in milliseconds
        data:
          type: object
          description: Event-specific payload data

paths:
  # ════════════════════════════════════════════════════════════
  # Health
  # ════════════════════════════════════════════════════════════
  /health:
    get:
      tags: [Health]
      summary: Health check
      security: []
      operationId: healthCheck
      responses:
        '200':
          description: Service is healthy
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: healthy
                  service:
                    type: string
                    example: prediction-market
                  version:
                    type: string
                    example: "1.0.0"
                  timestamp:
                    type: string
                    format: date-time

  /ready:
    get:
      tags: [Health]
      summary: Readiness check
      security: []
      operationId: readyCheck
      responses:
        '200':
          description: Service is ready
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: ready
                  timestamp:
                    type: string
                    format: date-time

  # ════════════════════════════════════════════════════════════
  # Markets
  # ════════════════════════════════════════════════════════════
  /api/v1/markets:
    post:
      tags: [Markets]
      summary: Create market
      operationId: createMarket
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [title]
              properties:
                title:
                  type: string
                  example: "Will it rain tomorrow?"
                description:
                  type: string
                categoryId:
                  type: string
                  format: uuid
                imageUrl:
                  type: string
                currency:
                  type: string
                  description: "Currency code. Must be one of the operator's supported currencies."
                  example: "USD"
                tradingStartsAt:
                  type: string
                  format: date-time
                tradingEndsAt:
                  type: string
                  format: date-time
                outcomes:
                  type: array
                  items:
                    $ref: '#/components/schemas/MarketOutcomeInput'
                metadata:
                  type: object
      responses:
        '201':
          description: Market created
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  data:
                    $ref: '#/components/schemas/Market'
        '400':
          description: Validation error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'

    get:
      tags: [Markets]
      summary: List markets
      operationId: listMarkets
      parameters:
        - name: categoryId
          in: query
          schema:
            type: string
        - name: status
          in: query
          description: Comma-separated statuses (e.g. OPEN,CLOSED)
          schema:
            type: string
        - name: search
          in: query
          schema:
            type: string
        - name: cursor
          in: query
          schema:
            type: string
        - name: limit
          in: query
          schema:
            type: integer
            default: 20
      responses:
        '200':
          description: Markets list
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      markets:
                        type: array
                        items:
                          $ref: '#/components/schemas/Market'
                      total:
                        type: integer
                      hasMore:
                        type: boolean
                      nextCursor:
                        type: string
                        nullable: true

  /api/v1/markets/{id}:
    get:
      tags: [Markets]
      summary: Get market
      operationId: getMarket
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Market details
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    $ref: '#/components/schemas/Market'
        '404':
          description: Market not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'

    patch:
      tags: [Markets]
      summary: Update market
      operationId: updateMarket
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                title:
                  type: string
                description:
                  type: string
                imageUrl:
                  type: string
                categoryId:
                  type: string
                  format: uuid
                tradingStartsAt:
                  type: string
                  format: date-time
                tradingEndsAt:
                  type: string
                  format: date-time
                metadata:
                  type: object
      responses:
        '200':
          description: Market updated
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    $ref: '#/components/schemas/Market'

  /api/v1/markets/{id}/open:
    post:
      tags: [Markets]
      summary: Open market for trading
      operationId: openMarket
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Market opened
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    $ref: '#/components/schemas/Market'

  /api/v1/markets/{id}/suspend:
    post:
      tags: [Markets]
      summary: Suspend market trading
      operationId: suspendMarket
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [reason]
              properties:
                reason:
                  type: string
                  example: "Irregular trading activity detected"
      responses:
        '200':
          description: Market suspended
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    $ref: '#/components/schemas/Market'

  /api/v1/markets/{id}/resume:
    post:
      tags: [Markets]
      summary: Resume suspended market
      operationId: resumeMarket
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Market resumed
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    $ref: '#/components/schemas/Market'

  /api/v1/markets/{id}/close:
    post:
      tags: [Markets]
      summary: Close market
      operationId: closeMarket
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Market closed
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    $ref: '#/components/schemas/Market'

  /api/v1/markets/{id}/resolve:
    post:
      tags: [Markets]
      summary: Resolve market with winning outcome
      operationId: resolveMarket
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [winningOutcomeId, resolutionSource]
              properties:
                winningOutcomeId:
                  type: string
                  format: uuid
                resolutionSource:
                  type: string
                  example: "Official match result"
                resolutionNotes:
                  type: string
                  example: "Team A won 3-1"
      responses:
        '200':
          description: Market resolved
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    $ref: '#/components/schemas/Market'

  /api/v1/markets/{id}/cancel:
    post:
      tags: [Markets]
      summary: Cancel market
      operationId: cancelMarket
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [reason]
              properties:
                reason:
                  type: string
                  example: "Event cancelled"
      responses:
        '200':
          description: Market cancelled
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    $ref: '#/components/schemas/Market'

  # ════════════════════════════════════════════════════════════
  # Categories
  # ════════════════════════════════════════════════════════════
  /api/v1/categories:
    post:
      tags: [Categories]
      summary: Create category
      operationId: createCategory
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [name, slug]
              properties:
                name:
                  type: string
                  example: "Sports"
                slug:
                  type: string
                  example: "sports"
                description:
                  type: string
                iconUrl:
                  type: string
                sortOrder:
                  type: integer
      responses:
        '201':
          description: Category created
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    $ref: '#/components/schemas/Category'

    get:
      tags: [Categories]
      summary: List categories
      operationId: listCategories
      parameters:
        - name: includeGlobal
          in: query
          schema:
            type: boolean
            default: true
        - name: activeOnly
          in: query
          schema:
            type: boolean
            default: true
      responses:
        '200':
          description: Categories list
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Category'

  /api/v1/categories/{id}:
    get:
      tags: [Categories]
      summary: Get category
      operationId: getCategory
      security: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Category details
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    $ref: '#/components/schemas/Category'

  # ════════════════════════════════════════════════════════════
  # Orders
  # ════════════════════════════════════════════════════════════
  /api/v1/orders:
    post:
      tags: [Orders]
      summary: Place order
      operationId: placeOrder
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [marketId, outcomeId, playerId, side, type, shares]
              properties:
                marketId:
                  type: string
                  format: uuid
                outcomeId:
                  type: string
                  format: uuid
                playerId:
                  type: string
                  description: Operator-defined player identifier
                  example: "player-123"
                side:
                  type: string
                  enum: [BUY, SELL]
                type:
                  type: string
                  enum: [MARKET, LIMIT]
                shares:
                  type: number
                  minimum: 1
                  maximum: 100000
                  example: 50
                price:
                  type: number
                  minimum: 0.01
                  maximum: 0.99
                  description: Required for LIMIT orders
                  example: 0.65
                transactionId:
                  type: string
                  description: Operator-provided reference / idempotency key
                  example: "txn-abc-123"
                expiresAt:
                  type: string
                  format: date-time
      responses:
        '201':
          description: Order placed
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      order:
                        $ref: '#/components/schemas/Order'
                      trades:
                        type: array
                        items:
                          $ref: '#/components/schemas/Trade'
                      status:
                        type: string
                        enum: [PENDING, PARTIAL, FILLED, REJECTED]
                      filledShares:
                        type: string
                      avgFillPrice:
                        type: string
                        nullable: true
                      remainingShares:
                        type: string
        '400':
          description: Validation error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'

    get:
      tags: [Orders]
      summary: List orders
      operationId: listOrders
      parameters:
        - name: playerId
          in: query
          schema:
            type: string
        - name: marketId
          in: query
          schema:
            type: string
        - name: outcomeId
          in: query
          schema:
            type: string
        - name: side
          in: query
          schema:
            type: string
            enum: [BUY, SELL]
        - name: type
          in: query
          schema:
            type: string
            enum: [MARKET, LIMIT]
        - name: status
          in: query
          description: Comma-separated statuses (e.g. PENDING,PARTIAL)
          schema:
            type: string
        - name: cursor
          in: query
          schema:
            type: string
        - name: limit
          in: query
          schema:
            type: integer
      responses:
        '200':
          description: Orders list
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      orders:
                        type: array
                        items:
                          $ref: '#/components/schemas/Order'
                      total:
                        type: integer
                      hasMore:
                        type: boolean
                      nextCursor:
                        type: string
                        nullable: true

  /api/v1/orders/{orderId}:
    get:
      tags: [Orders]
      summary: Get order
      operationId: getOrder
      parameters:
        - name: orderId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Order details
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    $ref: '#/components/schemas/Order'

    delete:
      tags: [Orders]
      summary: Cancel order
      operationId: cancelOrder
      parameters:
        - name: orderId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Order cancelled
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    $ref: '#/components/schemas/Order'
        '400':
          description: Order cannot be cancelled
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'

  # ════════════════════════════════════════════════════════════
  # Positions
  # ════════════════════════════════════════════════════════════
  /api/v1/positions:
    get:
      tags: [Positions]
      summary: Get positions
      operationId: getPositions
      parameters:
        - name: marketId
          in: query
          schema:
            type: string
            format: uuid
        - name: playerId
          in: query
          description: Filter positions by player
          schema:
            type: string
      responses:
        '200':
          description: Positions list
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Position'

  # ════════════════════════════════════════════════════════════
  # Trades
  # ════════════════════════════════════════════════════════════
  /api/v1/trades:
    get:
      tags: [Trades]
      summary: List trades
      operationId: listTrades
      parameters:
        - name: marketId
          in: query
          schema:
            type: string
        - name: outcomeId
          in: query
          schema:
            type: string
        - name: cursor
          in: query
          schema:
            type: string
        - name: limit
          in: query
          schema:
            type: integer
      responses:
        '200':
          description: Trades list
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      trades:
                        type: array
                        items:
                          $ref: '#/components/schemas/Trade'
                      total:
                        type: integer
                      hasMore:
                        type: boolean
                      nextCursor:
                        type: string
                        nullable: true

  # ════════════════════════════════════════════════════════════
  # Market Data (Public)
  # ════════════════════════════════════════════════════════════
  /api/v1/markets/{id}/orderbook/{outcomeId}:
    get:
      tags: [Market Data]
      summary: Get order book
      operationId: getOrderBook
      security: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
        - name: outcomeId
          in: path
          required: true
          schema:
            type: string
            format: uuid
        - name: depth
          in: query
          schema:
            type: integer
            default: 10
      responses:
        '200':
          description: Order book snapshot
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    $ref: '#/components/schemas/OrderBookSnapshot'

  /api/v1/markets/{id}/prices:
    get:
      tags: [Market Data]
      summary: Get all market prices
      operationId: getMarketPrices
      security: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Prices for all outcomes
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/MarketPrice'

  /api/v1/markets/{id}/prices/{outcomeId}:
    get:
      tags: [Market Data]
      summary: Get outcome price
      operationId: getOutcomePrice
      security: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
        - name: outcomeId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Price data for outcome
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    $ref: '#/components/schemas/MarketPrice'

  # ════════════════════════════════════════════════════════════
  # Stats
  # ════════════════════════════════════════════════════════════
  /api/v1/stats/overview:
    get:
      tags: [Stats]
      summary: Operator statistics overview
      operationId: getStatsOverview
      responses:
        '200':
          description: Stats overview
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      openMarkets:
                        type: integer
                      pendingResolution:
                        type: integer
                      resolved:
                        type: integer

  # ════════════════════════════════════════════════════════════
  # Settlements
  # ════════════════════════════════════════════════════════════
  /api/v1/markets/{id}/settle:
    post:
      tags: [Settlements]
      summary: Settle resolved market
      operationId: settleMarket
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Settlement result
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      marketId:
                        type: string
                        format: uuid
                      totalPositions:
                        type: integer
                      successCount:
                        type: integer
                      failedCount:
                        type: integer
                      totalPayout:
                        type: string
                      settlements:
                        type: array
                        items:
                          $ref: '#/components/schemas/Settlement'
                      errors:
                        type: array
                        items:
                          type: object
                          properties:
                            positionId:
                              type: string
                            error:
                              type: string
                      cancelledOrders:
                        type: integer

  /api/v1/markets/{id}/settlement-status:
    get:
      tags: [Settlements]
      summary: Get settlement status
      operationId: getSettlementStatus
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Settlement status
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      marketId:
                        type: string
                        format: uuid
                      totalPositions:
                        type: integer
                      pendingCount:
                        type: integer
                      processingCount:
                        type: integer
                      completedCount:
                        type: integer
                      failedCount:
                        type: integer
                      totalPayout:
                        type: string
                      completedPayout:
                        type: string

  /api/v1/markets/{id}/retry-settlements:
    post:
      tags: [Settlements]
      summary: Retry failed settlements
      operationId: retrySettlements
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Retry result
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      marketId:
                        type: string
                        format: uuid
                      totalPositions:
                        type: integer
                      successCount:
                        type: integer
                      failedCount:
                        type: integer
                      totalPayout:
                        type: string
                      settlements:
                        type: array
                        items:
                          $ref: '#/components/schemas/Settlement'
                      errors:
                        type: array
                        items:
                          type: object
                          properties:
                            positionId:
                              type: string
                            error:
                              type: string

  /api/v1/settlements:
    get:
      tags: [Settlements]
      summary: Get operator settlements
      operationId: getOperatorSettlements
      parameters:
        - name: marketId
          in: query
          schema:
            type: string
            format: uuid
        - name: playerId
          in: query
          description: Filter settlements by player
          schema:
            type: string
      responses:
        '200':
          description: Settlements list
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Settlement'

  # ════════════════════════════════════════════════════════════
  # Webhooks
  # ════════════════════════════════════════════════════════════
  /api/v1/webhooks:
    post:
      tags: [Webhooks]
      summary: Register a webhook
      operationId: createWebhook
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [url]
              properties:
                url:
                  type: string
                  format: uri
                  description: HTTPS URL to receive POST deliveries
                  example: https://example.com/webhooks/prediction
                events:
                  type: array
                  items:
                    $ref: '#/components/schemas/EventType'
                  description: Event types to subscribe to (empty = all)
                description:
                  type: string
                  example: Production webhook
      responses:
        '201':
          description: Webhook created (secret shown in full only once)
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    $ref: '#/components/schemas/Webhook'
        '400':
          description: Invalid input

    get:
      tags: [Webhooks]
      summary: List operator webhooks
      operationId: listWebhooks
      responses:
        '200':
          description: Webhooks list (secrets truncated)
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Webhook'

  /api/v1/webhooks/{id}:
    patch:
      tags: [Webhooks]
      summary: Update a webhook
      operationId: updateWebhook
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                url:
                  type: string
                  format: uri
                events:
                  type: array
                  items:
                    $ref: '#/components/schemas/EventType'
                isActive:
                  type: boolean
                description:
                  type: string
      responses:
        '200':
          description: Webhook updated
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    $ref: '#/components/schemas/Webhook'
        '404':
          description: Webhook not found

    delete:
      tags: [Webhooks]
      summary: Delete a webhook
      operationId: deleteWebhook
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Webhook deleted
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      message:
                        type: string
                        example: Webhook deleted
        '404':
          description: Webhook not found

  # ════════════════════════════════════════════════════════════
  # Events (Replay)
  # ════════════════════════════════════════════════════════════
  /api/v1/events:
    get:
      tags: [Events]
      summary: Replay events
      description: |
        Fetch historical events for your operator. Events are retained for 24 hours.
        Use the `lastSequence` value from the response as the `since` parameter
        in subsequent requests for cursor-based pagination.
      operationId: replayEvents
      parameters:
        - name: since
          in: query
          description: Return events with sequence greater than this value
          schema:
            type: integer
            example: 42
        - name: eventType
          in: query
          description: Filter by event type
          schema:
            $ref: '#/components/schemas/EventType'
        - name: marketId
          in: query
          description: Filter by market ID
          schema:
            type: string
            format: uuid
        - name: limit
          in: query
          description: Maximum events to return (max 1000)
          schema:
            type: integer
            default: 100
            maximum: 1000
      responses:
        '200':
          description: Events list
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      events:
                        type: array
                        items:
                          $ref: '#/components/schemas/OperatorEvent'
                      lastSequence:
                        type: integer
                        description: Sequence number of the last event (use as `since` for next page)
                        example: 57
                      hasMore:
                        type: boolean

tags:
  - name: Health
    description: Service health and readiness
  - name: Markets
    description: Market lifecycle management
  - name: Categories
    description: Market categorization
  - name: Orders
    description: Order placement and management
  - name: Positions
    description: Position tracking
  - name: Trades
    description: Trade history
  - name: Market Data
    description: Public market data (order book, prices)
  - name: Stats
    description: Operator statistics
  - name: Settlements
    description: Settlement processing and queries
  - name: Webhooks
    description: Webhook registration and management
  - name: Events
    description: Event replay for missed events
