openapi: 3.1.0
info:
  title: MyRatings.ai Agent & Offer API
  version: 0.1.0
  description: |
    REST and HTTP-MCP surfaces for buyer offers, seller inbox, and agent tooling.
    MCP tools mirror these routes under `/mcp/buyer` and `/mcp/seller`.
    Money-moving actions require explicit confirmation (`X-MyRatings-Confirm: true` or `confirmed: true`).
servers:
  - url: https://api.myratings.ai
    description: Production
  - url: http://127.0.0.1:3000
    description: Local backend
tags:
  - name: Ops
  - name: Buyer Offers
  - name: Buyer MCP
  - name: Seller Offers
  - name: Seller MCP
  - name: Agent
components:
  securitySchemes:
    sessionBearer:
      type: http
      scheme: bearer
      description: Supabase / Better Auth session JWT for human web and mobile clients.
    mcpBearer:
      type: http
      scheme: bearer
      description: MCP agent token — `mra_*` API key or `mto_*` OAuth access token.
  schemas:
    AllowedAction:
      type: object
      required: [actionId, scope, confirmationRequired, available]
      properties:
        actionId:
          type: string
        intentType:
          type: string
        tool:
          type: string
        mcpPath:
          type: string
        restPath:
          type: string
        method:
          type: string
          enum: [GET, POST, PUT, DELETE]
        scope:
          type: string
        confirmationRequired:
          type: boolean
        available:
          type: boolean
        reason:
          type: string
    AllowedActionsResponse:
      type: object
      required: [surface, principalUserId, scopes, actions]
      properties:
        surface:
          type: string
          enum: [buyer, seller]
        principalUserId:
          type: string
        scopes:
          type: array
          items:
            type: string
        offerId:
          type: string
        sellerId:
          type: string
        actions:
          type: array
          items:
            $ref: '#/components/schemas/AllowedAction'
    HealthResponse:
      type: object
      required: [status, auth]
      description: |
        Public liveness probe. Does not require auth.
        `auth.supabaseConfigured` reflects whether SUPABASE_URL and SUPABASE_ANON_KEY
        are both set in the process environment (presence check only — not a live
        Supabase network call). Production smoke expects status=ok and
        supabaseConfigured=true.
      properties:
        status:
          type: string
          enum: [ok]
          description: Process is serving requests.
        auth:
          type: object
          required: [supabaseConfigured]
          properties:
            supabaseConfigured:
              type: boolean
              description: true when SUPABASE_URL and SUPABASE_ANON_KEY are both set.
paths:
  /health:
    get:
      tags: [Ops]
      summary: Public health / liveness probe
      description: |
        Returns process liveness and whether Supabase client env vars are configured.
        Used by load balancers, deploy smoke (`npm run test:e2e:production`), and
        factory production-smoke scripts. No authentication.

        Example production response:
        `{"status":"ok","auth":{"supabaseConfigured":true}}`
      security: []
      responses:
        '200':
          description: Service is up
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HealthResponse'
              examples:
                production:
                  summary: Production baseline
                  value:
                    status: ok
                    auth:
                      supabaseConfigured: true
                localWithoutSupabase:
                  summary: Local without Supabase env
                  value:
                    status: ok
                    auth:
                      supabaseConfigured: false
  /api/offers:
    get:
      tags: [Buyer Offers]
      summary: List buyer offers
      security:
        - sessionBearer: []
      responses:
        '200':
          description: Offer list
        '401':
          description: Unauthorized
    post:
      tags: [Buyer Offers]
      summary: Create buyer offer
      security:
        - sessionBearer: []
      responses:
        '201':
          description: Offer created
        '401':
          description: Unauthorized
  /api/offers/{offerId}:
    get:
      tags: [Buyer Offers]
      summary: Get buyer offer detail
      security:
        - sessionBearer: []
      parameters:
        - name: offerId
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Buyer offer detail with items and counter history
        '404':
          description: Offer not found
  /api/offers/{offerId}/withdraw:
    post:
      tags: [Buyer Offers]
      summary: Withdraw buyer offer
      security:
        - sessionBearer: []
      parameters:
        - name: offerId
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Offer withdrawn
  /api/offers/{offerId}/counters/{counterId}/accept:
    post:
      tags: [Buyer Offers]
      summary: Accept seller counter
      security:
        - sessionBearer: []
      parameters:
        - name: offerId
          in: path
          required: true
          schema:
            type: string
        - name: counterId
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Counter accepted
  /api/sellers/me/offers:
    get:
      tags: [Seller Offers]
      summary: List seller offer queue
      security:
        - sessionBearer: []
      parameters:
        - name: queue
          in: query
          schema:
            type: string
            enum: [needs_review, expiring, all_active, closed]
        - name: sellerId
          in: query
          schema:
            type: string
      responses:
        '200':
          description: Seller offer list
  /api/sellers/me/offers/{offerId}:
    get:
      tags: [Seller Offers]
      summary: Get seller offer detail
      security:
        - sessionBearer: []
      parameters:
        - name: offerId
          in: path
          required: true
          schema:
            type: string
        - name: sellerId
          in: query
          schema:
            type: string
      responses:
        '200':
          description: Seller offer detail
  /mcp/buyer/manifest:
    get:
      tags: [Buyer MCP]
      summary: Buyer MCP tool manifest
      security:
        - mcpBearer: []
      responses:
        '200':
          description: Tool catalog and scopes
  /mcp/buyer/allowed_actions:
    get:
      tags: [Buyer MCP, Agent]
      summary: Read allowed buyer actions for the authenticated agent
      description: |
        Returns scope-gated actions and, when `offerId` is provided, runtime availability
        based on offer status and counter state.
      security:
        - mcpBearer: []
      parameters:
        - name: offerId
          in: query
          schema:
            type: string
        - name: counterId
          in: query
          schema:
            type: string
      responses:
        '200':
          description: Allowed actions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AllowedActionsResponse'
        '403':
          description: Missing scope
  /mcp/buyer/list_offers:
    get:
      tags: [Buyer MCP]
      summary: mr.shopper.list_offers
      security:
        - mcpBearer: []
      responses:
        '200':
          description: Offer list
  /mcp/buyer/offers/{offerId}:
    get:
      tags: [Buyer MCP]
      summary: mr.shopper.get_offer
      security:
        - mcpBearer: []
      parameters:
        - name: offerId
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Offer detail
  /mcp/seller/manifest:
    get:
      tags: [Seller MCP]
      summary: Seller MCP tool manifest
      security:
        - mcpBearer: []
      responses:
        '200':
          description: Tool catalog and scopes
  /mcp/seller/allowed_actions:
    get:
      tags: [Seller MCP, Agent]
      summary: Read allowed seller actions for the authenticated agent
      security:
        - mcpBearer: []
      parameters:
        - name: sellerId
          in: query
          schema:
            type: string
        - name: offerId
          in: query
          schema:
            type: string
      responses:
        '200':
          description: Allowed actions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AllowedActionsResponse'
  /mcp/seller/list_offers:
    get:
      tags: [Seller MCP]
      summary: mr.seller.list_offers
      security:
        - mcpBearer: []
      responses:
        '200':
          description: Seller offer queue
  /.well-known/oauth-authorization-server:
    get:
      tags: [Agent]
      summary: MCP OAuth metadata (PKCE)
      responses:
        '200':
          description: OAuth authorization server metadata
